jeo-code 0.6.32 → 0.6.33

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/CHANGELOG.md CHANGED
@@ -6,6 +6,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6
6
 
7
7
  The README mirrors the latest 5 entries — regenerate with `bun run changelog:sync`.
8
8
 
9
+ ## [0.6.33] - 2026-06-19
10
+ _A redesigned `jeo` forge mark — a hollow line-board crayfish/eyeglass emblem drawn as thick rounded-corner tubes (no letters, no DNA helix) — that now renders inside compact-scaled forge cards, plus a unified verification directive that adds gjc's test-quality contract, and a fresh `jeo --tmux` no-leak re-verification._
11
+
12
+ ### Changed
13
+ - **The forge mark is a hollow line-board emblem now.** `FORGE_MARK_ART`, its grand `FORGE_MARK_ART_GRAND` hero variant, the claw-snap blink frames (`FORGE_MARK_FRAMES`), and every ASCII fallback (`*_ASCII`) were redrawn as the `>-<` silhouette of two pincer CLAWS (집게) whose top arms bend inward toward a narrow central eyeglass-frame (안경태) BRIDGE — each stroke a thick rounded-corner tube (`╭╮╰╯` + `─│`, ASCII `.-'|`) so the shape reads as a heavy neon outline instead of a filled block. The old wordmark glyphs (`J E O`) and the `╳` DNA double-helix nodes are gone; every line stays width-1 and equal-width so the blue→violet→pink flow gradient and the padding/centering math are untouched.
14
+ - **Forge cards render at a compact reduced width.** New `FORGE_SCALE` (1.2) + `scaleForgeWidth(available)` in `forge.ts` divide the caller's available column run down to a compact panel width (floored at 24). `app.ts` routes both the inline `flushForgeCard` and the static forge summary through it, so a card reads as a contained panel instead of stretching edge-to-edge with a dead right margin.
15
+ - **One source for the done-time verification directive.** New `VERIFICATION_DIRECTIVE` constant in `engine.ts` replaces the string that was duplicated verbatim in `executorSystemPrompt`'s default and `launch.ts`'s interactive prompt. It folds in gjc's `<verification>` test-quality contract — written tests must exercise observable behavior, edge values, branch conditions, invariants, and error handling, never asserting defaults or tautologies — and `prompts/agents/executor.md` gains a matching constraint line.
16
+
17
+ ### Verified
18
+ - **No bun memory leak / slowdown.** `scripts/mem-probe.ts` drove 2000 realistic LaunchTui turns: post-GC heap returns to baseline (per-turn slope **−480 bytes/turn**, net +3.28 MB held flat), with `exit`/`resize`/`SIGINT` process-listener counts stable (no accumulation).
19
+ - **`jeo --tmux` live.** `scripts/tmux-verify.sh smoke` OK and `battery` **6/6 PASSED** (boot, `/help`, unknown `$skill` feedback, `/agents` roster, `$ultragoal` dispatch, unresolved `/command` report).
20
+ - **Green gates.** `bun run typecheck` clean; `bun test` **1710 pass / 0 fail** across 211 files.
21
+
9
22
  ## [0.6.32] - 2026-06-19
10
23
  _Anthropic extended thinking is actually enabled now — the request finally sends a `thinking` block (adaptive for Opus/Sonnet 4.6+, budget for older), fixing reasoning on **opus-4-8** — plus a multi-token `/command`·`$skill` trigger highlight that paints every invocation and survives the trailing space, and a fresh `jeo --tmux` no-leak re-verification._
11
24
 
package/README.ja.md CHANGED
@@ -200,11 +200,11 @@ CI は `.github/workflows/npm-publish.yml` で公開します — GitHub リリ
200
200
  ## 変更履歴 (Changelog)
201
201
 
202
202
  <!-- CHANGELOG:START (auto-generated from CHANGELOG.md — run `bun run changelog:sync`) -->
203
+ - **[0.6.33]** (2026-06-19) — A redesigned `jeo` forge mark — a hollow line-board crayfish/eyeglass emblem drawn as thick rounded-corner tubes (no letters, no DNA helix) — that now renders inside compact-scaled forge cards, plus a unified verification directive that adds gjc's test-quality contract, and a fresh `jeo --tmux` no-leak re-verification.
203
204
  - **[0.6.32]** (2026-06-19) — Anthropic extended thinking is actually enabled now — the request finally sends a `thinking` block (adaptive for Opus/Sonnet 4.6+, budget for older), fixing reasoning on **opus-4-8** — plus a multi-token `/command`·`$skill` trigger highlight that paints every invocation and survives the trailing space, and a fresh `jeo --tmux` no-leak re-verification.
204
205
  - **[0.6.31]** (2026-06-19) — Live "Thinking" indicator for signature-only reasoning models (Anthropic opus-4-7/4-8), a live color cue when a `/command` or `$skill` trigger is recognized in the prompt, and a rich gjc-style `/resume` session picker — plus a fresh `jeo --tmux` no-leak re-verification.
205
206
  - **[0.6.30]** (2026-06-19) — gjc-style intermediate-judgment guard classification extracted from the engine loop, plus a re-verification that `jeo --tmux` does not leak bun memory or slow down.
206
207
  - **[0.6.29]** (2026-06-19) — Signature-only thinking-block replay (Anthropic opus-4-7/4-8), plus a tmux mouse-flood memory guard confirming `jeo --tmux` does not leak.
207
- - **[0.6.28]** (2026-06-19) — Signed thinking-block replay: native reasoning is now sent BACK to providers across steps/turns, restoring multi-step reasoning continuity (gajae parity).
208
208
 
209
209
  See [CHANGELOG.md](CHANGELOG.md) for the full history.
210
210
  <!-- CHANGELOG:END -->
package/README.ko.md CHANGED
@@ -200,11 +200,11 @@ CI는 `.github/workflows/npm-publish.yml`로 배포합니다 — GitHub 릴리
200
200
  ## 변경 이력 (Changelog)
201
201
 
202
202
  <!-- CHANGELOG:START (auto-generated from CHANGELOG.md — run `bun run changelog:sync`) -->
203
+ - **[0.6.33]** (2026-06-19) — A redesigned `jeo` forge mark — a hollow line-board crayfish/eyeglass emblem drawn as thick rounded-corner tubes (no letters, no DNA helix) — that now renders inside compact-scaled forge cards, plus a unified verification directive that adds gjc's test-quality contract, and a fresh `jeo --tmux` no-leak re-verification.
203
204
  - **[0.6.32]** (2026-06-19) — Anthropic extended thinking is actually enabled now — the request finally sends a `thinking` block (adaptive for Opus/Sonnet 4.6+, budget for older), fixing reasoning on **opus-4-8** — plus a multi-token `/command`·`$skill` trigger highlight that paints every invocation and survives the trailing space, and a fresh `jeo --tmux` no-leak re-verification.
204
205
  - **[0.6.31]** (2026-06-19) — Live "Thinking" indicator for signature-only reasoning models (Anthropic opus-4-7/4-8), a live color cue when a `/command` or `$skill` trigger is recognized in the prompt, and a rich gjc-style `/resume` session picker — plus a fresh `jeo --tmux` no-leak re-verification.
205
206
  - **[0.6.30]** (2026-06-19) — gjc-style intermediate-judgment guard classification extracted from the engine loop, plus a re-verification that `jeo --tmux` does not leak bun memory or slow down.
206
207
  - **[0.6.29]** (2026-06-19) — Signature-only thinking-block replay (Anthropic opus-4-7/4-8), plus a tmux mouse-flood memory guard confirming `jeo --tmux` does not leak.
207
- - **[0.6.28]** (2026-06-19) — Signed thinking-block replay: native reasoning is now sent BACK to providers across steps/turns, restoring multi-step reasoning continuity (gajae parity).
208
208
 
209
209
  See [CHANGELOG.md](CHANGELOG.md) for the full history.
210
210
  <!-- CHANGELOG:END -->
package/README.md CHANGED
@@ -200,11 +200,11 @@ Required npm token permissions (repository secret `NPM_TOKEN`):
200
200
  ## Changelog
201
201
 
202
202
  <!-- CHANGELOG:START (auto-generated from CHANGELOG.md — run `bun run changelog:sync`) -->
203
+ - **[0.6.33]** (2026-06-19) — A redesigned `jeo` forge mark — a hollow line-board crayfish/eyeglass emblem drawn as thick rounded-corner tubes (no letters, no DNA helix) — that now renders inside compact-scaled forge cards, plus a unified verification directive that adds gjc's test-quality contract, and a fresh `jeo --tmux` no-leak re-verification.
203
204
  - **[0.6.32]** (2026-06-19) — Anthropic extended thinking is actually enabled now — the request finally sends a `thinking` block (adaptive for Opus/Sonnet 4.6+, budget for older), fixing reasoning on **opus-4-8** — plus a multi-token `/command`·`$skill` trigger highlight that paints every invocation and survives the trailing space, and a fresh `jeo --tmux` no-leak re-verification.
204
205
  - **[0.6.31]** (2026-06-19) — Live "Thinking" indicator for signature-only reasoning models (Anthropic opus-4-7/4-8), a live color cue when a `/command` or `$skill` trigger is recognized in the prompt, and a rich gjc-style `/resume` session picker — plus a fresh `jeo --tmux` no-leak re-verification.
205
206
  - **[0.6.30]** (2026-06-19) — gjc-style intermediate-judgment guard classification extracted from the engine loop, plus a re-verification that `jeo --tmux` does not leak bun memory or slow down.
206
207
  - **[0.6.29]** (2026-06-19) — Signature-only thinking-block replay (Anthropic opus-4-7/4-8), plus a tmux mouse-flood memory guard confirming `jeo --tmux` does not leak.
207
- - **[0.6.28]** (2026-06-19) — Signed thinking-block replay: native reasoning is now sent BACK to providers across steps/turns, restoring multi-step reasoning continuity (gajae parity).
208
208
 
209
209
  See [CHANGELOG.md](CHANGELOG.md) for the full history.
210
210
  <!-- CHANGELOG:END -->
package/README.zh.md CHANGED
@@ -200,11 +200,11 @@ CI 通过 `.github/workflows/npm-publish.yml` 发布 — GitHub 发布 release
200
200
  ## 更新日志 (Changelog)
201
201
 
202
202
  <!-- CHANGELOG:START (auto-generated from CHANGELOG.md — run `bun run changelog:sync`) -->
203
+ - **[0.6.33]** (2026-06-19) — A redesigned `jeo` forge mark — a hollow line-board crayfish/eyeglass emblem drawn as thick rounded-corner tubes (no letters, no DNA helix) — that now renders inside compact-scaled forge cards, plus a unified verification directive that adds gjc's test-quality contract, and a fresh `jeo --tmux` no-leak re-verification.
203
204
  - **[0.6.32]** (2026-06-19) — Anthropic extended thinking is actually enabled now — the request finally sends a `thinking` block (adaptive for Opus/Sonnet 4.6+, budget for older), fixing reasoning on **opus-4-8** — plus a multi-token `/command`·`$skill` trigger highlight that paints every invocation and survives the trailing space, and a fresh `jeo --tmux` no-leak re-verification.
204
205
  - **[0.6.31]** (2026-06-19) — Live "Thinking" indicator for signature-only reasoning models (Anthropic opus-4-7/4-8), a live color cue when a `/command` or `$skill` trigger is recognized in the prompt, and a rich gjc-style `/resume` session picker — plus a fresh `jeo --tmux` no-leak re-verification.
205
206
  - **[0.6.30]** (2026-06-19) — gjc-style intermediate-judgment guard classification extracted from the engine loop, plus a re-verification that `jeo --tmux` does not leak bun memory or slow down.
206
207
  - **[0.6.29]** (2026-06-19) — Signature-only thinking-block replay (Anthropic opus-4-7/4-8), plus a tmux mouse-flood memory guard confirming `jeo --tmux` does not leak.
207
- - **[0.6.28]** (2026-06-19) — Signed thinking-block replay: native reasoning is now sent BACK to providers across steps/turns, restoring multi-step reasoning continuity (gajae parity).
208
208
 
209
209
  See [CHANGELOG.md](CHANGELOG.md) for the full history.
210
210
  <!-- CHANGELOG:END -->
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jeo-code",
3
- "version": "0.6.32",
3
+ "version": "0.6.33",
4
4
  "description": "Clean, highly optimized AI coding agent using spec-first loop",
5
5
  "type": "module",
6
6
  "main": "src/cli.ts",
@@ -164,10 +164,18 @@ export const OUTPUT_DISCIPLINE = [
164
164
  "- Match reply length to the task: a one-line change gets a one-line report.",
165
165
  ].join("\n");
166
166
 
167
+ /** gjc-inherited verification directive (plan/gjc-inheritance.md, round 16): the
168
+ * done self-check PLUS gjc's `<verification>` test-quality contract — what makes a
169
+ * test worth writing. Single source consumed by both executorSystemPrompt's default
170
+ * and launch.ts's interactive prompt (was duplicated verbatim in both). */
171
+ export const VERIFICATION_DIRECTIVE =
172
+ "Before calling done, self-check: did I run the test or command that exercises this change, are directly-affected callsites/tests/docs updated, and does my claim match real output? If any answer is no, keep working — do not call done. " +
173
+ "When you write tests, exercise observable behavior, edge values, branch conditions, invariants, and error handling — never assert defaults or tautologies.";
174
+
167
175
  export function executorSystemPrompt(
168
176
  role = "Executor Agent, a senior software developer",
169
177
  protocol: string = TOOL_PROTOCOL,
170
- verificationDirective = "Before calling done, self-check: did I run the test or command that exercises this change, are directly-affected callsites/tests/docs updated, and does my claim match real output? If any answer is no, keep working — do not call done.",
178
+ verificationDirective = VERIFICATION_DIRECTIVE,
171
179
  ): string {
172
180
  return (
173
181
  `You are the ${role}.\n` +
@@ -1,7 +1,7 @@
1
1
  import { createInterface } from "node:readline/promises";
2
2
  import { emitKeypressEvents } from "node:readline";
3
3
  import { PassThrough } from "node:stream";
4
- import { runAgentLoop, DEFAULT_TOOLS, TOOL_PROTOCOL, WORKING_DISCIPLINE, OUTPUT_DISCIPLINE, type AgentLoopEvents } from "../agent/engine";
4
+ import { runAgentLoop, DEFAULT_TOOLS, TOOL_PROTOCOL, WORKING_DISCIPLINE, OUTPUT_DISCIPLINE, VERIFICATION_DIRECTIVE, type AgentLoopEvents } from "../agent/engine";
5
5
  import { createOpikTracer, wrapEvents } from "../agent/opik-tracer";
6
6
  import { initialDynamicStepLimit } from "../agent/step-budget";
7
7
  import { memoryPromptSection, spawnDetachedDistill } from "../agent/memory";
@@ -15,7 +15,7 @@ import { runRalplanEngine, type RalplanEngineOptions } from "./ralplan";
15
15
  import { runTeamEngine, type TeamEngineOptions } from "./team";
16
16
  import { runUltragoalEngine, type UltragoalEngineOptions } from "./ultragoal";
17
17
  import { skillsPromptSection, loadSkills, buildSkillTask, workflowSkillsForPrompt, parseSkillInvocation, parseSkillChain, looksLikeSkillEcho, skillInvocationCard, type SkillDoc, type SkillInvocation } from "../skills/catalog";
18
- import { formatForgeBox } from "../tui/components/forge";
18
+ import { formatForgeBox, scaleForgeWidth } from "../tui/components/forge";
19
19
  import { interactiveOAuthLogin } from "./auth";
20
20
  import { logoutOAuth, OAUTH_PROVIDERS, API_KEY_ONLY_PROVIDERS, setApiKey } from "../auth";
21
21
  import type { AuthProvider } from "../auth";
@@ -470,7 +470,7 @@ export async function runLaunchCommand(args: string[]): Promise<void> {
470
470
  preamble + "\n\n" + protocol + "\n\n" +
471
471
  WORKING_DISCIPLINE + "\n\n" +
472
472
  OUTPUT_DISCIPLINE + "\n\n" +
473
- "Before calling done, self-check: did I run the test or command that exercises this change, are directly-affected callsites/tests/docs updated, and does my claim match real output? If any answer is no, keep working — do not call done." +
473
+ VERIFICATION_DIRECTIVE +
474
474
  "\nWhen you have finished the user's request, or need to reply to or ask the user something, call done with {\"reason\": <your natural-language reply to the user>}. The reason text is shown to the user as your message." +
475
475
  (allowedTools.has("task") ? "\n\nDelegation: " + taskToolProtocolLine(cfg) +
476
476
  " Call task with {\"role\": <one of the advertised roles>, \"task\": <assignment>, \"context\": <optional>} to hand a focused slice to a subagent." : "") +
@@ -1194,7 +1194,7 @@ export async function runLaunchCommand(args: string[]): Promise<void> {
1194
1194
  {
1195
1195
  const card = formatForgeBox(
1196
1196
  { title: "[skill]", lines: skillInvocationCard(skill, intent) },
1197
- { width: Math.min(100, Math.max(40, (process.stdout.columns ?? 80) - 2)), unicode: supportsUnicode(), paint: accentPaint(uiTheme), paintShadow: accentShadowPaint(uiTheme), color: uiTheme.color },
1197
+ { width: scaleForgeWidth(Math.min(100, Math.max(40, (process.stdout.columns ?? 80) - 2))), unicode: supportsUnicode(), paint: accentPaint(uiTheme), paintShadow: accentShadowPaint(uiTheme), color: uiTheme.color },
1198
1198
  );
1199
1199
  logLines(card);
1200
1200
  }
@@ -10,6 +10,7 @@ Turn a bounded task into a working, verified outcome with the smallest correct c
10
10
  - Keep diffs small and aligned to existing patterns.
11
11
  - Do not broaden scope or invent abstractions unless the task requires them.
12
12
  - Verify the task before calling done.
13
+ - When you add tests, exercise observable behavior, edge values, branch conditions, invariants, and error handling — never assert defaults or tautologies.
13
14
  - Communicate the result through `done.reason` using the required output contract.
14
15
  </constraints>
15
16
 
package/src/tui/app.ts CHANGED
@@ -24,7 +24,7 @@ import { centerBlock, padLineTo, boxBlock, BOX_ASCII, BOX_UNICODE } from "./comp
24
24
  import { SECTION_GAP, sectionLabel, stackSections } from "./components/section";
25
25
  import { resolveTheme, themeGradient, accentPaint, accentShadowPaint, diffPaint, mutedPaint, cardFillPaint } from "./components/themes";
26
26
  import { detectColorLevel, animatedGradientText, ColorLevel } from "./components/color";
27
- import { formatForgeBox, summarizeForgeInvocation, summarizeForgeResult, fitForgeBoxes, webSearchCardLines, type ForgeSummary } from "./components/forge";
27
+ import { formatForgeBox, summarizeForgeInvocation, summarizeForgeResult, fitForgeBoxes, webSearchCardLines, scaleForgeWidth, type ForgeSummary } from "./components/forge";
28
28
  import { renderStatusBar, renderStatusBox, type StatusBoxData } from "./components/status";
29
29
  import { costForUsage } from "../ai/pricing";
30
30
  import { renderMarkdownTables } from "./components/markdown-table";
@@ -1206,7 +1206,7 @@ export class LaunchTui {
1206
1206
  * Non-inline modes keep the card in `forgeSummaries` for the final static summary. */
1207
1207
  private flushForgeCard(summary: ForgeSummary, success?: boolean): void {
1208
1208
  if (!this.inline || this.finished) return;
1209
- const width = Math.max(24, size().cols - 1);
1209
+ const width = scaleForgeWidth(size().cols - 1);
1210
1210
  // gjc D2 (state-encoded border): a FAILED card gets a red border so it pops
1211
1211
  // out of scrollback at a glance; OK/neutral cards keep the theme accent
1212
1212
  // identity. The ✓/✗ title mark already encodes state, but the border tone
@@ -1235,10 +1235,9 @@ export class LaunchTui {
1235
1235
  anim?: { phase: number; colorLevel: ColorLevel; beat: string },
1236
1236
  dim = false,
1237
1237
  ): string[] {
1238
- const floor = Math.min(24, width);
1239
- // Fill the available width so an in-frame box does not leave a dead right-margin
1240
- // column inside the outer panel.
1241
- const boxWidth = Math.max(floor, width);
1238
+ // Forge cards render at a reduced (÷FORGE_SCALE) compact width rather than
1239
+ // spanning the full available column run.
1240
+ const boxWidth = scaleForgeWidth(width);
1242
1241
  const paint = this.theme.color ? accentPaint(this.theme) : (s: string) => s;
1243
1242
  const lines: string[] = [];
1244
1243
  for (const [i, summary] of this.forgeSummaries.slice(-maxEntries).entries()) {
@@ -412,46 +412,61 @@ export async function animateFrames(stage: AsciiStage, opts: AnimateFramesOption
412
412
  }
413
413
  return total;
414
414
  }
415
- /** The compact jeo forge mark: a symmetrical crayfish (가재) brand emblem composed
416
- * of SIMPLE, DISCONNECTED shapes (no connecting strokes) that highlight the signature
417
- * pincer CLAWS (집게) flanking the sides (◤◣ and on the left, ◥◢ and ❯ on the right),
418
- * the body carrying the JEO wordmark (J E O), and a DNA double-helix woven above and
419
- * below as a row of crossing nodes (╳ = base-pair crossings). gjc-forge aesthetic:
420
- * clean negative space, geometric symmetry, the blue→violet→pink flow gradient applied
421
- * by renderForgeMark doing the neon glow. Width-1 glyphs only (box drawing + geometrics)
422
- * so padding/centering math stays exact. Frame 0 is the static symbol. */
415
+ /** The compact jeo forge mark: a symmetrical crayfish (가재) brand emblem drawn as a
416
+ * 2.5×-thick LINE-BOARD (hollow outline, no fill) the `>-<` silhouette of two pincer
417
+ * CLAWS (집게) whose top arms bend (꺾임) inward toward a narrow central BRIDGE (the
418
+ * eyeglass-frame / 안경태 bar). Every stroke is rendered as a thick rounded-corner tube
419
+ * (╭╮╰╯ + ─│) so the shape reads as a heavy neon outline, not a filled block. No letters.
420
+ * Width-1 glyphs only (box drawing) so padding/centering math stays exact, and the
421
+ * blue→violet→pink flow gradient from renderForgeMark supplies the neon glow. Frame 0 is
422
+ * the static symbol. */
423
423
  export const FORGE_MARK_ART: string[] = [
424
- "◤ ╳ ╳ ╳ ╳ ◥",
425
- "❮ J E O ❯",
426
- " ╳ ╳ "
424
+ "╭─────╮ ╭─────╮",
425
+ "│ │ │ │",
426
+ "╰─╮ ╭─────────╮ ╭─╯",
427
+ " │ │ │ │ │ │ ",
428
+ "╭─╯ ╭─╯ ╰─────────╯ ╰─╮ ╰─╮",
429
+ "│ │ │ │",
430
+ "╰───╯ ╰───╯"
427
431
  ];
428
432
 
429
433
  export const FORGE_MARK_ART_ASCII: string[] = [
430
- "/ x x x x \\",
431
- "< J E O >",
432
- "\\ x x x x /"
434
+ ".-----. .-----.",
435
+ "| | | |",
436
+ "'-. | .---------. | .-'",
437
+ " | | | | | | ",
438
+ ".-' .-' '---------' '-. '-.",
439
+ "| | | |",
440
+ "'---' '---'"
433
441
  ];
434
442
 
435
- /** Claw-snap blink frames for the compact lobster forge mark: the helix nodes, the
436
- * JEO body and the inner claw/tail glyphs stay fixed while the four splayed pincer
437
- * CORNERS snap (◤◣ / ◥◢ open ◢◥ / ◣◤ closed), so the lobster "clicks" its claws.
438
- * Frame 0 === FORGE_MARK_ART, so a frameless render is byte-identical to the static
443
+ /** Claw-snap blink frames for the compact lobster forge mark: the central bridge stays
444
+ * fixed while the four pincer arms snap (open clenched), so the lobster "clicks" its
445
+ * claws. Frame 0 === FORGE_MARK_ART, so a frameless render is byte-identical to the static
439
446
  * symbol. All lines share the same width and width-1 glyphs. */
440
447
  export const FORGE_MARK_FRAMES: string[][] = [
441
448
  FORGE_MARK_ART,
442
449
  [
443
- "◢ ╳ ╳ ╳ ╳ ◣",
444
- "❮ J E O ❯",
445
- "◥ ╳ ╳ ◤"
450
+ "╭───╮ ╭───╮",
451
+ "│ │ │ │",
452
+ "╰─╮ ╰─╮ ╭─────────╮ ╭─╯ ╭─╯",
453
+ " │ │ │ │ │ │ ",
454
+ "╭─╯ │ ╰─────────╯ │ ╰─╮",
455
+ "│ │ │ │",
456
+ "╰─────╯ ╰─────╯"
446
457
  ]
447
458
  ];
448
459
 
449
460
  export const FORGE_MARK_FRAMES_ASCII: string[][] = [
450
461
  FORGE_MARK_ART_ASCII,
451
462
  [
452
- "\\ x x x x /",
453
- "< J E O >",
454
- "/ x x x x \\"
463
+ ".---. .---.",
464
+ "| | | |",
465
+ "'-. '-. .---------. .-' .-'",
466
+ " | | | | | | ",
467
+ ".-' | '---------' | '-.",
468
+ "| | | |",
469
+ "'-----' '-----'"
455
470
  ]
456
471
  ];
457
472
 
@@ -461,23 +476,34 @@ export function forgeMarkFrameCount(): number {
461
476
  }
462
477
 
463
478
  /** Grand hero variant for the welcome forge box (gjc-style spacious banner): the same
464
- * symmetrical crayfish emblem rendered large — the splayed pincer claws as corner wedges
465
- * (◤◣ left, ◥◢ right) and heavy brackets ( left, ❯ right), the JEO wordmark spaced
466
- * across the body (J E O), and the DNA double-helix woven above and below as a wider
467
- * row of crossing nodes (╳). gjc-forge aesthetic: generous negative space + geometric
468
- * symmetry, with renderForgeMark's blue→violet→pink flow gradient supplying the neon glow.
469
- * Width 29 (matches the welcome compact↔grand threshold) and width-1 glyphs only so
470
- * padding/centering math stays exact. */
479
+ * crayfish line-board emblem rendered large — the pincer claws and central eyeglass
480
+ * bridge drawn as wider 3×-thick rounded outline tubes (╭╮╰╯ + ─│), no fill, no letters.
481
+ * Width-1 glyphs only so padding/centering math stays exact, with renderForgeMark's
482
+ * blue→violet→pink flow gradient supplying the neon glow. */
471
483
  export const FORGE_MARK_ART_GRAND: string[] = [
472
- "◤ ╳ ╳ ╳ ╳ ╳ ╳ ◥",
473
- "❮ J E O ❯",
474
- " ╳ ╳ ╳ ╳ ╳ ╳ "
484
+ "╭────────╮ ╭────────╮",
485
+ "│ │ │ │",
486
+ " │ │ ",
487
+ "╰──╮ │ ╭──────────────╮ │ ╭──╯",
488
+ " │ │ │ │ │ │ ",
489
+ " │ │ │ │ │ │ ",
490
+ "╭──╯ ╭──╯ ╰──────────────╯ ╰──╮ ╰──╮",
491
+ "│ │ │ │",
492
+ "│ │ │ │",
493
+ "╰─────╯ ╰─────╯"
475
494
  ];
476
495
 
477
496
  export const FORGE_MARK_ART_GRAND_ASCII: string[] = [
478
- "/ x x x x x x \\",
479
- "< J E O >",
480
- "\\ x x x x x x /"
497
+ ".--------. .--------.",
498
+ "| | | |",
499
+ "| | | |",
500
+ "'--. | .--------------. | .--'",
501
+ " | | | | | | ",
502
+ " | | | | | | ",
503
+ ".--' .--' '--------------' '--. '--.",
504
+ "| | | |",
505
+ "| | | |",
506
+ "'-----' '-----'"
481
507
  ];
482
508
 
483
509
  // Bounded memo of fully-rendered forge-mark frames keyed by every input that affects
@@ -479,6 +479,15 @@ export function fitForgeBoxes(lines: string[], budget: number): string[] {
479
479
  return out;
480
480
  }
481
481
 
482
+ /** Forge cards render at a reduced scale: the available width is divided by this
483
+ * factor so a box reads as a compact panel instead of spanning the full terminal. */
484
+ export const FORGE_SCALE = 1.2;
485
+
486
+ /** Scale a caller's available width down to the forge card's compact render width. */
487
+ export function scaleForgeWidth(available: number): number {
488
+ return Math.max(24, Math.trunc(available / FORGE_SCALE));
489
+ }
490
+
482
491
  export function formatForgeBox(summary: ForgeSummary, opts: ForgeBoxOptions = {}): string[] {
483
492
  const innerWidth = opts.width ?? 80;
484
493
  const floor = Math.min(24, innerWidth);