// All screen renderers. Each is a small functional component that
// emits the body of a <Term>. Variant prop is read via context only —
// screens authored once render correctly across color/mono/ascii.

// ─────────────────────────────────────────────────────────────────
// 1. WORKED EXAMPLE — Welcome / Banner (the foundation contract)
// ─────────────────────────────────────────────────────────────────

function WelcomeScreen() {
  return (
    <>
      <Banner />
      <L><Yb>  Spec-Driven Development Framework</Yb>  <Gr>v3.0.0</Gr></L>
      <Blank />
      <L><Gr>  Zero technical debt. AI-powered quality gates.</Gr></L>
      <Blank />
      <L><Cyb><Sym n="question" /> Where do you want to install?</Cyb></L>
      <L>   <Dm>(default: ./my-app)</Dm></L>
      <L><Cy>{' '}</Cy><Caret /></L>
      <Blank />
      <Footer step={1} label="Welcome" />
    </>
  );
}

// ─────────────────────────────────────────────────────────────────
// 2. COMPONENT INVENTORY — Messages
// ─────────────────────────────────────────────────────────────────

function InventoryMessages() {
  return (
    <>
      <L><Dm># Messages — single-line semantic output</Dm></L>
      <Blank />
      <L><G><Sym n="success" /> Installed 87 agents into .claude/agents</G></L>
      <Blank />
      <L><Y><Sym n="warning" /> CLAUDE.md exists; will prepend marker</Y></L>
      <L>   <Dm>Existing content preserved below the marker.</Dm></L>
      <Blank />
      <L><R><Sym n="error" /> </R><Rb>E_PYTHON_MISSING</Rb></L>
      <L><R>   Python 3.10+ is required for the python-cli component.</R></L>
      <L>   <Dm>Hint: install Python 3.10+ or pass --skip-python.</Dm></L>
      <L>   <Dm>Details: docs/guides/TROUBLESHOOTING.md#python-missing</Dm></L>
      <Blank />
      <L><Gr><Sym n="info" /> Using NPM registry as update authority</Gr></L>
      <Blank />
      <L><Dm><Sym n="skipped" /> python-cli           --skip-python</Dm></L>
    </>
  );
}

// ─────────────────────────────────────────────────────────────────
// 3. COMPONENT INVENTORY — Prompts
// ─────────────────────────────────────────────────────────────────

function InventoryPrompts() {
  return (
    <>
      <L><Dm># Prompts — one inquirer primitive per screen</Dm></L>
      <Blank />
      <L><Cyb><Sym n="question" /> Project name:</Cyb> <Dm>(my-app)</Dm> <Caret /></L>
      <Blank />
      <L><Cyb><Sym n="question" /> Install pre-commit hook?</Cyb> <Dm>(Y/n)</Dm></L>
      <Blank />
      <L><Cyb><Sym n="question" /> Choose update channel:</Cyb></L>
      <L>  <Cy><Sym n="cursor" /> <Cy>stable</Cy></Cy>   <Dm><Dash /> production (npm @latest)</Dm></L>
      <L>    <Gr>beta</Gr>     <Mb>•</Mb> <Dm>pre-release (npm @beta)</Dm></L>
      <L>    <Gr>edge</Gr>     <Mb>•</Mb> <Dm>bleeding edge (github:main)</Dm></L>
      <Blank />
      <L><Cyb><Sym n="question" /> Select components to install:</Cyb></L>
      <L>  <Cy><Sym n="cursor" /></Cy> <G><Sym n="check_on" /></G> core-framework   <Dm>(required)</Dm></L>
      <L>    <G><Sym n="check_on" /></G> agents</L>
      <L>    <G><Sym n="check_on" /></G> skills</L>
      <L>    <Tone><Sym n="check_off" /></Tone> hooks</L>
      <L>    <Tone><Sym n="check_off" /></Tone> python-cli       <Dm>(needs Python 3.10+)</Dm></L>
    </>
  );
}

// ─────────────────────────────────────────────────────────────────
// 4. COMPONENT INVENTORY — Indicators
// ─────────────────────────────────────────────────────────────────

function InventoryIndicators() {
  return (
    <>
      <L><Dm># Indicators — ora spinner, cli-progress bar, panel</Dm></L>
      <Blank />
      <L><Cy><Spinner /></Cy> <Cy>Copying 87 agent files...</Cy></L>
      <Blank />
      <L><Bar pct={64} /> <Wh>64%</Wh> <Gr>| 142/220 | tree.json</Gr></L>
      <Blank />
      <L><Gr>┌─ Detected installation </Gr><Gr>─────────────────────────────────────────────┐</Gr></L>
      <L><Gr>│</Gr>  Version           <B>v2.0.0</B>                                          <Gr>│</Gr></L>
      <L><Gr>│</Gr>  Channel           <B>stable</B>                                          <Gr>│</Gr></L>
      <L><Gr>│</Gr>  Manifest schema   <B>1</B> <Y>(will migrate to 2)</Y>                          <Gr>│</Gr></L>
      <L><Gr>└──────────────────────────────────────────────────────────────────┘</Gr></L>
      <Blank />
      <L><Dm># Diff / drift markers (ASCII only — round-trips through patch)</Dm></L>
      <Blank />
      <L>   <Y>~</Y> .claude/settings.json       <Dm>(merged — 3 keys added)</Dm></L>
      <L>   <G>+</G> .claude/hooks/pre-context.sh</L>
      <L>   <R>-</R> .claude/hooks/legacy.sh</L>
      <L>   <Rb>!</Rb> CLAUDE.md                   <Dm>(conflict — see hint)</Dm></L>
    </>
  );
}

// ─────────────────────────────────────────────────────────────────
// 5. INTERACTION — Sequential flow (mid-wizard)
// ─────────────────────────────────────────────────────────────────

function SequentialFlow() {
  return (
    <>
      <L><Dm>Install directory:</Dm>   <B>./my-app</B></L>
      <L><Dm>Project name:</Dm>        <B>my-app</B></L>
      <L><Dm>Update channel:</Dm>      <B>stable</B></L>
      <Blank />
      <L><Cyb><Sym n="question" /> Select components to install:</Cyb></L>
      <L>  <Cy><Sym n="cursor" /></Cy> <G><Sym n="check_on" /></G> core-framework   <Dm>(required)</Dm></L>
      <L>    <G><Sym n="check_on" /></G> agents</L>
      <L>    <G><Sym n="check_on" /></G> skills</L>
      <L>    <G><Sym n="check_on" /></G> commands</L>
      <L>    <Tone><Sym n="check_off" /></Tone> hooks</L>
      <L>    <Tone><Sym n="check_off" /></Tone> python-cli       <Dm>(needs Python 3.10+)</Dm></L>
      <Blank />
      <L><Dm>  (space to toggle · a to toggle all · enter to confirm)</Dm></L>
      <Blank />
      <Footer step={4} label="Component Selection" />
    </>
  );
}

// ─────────────────────────────────────────────────────────────────
// 6. INTERACTION — Validation retry
// ─────────────────────────────────────────────────────────────────

function ValidationRetry() {
  return (
    <>
      <L><Cyb><Sym n="question" /> Project name:</Cyb> foo bar</L>
      <L>   <R>&gt;&gt; Project name must be a valid npm package name.</R></L>
      <Blank />
      <L><Cyb><Sym n="question" /> Project name:</Cyb> 1-invalid</L>
      <L>   <R>&gt;&gt; Project name must start with a letter.</R></L>
      <Blank />
      <L><Cyb><Sym n="question" /> Project name:</Cyb> <Caret /></L>
      <L>   <Dm>(2 attempts left — exit 2 on the third)</Dm></L>
      <Blank />
      <Footer step={2} label="Project Name" />
    </>
  );
}

// ─────────────────────────────────────────────────────────────────
// 7. INTERACTION — SIGINT arm
// ─────────────────────────────────────────────────────────────────

function SigintArm() {
  return (
    <>
      <L><G><Sym n="success" /> core-framework      142 files</G></L>
      <L><G><Sym n="success" /> agents               87 files</G></L>
      <L><Cy><Spinner /></Cy> <Cy>Copying skills... </Cy><Dm>(45 / 142)</Dm></L>
      <L><R>^C</R></L>
      <Blank />
      <L><Y><Sym n="warning" /> Press Ctrl-C again within 3s to cancel</Y></L>
      <L>   <Dm>(or any key to resume)</Dm></L>
      <Blank />
      <L><Dm>  3 ... 2 ... 1 ...</Dm></L>
      <Blank />
      <Footer step={6} label="File Copy" />
    </>
  );
}

// ─────────────────────────────────────────────────────────────────
// 8. INTERACTION — Confirm gate (destructive)
// ─────────────────────────────────────────────────────────────────

function ConfirmGate() {
  return (
    <>
      <L><Gr>┌─ Confirm channel switch </Gr><Gr>─────────────────────────────────────────────┐</Gr></L>
      <L><Gr>│</Gr>  Current   <Mb>beta</Mb>    <B>v3.1.0-beta.4</B>                                  <Gr>│</Gr></L>
      <L><Gr>│</Gr>  Target    <B>stable</B>  <B>v3.0.5</B>                                          <Gr>│</Gr></L>
      <L><Gr>│</Gr>                                                                  <Gr>│</Gr></L>
      <L><Gr>│</Gr>  <Y><Sym n="warning" /> </Y><Y>This is a downgrade.</Y>                                          <Gr>│</Gr></L>
      <L><Gr>│</Gr>  <Dm>Your .venv/ will be rebuilt.</Dm>                                    <Gr>│</Gr></L>
      <L><Gr>│</Gr>  <Dm>3 components will be downgraded; 1 added; 0 removed.</Dm>            <Gr>│</Gr></L>
      <L><Gr>└──────────────────────────────────────────────────────────────────┘</Gr></L>
      <Blank />
      <L><Cyb><Sym n="question" /> Proceed with downgrade?</Cyb> <Dm>(y/N)</Dm> <Caret /></L>
      <Blank />
      <Footer step={5} label="Channel Switch" />
    </>
  );
}

// ─────────────────────────────────────────────────────────────────
// 9. STATE PATTERNS — all 7 states
// ─────────────────────────────────────────────────────────────────

function StatePatterns() {
  return (
    <>
      <L><Dm># State patterns — fixed visual per state, every component</Dm></L>
      <Blank />
      <L>  <Tone><Sym n="check_off" /></Tone>  <Tone>pending</Tone>          <Dm>known, not started</Dm></L>
      <L>  <Cy><Spinner /></Cy>  <Cy>in-progress</Cy>      <Dm>ora active or bar growing</Dm></L>
      <L>  <G><Sym n="success" /></G>  <G>success</G>          <Dm>finalized OK</Dm></L>
      <L>  <Y><Sym n="warning" /></Y>  <Y>warning</Y>          <Dm>finalized OK, caveats</Dm></L>
      <L>  <R><Sym n="error" /></R>  <R>error</R>            <Dm>finalized failed</Dm></L>
      <L>  <Gr><Sym n="skipped" /></Gr>  <Gr>skipped</Gr>          <Dm>precondition false / opt-out</Dm></L>
      <L>  <Gr><Sym n="cancelled" /></Gr>  <Gr>cancelled</Gr>        <Dm>SIGINT during op</Dm></L>
      <Blank />
      <L><Dm>  Transitions: pending → in-progress → (success | warning | error)</Dm></L>
      <L><Dm>               pending → skipped     |    in-progress → cancelled</Dm></L>
      <Blank />
      <L><Dm>  Once finalized, the line is immutable for the rest of the run.</Dm></L>
    </>
  );
}

// ─────────────────────────────────────────────────────────────────
// 10–18. WIZARD STORYBOARD — 9 phases
// ─────────────────────────────────────────────────────────────────

function Phase1Welcome() {
  return <WelcomeScreen />;
}

function Phase2Directory() {
  return (
    <>
      <L><Dm>Install directory:</Dm>   <Caret /></L>
      <L>  <Dm>(default: ./my-app — relative to $PWD)</Dm></L>
      <L>  <Dm>(must be empty OR contain a v2 manifest for update)</Dm></L>
      <Blank />
      <L><Cyb><Sym n="question" /> Where do you want to install?</Cyb> ./apps/payments</L>
      <Blank />
      <Footer step={2} label="Directory" />
    </>
  );
}

function Phase3Detection() {
  return (
    <>
      <L><Dm>Install directory:</Dm>   <B>./apps/payments</B></L>
      <Blank />
      <L><Cy><Spinner /></Cy> <Cy>Scanning ./apps/payments ...</Cy></L>
      <Blank />
      <L><G><Sym n="success" /> Existing installation detected</G></L>
      <Blank />
      <L><Gr>┌─ Detected installation </Gr><Gr>─────────────────────────────────────────────┐</Gr></L>
      <L><Gr>│</Gr>  Mode              <B>Update</B>                                          <Gr>│</Gr></L>
      <L><Gr>│</Gr>  Current version   <B>v2.0.0</B>                                          <Gr>│</Gr></L>
      <L><Gr>│</Gr>  Channel           <B>stable</B>                                          <Gr>│</Gr></L>
      <L><Gr>│</Gr>  Manifest schema   <B>1</B> <Y>(will migrate to 2 on commit)</Y>                  <Gr>│</Gr></L>
      <L><Gr>│</Gr>  Components on disk <B>5</B>/7 installed                                  <Gr>│</Gr></L>
      <L><Gr>└──────────────────────────────────────────────────────────────────┘</Gr></L>
      <Blank />
      <L><Cyb><Sym n="question" /> Continue with update?</Cyb> <Dm>(Y/n)</Dm> <Caret /></L>
      <Blank />
      <Footer step={3} label="Detection" />
    </>
  );
}

function Phase4Components() {
  return <SequentialFlow />;
}

function Phase5Python() {
  return (
    <>
      <L><G><Sym n="success" /> Selected: core-framework, agents, skills, commands, python-cli</G></L>
      <Blank />
      <L><Cy><Spinner /></Cy> <Cy>Probing Python toolchain...</Cy></L>
      <Blank />
      <L><Gr>┌─ Python toolchain </Gr><Gr>──────────────────────────────────────────────────┐</Gr></L>
      <L><Gr>│</Gr>  Found       <B>python3.11</B>  <Dm>(/usr/bin/python3.11)</Dm>                   <Gr>│</Gr></L>
      <L><Gr>│</Gr>  Required    <B>≥ 3.10</B>      <G>OK</G>                                        <Gr>│</Gr></L>
      <L><Gr>│</Gr>  Venv path   <B>./.venv</B>     <Dm>(will be created)</Dm>                      <Gr>│</Gr></L>
      <L><Gr>│</Gr>  Entry point <B>devforgeai</B>  <Dm>(post-install validation)</Dm>              <Gr>│</Gr></L>
      <L><Gr>└──────────────────────────────────────────────────────────────────┘</Gr></L>
      <Blank />
      <L><Cyb><Sym n="question" /> Create .venv/ and install python-cli?</Cyb> <Dm>(Y/n)</Dm> <Caret /></L>
      <Blank />
      <Footer step={5} label="Python Environment" />
    </>
  );
}

function Phase6Copy() {
  return (
    <>
      <L><G><Sym n="success" /> core-framework      </G><Dm>142 files · 312 KB</Dm></L>
      <L><G><Sym n="success" /> agents               </G><Dm>87 files · 1.4 MB</Dm></L>
      <L><G><Sym n="success" /> skills               </G><Dm>45 files · 612 KB</Dm></L>
      <L><G><Sym n="success" /> commands             </G><Dm>64 files · 248 KB</Dm></L>
      <L><Cy><Spinner /></Cy> <Cy>Copying context-files... </Cy><Dm>(stream — tree.json 3.1 MB)</Dm></L>
      <Blank />
      <L><Bar pct={64} /> <Wh>64%</Wh> <Gr>| 9/14 | devforgeai/specs/context/tree.json</Gr></L>
      <Blank />
      <L><Dm>  ETA 4.2s · stream-copy in 8 KB chunks</Dm></L>
      <Blank />
      <Footer step={6} label="File Copy" />
    </>
  );
}

function Phase7Settings() {
  return (
    <>
      <L><G><Sym n="success" /> All component files copied</G></L>
      <Blank />
      <L><Cy><Spinner /></Cy> <Cy>Merging .claude/settings.json ...</Cy></L>
      <Blank />
      <L><Gr>┌─ settings.json merge preview </Gr><Gr>───────────────────────────────────────┐</Gr></L>
      <L><Gr>│</Gr>  <G>+</G> hooks.preCommit              <Dm>added by framework</Dm>             <Gr>│</Gr></L>
      <L><Gr>│</Gr>  <G>+</G> agents.registry              <Dm>added by framework</Dm>             <Gr>│</Gr></L>
      <L><Gr>│</Gr>  <Y>~</Y> editor.formatOnSave          <Dm>your value kept (true)</Dm>          <Gr>│</Gr></L>
      <L><Gr>│</Gr>  <Y>~</Y> python.defaultInterpreter    <Dm>your value kept (./.venv/bin)</Dm>   <Gr>│</Gr></L>
      <L><Gr>│</Gr>                                                                  <Gr>│</Gr></L>
      <L><Gr>│</Gr>  <Dm>Backup → .claude/settings.json.bak (rotation 3)</Dm>                <Gr>│</Gr></L>
      <L><Gr>└──────────────────────────────────────────────────────────────────┘</Gr></L>
      <Blank />
      <L><Cyb><Sym n="question" /> Apply merge?</Cyb> <Dm>(Y/n)</Dm> <Caret /></L>
      <Blank />
      <Footer step={7} label="IDE Settings" />
    </>
  );
}

function Phase8Manifest() {
  return (
    <>
      <L><G><Sym n="success" /> settings.json merged   </G><Dm>2 added · 2 kept · 1 backup written</Dm></L>
      <L><G><Sym n="success" /> CLAUDE.md installed    </G><Dm>(prepended marker block)</Dm></L>
      <L><G><Sym n="success" /> pre-commit hook        </G><Dm>(.git/hooks/pre-commit · 0o755)</Dm></L>
      <Blank />
      <L><Cy><Spinner /></Cy> <Cy>Writing .devforgeai-manifest.json ...</Cy></L>
      <Blank />
      <L><Gr>┌─ Manifest </Gr><Gr>──────────────────────────────────────────────────────────┐</Gr></L>
      <L><Gr>│</Gr>  manifest_schema_version  <B>2</B>                                       <Gr>│</Gr></L>
      <L><Gr>│</Gr>  version                  <B>3.0.5</B>                                   <Gr>│</Gr></L>
      <L><Gr>│</Gr>  channel                  <B>stable</B>                                  <Gr>│</Gr></L>
      <L><Gr>│</Gr>  source                   <B>npm</B>                                     <Gr>│</Gr></L>
      <L><Gr>│</Gr>  installed_at             <B>2026-05-25T16:42:11Z</B>                    <Gr>│</Gr></L>
      <L><Gr>│</Gr>  modules                  <B>11</B> components · 472 files · SHA256 OK   <Gr>│</Gr></L>
      <L><Gr>└──────────────────────────────────────────────────────────────────┘</Gr></L>
      <Blank />
      <Footer step={8} label="Manifest Write" />
    </>
  );
}

function Phase9Summary() {
  return (
    <>
      <L><Gr>┌─ Installation summary </Gr><Gr>──────────────────────────────────────────────┐</Gr></L>
      <L><Gr>│</Gr>  <G><Sym n="success" /></G> core-framework      <Dm>142 files</Dm>                          <Gr>│</Gr></L>
      <L><Gr>│</Gr>  <G><Sym n="success" /></G> agents              <Dm>87 files</Dm>                           <Gr>│</Gr></L>
      <L><Gr>│</Gr>  <G><Sym n="success" /></G> skills              <Dm>45 files</Dm>                           <Gr>│</Gr></L>
      <L><Gr>│</Gr>  <G><Sym n="success" /></G> commands            <Dm>64 files</Dm>                           <Gr>│</Gr></L>
      <L><Gr>│</Gr>  <Gr><Sym n="skipped" /></Gr> hooks               <Dm>user opt-out</Dm>                       <Gr>│</Gr></L>
      <L><Gr>│</Gr>  <G><Sym n="success" /></G> python-cli          <Dm>.venv/ · entry-point OK</Dm>             <Gr>│</Gr></L>
      <L><Gr>│</Gr>  <G><Sym n="success" /></G> context-files       <Dm>6 immutable files</Dm>                   <Gr>│</Gr></L>
      <L><Gr>│</Gr>  <Y><Sym n="warning" /></Y> claude-md           <Dm>prepended (existing kept)</Dm>           <Gr>│</Gr></L>
      <L><Gr>│</Gr>  <G><Sym n="success" /></G> claude-settings     <Dm>merged · backup .bak</Dm>                <Gr>│</Gr></L>
      <L><Gr>│</Gr>  <G><Sym n="success" /></G> pre-commit-hook     <Dm>installed</Dm>                           <Gr>│</Gr></L>
      <L><Gr>│</Gr>  <G><Sym n="success" /></G> manifest            <Dm>schema v2 written</Dm>                   <Gr>│</Gr></L>
      <L><Gr>├──────────────────────────────────────────────────────────────────┤</Gr></L>
      <L><Gr>│</Gr>  Channel <B>stable</B>      Version <B>3.0.5</B>      ETA <B>4.1s</B>            <Gr>│</Gr></L>
      <L><Gr>└──────────────────────────────────────────────────────────────────┘</Gr></L>
      <Blank />
      <L><G><Sym n="success" /> DevForgeAI installed successfully.</G></L>
      <L><Dm>  Next: </Dm><B>devforgeai status</B><Dm>  ·  </Dm><B>devforgeai check-updates</B></L>
      <Blank />
      <Footer step={9} label="Done" />
    </>
  );
}

// ─────────────────────────────────────────────────────────────────
// PROMPT 2 ADDITIONS — Happy-path screens not in the original set
// ─────────────────────────────────────────────────────────────────

function Step3DetectionList() {
  return (
    <>
      <L><G><Sym n="success" /> Existing installation detected</G></L>
      <Blank />
      <L><Gr>┌─ Detected installation </Gr><Gr>─────────────────────────────────────────────┐</Gr></L>
      <L><Gr>│</Gr>  Current version    <B>v2.0.0</B>                                       <Gr>│</Gr></L>
      <L><Gr>│</Gr>  Channel            <B>stable</B>                                       <Gr>│</Gr></L>
      <L><Gr>│</Gr>  Manifest schema    <B>1</B> <Y>(will migrate to 2)</Y>                       <Gr>│</Gr></L>
      <L><Gr>│</Gr>  Components on disk <B>5</B>/7 installed                                <Gr>│</Gr></L>
      <L><Gr>│</Gr>  Last installed     <B>2026-03-31</B>                                   <Gr>│</Gr></L>
      <L><Gr>└──────────────────────────────────────────────────────────────────┘</Gr></L>
      <Blank />
      <L><Cyb><Sym n="question" /> How do you want to proceed?</Cyb></L>
      <L>  <Cy><Sym n="cursor" /> <Cy>Update</Cy></Cy>      <Dm><Dash /> re-copy framework, keep context files</Dm></L>
      <L>    <Gr>Reinstall</Gr>   <Dm>(destructive — overwrites context files)</Dm></L>
      <L>    <Gr>Cancel</Gr>      <Dm><Dash /> exit without changes</Dm></L>
      <Blank />
      <Footer step={3} label="Detection" />
    </>
  );
}

function Step4ChannelSelect() {
  return (
    <>
      <L><Gr>  Channel determines which release stream you track:</Gr></L>
      <Blank />
      <L><Cyb><Sym n="question" /> Choose update channel:</Cyb></L>
      <L>  <Cy><Sym n="cursor" /> <Cy>Stable</Cy></Cy>   <Dm>(Recommended) Latest GA · npm @latest</Dm></L>
      <L>    <Gr>Beta</Gr>     <M>●</M> <Dm>Latest pre-release · npm @beta</Dm></L>
      <L>    <Gr>Edge</Gr>     <M>●</M> <R>Unstable</R> <Dm>· github:DevForgeAI#main</Dm></L>
      <Blank />
      <L><Gr>  Switch later via:  </Gr><B>devforgeai install --switch-channel=X</B></L>
      <Blank />
      <Footer step={4} label="Channel" />
    </>
  );
}

function Step5ComponentsFull() {
  return (
    <>
      <L><Cyb><Sym n="question" /> Select components to install:</Cyb></L>
      <L>  <Cy><Sym n="cursor" /> <G><Sym n="check_on" /></G></Cy> core-framework      <Dm>(required)</Dm></L>
      <L>    <G><Sym n="check_on" /></G> context-files       <Dm>(required, immutable)</Dm></L>
      <L>    <G><Sym n="check_on" /></G> agents              <Dm>87 task delegates</Dm></L>
      <L>    <G><Sym n="check_on" /></G> skills              <Dm>45 workflow automations</Dm></L>
      <L>    <G><Sym n="check_on" /></G> commands            <Dm>64 slash commands</Dm></L>
      <L>    <G><Sym n="check_on" /></G> hooks               <Dm>47 lifecycle gates</Dm></L>
      <L>    <G><Sym n="check_on" /></G> python-cli          <Dm>devforgeai-validate + .venv/</Dm></L>
      <L>    <G><Sym n="check_on" /></G> project-structure   <Dm>docs/ tree skeleton</Dm></L>
      <L>    <G><Sym n="check_on" /></G> claude-md           <Dm>(required)</Dm></L>
      <L>    <G><Sym n="check_on" /></G> claude-settings     <Dm>(required, merged)</Dm></L>
      <L>    <G><Sym n="check_on" /></G> pre-commit-hook     <Dm>(.git/ detected — opt-in)</Dm></L>
      <L>  <Dm>(space to toggle · a to toggle all · enter to confirm)</Dm></L>
      <Blank />
      <Footer step={5} label="Components" />
    </>
  );
}

function Step8Preflight() {
  return (
    <>
      <L><Gr>┌─ Pre-flight summary </Gr><Gr>─────────────────────────────────────────────┐</Gr></L>
      <L><Gr>│</Gr>  Directory     <B>./apps/payments</B>                                  <Gr>│</Gr></L>
      <L><Gr>│</Gr>  Mode          <B>Update</B>   <Dm>(from v2.0.0)</Dm>                          <Gr>│</Gr></L>
      <L><Gr>│</Gr>  Channel       <B>stable</B>   <Dm>(npm @latest → v3.0.5)</Dm>                <Gr>│</Gr></L>
      <L><Gr>│</Gr>  Project name  <B>payments</B>                                        <Gr>│</Gr></L>
      <L><Gr>├──────────────────────────────────────────────────────────────────┤</Gr></L>
      <L><Gr>│</Gr>  Components    <B>11 selected</B> · 472 files · ~3.4 MB                <Gr>│</Gr></L>
      <L><Gr>│</Gr>    <G><Sym n="success" /></G> core, context, agents, skills, commands, hooks,        <Gr>│</Gr></L>
      <L><Gr>│</Gr>      python-cli, project-structure, claude-md,                <Gr>│</Gr></L>
      <L><Gr>│</Gr>      claude-settings, pre-commit-hook                         <Gr>│</Gr></L>
      <L><Gr>├──────────────────────────────────────────────────────────────────┤</Gr></L>
      <L><Gr>│</Gr>  Mutations                                                       <Gr>│</Gr></L>
      <L><Gr>│</Gr>    <G>+</G> 472 files into .claude/, devforgeai/, docs/             <Gr>│</Gr></L>
      <L><Gr>│</Gr>    <Y>~</Y> CLAUDE.md      <Dm>(prepend marker; existing kept)</Dm>          <Gr>│</Gr></L>
      <L><Gr>│</Gr>    <Y>~</Y> .claude/settings.json   <Dm>(merge · backup .bak)</Dm>           <Gr>│</Gr></L>
      <L><Gr>│</Gr>    <G>+</G> .git/hooks/pre-commit   <Dm>(new, 0o755)</Dm>                    <Gr>│</Gr></L>
      <L><Gr>│</Gr>    <G>+</G> .venv/  <Dm>(Python 3.11 · -e .claude/scripts/)</Dm>             <Gr>│</Gr></L>
      <L><Gr>│</Gr>    <G>+</G> .devforgeai-manifest.json <Dm>(schema v2)</Dm>                    <Gr>│</Gr></L>
      <L><Gr>│</Gr>  <Dm>Rollback journal: tmp/devforgeai-install-9F2A1B/state.json</Dm>  <Gr>│</Gr></L>
      <L><Gr>└──────────────────────────────────────────────────────────────────┘</Gr></L>
      <Blank />
      <L><Cyb><Sym n="question" /> Proceed with install?</Cyb> <Dm>(Y/n)</Dm> <Caret /></L>
      <Blank />
      <Footer step={8} label="Pre-flight Summary" />
    </>
  );
}

function Step9aPhaseHeader() {
  return (
    <>
      <L><Gr>╔════════════════════════════════════════════════════════════════════╗</Gr></L>
      <L><Gr>║</Gr>  <Cyb>PHASE 9 / 12  —  INSTALLING</Cyb>                                       <Gr>║</Gr></L>
      <L><Gr>║</Gr>  <Dm>Journal: tmp/devforgeai-install-9F2A1B/state.json</Dm>                <Gr>║</Gr></L>
      <L><Gr>╚════════════════════════════════════════════════════════════════════╝</Gr></L>
      <Blank />
      <L><Dm>  Planning topological order of 11 components...</Dm></L>
      <L><Dm>  Allocating rollback journal...</Dm></L>
      <L><Dm>  Ready.</Dm></L>
      <Blank />
      <Footer step={9} label="Installing · planning" />
    </>
  );
}

function Step10Verify() {
  return (
    <>
      <L><G><Sym n="success" /> Manifest written</G>   <Dm>.devforgeai-manifest.json · schema v2</Dm></L>
      <Blank />
      <L><Cy><Spinner /></Cy> <Cy>Verifying install... </Cy><Dm>(hashing 472 files)</Dm></L>
      <Blank />
      <L><Gr>  Verified so far</Gr></L>
      <L><Dm>    core-framework      142/142     SHA256 OK</Dm></L>
      <L><Dm>    context-files       6/6         SHA256 OK</Dm></L>
      <L><Dm>    agents              87/87       SHA256 OK</Dm></L>
      <L><Dm>    skills              42/45       ...</Dm></L>
      <Blank />
      <Footer step={10} label="Verifying" />
    </>
  );
}

function Step12NextSteps() {
  return (
    <>
      <L><Cyb>  Next steps</Cyb></L>
      <Blank />
      <L>  <B>1.</B> Open Claude Code and try a skill:</L>
      <L>       <Dm>$</Dm> <B>claude /create-system-architecture</B></L>
      <Blank />
      <L>  <B>2.</B> Verify the install whenever you want:</L>
      <L>       <Dm>$</Dm> <B>devforgeai status</B></L>
      <L>       <Dm>$</Dm> <B>devforgeai check-updates</B></L>
      <Blank />
      <L>  <B>3.</B> Activate the Python validator:</L>
      <L>       <Dm>$</Dm> <B>source ./.venv/bin/activate</B></L>
      <L>       <Dm>$</Dm> <B>devforgeai-validate --help</B></L>
      <Blank />
      <L><Gr>  Docs:   https://devforgeai.dev/docs</Gr></L>
      <L><Gr>  Issues: https://github.com/DevForgeAI/issues</Gr></L>
      <Blank />
      <Footer step={12} label="Next Steps" />
    </>
  );
}

Object.assign(window, {
  WelcomeScreen,
  InventoryMessages, InventoryPrompts, InventoryIndicators,
  SequentialFlow, ValidationRetry, SigintArm, ConfirmGate,
  StatePatterns,
  Phase1Welcome, Phase2Directory, Phase3Detection, Phase4Components,
  Phase5Python, Phase6Copy, Phase7Settings, Phase8Manifest, Phase9Summary,
  Step3DetectionList, Step4ChannelSelect, Step5ComponentsFull,
  Step8Preflight, Step9aPhaseHeader, Step10Verify, Step12NextSteps,
});

// ─────────────────────────────────────────────────────────────────
// PROMPT 3 ADDITIONS — Recovery / Error / Edge-case screens
// ─────────────────────────────────────────────────────────────────

function RecoveryA1PythonMissing() {
  return (
    <>
      <L><R><Sym n="error" /> </R><Rb>E_PYTHON_MISSING</Rb></L>
      <L><R>   Python 3.10+ is required for the python-cli component.</R></L>
      <L>   <Dm>Hint: install Python 3.10+ or pass --skip-python on next run.</Dm></L>
      <L>   <Dm>Details: devforgeai/logs/install-9F2A1B.log</Dm></L>
      <Blank />
      <L><Cyb><Sym n="question" /> What would you like to do?</Cyb></L>
      <L>  <Cy><Sym n="cursor" /> <Cy>Retry detection</Cy></Cy>   <Dm>(re-probe PATH for python3)</Dm></L>
      <L>    <Gr>Skip python-cli</Gr>   <Dm>(drop component, keep rest of install)</Dm></L>
      <L>    <Gr>Abort with rollback</Gr> <Dm>(exit 4, restore prior state)</Dm></L>
      <Blank />
      <L><Gr>[Step 9/12 — Installing · failed]  E_PYTHON_MISSING (4)</Gr></L>
    </>
  );
}

function RecoveryA9ResumeOffer() {
  return (
    <>
      <L><Yb><Sym n="warning" /> Partial install detected</Yb></L>
      <Blank />
      <L><Gr>┌─ Prior session </Gr><Gr>──────────────────────────────────────────────────┐</Gr></L>
      <L><Gr>│</Gr>  Session ID       <B>9F2A1B</B>                                  <Gr>│</Gr></L>
      <L><Gr>│</Gr>  Started          <B>2026-05-25 16:42</B>    24m ago             <Gr>│</Gr></L>
      <L><Gr>│</Gr>  Last good step   <B>9b · skills</B>                             <Gr>│</Gr></L>
      <L><Gr>│</Gr>  Files written    <B>328</B> / 472                               <Gr>│</Gr></L>
      <L><Gr>│</Gr>  Resumable        <G>yes</G>                                     <Gr>│</Gr></L>
      <L><Gr>│</Gr>  Journal          tmp/devforgeai-install-9F2A1B/state.json   <Gr>│</Gr></L>
      <L><Gr>└──────────────────────────────────────────────────────────────────┘</Gr></L>
      <Blank />
      <L><Cyb><Sym n="question" /> How would you like to proceed?</Cyb></L>
      <L>  <Cy><Sym n="cursor" /> <Cy>Resume from last good step</Cy></Cy> <Dm>(--resume)</Dm></L>
      <L>    <Gr>Roll back the prior session</Gr> <Dm>(restore previous state)</Dm></L>
      <L>    <Gr>Start fresh</Gr>   <Dm>(delete journal, begin Step 1)</Dm></L>
      <L>    <Gr>Abort</Gr>         <Dm>(exit 9, journal untouched)</Dm></L>
      <Blank />
      <L><Gr>[Step 0/12 — Resume Check]</Gr></L>
    </>
  );
}

function RecoveryB3SettingsMergeConflict() {
  return (
    <>
      <L><Y><Sym n="warning" /> </Y><Y>settings.json merge — 4 conflicts</Y></L>
      <Blank />
      <L><Gr>┌─ Merge preview </Gr><Gr>──────────────────────────────────────────────────┐</Gr></L>
      <L><Gr>│</Gr>  <G>+</G> hooks.preCommit              <Dm>added by framework</Dm>       <Gr>│</Gr></L>
      <L><Gr>│</Gr>  <G>+</G> agents.registry              <Dm>added by framework</Dm>       <Gr>│</Gr></L>
      <L><Gr>│</Gr>  <Y>~</Y> editor.formatOnSave                                      <Gr>│</Gr></L>
      <L><Gr>│</Gr>      your value:       <B>false</B>                              <Gr>│</Gr></L>
      <L><Gr>│</Gr>      framework value:  <B>true</B>                               <Gr>│</Gr></L>
      <L><Gr>│</Gr>  <Y>~</Y> python.defaultInterpreter                                <Gr>│</Gr></L>
      <L><Gr>│</Gr>      your value:       <B>/usr/bin/python3.9</B>                 <Gr>│</Gr></L>
      <L><Gr>│</Gr>      framework value:  <B>./.venv/bin/python3</B>                <Gr>│</Gr></L>
      <L><Gr>│</Gr>  <Y>~</Y> memory.maxTokens                                         <Gr>│</Gr></L>
      <L><Gr>│</Gr>      your value:       <B>50000</B>                              <Gr>│</Gr></L>
      <L><Gr>│</Gr>      framework value:  <B>200000</B>                             <Gr>│</Gr></L>
      <L><Gr>│</Gr>                                                                  <Gr>│</Gr></L>
      <L><Gr>│</Gr>  Backup: .claude/settings.json.bak  (rotation .bak.1 / .bak.2) <Gr>│</Gr></L>
      <L><Gr>└──────────────────────────────────────────────────────────────────┘</Gr></L>
      <Blank />
      <L><Cyb><Sym n="question" /> How to resolve the 3 conflicts?</Cyb></L>
      <L>  <Cy><Sym n="cursor" /> <Cy>Keep your values</Cy></Cy>    <Dm>(consumer wins · default)</Dm></L>
      <L>    <Gr>Use framework values</Gr> <Dm>(framework wins · your .bak kept)</Dm></L>
      <L>    <Gr>View full diff</Gr>      <Dm>(renders D2-style report, then returns)</Dm></L>
      <L>    <Gr>Abort</Gr>                <Dm>(exit 9)</Dm></L>
      <Blank />
      <L><Gr>[Step 9/12 — Installing · settings conflict]</Gr></L>
    </>
  );
}

function RecoveryC4ChannelDowngrade() {
  return (
    <>
      <L><R><Sym n="error" /> </R><Rb>Downgrade required for this switch</Rb></L>
      <Blank />
      <L><Gr>┌─ Downgrade details </Gr><Gr>──────────────────────────────────────────────┐</Gr></L>
      <L><Gr>│</Gr>  Current     <M>beta</M>     <B>v3.1.0-beta.4</B>                      <Gr>│</Gr></L>
      <L><Gr>│</Gr>  Target      stable   <B>v3.0.5</B>                              <Gr>│</Gr></L>
      <L><Gr>│</Gr>  Delta       <R>-1 minor · -8 RC commits</R>                     <Gr>│</Gr></L>
      <L><Gr>│</Gr>  Side effects                                                 <Gr>│</Gr></L>
      <L><Gr>│</Gr>    <Rb>!</Rb> python-cli .venv/ will be rebuilt                <Gr>│</Gr></L>
      <L><Gr>│</Gr>    <Rb>!</Rb> beta-only components will be removed:            <Gr>│</Gr></L>
      <L><Gr>│</Gr>        new-component-x                                        <Gr>│</Gr></L>
      <L><Gr>│</Gr>    <Y>~</Y> 4 components will revert to older versions         <Gr>│</Gr></L>
      <L><Gr>│</Gr>  Reversible   manually only · prior beta install destroyed   <Gr>│</Gr></L>
      <L><Gr>└──────────────────────────────────────────────────────────────────┘</Gr></L>
      <Blank />
      <L><Gr>  Required in silent mode:  </Gr><B>--allow-downgrade</B></L>
      <Blank />
      <L><Cyb><Sym n="question" /> Proceed with downgrade?</Cyb> <Dm>(y/N)</Dm> <Caret /></L>
      <Blank />
      <L><Gr>[--switch-channel stable · downgrade]  USER_CANCELLED on N (9)</Gr></L>
    </>
  );
}

function RecoveryC5EdgeUnstable() {
  return (
    <>
      <L><R><Sym n="error" /> </R><Rb>EDGE CHANNEL — UNSTABLE</Rb></L>
      <Blank />
      <L><Gr>┌─ What this means </Gr><Gr>────────────────────────────────────────────────┐</Gr></L>
      <L><Gr>│</Gr>  Source           <M>github:DevForgeAI#main</M>                <Gr>│</Gr></L>
      <L><Gr>│</Gr>  Stability        <R>no guarantees · may break at any commit</R>    <Gr>│</Gr></L>
      <L><Gr>│</Gr>  Update authority GitHub main HEAD                            <Gr>│</Gr></L>
      <L><Gr>│</Gr>  Rate-limit       60 anonymous GH API calls / hour            <Gr>│</Gr></L>
      <L><Gr>│</Gr>  Audience         <B>framework contributors only</B>            <Gr>│</Gr></L>
      <L><Gr>└──────────────────────────────────────────────────────────────────┘</Gr></L>
      <Blank />
      <L><Y>  You are explicitly opting into broken-at-any-moment software.</Y></L>
      <Blank />
      <L><Cyb><Sym n="question" /> Continue with edge channel?</Cyb> <Dm>(y/N)</Dm> <Caret /></L>
      <Blank />
      <L><Gr>[Step 4/12 — Channel · edge confirm]  USER_CANCELLED on N (9)</Gr></L>
    </>
  );
}

function RecoveryD2VerifyDrift() {
  return (
    <>
      <L><R><Sym n="error" /> </R><Rb>Verify failed — 4 drift entries</Rb></L>
      <Blank />
      <L><Gr>  Manifest: .devforgeai-manifest.json · 472 files · schema v2</Gr></L>
      <L><Gr>  Channel: stable v3.0.5</Gr></L>
      <Blank />
      <L><Gr>  Drift detected</Gr></L>
      <L>  <Y>~</Y> .claude/settings.json              <Dm>(modified locally · diff +12/-3)</Dm></L>
      <L>  <Rb>!</Rb> .claude/agents/registry.json         <Dm>(SHA256 mismatch)</Dm></L>
      <L>  <R>-</R> .claude/hooks/post-spec-bind.sh      <Dm>(missing)</Dm></L>
      <L>  <G>+</G> .claude/hooks/custom-user-hook.sh   <Dm>(untracked)</Dm></L>
      <Blank />
      <L><Gr>  Summary    1 modified · 1 mismatch · 1 missing · 1 untracked</Gr></L>
      <Blank />
      <L><Gr>  Recovery   </Gr><B>devforgeai install --resume</B><Gr>  (restores from manifest)</Gr></L>
      <L><Gr>             </Gr><B>devforgeai uninstall && devforgeai install</B><Gr> (clean)</Gr></L>
      <Blank />
      <L><Gr>[--verify · drift]  VERIFY_FAILED (6)</Gr></L>
    </>
  );
}

function RecoveryD5RollbackFailed() {
  return (
    <>
      <L><R><Sym n="error" /> </R><Rb>Rollback incomplete — manual intervention required</Rb></L>
      <Blank />
      <L><Gr>┌─ Reversed cleanly </Gr><Gr>───────────────────────────────────────────────┐</Gr></L>
      <L><Gr>│</Gr>  <G><Sym n="success" /></G> manifest-write          <G><Sym n="success" /></G> settings-merge      <Gr>│</Gr></L>
      <L><Gr>│</Gr>  <G><Sym n="success" /></G> pre-commit-hook-install <G><Sym n="success" /></G> python-venv-install <Gr>│</Gr></L>
      <L><Gr>│</Gr>  <G><Sym n="success" /></G> copy (skills)           <G><Sym n="success" /></G> copy (commands)     <Gr>│</Gr></L>
      <L><Gr>└──────────────────────────────────────────────────────────────────┘</Gr></L>
      <Blank />
      <L><Gr>┌─ Needs your attention </Gr><Gr>───────────────────────────────────────────┐</Gr></L>
      <L><Gr>│</Gr>  <Rb>!</Rb> copy (context-files) — partially reversed             <Gr>│</Gr></L>
      <L><Gr>│</Gr>      <Dm>devforgeai/specs/context/tree.json (1.8 MB written)</Dm>    <Gr>│</Gr></L>
      <L><Gr>│</Gr>      <Dm>devforgeai/specs/context/source-tree/index.json</Dm>        <Gr>│</Gr></L>
      <L><Gr>│</Gr>    Recovery:  <B>rm -rf devforgeai/specs/context/</B>             <Gr>│</Gr></L>
      <L><Gr>│</Gr>                                                                 <Gr>│</Gr></L>
      <L><Gr>│</Gr>  <Rb>!</Rb> claude-md-import — non-reversible action             <Gr>│</Gr></L>
      <L><Gr>│</Gr>      CLAUDE.md was rewritten, not prepended; original lost     <Gr>│</Gr></L>
      <L><Gr>│</Gr>    Recovery:  <B>git checkout CLAUDE.md</B> (if tracked)          <Gr>│</Gr></L>
      <L><Gr>│</Gr>               or restore from your editor's local history      <Gr>│</Gr></L>
      <L><Gr>└──────────────────────────────────────────────────────────────────┘</Gr></L>
      <Blank />
      <L><Gr>  Full diagnostic at devforgeai/logs/install-9F2A1B.log</Gr></L>
      <Blank />
      <L><Gr>[--rollback · failed]  ROLLBACK_FAILED (8)</Gr></L>
    </>
  );
}

Object.assign(window, {
  RecoveryA1PythonMissing,
  RecoveryA9ResumeOffer,
  RecoveryB3SettingsMergeConflict,
  RecoveryC4ChannelDowngrade,
  RecoveryC5EdgeUnstable,
  RecoveryD2VerifyDrift,
  RecoveryD5RollbackFailed,
});

// ─────────────────────────────────────────────────────────────────
// PROMPT 4 ADDITIONS — Status / Check-updates / Help layouts
// ─────────────────────────────────────────────────────────────────

function StatusS2InstallHelp() {
  return (
    <>
      <L><Cyb>devforgeai install</Cyb> — Install or update DevForgeAI</L>
      <Blank />
      <L><Cyb>Usage</Cyb></L>
      <L>   <B>devforgeai install</B> [dir] [options]</L>
      <Blank />
      <L>   [dir]                      Target directory (default: ./)</L>
      <Blank />
      <L><Cyb>Mode</Cyb></L>
      <L>   --silent                   Non-interactive; NDJSON event output</L>
      <L>   --interactive              Force interactive (default if TTY)</L>
      <Blank />
      <L><Cyb>Capability</Cyb></L>
      <L>   --dry-run                  Plan only — no filesystem writes</L>
      <L>   --resume                   Continue from last checkpoint</L>
      <L>   --rollback                 Reverse the last journal</L>
      <L>   --verify                   Re-hash all installed files</L>
      <Blank />
      <L><Cyb>Update / channel (ADR-105)</Cyb></L>
      <L>   --update                   Re-copy framework, keep context files</L>
      <L>   --channel <Gr>&lt;name&gt;</Gr>           stable | beta | edge</L>
      <L>   --switch-channel <Gr>&lt;name&gt;</Gr>    Switch + reinstall in one step</L>
      <L>   --to-version <Gr>&lt;semver&gt;</Gr>      Pin to a specific version</L>
      <L>   --allow-downgrade          Required in silent mode for downgrades</L>
      <L>   --check-updates            Query version-detector; exit 12 if stale</L>
      <Blank />
      <L><Cyb>Examples</Cyb></L>
      <L>   <Dm># Silent CI install — NDJSON to stdout</Dm></L>
      <L>   <B>devforgeai install . --silent --components=core-framework,agents</B></L>
      <Blank />
      <L>   <Dm># Switch to beta channel + reinstall</Dm></L>
      <L>   <B>devforgeai install . --switch-channel=beta</B></L>
      <Blank />
      <L><Cyb>Exit codes</Cyb></L>
      <L>   <G>  0</G>  SUCCESS                  <Gr>  7</Gr>  ROLLBACK_SUCCEEDED</L>
      <L>   <Gr>  1</Gr>  GENERIC_FAILURE          <Gr>  8</Gr>  ROLLBACK_FAILED</L>
      <L>   <Gr>  2</Gr>  INVALID_INVOCATION       <Gr>  9</Gr>  USER_CANCELLED</L>
      <L>   <Gr>  3</Gr>  CONFIG_INVALID           <Gr> 10</Gr>  TARGET_CONFLICT</L>
      <L>   <Gr>  4</Gr>  PREFLIGHT_FAILED         <Gr> 11</Gr>  NETWORK_REQUIRED</L>
      <L>   <Gr>  5</Gr>  PARTIAL_INSTALL          <Gr> 12</Gr>  UPDATE_AVAILABLE</L>
      <L>   <Gr>  6</Gr>  VERIFY_FAILED            <Gr>130</Gr>  SIGINT</L>
    </>
  );
}

function StatusS7Default() {
  return (
    <>
      <L><Cyb>DevForgeAI status</Cyb> <Dm>· ./apps/payments</Dm></L>
      <Blank />
      <L><Gr>┌─ Installation </Gr><Gr>──────────────────────────────────────────────────┐</Gr></L>
      <L><Gr>│</Gr>  Installed version    <B>3.0.5</B>                              <Gr>│</Gr></L>
      <L><Gr>│</Gr>  Channel              <B>stable</B>                             <Gr>│</Gr></L>
      <L><Gr>│</Gr>  Source               <B>npm</B>                                <Gr>│</Gr></L>
      <L><Gr>│</Gr>  Installed at         <B>2026-04-12T14:32:11Z</B>               <Gr>│</Gr></L>
      <L><Gr>│</Gr>  Last update          <B>2026-05-10T09:14:55Z</B>               <Gr>│</Gr></L>
      <L><Gr>│</Gr>  Manifest schema      <B>2</B>                                  <Gr>│</Gr></L>
      <L><Gr>│</Gr>  Components           <B>11</B> / 11 installed                  <Gr>│</Gr></L>
      <L><Gr>└─────────────────────────────────────────────────────────────────┘</Gr></L>
      <Blank />
      <L><Gr>┌─ Subsystems </Gr><Gr>────────────────────────────────────────────────────┐</Gr></L>
      <L><Gr>│</Gr>  <G><Sym n="success" /></G> Python CLI         venv at .venv/ · Python 3.11.2     <Gr>│</Gr></L>
      <L><Gr>│</Gr>  <G><Sym n="success" /></G> Pre-commit hook    installed · checksum matches       <Gr>│</Gr></L>
      <L><Gr>│</Gr>  <G><Sym n="success" /></G> CLAUDE.md          imports @DevForgeAI.md             <Gr>│</Gr></L>
      <L><Gr>│</Gr>  <G><Sym n="success" /></G> settings.json      merged · 2 backups retained        <Gr>│</Gr></L>
      <L><Gr>│</Gr>  <G><Sym n="success" /></G> Last verify        2026-05-15T12:00:00Z — PASSED      <Gr>│</Gr></L>
      <L><Gr>└─────────────────────────────────────────────────────────────────┘</Gr></L>
      <Blank />
      <L><Gr>  Run </Gr><B>devforgeai status --check-updates</B><Gr> to query for new versions.</Gr></L>
    </>
  );
}

function StatusS8UpdateAvailable() {
  return (
    <>
      <L><Cyb>DevForgeAI status</Cyb> <Dm>· ./apps/payments</Dm></L>
      <Blank />
      <L><Gr>┌─ Installation </Gr><Gr>──────────────────────────────────────────────────┐</Gr></L>
      <L><Gr>│</Gr>  Installed version    <B>3.0.5</B>                              <Gr>│</Gr></L>
      <L><Gr>│</Gr>  Channel              <B>stable</B>                             <Gr>│</Gr></L>
      <L><Gr>└─────────────────────────────────────────────────────────────────┘</Gr></L>
      <Blank />
      <L><Y><Sym n="warning" /> </Y><Yb>Update available</Yb>  <Y>3.0.5 → 3.0.7</Y></L>
      <Blank />
      <L><Gr>┌─ Version availability </Gr><Gr>──────────────────────────────────────────┐</Gr></L>
      <L><Gr>│</Gr>  <Y><Sym n="warning" /></Y> stable    <B>3.0.7</B>            +2 patches behind         <Gr>│</Gr></L>
      <L><Gr>│</Gr>  <Gr><Sym n="info" /></Gr> beta      <M>3.1.0-beta.4</M>    use --switch-channel=beta <Gr>│</Gr></L>
      <L><Gr>│</Gr>  <Gr><Sym n="info" /></Gr> edge      <M>+11 commits</M>    ahead of beta · UNSTABLE  <Gr>│</Gr></L>
      <L><Gr>└─────────────────────────────────────────────────────────────────┘</Gr></L>
      <Blank />
      <L><Gr>  Apply with:</Gr>  <B>devforgeai install --update</B></L>
      <L><Gr>  Or pin a specific version:</Gr> <B>devforgeai install --to-version=3.0.7</B></L>
      <Blank />
      <L><Gr>  Cache  fresh · last fetched 2026-05-25T10:00:00Z · valid 22h 13m</Gr></L>
      <L><Gr>  UPDATE_AVAILABLE (12) — only emitted in --silent</Gr></L>
    </>
  );
}

function StatusS10JsonOutput() {
  return (
    <>
      <L><Gr>{'{'}</Gr></L>
      <L>  <Gr>"schema_version":</Gr> <G>"3.0"</G><Gr>,</Gr></L>
      <L>  <Gr>"ts":</Gr> <G>"2026-05-25T16:42:11Z"</G><Gr>,</Gr></L>
      <L>  <Gr>"command":</Gr> <G>"status"</G><Gr>,</Gr></L>
      <L>  <Gr>"version":</Gr> <Gr>{'{'}</Gr></L>
      <L>    <Gr>"installed":</Gr> <G>"3.0.5"</G><Gr>,</Gr></L>
      <L>    <Gr>"latest_stable":</Gr> <G>"3.0.5"</G><Gr>,</Gr></L>
      <L>    <Gr>"latest_beta":</Gr> <G>"3.1.0-beta.2"</G><Gr>,</Gr></L>
      <L>    <Gr>"update_available":</Gr> <M>false</M></L>
      <L>  <Gr>{'},'}</Gr></L>
      <L>  <Gr>"channel":</Gr> <G>"stable"</G><Gr>,</Gr></L>
      <L>  <Gr>"source":</Gr> <G>"npm"</G><Gr>,</Gr></L>
      <L>  <Gr>"components":</Gr> <Gr>[</Gr></L>
      <L>    <Gr>{'{ "id":'}</Gr> <G>"core-framework"</G><Gr>, "installed":</Gr> <M>true</M><Gr>{', "checksum":'}</Gr> <G>"sha256:abc..."</G> <Gr>{'},'}</Gr></L>
      <L>    <Gr>...</Gr></L>
      <L>  <Gr>],</Gr></L>
      <L>  <Gr>"python":</Gr> <Gr>{'{'}</Gr></L>
      <L>    <Gr>"venv_path":</Gr> <G>".venv/"</G><Gr>,</Gr></L>
      <L>    <Gr>"interpreter":</Gr> <G>"3.11.2"</G><Gr>,</Gr></L>
      <L>    <Gr>"entry_point_ok":</Gr> <M>true</M></L>
      <L>  <Gr>{'},'}</Gr></L>
      <L>  <Gr>"last_verify":</Gr> <Gr>{'{'}</Gr></L>
      <L>    <Gr>"ts":</Gr> <G>"2026-05-15T12:00:00Z"</G><Gr>,</Gr></L>
      <L>    <Gr>"passed":</Gr> <M>true</M><Gr>,</Gr></L>
      <L>    <Gr>"drift_count":</Gr> <Y>0</Y></L>
      <L>  <Gr>{'}'}</Gr></L>
      <L><Gr>{'}'}</Gr></L>
    </>
  );
}

function StatusS13UninstallPurge() {
  return (
    <>
      <L><R><Sym n="error" /> </R><Rb>Uninstall + purge DevForgeAI from ./apps/payments</Rb></L>
      <Blank />
      <L><Gr>┌─ Will be removed </Gr><Gr>───────────────────────────────────────────────┐</Gr></L>
      <L><Gr>│</Gr>  .claude/                   <B>443 files</B>                   <Gr>│</Gr></L>
      <L><Gr>│</Gr>  devforgeai/specs/context/   <B>6 files</B>                     <Gr>│</Gr></L>
      <L><Gr>│</Gr>  CLAUDE.md (marker lines)    <B>prepend-stripped</B>             <Gr>│</Gr></L>
      <L><Gr>│</Gr>  .claude/settings.json       <B>restored from .bak</B>           <Gr>│</Gr></L>
      <L><Gr>│</Gr>  .git/hooks/pre-commit       <B>removed if framework-owned</B>   <Gr>│</Gr></L>
      <L><Gr>│</Gr>  .devforgeai-manifest.json   <B>removed</B>                      <Gr>│</Gr></L>
      <L><Gr>│</Gr>  <R>+</R> .venv/                  <B>Python env DELETED</B>            <Gr>│</Gr></L>
      <L><Gr>│</Gr>  <R>+</R> .claude/*.bak (×3)      <B>rotation backups DELETED</B>      <Gr>│</Gr></L>
      <L><Gr>└──────────────────────────────────────────────────────────────────┘</Gr></L>
      <Blank />
      <L><Y>  Purge is irreversible. No backups will remain.</Y></L>
      <Blank />
      <L><Cyb><Sym n="question" /> Proceed with uninstall --purge?</Cyb> <Dm>(y/N)</Dm> <Caret /></L>
      <Blank />
      <L><Gr>[uninstall --purge · confirm]  USER_CANCELLED on N (9)</Gr></L>
    </>
  );
}

Object.assign(window, {
  StatusS2InstallHelp, StatusS7Default, StatusS8UpdateAvailable,
  StatusS10JsonOutput, StatusS13UninstallPurge,
});

// ─────────────────────────────────────────────────────────────────
// PROMPT 5 ADDITION — Silent-mode NDJSON stream
// ─────────────────────────────────────────────────────────────────

// Tiny NDJSON line renderer — colors keys gray, strings green,
// numbers yellow, booleans magenta, null dim. Mirrors S10's tokenizer
// applied per line.
function NdjsonLine({ obj }) {
  // Render JSON.stringify(obj) on one line, then tokenize.
  // We embed manual JSX rather than parse JSON to keep it simple.
  return <L>{obj}</L>;
}

function PromptS5NdjsonStream() {
  // Render the canonical fresh-install events at narrow column widths
  // so the artboard stays readable. We elide some events with "...".
  const ev = (parts) => <L>{parts}</L>;
  return (
    <>
      <L><Dm># stdout — devforgeai install . --silent --components=...</Dm></L>
      <L><Dm># JetBrains Mono · one JSON object per line · monotonic timestamps</Dm></L>
      <Blank />
      <L><Gr>{'{'}</Gr><Gr>"ts":</Gr><G>"14:32:00.001Z"</G><Gr>,"phase":</Gr><G>"preflight"</G><Gr>,"action":</Gr><G>"start"</G><Gr>,"status":</Gr><G>"pending"</G><Gr>,"details":{'{'}</Gr><Gr>"session_id":</Gr><G>"9F2A1B"</G><Gr>,"installer_version":</Gr><G>"3.0.5"</G><Gr>{'}'}{'}'}</Gr></L>
      <L><Gr>{'{'}</Gr><Gr>"ts":</Gr><G>"14:32:00.218Z"</G><Gr>,"phase":</Gr><G>"preflight"</G><Gr>,"action":</Gr><G>"complete"</G><Gr>,"status":</Gr><G>"ok"</G><Gr>,"details":{'{'}</Gr><Gr>"node_version":</Gr><G>"20.10.0"</G><Gr>,"git_present":</Gr><M>true</M><Gr>{'}'}{'}'}</Gr></L>
      <L><Gr>{'{'}</Gr><Gr>"ts":</Gr><G>"14:32:00.305Z"</G><Gr>,"phase":</Gr><G>"manifest-load"</G><Gr>,"action":</Gr><G>"complete"</G><Gr>,"status":</Gr><G>"ok"</G><Gr>,"details":{'{'}</Gr><Gr>"mode":</Gr><G>"fresh"</G><Gr>{'}'}{'}'}</Gr></L>
      <L><Gr>{'{'}</Gr><Gr>"ts":</Gr><G>"14:32:00.421Z"</G><Gr>,"phase":</Gr><G>"plan"</G><Gr>,"action":</Gr><G>"complete"</G><Gr>,"status":</Gr><G>"ok"</G><Gr>,"details":{'{'}</Gr><Gr>"components":</Gr><Y>11</Y><Gr>,"files_total":</Gr><Y>472</Y><Gr>{'}'}{'}'}</Gr></L>
      <L><Gr>{'{'}</Gr><Gr>"ts":</Gr><G>"14:32:00.902Z"</G><Gr>,"phase":</Gr><G>"copy"</G><Gr>,"component":</Gr><G>"core-framework"</G><Gr>,"action":</Gr><G>"complete"</G><Gr>,"status":</Gr><G>"ok"</G><Gr>,"details":{'{'}</Gr><Gr>"files_copied":</Gr><Y>142</Y><Gr>{'}'}{'}'}</Gr></L>
      <L><Dm>... 4 more copy.complete lines ...</Dm></L>
      <L><Cy>{'{'}</Cy><Gr>"ts":</Gr><G>"14:32:30.910Z"</G><Gr>,"level":</Gr><G>"debug"</G><Gr>,"phase":</Gr><G>"copy"</G><Gr>,"component":</Gr><G>"context-files"</G><Gr>,"action":</Gr><G>"heartbeat"</G><Gr>,"details":{'{'}</Gr><Gr>"files_copied":</Gr><Y>4</Y><Gr>,"elapsed_ms":</Gr><Y>30000</Y><Gr>{'}'}</Gr><Cy>{'}'}</Cy></L>
      <L><Gr>{'{'}</Gr><Gr>"ts":</Gr><G>"14:32:34.187Z"</G><Gr>,"phase":</Gr><G>"copy"</G><Gr>,"component":</Gr><G>"context-files"</G><Gr>,"action":</Gr><G>"complete"</G><Gr>,"status":</Gr><G>"ok"</G><Gr>,"details":{'{'}</Gr><Gr>"streamed_files":</Gr><Y>1</Y><Gr>{'}'}{'}'}</Gr></L>
      <L><Gr>{'{'}</Gr><Gr>"ts":</Gr><G>"14:32:35.640Z"</G><Gr>,"phase":</Gr><G>"python"</G><Gr>,"component":</Gr><G>"python-cli"</G><Gr>,"action":</Gr><G>"start"</G><Gr>,"status":</Gr><G>"pending"</G><Gr>,"details":{'{'}</Gr><Gr>"venv_path":</Gr><G>"./.venv"</G><Gr>{'}'}{'}'}</Gr></L>
      <L><Gr>{'{'}</Gr><Gr>"ts":</Gr><G>"14:32:43.520Z"</G><Gr>,"phase":</Gr><G>"python"</G><Gr>,"component":</Gr><G>"python-cli"</G><Gr>,"action":</Gr><G>"complete"</G><Gr>,"status":</Gr><G>"ok"</G><Gr>,"details":{'{'}</Gr><Gr>"duration_ms":</Gr><Y>7880</Y><Gr>,"entry_point_ok":</Gr><M>true</M><Gr>{'}'}{'}'}</Gr></L>
      <L><Y>{'{'}</Y><Gr>"ts":</Gr><G>"14:32:43.610Z"</G><Gr>,"level":</Gr><G>"info"</G><Gr>,"phase":</Gr><G>"ide"</G><Gr>,"action":</Gr><G>"complete"</G><Gr>,"status":</Gr><G>"warn"</G><Gr>,"details":{'{'}</Gr><Gr>"action_taken":</Gr><G>"prepended"</G><Gr>{'}'}</Gr><Y>{'}'}</Y></L>
      <L><Gr>{'{'}</Gr><Gr>"ts":</Gr><G>"14:32:43.700Z"</G><Gr>,"phase":</Gr><G>"manifest-write"</G><Gr>,"action":</Gr><G>"complete"</G><Gr>,"status":</Gr><G>"ok"</G><Gr>,"details":{'{'}</Gr><Gr>"schema_version":</Gr><Y>2</Y><Gr>{'}'}{'}'}</Gr></L>
      <L><Gr>{'{'}</Gr><Gr>"ts":</Gr><G>"14:32:44.012Z"</G><Gr>,"phase":</Gr><G>"verify"</G><Gr>,"action":</Gr><G>"complete"</G><Gr>,"status":</Gr><G>"ok"</G><Gr>,"details":{'{'}</Gr><Gr>"files_verified":</Gr><Y>472</Y><Gr>,"sha256_mismatches":</Gr><Y>0</Y><Gr>{'}'}{'}'}</Gr></L>
      <L><Gb>{'{'}</Gb><Gr>"ts":</Gr><G>"14:32:44.015Z"</G><Gr>,"phase":</Gr><G>"done"</G><Gr>,"action":</Gr><G>"complete"</G><Gr>,"status":</Gr><G>"ok"</G><Gr>,"details":{'{'}</Gr><Gr>"duration_ms":</Gr><Y>44014</Y><Gr>,"exit_code":</Gr><Y>0</Y><Gr>,"rollback_invoked":</Gr><M>false</M><Gr>{'}'}</Gr><Gb>{'}'}</Gb></L>
    </>
  );
}

function PromptS5NdjsonError() {
  return (
    <>
      <L><Dm># Failure path — A1 Python missing in silent mode</Dm></L>
      <L><Dm># --auto-rollback default in CI; final event = exit 4</Dm></L>
      <Blank />
      <L><Gr>{'{'}</Gr><Gr>"ts":</Gr><G>"14:32:38.110Z"</G><Gr>,"phase":</Gr><G>"python"</G><Gr>,"component":</Gr><G>"python-cli"</G><Gr>,"action":</Gr><G>"start"</G><Gr>,"status":</Gr><G>"pending"</G><Gr>,"details":{'{}'}{'}'}</Gr></L>
      <L><Rb>{'{'}</Rb><Gr>"ts":</Gr><G>"14:32:38.142Z"</G><Gr>,"level":</Gr><R>"error"</R><Gr>,"phase":</Gr><G>"python"</G><Gr>,"action":</Gr><R>"fail"</R><Gr>,"status":</Gr><R>"error"</R><Gr>,"details":{'{'}</Gr><Gr>"error_code":</Gr><R>"E_PYTHON_MISSING"</R><Gr>,"error_class":</Gr><G>"python"</G><Gr>,"recoverable":</Gr><M>true</M><Gr>,"suggested_action":</Gr><G>"rerun-with-flag"</G><Gr>,"suggested_flag":</Gr><G>"--skip-python"</G><Gr>{'}'}</Gr><Rb>{'}'}</Rb></L>
      <L><Y>{'{'}</Y><Gr>"ts":</Gr><G>"14:32:38.190Z"</G><Gr>,"phase":</Gr><G>"rollback"</G><Gr>,"action":</Gr><G>"start"</G><Gr>,"status":</Gr><G>"pending"</G><Gr>,"details":{'{'}</Gr><Gr>"trigger":</Gr><G>"auto"</G><Gr>,"journal_entries":</Gr><Y>4</Y><Gr>{'}'}</Gr><Y>{'}'}</Y></L>
      <L><Gr>{'{'}</Gr><Gr>"ts":</Gr><G>"14:32:38.610Z"</G><Gr>,"phase":</Gr><G>"rollback"</G><Gr>,"action":</Gr><G>"complete"</G><Gr>,"status":</Gr><G>"ok"</G><Gr>,"details":{'{'}</Gr><Gr>"entries_reversed":</Gr><Y>4</Y><Gr>,"files_restored":</Gr><Y>328</Y><Gr>{'}'}{'}'}</Gr></L>
      <L><Rb>{'{'}</Rb><Gr>"ts":</Gr><G>"14:32:38.612Z"</G><Gr>,"level":</Gr><R>"error"</R><Gr>,"phase":</Gr><G>"done"</G><Gr>,"action":</Gr><G>"complete"</G><Gr>,"status":</Gr><R>"error"</R><Gr>,"details":{'{'}</Gr><Gr>"duration_ms":</Gr><Y>7320</Y><Gr>,"exit_code":</Gr><R>4</R><Gr>,"rollback_invoked":</Gr><M>true</M><Gr>{'}'}</Gr><Rb>{'}'}</Rb></L>
    </>
  );
}

Object.assign(window, { PromptS5NdjsonStream, PromptS5NdjsonError });
