# Code Scroll Mode — Design Spec **Date:** 2026-03-16 **Branch:** feat/code-scroll **Status:** Approved --- ## Overview Add a `--code` CLI flag that puts MAINLINE into "source consciousness" mode. Instead of RSS headlines or poetry stanzas, the program's own source code scrolls upward as large OTF half-block characters with the standard white-hot → deep green gradient. Each scroll item is one non-blank, non-comment line from `engine/*.py`, attributed to its enclosing function/class scope and dotted module path. --- ## Goals - Mirror the existing `--poetry` mode pattern as closely as possible - Zero new runtime dependencies (stdlib `ast` and `pathlib` only) - No changes to `scroll.py` or the render pipeline - The item tuple shape `(text, src, ts)` is unchanged --- ## New Files ### `engine/fetch_code.py` Single public function `fetch_code()` that returns `(items, line_count, 0)`. **Algorithm:** 1. Glob `engine/*.py` in sorted order 2. For each file: a. Read source text b. `ast.parse(source)` → build a `{line_number: scope_label}` map by walking all `FunctionDef`, `AsyncFunctionDef`, and `ClassDef` nodes. Each node covers its full line range. Inner scopes override outer ones. c. Iterate source lines (1-indexed). Skip if: - The stripped line is empty - The stripped line starts with `#` d. For each kept line emit: - `text` = `line.rstrip()` (preserve indentation for readability in the big render) - `src` = scope label from the AST map, e.g. `stream()` for functions, `MicMonitor` for classes, `` for top-level lines - `ts` = dotted module path derived from filename, e.g. `engine/scroll.py` → `engine.scroll` 3. Return `(items, len(items), 0)` **Scope label rules:** - `FunctionDef` / `AsyncFunctionDef` → `name()` - `ClassDef` → `name` (no parens) - No enclosing node → `` **Dependencies:** `ast`, `pathlib` — stdlib only. --- ## Modified Files ### `engine/config.py` Extend `MODE` detection to recognise `--code`: ```python MODE = ( "poetry" if "--poetry" in sys.argv or "-p" in sys.argv else "code" if "--code" in sys.argv else "news" ) ``` ### `engine/app.py` **Subtitle line** — extend the subtitle dict: ```python _subtitle = { "poetry": "literary consciousness stream", "code": "source consciousness stream", }.get(config.MODE, "digital consciousness stream") ``` **Boot sequence** — add `elif config.MODE == "code":` branch after the poetry branch: ```python elif config.MODE == "code": from engine.fetch_code import fetch_code slow_print(" > INITIALIZING SOURCE ARRAY...\n") time.sleep(0.2) print() items, line_count, _ = fetch_code() print() print(f" {G_DIM}>{RST} {G_MID}{line_count} LINES ACQUIRED{RST}") ``` No cache save/load — local source files are read instantly and change only on disk writes. --- ## Data Flow ``` engine/*.py (sorted) │ ▼ fetch_code() │ ast.parse → scope map │ filter blank + comment lines │ emit (line, scope(), engine.module) ▼ items: List[Tuple[str, str, str]] │ ▼ stream(items, ntfy, mic) ← unchanged │ ▼ next_headline() shuffles + recycles automatically ``` --- ## Error Handling - If a file fails to `ast.parse` (malformed source), fall back to `` scope for all lines in that file — do not crash. - If `engine/` contains no `.py` files (shouldn't happen in practice), `fetch_code()` returns an empty list; `app.py`'s existing `if not items:` guard handles this. --- ## Testing New file: `tests/test_fetch_code.py` | Test | Assertion | |------|-----------| | `test_items_are_tuples` | Every item from `fetch_code()` is a 3-tuple of strings | | `test_blank_and_comment_lines_excluded` | No item text is empty; no item text (stripped) starts with `#` | | `test_module_path_format` | Every `ts` field matches pattern `engine\.\w+` | No mocking — tests read the real engine source files, keeping them honest against actual content. --- ## CLI ```bash python3 mainline.py --code # source consciousness mode uv run mainline.py --code ``` Compatible with all existing flags (`--no-font-picker`, `--font-file`, `--firehose`, etc.). --- ## Out of Scope - Syntax highlighting / token-aware coloring (can be added later) - `--code-dir` flag for pointing at arbitrary directories (YAGNI) - Caching code items to disk