jeo-code 0.4.8 → 0.5.0

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/README.ja.md CHANGED
@@ -150,11 +150,11 @@ CI は `.github/workflows/npm-publish.yml` で公開します — GitHub リリ
150
150
  ## 変更履歴 (Changelog)
151
151
 
152
152
  <!-- CHANGELOG:START (auto-generated from CHANGELOG.md — run `bun run changelog:sync`) -->
153
+ - **[0.5.0]** (2026-06-14) — Performance: workspace-scan, workflow-state, and DNA-Claw HUD caches; plus a credential-safety fix that never wipes OAuth over an invalid config.
154
+ - **[0.4.9]** (2026-06-14) — Live-frame width-clamp (content-sized height) replaces the constant-height approach, typed text shows during a running turn, and a docs/AGENTS refresh.
153
155
  - **[0.4.8]** (2026-06-14) — Live-frame stability: constant-height live turn, renderer self-heal off-by-one fix, and frame-safe child-stdout sanitizing — no more duplicate model bar or torn escapes.
154
156
  - **[0.4.7]** (2026-06-14) — Detached subagents + `subagent` control tool, live shaded in-flight output, registry-driven providers, fuller `read` budget, styled italics in the final report, and `gjc` retired.
155
157
  - **[0.4.6]** (2026-06-14) — Width-correct forge cards for CJK/emoji, red borders on failed tool cards, aligned `ooo ralph` monitor HUD, and a per-theme user-card palette.
156
- - **[0.4.5]** (2026-06-14) — First-class filesystem make/remove tools.
157
- - **[0.4.4]** (2026-06-13) — Live subagent status mirroring, always-useful Ctrl+O activity tail, read lineRange crash guard.
158
158
 
159
159
  See [CHANGELOG.md](CHANGELOG.md) for the full history.
160
160
  <!-- CHANGELOG:END -->
package/README.ko.md CHANGED
@@ -150,11 +150,11 @@ CI는 `.github/workflows/npm-publish.yml`로 배포합니다 — GitHub 릴리
150
150
  ## 변경 이력 (Changelog)
151
151
 
152
152
  <!-- CHANGELOG:START (auto-generated from CHANGELOG.md — run `bun run changelog:sync`) -->
153
+ - **[0.5.0]** (2026-06-14) — Performance: workspace-scan, workflow-state, and DNA-Claw HUD caches; plus a credential-safety fix that never wipes OAuth over an invalid config.
154
+ - **[0.4.9]** (2026-06-14) — Live-frame width-clamp (content-sized height) replaces the constant-height approach, typed text shows during a running turn, and a docs/AGENTS refresh.
153
155
  - **[0.4.8]** (2026-06-14) — Live-frame stability: constant-height live turn, renderer self-heal off-by-one fix, and frame-safe child-stdout sanitizing — no more duplicate model bar or torn escapes.
154
156
  - **[0.4.7]** (2026-06-14) — Detached subagents + `subagent` control tool, live shaded in-flight output, registry-driven providers, fuller `read` budget, styled italics in the final report, and `gjc` retired.
155
157
  - **[0.4.6]** (2026-06-14) — Width-correct forge cards for CJK/emoji, red borders on failed tool cards, aligned `ooo ralph` monitor HUD, and a per-theme user-card palette.
156
- - **[0.4.5]** (2026-06-14) — First-class filesystem make/remove tools.
157
- - **[0.4.4]** (2026-06-13) — Live subagent status mirroring, always-useful Ctrl+O activity tail, read lineRange crash guard.
158
158
 
159
159
  See [CHANGELOG.md](CHANGELOG.md) for the full history.
160
160
  <!-- CHANGELOG:END -->
package/README.md CHANGED
@@ -150,11 +150,11 @@ Required npm token permissions (repository secret `NPM_TOKEN`):
150
150
  ## Changelog
151
151
 
152
152
  <!-- CHANGELOG:START (auto-generated from CHANGELOG.md — run `bun run changelog:sync`) -->
153
+ - **[0.5.0]** (2026-06-14) — Performance: workspace-scan, workflow-state, and DNA-Claw HUD caches; plus a credential-safety fix that never wipes OAuth over an invalid config.
154
+ - **[0.4.9]** (2026-06-14) — Live-frame width-clamp (content-sized height) replaces the constant-height approach, typed text shows during a running turn, and a docs/AGENTS refresh.
153
155
  - **[0.4.8]** (2026-06-14) — Live-frame stability: constant-height live turn, renderer self-heal off-by-one fix, and frame-safe child-stdout sanitizing — no more duplicate model bar or torn escapes.
154
156
  - **[0.4.7]** (2026-06-14) — Detached subagents + `subagent` control tool, live shaded in-flight output, registry-driven providers, fuller `read` budget, styled italics in the final report, and `gjc` retired.
155
157
  - **[0.4.6]** (2026-06-14) — Width-correct forge cards for CJK/emoji, red borders on failed tool cards, aligned `ooo ralph` monitor HUD, and a per-theme user-card palette.
156
- - **[0.4.5]** (2026-06-14) — First-class filesystem make/remove tools.
157
- - **[0.4.4]** (2026-06-13) — Live subagent status mirroring, always-useful Ctrl+O activity tail, read lineRange crash guard.
158
158
 
159
159
  See [CHANGELOG.md](CHANGELOG.md) for the full history.
160
160
  <!-- CHANGELOG:END -->
package/README.zh.md CHANGED
@@ -150,11 +150,11 @@ CI 通过 `.github/workflows/npm-publish.yml` 发布 — GitHub 发布 release
150
150
  ## 更新日志 (Changelog)
151
151
 
152
152
  <!-- CHANGELOG:START (auto-generated from CHANGELOG.md — run `bun run changelog:sync`) -->
153
+ - **[0.5.0]** (2026-06-14) — Performance: workspace-scan, workflow-state, and DNA-Claw HUD caches; plus a credential-safety fix that never wipes OAuth over an invalid config.
154
+ - **[0.4.9]** (2026-06-14) — Live-frame width-clamp (content-sized height) replaces the constant-height approach, typed text shows during a running turn, and a docs/AGENTS refresh.
153
155
  - **[0.4.8]** (2026-06-14) — Live-frame stability: constant-height live turn, renderer self-heal off-by-one fix, and frame-safe child-stdout sanitizing — no more duplicate model bar or torn escapes.
154
156
  - **[0.4.7]** (2026-06-14) — Detached subagents + `subagent` control tool, live shaded in-flight output, registry-driven providers, fuller `read` budget, styled italics in the final report, and `gjc` retired.
155
157
  - **[0.4.6]** (2026-06-14) — Width-correct forge cards for CJK/emoji, red borders on failed tool cards, aligned `ooo ralph` monitor HUD, and a per-theme user-card palette.
156
- - **[0.4.5]** (2026-06-14) — First-class filesystem make/remove tools.
157
- - **[0.4.4]** (2026-06-13) — Live subagent status mirroring, always-useful Ctrl+O activity tail, read lineRange crash guard.
158
158
 
159
159
  See [CHANGELOG.md](CHANGELOG.md) for the full history.
160
160
  <!-- CHANGELOG:END -->
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jeo-code",
3
- "version": "0.4.8",
3
+ "version": "0.5.0",
4
4
  "description": "Clean, highly optimized AI coding agent using spec-first loop",
5
5
  "type": "module",
6
6
  "main": "src/cli.ts",
package/src/AGENTS.md CHANGED
@@ -1,5 +1,5 @@
1
1
  <!-- Parent: ../AGENTS.md -->
2
- <!-- Generated: 2026-06-11 | Updated: 2026-06-11 -->
2
+ <!-- Generated: 2026-06-11 | Updated: 2026-06-14 -->
3
3
 
4
4
  # src
5
5
 
@@ -9,9 +9,12 @@ Core application source code for the `jeo-code` CLI and agent runtime. It orches
9
9
  ## Key Files
10
10
  | File | Description |
11
11
  |------|-------------|
12
+ | `autopilot.ts` | Brief description of purpose |
13
+ | `bun-imports.d.ts` | TypeScript declarations for Bun built-ins and raw module imports |
12
14
  | `cli.ts` | The main binary entrypoint |
13
15
  | `index.ts` | Library exports |
14
- | `bun-imports.d.ts` / `md-modules.d.ts` | TypeScript declarations for Bun built-ins and raw module imports |
16
+ | `ledger.ts` | Brief description of purpose |
17
+ | `md-modules.d.ts` | TypeScript declarations for Bun built-ins and raw module imports |
15
18
 
16
19
  ## Subdirectories
17
20
  | Directory | Purpose |
@@ -1,5 +1,5 @@
1
1
  <!-- Parent: ../AGENTS.md -->
2
- <!-- Generated: 2026-06-11 | Updated: 2026-06-11 -->
2
+ <!-- Generated: 2026-06-11 | Updated: 2026-06-14 -->
3
3
 
4
4
  # agent
5
5
 
@@ -9,13 +9,33 @@ The core runtime loop, tool registry, session management, and state persistence
9
9
  ## Key Files
10
10
  | File | Description |
11
11
  |------|-------------|
12
+ | `bash-fixups.ts` | Brief description of purpose |
13
+ | `compaction.ts` | Brief description of purpose |
14
+ | `config-schema.ts` | Brief description of purpose |
15
+ | `context-files.ts` | Brief description of purpose |
16
+ | `engine.ts` | Brief description of purpose |
17
+ | `hooks.ts` | Brief description of purpose |
18
+ | `json.ts` | Brief description of purpose |
12
19
  | `loop.ts` | The primary execution loop orchestrating model calls and tool execution |
13
- | `tools.ts` | Built-in tool definitions (bash, read, write, edit, etc.) |
14
- | `state.ts` | File-backed state and session persistence (`.jeo/state/`) |
15
- | `session.ts` | Session context building, compaction, and history management |
20
+ | `memory.ts` | Brief description of purpose |
21
+ | `model-recency.ts` | Brief description of purpose |
22
+ | `output-minimizer.ts` | Brief description of purpose |
23
+ | `output-util.ts` | Brief description of purpose |
16
24
  | `plan.ts` | Subagent planning structures and validation |
25
+ | `seed.ts` | Brief description of purpose |
26
+ | `session.ts` | Session context building, compaction, and history management |
27
+ | `state.ts` | File-backed state and session persistence (`.jeo/state/`) |
17
28
  | `step-budget.ts` | gjc-style flexible step budgeting: progress-scored extensions, hard cap, fail-fast |
18
- | `subagents.ts` / `task-tool.ts` | Delegation mechanisms and background execution of task subagents |
29
+ | `subagent-registry.ts` | Brief description of purpose |
30
+ | `subagent-tool.ts` | Brief description of purpose |
31
+ | `subagents.ts` | Brief description of purpose |
32
+ | `task-tool.ts` | Brief description of purpose |
33
+ | `todo-tool.ts` | Brief description of purpose |
34
+ | `tokenizer.ts` | Brief description of purpose |
35
+ | `tool-output.ts` | Brief description of purpose |
36
+ | `tool-registry.ts` | Brief description of purpose |
37
+ | `tools.ts` | Built-in tool definitions (bash, read, write, edit, etc.) |
38
+ | `web-search.ts` | Brief description of purpose |
19
39
 
20
40
  ## Subdirectories
21
41
  | Directory | Purpose |
@@ -78,7 +78,10 @@ const EXPLICIT_GUIDANCE_FILES = [".agents/oma-config.yaml", ".agents/oma-config.
78
78
 
79
79
  // Module-level cache of the downward scan, keyed by resolved cwd. The scan is
80
80
  // independent of $HOME (it only walks the cwd subtree), so caching by cwd is safe.
81
+ // Bounded LRU: a long-running session that scans many distinct cwds (subagents,
82
+ // worktrees, /view of other trees) must not grow this Map without bound.
81
83
  const workspaceScanCache = new Map<string, WorkspaceScan>();
84
+ const WORKSPACE_SCAN_CACHE_CAP = 32;
82
85
 
83
86
  function segsEqual(a: readonly string[], b: readonly string[]): boolean {
84
87
  if (a.length !== b.length) return false;
@@ -161,8 +164,18 @@ async function scanWorkspaceDownwards(resolvedCwd: string): Promise<WorkspaceSca
161
164
  async function getWorkspaceScan(cwd: string): Promise<WorkspaceScan> {
162
165
  const resolvedCwd = path.resolve(cwd);
163
166
  const cached = workspaceScanCache.get(resolvedCwd);
164
- if (cached) return cached;
167
+ if (cached) {
168
+ // LRU refresh: re-insert so the most-recently-used entry is evicted last.
169
+ workspaceScanCache.delete(resolvedCwd);
170
+ workspaceScanCache.set(resolvedCwd, cached);
171
+ return cached;
172
+ }
165
173
  const scan = await scanWorkspaceDownwards(resolvedCwd);
174
+ // Evict the oldest entry (Map preserves insertion order) once at capacity.
175
+ if (workspaceScanCache.size >= WORKSPACE_SCAN_CACHE_CAP) {
176
+ const oldest = workspaceScanCache.keys().next().value;
177
+ if (oldest !== undefined) workspaceScanCache.delete(oldest);
178
+ }
166
179
  workspaceScanCache.set(resolvedCwd, scan);
167
180
  return scan;
168
181
  }
@@ -1,5 +1,5 @@
1
- <!-- Parent: ../../AGENTS.md -->
2
- <!-- Generated: 2026-06-11 | Updated: 2026-06-11 -->
1
+ <!-- Parent: ../AGENTS.md -->
2
+ <!-- Generated: 2026-06-11 | Updated: 2026-06-14 -->
3
3
 
4
4
  # dev
5
5
 
@@ -9,6 +9,11 @@ Developer-specific agent tooling and spec automation.
9
9
  ## Key Files
10
10
  | File | Description |
11
11
  |------|-------------|
12
+ | `advanced-analyzer.ts` | Brief description of purpose |
13
+ | `evolution-bridge.ts` | Brief description of purpose |
14
+ | `evolution-logger.ts` | Brief description of purpose |
15
+ | `self-analysis.ts` | Brief description of purpose |
16
+ | `self-improve.ts` | Brief description of purpose |
12
17
  | `spec-automation.ts` | Tools to sync `.specify/` artifacts to ooo seeds |
13
18
 
14
19
  ## Subdirectories
@@ -233,7 +233,7 @@ type ParsedFile =
233
233
  | { kind: "ok"; config: Config }
234
234
  | { kind: "missing" }
235
235
  | { kind: "bad-json"; warned: boolean }
236
- | { kind: "invalid"; message: string; warned: boolean };
236
+ | { kind: "invalid"; message: string; warned: boolean; rawObject?: unknown };
237
237
  const configReadCache = new Map<string, { mtimeMs: number; size: number; parsed: ParsedFile }>();
238
238
  const CONFIG_CACHE_CAP = 8;
239
239
 
@@ -259,7 +259,9 @@ async function readParsedConfigFile(): Promise<ParsedFile> {
259
259
  const result = parseConfig(raw);
260
260
  parsed = result.ok
261
261
  ? { kind: "ok", config: result.config as Config }
262
- : { kind: "invalid", message: result.message, warned: false };
262
+ // Keep the raw JSON object on a schema-invalid (but JSON-valid) config so
263
+ // readRawGlobalConfig can salvage the credential blocks instead of dropping them.
264
+ : { kind: "invalid", message: result.message, warned: false, rawObject: raw };
263
265
  } catch {
264
266
  parsed = { kind: "bad-json", warned: false };
265
267
  }
@@ -271,6 +273,20 @@ async function readParsedConfigFile(): Promise<ParsedFile> {
271
273
  return parsed;
272
274
  }
273
275
 
276
+ /** Overlay the `oauth` + `providers` credential blocks from a schema-invalid (but
277
+ * JSON-valid) config's raw object onto `base`. A single bad scalar field (e.g. a
278
+ * non-string defaultModel) must never cost the user their stored credentials — neither
279
+ * when resolving them at runtime (readGlobalConfig) nor when persisting (readRawGlobalConfig). */
280
+ function salvageCredentials(base: Config, parsed: ParsedFile): Config {
281
+ if (parsed.kind !== "invalid" || !parsed.rawObject || typeof parsed.rawObject !== "object") return base;
282
+ const ro = parsed.rawObject as Record<string, unknown>;
283
+ if (ro.oauth && typeof ro.oauth === "object") base.oauth = structuredClone(ro.oauth) as Config["oauth"];
284
+ if (ro.providers && typeof ro.providers === "object") {
285
+ base.providers = { ...base.providers, ...(structuredClone(ro.providers) as Config["providers"]) };
286
+ }
287
+ return base;
288
+ }
289
+
274
290
  export async function readGlobalConfig(): Promise<Config> {
275
291
  const parsed = await readParsedConfigFile();
276
292
  if (parsed.kind === "bad-json" || parsed.kind === "invalid") {
@@ -280,7 +296,9 @@ export async function readGlobalConfig(): Promise<Config> {
280
296
  const detail = parsed.kind === "invalid" ? ` is invalid (${parsed.message})` : " is not valid JSON";
281
297
  process.stderr.write(`[jeo] ${globalConfigPath()}${detail}; using environment defaults.\n`);
282
298
  }
283
- return withEnvOverlay(envDefaultConfig());
299
+ // Credential salvage: keep oauth/providers from a JSON-valid-but-schema-invalid
300
+ // config so the runtime stays authenticated (and a later write repairs the file).
301
+ return withEnvOverlay(salvageCredentials(envDefaultConfig(), parsed));
284
302
  }
285
303
  if (parsed.kind === "missing") return withEnvOverlay(envDefaultConfig());
286
304
  return withEnvOverlay(structuredClone(parsed.config));
@@ -307,9 +325,15 @@ export async function saveGlobalConfig(config: Config): Promise<void> {
307
325
  * JEO_*_MODEL role tiers, OLLAMA_HOST/OPENAI_BASE_URL) are never baked into
308
326
  * ~/.jeo/config.json by an unrelated `/agents`/`/roles`/`/model save`. */
309
327
  export async function readRawGlobalConfig(): Promise<Config> {
310
- const clean: Config = { providers: {}, defaultModel: DEFAULT_MODEL, thinkingLevel: "medium" };
311
328
  const parsed = await readParsedConfigFile();
312
- return parsed.kind === "ok" ? structuredClone(parsed.config) : clean;
329
+ if (parsed.kind === "ok") return structuredClone(parsed.config);
330
+ // CREDENTIAL SAFETY: when the on-disk config is JSON-valid but fails schema validation
331
+ // on some unrelated field, salvage the `oauth` + `providers` blocks. Without this, the
332
+ // next saveConfigPatch (e.g. an auto token refresh that patches ONE provider) bases on
333
+ // a clean config and silently wipes every OTHER stored credential — the "OAuth de-authed
334
+ // after a session" bug. The invalid scalar field is dropped (reset to default).
335
+ const clean: Config = { providers: {}, defaultModel: DEFAULT_MODEL, thinkingLevel: "medium" };
336
+ return salvageCredentials(clean, parsed);
313
337
  }
314
338
 
315
339
  /** Merge a patch onto the RAW on-disk config and persist. The `build` callback
@@ -326,17 +350,65 @@ export function getLocalJeoDir(cwd: string = process.cwd()): string {
326
350
  return path.join(cwd, ".jeo");
327
351
  }
328
352
 
353
+ // mtime+size-validated cache for the small per-skill workflow-state JSON. readWorkflowState
354
+ // runs repeatedly (the mutation guard reads before every mutating tool), so re-reading +
355
+ // re-parsing each call is wasteful. CROSS-PROCESS-SAFE: a write by another process bumps
356
+ // mtime/size → forces a fresh read, so the security-sensitive guard never serves a stale
357
+ // lock. Same-process write/clear update or drop the entry directly. LRU-capped.
358
+ const workflowStateCache = new Map<string, { mtimeMs: number; size: number; value: WorkflowState | null }>();
359
+ const WORKFLOW_STATE_CACHE_CAP = 16;
360
+
361
+ function cacheWorkflowState(statePath: string, mtimeMs: number, size: number, value: WorkflowState | null): void {
362
+ workflowStateCache.delete(statePath);
363
+ if (workflowStateCache.size >= WORKFLOW_STATE_CACHE_CAP) {
364
+ const oldest = workflowStateCache.keys().next().value;
365
+ if (oldest !== undefined) workflowStateCache.delete(oldest);
366
+ }
367
+ workflowStateCache.set(statePath, { mtimeMs, size, value });
368
+ }
369
+
370
+ async function loadWorkflowStateFile(statePath: string, strict: boolean): Promise<WorkflowState | null> {
371
+ let st: { mtimeMs: number; size: number };
372
+ try {
373
+ st = await fs.stat(statePath);
374
+ } catch (err) {
375
+ workflowStateCache.delete(statePath);
376
+ if ((err as NodeJS.ErrnoException).code === "ENOENT") return null;
377
+ if (strict) throw err;
378
+ return null;
379
+ }
380
+ const hit = workflowStateCache.get(statePath);
381
+ if (hit && hit.mtimeMs === st.mtimeMs && hit.size === st.size) {
382
+ workflowStateCache.delete(statePath); // LRU refresh
383
+ workflowStateCache.set(statePath, hit);
384
+ return hit.value;
385
+ }
386
+ let data: string;
387
+ try {
388
+ data = await fs.readFile(statePath, "utf-8");
389
+ } catch (err) {
390
+ workflowStateCache.delete(statePath);
391
+ if ((err as NodeJS.ErrnoException).code === "ENOENT") return null;
392
+ if (strict) throw err;
393
+ return null;
394
+ }
395
+ try {
396
+ const parsed = JSON.parse(data) as WorkflowState;
397
+ cacheWorkflowState(statePath, st.mtimeMs, st.size, parsed);
398
+ return parsed;
399
+ } catch {
400
+ workflowStateCache.delete(statePath);
401
+ if (strict) throw new Error(`workflow state ${statePath} is corrupt (invalid JSON)`);
402
+ return null;
403
+ }
404
+ }
405
+
329
406
  export async function readWorkflowState(
330
407
  skill: "deep-interview" | "ralplan" | "team" | "ultragoal",
331
408
  cwd: string = process.cwd()
332
409
  ): Promise<WorkflowState | null> {
333
410
  const statePath = path.join(getLocalJeoDir(cwd), "state", `${skill}-state.json`);
334
- try {
335
- const data = await fs.readFile(statePath, "utf-8");
336
- return JSON.parse(data) as WorkflowState;
337
- } catch {
338
- return null;
339
- }
411
+ return loadWorkflowStateFile(statePath, false);
340
412
  }
341
413
 
342
414
  /**
@@ -349,18 +421,7 @@ export async function readWorkflowStateStrict(
349
421
  cwd: string = process.cwd()
350
422
  ): Promise<WorkflowState | null> {
351
423
  const statePath = path.join(getLocalJeoDir(cwd), "state", `${skill}-state.json`);
352
- let data: string;
353
- try {
354
- data = await fs.readFile(statePath, "utf-8");
355
- } catch (err) {
356
- if ((err as NodeJS.ErrnoException).code === "ENOENT") return null;
357
- throw err;
358
- }
359
- try {
360
- return JSON.parse(data) as WorkflowState;
361
- } catch {
362
- throw new Error(`workflow state ${statePath} is corrupt (invalid JSON)`);
363
- }
424
+ return loadWorkflowStateFile(statePath, true);
364
425
  }
365
426
 
366
427
  export async function writeWorkflowState(
@@ -382,6 +443,14 @@ export async function writeWorkflowState(
382
443
  await fs.unlink(tmpPath).catch(() => {});
383
444
  throw err;
384
445
  }
446
+ // Cache the just-written state keyed on the new file fingerprint so the next read
447
+ // (often the mutation guard milliseconds later) is served from memory.
448
+ try {
449
+ const st = await fs.stat(statePath);
450
+ cacheWorkflowState(statePath, st.mtimeMs, st.size, state);
451
+ } catch {
452
+ workflowStateCache.delete(statePath);
453
+ }
385
454
  return statePath;
386
455
  }
387
456
 
@@ -393,6 +462,7 @@ export async function clearWorkflowState(
393
462
  try {
394
463
  await fs.unlink(statePath);
395
464
  } catch {}
465
+ workflowStateCache.delete(statePath);
396
466
  }
397
467
 
398
468
  /**
package/src/ai/AGENTS.md CHANGED
@@ -1,5 +1,5 @@
1
1
  <!-- Parent: ../AGENTS.md -->
2
- <!-- Generated: 2026-06-11 | Updated: 2026-06-11 -->
2
+ <!-- Generated: 2026-06-11 | Updated: 2026-06-14 -->
3
3
 
4
4
  # ai
5
5
 
@@ -9,9 +9,20 @@ Abstractions for LLM inference, provider management, tool formatting, and token
9
9
  ## Key Files
10
10
  | File | Description |
11
11
  |------|-------------|
12
- | `registry.ts` | Central registry for available providers and model resolution |
12
+ | `index.ts` | Brief description of purpose |
13
+ | `model-catalog-compat.ts` | Brief description of purpose |
14
+ | `model-catalog.ts` | Brief description of purpose |
15
+ | `model-discovery.ts` | Brief description of purpose |
16
+ | `model-enrich.ts` | Brief description of purpose |
17
+ | `model-manager.ts` | Brief description of purpose |
18
+ | `model-picker.ts` | Brief description of purpose |
19
+ | `model-registry.ts` | Brief description of purpose |
20
+ | `pricing.ts` | Brief description of purpose |
21
+ | `provider-registry.ts` | Brief description of purpose |
22
+ | `provider-status.ts` | Brief description of purpose |
23
+ | `register-providers.ts` | Brief description of purpose |
24
+ | `sse.ts` | Brief description of purpose |
13
25
  | `types.ts` | Common interfaces for AI requests, responses, and streams |
14
- | `format.ts` | Conversion between internal tool schemas and provider-specific formats |
15
26
 
16
27
  ## Subdirectories
17
28
  | Directory | Purpose |
@@ -1,5 +1,5 @@
1
- <!-- Parent: ../../AGENTS.md -->
2
- <!-- Generated: 2026-06-11 | Updated: 2026-06-11 -->
1
+ <!-- Parent: ../AGENTS.md -->
2
+ <!-- Generated: 2026-06-11 | Updated: 2026-06-14 -->
3
3
 
4
4
  # providers
5
5
 
@@ -10,10 +10,12 @@ Concrete implementations for various LLM providers, translating generic requests
10
10
  | File | Description |
11
11
  |------|-------------|
12
12
  | `anthropic.ts` | Anthropic Claude integration |
13
- | `openai.ts` | OpenAI (and Codex backend) integration |
14
- | `gemini.ts` | Google Gemini (and Cloud Code Assist) integration |
15
13
  | `antigravity.ts` | Antigravity desktop-app OAuth client integration |
14
+ | `errors.ts` | Brief description of purpose |
15
+ | `gemini.ts` | Google Gemini (and Cloud Code Assist) integration |
16
16
  | `ollama.ts` | Local Ollama integration |
17
+ | `openai-responses.ts` | Brief description of purpose |
18
+ | `openai.ts` | OpenAI (and Codex backend) integration |
17
19
 
18
20
  ## Subdirectories
19
21
  *(None)*
@@ -1,5 +1,5 @@
1
1
  <!-- Parent: ../AGENTS.md -->
2
- <!-- Generated: 2026-06-11 | Updated: 2026-06-11 -->
2
+ <!-- Generated: 2026-06-11 | Updated: 2026-06-14 -->
3
3
 
4
4
  # auth
5
5
 
@@ -9,8 +9,13 @@ Authentication and credential management for OAuth flows and API keys. Ensures s
9
9
  ## Key Files
10
10
  | File | Description |
11
11
  |------|-------------|
12
- | `store.ts` | Secure credential storage mechanism |
13
- | `config.ts` | Resolution of keys from environment variables and config files |
12
+ | `callback-server.ts` | Brief description of purpose |
13
+ | `index.ts` | Brief description of purpose |
14
+ | `oauth.ts` | Brief description of purpose |
15
+ | `pkce.ts` | Brief description of purpose |
16
+ | `refresh.ts` | Brief description of purpose |
17
+ | `storage.ts` | Brief description of purpose |
18
+ | `types.ts` | Brief description of purpose |
14
19
 
15
20
  ## Subdirectories
16
21
  | Directory | Purpose |
@@ -1,5 +1,5 @@
1
- <!-- Parent: ../../AGENTS.md -->
2
- <!-- Generated: 2026-06-11 | Updated: 2026-06-11 -->
1
+ <!-- Parent: ../AGENTS.md -->
2
+ <!-- Generated: 2026-06-11 | Updated: 2026-06-14 -->
3
3
 
4
4
  # flows
5
5
 
@@ -9,8 +9,12 @@ Specific OAuth flow implementations for various providers.
9
9
  ## Key Files
10
10
  | File | Description |
11
11
  |------|-------------|
12
- | `oauth.ts` / `pkce.ts` | Generic OAuth and PKCE utilities |
13
- | `*.ts` | Provider-specific login flows (e.g., anthropic, openai, gemini) |
12
+ | `anthropic.ts` | Brief description of purpose |
13
+ | `antigravity.ts` | Brief description of purpose |
14
+ | `google-project.ts` | Brief description of purpose |
15
+ | `google.ts` | Brief description of purpose |
16
+ | `index.ts` | Brief description of purpose |
17
+ | `openai.ts` | Brief description of purpose |
14
18
 
15
19
  ## Subdirectories
16
20
  *(None)*
@@ -27,6 +31,11 @@ Specific OAuth flow implementations for various providers.
27
31
  - Loopback HTTP servers for receiving OAuth callbacks.
28
32
 
29
33
  ## Dependencies
30
- *(None)*
34
+
35
+ ### Internal
36
+ {References to other parts of the codebase this depends on}
37
+
38
+ ### External
39
+ {Key external packages/libraries used}
31
40
 
32
41
  <!-- MANUAL: -->
package/src/cli/AGENTS.md CHANGED
@@ -1,5 +1,5 @@
1
1
  <!-- Parent: ../AGENTS.md -->
2
- <!-- Generated: 2026-06-11 | Updated: 2026-06-11 -->
2
+ <!-- Generated: 2026-06-11 | Updated: 2026-06-14 -->
3
3
 
4
4
  # cli
5
5
 
@@ -9,8 +9,8 @@ Command-line interface routing, argument parsing, and initialization logic. Defi
9
9
  ## Key Files
10
10
  | File | Description |
11
11
  |------|-------------|
12
- | `parser.ts` | Argument parsing and flag validation |
13
- | `router.ts` | Dispatches CLI commands to their respective implementations |
12
+ | `index.ts` | Brief description of purpose |
13
+ | `runner.ts` | Brief description of purpose |
14
14
 
15
15
  ## Subdirectories
16
16
  *(None)*
@@ -1,5 +1,5 @@
1
1
  <!-- Parent: ../AGENTS.md -->
2
- <!-- Generated: 2026-06-11 | Updated: 2026-06-11 -->
2
+ <!-- Generated: 2026-06-11 | Updated: 2026-06-14 -->
3
3
 
4
4
  # commands
5
5
 
@@ -9,10 +9,28 @@ Concrete implementations of `jeo` subcommands (e.g., launch, setup, team, ultrag
9
9
  ## Key Files
10
10
  | File | Description |
11
11
  |------|-------------|
12
+ | `approve.ts` | Brief description of purpose |
13
+ | `auth.ts` | Brief description of purpose |
14
+ | `chat.ts` | Brief description of purpose |
15
+ | `deep-interview.ts` | Brief description of purpose |
16
+ | `doctor.ts` | Brief description of purpose |
17
+ | `evolve-core.ts` | Brief description of purpose |
18
+ | `evolve.ts` | Brief description of purpose |
19
+ | `export.ts` | Brief description of purpose |
12
20
  | `launch.ts` | The primary interactive/one-shot execution command |
21
+ | `mcp.ts` | Brief description of purpose |
22
+ | `ooo-seed.ts` | Brief description of purpose |
23
+ | `ralplan.ts` | Brief description of purpose |
24
+ | `resume.ts` | Brief description of purpose |
25
+ | `session.ts` | Brief description of purpose |
26
+ | `setup-helpers.ts` | Brief description of purpose |
13
27
  | `setup.ts` | Guided configuration command |
28
+ | `skills.ts` | Brief description of purpose |
29
+ | `state.ts` | Brief description of purpose |
30
+ | `status.ts` | Brief description of purpose |
14
31
  | `team.ts` | Multi-agent coordination command |
15
- | `status.ts` / `update.ts` | Inspection and maintenance commands |
32
+ | `ultragoal.ts` | Brief description of purpose |
33
+ | `update.ts` | Brief description of purpose |
16
34
 
17
35
  ## Subdirectories
18
36
  *(None)*
@@ -1418,13 +1418,13 @@ export async function runLaunchCommand(args: string[]): Promise<void> {
1418
1418
  return;
1419
1419
  }
1420
1420
  }
1421
- // Mid-turn additional input is committed (and shown) ONLY on Enter (above):
1422
- // the running turn does NOT echo half-typed text per keystroke. Captured
1423
- // printable input accumulates silently in the draft buffer and surfaces as a
1424
- // `user` card the moment Enter lifts it into the steering inbox (or folds into
1425
- // the next prompt if the turn ends first). JEO_LIVE_DRAFT=1 restores the
1426
- // legacy live per-keystroke echo in the input box.
1427
- if (captured && jeoEnv("LIVE_DRAFT") === "1") {
1421
+ // Mid-turn typing is echoed LIVE into the input box so the field never looks
1422
+ // frozen/disabled while a turn runs the typed text IS captured, so it must be
1423
+ // visible. This updates the in-frame input box via the differential renderer
1424
+ // only; it never leaks into scrollback/history (native readline echo stays
1425
+ // suppressed for the whole turn). On Enter the draft is lifted into the steering
1426
+ // inbox and surfaces as a `user` card (above). JEO_NO_LIVE_DRAFT=1 opts out.
1427
+ if (captured && jeoEnv("NO_LIVE_DRAFT") !== "1") {
1428
1428
  tui.setLivePromptInput(queueBusySnapshot?.().text ?? "");
1429
1429
  }
1430
1430
  },
package/src/mcp/AGENTS.md CHANGED
@@ -1,5 +1,5 @@
1
1
  <!-- Parent: ../AGENTS.md -->
2
- <!-- Generated: 2026-06-11 | Updated: 2026-06-11 -->
2
+ <!-- Generated: 2026-06-11 | Updated: 2026-06-14 -->
3
3
 
4
4
  # mcp
5
5
 
@@ -9,8 +9,10 @@ Model Context Protocol (MCP) integration, allowing `jeo-code` to expose tools or
9
9
  ## Key Files
10
10
  | File | Description |
11
11
  |------|-------------|
12
+ | `index.ts` | Brief description of purpose |
13
+ | `protocol.ts` | Brief description of purpose |
12
14
  | `server.ts` | MCP server implementation (if exposing tools) |
13
- | `client.ts` | MCP client implementation (for consuming external tools) |
15
+ | `tools.ts` | Brief description of purpose |
14
16
 
15
17
  ## Subdirectories
16
18
  *(None)*
@@ -1,5 +1,5 @@
1
1
  <!-- Parent: ../AGENTS.md -->
2
- <!-- Generated: 2026-06-11 | Updated: 2026-06-11 -->
2
+ <!-- Generated: 2026-06-11 | Updated: 2026-06-14 -->
3
3
 
4
4
  # prompts
5
5
 
@@ -7,9 +7,7 @@
7
7
  Bundled system prompts, role definitions, and workflow skill documentation for the agent.
8
8
 
9
9
  ## Key Files
10
- | File | Description |
11
- |------|-------------|
12
- | `system.md` | Core system prompt template |
10
+ *(None)*
13
11
 
14
12
  ## Subdirectories
15
13
  | Directory | Purpose |
@@ -1,5 +1,5 @@
1
- <!-- Parent: ../../AGENTS.md -->
2
- <!-- Generated: 2026-06-11 | Updated: 2026-06-11 -->
1
+ <!-- Parent: ../AGENTS.md -->
2
+ <!-- Generated: 2026-06-11 | Updated: 2026-06-14 -->
3
3
 
4
4
  # agents
5
5
 
@@ -9,10 +9,10 @@ Role-specific system prompts defining the behavior of subagents (executor, plann
9
9
  ## Key Files
10
10
  | File | Description |
11
11
  |------|-------------|
12
- | `executor.md` | Mutating agent for executing bounded tasks |
13
- | `planner.md` | Read-only agent for sequencing tasks |
14
12
  | `architect.md` | Read-only agent for structural review |
15
13
  | `critic.md` | Read-only agent for plan critique |
14
+ | `executor.md` | Mutating agent for executing bounded tasks |
15
+ | `planner.md` | Read-only agent for sequencing tasks |
16
16
 
17
17
  ## Subdirectories
18
18
  *(None)*
@@ -30,6 +30,11 @@ Role-specific system prompts defining the behavior of subagents (executor, plann
30
30
  *(None)*
31
31
 
32
32
  ## Dependencies
33
- *(None)*
33
+
34
+ ### Internal
35
+ {References to other parts of the codebase this depends on}
36
+
37
+ ### External
38
+ {Key external packages/libraries used}
34
39
 
35
40
  <!-- MANUAL: -->
@@ -1,5 +1,5 @@
1
- <!-- Parent: ../../AGENTS.md -->
2
- <!-- Generated: 2026-06-11 | Updated: 2026-06-11 -->
1
+ <!-- Parent: ../AGENTS.md -->
2
+ <!-- Generated: 2026-06-11 | Updated: 2026-06-14 -->
3
3
 
4
4
  # skills
5
5
 
@@ -7,16 +7,16 @@
7
7
  Bundled workflow skills offering specialized, multi-step procedures for the agent.
8
8
 
9
9
  ## Key Files
10
- *(See subdirectories)*
10
+ *(None)*
11
11
 
12
12
  ## Subdirectories
13
13
  | Directory | Purpose |
14
14
  |-----------|---------|
15
+ | `deep-dive/` | What it contains (see `deep-dive/AGENTS.md`) |
15
16
  | `deep-interview/` | Socratic requirements gathering |
16
17
  | `ralplan/` | Spec-first planning and consensus building |
17
18
  | `team/` | Coordinated multi-agent execution |
18
19
  | `ultragoal/` | Durable verification and ledger tracking |
19
- | `gjc/` | Legacy parity configurations |
20
20
 
21
21
  ## For AI Agents
22
22
 
@@ -31,6 +31,11 @@ Bundled workflow skills offering specialized, multi-step procedures for the agen
31
31
  *(None)*
32
32
 
33
33
  ## Dependencies
34
- *(None)*
34
+
35
+ ### Internal
36
+ {References to other parts of the codebase this depends on}
37
+
38
+ ### External
39
+ {Key external packages/libraries used}
35
40
 
36
41
  <!-- MANUAL: -->
@@ -1,5 +1,5 @@
1
1
  <!-- Parent: ../AGENTS.md -->
2
- <!-- Generated: 2026-06-11 | Updated: 2026-06-11 -->
2
+ <!-- Generated: 2026-06-11 | Updated: 2026-06-14 -->
3
3
 
4
4
  # deep-dive
5
5
 
@@ -26,6 +26,11 @@ Bundled SKILL.md for the `deep-dive` workflow.
26
26
  *(None)*
27
27
 
28
28
  ## Dependencies
29
- *(None)*
29
+
30
+ ### Internal
31
+ {References to other parts of the codebase this depends on}
32
+
33
+ ### External
34
+ {Key external packages/libraries used}
30
35
 
31
36
  <!-- MANUAL: -->
@@ -1,5 +1,5 @@
1
1
  <!-- Parent: ../AGENTS.md -->
2
- <!-- Generated: 2026-06-11 | Updated: 2026-06-11 -->
2
+ <!-- Generated: 2026-06-11 | Updated: 2026-06-14 -->
3
3
 
4
4
  # deep-interview
5
5
 
@@ -26,6 +26,11 @@ Bundled SKILL.md for the `deep-interview` workflow.
26
26
  *(None)*
27
27
 
28
28
  ## Dependencies
29
- *(None)*
29
+
30
+ ### Internal
31
+ {References to other parts of the codebase this depends on}
32
+
33
+ ### External
34
+ {Key external packages/libraries used}
30
35
 
31
36
  <!-- MANUAL: -->
@@ -1,5 +1,5 @@
1
1
  <!-- Parent: ../AGENTS.md -->
2
- <!-- Generated: 2026-06-11 | Updated: 2026-06-11 -->
2
+ <!-- Generated: 2026-06-11 | Updated: 2026-06-14 -->
3
3
 
4
4
  # ralplan
5
5
 
@@ -26,6 +26,11 @@ Bundled SKILL.md for the `ralplan` workflow.
26
26
  *(None)*
27
27
 
28
28
  ## Dependencies
29
- *(None)*
29
+
30
+ ### Internal
31
+ {References to other parts of the codebase this depends on}
32
+
33
+ ### External
34
+ {Key external packages/libraries used}
30
35
 
31
36
  <!-- MANUAL: -->
@@ -1,5 +1,5 @@
1
1
  <!-- Parent: ../AGENTS.md -->
2
- <!-- Generated: 2026-06-11 | Updated: 2026-06-11 -->
2
+ <!-- Generated: 2026-06-11 | Updated: 2026-06-14 -->
3
3
 
4
4
  # team
5
5
 
@@ -26,6 +26,11 @@ Bundled SKILL.md for the `team` workflow.
26
26
  *(None)*
27
27
 
28
28
  ## Dependencies
29
- *(None)*
29
+
30
+ ### Internal
31
+ {References to other parts of the codebase this depends on}
32
+
33
+ ### External
34
+ {Key external packages/libraries used}
30
35
 
31
36
  <!-- MANUAL: -->
@@ -1,5 +1,5 @@
1
1
  <!-- Parent: ../AGENTS.md -->
2
- <!-- Generated: 2026-06-11 | Updated: 2026-06-11 -->
2
+ <!-- Generated: 2026-06-11 | Updated: 2026-06-14 -->
3
3
 
4
4
  # ultragoal
5
5
 
@@ -26,6 +26,11 @@ Bundled SKILL.md for the `ultragoal` workflow.
26
26
  *(None)*
27
27
 
28
28
  ## Dependencies
29
- *(None)*
29
+
30
+ ### Internal
31
+ {References to other parts of the codebase this depends on}
32
+
33
+ ### External
34
+ {Key external packages/libraries used}
30
35
 
31
36
  <!-- MANUAL: -->
@@ -1,5 +1,5 @@
1
1
  <!-- Parent: ../AGENTS.md -->
2
- <!-- Generated: 2026-06-11 | Updated: 2026-06-11 -->
2
+ <!-- Generated: 2026-06-11 | Updated: 2026-06-14 -->
3
3
 
4
4
  # skills
5
5
 
@@ -9,8 +9,7 @@ Framework for discovering, loading, and executing workflow skills (both bundled
9
9
  ## Key Files
10
10
  | File | Description |
11
11
  |------|-------------|
12
- | `registry.ts` | Discovers and catalogs available skills |
13
- | `executor.ts` | Mechanism to inject skill prompts into the active session |
12
+ | `catalog.ts` | Brief description of purpose |
14
13
 
15
14
  ## Subdirectories
16
15
  *(None)*
package/src/tui/AGENTS.md CHANGED
@@ -1,5 +1,5 @@
1
1
  <!-- Parent: ../AGENTS.md -->
2
- <!-- Generated: 2026-06-11 | Updated: 2026-06-11 -->
2
+ <!-- Generated: 2026-06-11 | Updated: 2026-06-14 -->
3
3
 
4
4
  # tui
5
5
 
@@ -10,6 +10,7 @@ Terminal User Interface logic, layout systems, and the differential renderer. Re
10
10
  | File | Description |
11
11
  |------|-------------|
12
12
  | `app.ts` | High-level TUI orchestrator (`LaunchTui`) |
13
+ | `index.ts` | Brief description of purpose |
13
14
  | `renderer.ts` | The differential, atomic terminal renderer (handles scrollback, resizing, DECSET 2026) |
14
15
  | `terminal.ts` | Low-level ANSI escape codes and terminal size utilities |
15
16
 
package/src/tui/app.ts CHANGED
@@ -554,10 +554,6 @@ export class LaunchTui {
554
554
  });
555
555
  }
556
556
 
557
- private renderLiveUserQueryCard(cols: number): string[] {
558
- return this.renderUserCard(this.livePromptInput, cols);
559
- }
560
-
561
557
  /** Render a `user`-labeled query card (orange "user" header over a filled box).
562
558
  * Shared by the live next-prompt draft and the mid-turn steering flush. */
563
559
  private renderUserCard(rawText: string, cols: number): string[] {
@@ -1186,12 +1182,6 @@ export class LaunchTui {
1186
1182
  }));
1187
1183
  }
1188
1184
 
1189
- // User text typed while the model is still thinking is surfaced as a live
1190
- // pending-user card (same query input underneath, no hidden auto-executing queue).
1191
- if (this.livePromptInput.trim()) {
1192
- tail.push("");
1193
- tail.push(...this.renderLiveUserQueryCard(cols));
1194
- }
1195
1185
 
1196
1186
  // Agent task plan (the `todo` tool) as a Todos checklist.
1197
1187
  if (args.planLines.length) {
@@ -1316,18 +1306,11 @@ export class LaunchTui {
1316
1306
  // model bar), no outer border, no mascot art — completed work lives in scrollback.
1317
1307
  if (fit && this.inline) {
1318
1308
  const inlineFrame = this.composeInlineFrame({ cols, rows, stepNow, elapsedMs, idx, isThinking, planLines });
1319
- // Option C (constant live-frame height): pad the composed frame to EXACTLY `rows`
1320
- // blank rows at the TOP, the tail (status/hud/input/model bar) pinned to the
1321
- // bottom. With a constant height the differential renderer reserves rows ONCE and
1322
- // thereafter only does in-place, within-frame cursor moves; the bottom-margin
1323
- // reserve-GROW that drifted the anchor by one row (the duplicate model bar during
1324
- // rapid tool churn) never runs again. Every line is still width-clamped so a long
1325
- // line cannot soft-wrap into a second physical row and desync the row accounting.
1326
- const capped = inlineFrame.length > rows ? inlineFrame.slice(inlineFrame.length - rows) : inlineFrame;
1327
- const fixedHeight = capped.length < rows
1328
- ? [...new Array(rows - capped.length).fill(""), ...capped]
1329
- : capped;
1330
- this.renderer.render(fixedHeight.map(l => truncateToWidth(l, cols)));
1309
+ // Screen-safety: every rendered line is width-clamped to `cols` so a long line
1310
+ // (e.g. the model bar with a deep cwd) cannot soft-wrap into a second physical row
1311
+ // and desync the differential renderer's 1-line=1-row accounting. Frame height stays
1312
+ // content-sized so completed cards remain visible in scrollback above the live frame.
1313
+ this.renderer.render(inlineFrame.slice(0, rows).map(l => truncateToWidth(l, cols)));
1331
1314
  return;
1332
1315
  }
1333
1316
 
@@ -1391,10 +1374,6 @@ export class LaunchTui {
1391
1374
  bottom.push(` ${categoryBadge("status", { color: this.theme.color })} ${msg}${guardBadge}`);
1392
1375
  }
1393
1376
  }
1394
- if (fit && this.livePromptInput.trim()) {
1395
- bottom.push("");
1396
- bottom.push(...this.renderLiveUserQueryCard(innerWidth));
1397
- }
1398
1377
  // TTY only: keep the same query input box visible above the footer while the
1399
1378
  // turn is running; typed text edits the next-prompt draft, not a side queue.
1400
1379
  if (fit) {
@@ -1,5 +1,5 @@
1
- <!-- Parent: ../../AGENTS.md -->
2
- <!-- Generated: 2026-06-11 | Updated: 2026-06-11 -->
1
+ <!-- Parent: ../AGENTS.md -->
2
+ <!-- Generated: 2026-06-11 | Updated: 2026-06-14 -->
3
3
 
4
4
  # components
5
5
 
@@ -9,11 +9,44 @@ Reusable UI widgets and layout primitives for the terminal interface.
9
9
  ## Key Files
10
10
  | File | Description |
11
11
  |------|-------------|
12
+ | `ascii-art.ts` | Cellular evolution graphics |
13
+ | `autocomplete.ts` | Brief description of purpose |
14
+ | `autopilot-status.ts` | Brief description of purpose |
15
+ | `capability.ts` | Brief description of purpose |
16
+ | `category-index.ts` | Brief description of purpose |
17
+ | `code-view.ts` | Brief description of purpose |
18
+ | `color.ts` | Brief description of purpose |
19
+ | `config-panel.ts` | Brief description of purpose |
20
+ | `duration.ts` | Brief description of purpose |
21
+ | `evolution.ts` | Brief description of purpose |
22
+ | `footer.ts` | Brief description of purpose |
12
23
  | `forge.ts` | Formats the boxed tool execution outputs |
13
- | `status.ts` | The `[STEP]` / `[STATUS]` / `[TOOL]` HUD lines |
14
- | `section.ts` | Shadcn-inspired card layout and spacing tokens |
24
+ | `hints.ts` | Brief description of purpose |
25
+ | `hud.ts` | Brief description of purpose |
26
+ | `index.ts` | Brief description of purpose |
27
+ | `input-box.ts` | Brief description of purpose |
15
28
  | `layout.ts` | Low-level padding, boxing, and alignment math |
16
- | `ascii-art.ts` | Cellular evolution graphics |
29
+ | `live-model-picker.ts` | Brief description of purpose |
30
+ | `markdown-table.ts` | Brief description of purpose |
31
+ | `markdown-text.ts` | Brief description of purpose |
32
+ | `meter.ts` | Brief description of purpose |
33
+ | `model-picker.ts` | Brief description of purpose |
34
+ | `provider-picker.ts` | Brief description of purpose |
35
+ | `section.ts` | Shadcn-inspired card layout and spacing tokens |
36
+ | `select-list.ts` | Brief description of purpose |
37
+ | `skill-picker.ts` | Brief description of purpose |
38
+ | `slash.ts` | Brief description of purpose |
39
+ | `spinner.ts` | Brief description of purpose |
40
+ | `status.ts` | The `[STEP]` / `[STATUS]` / `[TOOL]` HUD lines |
41
+ | `step-timeline.ts` | Brief description of purpose |
42
+ | `stream.ts` | Brief description of purpose |
43
+ | `themes.ts` | Brief description of purpose |
44
+ | `todo-card.ts` | Brief description of purpose |
45
+ | `tool-list.ts` | Brief description of purpose |
46
+ | `transcript.ts` | Brief description of purpose |
47
+ | `update-box.ts` | Brief description of purpose |
48
+ | `welcome.ts` | Brief description of purpose |
49
+ | `width.ts` | Brief description of purpose |
17
50
 
18
51
  ## Subdirectories
19
52
  *(None)*
@@ -524,6 +524,15 @@ export const DNA_CLAW_ART_GRAND_ASCII: string[] = [
524
524
  " [ D N A . C L A W ] "
525
525
  ];
526
526
 
527
+ // Bounded memo of fully-rendered DNA Claw frames keyed by every input that affects
528
+ // output (grand/unicode/cols/color/colorLevel/phase/frame). The live HUD cycles a
529
+ // FIXED ~60-frame set (3 twists × 20 gradient phases) at ~120ms; without this each
530
+ // recurrence recomputed per-line animatedGradientText (ANSI gradient) from scratch.
531
+ // The memo makes the 2nd+ cycle O(1) lookups, cutting steady-state HUD CPU. LRU-capped.
532
+ const dnaClawMemo = new Map<string, string[]>();
533
+ const DNA_CLAW_MEMO_CAP = 256;
534
+ const EMPTY_DNA_FRAME: string[] = [];
535
+
527
536
  export function renderDnaClaw(opts: {
528
537
  cols?: number;
529
538
  phase?: number;
@@ -537,6 +546,9 @@ export function renderDnaClaw(opts: {
537
546
  * `phase` this animates the forge identity without any frame-count growth. */
538
547
  frame?: number;
539
548
  }): string[] {
549
+ const memoKey = `${opts.grand ? "g" : "c"}|${opts.unicode !== false ? 1 : 0}|${opts.cols ?? -1}|${opts.color !== false ? 1 : 0}|${opts.colorLevel ?? ColorLevel.TrueColor}|${opts.phase ?? 0}|${opts.frame ?? 0}`;
550
+ const memoHit = dnaClawMemo.get(memoKey);
551
+ if (memoHit) return memoHit;
540
552
  const useUnicode = opts.unicode !== false;
541
553
  let source: string[];
542
554
  if (opts.grand) {
@@ -549,7 +561,8 @@ export function renderDnaClaw(opts: {
549
561
  const width = Math.max(0, ...source.map(l => l.length));
550
562
 
551
563
  if (opts.cols !== undefined && opts.cols < width) {
552
- return [];
564
+ dnaClawMemo.set(memoKey, EMPTY_DNA_FRAME);
565
+ return EMPTY_DNA_FRAME;
553
566
  }
554
567
 
555
568
  const phase = opts.phase ?? 0;
@@ -557,13 +570,20 @@ export function renderDnaClaw(opts: {
557
570
  const colorLevel = opts.colorLevel ?? ColorLevel.TrueColor;
558
571
  const palette = DNA_FLOW_PALETTE;
559
572
 
560
- return source.map((line, idx) => {
573
+ const result = source.map((line, idx) => {
561
574
  const padded = line.length < width ? line + " ".repeat(width - line.length) : line;
562
575
  if (!useColor || colorLevel < ColorLevel.TrueColor) {
563
576
  return padded;
564
577
  }
565
578
  return animatedGradientText(padded, palette, phase + idx * 0.07, { colorLevel });
566
579
  });
580
+
581
+ if (dnaClawMemo.size >= DNA_CLAW_MEMO_CAP) {
582
+ const oldest = dnaClawMemo.keys().next().value;
583
+ if (oldest !== undefined) dnaClawMemo.delete(oldest);
584
+ }
585
+ dnaClawMemo.set(memoKey, result);
586
+ return result;
567
587
  }
568
588
 
569
589
  /** The DNA Claw identity palette (emerald → cyan → violet helix flow). Shared by
@@ -1,5 +1,5 @@
1
- <!-- Parent: ../../AGENTS.md -->
2
- <!-- Generated: 2026-06-11 | Updated: 2026-06-11 -->
1
+ <!-- Parent: ../AGENTS.md -->
2
+ <!-- Generated: 2026-06-11 | Updated: 2026-06-14 -->
3
3
 
4
4
  # monitoring
5
5
 
@@ -26,6 +26,11 @@ Specialized HUD views and sovereign monitoring interfaces.
26
26
  *(None)*
27
27
 
28
28
  ## Dependencies
29
- *(None)*
29
+
30
+ ### Internal
31
+ {References to other parts of the codebase this depends on}
32
+
33
+ ### External
34
+ {Key external packages/libraries used}
30
35
 
31
36
  <!-- MANUAL: -->
@@ -134,20 +134,10 @@ export class Renderer {
134
134
  .map((line, i, arr) => (i === arr.length - 1 && line === "" ? "" : toColumn(1) + clearLine() + line))
135
135
  .join("\n");
136
136
  let out = BEGIN_SYNC + body;
137
- // Eagerly EL-clear the old frame rows the inserted block did NOT cover, then hop
138
- // back to the row right below the insert (where the next render() anchors).
139
- // The geometry is provably safe HERE: when stale > 0 the body write never hit
140
- // the bottom margin (the old frame fit on screen and the insert is shorter), so
141
- // every stale row exists and cursor-down cannot clamp. Deferring this clear to
142
- // the next render() via coverRows walked PAST the bottom margin, where the
143
- // clamped cursor-down desynced the row bookkeeping — each subsequent frame then
144
- // painted one row higher, devouring the flushed scrollback content above (the
145
- // "truncated card" corruption).
146
- // Use the same occupancy measure the reserve block uses (max of prev.length and
147
- // coverRows). A reset() between frames drops prev but records coverRows; ignoring it
148
- // here left the old frame's lower rows uncleared and the cursor below the true
149
- // anchor, so the next render's cursorDown crossed the bottom margin and clamped —
150
- // the persistent off-by-one that duplicated the model bar.
137
+ // EL-clear the old frame rows the inserted block did NOT cover, then hop back to the
138
+ // row right below the insert (where the next render() anchors). occupied = max(prev,
139
+ // coverRows) matches the reserve block so a reset()->insertAbove() ordering still
140
+ // clears the old frame's lower rows (the off-by-one that duplicated the model bar).
151
141
  const occupied = Math.max(this.prev.length, this.coverRows);
152
142
  const stale = occupied - written;
153
143
  if (stale > 0) {
@@ -158,7 +148,7 @@ export class Renderer {
158
148
  }
159
149
  this.write(out);
160
150
  this.prev = [];
161
- this.coverRows = 0; // consumed: the frame below is now the single source of truth
151
+ this.coverRows = 0;
162
152
  }
163
153
 
164
154
  /** Clear the live frame. Inline (reserve) mode walks the known frame rows with
@@ -1,5 +1,5 @@
1
1
  <!-- Parent: ../AGENTS.md -->
2
- <!-- Generated: 2026-06-11 | Updated: 2026-06-11 -->
2
+ <!-- Generated: 2026-06-11 | Updated: 2026-06-14 -->
3
3
 
4
4
  # util
5
5
 
@@ -9,9 +9,11 @@ General utilities, helper functions, and shared types used across the applicatio
9
9
  ## Key Files
10
10
  | File | Description |
11
11
  |------|-------------|
12
- | `update-check.ts` | Async check for newer npm versions |
13
- | `retry.ts` | Rate-limit backoff and generic retry mechanisms |
12
+ | `clipboard-image.ts` | Brief description of purpose |
13
+ | `env.ts` | Brief description of purpose |
14
14
  | `provider-error.ts` | Error normalization helpers |
15
+ | `retry.ts` | Rate-limit backoff and generic retry mechanisms |
16
+ | `update-check.ts` | Async check for newer npm versions |
15
17
 
16
18
  ## Subdirectories
17
19
  *(None)*