# PR: Add Interactive Mode with Profile-Based Initial Scaffold to GrowNet CLI

## Title

interactive: add live keyboard-driven mode with profiles, reset-preserving scaffold, and dual-input support

---

## Summary

This PR adds an **interactive mode** to the GrowNet command-line runner so a user can press keys live and send one input tick at a time into a persistent GrowNet instance.

The main goal is to let the user get **hands-on intuition** for the model:

- press `1 2 3 4 5 6 7`
- watch slot selection, firing, delivery, and growth behavior
- repeat patterns and see whether the network stabilizes or grows
- reset back to the same initial scaffold without rebuilding the CLI experience

This mode should feel like a **live probing / lab mode**, not just another batch scenario runner.

---

## Important architectural rule

Respect GrowNet's language-reference model:

- **Java** = core semantic / architectural reference
- **Python** = Python-language-style reference
- **Mojo** should track Python almost one-to-one
- **C++** follows Java as much as practical

For this PR:

- implement interactive mode in **Python first**
- do **not** contort Python to look Java-like
- keep code explicit and readable
- design it so Mojo can later track the Python implementation closely

---

## Core mental model

Interactive mode does **not** freeze GrowNet into a fixed architecture.

Instead:

- the profile/config defines the **initial scaffold**
- the live key stream provides **incremental inputs**
- GrowNet still remains free to:
  - create new slots
  - create new neurons
  - create new layers
  - create new regions

So the model is:

```text
initial scaffold + live key input + normal GrowNet growth
```

Reset means:

> rebuild the original scaffold from the same profile/config and start again from tick 0

---

## Required reading before coding

Read these before implementation:

1. `docs/READ_ORDER.md`
2. `docs/LANGUAGE_REFERENCE_POLICY.md`
3. `docs/CODING_STYLE_MUST_READ.md`
4. `docs/GOLDEN_RULE.md`
5. `docs/GROWTH.md`
6. `docs/CREATION_AND_GROWTH_POINTS.md`
7. `docs/contracts/grownet.contract.v5.json`
8. `docs/GrowNet_Design_Spec_V5.md`
9. `docs/TRACE_RUNNER.md`
10. `docs/TRACE_PARITY.md`
11. `docs/PARITY_DECISION_CHECKLIST.md`
12. `docs/BENCHMARK_RUNNER.md` if present

---

## Coding style requirements

These are mandatory:

- Follow `docs/CODING_STYLE_MUST_READ.md`
- No single- or double-character identifiers anywhere, including loops
- Keep Python explicit and readable
- Avoid clever one-liners
- Preserve determinism
- Preserve two-phase tick discipline
- Do not introduce speculative redesigns
- Do not change runtime semantics just to make interactive mode simpler
- Prefer obvious helper modules over one huge file

---

## Scope

### Implement in this PR

1. `--interactive` mode in the CLI
2. built-in interactive profiles
3. optional `--config` support for initial scaffold definition
4. normalized vs raw key-value mapping
5. reset-preserving scaffold rebuild
6. single-input and dual-input interactive behavior
7. compact and verbose terminal output modes
8. interactive docs
9. focused tests for parsing / profile loading / key mapping / reset behavior

### Do not implement in this PR

- full image-file / audio-file interactive ingestion
- full arbitrary 2D/3D live interactive editing
- Java interactive TUI unless it is trivial
- Mojo interactive mode
- C++ interactive mode
- benchmark redesign
- Blender integration

---

# Main design goal

Interactive mode should be a **separate execution mode**:

- trace mode = explain what happened
- benchmark mode = measure performance
- interactive mode = let the user probe the model live

It should reuse the real runtime, not a fake toy runtime.

---

# Phase 1 — CLI surface

## 1. Add interactive flags

Extend the CLI to support at least:

```text
--interactive
--profile single_scalar|dual_scalar|growth_probe
--config path/to/interactive_config.json
--normalize-inputs normalized|raw
--interactive-output compact|verbose|jsonl
--interactive-trace on|off
```

### Notes

- `--interactive` selects interactive mode
- `--profile` selects a built-in initial scaffold
- `--config` overrides or replaces the built-in profile with a user-defined scaffold
- `--normalize-inputs normalized|raw` controls how numeric keys map to values
- `--interactive-output` controls how much is printed after each tick
- `--interactive-trace on|off` controls whether full trace events are emitted on each tick

### Preferred defaults

If the user runs:

```bash
./grownet.sh --lang python --interactive
```

default to:

- profile = `single_scalar`
- normalize-inputs = `normalized`
- interactive-output = `compact`
- interactive-trace = `off`

---

# Phase 2 — interactive profiles

## 2. Built-in profiles define the initial scaffold only

Do **not** call these old-style scenarios.
Use the term **profile**.

### Required built-in profiles

#### `single_scalar`
- one input port
- simple scalar scaffold
- good for immediate probing

#### `dual_scalar`
- two scalar input ports
- top number row = input port A
- numpad = input port B where distinguishable
- preserve current value of the other port between ticks

#### `growth_probe`
- a small scaffold biased toward making growth behavior visible
- useful for repeated novelty experiments

### Optional / provisional
If you add a `grid_2d` profile, mark it clearly as provisional unless the runtime path is already strong enough.

## 3. Profile semantics

Each profile should define at least:

- dimensions / rank
- initial regions
- initial layers
- excitatory / inhibitory / modulatory counts
- input ports
- key mapping
- normalization default
- output display default

---

# Phase 3 — config-driven scaffold

## 4. Add `--config` support for interactive mode

Interactive mode should support a user-supplied config file that defines the initial scaffold.

### Example shape

```json
{
  "name": "dual_scalar_probe",
  "interactive": {
    "output": "compact",
    "trace": false,
    "normalize_inputs": "normalized"
  },
  "input_space": {
    "rank": 1,
    "ports": [
      {"name": "a"},
      {"name": "b"}
    ]
  },
  "network": {
    "regions": [
      {
        "name": "main",
        "layers": [
          {
            "excitatory_count": 20,
            "inhibitory_count": 4,
            "modulatory_count": 2
          }
        ]
      }
    ]
  }
}
```

### Important

This config defines the **initial scaffold** only.
GrowNet remains free to grow after the interactive session starts.

---

# Phase 4 — key mapping semantics

## 5. Numeric key mapping

### Normalized mode
Map:

```text
0 -> 0.0
1 -> 0.1
2 -> 0.2
...
9 -> 0.9
```

### Raw mode
Map:

```text
0 -> 0.0
1 -> 1.0
2 -> 2.0
...
9 -> 9.0
```

## 6. Single-input profile behavior

For `single_scalar`:

- pressing a numeric key sends one tick
- that tick injects the mapped value to the single input port

Example:

```text
press "4" -> one tick with input = 0.4 in normalized mode
```

## 7. Dual-input profile behavior

For `dual_scalar`:

- top number row updates **input port A**
- numpad updates **input port B**, where terminal/platform distinguishes numpad events
- each key press triggers **one tick**
- if only one port was updated, the other port retains its previous value

### Example

- current state: `A=0.2`, `B=0.7`
- press top-row `5`
- next tick uses `A=0.5`, `B=0.7`

- press numpad `3`
- next tick uses `A=0.5`, `B=0.3`

## 8. Numpad fallback

Terminal/numpad distinction is not always reliable across all terminals/platforms.

So implement this carefully:

### Preferred
Use distinct keypad input when the platform/terminal exposes it.

### Required fallback
Provide an alternate second-port mapping if numpad cannot be distinguished.

Example fallback mapping:
- top row digits = input port A
- `qwertyuiop` or another clearly-documented key row = input port B

Document the fallback clearly in the help text and interactive startup panel.

Do **not** silently pretend numpad is always distinguishable if it is not.

---

# Phase 5 — interactive control keys

## 9. Add a small control vocabulary

Support at least:

```text
space = run one tick with current input state again
r     = reset network to original scaffold/profile/config
s     = print current metrics summary
t     = toggle compact/verbose trace display
c     = clear screen or reprint panel
q     = quit
h     = help
```

### Important

Keep the control set small and memorable.

---

# Phase 6 — session state model

## 10. Maintain persistent session state

Interactive mode should keep an in-memory session object containing:

- original profile/config
- current region/network instance
- current tick number
- current input-port state
- current output mode
- current trace mode

## 11. Reset behavior

When `r` is pressed:

- discard the current live network
- rebuild from the original profile/config
- reset tick counter
- reset current input-port state to defaults

This is the **reset-preserving config** behavior.

---

# Phase 7 — output behavior

## 12. Compact output mode

Default per-key output should be concise and useful.

Example:

```text
tick=12 port=a input=0.4 fired=true slot=3 delivered=1 total_slots=5 neurons=2 layers=1 regions=1
```

This should help the user feel the model quickly.

## 13. Verbose output mode

Verbose mode should emit richer details after each tick.

It may include:

- key pressed
- port updated
- full trace summary
- growth events
- metrics

If trace is enabled, verbose mode can show or summarize trace events.

## 14. JSONL output mode

If `--interactive-output jsonl` is selected, emit one JSON object per tick summary.

This is useful for later replay or tooling.

Example:

```json
{"event":"interactive.tick","tick":12,"profile":"dual_scalar","updated_port":"a","input_a":0.4,"input_b":0.7,"fired":true,"delivered_events":1,"total_slots":5,"layer_count":1,"region_count":1}
```

---

# Phase 8 — implementation approach

## 15. Implement interactive mode in Python first

Python is the right first implementation because:

- easier terminal control
- easier readable orchestration
- aligns with Python/Mojo near-1:1 strategy

If the CLI is invoked with:

```bash
./grownet.sh --lang java --interactive
```

it is acceptable for this PR to return a clear “interactive mode not implemented for java yet” message, **if** full Java interactive support would add disproportionate complexity.

### Important

Be explicit in docs and help text if interactive mode is Python-first in this PR.

---

# Phase 9 — likely file structure

A clean structure might look like:

```text
src/python/interactive/
    __init__.py
    interactive_main.py
    interactive_session.py
    interactive_profiles.py
    interactive_config.py
    interactive_keyboard.py
    interactive_renderer.py
```

### Responsibilities

- `interactive_main.py` — entry point
- `interactive_session.py` — live network/session state
- `interactive_profiles.py` — built-in profiles
- `interactive_config.py` — config loading/validation
- `interactive_keyboard.py` — terminal key handling and key mapping
- `interactive_renderer.py` — compact/verbose/jsonl display

Keep files small and obvious.

---

# Phase 10 — tests

## 16. Add focused tests

At minimum, test:

- CLI parsing for `--interactive`
- profile loading
- config loading
- normalized vs raw value mapping
- reset rebuilds the original scaffold
- dual-input state retention behavior
- second-port fallback mapping
- compact output shape
- JSONL output shape

### Important

Do not write fragile terminal-integration tests that depend on a real live terminal session.
Abstract the key-mapping/session logic so it can be unit-tested.

---

# Phase 11 — docs

## 17. Add a dedicated interactive doc

Create:

```text
docs/INTERACTIVE_RUNNER.md
```

Include:

- what interactive mode is for
- built-in profiles
- config support
- normalized vs raw input mapping
- top-row vs numpad / fallback mapping
- reset behavior
- example commands
- Python-first scope if applicable

## 18. Update `docs/TRACE_RUNNER.md`

Add a short section explaining that the CLI now supports:

- trace mode
- benchmark mode
- interactive mode

and link to `docs/INTERACTIVE_RUNNER.md`.

---

## Acceptance criteria

This PR is complete when:

1. `./grownet.sh --lang python --interactive` works
2. built-in profiles exist:
   - `single_scalar`
   - `dual_scalar`
   - `growth_probe`
3. `--config` can define the initial scaffold
4. normalized and raw key mapping both work
5. each key press can trigger one tick
6. dual-input mode retains the other port state between ticks
7. reset rebuilds the original scaffold
8. output supports compact / verbose / jsonl modes
9. docs explain how to use interactive mode
10. tests cover the non-terminal logic cleanly

---

## Explicit non-goals

Do not do these in this PR:

- full audio/image interactive ingestion
- full arbitrary 2D/3D live editing UI
- Java interactive mode unless trivial
- Mojo interactive mode
- C++ interactive mode
- benchmark redesign
- Blender integration

---

## Suggested commit structure

1. add CLI parsing and interactive session plumbing
2. add built-in profiles and config loading
3. add keyboard mapping and renderer
4. add docs and tests

---

## Final response expected from Codex

At the end, provide:

1. summary of what changed
2. files changed
3. example interactive commands
4. supported profiles
5. how numpad fallback works
6. tests run
7. any follow-up ideas for config-driven file inputs / image / audio support
