@ghl-ai/aw 0.1.34-beta.16 → 0.1.34-beta.17
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/apply.mjs +19 -1
- package/commands/pull.mjs +2 -1
- package/fmt.mjs +2 -2
- package/package.json +1 -1
- package/plan.mjs +21 -17
package/apply.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// apply.mjs — Apply sync plan (file operations). Zero dependencies.
|
|
2
2
|
|
|
3
|
-
import { readFileSync, writeFileSync, mkdirSync, cpSync, existsSync } from 'node:fs';
|
|
3
|
+
import { readFileSync, writeFileSync, mkdirSync, cpSync, existsSync, unlinkSync, rmSync, readdirSync } from 'node:fs';
|
|
4
4
|
import { dirname } from 'node:path';
|
|
5
5
|
|
|
6
6
|
function writeConflictMarkers(filePath, localContent, registryContent) {
|
|
@@ -51,6 +51,24 @@ export function applyActions(actions, { teamNS } = {}) {
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
case 'ORPHAN':
|
|
54
|
+
// File was removed from registry — delete local copy
|
|
55
|
+
if (existsSync(act.targetPath)) {
|
|
56
|
+
try {
|
|
57
|
+
unlinkSync(act.targetPath);
|
|
58
|
+
// Clean up empty parent dirs, stop at .aw_registry/ boundary
|
|
59
|
+
let dir = dirname(act.targetPath);
|
|
60
|
+
while (!dir.endsWith('.aw_registry') && !dir.endsWith('.aw_registry/')) {
|
|
61
|
+
if (readdirSync(dir).length === 0) {
|
|
62
|
+
rmSync(dir);
|
|
63
|
+
dir = dirname(dir);
|
|
64
|
+
} else {
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
} catch { /* best effort */ }
|
|
69
|
+
}
|
|
70
|
+
break;
|
|
71
|
+
|
|
54
72
|
case 'UNCHANGED':
|
|
55
73
|
break;
|
|
56
74
|
}
|
package/commands/pull.mjs
CHANGED
|
@@ -320,7 +320,7 @@ export async function pullAsync(args) {
|
|
|
320
320
|
config.addPattern(workspaceDir, pattern);
|
|
321
321
|
}
|
|
322
322
|
|
|
323
|
-
const { actions: rawActions } = computePlan(registryDirs, workspaceDir, [pattern], { skipOrphans:
|
|
323
|
+
const { actions: rawActions } = computePlan(registryDirs, workspaceDir, [pattern], { skipOrphans: false });
|
|
324
324
|
const actions = filterActions(rawActions, pattern);
|
|
325
325
|
const conflictCount = applyActions(actions, { teamNS: teamNSOverride || renameNamespace || undefined });
|
|
326
326
|
updateManifest(workspaceDir, actions, cfg.namespace, { fromTemplate: !!renameNamespace });
|
|
@@ -418,6 +418,7 @@ function printSummary(actions, verbose, conflictCount) {
|
|
|
418
418
|
if (counts.ADD > 0) parts.push(chalk.green(`${counts.ADD} new`));
|
|
419
419
|
if (counts.UPDATE > 0) parts.push(chalk.cyan(`${counts.UPDATE} updated`));
|
|
420
420
|
if (counts.CONFLICT > 0) parts.push(chalk.red(`${counts.CONFLICT} conflict`));
|
|
421
|
+
if (counts.ORPHAN > 0) parts.push(chalk.yellow(`${counts.ORPHAN} removed`));
|
|
421
422
|
const detail = parts.length > 0 ? ` (${parts.join(', ')})` : '';
|
|
422
423
|
|
|
423
424
|
fmt.logSuccess(`${typeActions.length} ${type} pulled${detail}`);
|
package/fmt.mjs
CHANGED
|
@@ -81,7 +81,7 @@ export function actionLabel(action) {
|
|
|
81
81
|
case 'UPDATE': return chalk.bgCyan.black(' UPD ');
|
|
82
82
|
case 'SKIP': return chalk.bgYellow.black(' SKP ');
|
|
83
83
|
case 'CONFLICT': return chalk.bgRed.white(' CON ');
|
|
84
|
-
case 'ORPHAN': return chalk.
|
|
84
|
+
case 'ORPHAN': return chalk.bgRed.white(' DEL ');
|
|
85
85
|
case 'UNCHANGED': return chalk.dim(' --- ');
|
|
86
86
|
default: return chalk.dim(` ${action} `);
|
|
87
87
|
}
|
|
@@ -94,6 +94,6 @@ export function countSummary(counts) {
|
|
|
94
94
|
if (counts.UNCHANGED > 0) parts.push(chalk.dim(`${counts.UNCHANGED} unchanged`));
|
|
95
95
|
if (counts.SKIP > 0) parts.push(chalk.yellow(`${counts.SKIP} skipped`));
|
|
96
96
|
if (counts.CONFLICT > 0) parts.push(chalk.red(`${counts.CONFLICT} conflict`));
|
|
97
|
-
if (counts.ORPHAN > 0) parts.push(chalk.
|
|
97
|
+
if (counts.ORPHAN > 0) parts.push(chalk.red(`${counts.ORPHAN} removed`));
|
|
98
98
|
return parts.join(chalk.dim(' · '));
|
|
99
99
|
}
|
package/package.json
CHANGED
package/plan.mjs
CHANGED
|
@@ -100,8 +100,14 @@ export function computePlan(registryDirs, workspaceDir, includePatterns = [], {
|
|
|
100
100
|
|
|
101
101
|
// Orphans: in manifest but not in plan
|
|
102
102
|
if (manifest.files && !skipOrphans) {
|
|
103
|
+
// Build a set of all targetFilenames in the plan for exact matching
|
|
104
|
+
const planTargets = new Set(actions.map(a => a.targetFilename));
|
|
105
|
+
|
|
103
106
|
for (const [manifestKey, manifestEntry] of Object.entries(manifest.files)) {
|
|
104
|
-
//
|
|
107
|
+
// Already handled by the plan — not an orphan
|
|
108
|
+
if (planTargets.has(manifestKey)) continue;
|
|
109
|
+
|
|
110
|
+
// manifestKey is namespace/type/slug.md or namespace/type/slug/relPath
|
|
105
111
|
const parts = manifestKey.split('/');
|
|
106
112
|
// Find the type segment
|
|
107
113
|
let typeIdx = -1;
|
|
@@ -115,22 +121,20 @@ export function computePlan(registryDirs, workspaceDir, includePatterns = [], {
|
|
|
115
121
|
const namespace = parts.slice(0, typeIdx).join('/');
|
|
116
122
|
const type = parts[typeIdx];
|
|
117
123
|
const slug = parts[typeIdx + 1]?.replace(/\.md$/, '');
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
});
|
|
133
|
-
}
|
|
124
|
+
|
|
125
|
+
actions.push({
|
|
126
|
+
slug,
|
|
127
|
+
source: manifestEntry.source || 'unknown',
|
|
128
|
+
type,
|
|
129
|
+
action: 'ORPHAN',
|
|
130
|
+
sourcePath: '',
|
|
131
|
+
targetPath: join(workspaceDir, manifestKey),
|
|
132
|
+
targetFilename: manifestKey,
|
|
133
|
+
isDirectory: false,
|
|
134
|
+
registryHash: '',
|
|
135
|
+
namespacePath: namespace,
|
|
136
|
+
registryPath: '',
|
|
137
|
+
});
|
|
134
138
|
}
|
|
135
139
|
}
|
|
136
140
|
|