# nagent: Actionable Takeaways for Manual Slop

**Track:** `nagent_review_20260608`
**Date:** 2026-06-08
**Companion to:** `report.md` (deep-dive comparison), `comparison_table.md` (flat reference), `decisions.md` (10 future-track candidates)
**Author:** Tier 2 Tech Lead
**Read this if:** you're planning a future track, designing a UX change, or wondering "what should we actually do with nagent's ideas?"

> **What this document is.** The deep-dive in `report.md` maps nagent's 14 principles 1:1 to Manual Slop's existing features and finds six pitfalls. That's the *diagnosis*. This document is the *prescription* — 10 concrete patterns nagent uses that we can borrow, with each one grounded in actual code we've read and an explicit "what to do" path.
>
> **What this document is not.** It is not a critique of Manual Slop, not a recommendation to rewrite anything, and not a "framework migration" plan. nagent is a 4,000-line reference; Manual Slop is 13,000+ lines of production code with a GUI, real persistence, real HITL. The right reaction to nagent is *steal the patterns that fit our domain*, not adopt the whole system.
>
> **Domain filter.** Every takeaway below is tagged **Application**, **Meta-Tooling**, or **Both** — per `docs/guide_meta_boundary.md`. nagent lives in the Meta-Tooling domain by default. Some patterns transfer cleanly to the Application; some only make sense for the agents that build the Application. Don't apply a "Both" pattern without checking the domain.

---

## 0. The 30-second version

If you only read 3 things, read these:

1. **Make state visible at the right layer** (§1) — nagent puts state in files you can `cat`. Manual Slop already does this for *editable* state (`disc_entries`, `ContextPreset`, `FileItem`, project TOML) but the *provider-side* history still lives in process globals. *Steal the visibility, not the file abstraction.*

2. **Make the protocol readable in the conversation log** (§2) — nagent's conversation is plain text with `<nagent-shell>...</nagent-shell>` tags you can grep. Manual Slop's comms log is JSON-L with provider-native function-call blobs. *Add a "what the model actually said" projection layer.*

3. **Make sub-agents a first-class primitive for the Application, not just MMA** (§3) — nagent has one sub-conversation mechanism, used everywhere. Manual Slop has sub-agents for MMA workers but not for 1:1 discussions. *The user explicitly wants this — it's the highest-priority future track.*

The other 7 patterns are below. Each is grounded in code, not vibes.

---

## 1. State visibility — files for the things that matter, processes for the things that don't

**nagent's pattern.** Every piece of state that *survives* lives in a file under `~/.nagent/`:
- `conversations/<conversation_name>` — the conversation transcript
- `conversations/file-index-{pid}.json` — file_id → conversation map
- `splits/<slug>-<uuid>/index.json` — large-file split metadata
- `splits/<slug>-<uuid>/<slug>-0001.<ext>` — segment files
- `splits/<slug>-<uuid>/<slug>.patch` — unified diff patch

The state that *doesn't survive* is the running process: LLM call result, current turn, parse state. The boundary is sharp: anything the user might want to inspect, diff, copy, or back up is a file.

**Manual Slop today.** Already does this for the *editable* surface:
- `manual_slop.toml` (project) — `discussion.discussions[<take_name>].history` (`app_controller.py:3236`)
- `conductor/tracks/<id>/{spec,plan,state.toml,metadata.json}` — track state
- `personas.toml` (global + project) — persona config
- `tool_presets.toml` — tool weights
- `logs/sessions/<session_id>/comms.log` — JSON-L of every LLM call (`app_controller.py:379`)

What *isn't* in files:
- `ai_client._anthropic_history`, `_deepseek_history`, `_minimax_history` — 3 per-provider lists in process globals (`ai_client.py:123-132`)
- The current `disc_entries[i]["content"]` AI response *before* the user flushes the discussion to TOML
- The current `files` / `context_files` / `screenshots` until the next `_flush_to_project`

**Actionable idea.** Add a **"Live State Inspector"** panel in the GUI that shows *all* the state that's currently in process — provider history lengths, current discussion entry count, the actual bytes that haven't been flushed yet, the `ai_client` module globals being read. This is a UX change, not an architecture change. It costs ~200 lines (a panel that reads from `app_controller._get_state_for_inspector()` and renders a tree).

**Domain:** Both. The Application benefits from "what is the AI actually remembering right now?"; the Meta-Tooling benefits from "did my edit actually flow through to the right state?"

**Effort:** Small. *Not* a new track — this can be a one-day add-on once the inspector is specced.

**Cross-references:** Decision candidate #3 (Stateless LLMClient) becomes more attractive once the inspector exists, because you'd have a UI to verify the stateless refactor preserves behavior.

---

## 2. A readable conversation log — text the user can grep, not just JSON-L

**nagent's pattern.** The conversation file is plain text. Every action appears as a tag:
```
<nagent-shell>python3 -m unittest discover -s tests -v</nagent-shell>
<nagent-shell-result>
exit_code: 0
stdout: ...
</nagent-shell-result>
<nagent-response>All 12 tests pass.</nagent-response>
```

The user can `grep -n "exit_code: [^0]" ~/.nagent/conversations/latest-*` to find all failed shell runs. The user can `git diff` the conversation file. The user can `cp` it to a teammate. The protocol is *the storage format*, not a side channel.

**Manual Slop today.** `comms.log` is JSON-L with provider-native function-call blobs. To find "did the model call `read_file` with the right path?" you need to load JSON, navigate to the right `function_call` entry, know the provider's schema, and dig out the args. The `function_call` itself is opaque — you can't `grep` for it without understanding the provider's wrapping.

The `app.disc_entries` GUI display *is* the readable projection — when you look at a discussion in the GUI, you see the user/AI turns. But:
1. The view is in the GUI only; the underlying `comms.log` is JSON-L.
2. The thinking trace, tool calls, and tool results are flattened into the entry's `content` field via `thinking_parser.py`. You see the *result* but not the *call* unless you open the read mode.
3. There's no per-tool-call "View raw" button in the comms log panel (per `docs/guide_gui_2.md`).

**Actionable idea — option A (small, UI-only).** Add a **"Reveal Raw"** toggle on the comms log panel that, when on, shows the JSON-L entry *next to* the rendered view, with the JSON pretty-printed. The user can copy either the rendered text or the raw JSON. ~100 lines.

**Actionable idea — option B (medium, behavioral).** Project the conversation log into a sibling markdown file as it's written. Every `comms.log` entry gets a corresponding `<session_id>.md` line that says "model called `read_file('src/foo.py')` at <ts>." The user can `cat`, `grep`, or `tail -f` this file. The GUI reads from the same source of truth (the markdown) instead of from the JSON-L. ~300 lines + a streaming write hook in `ai_client`.

**Domain:** Both. Option A is UI work in the Application. Option B benefits the Meta-Tooling more — an external agent that needs to understand what the Application AI did can read the markdown without parsing JSON-L.

**Effort:** A is small. B is medium. **Pick A first**; the user-correction in `report.md §3` shows the user is already on top of editable-discussion nuance, so a small UX win here validates the larger bet.

**Cross-references:** Decision candidate #6 (git-history injection) — the markdown projection is the same kind of "explicit data artifact for the AI's input/output" pattern, just for the comms log instead of git history.

---

## 3. Sub-agents as a first-class primitive for 1:1 discussions

**nagent's pattern.** The `<nagent-conversation>` tag in `bin/nagent:execute_agent(...)` is the *only* sub-agent mechanism. Used everywhere: investigation, research, large-output work, debugging. The child is a fresh process with `Invocation = "delegated"`, an isolated conversation file, and a `<nagent-conversation-result>` tag returned to the parent with the child's exit code + output + stderr + token totals.

**Manual Slop today.** Sub-agents exist for MMA:
- `scripts/mma_exec.py` — Tier 3/4 worker subprocess
- `src/multi_agent_conductor.py:run_worker_lifecycle` — worker lifecycle
- `src/dag_engine.py` — ticket DAG and per-ticket worker pool

But for 1:1 discussions (`simulation/workflow_sim.py:WorkflowSimulator.run_discussion_turn_async`), there's no sub-agent primitive. The user types a prompt, the AI responds, the loop continues. If the user wants the AI to "investigate this file" or "look up this API," the answer has to come from the same conversation.

**Why it matters.** The MMA pattern is *already* the prototype. `mma_exec.py` is a real subprocess with Context Amnesia and a clean prompt boundary. The only thing missing is a way to invoke it from the 1:1 chat loop without going through the full MMA tier system.

**Actionable idea.** Build `src/sub_conversation.py:SubConversationRunner` (Decision candidate #1, already specced in `decisions.md`):
```python
class SubConversationRunner:
    async def spawn(
        self,
        prompt: str,
        *,
        allowed_tools: list[str] | None = None,
        system_prompt: str | None = None,
        timeout_s: int = 120,
    ) -> SubConversationResult:
        # Reuse mma_exec.py as the subprocess template
        # Return the child's <nagent-response> content + token usage
        ...
```

Wire it into the GUI as a new "Investigate…" button on the message panel (`gui_2.py:4513+`). The button opens a small modal: "Ask a sub-agent: ___ [Investigate]". The sub-agent runs, the result is inserted as a "User" role entry in the current discussion, and the next LLM call sees it.

**Domain:** Application. (The Meta-Tooling could use the same primitive from `scripts/`, but the win is in the App.)

**Effort:** Medium. 2-3 phases. **HIGH priority** because the user explicitly wants it.

**Cross-references:** Decision candidate #2 (RAG pre-staging) is the natural second use of this primitive — a sub-conversation that pre-builds the RAG index before a long discussion.

---

## 4. File-identity over file-path — a stable `st_dev:st_ino` is rename-safe

**nagent's pattern.** `nagent_file_edit_lib.py:file_id_for_path(path) -> "{st_dev}:{st_ino}"`. The per-file conversation index keys by inode, not by path. Rename the file in place (same inode) → same conversation. Move the file across dirs (same inode) → same conversation. This is the right primitive for "memory attached to the artifact, not the path."

**Manual Slop today.** `models.FileItem.path: str` — path-keyed. `project.discussion.discussions[<take>].context_snapshot` is a list of `FileItem.to_dict()` dicts, indexed by position in the list. Rename the file in your editor → `FileItem.path` is stale, `aggregate.py:build_file_items` re-reads the old path, may fail. The curation memory *survives* the rename (it's keyed by name in the project TOML) but the file lookup at render time does not.

**Actionable idea — small (additive).** Add a `file_id: str` field to `FileItem` populated at load time via `os.stat(path).st_dev:st_ino`. Use it as the lookup key in the `context_snapshot` list. On file-read failure, attempt a fuzzy match: same basename in the same directory tree, or same `file_id` under a new path. ~150 lines + a migration for existing project TOML files (path-only becomes path + file_id).

**Actionable idea — bigger (architectural).** If you do this, also rethink the `ContextPreset` storage. The current schema is a flat list of `FileItem` dicts. nagent's analog is a per-file `IndexEntry { file_id, path, last_seen, conversation, last_summary }`. A path rename in nagent updates `path` in the index but leaves `file_id` stable; in Manual Slop a path rename would orphan the entire `FileItem`.

**Domain:** Application. (The Meta-Tooling would benefit from a stable file_id when navigating references across many files in a long session.)

**Effort:** Small (additive) or medium (architectural). The additive path is the right starting point; the architectural rewrite is overkill for a feature that already works for 95% of cases.

**Cross-references:** Decision candidate #7 (per-file conversation log) — `file_id` is the prerequisite for this candidate.

---

## 5. One loop, one file — make the agent's brain visible by default

**nagent's pattern.** `bin/nagent:run_agent_loop` is ~50 lines. `main()` reads CLI args, sets up the conversation file, calls `run_agent_loop`, exits. The conversation file accumulates over the entire session. The "agent" *is* the file plus a transient process.

**Manual Slop today.** Three parallel loops, each in a different file:
- `src/ai_client.py:_send_<provider>` (per-provider, ~100-200 lines each × 5 providers) — the LLM-call loop
- `src/multi_agent_conductor.py:ConductorEngine.run` — the MMA loop
- `simulation/workflow_sim.py:WorkflowSimulator.run_discussion_turn_async` — the 1:1 chat loop

Each loop has the same shape (build prompt → call LLM → parse response → dispatch tools → repeat) but the data structures differ. A reader has to hold three mental models.

**Actionable idea — UX win, not architecture change.** Surface the *unified loop shape* in the diagnostics panel. The diagnostics panel already exists (`gui_2.py` §"Diagnostics Hub" per the Readme). Add a section "Loop Inspector" that shows, for each of the three loops:
- Last N iterations of: input tokens, output tokens, tool calls made, tool results, parse failures
- Color-coded: same shape across all three loops, different data sources
- "View raw" drill-down to the actual function call

This is *not* a refactor. It's making the existing three loops legible. ~200 lines.

**Actionable idea — bigger refactor.** Extract a `src/llm_loop.py:run_loop(conversation, provider, tool_dispatch, parse_response, ...)` that's called by all three. This is Decision candidate #5.5 (not in `decisions.md`; would be a new candidate). Effort: large. Value: real but the current separation is readable.

**Domain:** Both. The UX win is in the Application. The refactor is neutral but helps the Meta-Tooling when agents need to reason about the loop.

**Effort:** UX win is small. Refactor is large. **Do the UX win first.**

**Cross-references:** Decision candidate #3 (Stateless LLMClient) — the refactor becomes more attractive if a unified loop exposes the data flow more clearly.

---

## 6. Visible retry on protocol failure — turn errors into conversation data

**nagent's pattern.** `bin/nagent:run_agent_loop` has `MAX_FORMAT_RETRIES = 3`. On a parse failure:
```python
append_to_conversation(
    conversation_file,
    f"<agent-response>\n{llm_output}\n</agent-response>\n"
    f"<system>Invalid nagent response format: {parse_error}. "
    f"Respond only with valid nagent tags.</system>",
)
```

The bad output is *appended to the conversation* with a `<system>` correction. The next call sees its own previous failure and the correction message. The user can `grep` the conversation for `<system>` to find every retry.

**Manual Slop today.** `_send_<provider>` loops internally; on a tool-call parse failure it... retries. But the failure isn't visible in `comms.log` as a first-class entry — it's swallowed by the loop. The `tier4_qa` interceptor (per `docs/guide_ai_client.md` §"Tier 4 QA") catches *errors from tool execution* and forwards them to a cheap sub-agent for a 20-word summary, but parse failures don't go through this path.

**Actionable idea — small, high value.** Add a `parse_failures` counter and a "Last 5 parse failures" section to the diagnostics panel. The counter increments on each `parse_response` failure; the section shows the model output, the error message, and the time. ~50 lines. The user gets to see *what* the model is getting wrong — useful for prompt engineering.

**Actionable idea — medium, prompt-quality win.** When a parse failure happens, append a "self-correction" entry to `disc_entries` as a `role: "System"` entry. The next AI call sees the correction in the visible discussion history. The user can see the corrections and can edit them. ~150 lines.

**Domain:** Both. The diagnostics panel is Application UX. The self-correction entry is neutral — useful for any agent that reads `disc_entries`.

**Effort:** Small for option 1. Medium for option 2. **Do option 1 first.**

**Cross-references:** nagent §5 "The loop" — the retry visibility is a load-bearing part of nagent's debuggability claim.

---

## 7. "Inspect this file" / "Read this URL" as *prompts*, not function calls

**nagent's pattern.** `<nagent-read path="..."/>` is a self-closing tag. The model emits it; the parser matches; `execute_read` runs. The model doesn't need to know the function-call schema for the LLM SDK — it just needs to emit text containing a tag.

**Manual Slop today.** `read_file(path)` is a function call. The model has to know the function signature, format the JSON, embed it in the right `tool_use` block. The training data for "emit a `<nagent-read>` tag" is zero; the training data for "emit a `read_file` tool call" is high. *Function calling wins on capability and on training*; *tag protocols win on debuggability*.

**Actionable idea — both, but in different places.** This is the *one* place where the existing reports lean toward "different mechanism, both right." Don't replace the Application's function calling. But for the Meta-Tooling, document a *Meta-Tooling DSL* in `conductor/code_styleguides/` for use by external agents when they need to invoke Manual Slop's tools via the bridge script. The DSL would look like:
```
<ms-tool name="read_file" path="src/foo.py" />
<ms-tool name="py_get_skeleton" path="src/foo.py" symbol="MyClass" />
```

The bridge script (`scripts/mma_exec.py` or whatever the Meta-Tooling bridge is) translates these to the underlying function calls. The external agent's prompt training data does *not* need to know the function-calling JSON schema for every Manual Slop tool — it just needs to know the DSL.

**This is Decision candidate #4 (intent-based DSL) from `decisions.md`** — but reframed: it's not a Meta-Tooling-*side* DSL, it's a *bridge* DSL. The Application's function-calling stays.

**Domain:** Meta-Tooling. The Application doesn't need this.

**Effort:** Research spike, per the user's own assessment: "no where near that ideation yet." Document the design space; don't build it.

**Cross-references:** Decision candidate #4. Also nagent §12 (tool discovery) — the DSL would be the bridge-side analog of `--description` self-describing executables.

---

## 8. Self-describing tools — let the tool tell the agent what it does

**nagent's pattern.** `nagent_cli.py:exit_on_description(description)` is called at the top of every executable:
```python
def exit_on_description(description: str) -> None:
    if "--description" in sys.argv:
        print(description)
        raise SystemExit(0)
```

`nagent_cli.py:collect_bin_tool_descriptions(bin_dir)` runs each tool in `bin/` with `--description`, captures stdout, concatenates. The startup prompt includes the concatenated descriptions automatically. *Adding a new tool is: drop a script, write a description.* The system auto-discovers.

**Manual Slop today.** `src/mcp_client.py:dispatch(...)` is a flat if/elif chain with 45+ branches. Adding a tool requires:
1. Edit `dispatch()` to add the branch
2. Update the security allowlist in `_resolve_and_check` (if filesystem access)
3. Update the AI capability declaration in `get_tool_schemas()`
4. Add tests

**Actionable idea — defer to `mcp_architecture_refactor_20260606`.** This is already on the board as Decision candidate #5 (subsumed). The "sub-MCP" extraction that the refactor proposes is *exactly* the right scope for the self-describing pattern — each sub-MCP is a self-contained module with its own tool registry, and `collect_tool_descriptions` becomes a method on the sub-MCP class.

**Don't** try to add this incrementally. The dispatch chain is large enough that half-measures (e.g. a per-tool decorator that auto-registers but still requires a manual allowlist edit) are net-negative. Wait for the refactor.

**Domain:** Both. (Largely Application — the dispatch is in `mcp_client.py`. But the pattern would also be useful for the Meta-Tooling's `scripts/` directory.)

**Effort:** Subsumed by `mcp_architecture_refactor_20260606`.

**Cross-references:** Decision candidate #5. Already documented.

---

## 9. Edit-the-input, not the output — make the prompt the artifact

**nagent's claim (verbatim from README).** *"Don't edit the output artifacts. Edit the prompt."* If the LLM gives a bad answer, the fix is in the prompt or the inputs — not by hand-patching the output. The conversation file *contains* the prompt. Editing the conversation is editing the prompt for the next turn.

**Manual Slop today.** The user can edit any `disc_entries[i]["content"]` directly via the `[Edit]` mode in the GUI (per `report.md §3 A1`). But the edited entry goes into the *abstracted entry list*, not into the *raw provider history*. The next LLM call sees:
- The full `disc_entries` rendered as markdown (with the user's edits)
- BUT the `ai_client._anthropic_history` (and siblings) is the *raw* provider-side list, with the *original* AI response and the *original* function calls

So the user edits the *projection* but not the *source*. If the user corrects an AI response that included a bad tool call, the *display* shows the correction but the *provider's next call* will replay the original bad tool call as a "previous tool result" in the history. The two diverge.

**This is subtle but important.** nagent avoids this entirely because the conversation file *is* the prompt — there's no separate "raw provider history" to keep in sync.

**Actionable idea — small, surgical.** When the user edits an entry's `content` in `[Edit]` mode, *also* rewrite the corresponding `ai_client._<provider>_history[i]["content"]` to match. The user sees one source of truth; the provider sees the same source of truth. ~100 lines + a careful test for Anthropic's content-block semantics (it has multiple content blocks per message, not a single string).

**Actionable idea — bigger, the right architecture.** Stop maintaining two histories. Make `disc_entries` the *only* history. `ai_client._<provider>_history` becomes a *projection* of `disc_entries`, rebuilt on each send(). This is part of Decision candidate #3 (Stateless LLMClient) — the `Conversation` object becomes the single source of truth.

**Domain:** Both. The edit-the-projection fix is Application UX. The single-history architecture is Application + (benefiting) Meta-Tooling.

**Effort:** Small for option 1, large for option 2. **Option 1 is the right starting point** — it's a known issue with a known fix, and the user-correction in `report.md §3` shows the user is on top of editable-discussion nuance.

**Cross-references:** Decision candidate #3 (Stateless LLMClient). Also nagent §3 (conversations are editable state) — the philosophy is "one editable source of truth," and Manual Slop currently has two.

---

## 10. Sub-agents return a *concise artifact*, not a full transcript

**nagent's pattern.** `<nagent-conversation-result conversation="..." tokens_in="..." tokens_out="...">` contains only the child's `<nagent-response>` body + exit code + stderr. The parent's conversation is *not* polluted with the child's intermediate reads, shell calls, or retries. The parent gets a *distilled* result.

**Manual Slop today (MMA path).** `multi_agent_conductor.py` returns the worker's final response to the parent (the `ConductorEngine`). The worker's intermediate steps are logged to `comms.log` but not propagated. So MMA *does* follow the nagent pattern for sub-agent outputs. *This is good.*

**Manual Slop today (1:1 chat, no sub-agents).** No equivalent. The user can't ask a sub-agent and get a distilled answer. The whole point of the user-flagged Decision candidate #1 is to add this — and the implementation should follow nagent's pattern: the sub-agent returns a *string artifact*, not its full conversation log.

**Actionable idea — design constraint on the upcoming track.** When implementing Decision candidate #1 (SubConversationRunner), specify the return type as `SubConversationResult { artifact: str, tokens_in: int, tokens_out: int, exit_code: int, errors: list[str] }`. Do *not* return the child's full conversation. The parent's `disc_entries` gets one new "User" entry containing `artifact`. The child's full transcript is persisted to `~/.manual_slop/sub_conversations/<uuid>.jsonl` for debugging but is not in the parent's visible discussion.

**Domain:** Application (this is the design constraint for candidate #1).

**Effort:** Zero net new effort — this is a design constraint, not a feature. Bake it into the spec for candidate #1.

**Cross-references:** Decision candidate #1. nagent §9 (sub-conversations). The `MAX_FORMAT_RETRIES = 3` retry budget in nagent also informs the design — the sub-agent should be allowed to retry internally, but its final artifact to the parent should be a single string.

---

## Cross-cutting observations (not patterns, but framing)

### A. nagent's "files are the system" is the same philosophy as Manual Slop's project TOML + conductor tracks

The *philosophy* of nagent — that data lives in files you can `cat`, `git diff`, and `cp` — is already present in Manual Slop:
- `manual_slop.toml` is the project's source of truth
- `conductor/tracks/<id>/state.toml` is the track's state
- `personas.toml`, `tool_presets.toml`, `context_presets.toml` are all TOML
- The Hook API exposes this state via `POST /api/project` for external automation

What's *not* yet at that level: the AI's working state (the in-flight `disc_entries`, the provider history globals). Closing this gap is the theme of Decision candidates #3, #7, and #10.

### B. nagent is small because it has no GUI. Don't be jealous of the size.

nagent: ~4,000 lines. Manual Slop: 13,000+ lines of production code + 5,000+ lines of MCP tools + a 5,000-line GUI. The size difference is the GUI, the persistence, the test harness, the HITL dialogs, and the Hook API. None of those are reducible by adopting nagent's patterns; they're features Manual Slop users want and use. The right comparison is "nagent's *patterns* vs Manual Slop's *implementation*," not "which codebase is smaller."

### C. The user-corrections shaped the takeaways

Three user-corrections during the deep-dive review directly influenced which patterns made this list:
- **"Editable discussions are more comprehensive than the first draft said"** → made takeaway #1, #2, #9 (visibility, log readability, single-history) all about *respecting* what Manual Slop already has rather than suggesting it lacks.
- **"MMA is fine; 1:1 sub-agents are the gap"** → made takeaway #3 (sub-agents for 1:1) the highest-priority actionable item, with #10 (sub-agent return type) as the design constraint.
- **"Personas are config bundling, RAG is opt-in, tool discovery is deferred"** → kept those three out of the "must steal" list. They're in the future-track `decisions.md` but not in *this* document.

The takeaways are *user-shaped* as well as nagent-shaped. If the user had a different correction in any of those areas, the takeaway list would shift.

---

## Recommended reading order for a future implementer

If you're about to build one of the future tracks, read in this order:

1. **Track 1 — Sub-conversation runner (Application):** Read this entire document, especially §3 and §10. Then read `decisions.md` candidate #1. Then read `src/multi_agent_conductor.py:run_worker_lifecycle` and `scripts/mma_exec.py` for the template.

2. **Track 2 — RAG pre-staging (Application):** Read this entire document, especially §3 (the parent). Then read `decisions.md` candidate #2. Then read `src/rag_engine.py:index_file` and `docs/guide_rag.md`.

3. **Track 3 — Stateless LLMClient (Application, big refactor):** Read this entire document, especially §1, §5, #6, #9. Then read `decisions.md` candidate #3. Then read `src/ai_client.py:113-135` (the provider globals) and `src/history.py` (the UISnapshot pattern). Then read `docs/guide_ai_client.md` end-to-end.

4. **Track 4 — Meta-Tooling intent DSL (Meta-Tooling, research):** Read this entire document, especially §7. Then read `decisions.md` candidate #4. Then read `bin/nagent:parse_response` and the 8 tag patterns there. Then read `src/commands.py` and `src/command_palette.py` to see Manual Slop's existing command-DSL precedents.

5. **Track 5 — Self-describing MCP tools (subsumed):** Read this entire document, especially §8. Then read the existing `mcp_architecture_refactor_20260606` spec.

6. **Track 6 — Git history injection (Application, medium):** Read this entire document, especially #1 and #4 (file identity). Then read `decisions.md` candidate #6. Then read `bin/nagent:format_file_history` and `bin/nagent:coedited_file_rows` for the reference implementation. Then read `src/aggregate.py:run` for the insertion point in Manual Slop.

7. **Track 7 — Per-file conversation log (Application, small):** Read this entire document, especially #1, #4, and #9. Then read `decisions.md` candidate #7. This is dependent on candidate #4 (file_id) — read takeaway #4 first.

8. **Track 8 — Co-edited files tools (Application, small):** Read this entire document, especially §6 and #8. Then read `decisions.md` candidate #8. This is dependent on candidate #6 (git history) — read takeaway #6's reference impl first.

9. **Track 9 — Split/patch lib (defer until need):** Read this entire document, especially #5 (unified loop). Then read `decisions.md` candidate #9. Then read `bin/helpers/nagent_file_split_lib.py` and `bin/helpers/nagent_file_patch_lib.py` for the reference implementation. This is *not* a near-term need; only build when a very-large-file scenario actually surfaces.

10. **Track 10 — Raw-transcript persistence per Take (Application, small):** Read this entire document, especially §1, §2, and §9. Then read `decisions.md` candidate #10. This is dependent on candidate #3 (single history) — read takeaway #9 first.

---

## Final note: this is a *reference* track

This document does not commit any of the 10 takeaways to implementation. Each is a *candidate* — a design space, not a decision. The user (the product owner) and the Tier 2 Tech Lead will scope each into a real conductor track when the corresponding need surfaces. The fact that these patterns are *all grounded in code I've read* (nagent + Manual Slop) is the value of this document; the patterns themselves are *raw material for future work*, not commitments.

End of takeaways document.
