LLMPlanningAgent builds each planning turn from self._store.read_events() with no lower bound (planner.py), and LLMExecutor scans read_events() in full (executor.py, the loop before its turns). The canonical log is never cleared between tasks, and nothing marks where a task begins. After the first live run the store held 95 events from the slugify task. Starting a new task with use, the planner would get that whole conversation — the old task description, plans, approvals and review comments — as if it were the current one.
Expected: each task's model turns see only that task's events: from its use <project> (or the task-start event) onward. Earlier tasks stay in the log as the record (A2/A10), not as context. Resuming a parked work item (0.2) must still see that item's own history.
Options:
record the first event id of the task in _data (task_start_event) and read from there;
or tag events with task_id and filter on it, which also fits park-and-switch, where tasks interleave.
Tests: two tasks back to back; the second's planner turn contains none of the first's messages; a restart mid-second-task keeps the bound.
Also check: the context budgeting (context.py) and delegation (A13) readers of the log.
Found preparing the second live run.
`LLMPlanningAgent` builds each planning turn from `self._store.read_events()` with no lower bound (`planner.py`), and `LLMExecutor` scans `read_events()` in full (`executor.py`, the loop before its turns). The canonical log is never cleared between tasks, and nothing marks where a task begins. After the first live run the store held 95 events from the slugify task. Starting a new task with `use`, the planner would get that whole conversation — the old task description, plans, approvals and review comments — as if it were the current one.
**Expected:** each task's model turns see only that task's events: from its `use <project>` (or the task-start event) onward. Earlier tasks stay in the log as the record (A2/A10), not as context. Resuming a parked work item (0.2) must still see that item's own history.
**Options:**
- record the first event id of the task in `_data` (`task_start_event`) and read from there;
- or tag events with `task_id` and filter on it, which also fits park-and-switch, where tasks interleave.
**Tests:** two tasks back to back; the second's planner turn contains none of the first's messages; a restart mid-second-task keeps the bound.
**Also check:** the context budgeting (`context.py`) and delegation (A13) readers of the log.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_01PPQ14L3LikyefCMFBqEbKE
Correction: the executor is not affected. Its full read_events() scan (LLMExecutor._scope) only finds the latest PlanSubmitted, and its turns read from that event on, so it already sees just the current milestone. The bug is the planner's alone: LLMPlanningAgent renders every event in the store.
Correction: the executor is **not** affected. Its full `read_events()` scan (`LLMExecutor._scope`) only finds the latest `PlanSubmitted`, and its turns read from that event on, so it already sees just the current milestone. The bug is the planner's alone: `LLMPlanningAgent` renders every event in the store.
dev-agent
changed title from The transcript is not scoped to the task: a new task's planner sees the previous task to The planner's transcript: scope it to the task, attribute who acted, and include orchestrator facts2026-09-30 12:58:06 +00:00
Widened after the second live run. Two more problems come from the same design: the planner renders the shared log raw.
1. It can't tell who acted. The executor's tool calls and messages are in the same log and render as assistant turns. Before milestone 2, the planner (Opus) told the operator: "In the last turn I did milestone 1 myself: I ran commands, wrote files, and made commit cb70e1d… My role is to plan only… that commit was made by me, not by an executor, and nobody else has reviewed it." It repeated this in its next plan. Careful reasoning, but a false premise that our rendering created.
2. It lacks orchestrator facts. It said the commit was "not pushed or merged" and offered to open a PR, while PR #165 was already open. Publishing, PRs, branches and gate outcomes never enter the transcript.
Expected: the planner sees
its own conversation for this task: operator messages, its plans, questions and answers (the original scope of this issue);
orchestrator-written facts as clearly attributed entries, e.g. "milestone 1 executed by the executor (qwen3.8-27b): commit cb70e1d on branch …; summary: …" and "PR #165 opened";
the executor's finish summary as a report from the executor, not its raw turns.
Structural, not advisory: attribution belongs in the rendering (A10), not in a prompt asking the model to infer it. The Anthropic passthrough renderer and the OpenAI-shaped one both need it.
Tests:
a planner turn after a milestone contains no executor tool calls, and does contain the milestone fact and the PR;
the rendered roles never present executor actions as the planner's own.
**Widened after the second live run.** Two more problems come from the same design: the planner renders the shared log raw.
**1. It can't tell who acted.** The executor's tool calls and messages are in the same log and render as *assistant* turns. Before milestone 2, the planner (Opus) told the operator: *"In the last turn I did milestone 1 myself: I ran commands, wrote files, and made commit cb70e1d… My role is to plan only… that commit was made by me, not by an executor, and nobody else has reviewed it."* It repeated this in its next plan. Careful reasoning, but a false premise that our rendering created.
**2. It lacks orchestrator facts.** It said the commit was "not pushed or merged" and offered to open a PR, while PR #165 was already open. Publishing, PRs, branches and gate outcomes never enter the transcript.
**Expected: the planner sees**
- its own conversation for **this** task: operator messages, its plans, questions and answers (the original scope of this issue);
- **orchestrator-written facts** as clearly attributed entries, e.g. "milestone 1 executed by the executor (qwen3.8-27b): commit cb70e1d on branch …; summary: …" and "PR #165 opened";
- the executor's `finish` summary as a report *from the executor*, **not** its raw turns.
**Structural, not advisory:** attribution belongs in the rendering (A10), not in a prompt asking the model to infer it. The Anthropic passthrough renderer and the OpenAI-shaped one both need it.
**Tests:**
- a planner turn after a milestone contains no executor tool calls, and does contain the milestone fact and the PR;
- the rendered roles never present executor actions as the planner's own.
Confirmed live (bring-up run 3, 2026-10-02, on M1.3's branch). After milestone 1 and next milestone, the planner's milestone-2 turn cited the orchestrator's facts: milestone 1 finished, PR #208, the test count. It treated none of the executor's work as its own turns, and asked the operator what milestone 2 should cover instead of inventing work. M1.1 (work items) and M1.2 (per-role views and facts) together close this.
Confirmed live (bring-up run 3, 2026-10-02, on M1.3's branch). After milestone 1 and `next milestone`, the planner's milestone-2 turn cited the orchestrator's facts: milestone 1 finished, PR #208, the test count. It treated none of the executor's work as its own turns, and asked the operator what milestone 2 should cover instead of inventing work. M1.1 (work items) and M1.2 (per-role views and facts) together close this.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Found preparing the second live run.
LLMPlanningAgentbuilds each planning turn fromself._store.read_events()with no lower bound (planner.py), andLLMExecutorscansread_events()in full (executor.py, the loop before its turns). The canonical log is never cleared between tasks, and nothing marks where a task begins. After the first live run the store held 95 events from the slugify task. Starting a new task withuse, the planner would get that whole conversation — the old task description, plans, approvals and review comments — as if it were the current one.Expected: each task's model turns see only that task's events: from its
use <project>(or the task-start event) onward. Earlier tasks stay in the log as the record (A2/A10), not as context. Resuming a parked work item (0.2) must still see that item's own history.Options:
_data(task_start_event) and read from there;task_idand filter on it, which also fits park-and-switch, where tasks interleave.Tests: two tasks back to back; the second's planner turn contains none of the first's messages; a restart mid-second-task keeps the bound.
Also check: the context budgeting (
context.py) and delegation (A13) readers of the log.🤖 Generated with Claude Code
https://claude.ai/code/session_01PPQ14L3LikyefCMFBqEbKE
Correction: the executor is not affected. Its full
read_events()scan (LLMExecutor._scope) only finds the latestPlanSubmitted, and its turns read from that event on, so it already sees just the current milestone. The bug is the planner's alone:LLMPlanningAgentrenders every event in the store.The transcript is not scoped to the task: a new task's planner sees the previous taskto The planner's transcript: scope it to the task, attribute who acted, and include orchestrator factsWidened after the second live run. Two more problems come from the same design: the planner renders the shared log raw.
1. It can't tell who acted. The executor's tool calls and messages are in the same log and render as assistant turns. Before milestone 2, the planner (Opus) told the operator: "In the last turn I did milestone 1 myself: I ran commands, wrote files, and made commit cb70e1d… My role is to plan only… that commit was made by me, not by an executor, and nobody else has reviewed it." It repeated this in its next plan. Careful reasoning, but a false premise that our rendering created.
2. It lacks orchestrator facts. It said the commit was "not pushed or merged" and offered to open a PR, while PR #165 was already open. Publishing, PRs, branches and gate outcomes never enter the transcript.
Expected: the planner sees
finishsummary as a report from the executor, not its raw turns.Structural, not advisory: attribution belongs in the rendering (A10), not in a prompt asking the model to infer it. The Anthropic passthrough renderer and the OpenAI-shaped one both need it.
Tests:
Confirmed live (bring-up run 3, 2026-10-02, on M1.3's branch). After milestone 1 and
next milestone, the planner's milestone-2 turn cited the orchestrator's facts: milestone 1 finished, PR #208, the test count. It treated none of the executor's work as its own turns, and asked the operator what milestone 2 should cover instead of inventing work. M1.1 (work items) and M1.2 (per-role views and facts) together close this.🤖 Generated with Claude Code