sqlew 4.0.5 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1805 -1782
- package/README.md +409 -468
- package/assets/claude-md-snippets/plan-mode-integration.md +17 -6
- package/assets/config.example.toml +282 -284
- package/assets/sample-agents/README.md +36 -40
- package/assets/sample-agents/sqlew-architect.md +321 -322
- package/assets/sample-agents/sqlew-researcher.md +292 -293
- package/assets/sample-agents/sqlew-scrum-master.md +286 -287
- package/assets/sample-commands/README.md +56 -57
- package/assets/sample-skills/sqlew-plan-guidance/SKILL.md +33 -26
- package/dist/cli/hooks/check-completion.d.ts +19 -0
- package/dist/cli/hooks/check-completion.d.ts.map +1 -0
- package/dist/cli/hooks/check-completion.js +104 -0
- package/dist/cli/hooks/check-completion.js.map +1 -0
- package/dist/cli/hooks/init-hooks.d.ts +35 -0
- package/dist/cli/hooks/init-hooks.d.ts.map +1 -0
- package/dist/cli/hooks/init-hooks.js +425 -0
- package/dist/cli/hooks/init-hooks.js.map +1 -0
- package/dist/cli/hooks/mark-done.d.ts +25 -0
- package/dist/cli/hooks/mark-done.d.ts.map +1 -0
- package/dist/cli/hooks/mark-done.js +128 -0
- package/dist/cli/hooks/mark-done.js.map +1 -0
- package/dist/cli/hooks/plan-id-utils.d.ts +83 -0
- package/dist/cli/hooks/plan-id-utils.d.ts.map +1 -0
- package/dist/cli/hooks/plan-id-utils.js +183 -0
- package/dist/cli/hooks/plan-id-utils.js.map +1 -0
- package/dist/cli/hooks/save.d.ts +23 -0
- package/dist/cli/hooks/save.d.ts.map +1 -0
- package/dist/cli/hooks/save.js +90 -0
- package/dist/cli/hooks/save.js.map +1 -0
- package/dist/cli/hooks/stdin-parser.d.ts +139 -0
- package/dist/cli/hooks/stdin-parser.d.ts.map +1 -0
- package/dist/cli/hooks/stdin-parser.js +127 -0
- package/dist/cli/hooks/stdin-parser.js.map +1 -0
- package/dist/cli/hooks/suggest.d.ts +19 -0
- package/dist/cli/hooks/suggest.d.ts.map +1 -0
- package/dist/cli/hooks/suggest.js +157 -0
- package/dist/cli/hooks/suggest.js.map +1 -0
- package/dist/cli/hooks/track-plan.d.ts +36 -0
- package/dist/cli/hooks/track-plan.d.ts.map +1 -0
- package/dist/cli/hooks/track-plan.js +152 -0
- package/dist/cli/hooks/track-plan.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +56 -16
- package/dist/cli.js.map +1 -1
- package/dist/config/global-config.d.ts +187 -0
- package/dist/config/global-config.d.ts.map +1 -0
- package/dist/config/global-config.js +206 -0
- package/dist/config/global-config.js.map +1 -0
- package/dist/config/loader.d.ts +42 -0
- package/dist/config/loader.d.ts.map +1 -1
- package/dist/config/loader.js +96 -0
- package/dist/config/loader.js.map +1 -1
- package/dist/constants.d.ts +4 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +10 -0
- package/dist/constants.js.map +1 -1
- package/dist/database/operations/queries.d.ts.map +1 -1
- package/dist/database/operations/queries.js +11 -2
- package/dist/database/operations/queries.js.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/init-agents.js +0 -1
- package/dist/init-agents.js.map +1 -1
- package/dist/init-skills.d.ts +4 -3
- package/dist/init-skills.d.ts.map +1 -1
- package/dist/init-skills.js +10 -3
- package/dist/init-skills.js.map +1 -1
- package/dist/server/setup.d.ts +8 -0
- package/dist/server/setup.d.ts.map +1 -1
- package/dist/server/setup.js +141 -21
- package/dist/server/setup.js.map +1 -1
- package/dist/sync-agents.d.ts.map +1 -1
- package/dist/sync-agents.js +48 -3
- package/dist/sync-agents.js.map +1 -1
- package/dist/sync-commands.d.ts.map +1 -1
- package/dist/sync-commands.js +43 -3
- package/dist/sync-commands.js.map +1 -1
- package/dist/tools/constraints/actions/get.d.ts.map +1 -1
- package/dist/tools/constraints/actions/get.js +5 -8
- package/dist/tools/constraints/actions/get.js.map +1 -1
- package/dist/tools/constraints/help/help.d.ts.map +1 -1
- package/dist/tools/constraints/help/help.js +1 -6
- package/dist/tools/constraints/help/help.js.map +1 -1
- package/dist/tools/context/actions/get.d.ts.map +1 -1
- package/dist/tools/context/actions/get.js.map +1 -1
- package/dist/tools/context/actions/search-layer.d.ts.map +1 -1
- package/dist/tools/context/actions/search-layer.js +5 -3
- package/dist/tools/context/actions/search-layer.js.map +1 -1
- package/dist/tools/context/actions/set-from-policy.d.ts +2 -1
- package/dist/tools/context/actions/set-from-policy.d.ts.map +1 -1
- package/dist/tools/context/actions/set-from-policy.js.map +1 -1
- package/dist/tools/context/help/help.d.ts.map +1 -1
- package/dist/tools/context/help/help.js +1 -7
- package/dist/tools/context/help/help.js.map +1 -1
- package/dist/tools/context/internal/queries.d.ts.map +1 -1
- package/dist/tools/context/internal/queries.js +5 -2
- package/dist/tools/context/internal/queries.js.map +1 -1
- package/dist/tools/context/types.d.ts +1 -1
- package/dist/tools/context/types.d.ts.map +1 -1
- package/dist/tools/files/actions/get.d.ts.map +1 -1
- package/dist/tools/files/actions/get.js +4 -6
- package/dist/tools/files/actions/get.js.map +1 -1
- package/dist/tools/files/help/help.d.ts.map +1 -1
- package/dist/tools/files/help/help.js +1 -6
- package/dist/tools/files/help/help.js.map +1 -1
- package/dist/tools/suggest/help/constraint-help.d.ts.map +1 -1
- package/dist/tools/suggest/help/constraint-help.js +0 -2
- package/dist/tools/suggest/help/constraint-help.js.map +1 -1
- package/dist/tools/suggest/internal/constraint-queries.d.ts.map +1 -1
- package/dist/tools/suggest/internal/constraint-queries.js +12 -5
- package/dist/tools/suggest/internal/constraint-queries.js.map +1 -1
- package/dist/tools/suggest/internal/queries.js +2 -2
- package/dist/tools/suggest/internal/queries.js.map +1 -1
- package/dist/tools/tasks/help/help.d.ts.map +1 -1
- package/dist/tools/tasks/help/help.js +0 -6
- package/dist/tools/tasks/help/help.js.map +1 -1
- package/dist/tools/tasks/help/use-case.d.ts.map +1 -1
- package/dist/tools/tasks/help/use-case.js +0 -1
- package/dist/tools/tasks/help/use-case.js.map +1 -1
- package/dist/tools/tasks/watcher/status.d.ts.map +1 -1
- package/dist/tools/tasks/watcher/status.js +5 -1
- package/dist/tools/tasks/watcher/status.js.map +1 -1
- package/dist/types/decision/params.d.ts +7 -6
- package/dist/types/decision/params.d.ts.map +1 -1
- package/dist/types/decision/templates.d.ts +3 -2
- package/dist/types/decision/templates.d.ts.map +1 -1
- package/dist/types/view-entities.d.ts +2 -1
- package/dist/types/view-entities.d.ts.map +1 -1
- package/dist/types.d.ts +19 -11
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +4 -1
- package/dist/types.js.map +1 -1
- package/dist/utils/enum-converter.d.ts +72 -0
- package/dist/utils/enum-converter.d.ts.map +1 -0
- package/dist/utils/enum-converter.js +76 -0
- package/dist/utils/enum-converter.js.map +1 -0
- package/dist/utils/hook-queue.d.ts +81 -0
- package/dist/utils/hook-queue.d.ts.map +1 -0
- package/dist/utils/hook-queue.js +156 -0
- package/dist/utils/hook-queue.js.map +1 -0
- package/dist/utils/project-root.d.ts +9 -2
- package/dist/utils/project-root.d.ts.map +1 -1
- package/dist/utils/project-root.js +16 -2
- package/dist/utils/project-root.js.map +1 -1
- package/dist/utils/tag-parser.d.ts.map +1 -1
- package/dist/utils/tag-parser.js +6 -0
- package/dist/utils/tag-parser.js.map +1 -1
- package/dist/utils/validators.d.ts +1 -1
- package/dist/utils/validators.d.ts.map +1 -1
- package/dist/utils/validators.js +1 -1
- package/dist/utils/validators.js.map +1 -1
- package/dist/utils/vcs-adapter.d.ts +44 -0
- package/dist/utils/vcs-adapter.d.ts.map +1 -1
- package/dist/utils/vcs-adapter.js +88 -0
- package/dist/utils/vcs-adapter.js.map +1 -1
- package/dist/utils/view-queries.d.ts.map +1 -1
- package/dist/utils/view-queries.js +9 -19
- package/dist/utils/view-queries.js.map +1 -1
- package/dist/watcher/base-watcher.d.ts +69 -0
- package/dist/watcher/base-watcher.d.ts.map +1 -0
- package/dist/watcher/base-watcher.js +130 -0
- package/dist/watcher/base-watcher.js.map +1 -0
- package/dist/watcher/index.d.ts +3 -0
- package/dist/watcher/index.d.ts.map +1 -1
- package/dist/watcher/index.js +2 -0
- package/dist/watcher/index.js.map +1 -1
- package/dist/watcher/queue-watcher.d.ts +64 -0
- package/dist/watcher/queue-watcher.d.ts.map +1 -0
- package/dist/watcher/queue-watcher.js +187 -0
- package/dist/watcher/queue-watcher.js.map +1 -0
- package/docs/ADR_CONCEPTS.md +140 -0
- package/docs/CONFIGURATION.md +922 -925
- package/docs/CROSS_DATABASE.md +153 -0
- package/docs/DATABASE_AUTH.md +70 -356
- package/docs/HOOKS_GUIDE.md +159 -0
- package/docs/SLASH_COMMANDS.md +329 -337
- package/docs/TASK_SYSTEM_DEPRECATED.md +88 -0
- package/docs/changelogs/CHANGELOG_ARCHIVE_v3.4_and_older.md +293 -296
- package/docs/cli/DATA_EXPORT_IMPORT.md +699 -700
- package/docs/cli/README.md +276 -277
- package/package.json +123 -124
- package/docs/ACCEPTANCE_CRITERIA.md +0 -625
- package/docs/AI_AGENT_GUIDE.md +0 -299
- package/docs/ARCHITECTURE.md +0 -167
- package/docs/AUTO_FILE_TRACKING.md +0 -841
- package/docs/BATCH_VALIDATION.md +0 -617
- package/docs/BEST_PRACTICES.md +0 -168
- package/docs/CONSTRAINT_INTELLIGENCE.md +0 -339
- package/docs/DECISION_CONTEXT.md +0 -697
- package/docs/DECISION_INTELLIGENCE.md +0 -605
- package/docs/GIT_AWARE_AUTO_COMPLETE.md +0 -646
- package/docs/MIGRATION_GUIDE_V3.9.0.md +0 -371
- package/docs/SHARED_CONCEPTS.md +0 -225
- package/docs/SPECIALIZED_AGENTS.md +0 -126
- package/docs/TASK_ACTIONS.md +0 -1177
- package/docs/TASK_OVERVIEW.md +0 -452
- package/docs/TASK_PRUNING.md +0 -594
- package/docs/TOOL_REFERENCE.md +0 -1077
- package/docs/TOOL_SELECTION.md +0 -83
- package/docs/WORKFLOWS.md +0 -941
|
@@ -0,0 +1,425 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Init Hooks Command
|
|
3
|
+
*
|
|
4
|
+
* Initializes Claude Code Hooks configuration for sqlew.
|
|
5
|
+
* Creates/updates .claude/settings.local.json with hook settings.
|
|
6
|
+
* Optionally installs Git hooks (post-merge, post-rewrite).
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* sqlew init --hooks # Initialize all hooks
|
|
10
|
+
* sqlew init --hooks --no-git # Skip Git hooks
|
|
11
|
+
*
|
|
12
|
+
* Auto-initialization:
|
|
13
|
+
* Called automatically on MCP server startup (first time only).
|
|
14
|
+
* Silent mode - no console output unless errors occur.
|
|
15
|
+
*
|
|
16
|
+
* @since v4.1.0
|
|
17
|
+
*/
|
|
18
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync, chmodSync, statSync } from 'fs';
|
|
19
|
+
import { join } from 'path';
|
|
20
|
+
import { determineProjectRoot } from '../../utils/project-root.js';
|
|
21
|
+
import { isGitHooksEnabled } from '../../config/global-config.js';
|
|
22
|
+
// ============================================================================
|
|
23
|
+
// Constants
|
|
24
|
+
// ============================================================================
|
|
25
|
+
/** Claude Code hooks to install */
|
|
26
|
+
const CLAUDE_HOOKS = {
|
|
27
|
+
PreToolUse: [
|
|
28
|
+
{
|
|
29
|
+
matcher: 'Task',
|
|
30
|
+
hooks: [{ type: 'command', command: 'sqlew suggest' }],
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
matcher: 'Write',
|
|
34
|
+
hooks: [{ type: 'command', command: 'sqlew track-plan' }],
|
|
35
|
+
},
|
|
36
|
+
],
|
|
37
|
+
PostToolUse: [
|
|
38
|
+
{
|
|
39
|
+
matcher: 'Edit|Write',
|
|
40
|
+
hooks: [{ type: 'command', command: 'sqlew save' }],
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
matcher: 'TodoWrite',
|
|
44
|
+
hooks: [{ type: 'command', command: 'sqlew check-completion' }],
|
|
45
|
+
},
|
|
46
|
+
],
|
|
47
|
+
};
|
|
48
|
+
/** Git post-merge hook content */
|
|
49
|
+
const POST_MERGE_HOOK = `#!/bin/bash
|
|
50
|
+
# sqlew: Mark plan decisions as implemented after merge
|
|
51
|
+
sqlew mark-done --auto
|
|
52
|
+
`;
|
|
53
|
+
/** Git post-rewrite hook content */
|
|
54
|
+
const POST_REWRITE_HOOK = `#!/bin/bash
|
|
55
|
+
# sqlew: Mark plan decisions as implemented after rebase
|
|
56
|
+
if [ "$1" = "rebase" ]; then
|
|
57
|
+
sqlew mark-done --auto
|
|
58
|
+
fi
|
|
59
|
+
`;
|
|
60
|
+
// ============================================================================
|
|
61
|
+
// Settings Management
|
|
62
|
+
// ============================================================================
|
|
63
|
+
/**
|
|
64
|
+
* Get path to Claude settings file
|
|
65
|
+
*
|
|
66
|
+
* Uses settings.local.json (gitignored) for local development hooks.
|
|
67
|
+
*
|
|
68
|
+
* @param projectPath - Project root path
|
|
69
|
+
* @returns Path to .claude/settings.local.json
|
|
70
|
+
*/
|
|
71
|
+
function getSettingsPath(projectPath) {
|
|
72
|
+
return join(projectPath, '.claude', 'settings.local.json');
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Load existing Claude settings
|
|
76
|
+
*
|
|
77
|
+
* @param settingsPath - Path to settings file
|
|
78
|
+
* @returns Existing settings or empty object
|
|
79
|
+
*/
|
|
80
|
+
function loadSettings(settingsPath) {
|
|
81
|
+
if (!existsSync(settingsPath)) {
|
|
82
|
+
return {};
|
|
83
|
+
}
|
|
84
|
+
try {
|
|
85
|
+
const content = readFileSync(settingsPath, 'utf-8');
|
|
86
|
+
return JSON.parse(content);
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
return {};
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Save Claude settings
|
|
94
|
+
*
|
|
95
|
+
* @param settingsPath - Path to settings file
|
|
96
|
+
* @param settings - Settings to save
|
|
97
|
+
*/
|
|
98
|
+
function saveSettings(settingsPath, settings) {
|
|
99
|
+
const dir = join(settingsPath, '..');
|
|
100
|
+
if (!existsSync(dir)) {
|
|
101
|
+
mkdirSync(dir, { recursive: true });
|
|
102
|
+
}
|
|
103
|
+
const content = JSON.stringify(settings, null, 2);
|
|
104
|
+
writeFileSync(settingsPath, content, 'utf-8');
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Merge hook configurations
|
|
108
|
+
*
|
|
109
|
+
* Adds new hooks without duplicating existing ones.
|
|
110
|
+
*
|
|
111
|
+
* @param existing - Existing hook configs
|
|
112
|
+
* @param newHooks - New hooks to add
|
|
113
|
+
* @returns Merged hook configs
|
|
114
|
+
*/
|
|
115
|
+
function mergeHooks(existing, newHooks) {
|
|
116
|
+
const result = [...(existing || [])];
|
|
117
|
+
for (const newHook of newHooks) {
|
|
118
|
+
// Check if a hook with same matcher already exists
|
|
119
|
+
const existingIndex = result.findIndex(h => h.matcher === newHook.matcher);
|
|
120
|
+
if (existingIndex >= 0) {
|
|
121
|
+
// Merge commands
|
|
122
|
+
const existingHook = result[existingIndex];
|
|
123
|
+
for (const cmd of newHook.hooks) {
|
|
124
|
+
const cmdExists = existingHook.hooks.some(h => h.type === cmd.type && h.command === cmd.command);
|
|
125
|
+
if (!cmdExists) {
|
|
126
|
+
existingHook.hooks.push(cmd);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
// Add new hook
|
|
132
|
+
result.push(newHook);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return result;
|
|
136
|
+
}
|
|
137
|
+
// ============================================================================
|
|
138
|
+
// Git Hooks
|
|
139
|
+
// ============================================================================
|
|
140
|
+
/**
|
|
141
|
+
* Install Git hooks
|
|
142
|
+
*
|
|
143
|
+
* @param projectPath - Project root path
|
|
144
|
+
* @returns true if hooks were installed
|
|
145
|
+
*/
|
|
146
|
+
function installGitHooks(projectPath) {
|
|
147
|
+
const gitDir = join(projectPath, '.git');
|
|
148
|
+
// Check if .git exists (might be worktree with .git file)
|
|
149
|
+
if (!existsSync(gitDir)) {
|
|
150
|
+
console.log('[sqlew init] No .git directory found - skipping Git hooks');
|
|
151
|
+
return false;
|
|
152
|
+
}
|
|
153
|
+
// Determine hooks directory
|
|
154
|
+
let hooksDir;
|
|
155
|
+
const gitPath = join(projectPath, '.git');
|
|
156
|
+
if (existsSync(gitPath)) {
|
|
157
|
+
const stat = statSync(gitPath);
|
|
158
|
+
if (stat.isFile()) {
|
|
159
|
+
// Worktree - read gitdir from .git file
|
|
160
|
+
const content = readFileSync(gitPath, 'utf-8').trim();
|
|
161
|
+
const match = content.match(/^gitdir:\s*(.+)$/);
|
|
162
|
+
if (match) {
|
|
163
|
+
hooksDir = join(match[1], 'hooks');
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
console.log('[sqlew init] Invalid .git file format - skipping Git hooks');
|
|
167
|
+
return false;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
// Regular repo
|
|
172
|
+
hooksDir = join(gitPath, 'hooks');
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
return false;
|
|
177
|
+
}
|
|
178
|
+
// Create hooks directory if needed
|
|
179
|
+
if (!existsSync(hooksDir)) {
|
|
180
|
+
mkdirSync(hooksDir, { recursive: true });
|
|
181
|
+
}
|
|
182
|
+
// Install post-merge hook
|
|
183
|
+
const postMergePath = join(hooksDir, 'post-merge');
|
|
184
|
+
installHookFile(postMergePath, POST_MERGE_HOOK, 'post-merge');
|
|
185
|
+
// Install post-rewrite hook
|
|
186
|
+
const postRewritePath = join(hooksDir, 'post-rewrite');
|
|
187
|
+
installHookFile(postRewritePath, POST_REWRITE_HOOK, 'post-rewrite');
|
|
188
|
+
return true;
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Install a single hook file
|
|
192
|
+
*
|
|
193
|
+
* @param hookPath - Path to hook file
|
|
194
|
+
* @param content - Hook content
|
|
195
|
+
* @param name - Hook name for logging
|
|
196
|
+
*/
|
|
197
|
+
function installHookFile(hookPath, content, name) {
|
|
198
|
+
if (existsSync(hookPath)) {
|
|
199
|
+
// Check if our hook is already installed
|
|
200
|
+
const existing = readFileSync(hookPath, 'utf-8');
|
|
201
|
+
if (existing.includes('sqlew mark-done')) {
|
|
202
|
+
console.log(`[sqlew init] Git hook ${name} already has sqlew integration`);
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
// Append to existing hook
|
|
206
|
+
const newContent = existing.trim() + '\n\n' + content;
|
|
207
|
+
writeFileSync(hookPath, newContent, 'utf-8');
|
|
208
|
+
console.log(`[sqlew init] Updated Git hook: ${name}`);
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
// Create new hook
|
|
212
|
+
writeFileSync(hookPath, content, 'utf-8');
|
|
213
|
+
console.log(`[sqlew init] Created Git hook: ${name}`);
|
|
214
|
+
}
|
|
215
|
+
// Make executable (Unix only)
|
|
216
|
+
if (process.platform !== 'win32') {
|
|
217
|
+
try {
|
|
218
|
+
chmodSync(hookPath, 0o755);
|
|
219
|
+
}
|
|
220
|
+
catch {
|
|
221
|
+
// Ignore chmod errors on Windows
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
// ============================================================================
|
|
226
|
+
// Main Entry Point
|
|
227
|
+
// ============================================================================
|
|
228
|
+
/**
|
|
229
|
+
* Parse command line arguments for init --hooks
|
|
230
|
+
*
|
|
231
|
+
* @param args - Command line arguments
|
|
232
|
+
* @returns Parsed options
|
|
233
|
+
*/
|
|
234
|
+
function parseInitArgs(args) {
|
|
235
|
+
return {
|
|
236
|
+
noGit: args.includes('--no-git'),
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Main init hooks command entry point
|
|
241
|
+
*
|
|
242
|
+
* @param args - Command line arguments
|
|
243
|
+
*/
|
|
244
|
+
export async function initHooksCommand(args = []) {
|
|
245
|
+
try {
|
|
246
|
+
const options = parseInitArgs(args);
|
|
247
|
+
// Determine project root
|
|
248
|
+
const projectPath = determineProjectRoot();
|
|
249
|
+
console.log(`[sqlew init] Project root: ${projectPath}`);
|
|
250
|
+
// Update Claude settings
|
|
251
|
+
const settingsPath = getSettingsPath(projectPath);
|
|
252
|
+
const settings = loadSettings(settingsPath);
|
|
253
|
+
// Merge hooks
|
|
254
|
+
settings.hooks = settings.hooks || {};
|
|
255
|
+
settings.hooks.PreToolUse = mergeHooks(settings.hooks.PreToolUse, CLAUDE_HOOKS.PreToolUse);
|
|
256
|
+
settings.hooks.PostToolUse = mergeHooks(settings.hooks.PostToolUse, CLAUDE_HOOKS.PostToolUse);
|
|
257
|
+
// Save settings
|
|
258
|
+
saveSettings(settingsPath, settings);
|
|
259
|
+
console.log(`[sqlew init] Updated Claude settings: ${settingsPath}`);
|
|
260
|
+
// Install Git hooks if enabled
|
|
261
|
+
if (!options.noGit && isGitHooksEnabled()) {
|
|
262
|
+
const installed = installGitHooks(projectPath);
|
|
263
|
+
if (installed) {
|
|
264
|
+
console.log('[sqlew init] Git hooks installed successfully');
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
else if (options.noGit) {
|
|
268
|
+
console.log('[sqlew init] Skipping Git hooks (--no-git specified)');
|
|
269
|
+
}
|
|
270
|
+
else {
|
|
271
|
+
console.log('[sqlew init] Git hooks disabled in global config');
|
|
272
|
+
}
|
|
273
|
+
console.log('\n[sqlew init] Hooks initialization complete!');
|
|
274
|
+
console.log('Restart Claude Code for changes to take effect.');
|
|
275
|
+
}
|
|
276
|
+
catch (error) {
|
|
277
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
278
|
+
console.error(`[sqlew init] Error: ${message}`);
|
|
279
|
+
process.exit(1);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
// ============================================================================
|
|
283
|
+
// Auto-Initialization (Server Startup)
|
|
284
|
+
// ============================================================================
|
|
285
|
+
/**
|
|
286
|
+
* Check if sqlew hooks are already configured
|
|
287
|
+
*
|
|
288
|
+
* @param projectPath - Project root path
|
|
289
|
+
* @returns true if hooks are already set up
|
|
290
|
+
*/
|
|
291
|
+
function hasHooksConfigured(projectPath) {
|
|
292
|
+
const settingsPath = getSettingsPath(projectPath);
|
|
293
|
+
if (!existsSync(settingsPath)) {
|
|
294
|
+
return false;
|
|
295
|
+
}
|
|
296
|
+
try {
|
|
297
|
+
const settings = loadSettings(settingsPath);
|
|
298
|
+
// Check if sqlew hooks exist
|
|
299
|
+
const hasPreToolUse = settings.hooks?.PreToolUse?.some(h => h.hooks?.some(cmd => cmd.command?.startsWith('sqlew ')));
|
|
300
|
+
const hasPostToolUse = settings.hooks?.PostToolUse?.some(h => h.hooks?.some(cmd => cmd.command?.startsWith('sqlew ')));
|
|
301
|
+
return !!(hasPreToolUse || hasPostToolUse);
|
|
302
|
+
}
|
|
303
|
+
catch {
|
|
304
|
+
return false;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Auto-initialize hooks on MCP server startup
|
|
309
|
+
*
|
|
310
|
+
* Called from initializeSqlewIntegrations() during server startup.
|
|
311
|
+
* Silent mode - only logs via debugLog, no console output.
|
|
312
|
+
* Only runs if hooks are not already configured.
|
|
313
|
+
*
|
|
314
|
+
* @param projectPath - Project root path
|
|
315
|
+
* @returns true if hooks were initialized, false if already configured or skipped
|
|
316
|
+
*/
|
|
317
|
+
export function autoInitializeHooks(projectPath) {
|
|
318
|
+
// Skip if already configured
|
|
319
|
+
if (hasHooksConfigured(projectPath)) {
|
|
320
|
+
return false;
|
|
321
|
+
}
|
|
322
|
+
try {
|
|
323
|
+
// Update Claude settings
|
|
324
|
+
const settingsPath = getSettingsPath(projectPath);
|
|
325
|
+
const settings = loadSettings(settingsPath);
|
|
326
|
+
// Merge hooks
|
|
327
|
+
settings.hooks = settings.hooks || {};
|
|
328
|
+
settings.hooks.PreToolUse = mergeHooks(settings.hooks.PreToolUse, CLAUDE_HOOKS.PreToolUse);
|
|
329
|
+
settings.hooks.PostToolUse = mergeHooks(settings.hooks.PostToolUse, CLAUDE_HOOKS.PostToolUse);
|
|
330
|
+
// Save settings
|
|
331
|
+
saveSettings(settingsPath, settings);
|
|
332
|
+
// Install Git hooks if enabled (silent mode)
|
|
333
|
+
if (isGitHooksEnabled()) {
|
|
334
|
+
installGitHooksSilent(projectPath);
|
|
335
|
+
}
|
|
336
|
+
return true;
|
|
337
|
+
}
|
|
338
|
+
catch {
|
|
339
|
+
// Silent failure - don't interrupt server startup
|
|
340
|
+
return false;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Install Git hooks silently (no console output)
|
|
345
|
+
*
|
|
346
|
+
* @param projectPath - Project root path
|
|
347
|
+
*/
|
|
348
|
+
function installGitHooksSilent(projectPath) {
|
|
349
|
+
const gitPath = join(projectPath, '.git');
|
|
350
|
+
if (!existsSync(gitPath)) {
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
let hooksDir;
|
|
354
|
+
try {
|
|
355
|
+
const stat = statSync(gitPath);
|
|
356
|
+
if (stat.isFile()) {
|
|
357
|
+
// Worktree - use main repo's hooks directory
|
|
358
|
+
const content = readFileSync(gitPath, 'utf-8').trim();
|
|
359
|
+
const match = content.match(/^gitdir:\s*(.+)$/);
|
|
360
|
+
if (match) {
|
|
361
|
+
// gitdir: C:/repo/.git/worktrees/branch-name
|
|
362
|
+
// We want: C:/repo/.git/hooks
|
|
363
|
+
const gitdirPath = match[1];
|
|
364
|
+
const worktreesIndex = gitdirPath.lastIndexOf('/worktrees/');
|
|
365
|
+
if (worktreesIndex !== -1) {
|
|
366
|
+
const mainGitDir = gitdirPath.substring(0, worktreesIndex);
|
|
367
|
+
hooksDir = join(mainGitDir, 'hooks');
|
|
368
|
+
}
|
|
369
|
+
else {
|
|
370
|
+
// Windows path fallback
|
|
371
|
+
const winIndex = gitdirPath.lastIndexOf('\\worktrees\\');
|
|
372
|
+
if (winIndex !== -1) {
|
|
373
|
+
const mainGitDir = gitdirPath.substring(0, winIndex);
|
|
374
|
+
hooksDir = join(mainGitDir, 'hooks');
|
|
375
|
+
}
|
|
376
|
+
else {
|
|
377
|
+
return;
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
else {
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
else {
|
|
386
|
+
hooksDir = join(gitPath, 'hooks');
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
catch {
|
|
390
|
+
return;
|
|
391
|
+
}
|
|
392
|
+
if (!existsSync(hooksDir)) {
|
|
393
|
+
mkdirSync(hooksDir, { recursive: true });
|
|
394
|
+
}
|
|
395
|
+
// Install hooks silently
|
|
396
|
+
installHookFileSilent(join(hooksDir, 'post-merge'), POST_MERGE_HOOK);
|
|
397
|
+
installHookFileSilent(join(hooksDir, 'post-rewrite'), POST_REWRITE_HOOK);
|
|
398
|
+
}
|
|
399
|
+
/**
|
|
400
|
+
* Install a single hook file silently
|
|
401
|
+
*
|
|
402
|
+
* @param hookPath - Path to hook file
|
|
403
|
+
* @param content - Hook content
|
|
404
|
+
*/
|
|
405
|
+
function installHookFileSilent(hookPath, content) {
|
|
406
|
+
try {
|
|
407
|
+
if (existsSync(hookPath)) {
|
|
408
|
+
const existing = readFileSync(hookPath, 'utf-8');
|
|
409
|
+
if (existing.includes('sqlew mark-done')) {
|
|
410
|
+
return; // Already installed
|
|
411
|
+
}
|
|
412
|
+
writeFileSync(hookPath, existing.trim() + '\n\n' + content, 'utf-8');
|
|
413
|
+
}
|
|
414
|
+
else {
|
|
415
|
+
writeFileSync(hookPath, content, 'utf-8');
|
|
416
|
+
}
|
|
417
|
+
if (process.platform !== 'win32') {
|
|
418
|
+
chmodSync(hookPath, 0o755);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
catch {
|
|
422
|
+
// Silent failure
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
//# sourceMappingURL=init-hooks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init-hooks.js","sourceRoot":"","sources":["../../../src/cli/hooks/init-hooks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,IAAI,CAAC;AAC7F,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAyClE,+EAA+E;AAC/E,YAAY;AACZ,+EAA+E;AAE/E,mCAAmC;AACnC,MAAM,YAAY,GAAkB;IAClC,UAAU,EAAE;QACV;YACE,OAAO,EAAE,MAAM;YACf,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,eAAe,EAAE,CAAC;SACvD;QACD;YACE,OAAO,EAAE,OAAO;YAChB,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,kBAAkB,EAAE,CAAC;SAC1D;KACF;IACD,WAAW,EAAE;QACX;YACE,OAAO,EAAE,YAAY;YACrB,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,YAAY,EAAE,CAAC;SACpD;QACD;YACE,OAAO,EAAE,WAAW;YACpB,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,wBAAwB,EAAE,CAAC;SAChE;KACF;CACF,CAAC;AAEF,kCAAkC;AAClC,MAAM,eAAe,GAAG;;;CAGvB,CAAC;AAEF,oCAAoC;AACpC,MAAM,iBAAiB,GAAG;;;;;CAKzB,CAAC;AAEF,+EAA+E;AAC/E,sBAAsB;AACtB,+EAA+E;AAE/E;;;;;;;GAOG;AACH,SAAS,eAAe,CAAC,WAAmB;IAC1C,OAAO,IAAI,CAAC,WAAW,EAAE,SAAS,EAAE,qBAAqB,CAAC,CAAC;AAC7D,CAAC;AAED;;;;;GAKG;AACH,SAAS,YAAY,CAAC,YAAoB;IACxC,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAC9B,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QACpD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAmB,CAAC;IAC/C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,SAAS,YAAY,CAAC,YAAoB,EAAE,QAAwB;IAClE,MAAM,GAAG,GAAG,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;IACrC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACrB,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACtC,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAClD,aAAa,CAAC,YAAY,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;AAChD,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,UAAU,CAAC,QAAkC,EAAE,QAAsB;IAC5E,MAAM,MAAM,GAAG,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,CAAC;IAErC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,mDAAmD;QACnD,MAAM,aAAa,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;QAE3E,IAAI,aAAa,IAAI,CAAC,EAAE,CAAC;YACvB,iBAAiB;YACjB,MAAM,YAAY,GAAG,MAAM,CAAC,aAAa,CAAC,CAAC;YAC3C,KAAK,MAAM,GAAG,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;gBAChC,MAAM,SAAS,GAAG,YAAY,CAAC,KAAK,CAAC,IAAI,CACvC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,IAAI,CAAC,CAAC,OAAO,KAAK,GAAG,CAAC,OAAO,CACtD,CAAC;gBACF,IAAI,CAAC,SAAS,EAAE,CAAC;oBACf,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBAC/B,CAAC;YACH,CAAC;QACH,CAAC;aAAM,CAAC;YACN,eAAe;YACf,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,+EAA+E;AAC/E,YAAY;AACZ,+EAA+E;AAE/E;;;;;GAKG;AACH,SAAS,eAAe,CAAC,WAAmB;IAC1C,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IAEzC,0DAA0D;IAC1D,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QACxB,OAAO,CAAC,GAAG,CAAC,2DAA2D,CAAC,CAAC;QACzE,OAAO,KAAK,CAAC;IACf,CAAC;IAED,4BAA4B;IAC5B,IAAI,QAAgB,CAAC;IACrB,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IAE1C,IAAI,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;QAC/B,IAAI,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;YAClB,wCAAwC;YACxC,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;YACtD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;YAChD,IAAI,KAAK,EAAE,CAAC;gBACV,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;YACrC,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,GAAG,CAAC,4DAA4D,CAAC,CAAC;gBAC1E,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC;aAAM,CAAC;YACN,eAAe;YACf,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACpC,CAAC;IACH,CAAC;SAAM,CAAC;QACN,OAAO,KAAK,CAAC;IACf,CAAC;IAED,mCAAmC;IACnC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1B,SAAS,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3C,CAAC;IAED,0BAA0B;IAC1B,MAAM,aAAa,GAAG,IAAI,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;IACnD,eAAe,CAAC,aAAa,EAAE,eAAe,EAAE,YAAY,CAAC,CAAC;IAE9D,4BAA4B;IAC5B,MAAM,eAAe,GAAG,IAAI,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;IACvD,eAAe,CAAC,eAAe,EAAE,iBAAiB,EAAE,cAAc,CAAC,CAAC;IAEpE,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;GAMG;AACH,SAAS,eAAe,CAAC,QAAgB,EAAE,OAAe,EAAE,IAAY;IACtE,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QACzB,yCAAyC;QACzC,MAAM,QAAQ,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACjD,IAAI,QAAQ,CAAC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC;YACzC,OAAO,CAAC,GAAG,CAAC,yBAAyB,IAAI,gCAAgC,CAAC,CAAC;YAC3E,OAAO;QACT,CAAC;QAED,0BAA0B;QAC1B,MAAM,UAAU,GAAG,QAAQ,CAAC,IAAI,EAAE,GAAG,MAAM,GAAG,OAAO,CAAC;QACtD,aAAa,CAAC,QAAQ,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;QAC7C,OAAO,CAAC,GAAG,CAAC,kCAAkC,IAAI,EAAE,CAAC,CAAC;IACxD,CAAC;SAAM,CAAC;QACN,kBAAkB;QAClB,aAAa,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QAC1C,OAAO,CAAC,GAAG,CAAC,kCAAkC,IAAI,EAAE,CAAC,CAAC;IACxD,CAAC;IAED,8BAA8B;IAC9B,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QACjC,IAAI,CAAC;YACH,SAAS,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QAC7B,CAAC;QAAC,MAAM,CAAC;YACP,iCAAiC;QACnC,CAAC;IACH,CAAC;AACH,CAAC;AAED,+EAA+E;AAC/E,mBAAmB;AACnB,+EAA+E;AAE/E;;;;;GAKG;AACH,SAAS,aAAa,CAAC,IAAc;IACnC,OAAO;QACL,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC;KACjC,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,OAAiB,EAAE;IACxD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;QAEpC,yBAAyB;QACzB,MAAM,WAAW,GAAG,oBAAoB,EAAE,CAAC;QAC3C,OAAO,CAAC,GAAG,CAAC,8BAA8B,WAAW,EAAE,CAAC,CAAC;QAEzD,yBAAyB;QACzB,MAAM,YAAY,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC;QAClD,MAAM,QAAQ,GAAG,YAAY,CAAC,YAAY,CAAC,CAAC;QAE5C,cAAc;QACd,QAAQ,CAAC,KAAK,GAAG,QAAQ,CAAC,KAAK,IAAI,EAAE,CAAC;QACtC,QAAQ,CAAC,KAAK,CAAC,UAAU,GAAG,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,UAAU,EAAE,YAAY,CAAC,UAAU,CAAC,CAAC;QAC3F,QAAQ,CAAC,KAAK,CAAC,WAAW,GAAG,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,WAAW,EAAE,YAAY,CAAC,WAAW,CAAC,CAAC;QAE9F,gBAAgB;QAChB,YAAY,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;QACrC,OAAO,CAAC,GAAG,CAAC,yCAAyC,YAAY,EAAE,CAAC,CAAC;QAErE,+BAA+B;QAC/B,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,iBAAiB,EAAE,EAAE,CAAC;YAC1C,MAAM,SAAS,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC;YAC/C,IAAI,SAAS,EAAE,CAAC;gBACd,OAAO,CAAC,GAAG,CAAC,+CAA+C,CAAC,CAAC;YAC/D,CAAC;QACH,CAAC;aAAM,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;YACzB,OAAO,CAAC,GAAG,CAAC,sDAAsD,CAAC,CAAC;QACtE,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,kDAAkD,CAAC,CAAC;QAClE,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,+CAA+C,CAAC,CAAC;QAC7D,OAAO,CAAC,GAAG,CAAC,iDAAiD,CAAC,CAAC;IACjE,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,KAAK,CAAC,uBAAuB,OAAO,EAAE,CAAC,CAAC;QAChD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,+EAA+E;AAC/E,uCAAuC;AACvC,+EAA+E;AAE/E;;;;;GAKG;AACH,SAAS,kBAAkB,CAAC,WAAmB;IAC7C,MAAM,YAAY,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC;IAElD,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,YAAY,CAAC,YAAY,CAAC,CAAC;QAE5C,6BAA6B;QAC7B,MAAM,aAAa,GAAG,QAAQ,CAAC,KAAK,EAAE,UAAU,EAAE,IAAI,CACpD,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC,CAC7D,CAAC;QACF,MAAM,cAAc,GAAG,QAAQ,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,CACtD,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC,CAC7D,CAAC;QAEF,OAAO,CAAC,CAAC,CAAC,aAAa,IAAI,cAAc,CAAC,CAAC;IAC7C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,mBAAmB,CAAC,WAAmB;IACrD,6BAA6B;IAC7B,IAAI,kBAAkB,CAAC,WAAW,CAAC,EAAE,CAAC;QACpC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,CAAC;QACH,yBAAyB;QACzB,MAAM,YAAY,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC;QAClD,MAAM,QAAQ,GAAG,YAAY,CAAC,YAAY,CAAC,CAAC;QAE5C,cAAc;QACd,QAAQ,CAAC,KAAK,GAAG,QAAQ,CAAC,KAAK,IAAI,EAAE,CAAC;QACtC,QAAQ,CAAC,KAAK,CAAC,UAAU,GAAG,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,UAAU,EAAE,YAAY,CAAC,UAAU,CAAC,CAAC;QAC3F,QAAQ,CAAC,KAAK,CAAC,WAAW,GAAG,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,WAAW,EAAE,YAAY,CAAC,WAAW,CAAC,CAAC;QAE9F,gBAAgB;QAChB,YAAY,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;QAErC,6CAA6C;QAC7C,IAAI,iBAAiB,EAAE,EAAE,CAAC;YACxB,qBAAqB,CAAC,WAAW,CAAC,CAAC;QACrC,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,kDAAkD;QAClD,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,SAAS,qBAAqB,CAAC,WAAmB;IAChD,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IAE1C,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACzB,OAAO;IACT,CAAC;IAED,IAAI,QAAgB,CAAC;IAErB,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;QAC/B,IAAI,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;YAClB,6CAA6C;YAC7C,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;YACtD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;YAChD,IAAI,KAAK,EAAE,CAAC;gBACV,6CAA6C;gBAC7C,8BAA8B;gBAC9B,MAAM,UAAU,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;gBAC5B,MAAM,cAAc,GAAG,UAAU,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC;gBAC7D,IAAI,cAAc,KAAK,CAAC,CAAC,EAAE,CAAC;oBAC1B,MAAM,UAAU,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC;oBAC3D,QAAQ,GAAG,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;gBACvC,CAAC;qBAAM,CAAC;oBACN,wBAAwB;oBACxB,MAAM,QAAQ,GAAG,UAAU,CAAC,WAAW,CAAC,eAAe,CAAC,CAAC;oBACzD,IAAI,QAAQ,KAAK,CAAC,CAAC,EAAE,CAAC;wBACpB,MAAM,UAAU,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;wBACrD,QAAQ,GAAG,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;oBACvC,CAAC;yBAAM,CAAC;wBACN,OAAO;oBACT,CAAC;gBACH,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,OAAO;YACT,CAAC;QACH,CAAC;aAAM,CAAC;YACN,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACpC,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;IACT,CAAC;IAED,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1B,SAAS,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3C,CAAC;IAED,yBAAyB;IACzB,qBAAqB,CAAC,IAAI,CAAC,QAAQ,EAAE,YAAY,CAAC,EAAE,eAAe,CAAC,CAAC;IACrE,qBAAqB,CAAC,IAAI,CAAC,QAAQ,EAAE,cAAc,CAAC,EAAE,iBAAiB,CAAC,CAAC;AAC3E,CAAC;AAED;;;;;GAKG;AACH,SAAS,qBAAqB,CAAC,QAAgB,EAAE,OAAe;IAC9D,IAAI,CAAC;QACH,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YACzB,MAAM,QAAQ,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YACjD,IAAI,QAAQ,CAAC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC;gBACzC,OAAO,CAAC,oBAAoB;YAC9B,CAAC;YACD,aAAa,CAAC,QAAQ,EAAE,QAAQ,CAAC,IAAI,EAAE,GAAG,MAAM,GAAG,OAAO,EAAE,OAAO,CAAC,CAAC;QACvE,CAAC;aAAM,CAAC;YACN,aAAa,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QAC5C,CAAC;QAED,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;YACjC,SAAS,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,iBAAiB;IACnB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mark Done Hook Command
|
|
3
|
+
*
|
|
4
|
+
* Marks plan decisions as "implemented" after merge/rebase.
|
|
5
|
+
* Called by Git hooks (post-merge, post-rewrite) or manually.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* sqlew mark-done --auto # Auto-detect from current plan
|
|
9
|
+
* sqlew mark-done <plan-id> # Specify plan ID explicitly
|
|
10
|
+
*
|
|
11
|
+
* Git Hooks Usage:
|
|
12
|
+
* .git/hooks/post-merge: sqlew mark-done --auto
|
|
13
|
+
* .git/hooks/post-rewrite: if [ "$1" = "rebase" ]; then sqlew mark-done --auto; fi
|
|
14
|
+
*
|
|
15
|
+
* @since v4.1.0
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Main mark-done command entry point
|
|
19
|
+
*
|
|
20
|
+
* Called by Git hooks or manually to mark decisions as implemented.
|
|
21
|
+
*
|
|
22
|
+
* @param args - Command line arguments (optional, for CLI usage)
|
|
23
|
+
*/
|
|
24
|
+
export declare function markDoneCommand(args?: string[]): Promise<void>;
|
|
25
|
+
//# sourceMappingURL=mark-done.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mark-done.d.ts","sourceRoot":"","sources":["../../../src/cli/hooks/mark-done.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AA8CH;;;;;;GAMG;AACH,wBAAsB,eAAe,CAAC,IAAI,GAAE,MAAM,EAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAqExE"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mark Done Hook Command
|
|
3
|
+
*
|
|
4
|
+
* Marks plan decisions as "implemented" after merge/rebase.
|
|
5
|
+
* Called by Git hooks (post-merge, post-rewrite) or manually.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* sqlew mark-done --auto # Auto-detect from current plan
|
|
9
|
+
* sqlew mark-done <plan-id> # Specify plan ID explicitly
|
|
10
|
+
*
|
|
11
|
+
* Git Hooks Usage:
|
|
12
|
+
* .git/hooks/post-merge: sqlew mark-done --auto
|
|
13
|
+
* .git/hooks/post-rewrite: if [ "$1" = "rebase" ]; then sqlew mark-done --auto; fi
|
|
14
|
+
*
|
|
15
|
+
* @since v4.1.0
|
|
16
|
+
*/
|
|
17
|
+
import { loadCurrentPlan } from '../../config/global-config.js';
|
|
18
|
+
import { initializeDatabase } from '../../database.js';
|
|
19
|
+
import { setDecision } from '../../tools/context/actions/set.js';
|
|
20
|
+
import { determineProjectRoot } from '../../utils/project-root.js';
|
|
21
|
+
import { join } from 'path';
|
|
22
|
+
// ============================================================================
|
|
23
|
+
// Constants
|
|
24
|
+
// ============================================================================
|
|
25
|
+
/** Decision key prefix for plan-based decisions */
|
|
26
|
+
const PLAN_DECISION_PREFIX = 'plan/implementation';
|
|
27
|
+
/** Status for implemented decisions (using 'active' as DB only supports active/deprecated/draft) */
|
|
28
|
+
const IMPLEMENTED_STATUS = 'active';
|
|
29
|
+
/** Workflow tag for implemented state */
|
|
30
|
+
const WORKFLOW_TAG_IMPLEMENTED = 'workflow:implemented';
|
|
31
|
+
// ============================================================================
|
|
32
|
+
// Command Implementation
|
|
33
|
+
// ============================================================================
|
|
34
|
+
/**
|
|
35
|
+
* Parse command line arguments for mark-done
|
|
36
|
+
*
|
|
37
|
+
* @param args - Command line arguments
|
|
38
|
+
* @returns Parsed options
|
|
39
|
+
*/
|
|
40
|
+
function parseMarkDoneArgs(args) {
|
|
41
|
+
let auto = false;
|
|
42
|
+
let planId;
|
|
43
|
+
for (const arg of args) {
|
|
44
|
+
if (arg === '--auto') {
|
|
45
|
+
auto = true;
|
|
46
|
+
}
|
|
47
|
+
else if (!arg.startsWith('-')) {
|
|
48
|
+
planId = arg;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return { auto, planId };
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Main mark-done command entry point
|
|
55
|
+
*
|
|
56
|
+
* Called by Git hooks or manually to mark decisions as implemented.
|
|
57
|
+
*
|
|
58
|
+
* @param args - Command line arguments (optional, for CLI usage)
|
|
59
|
+
*/
|
|
60
|
+
export async function markDoneCommand(args = []) {
|
|
61
|
+
try {
|
|
62
|
+
const options = parseMarkDoneArgs(args);
|
|
63
|
+
// Determine project root
|
|
64
|
+
const projectPath = determineProjectRoot();
|
|
65
|
+
// Load current plan if using --auto
|
|
66
|
+
let planInfo = null;
|
|
67
|
+
if (options.auto) {
|
|
68
|
+
planInfo = loadCurrentPlan(projectPath);
|
|
69
|
+
if (!planInfo) {
|
|
70
|
+
// No plan being tracked - nothing to do
|
|
71
|
+
console.log('[sqlew mark-done] No plan currently being tracked.');
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
if (!planInfo.recorded) {
|
|
75
|
+
// Plan was never recorded as a decision
|
|
76
|
+
console.log('[sqlew mark-done] No decision recorded for current plan.');
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
else if (!options.planId) {
|
|
81
|
+
console.error('[sqlew mark-done] Usage: sqlew mark-done --auto or sqlew mark-done <plan-id>');
|
|
82
|
+
process.exit(1);
|
|
83
|
+
}
|
|
84
|
+
// Initialize database
|
|
85
|
+
const dbPath = join(projectPath, '.sqlew', 'sqlew.db');
|
|
86
|
+
try {
|
|
87
|
+
await initializeDatabase({ configPath: dbPath });
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
console.error('[sqlew mark-done] Database not initialized.');
|
|
91
|
+
process.exit(1);
|
|
92
|
+
}
|
|
93
|
+
// Build decision key
|
|
94
|
+
let decisionKey;
|
|
95
|
+
if (planInfo) {
|
|
96
|
+
const planName = planInfo.plan_file.replace(/\.md$/, '');
|
|
97
|
+
decisionKey = `${PLAN_DECISION_PREFIX}/${planName}`;
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
// Use provided plan ID
|
|
101
|
+
decisionKey = `${PLAN_DECISION_PREFIX}/${options.planId}`;
|
|
102
|
+
}
|
|
103
|
+
// Update decision status to active (implemented tracked via tag)
|
|
104
|
+
try {
|
|
105
|
+
await setDecision({
|
|
106
|
+
key: decisionKey,
|
|
107
|
+
value: planInfo
|
|
108
|
+
? `Implementation completed for plan: ${planInfo.plan_file}`
|
|
109
|
+
: `Implementation completed for plan: ${options.planId}`,
|
|
110
|
+
status: IMPLEMENTED_STATUS,
|
|
111
|
+
layer: 'cross-cutting',
|
|
112
|
+
tags: ['plan', 'implementation', WORKFLOW_TAG_IMPLEMENTED],
|
|
113
|
+
});
|
|
114
|
+
console.log(`[sqlew mark-done] Decision marked as ${IMPLEMENTED_STATUS}: ${decisionKey}`);
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
118
|
+
console.error(`[sqlew mark-done] Error updating decision: ${message}`);
|
|
119
|
+
process.exit(1);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
124
|
+
console.error(`[sqlew mark-done] Error: ${message}`);
|
|
125
|
+
process.exit(1);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=mark-done.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mark-done.js","sourceRoot":"","sources":["../../../src/cli/hooks/mark-done.ts"],"names":[],"mappings":"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"}
|