@ghl-ai/aw 0.1.41-beta.1 → 0.1.41-beta.3

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/init.mjs CHANGED
@@ -13,6 +13,7 @@ import {
13
13
  readFileSync,
14
14
  rmSync,
15
15
  realpathSync,
16
+ appendFileSync,
16
17
  } from 'node:fs';
17
18
  import { execSync } from 'node:child_process';
18
19
  import { join, dirname, sep } from 'node:path';
@@ -87,65 +88,24 @@ function syncHomeAndProjectInstructions(cwd, namespace) {
87
88
  }
88
89
  }
89
90
 
90
- // ── Ensure ~/.aw/.git/info/exclude has the whitelist block ─────────────
91
- //
92
- // Strategy: only .aw_registry/, .aw_rules/, content/ are tracked — everything
93
- // else at the top level of ~/.aw/ is local-only (telemetry/, hooks/, logs,
94
- // .DS_Store, etc.). We write to .git/info/exclude (not tracked .gitignore)
95
- // so upstream pulls never conflict.
96
-
97
- const AW_MANAGED_BEGIN = '# BEGIN aw-managed (do not edit; managed by `aw init`)';
98
- const AW_MANAGED_END = '# END aw-managed';
99
-
100
- const AW_MANAGED_BLOCK = [
101
- AW_MANAGED_BEGIN,
102
- '# Whitelist: only these top-level entries are tracked; everything else is local-only.',
103
- '/*',
104
- '!/.aw_registry',
105
- '!/.aw_rules',
106
- '!/content',
107
- '',
108
- '# Nested local state within whitelisted dirs',
109
- '/.aw_registry/.sync-config.json',
110
- AW_MANAGED_END,
111
- '',
112
- ].join('\n');
113
-
114
- // Legacy flat lines appended by earlier versions of ensureAwGitignore — strip on upgrade
115
- // so we don't leave stale rules lingering outside the managed block.
116
- const LEGACY_GITIGNORE_LINES = new Set([
91
+ // ── Ensure ~/.aw/.gitignore has personal/local entries ───────────────────
92
+
93
+ const AW_GITIGNORE_ENTRIES = [
117
94
  '.aw_registry/.sync-config.json',
118
95
  'hooks/',
119
- '# aw: personal/local — do not commit',
120
- ]);
121
-
122
- function escapeRegex(s) {
123
- return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
124
- }
96
+ ];
125
97
 
126
- export function ensureAwGitignore(awHome) {
98
+ function ensureAwGitignore(awHome) {
99
+ // Use .git/info/exclude so the tracked .gitignore stays clean
127
100
  const excludePath = join(awHome, '.git', 'info', 'exclude');
128
101
  let existing = '';
129
- try { existing = readFileSync(excludePath, 'utf8'); } catch (err) { void err; /* doesn't exist yet */ }
130
-
131
- // Strip any prior aw-managed block so re-rendering is idempotent.
132
- const blockRegex = new RegExp(
133
- `${escapeRegex(AW_MANAGED_BEGIN)}[\\s\\S]*?${escapeRegex(AW_MANAGED_END)}\\n?`,
134
- 'g'
135
- );
136
- const withoutManaged = existing.replace(blockRegex, '');
137
-
138
- // Strip legacy flat lines (pre-whitelist implementation).
139
- const cleaned = withoutManaged
140
- .split('\n')
141
- .filter(line => !LEGACY_GITIGNORE_LINES.has(line.trim()))
142
- .join('\n');
143
-
144
- const prefix = cleaned === '' || cleaned.endsWith('\n') ? cleaned : cleaned + '\n';
145
- const next = prefix + AW_MANAGED_BLOCK;
146
-
147
- if (next === existing) return; // already up to date
148
- try { writeFileSync(excludePath, next); } catch (err) { void err; /* best effort */ }
102
+ try { existing = readFileSync(excludePath, 'utf8'); } catch { /* doesn't exist yet */ }
103
+ const missing = AW_GITIGNORE_ENTRIES.filter(e => !existing.includes(e));
104
+ if (missing.length === 0) return;
105
+ const block = (existing.endsWith('\n') || existing === '' ? '' : '\n')
106
+ + '# aw: personal/local — do not commit\n'
107
+ + missing.join('\n') + '\n';
108
+ try { appendFileSync(excludePath, block); } catch { /* best effort */ }
149
109
  }
150
110
 
151
111
  // ── IDE tasks for auto-pull ─────────────────────────────────────────────
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.4.37";
13
+ export const AW_ECC_TAG = "v1.4.39-beta.2";
14
14
 
15
15
  const MARKETPLACE_NAME = "aw-marketplace";
16
16
  const PLUGIN_KEY = `aw@${MARKETPLACE_NAME}`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ghl-ai/aw",
3
- "version": "0.1.41-beta.1",
3
+ "version": "0.1.41-beta.3",
4
4
  "description": "Agentic Workspace CLI — pull, push & manage agents, skills and commands from the registry",
5
5
  "type": "module",
6
6
  "bin": {
package/render-rules.mjs CHANGED
@@ -351,6 +351,7 @@ For every non-trivial request, execute these steps in order before any substanti
351
351
  - /aw-review → Read aw-review/SKILL.md
352
352
  - /aw-deploy → Read aw-deploy/SKILL.md
353
353
  - /aw-ship → Read aw-ship/SKILL.md
354
+ - /aw-feature → Read aw-feature/SKILL.md
354
355
 
355
356
  4. **Follow the skill's behavior** — produce the artifacts the skill defines, not general-knowledge answers.
356
357
 
package/telemetry.mjs CHANGED
@@ -7,7 +7,7 @@
7
7
 
8
8
  import { createHash, randomUUID } from 'node:crypto';
9
9
  import { hostname, userInfo, platform, arch, release } from 'node:os';
10
- import { readFileSync, writeFileSync, mkdirSync, existsSync, readdirSync, lstatSync, unlinkSync } from 'node:fs';
10
+ import { readFileSync, writeFileSync, mkdirSync, existsSync, readdirSync } from 'node:fs';
11
11
  import { join, dirname } from 'node:path';
12
12
  import { fileURLToPath } from 'node:url';
13
13
  import { execSync } from 'node:child_process';
@@ -16,9 +16,7 @@ import { TELEMETRY_URL, AW_HOME } from './constants.mjs';
16
16
  const __dirname = dirname(fileURLToPath(import.meta.url));
17
17
  const VERSION = JSON.parse(readFileSync(join(__dirname, 'package.json'), 'utf8')).version;
18
18
 
19
- const CONFIG_DIR = join(AW_HOME, 'telemetry');
20
- const CONFIG_PATH = join(CONFIG_DIR, 'config.json');
21
- const LEGACY_CONFIG_PATH = join(AW_HOME, '.telemetry');
19
+ const CONFIG_PATH = join(AW_HOME, '.telemetry');
22
20
 
23
21
  // ── Config ──────────────────────────────────────────────────────────
24
22
 
@@ -32,15 +30,7 @@ export function loadConfig() {
32
30
  if (existsSync(CONFIG_PATH)) {
33
31
  return JSON.parse(readFileSync(CONFIG_PATH, 'utf8'));
34
32
  }
35
- // One-time migration from legacy single-file shape (~/.aw/.telemetry).
36
- // Only triggered when new path is missing, so re-running is a no-op.
37
- if (existsSync(LEGACY_CONFIG_PATH) && lstatSync(LEGACY_CONFIG_PATH).isFile()) {
38
- const legacy = JSON.parse(readFileSync(LEGACY_CONFIG_PATH, 'utf8'));
39
- saveConfig(legacy);
40
- try { unlinkSync(LEGACY_CONFIG_PATH); } catch (err) { void err; /* best-effort cleanup */ }
41
- return legacy;
42
- }
43
- } catch (err) { void err; /* corrupt file — fall through to fresh config */ }
33
+ } catch { /* corrupt file recreate */ }
44
34
 
45
35
  const config = {
46
36
  machine_id: generateMachineId(),