Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
f50415d
feat: claude.mcp_tools, allowed in every session, offered during onbo…
jflavan Oct 27, 2026
6b9c3aa
Merge remote-tracking branch 'origin/main' into feat/mcp-tools
jflavan Oct 27, 2026
627a604
docs: design for agent setup per step
jflavan Oct 27, 2026
05138d5
docs: plan for agent setup, part 1 (runtime)
jflavan Oct 27, 2026
44ec356
feat(config): agents block for per-step agent setup
jflavan Oct 27, 2026
51c7aa3
fix(config): tokenise git tool rules; test step mcp_tools and build e…
jflavan Oct 27, 2026
f5530bd
feat(agents): layer each step's agent setup and its prompt lines
jflavan Oct 27, 2026
e7157d6
feat(agents): find and parse agent and skill definitions, build inlin…
jflavan Oct 27, 2026
ba5c63b
test(agents): pin inline tools, skills and unsafe names; document exp…
jflavan Oct 27, 2026
4aa8389
feat(agents): check that every named agent and skill exists
jflavan Oct 27, 2026
cb807f8
feat(claude): agent flags and the init check, with failure reason setup
jflavan Oct 27, 2026
c0adc35
feat(phases): run each step with its agent setup
jflavan Oct 27, 2026
e60bece
fix(phases): stage skills alone keep today's argv; built-in main agen…
jflavan Oct 27, 2026
97686d2
feat(chat): agent setup for the orchestrator and the intent writer
jflavan Oct 27, 2026
7705d36
test(chat): pin that an empty agents block leaves chat's argv and pro…
jflavan Oct 27, 2026
72a47de
feat(start): refuse while a step names a missing agent
jflavan Oct 27, 2026
521c32c
docs: agent setup in the config template, skill, README and decisions
jflavan Oct 27, 2026
c035e18
docs: plan for agent setup, part 2 (setup section)
jflavan Oct 27, 2026
d20f64f
docs: plan for agent setup, part 3 (console and operator skill)
jflavan Oct 27, 2026
660c7ef
fix(agents): read a loop step's agents from main's commit, and keep w…
jflavan Oct 27, 2026
7fb90e8
fix(start): check the agents under the loop's lock, and refuse when m…
jflavan Oct 27, 2026
a64b611
fix(template): make the commented agents example a top-level block
jflavan Oct 27, 2026
ed66298
fix(agents): name a missing agent once in the setup check
jflavan Oct 27, 2026
f5c8d0c
fix(claude): an init list with no names in it cannot tell what loaded
jflavan Oct 27, 2026
6aa0690
fix(agents): read the frontmatter of an agent file saved with a byte …
jflavan Oct 27, 2026
0780b55
fix(agents): a plugin's agent or skill that is not found says to enab…
jflavan Oct 27, 2026
1012569
docs: agent files from main's commit, the snapshot deny rules, the st…
jflavan Oct 27, 2026
4d2cdd9
refactor(agents): narrow the committed path where findAgent builds it…
jflavan Oct 27, 2026
f0f9423
style(agents): write the byte order mark as an escape in the frontmat…
jflavan Oct 27, 2026
bcd0cdb
feat(agents): a library to list, copy, fetch and write skills and agents
jflavan Oct 27, 2026
ac7063f
fix(agents): keep copied skill paths inside their folder, hide URL cr…
jflavan Oct 27, 2026
8d9da0c
feat(setup): sections can add files, written only when the config saves
jflavan Oct 27, 2026
1a45d03
fix(setup): never write or remove files through a link out of the repo
jflavan Oct 27, 2026
6b6aa11
feat(setup): an agents section for each step's agent, subagents, team…
jflavan Oct 27, 2026
dd7f5b6
docs: setup agents section
jflavan Oct 27, 2026
07a92da
fix(setup): agents section prints untrusted text safely, refuses unre…
jflavan Oct 27, 2026
701968e
fix(setup): a file that fails to write after the save says the config…
jflavan Oct 27, 2026
a9ff30f
docs: setup asks about agents and MCP tools
jflavan Oct 27, 2026
f888804
feat(console): agents settings through settings requests
jflavan Oct 27, 2026
7ce8e4f
fix(console): an empty agents list removes the key
jflavan Oct 27, 2026
33ef9fc
feat(console): agent-files requests the loop commits
jflavan Oct 27, 2026
c81e39b
fix(console): agent-files refuses uncommitted files, links and multi-…
jflavan Oct 27, 2026
c7d65fd
fix(console): agent-files refuses index-only changes; neutral link wo…
jflavan Oct 27, 2026
747227d
feat(console): agents view and file operations
jflavan Oct 27, 2026
50277d7
fix(console): agent file operations carry the version the page read
jflavan Oct 27, 2026
a7b9fb7
feat(ui): agents section on the settings page
jflavan Oct 27, 2026
1a9a8f4
fix(ui): tools fields show what the step gets, not example placeholders
jflavan Oct 27, 2026
5e7ecf4
docs: agents in the console and the operator skill
jflavan Oct 27, 2026
1751eff
fix(apply): a settings change refuses a config edit that is only staged
jflavan Oct 27, 2026
3001c08
fix(settings): an empty list of team members is refused, not a removal
jflavan Oct 27, 2026
d6892ba
fix(console): a new agent never replaces one; a clash says to pick an…
jflavan Oct 27, 2026
00b5180
docs: setup agents does the copying and fetching; what the clone list…
jflavan Oct 27, 2026
8d25c22
fix(agents): the setup check tells a name all steps or a stage give o…
jflavan Oct 27, 2026
be322d5
fix(ui): the agents page confirms a replacing add, pickers say what a…
jflavan Oct 27, 2026
02a4ded
docs: plan for agent setup, part 4 (observability)
jflavan Oct 27, 2026
8c70b35
feat(console): a session's facts show what it ran as
jflavan Oct 27, 2026
c17b36e
fix(console): read a subagent's model by its inline name
jflavan Oct 27, 2026
3bc619c
feat(console): subagent work nested under the call that started it
jflavan Oct 27, 2026
ade9eae
fix(ui): a transcript row with a long target fits a narrow screen; th…
jflavan Oct 27, 2026
abbdc62
docs: agent setup on the session page
jflavan Oct 27, 2026
52ae6cd
fix(console): cap and skip off-screen subagent rows, keep a subagent'…
jflavan Oct 27, 2026
b772277
docs: diagrams of the stages, gates, sessions and agent setup in the …
jflavan Oct 27, 2026
bce4b17
docs: the agent setup modules in the architecture layers
jflavan Oct 27, 2026
58f3361
fix(setup): read each copied skill file through one open
jflavan Oct 27, 2026
8cb8967
fix(agents): review fixes for agent setup
jflavan Oct 27, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
204 changes: 190 additions & 14 deletions README.md

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Loopstra is an unattended development loop on top of the Claude Code CLI. Code o

## Layers

About 150 modules under `src/`, in eight layers. A module imports only from its own layer or the ones below it. There is no runtime import cycle, and every exported name is imported somewhere: `bun run deadcode` fails otherwise.
About 165 modules under `src/`, in eight layers. A module imports only from its own layer or the ones below it. There is no runtime import cycle, and every exported name is imported somewhere: `bun run deadcode` fails otherwise.

1. **Foundations**, which import no other Loopstra module.
- `text.ts`, `ids.ts`, `paths.ts` and `fsutil.ts` hold small helpers: `writeFileAtomic`, and `readJsonAs`, which reads a file through a zod schema.
Expand All @@ -22,6 +22,7 @@ About 150 modules under `src/`, in eight layers. A module imports only from its
- `heartbeat.ts` holds the loop's lock and pause.
- `requests.ts`, `inbox.ts`, `conversation.ts` and `questions.ts` are what people leave for the loop.
- `stamp.ts` holds what an upgrade knows.
- `agents.ts` resolves a step's agent setup from the config (`resolveSetup`) and holds its rules: which steps are read-only, which git a step may never get, and which steps run as the build's agent.
4. **Records.**
- `record-draft.ts` holds `RecordDraft`.
- `context.ts` holds `StepContext` and `commitRecord`, the one way anything is written to main, with `settleRecord` and `landed` (see Records).
Expand All @@ -31,6 +32,8 @@ About 150 modules under `src/`, in eight layers. A module imports only from its
- `sessions.ts` traces each session.
- `phases.ts` holds `agentPhase` and `codePhase`, plus `alongside`, for work that runs beside another phase.
- `judges.ts` holds the cheaper first-pass judges.
- `agent-files.ts` finds the agents and skills a setup names, reading the repository's agents from main's last commit so a change cannot rewrite the agent that judges it, and turns a setup into session options (`setupSession`) and a check of the session's start.
- `agent-library.ts` lists, copies and fetches agents and skills, for `loopstra setup agents` and the console.
6. **Stages**: `stages/*`. Design, plan, build, review, merge and verify, one step per tick, each a short sequence of phases and gates.
7. **The loop.**
- `scheduler.ts` runs `tick`, with up to `speed.max_parallel_changes` lanes, a thinker for design and plan, and a pull-request watcher beside them.
Expand Down
65 changes: 65 additions & 0 deletions docs/decisions.md

Large diffs are not rendered by default.

546 changes: 546 additions & 0 deletions docs/superpowers/plans/2026-10-26-agent-setup-1-runtime.md

Large diffs are not rendered by default.

249 changes: 249 additions & 0 deletions docs/superpowers/plans/2026-10-27-agent-setup-2-setup.md

Large diffs are not rendered by default.

200 changes: 200 additions & 0 deletions docs/superpowers/plans/2026-10-27-agent-setup-3-console.md

Large diffs are not rendered by default.

63 changes: 63 additions & 0 deletions docs/superpowers/plans/2026-10-27-agent-setup-4-observability.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Agent Setup, Part 4: Observability Implementation Plan

> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.

**Goal:** The console's session page shows what a step ran as (agent, subagents, teams, skills, tools, MCP tools, sources, subagent models) and shows each subagent's work nested under the call that started it.

**Architecture:** Part 1 already writes an `agent_setup` trace event on the phase row (`ctx.trace.event(slug, "agent_setup", {...}, seq)`) and passes `--forward-subagent-text` when a step has subagents or teams. This part reads that event into the phase view the session page already gets, and teaches the transcript parser (`src/console/transcript.ts` `toItems`) the `parent_tool_use_id` field so subagent items carry their parent call's id; the page nests them.

**Tech Stack:** Bun, TypeScript, Preact; tests in `tests/unit/console-*.test.ts` and `tests/unit/ui-logic.test.ts`.

**Spec:** `docs/superpowers/specs/2026-10-26-agent-setup-design.md`, section "Observability".

## Global Constraints

- A session with no `agent_setup` event (every session today, and every session with an empty setup) renders exactly as before.
- Stream facts (checked on Claude Code 2.1.311 with `--forward-subagent-text`): a subagent is started by a `tool_use` named `Agent` (older CLIs: `Task`) whose input has `subagent_type`, `description`, `prompt`; every event of the subagent carries `parent_tool_use_id: <that tool_use id>`; its first event is a `user` event whose content is a text block holding the prompt — this is NOT a person's message and must never render as one; the subagent's own `tool_use`/`tool_result`/`text` events follow, each with the parent id; the parent's `tool_result` for the `Agent` call has no parent id.
- Untrusted text (prompts, outputs) renders as text, as the transcript already does.

## Review Focus

1. A subagent's prompt (`user` event with `parent_tool_use_id`) never shows as a message from a person, in the live stream and when a transcript is read back from `raw.jsonl`.
2. Two subagents running at the same time (a `parallel` team) interleave their events: each item still lands under its own parent call.
3. A transcript resumed from a frame id in the middle of a subagent's events still nests the later items (the parent id travels with each item, not with reader state).
4. An old `raw.jsonl` without `parent_tool_use_id` renders exactly as before.

---

### Task 1: Agent setup in the phase view and the session facts

**Files:** the module that builds the session page's phase detail (`PhaseView`, find it from `src/ui/views/Session.tsx` `detail` and `card?.model`: `src/console/detail.ts` or `src/console/model.ts`), `src/console/types.ts`, `src/ui/views/Session.tsx` (`Facts`); tests in the matching console test file and `tests/unit/ui-logic.test.ts` if a pure helper is added.

**Interfaces:**
- `PhaseView` (or the card the page reads `model` from) gains `agentSetup: { agent: string | null; subagents: string[]; teams: string[]; skills: string[]; tools: string[]; mcpTools: string[]; sources: "all" | "repo"; models: Record<string, string> } | null`, read from the phase row's `agent_setup` event (latest one for that seq; null when none).
- `Facts` shows, only when `agentSetup` is not null: `Agent` (name, or "none"), `Subagents` (names, each with its model from `models` when known, e.g. "sec (haiku)"), `Teams`, `Skills`, `Tools` and `MCP tools` (only when non-empty), `Sources` (only when `repo`: "repo only").

- [ ] **Step 1: failing tests** — the phase view of a seq with an `agent_setup` event carries it (the event's payload keys are `agent, subagents, teams, skills, tools, mcp_tools, sources, models`); one without carries null; the page's Facts helper (if pure) gives the lines above, and nothing for null.
- [ ] **Step 2-4:** implement → pass → `bun run check`.
- [ ] **Step 5: Commit** `feat(console): a session's facts show what it ran as`.

---

### Task 2: Subagent work nested under its call

**Files:** `src/console/transcript.ts` (`toItems`, `replayed`), `src/console/types.ts` (`TranscriptItem`), `src/ui/transcript.ts` and the transcript view in `src/ui/views/Session.tsx` (and the Agents tiles if they render items); tests in the transcript test file (find with `grep -l toItems tests/unit`) and `tests/unit/ui-logic.test.ts`.

**Interfaces:**
- Every `TranscriptItem` variant may carry `parent?: string` (the `parent_tool_use_id`); `toItems` sets it from the event.
- A `user` event with a `parent_tool_use_id` whose content is text becomes `{ kind: "delegated", parent, text }` (the subagent's prompt), never a `message`.
- `toolTarget` for `Agent`/`Task` shows `subagent_type: description` (src/tools.ts; it already names Task "Handing off").
- `src/ui/transcript.ts` exports a pure `nest(items: TranscriptItem[]): Array<TranscriptItem & { children?: TranscriptItem[] }>` that places every item with `parent` under the `tool` item whose `id` equals it (items whose parent is not in the list stay top-level, marked so the page can say "(from a subagent)").
- The view renders a subagent call as a collapsible block: its summary line ("Handing off to sec: Security review of a.txt"), then the prompt (collapsed), the subagent's text and tool calls indented, and the call's result.

- [ ] **Step 1: failing tests** — with a fixture made from the stream facts in Global Constraints (one `Agent` call, its prompt event, one `Read` call and result, a text, the parent's result): `toItems` gives `parent` on the subagent's items and `delegated` for the prompt; `nest` puts them under the call; two interleaved subagents nest under their own calls; a resumed slice starting mid-subagent still nests; an old fixture without parent ids gives the same items as before.
- [ ] **Step 2-4:** implement → pass → `bun run check`; one browser screenshot of a seeded session with a subagent call (the Part 3 scripts in the scratchpad `agents-ui/` show how to seed and shoot) saved as `session-subagent.png` there.
- [ ] **Step 5: Commit** `feat(console): subagent work nested under the call that started it`.

---

### Task 3: Docs

- `README.md` (the console's session page paragraph): what a session shows of its agent setup and subagents.
- `docs/decisions.md`: the stream facts above (checked on 2.1.311), `delegated` items, nesting by parent id.
- [ ] Edit; `bun run check`; commit `docs: agent setup on the session page`.
Loading
Loading