Give each role its own view of the transcript (M1.2) #88

Merged
dongar merged 1 commits from transcript-views into main 2026-10-02 03:18:09 +00:00
Collaborator

Development Plan M1.2, as agreed in discussion. Part of #78 (M1.1 did the scoping; this does the attribution).

What changes

The canonical log stays one record per work item. What each model is shown is now a projection of it — Transcript.view() in the new views.py — and the planner, executor and helper build their context from that instead of the raw log. read() stays raw for the record, cursors and recovery.

Viewer Sees
planner operator messages, its own turns, facts. No executor or helper work.
executor (from the approved plan on) operator messages, its own turns, facts, a helper's handback as [helper report, <status>] …
helper [approved plan] …, operator messages, facts, its own turns, the executor's work as narration: [executor] run_command(make) → failed: …
expert unchanged (stateless; sees only the question)

Everything that isn't the viewer's own reaches it as a labelled user message: [orchestrator] …, [operator, Matrix] …, [operator, comment on PR #165] …, [operator, Matrix, sent while idle] …. Projected events keep their log ids, so after cursors and compaction ranges still line up.

Facts. A new canonical fact event (already in L7's table), written by the orchestrator when:

  • a work item opens;
  • a plan is approved or rejected;
  • a milestone starts, finishes, stops or escalates;
  • a milestone is published (PR number and URL) or not, or publishing fails;
  • a review comment is answered;
  • the work moves to the next milestone;
  • the task is completed or abandoned.

Both renderers render a raw fact as [orchestrator] … too. nisse_dev.dump shows them as FACT:.

PlanSubmitted is no longer rendered as assistant text: the planner's own submit_plan call already carries the plan. It stays in the log, for the executor's scope and the dump.

Gitea comment sources now carry their number (gitea:pr:165:comment:7, gitea:issue:9:comment:4) so the label can say where a comment was made.

Docs:

  • Architecture L6 now spells out the helper's view (the plan and narration) and the label rule;
  • M1.2 is marked Done in the Development Plan.

Tests

New tests/test_views.py:

  • Run 2's scenario: after milestone 1 and next milestone, the planner's rendered request holds only its own submit_plan calls as assistant turns. It holds the milestone-finished fact, PR #165 and its URL, the approval fact and the carried idle message, and none of the executor's text.
  • Executor:
    • sees milestone 1 started;
    • sees a review comment labelled comment on PR #165;
    • still sees its own earlier turn as its own.
  • Helper report: the executor sees the report and not the helper's turns.
  • Helper: sees the plan and narration; its own calls are unchanged, and the executor's calls are not shown as calls.
  • Planner: sees nothing of other roles.
  • Cursors: a view keeps log ids, so cursors work.
  • Labels and closing:
    • both renderers label facts;
    • operator labels are right per channel;
    • closing a task records its fact.

Plus a dump test, and two existing assertions updated.

Lint, unit (524), integration (19 passed, 7 opt-in skipped) and the Quint tests all pass locally.

🤖 Generated with Claude Code

https://claude.ai/code/session_01PPQ14L3LikyefCMFBqEbKE

Development Plan **M1.2**, as agreed in discussion. Part of #78 (M1.1 did the scoping; this does the attribution). ## What changes The canonical log stays one record per work item. What each model is shown is now a **projection** of it — `Transcript.view()` in the new `views.py` — and the planner, executor and helper build their context from that instead of the raw log. `read()` stays raw for the record, cursors and recovery. | Viewer | Sees | |---|---| | planner | operator messages, its own turns, facts. **No executor or helper work.** | | executor | (from the approved plan on) operator messages, its own turns, facts, a helper's handback as `[helper report, <status>] …` | | helper | `[approved plan] …`, operator messages, facts, its own turns, the executor's work as narration: `[executor] run_command(make) → failed: …` | | expert | unchanged (stateless; sees only the question) | Everything that isn't the viewer's own reaches it as a labelled **user** message: `[orchestrator] …`, `[operator, Matrix] …`, `[operator, comment on PR #165] …`, `[operator, Matrix, sent while idle] …`. Projected events keep their log ids, so `after` cursors and compaction ranges still line up. **Facts.** A new canonical `fact` event (already in L7's table), written by the orchestrator when: - a work item opens; - a plan is approved or rejected; - a milestone starts, finishes, stops or escalates; - a milestone is published (PR number and URL) or not, or publishing fails; - a review comment is answered; - the work moves to the next milestone; - the task is completed or abandoned. Both renderers render a raw `fact` as `[orchestrator] …` too. `nisse_dev.dump` shows them as `FACT:`. `PlanSubmitted` is no longer rendered as assistant text: the planner's own `submit_plan` call already carries the plan. It stays in the log, for the executor's scope and the dump. Gitea comment sources now carry their number (`gitea:pr:165:comment:7`, `gitea:issue:9:comment:4`) so the label can say where a comment was made. **Docs:** - Architecture L6 now spells out the helper's view (the plan and narration) and the label rule; - M1.2 is marked Done in the Development Plan. ## Tests New `tests/test_views.py`: - **Run 2's scenario:** after milestone 1 and `next milestone`, the planner's rendered request holds only its own `submit_plan` calls as assistant turns. It holds the milestone-finished fact, PR #165 and its URL, the approval fact and the carried idle message, and none of the executor's text. - **Executor:** - sees `milestone 1 started`; - sees a review comment labelled `comment on PR #165`; - still sees its own earlier turn as its own. - **Helper report:** the executor sees the report and not the helper's turns. - **Helper:** sees the plan and narration; its own calls are unchanged, and the executor's calls are not shown as calls. - **Planner:** sees nothing of other roles. - **Cursors:** a view keeps log ids, so cursors work. - **Labels and closing:** - both renderers label facts; - operator labels are right per channel; - closing a task records its fact. Plus a dump test, and two existing assertions updated. Lint, unit (524), integration (19 passed, 7 opt-in skipped) and the Quint tests all pass locally. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01PPQ14L3LikyefCMFBqEbKE
dev-agent added 1 commit 2026-10-02 00:39:53 +00:00
Give each role its own view of the transcript (M1.2)
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 1m27s
3fba958958
A model no longer reads another role's turns as its own (#78). The log
stays one record per work item; what a role is shown is projected from
it by Transcript.view() (views.py), which the planner, executor and
helper now build their context from:

- own events unchanged;
- operator messages labelled with their channel, e.g.
  [operator, Matrix] or [operator, comment on PR #165];
- orchestrator facts (a new `fact` event) as [orchestrator] statements;
- the executor sees a helper's handback as [helper report], not its turns;
- a helper sees the approved plan and the executor's milestone work as
  one-line narration;
- the planner sees no other role's work at all.

The orchestrator now writes facts at the points the models must know
about: work item opened, plan approved or rejected, milestone started,
finished or stopped, published (with PR number and URL) or not, review
comment answered, next milestone, task completed or abandoned.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPQ14L3LikyefCMFBqEbKE
dongar approved these changes 2026-10-02 03:18:05 +00:00
dongar merged commit 7b031179a2 into main 2026-10-02 03:18:09 +00:00
dongar deleted branch transcript-views 2026-10-02 03:18:09 +00:00
Sign in to join this conversation.
No Reviewers
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: dev/nisse#88