Files
sideline/docs/superpowers/specs/2026-03-16-code-scroll-design.md
2026-03-16 01:48:18 -07:00

155 lines
4.3 KiB
Markdown

# 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, `<module>` 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 → `<module>`
**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 `<module>` 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