@pugi/cli 0.1.0-alpha.17 → 0.1.0-alpha.19

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.
@@ -24,6 +24,7 @@ import { ReplSession, } from '../core/repl/session.js';
24
24
  import { resolveWorkspaceContext } from '../core/repl/workspace-context.js';
25
25
  import { SqliteSessionStore } from '../core/repl/store/index.js';
26
26
  import { slugForCwd } from '../core/repl/history.js';
27
+ import { WorkingSet, buildRepoSkeleton, loadPugiIgnore, PugiWatcher, } from '../core/context/index.js';
27
28
  /**
28
29
  * Mount the REPL and resolve when the user exits via Ctrl+C × 2 or
29
30
  * `/quit`. The session is closed (server-side stays alive; resume via
@@ -48,6 +49,14 @@ export async function renderRepl(options) {
48
49
  workspaceRoot: process.cwd(),
49
50
  resumeLocalSessionId: options.resumeLocalSessionId,
50
51
  });
52
+ // α6.5 three-tier context bootstrap. The skeleton + working set
53
+ // + watcher are local-first and best-effort: every step is wrapped
54
+ // in try/catch so an unreadable workspace never blocks REPL launch.
55
+ // Opt-out via PUGI_DISABLE_CONTEXT=1 for hermetic test runs.
56
+ const { skeleton, workingSet, watcher } = await bootstrapContext({
57
+ cwd: process.cwd(),
58
+ env: process.env,
59
+ });
51
60
  const session = new ReplSession({
52
61
  apiUrl: options.apiUrl,
53
62
  apiKey: options.apiKey,
@@ -57,6 +66,9 @@ export async function renderRepl(options) {
57
66
  workspace,
58
67
  store,
59
68
  localSessionId: openedSessionId,
69
+ repoSkeleton: skeleton,
70
+ workingSet,
71
+ watcher,
60
72
  });
61
73
  // Restore the transcript from the JSONL log if we resumed an
62
74
  // existing session. The restore is idempotent and bypasses persist
@@ -103,6 +115,14 @@ export async function renderRepl(options) {
103
115
  /* idempotent — already closed */
104
116
  }
105
117
  }
118
+ if (watcher) {
119
+ try {
120
+ await watcher.close();
121
+ }
122
+ catch {
123
+ /* idempotent — chokidar may already be torn down */
124
+ }
125
+ }
106
126
  }
107
127
  }
108
128
  /**
@@ -141,6 +161,58 @@ async function openLocalStore(input) {
141
161
  return { store: null, openedSessionId: undefined };
142
162
  }
143
163
  }
164
+ /**
165
+ * Bootstrap the α6.5 three-tier context primitives:
166
+ *
167
+ * - Tier 0: `RepoSkeleton` (~5KB ASCII tree + meta) for prompt injection.
168
+ * - Tier 1: `WorkingSet` LRU bounded at 50 entries.
169
+ * - Filewatch: chokidar started against cwd, ignore-filtered.
170
+ *
171
+ * The bootstrap is fail-safe: every primitive is wrapped so the REPL
172
+ * still launches when (e.g.) chokidar refuses to start on a
173
+ * permission-blocked dir. The PUGI_DISABLE_CONTEXT=1 env var skips
174
+ * the bootstrap entirely for hermetic test runs and for operators
175
+ * who want a zero-touch REPL.
176
+ */
177
+ async function bootstrapContext(input) {
178
+ if (input.env.PUGI_DISABLE_CONTEXT === '1') {
179
+ return { skeleton: null, workingSet: null, watcher: null };
180
+ }
181
+ let ignore;
182
+ try {
183
+ ignore = loadPugiIgnore(input.cwd);
184
+ }
185
+ catch (error) {
186
+ const msg = error instanceof Error ? error.message : String(error);
187
+ process.stderr.write(`[pugi] Three-tier context bootstrap skipped (ignore matcher failed: ${msg}).\n`);
188
+ return { skeleton: null, workingSet: null, watcher: null };
189
+ }
190
+ let skeleton = null;
191
+ try {
192
+ skeleton = buildRepoSkeleton(input.cwd, { ignore });
193
+ }
194
+ catch (error) {
195
+ const msg = error instanceof Error ? error.message : String(error);
196
+ process.stderr.write(`[pugi] Repo skeleton bootstrap failed (${msg}). Continuing without Tier 0.\n`);
197
+ }
198
+ const workingSet = new WorkingSet();
199
+ let watcher = null;
200
+ // chokidar opt-out: PUGI_DISABLE_FILEWATCH=1 keeps Tier 0/1 wired
201
+ // but skips the live-update channel. Useful on CI runners and on
202
+ // network mounts where fsevents misbehaves.
203
+ if (input.env.PUGI_DISABLE_FILEWATCH !== '1') {
204
+ try {
205
+ const w = new PugiWatcher({ cwd: input.cwd, ignore });
206
+ await w.start();
207
+ watcher = w;
208
+ }
209
+ catch (error) {
210
+ const msg = error instanceof Error ? error.message : String(error);
211
+ process.stderr.write(`[pugi] Filewatch bootstrap failed (${msg}). Continuing without live updates.\n`);
212
+ }
213
+ }
214
+ return { skeleton, workingSet, watcher };
215
+ }
144
216
  /* ------------------------------------------------------------------ */
145
217
  /* Production transport */
146
218
  /* ------------------------------------------------------------------ */
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@pugi/cli",
3
- "version": "0.1.0-alpha.17",
4
- "description": "Pugi CLI terminal-native software execution system",
3
+ "version": "0.1.0-alpha.19",
4
+ "description": "Pugi CLI - terminal-native software execution system",
5
5
  "homepage": "https://pugi.io",
6
6
  "repository": {
7
7
  "type": "git",
@@ -35,11 +35,14 @@
35
35
  "engines": {
36
36
  "node": ">=22.5.0"
37
37
  },
38
+ "//publishConfig": "CEO sign-off 2026-05-23 alpha launch: @pugi/cli is the customer-facing CLI and ships PUBLIC so `npm i -g @pugi/cli` resolves anonymously. The HARD default-restricted memory rule (2026-05-25) applies to INTERNAL @pugi/* packages (db-client, telegram bot helpers, etc.) - those must ship access:restricted unless an additional CEO sign-off granted. @pugi/sdk + @pugi/personas were published public alongside the CLI under the same alpha-launch sign-off because the CLI's customer install pulls them as transitive deps; review before α7 GA.",
38
39
  "publishConfig": {
39
40
  "access": "public"
40
41
  },
41
42
  "dependencies": {
42
43
  "@mozilla/readability": "^0.6.0",
44
+ "chokidar": "^3.6.0",
45
+ "ignore": "^5.3.2",
43
46
  "ink": "^5.0.1",
44
47
  "linkedom": "^0.18.12",
45
48
  "react": "^18.3.1",
@@ -49,7 +52,7 @@
49
52
  "undici": "^8.3.0",
50
53
  "zod": "^3.23.0",
51
54
  "@pugi/personas": "0.1.1",
52
- "@pugi/sdk": "0.1.0-alpha.17"
55
+ "@pugi/sdk": "0.1.0-alpha.19"
53
56
  },
54
57
  "devDependencies": {
55
58
  "@types/node": "^22.0.0",