@ghl-ai/aw 0.1.38-beta.10 → 0.1.38-beta.12
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/cli.mjs +1 -1
- package/commands/doctor.mjs +21 -19
- package/commands/init.mjs +23 -4
- package/commands/pull.mjs +26 -7
- package/commands/push-rules.mjs +4 -15
- package/commands/telemetry.mjs +3 -59
- package/constants.mjs +1 -1
- package/ecc.mjs +1 -4
- package/hooks/codex-home.mjs +3 -3
- package/hooks/shared-phase-scripts.mjs +0 -17
- package/integrate.mjs +3 -3
- package/package.json +1 -1
- package/render-rules.mjs +6 -4
- package/startup.mjs +1 -1
package/cli.mjs
CHANGED
|
@@ -134,7 +134,7 @@ function printHelp() {
|
|
|
134
134
|
cmd('aw push .aw_registry/agents/<name>.md', 'Push a single agent'),
|
|
135
135
|
cmd('aw push .aw_registry/skills/<name>/', 'Push a single skill folder'),
|
|
136
136
|
cmd('aw push .aw_rules', 'Auto-redirects to aw push-rules'),
|
|
137
|
-
cmd('aw push-rules', 'Pushes .aw_rules
|
|
137
|
+
cmd('aw push-rules', 'Pushes .aw_rules'),
|
|
138
138
|
'',
|
|
139
139
|
` ${chalk.dim('# Remove content from workspace')}`,
|
|
140
140
|
cmd('aw drop <team>', 'Stop syncing a namespace (removes all files)'),
|
package/commands/doctor.mjs
CHANGED
|
@@ -162,10 +162,12 @@ function resolveAwRegistryDir(homeDir) {
|
|
|
162
162
|
}
|
|
163
163
|
|
|
164
164
|
function resolveRulesDir(homeDir) {
|
|
165
|
-
const
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
165
|
+
const candidates = [
|
|
166
|
+
join(homeDir, '.aw_rules'),
|
|
167
|
+
join(homeDir, '.aw_registry', '.aw_rules'),
|
|
168
|
+
join(homeDir, '.aw', '.aw_registry', '.aw_rules'),
|
|
169
|
+
];
|
|
170
|
+
return candidates.find(existsSync) || null;
|
|
169
171
|
}
|
|
170
172
|
|
|
171
173
|
function findClaudePlugin(homeDir) {
|
|
@@ -471,7 +473,7 @@ function getProjectClaudeSessionStartStatus(cwd) {
|
|
|
471
473
|
}
|
|
472
474
|
|
|
473
475
|
function textHasRulesReference(text) {
|
|
474
|
-
return text.includes('Platform Rules') && text.includes('.
|
|
476
|
+
return text.includes('Platform Rules') && text.includes('.aw_rules/platform/');
|
|
475
477
|
}
|
|
476
478
|
|
|
477
479
|
function textHasManagedRouterBridge(text) {
|
|
@@ -484,9 +486,9 @@ function textHasManagedRouterBridge(text) {
|
|
|
484
486
|
&& text.includes('incremental-implementation');
|
|
485
487
|
}
|
|
486
488
|
|
|
487
|
-
function
|
|
489
|
+
function extractRuleReferencePaths(text) {
|
|
488
490
|
const matches = [];
|
|
489
|
-
const pattern = /(?:\]\(|`)([^)\n`]
|
|
491
|
+
const pattern = /(?:\]\(|`)([^)\n`]*(?:\.aw_rules|\.aw_registry\/\.aw_rules)\/[^)\n`]+\.md)(?:\)|`)/g;
|
|
490
492
|
for (const match of text.matchAll(pattern)) {
|
|
491
493
|
if (match[1]) matches.push(match[1]);
|
|
492
494
|
}
|
|
@@ -505,11 +507,11 @@ function listGeneratedRuleFiles(dirPath, extension) {
|
|
|
505
507
|
}
|
|
506
508
|
}
|
|
507
509
|
|
|
508
|
-
function
|
|
510
|
+
function findBrokenRuleReferences(filePaths) {
|
|
509
511
|
const broken = [];
|
|
510
512
|
for (const filePath of filePaths) {
|
|
511
513
|
const content = readText(filePath);
|
|
512
|
-
const refs =
|
|
514
|
+
const refs = extractRuleReferencePaths(content);
|
|
513
515
|
for (const ref of refs) {
|
|
514
516
|
if (ref.includes('<domain>')) continue;
|
|
515
517
|
const resolvedPath = join(dirname(filePath), ref);
|
|
@@ -565,8 +567,8 @@ function buildDoctorChecks(homeDir, cwd) {
|
|
|
565
567
|
'aw-rules-source',
|
|
566
568
|
'AW rules source',
|
|
567
569
|
'fail',
|
|
568
|
-
'No synced .aw_rules tree found under ~/.
|
|
569
|
-
'Run `aw init` or `aw pull platform` to sync the AW rules source into ~/.
|
|
570
|
+
'No synced .aw_rules tree found under ~/.aw_rules',
|
|
571
|
+
'Run `aw init` or `aw pull platform` to sync the AW rules source into ~/.aw_rules.',
|
|
570
572
|
));
|
|
571
573
|
} else {
|
|
572
574
|
const topLevelRulesAgents = join(rulesDir, 'AGENTS.md');
|
|
@@ -578,7 +580,7 @@ function buildDoctorChecks(homeDir, cwd) {
|
|
|
578
580
|
'aw-rules-source',
|
|
579
581
|
'AW rules source',
|
|
580
582
|
'fail',
|
|
581
|
-
'Rules source is incomplete under ~/.
|
|
583
|
+
'Rules source is incomplete under ~/.aw_rules',
|
|
582
584
|
'Run `aw pull platform` to refresh .aw_rules, then rerun `aw doctor`.',
|
|
583
585
|
),
|
|
584
586
|
);
|
|
@@ -784,7 +786,7 @@ function buildDoctorChecks(homeDir, cwd) {
|
|
|
784
786
|
);
|
|
785
787
|
|
|
786
788
|
const claudeRuleFiles = listGeneratedRuleFiles(claudeRulesDir, '.md');
|
|
787
|
-
const brokenClaudeRuleRefs =
|
|
789
|
+
const brokenClaudeRuleRefs = findBrokenRuleReferences(claudeRuleFiles);
|
|
788
790
|
checks.push(
|
|
789
791
|
claudeRuleFiles.length === 0
|
|
790
792
|
? makeCheck(
|
|
@@ -795,13 +797,13 @@ function buildDoctorChecks(homeDir, cwd) {
|
|
|
795
797
|
'Run `aw pull platform` or `aw init` to render Claude rules, then rerun `aw doctor`.',
|
|
796
798
|
)
|
|
797
799
|
: brokenClaudeRuleRefs.length === 0
|
|
798
|
-
? makeCheck('claude-rule-references', 'Claude rule references', 'pass', 'Claude generated rule references resolve to real files in ~/.
|
|
800
|
+
? makeCheck('claude-rule-references', 'Claude rule references', 'pass', 'Claude generated rule references resolve to real files in ~/.aw_rules')
|
|
799
801
|
: makeCheck(
|
|
800
802
|
'claude-rule-references',
|
|
801
803
|
'Claude rule references',
|
|
802
804
|
'fail',
|
|
803
805
|
`Claude rule reference is broken in ${brokenClaudeRuleRefs[0].filePath.replace(`${homeDir}/`, '~/')}: ${brokenClaudeRuleRefs[0].ref}`,
|
|
804
|
-
'Refresh the rendered Claude rules so embedded reference links point at real files under ~/.
|
|
806
|
+
'Refresh the rendered Claude rules so embedded reference links point at real files under ~/.aw_rules.',
|
|
805
807
|
),
|
|
806
808
|
);
|
|
807
809
|
|
|
@@ -894,7 +896,7 @@ function buildDoctorChecks(homeDir, cwd) {
|
|
|
894
896
|
);
|
|
895
897
|
|
|
896
898
|
const codexAgentsText = readText(codexAgentsPath);
|
|
897
|
-
const codexBrokenRuleRefs = existsSync(codexAgentsPath) ?
|
|
899
|
+
const codexBrokenRuleRefs = existsSync(codexAgentsPath) ? findBrokenRuleReferences([codexAgentsPath]) : [];
|
|
898
900
|
checks.push(
|
|
899
901
|
existsSync(codexAgentsPath) && textHasRulesReference(codexAgentsText)
|
|
900
902
|
? codexBrokenRuleRefs.length === 0
|
|
@@ -1004,7 +1006,7 @@ function buildDoctorChecks(homeDir, cwd) {
|
|
|
1004
1006
|
|
|
1005
1007
|
const cursorRulesDir = join(homeDir, '.cursor', 'rules');
|
|
1006
1008
|
const cursorRuleFiles = listGeneratedRuleFiles(cursorRulesDir, '.mdc');
|
|
1007
|
-
const brokenCursorRuleRefs =
|
|
1009
|
+
const brokenCursorRuleRefs = findBrokenRuleReferences(cursorRuleFiles);
|
|
1008
1010
|
checks.push(
|
|
1009
1011
|
cursorRuleFiles.length === 0
|
|
1010
1012
|
? makeCheck(
|
|
@@ -1015,13 +1017,13 @@ function buildDoctorChecks(homeDir, cwd) {
|
|
|
1015
1017
|
'Run `aw pull platform` or `aw init` to render Cursor rules, then rerun `aw doctor`.',
|
|
1016
1018
|
)
|
|
1017
1019
|
: brokenCursorRuleRefs.length === 0
|
|
1018
|
-
? makeCheck('cursor-rule-references', 'Cursor rule references', 'pass', 'Cursor generated rule references resolve to real files in ~/.
|
|
1020
|
+
? makeCheck('cursor-rule-references', 'Cursor rule references', 'pass', 'Cursor generated rule references resolve to real files in ~/.aw_rules')
|
|
1019
1021
|
: makeCheck(
|
|
1020
1022
|
'cursor-rule-references',
|
|
1021
1023
|
'Cursor rule references',
|
|
1022
1024
|
'fail',
|
|
1023
1025
|
`Cursor rule reference is broken in ${brokenCursorRuleRefs[0].filePath.replace(`${homeDir}/`, '~/')}: ${brokenCursorRuleRefs[0].ref}`,
|
|
1024
|
-
'Refresh the rendered Cursor rules so embedded reference links point at real files under ~/.
|
|
1026
|
+
'Refresh the rendered Cursor rules so embedded reference links point at real files under ~/.aw_rules.',
|
|
1025
1027
|
),
|
|
1026
1028
|
);
|
|
1027
1029
|
|
package/commands/init.mjs
CHANGED
|
@@ -59,6 +59,21 @@ const HOME = (() => { try { return realpathSync(_rawHome); } catch { return _raw
|
|
|
59
59
|
const GLOBAL_AW_DIR = join(HOME, '.aw_registry');
|
|
60
60
|
const AW_HOME = join(HOME, '.aw');
|
|
61
61
|
|
|
62
|
+
function syncRulesTargets(targetDir) {
|
|
63
|
+
const rulesSrc = join(AW_HOME, RULES_SOURCE_DIR);
|
|
64
|
+
if (!existsSync(rulesSrc)) return false;
|
|
65
|
+
syncFileTree(rulesSrc, join(targetDir, RULES_SOURCE_DIR));
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function removeLegacyRegistryRules() {
|
|
70
|
+
try {
|
|
71
|
+
rmSync(join(GLOBAL_AW_DIR, RULES_SOURCE_DIR), { recursive: true, force: true });
|
|
72
|
+
} catch {
|
|
73
|
+
// best effort cleanup
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
62
77
|
function syncInstructionsAndAwDocs(targetDir, namespace) {
|
|
63
78
|
copyInstructions(targetDir, null, namespace);
|
|
64
79
|
initAwDocs(targetDir);
|
|
@@ -262,9 +277,11 @@ export async function initCommand(args) {
|
|
|
262
277
|
|
|
263
278
|
ensureAwGitignore(AW_HOME);
|
|
264
279
|
const freshCfg = config.load(GLOBAL_AW_DIR);
|
|
265
|
-
|
|
266
|
-
|
|
280
|
+
syncRulesTargets(HOME);
|
|
281
|
+
if (cwd !== HOME) {
|
|
282
|
+
syncRulesTargets(cwd);
|
|
267
283
|
}
|
|
284
|
+
removeLegacyRegistryRules();
|
|
268
285
|
|
|
269
286
|
// Ensure project worktree sparse checkout matches the global clone.
|
|
270
287
|
// Covers the case where a namespace was added from HOME (or another project)
|
|
@@ -404,9 +421,11 @@ export async function initCommand(args) {
|
|
|
404
421
|
if (folderName) {
|
|
405
422
|
config.addPattern(GLOBAL_AW_DIR, folderName);
|
|
406
423
|
}
|
|
407
|
-
|
|
408
|
-
|
|
424
|
+
syncRulesTargets(HOME);
|
|
425
|
+
if (cwd !== HOME) {
|
|
426
|
+
syncRulesTargets(cwd);
|
|
409
427
|
}
|
|
428
|
+
removeLegacyRegistryRules();
|
|
410
429
|
|
|
411
430
|
// Step 3: Setup tasks, MCP, hooks
|
|
412
431
|
await installAwEcc(cwd, { silent });
|
package/commands/pull.mjs
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import {
|
|
4
4
|
existsSync,
|
|
5
5
|
lstatSync,
|
|
6
|
+
rmSync,
|
|
6
7
|
} from 'node:fs';
|
|
7
8
|
import { dirname, join, extname } from 'node:path';
|
|
8
9
|
import { homedir } from 'node:os';
|
|
@@ -38,6 +39,21 @@ const HOME = homedir();
|
|
|
38
39
|
const AW_HOME = join(HOME, '.aw');
|
|
39
40
|
const GLOBAL_AW_DIR = join(HOME, '.aw_registry');
|
|
40
41
|
|
|
42
|
+
function syncRulesTargets(targetDir) {
|
|
43
|
+
const rulesSrc = join(AW_HOME, RULES_SOURCE_DIR);
|
|
44
|
+
if (!existsSync(rulesSrc)) return false;
|
|
45
|
+
syncFileTree(rulesSrc, join(targetDir, RULES_SOURCE_DIR));
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function removeLegacyRegistryRules() {
|
|
50
|
+
try {
|
|
51
|
+
rmSync(join(GLOBAL_AW_DIR, RULES_SOURCE_DIR), { recursive: true, force: true });
|
|
52
|
+
} catch {
|
|
53
|
+
// best effort cleanup
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
41
57
|
export async function pullCommand(args) {
|
|
42
58
|
const input = args._positional?.[0] || '';
|
|
43
59
|
const cwd = process.cwd();
|
|
@@ -179,13 +195,6 @@ export async function pullCommand(args) {
|
|
|
179
195
|
log.logWarn(`Conflicts in: ${fetchResult.conflicts.join(', ')}`);
|
|
180
196
|
}
|
|
181
197
|
|
|
182
|
-
const rulesSrc = join(AW_HOME, RULES_SOURCE_DIR);
|
|
183
|
-
if (existsSync(rulesSrc)) {
|
|
184
|
-
const rulesDest = join(GLOBAL_AW_DIR, RULES_SOURCE_DIR);
|
|
185
|
-
syncFileTree(rulesSrc, rulesDest);
|
|
186
|
-
if (!silent) log.logSuccess('Synced .aw_rules');
|
|
187
|
-
}
|
|
188
|
-
|
|
189
198
|
// Rebase project worktree branch onto origin/main — only for legacy git worktrees.
|
|
190
199
|
// In the symlink model, <project>/.aw IS ~/.aw (same repo), so fetchAndMerge already
|
|
191
200
|
// brought it up to date. Nothing to rebase.
|
|
@@ -244,6 +253,16 @@ export async function pullCommand(args) {
|
|
|
244
253
|
}
|
|
245
254
|
}
|
|
246
255
|
|
|
256
|
+
let rulesSynced = syncRulesTargets(HOME);
|
|
257
|
+
const workspaceRoot = localAw ? dirname(localAw) : (cwd !== HOME ? cwd : null);
|
|
258
|
+
if (workspaceRoot && workspaceRoot !== HOME) {
|
|
259
|
+
rulesSynced = syncRulesTargets(workspaceRoot) || rulesSynced;
|
|
260
|
+
}
|
|
261
|
+
removeLegacyRegistryRules();
|
|
262
|
+
if (rulesSynced && !silent) {
|
|
263
|
+
log.logSuccess('Synced .aw_rules');
|
|
264
|
+
}
|
|
265
|
+
|
|
247
266
|
if (!args._skipIntegrate) {
|
|
248
267
|
const projectRegistryDir = cwd !== HOME ? join(cwd, '.aw', REGISTRY_DIR) : null;
|
|
249
268
|
const awDirForLinks = (projectRegistryDir && existsSync(projectRegistryDir)) ? projectRegistryDir : null;
|
package/commands/push-rules.mjs
CHANGED
|
@@ -23,11 +23,9 @@ export function isRulesPushInput(input) {
|
|
|
23
23
|
|
|
24
24
|
export function resolveRulesPushSource(input, cwd = process.cwd()) {
|
|
25
25
|
const localRulesRoot = join(cwd, RULES_SOURCE_DIR);
|
|
26
|
-
const syncedRulesRoot = join(cwd, '.aw_registry', RULES_SOURCE_DIR);
|
|
27
26
|
|
|
28
27
|
if (!input) {
|
|
29
28
|
if (existsSync(localRulesRoot)) return { sourceRoot: localRulesRoot, sourceType: 'local' };
|
|
30
|
-
if (existsSync(syncedRulesRoot)) return { sourceRoot: syncedRulesRoot, sourceType: 'synced' };
|
|
31
29
|
return null;
|
|
32
30
|
}
|
|
33
31
|
|
|
@@ -39,22 +37,19 @@ export function resolveRulesPushSource(input, cwd = process.cwd()) {
|
|
|
39
37
|
}
|
|
40
38
|
|
|
41
39
|
if (normalizedInput === `.aw_registry/${RULES_SOURCE_DIR}` || normalizedInput.startsWith(`.aw_registry/${RULES_SOURCE_DIR}/`)) {
|
|
42
|
-
if (!existsSync(syncedRulesRoot)) return null;
|
|
43
|
-
|
|
44
40
|
const relativeRulesPath = normalizedInput.slice(`.aw_registry/${RULES_SOURCE_DIR}`.length).replace(/^\/+/, '');
|
|
45
41
|
const localOverridePath = relativeRulesPath ? join(localRulesRoot, relativeRulesPath) : localRulesRoot;
|
|
46
42
|
if (existsSync(localOverridePath)) {
|
|
47
43
|
return { sourceRoot: localRulesRoot, sourceType: 'local' };
|
|
48
44
|
}
|
|
49
|
-
|
|
50
|
-
return { sourceRoot: syncedRulesRoot, sourceType: 'synced' };
|
|
45
|
+
return null;
|
|
51
46
|
}
|
|
52
47
|
|
|
53
48
|
return null;
|
|
54
49
|
}
|
|
55
50
|
|
|
56
51
|
export function hasRulesChanges(cwd = process.cwd()) {
|
|
57
|
-
const candidateDirs = [RULES_SOURCE_DIR
|
|
52
|
+
const candidateDirs = [RULES_SOURCE_DIR]
|
|
58
53
|
.filter(rel => existsSync(join(cwd, rel)));
|
|
59
54
|
|
|
60
55
|
if (candidateDirs.length === 0) return false;
|
|
@@ -141,9 +136,7 @@ function pushRulesTree(sourceRoot, { repo, dryRun, cwd }) {
|
|
|
141
136
|
fmt.cancel('Nothing to push — remote rules already match local content.');
|
|
142
137
|
}
|
|
143
138
|
|
|
144
|
-
const sourceType =
|
|
145
|
-
? 'synced'
|
|
146
|
-
: 'local';
|
|
139
|
+
const sourceType = 'local';
|
|
147
140
|
const prTitle = buildRulesPrTitle(sourceRoot, cwd);
|
|
148
141
|
const prBody = buildRulesPrBody(sourceRoot, sourceType, cwd);
|
|
149
142
|
|
|
@@ -191,16 +184,12 @@ export function pushRulesCommand(args) {
|
|
|
191
184
|
fmt.cancel([
|
|
192
185
|
'Could not find a rules source to push.',
|
|
193
186
|
'',
|
|
194
|
-
` Checked ${chalk.cyan('.aw_rules/')}
|
|
187
|
+
` Checked ${chalk.cyan('.aw_rules/')}.`,
|
|
195
188
|
'',
|
|
196
189
|
' Use `aw pull platform` first or create a local `.aw_rules/` authoring tree.',
|
|
197
190
|
].join('\n'));
|
|
198
191
|
}
|
|
199
192
|
|
|
200
|
-
if (resolved.sourceType === 'synced') {
|
|
201
|
-
fmt.logWarn('Pushing from synced `.aw_registry/.aw_rules/`. Local `.aw_rules/` is safer for authoring.');
|
|
202
|
-
}
|
|
203
|
-
|
|
204
193
|
pushRulesTree(resolved.sourceRoot, { repo, dryRun, cwd });
|
|
205
194
|
}
|
|
206
195
|
|
package/commands/telemetry.mjs
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
// commands/telemetry.mjs — `aw telemetry [enable|disable|status
|
|
1
|
+
// commands/telemetry.mjs — `aw telemetry [enable|disable|status]`
|
|
2
2
|
|
|
3
|
-
import { existsSync, readFileSync } from 'node:fs';
|
|
4
|
-
import { join } from 'node:path';
|
|
5
|
-
import { homedir } from 'node:os';
|
|
6
3
|
import { enableTelemetry, disableTelemetry, getStatus } from '../telemetry.mjs';
|
|
7
4
|
import * as fmt from '../fmt.mjs';
|
|
8
5
|
import { chalk } from '../fmt.mjs';
|
|
@@ -22,66 +19,13 @@ export async function telemetryCommand(args) {
|
|
|
22
19
|
return;
|
|
23
20
|
}
|
|
24
21
|
|
|
25
|
-
if (sub === 'flush-queue') {
|
|
26
|
-
await flushQueueCommand();
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
22
|
// status (default)
|
|
31
23
|
const status = getStatus();
|
|
32
24
|
fmt.intro('aw telemetry');
|
|
33
25
|
fmt.logStep(`Status: ${status.enabled ? chalk.green('enabled') : chalk.red('disabled')}`);
|
|
34
26
|
fmt.logStep(`Machine ID: ${chalk.dim(status.machine_id)}`);
|
|
35
27
|
fmt.logStep(`Config: ${chalk.dim(status.config_path)}`);
|
|
36
|
-
|
|
37
|
-
// Show queue depth if available
|
|
38
|
-
const queueFile = join(homedir(), '.aw', 'telemetry', 'queue.jsonl');
|
|
39
|
-
if (existsSync(queueFile)) {
|
|
40
|
-
try {
|
|
41
|
-
const lines = readFileSync(queueFile, 'utf8').trim().split('\n').filter(Boolean);
|
|
42
|
-
fmt.logStep(`Queue: ${chalk.yellow(lines.length)} pending prompt(s)`);
|
|
43
|
-
} catch { /* best effort */ }
|
|
44
|
-
}
|
|
45
|
-
|
|
46
28
|
fmt.logMessage('');
|
|
47
|
-
fmt.logMessage(` ${chalk.dim('aw telemetry disable')}
|
|
48
|
-
fmt.logMessage(` ${chalk.dim('aw telemetry enable')}
|
|
49
|
-
fmt.logMessage(` ${chalk.dim('aw telemetry flush-queue')} — manually flush pending queue`);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
async function flushQueueCommand() {
|
|
53
|
-
const eccBase = join(homedir(), '.aw-ecc');
|
|
54
|
-
const libPath = join(eccBase, 'scripts', 'hooks', 'capabilities', 'telemetry', 'telemetry-lib.js');
|
|
55
|
-
|
|
56
|
-
if (!existsSync(libPath)) {
|
|
57
|
-
fmt.logWarn('Telemetry library not found. Run aw init first.');
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const {
|
|
62
|
-
readQueue,
|
|
63
|
-
flushQueueToApi,
|
|
64
|
-
getNamespace,
|
|
65
|
-
buildTelemetryHeaders,
|
|
66
|
-
} = await import(libPath);
|
|
67
|
-
|
|
68
|
-
const entries = readQueue();
|
|
69
|
-
if (entries.length === 0) {
|
|
70
|
-
fmt.logSuccess('Queue is empty — nothing to flush.');
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
fmt.logStep(`Flushing ${entries.length} pending prompt(s)...`);
|
|
75
|
-
|
|
76
|
-
const namespace = getNamespace();
|
|
77
|
-
const headers = buildTelemetryHeaders(namespace);
|
|
78
|
-
const result = await flushQueueToApi(headers);
|
|
79
|
-
|
|
80
|
-
if (result.flushed > 0) {
|
|
81
|
-
fmt.logSuccess(`Flushed ${result.flushed} prompt(s) to API.`);
|
|
82
|
-
} else if (result.failed) {
|
|
83
|
-
fmt.logWarn('Flush failed — entries remain in queue for retry.');
|
|
84
|
-
} else {
|
|
85
|
-
fmt.logSuccess('Nothing to flush.');
|
|
86
|
-
}
|
|
29
|
+
fmt.logMessage(` ${chalk.dim('aw telemetry disable')} — opt out of anonymous analytics`);
|
|
30
|
+
fmt.logMessage(` ${chalk.dim('aw telemetry enable')} — re-enable analytics`);
|
|
87
31
|
}
|
package/constants.mjs
CHANGED
|
@@ -25,7 +25,7 @@ export const DOCS_SOURCE_DIR = 'content';
|
|
|
25
25
|
/** Persistent git clone root — ~/.aw/ */
|
|
26
26
|
export const AW_HOME = join(homedir(), '.aw');
|
|
27
27
|
|
|
28
|
-
/** Directory in platform-docs repo containing platform rules (
|
|
28
|
+
/** Directory in platform-docs repo containing platform rules (synced into root-level .aw_rules/) */
|
|
29
29
|
export const RULES_SOURCE_DIR = '.aw_rules';
|
|
30
30
|
/** Telemetry endpoint — override with AW_TELEMETRY_URL env var */
|
|
31
31
|
export const TELEMETRY_URL = process.env.AW_TELEMETRY_URL || 'https://services.leadconnectorhq.com/agentic-workspace/api/telemetry/events';
|
package/ecc.mjs
CHANGED
|
@@ -10,7 +10,7 @@ import { applyStoredStartupPreferences } from "./startup.mjs";
|
|
|
10
10
|
|
|
11
11
|
const AW_ECC_REPO_SSH = "git@github.com:shreyansh-ghl/aw-ecc.git";
|
|
12
12
|
const AW_ECC_REPO_HTTPS = "https://github.com/shreyansh-ghl/aw-ecc.git";
|
|
13
|
-
export const AW_ECC_TAG = "v1.
|
|
13
|
+
export const AW_ECC_TAG = "v1.4.23";
|
|
14
14
|
|
|
15
15
|
const MARKETPLACE_NAME = "aw-marketplace";
|
|
16
16
|
const PLUGIN_KEY = `aw@${MARKETPLACE_NAME}`;
|
|
@@ -241,9 +241,6 @@ export async function installAwEcc(
|
|
|
241
241
|
try {
|
|
242
242
|
cloneOrUpdate(AW_ECC_TAG, repoDir);
|
|
243
243
|
|
|
244
|
-
// Ensure telemetry state directory exists (vendor-agnostic, shared across IDEs)
|
|
245
|
-
mkdirSync(join(home, ".aw", "telemetry"), { recursive: true });
|
|
246
|
-
|
|
247
244
|
// Claude Code: plugin install via marketplace CLI (proper agent dispatch)
|
|
248
245
|
if (targets.includes("claude")) {
|
|
249
246
|
try {
|
package/hooks/codex-home.mjs
CHANGED
|
@@ -3,7 +3,6 @@ import { join } from 'node:path';
|
|
|
3
3
|
import { getSupportedHarnessPhaseEntries } from '../hook-manifest.mjs';
|
|
4
4
|
import {
|
|
5
5
|
buildDelegatingPhaseScript,
|
|
6
|
-
buildNodeSilentPhaseScript,
|
|
7
6
|
buildRegistryDelegatingPhaseScript,
|
|
8
7
|
buildReservedPhaseScript,
|
|
9
8
|
} from './shared-phase-scripts.mjs';
|
|
@@ -111,9 +110,10 @@ const CODEX_HOME_PHASE_BLUEPRINTS = {
|
|
|
111
110
|
scriptName: 'aw-stop.sh',
|
|
112
111
|
scriptMarker: '# aw-managed: codex-global-stop',
|
|
113
112
|
buildScriptContent() {
|
|
114
|
-
return
|
|
113
|
+
return buildReservedPhaseScript({
|
|
115
114
|
marker: this.scriptMarker,
|
|
116
|
-
|
|
115
|
+
phase: 'Stop',
|
|
116
|
+
harnessLabel: 'Codex home routing',
|
|
117
117
|
});
|
|
118
118
|
},
|
|
119
119
|
buildEntry(command) {
|
|
@@ -54,23 +54,6 @@ exit 0
|
|
|
54
54
|
`;
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
export function buildNodeSilentPhaseScript({
|
|
58
|
-
marker,
|
|
59
|
-
targetPath,
|
|
60
|
-
}) {
|
|
61
|
-
return `#!/usr/bin/env bash
|
|
62
|
-
${marker}
|
|
63
|
-
set -euo pipefail
|
|
64
|
-
|
|
65
|
-
TARGET="${targetPath}"
|
|
66
|
-
if [[ -f "$TARGET" ]]; then
|
|
67
|
-
node "$TARGET" > /dev/null
|
|
68
|
-
fi
|
|
69
|
-
|
|
70
|
-
exit 0
|
|
71
|
-
`;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
57
|
export function buildReservedPhaseScript({
|
|
75
58
|
marker,
|
|
76
59
|
phase,
|
package/integrate.mjs
CHANGED
|
@@ -29,7 +29,7 @@ function generateAwRouterBridgeSection() {
|
|
|
29
29
|
- Do not assume the previous skill stack is still active
|
|
30
30
|
|
|
31
31
|
### 2. Read Rules Before Acting (MANDATORY)
|
|
32
|
-
- Read applicable AW rules from \`~/.
|
|
32
|
+
- Read applicable AW rules from \`~/.aw_rules/platform/<domain>/AGENTS.md\`
|
|
33
33
|
- Also read \`universal\` and \`security\` rules whenever they apply
|
|
34
34
|
- If repo-local instructions conflict with org-level sources of truth, follow org-level sources
|
|
35
35
|
|
|
@@ -260,12 +260,12 @@ export function syncHomeHarnessInstructions(homeDir = homedir()) {
|
|
|
260
260
|
const codexRulesSection = rulesDir
|
|
261
261
|
? generateAgentsMdRulesSection(rulesDir, {
|
|
262
262
|
outputDir: join(homeDir, '.codex'),
|
|
263
|
-
})
|
|
263
|
+
})
|
|
264
264
|
: '';
|
|
265
265
|
const cursorRulesSection = rulesDir
|
|
266
266
|
? generateAgentsMdRulesSection(rulesDir, {
|
|
267
267
|
outputDir: join(homeDir, '.cursor'),
|
|
268
|
-
})
|
|
268
|
+
})
|
|
269
269
|
: '';
|
|
270
270
|
const claudeRulesSection = rulesDir ? generateClaudeMdRulesSection(rulesDir) : '';
|
|
271
271
|
|
package/package.json
CHANGED
package/render-rules.mjs
CHANGED
|
@@ -171,12 +171,14 @@ function relativeRuleLink(outputDir, targetPath) {
|
|
|
171
171
|
export function resolveRulesSourceDir(cwd, options = {}) {
|
|
172
172
|
const HOME = options.homeDir || homedir();
|
|
173
173
|
const candidates = [
|
|
174
|
+
join(cwd, RULES_SOURCE_DIR),
|
|
174
175
|
join(cwd, '.aw_registry', RULES_SOURCE_DIR),
|
|
175
176
|
join(cwd, '.aw', '.aw_registry', RULES_SOURCE_DIR),
|
|
176
177
|
];
|
|
177
178
|
|
|
178
179
|
if (cwd !== HOME) {
|
|
179
180
|
candidates.push(
|
|
181
|
+
join(HOME, RULES_SOURCE_DIR),
|
|
180
182
|
join(HOME, '.aw_registry', RULES_SOURCE_DIR),
|
|
181
183
|
join(HOME, '.aw', '.aw_registry', RULES_SOURCE_DIR),
|
|
182
184
|
);
|
|
@@ -410,7 +412,7 @@ export function generateClaudeMdRulesSection(rulesDir) {
|
|
|
410
412
|
const lines = [
|
|
411
413
|
'## Platform Rules (MUST)',
|
|
412
414
|
'',
|
|
413
|
-
'>
|
|
415
|
+
'> Rendered from platform `.aw_rules/`. Full details in reference files.',
|
|
414
416
|
'',
|
|
415
417
|
];
|
|
416
418
|
|
|
@@ -419,7 +421,7 @@ export function generateClaudeMdRulesSection(rulesDir) {
|
|
|
419
421
|
}
|
|
420
422
|
|
|
421
423
|
lines.push('');
|
|
422
|
-
lines.push('See `.
|
|
424
|
+
lines.push('See `.aw_rules/rule-manifest.json` for all rules including SHOULD/MAY.');
|
|
423
425
|
lines.push('');
|
|
424
426
|
|
|
425
427
|
return lines.join('\n');
|
|
@@ -436,7 +438,7 @@ export function generateAgentsMdRulesSection(rulesDir, options = {}) {
|
|
|
436
438
|
const lines = [
|
|
437
439
|
'## Platform Rules — Non-Negotiables',
|
|
438
440
|
'',
|
|
439
|
-
'>
|
|
441
|
+
'> Rendered from platform `.aw_rules/`.',
|
|
440
442
|
'',
|
|
441
443
|
topLevelAgents.trim(),
|
|
442
444
|
'',
|
|
@@ -487,7 +489,7 @@ export function generateAgentsMdRulesSection(rulesDir, options = {}) {
|
|
|
487
489
|
|
|
488
490
|
/**
|
|
489
491
|
* Main render function. Call after aw pull / aw sync.
|
|
490
|
-
* Reads .
|
|
492
|
+
* Reads root .aw_rules/ and renders:
|
|
491
493
|
* 1. .cursor/rules/<scope>.mdc — at cwd AND at $HOME (global)
|
|
492
494
|
* 2. Returns sections for CLAUDE.md and AGENTS.md injection
|
|
493
495
|
*/
|
package/startup.mjs
CHANGED
|
@@ -154,7 +154,7 @@ function isLegacyCodexSessionStartEntry(entry) {
|
|
|
154
154
|
const command = String(hook?.command || '');
|
|
155
155
|
return (
|
|
156
156
|
command.includes('.aw_registry/platform/core/skills/using-aw-skills/hooks/session-start.sh')
|
|
157
|
-
|| (command.includes('.codex/hooks/aw-session-start.sh') && entry?.matcher !==
|
|
157
|
+
|| (command.includes('.codex/hooks/aw-session-start.sh') && entry?.matcher !== CODEX_HOOK_MATCHER)
|
|
158
158
|
);
|
|
159
159
|
});
|
|
160
160
|
}
|