@ghl-ai/aw 0.1.36-beta.2 → 0.1.36-beta.21
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/commands/drop.mjs +2 -2
- package/commands/init.mjs +55 -19
- package/commands/link-project.mjs +50 -10
- package/commands/nuke.mjs +44 -1
- package/commands/pull.mjs +45 -6
- package/commands/push.mjs +224 -108
- package/commands/search.mjs +3 -2
- package/commands/status.mjs +8 -3
- package/git.mjs +298 -16
- package/hooks.mjs +49 -5
- package/integrate.mjs +3 -1
- package/link.mjs +7 -2
- package/package.json +1 -1
package/commands/drop.mjs
CHANGED
|
@@ -7,7 +7,7 @@ import * as config from '../config.mjs';
|
|
|
7
7
|
import * as fmt from '../fmt.mjs';
|
|
8
8
|
import { chalk } from '../fmt.mjs';
|
|
9
9
|
import { resolveInput } from '../paths.mjs';
|
|
10
|
-
import { removeFromSparseCheckout, isValidClone } from '../git.mjs';
|
|
10
|
+
import { removeFromSparseCheckout, isValidClone, getLocalRegistryDir } from '../git.mjs';
|
|
11
11
|
import { REGISTRY_DIR, REGISTRY_REPO } from '../constants.mjs';
|
|
12
12
|
import { linkWorkspace } from '../link.mjs';
|
|
13
13
|
|
|
@@ -18,7 +18,7 @@ export function dropCommand(args) {
|
|
|
18
18
|
const HOME = homedir();
|
|
19
19
|
const AW_HOME = join(HOME, '.aw');
|
|
20
20
|
const GLOBAL_AW_DIR = join(HOME, '.aw_registry');
|
|
21
|
-
const workspaceDir =
|
|
21
|
+
const workspaceDir = getLocalRegistryDir(cwd, GLOBAL_AW_DIR);
|
|
22
22
|
|
|
23
23
|
fmt.intro('aw drop');
|
|
24
24
|
|
package/commands/init.mjs
CHANGED
|
@@ -4,12 +4,11 @@
|
|
|
4
4
|
// Uses core.hooksPath (git-lfs pattern) for system-wide hook interception.
|
|
5
5
|
// Uses IDE tasks for auto-pull on workspace open.
|
|
6
6
|
|
|
7
|
-
import { existsSync, writeFileSync, symlinkSync, lstatSync, readdirSync } from 'node:fs';
|
|
7
|
+
import { existsSync, writeFileSync, symlinkSync, lstatSync, readdirSync, readFileSync, rmSync } from 'node:fs';
|
|
8
8
|
import { execSync } from 'node:child_process';
|
|
9
|
-
import { join, dirname } from 'node:path';
|
|
9
|
+
import { join, dirname, sep } from 'node:path';
|
|
10
10
|
import { homedir } from 'node:os';
|
|
11
11
|
import { fileURLToPath } from 'node:url';
|
|
12
|
-
import { readFileSync } from 'node:fs';
|
|
13
12
|
import * as config from '../config.mjs';
|
|
14
13
|
import * as fmt from '../fmt.mjs';
|
|
15
14
|
import { chalk } from '../fmt.mjs';
|
|
@@ -24,6 +23,8 @@ import {
|
|
|
24
23
|
isValidClone,
|
|
25
24
|
fetchAndMerge,
|
|
26
25
|
addToSparseCheckout,
|
|
26
|
+
addProjectWorktree,
|
|
27
|
+
isWorktree,
|
|
27
28
|
includeToSparsePaths,
|
|
28
29
|
sparseCheckoutAsync,
|
|
29
30
|
cleanup,
|
|
@@ -194,22 +195,40 @@ export async function initCommand(args) {
|
|
|
194
195
|
|
|
195
196
|
const freshCfg = config.load(GLOBAL_AW_DIR);
|
|
196
197
|
|
|
197
|
-
linkWorkspace(HOME);
|
|
198
198
|
await installAwEcc(cwd, { silent });
|
|
199
|
-
generateCommands(HOME);
|
|
200
199
|
copyInstructions(HOME, null, freshCfg?.namespace || team) || [];
|
|
201
200
|
initAwDocs(HOME);
|
|
202
201
|
await setupMcp(HOME, freshCfg?.namespace || team, { silent });
|
|
203
202
|
if (cwd !== HOME) await setupMcp(cwd, freshCfg?.namespace || team, { silent });
|
|
204
203
|
installGlobalHooks();
|
|
205
204
|
|
|
206
|
-
|
|
205
|
+
// Remove old local .git/hooks/post-checkout that pre-dates core.hooksPath (creates stale .aw_registry symlink)
|
|
206
|
+
if (cwd !== HOME) {
|
|
207
|
+
const oldLocalHook = join(cwd, '.git', 'hooks', 'post-checkout');
|
|
208
|
+
try {
|
|
209
|
+
const content = readFileSync(oldLocalHook, 'utf8');
|
|
210
|
+
if (content.includes('aw: auto-link registry') || content.includes('ln -s "$AW_REGISTRY"')) {
|
|
211
|
+
rmSync(oldLocalHook);
|
|
212
|
+
if (!silent) fmt.logStep('Removed legacy .git/hooks/post-checkout');
|
|
213
|
+
}
|
|
214
|
+
} catch { /* not there, fine */ }
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const isInsideAw = cwd.endsWith(`${sep}.aw`) || cwd.includes(`${sep}.aw${sep}`);
|
|
218
|
+
if (cwd !== HOME && !isInsideAw && !isWorktree(join(cwd, '.aw'))) {
|
|
207
219
|
try {
|
|
208
|
-
|
|
209
|
-
if (!silent) fmt.logStep('Linked
|
|
220
|
+
addProjectWorktree(AW_HOME, cwd);
|
|
221
|
+
if (!silent) fmt.logStep('Linked current project as git worktree');
|
|
210
222
|
} catch { /* best effort */ }
|
|
211
223
|
}
|
|
212
224
|
|
|
225
|
+
// Wire ~/.claude/.cursor/.codex to the project's registry when in a project,
|
|
226
|
+
// so edits to project/.aw/.aw_registry/ are instantly visible in global IDE dirs.
|
|
227
|
+
const projectRegistryDir = cwd !== HOME ? join(cwd, '.aw', REGISTRY_DIR) : null;
|
|
228
|
+
const awDirForLinks = (projectRegistryDir && existsSync(projectRegistryDir)) ? projectRegistryDir : null;
|
|
229
|
+
linkWorkspace(HOME, awDirForLinks);
|
|
230
|
+
generateCommands(HOME);
|
|
231
|
+
|
|
213
232
|
if (silent) {
|
|
214
233
|
autoUpdate(await args._updateCheck);
|
|
215
234
|
} else {
|
|
@@ -218,7 +237,7 @@ export async function initCommand(args) {
|
|
|
218
237
|
'',
|
|
219
238
|
` ${chalk.green('✓')} Registry updated`,
|
|
220
239
|
` ${chalk.green('✓')} IDE integration refreshed`,
|
|
221
|
-
cwd !== HOME &&
|
|
240
|
+
cwd !== HOME && isWorktree(join(cwd, '.aw')) ? ` ${chalk.green('✓')} Current project linked` : null,
|
|
222
241
|
].filter(Boolean).join('\n'));
|
|
223
242
|
}
|
|
224
243
|
return;
|
|
@@ -247,7 +266,7 @@ export async function initCommand(args) {
|
|
|
247
266
|
}
|
|
248
267
|
|
|
249
268
|
// Determine sparse paths
|
|
250
|
-
const sparsePaths = [`.aw_registry/platform`, `content`, `.aw_registry/AW-PROTOCOL.md`];
|
|
269
|
+
const sparsePaths = [`.aw_registry/platform`, `content`, `.aw_registry/AW-PROTOCOL.md`, `CODEOWNERS`];
|
|
251
270
|
if (folderName) {
|
|
252
271
|
sparsePaths.push(`.aw_registry/${folderName}`);
|
|
253
272
|
}
|
|
@@ -286,11 +305,8 @@ export async function initCommand(args) {
|
|
|
286
305
|
config.addPattern(GLOBAL_AW_DIR, folderName);
|
|
287
306
|
}
|
|
288
307
|
|
|
289
|
-
// Step 3:
|
|
290
|
-
fmt.logStep('Linking IDE symlinks...');
|
|
291
|
-
linkWorkspace(HOME);
|
|
308
|
+
// Step 3: Setup tasks, MCP, hooks
|
|
292
309
|
await installAwEcc(cwd, { silent });
|
|
293
|
-
generateCommands(HOME);
|
|
294
310
|
const instructionFiles = copyInstructions(HOME, null, team) || [];
|
|
295
311
|
initAwDocs(HOME);
|
|
296
312
|
const mcpFiles = await setupMcp(HOME, team) || [];
|
|
@@ -298,14 +314,34 @@ export async function initCommand(args) {
|
|
|
298
314
|
const hooksInstalled = installGlobalHooks();
|
|
299
315
|
installIdeTasks();
|
|
300
316
|
|
|
301
|
-
//
|
|
302
|
-
if (cwd !== HOME
|
|
317
|
+
// Remove old local .git/hooks/post-checkout that pre-dates core.hooksPath
|
|
318
|
+
if (cwd !== HOME) {
|
|
319
|
+
const oldLocalHook = join(cwd, '.git', 'hooks', 'post-checkout');
|
|
303
320
|
try {
|
|
304
|
-
|
|
305
|
-
|
|
321
|
+
const content = readFileSync(oldLocalHook, 'utf8');
|
|
322
|
+
if (content.includes('aw: auto-link registry') || content.includes('ln -s "$AW_REGISTRY"')) {
|
|
323
|
+
rmSync(oldLocalHook);
|
|
324
|
+
}
|
|
325
|
+
} catch { /* not there, fine */ }
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// Step 4: Link current project as a git worktree (gives IDE git panel)
|
|
329
|
+
const isInsideAw = cwd.endsWith(`${sep}.aw`) || cwd.includes(`${sep}.aw${sep}`);
|
|
330
|
+
if (cwd !== HOME && !isInsideAw && !isWorktree(join(cwd, '.aw'))) {
|
|
331
|
+
try {
|
|
332
|
+
addProjectWorktree(AW_HOME, cwd);
|
|
333
|
+
fmt.logStep('Linked current project as git worktree');
|
|
306
334
|
} catch { /* best effort */ }
|
|
307
335
|
}
|
|
308
336
|
|
|
337
|
+
// Step 5: Wire ~/.claude/.cursor/.codex to the project's registry when in a project,
|
|
338
|
+
// so edits to project/.aw/.aw_registry/ are instantly visible in global IDE dirs.
|
|
339
|
+
fmt.logStep('Linking IDE symlinks...');
|
|
340
|
+
const projectRegistryDir = cwd !== HOME ? join(cwd, '.aw', REGISTRY_DIR) : null;
|
|
341
|
+
const awDirForLinks = (projectRegistryDir && existsSync(projectRegistryDir)) ? projectRegistryDir : null;
|
|
342
|
+
linkWorkspace(HOME, awDirForLinks);
|
|
343
|
+
generateCommands(HOME);
|
|
344
|
+
|
|
309
345
|
// Offer to update if a newer version is available
|
|
310
346
|
await promptUpdate(await args._updateCheck);
|
|
311
347
|
|
|
@@ -317,7 +353,7 @@ export async function initCommand(args) {
|
|
|
317
353
|
` ${chalk.green('✓')} IDE integration: ~/.claude/, ~/.cursor/, ~/.codex/`,
|
|
318
354
|
hooksInstalled ? ` ${chalk.green('✓')} Git hooks: auto-sync on pull/clone (core.hooksPath)` : null,
|
|
319
355
|
` ${chalk.green('✓')} IDE task: auto-sync on workspace open`,
|
|
320
|
-
cwd !== HOME &&
|
|
356
|
+
cwd !== HOME && isWorktree(join(cwd, '.aw')) ? ` ${chalk.green('✓')} Linked in current project` : null,
|
|
321
357
|
'',
|
|
322
358
|
` ${chalk.dim('Existing repos:')} ${chalk.bold('cd <project> && aw link')}`,
|
|
323
359
|
` ${chalk.dim('New clones:')} auto-linked via git hook`,
|
|
@@ -1,26 +1,66 @@
|
|
|
1
|
-
// commands/link-project.mjs —
|
|
1
|
+
// commands/link-project.mjs — Link current project to registry via git worktree
|
|
2
2
|
|
|
3
|
-
import { existsSync,
|
|
3
|
+
import { existsSync, lstatSync, rmSync } from 'node:fs';
|
|
4
4
|
import { join } from 'node:path';
|
|
5
5
|
import { homedir } from 'node:os';
|
|
6
6
|
import * as fmt from '../fmt.mjs';
|
|
7
7
|
import { chalk } from '../fmt.mjs';
|
|
8
|
+
import { addProjectWorktree, isWorktree, isValidClone } from '../git.mjs';
|
|
9
|
+
import { REGISTRY_DIR, REGISTRY_REPO } from '../constants.mjs';
|
|
10
|
+
import { linkWorkspace } from '../link.mjs';
|
|
11
|
+
import { generateCommands } from '../integrate.mjs';
|
|
8
12
|
|
|
9
|
-
const
|
|
13
|
+
const HOME = homedir();
|
|
14
|
+
const AW_HOME = join(HOME, '.aw');
|
|
10
15
|
|
|
11
16
|
export function linkProjectCommand(args) {
|
|
12
17
|
const cwd = process.cwd();
|
|
13
|
-
const target = join(cwd, '.aw_registry');
|
|
14
18
|
|
|
15
|
-
|
|
16
|
-
|
|
19
|
+
fmt.intro('aw link');
|
|
20
|
+
|
|
21
|
+
const repoUrl = `https://github.com/${REGISTRY_REPO}.git`;
|
|
22
|
+
if (!isValidClone(AW_HOME, repoUrl)) {
|
|
23
|
+
fmt.cancel('Registry not initialized. Run: aw init');
|
|
24
|
+
return;
|
|
17
25
|
}
|
|
18
26
|
|
|
19
|
-
if (
|
|
20
|
-
fmt.
|
|
27
|
+
if (cwd === HOME) {
|
|
28
|
+
fmt.cancel('Cannot link home directory as a project');
|
|
21
29
|
return;
|
|
22
30
|
}
|
|
23
31
|
|
|
24
|
-
|
|
25
|
-
|
|
32
|
+
const worktreeDir = join(cwd, '.aw');
|
|
33
|
+
|
|
34
|
+
// Remove stale project-root .aw_registry symlink from old installs
|
|
35
|
+
const staleSymlink = join(cwd, REGISTRY_DIR);
|
|
36
|
+
try { if (lstatSync(staleSymlink).isSymbolicLink()) rmSync(staleSymlink); } catch { /* fine */ }
|
|
37
|
+
|
|
38
|
+
if (isWorktree(worktreeDir)) {
|
|
39
|
+
// Worktree exists — refresh global IDE symlinks pointing to this project's registry
|
|
40
|
+
const projectRegistryDir = join(worktreeDir, REGISTRY_DIR);
|
|
41
|
+
const awDirForLinks = existsSync(projectRegistryDir) ? projectRegistryDir : null;
|
|
42
|
+
linkWorkspace(HOME, awDirForLinks);
|
|
43
|
+
generateCommands(HOME);
|
|
44
|
+
fmt.logSuccess(`Already linked — refreshed IDE symlinks`);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
try {
|
|
49
|
+
addProjectWorktree(AW_HOME, cwd);
|
|
50
|
+
const projectRegistryDir = join(worktreeDir, REGISTRY_DIR);
|
|
51
|
+
const awDirForLinks = existsSync(projectRegistryDir) ? projectRegistryDir : null;
|
|
52
|
+
linkWorkspace(HOME, awDirForLinks);
|
|
53
|
+
generateCommands(HOME);
|
|
54
|
+
fmt.logSuccess([
|
|
55
|
+
`Linked project as git worktree`,
|
|
56
|
+
'',
|
|
57
|
+
` ${chalk.green('✓')} ${chalk.dim('.aw/')} git worktree (IDE git panel enabled)`,
|
|
58
|
+
` ${chalk.green('✓')} ${chalk.dim(`.aw/${REGISTRY_DIR}/`)} registry content`,
|
|
59
|
+
` ${chalk.green('✓')} ${chalk.dim('.claude/.cursor/.codex/')} IDE symlinks wired`,
|
|
60
|
+
].join('\n'));
|
|
61
|
+
} catch (e) {
|
|
62
|
+
fmt.cancel(`Failed to link project: ${e.message}`);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
fmt.outro('Done');
|
|
26
66
|
}
|
package/commands/nuke.mjs
CHANGED
|
@@ -10,6 +10,7 @@ import * as fmt from '../fmt.mjs';
|
|
|
10
10
|
import { chalk } from '../fmt.mjs';
|
|
11
11
|
import { removeGlobalHooks } from '../hooks.mjs';
|
|
12
12
|
import { uninstallAwEcc } from '../ecc.mjs';
|
|
13
|
+
import { listProjectWorktrees } from '../git.mjs';
|
|
13
14
|
|
|
14
15
|
const HOME = homedir();
|
|
15
16
|
const GLOBAL_AW_DIR = join(HOME, '.aw_registry');
|
|
@@ -169,6 +170,25 @@ function removeProjectSymlinks() {
|
|
|
169
170
|
}
|
|
170
171
|
|
|
171
172
|
if (removed > 0) fmt.logStep(`Removed ${removed} project .aw_registry symlink${removed > 1 ? 's' : ''}`);
|
|
173
|
+
|
|
174
|
+
// Also remove legacy local .git/hooks/post-checkout installed by old aw versions
|
|
175
|
+
let hooksRemoved = 0;
|
|
176
|
+
try {
|
|
177
|
+
const result = execSync(
|
|
178
|
+
`find "${HOME}" -maxdepth 5 -path "*/.git/hooks/post-checkout" -type f 2>/dev/null`,
|
|
179
|
+
{ encoding: 'utf8', timeout: 10000 }
|
|
180
|
+
).trim();
|
|
181
|
+
for (const hookPath of result.split('\n').filter(Boolean)) {
|
|
182
|
+
try {
|
|
183
|
+
const content = readFileSync(hookPath, 'utf8');
|
|
184
|
+
if (content.includes('aw: auto-link registry') || content.includes('ln -s "$AW_REGISTRY"')) {
|
|
185
|
+
unlinkSync(hookPath);
|
|
186
|
+
hooksRemoved++;
|
|
187
|
+
}
|
|
188
|
+
} catch { /* best effort */ }
|
|
189
|
+
}
|
|
190
|
+
} catch { /* find failed, skip */ }
|
|
191
|
+
if (hooksRemoved > 0) fmt.logStep(`Removed ${hooksRemoved} legacy .git/hooks/post-checkout script${hooksRemoved > 1 ? 's' : ''}`);
|
|
172
192
|
}
|
|
173
193
|
|
|
174
194
|
// 4. Remove git hooks (global core.hooksPath + legacy template)
|
|
@@ -298,8 +318,30 @@ export function nukeCommand(args) {
|
|
|
298
318
|
}
|
|
299
319
|
fmt.logStep('Removed ~/.aw_registry/');
|
|
300
320
|
|
|
301
|
-
// 11. Remove
|
|
321
|
+
// 11. Remove project git worktrees (must happen before deleting ~/.aw/)
|
|
302
322
|
const AW_HOME = join(HOME, '.aw');
|
|
323
|
+
if (existsSync(AW_HOME)) {
|
|
324
|
+
try {
|
|
325
|
+
const worktrees = listProjectWorktrees(AW_HOME);
|
|
326
|
+
let wtRemoved = 0;
|
|
327
|
+
for (const wt of worktrees) {
|
|
328
|
+
try {
|
|
329
|
+
execSync(`git -C "${AW_HOME}" worktree remove "${wt.path}" --force`, { stdio: 'pipe' });
|
|
330
|
+
wtRemoved++;
|
|
331
|
+
} catch {
|
|
332
|
+
// Manual cleanup if git command fails
|
|
333
|
+
try { rmSync(wt.path, { recursive: true, force: true }); } catch { /* best effort */ }
|
|
334
|
+
wtRemoved++;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
if (worktrees.length > 0) {
|
|
338
|
+
try { execSync(`git -C "${AW_HOME}" worktree prune`, { stdio: 'pipe' }); } catch { /* best effort */ }
|
|
339
|
+
fmt.logStep(`Removed ${wtRemoved} project worktree${wtRemoved > 1 ? 's' : ''}`);
|
|
340
|
+
}
|
|
341
|
+
} catch { /* best effort */ }
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// 12. Remove ~/.aw/ (persistent git clone)
|
|
303
345
|
if (existsSync(AW_HOME)) {
|
|
304
346
|
try {
|
|
305
347
|
rmSync(AW_HOME, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 });
|
|
@@ -315,6 +357,7 @@ export function nukeCommand(args) {
|
|
|
315
357
|
` ${chalk.green('✓')} Generated files cleaned`,
|
|
316
358
|
` ${chalk.green('✓')} IDE symlinks cleaned`,
|
|
317
359
|
` ${chalk.green('✓')} aw-ecc engine removed`,
|
|
360
|
+
` ${chalk.green('✓')} Project worktrees removed`,
|
|
318
361
|
` ${chalk.green('✓')} Project symlinks cleaned`,
|
|
319
362
|
` ${chalk.green('✓')} Git hooks removed`,
|
|
320
363
|
` ${chalk.green('✓')} IDE auto-sync tasks removed`,
|
package/commands/pull.mjs
CHANGED
|
@@ -7,7 +7,7 @@ import { execSync } from 'node:child_process';
|
|
|
7
7
|
import * as config from '../config.mjs';
|
|
8
8
|
import * as fmt from '../fmt.mjs';
|
|
9
9
|
import { chalk } from '../fmt.mjs';
|
|
10
|
-
import { fetchAndMerge, addToSparseCheckout, isValidClone } from '../git.mjs';
|
|
10
|
+
import { fetchAndMerge, addToSparseCheckout, isValidClone, isWorktree, rebaseOntoOriginMain } from '../git.mjs';
|
|
11
11
|
import { REGISTRY_DIR, REGISTRY_REPO, DOCS_SOURCE_DIR } from '../constants.mjs';
|
|
12
12
|
import { linkWorkspace } from '../link.mjs';
|
|
13
13
|
import { generateCommands, copyInstructions } from '../integrate.mjs';
|
|
@@ -73,18 +73,57 @@ export async function pullCommand(args) {
|
|
|
73
73
|
log.logWarn(`Conflicts in: ${fetchResult.conflicts.join(', ')}`);
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
+
// Always rebase project worktree's current branch onto origin/main
|
|
77
|
+
const localAw = join(cwd, '.aw');
|
|
78
|
+
if (cwd !== HOME && isWorktree(localAw)) {
|
|
79
|
+
try {
|
|
80
|
+
rebaseOntoOriginMain(localAw);
|
|
81
|
+
if (!silent) log.logStep('Local branch rebased onto latest');
|
|
82
|
+
} catch (e) {
|
|
83
|
+
// Check if the failure was due to merge conflicts
|
|
84
|
+
const isConflict = e.message?.includes('could not apply') || e.message?.includes('CONFLICT');
|
|
85
|
+
if (isConflict) {
|
|
86
|
+
// Get list of conflicted files
|
|
87
|
+
let conflictedFiles = [];
|
|
88
|
+
try {
|
|
89
|
+
const out = execSync(`git -C "${localAw}" diff --name-only --diff-filter=U`, {
|
|
90
|
+
stdio: 'pipe', encoding: 'utf8',
|
|
91
|
+
});
|
|
92
|
+
conflictedFiles = out.trim().split('\n').filter(Boolean);
|
|
93
|
+
} catch { /* best effort */ }
|
|
94
|
+
|
|
95
|
+
// Abort rebase to restore clean state
|
|
96
|
+
try {
|
|
97
|
+
execSync(`git -C "${localAw}" rebase --abort`, { stdio: 'pipe' });
|
|
98
|
+
} catch { /* best effort */ }
|
|
99
|
+
|
|
100
|
+
if (!silent) {
|
|
101
|
+
log.logWarn('Merge conflict detected — rebase aborted, your branch is unchanged.');
|
|
102
|
+
if (conflictedFiles.length > 0) {
|
|
103
|
+
log.logWarn(`Conflicting file${conflictedFiles.length > 1 ? 's' : ''}:`);
|
|
104
|
+
for (const f of conflictedFiles) log.logMessage(` ${chalk.red('✗')} ${f}`);
|
|
105
|
+
}
|
|
106
|
+
log.logWarn('Resolve the conflict and run `aw pull` again, or check with `aw status`.');
|
|
107
|
+
}
|
|
108
|
+
} else {
|
|
109
|
+
const msg = e.message?.split('\n').find(l => l.trim()) ?? e.message;
|
|
110
|
+
if (!silent) log.logWarn(`Rebase skipped: ${msg}`);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
76
115
|
// Sync content/ → platform/docs/
|
|
77
116
|
syncDocs(AW_HOME, GLOBAL_AW_DIR);
|
|
78
117
|
|
|
79
118
|
// Re-link IDE dirs
|
|
80
119
|
if (!args._skipIntegrate) {
|
|
81
|
-
|
|
120
|
+
// Wire ~/.claude/.cursor/.codex to the project's registry when in a project,
|
|
121
|
+
// so edits to project/.aw/.aw_registry/ are instantly visible in global IDE dirs.
|
|
122
|
+
const projectRegistryDir = cwd !== HOME ? join(cwd, '.aw', REGISTRY_DIR) : null;
|
|
123
|
+
const awDirForLinks = (projectRegistryDir && existsSync(projectRegistryDir)) ? projectRegistryDir : null;
|
|
124
|
+
linkWorkspace(HOME, awDirForLinks);
|
|
82
125
|
generateCommands(HOME);
|
|
83
126
|
copyInstructions(HOME, null, cfg.namespace);
|
|
84
|
-
if (cwd !== HOME) {
|
|
85
|
-
linkWorkspace(cwd);
|
|
86
|
-
generateCommands(cwd);
|
|
87
|
-
}
|
|
88
127
|
}
|
|
89
128
|
|
|
90
129
|
if (!silent) {
|