From 818959c39f190815932ac3d7f9189c7d02e01272 Mon Sep 17 00:00:00 2001 From: Christoph Maier Date: Tue, 21 Jul 2026 11:32:12 +0200 Subject: [PATCH 01/12] feature(simplify-ci-workflow): Simplify CI test workflow Feature: simplify-ci-workflow --- .github/workflows/ci.yml | 6 --- memory/backlog/index.md | 6 +-- .../auto-plan-review-terminal-reset.md | 26 ++++++++++ memory/decisions/index.md | 1 + .../finalize-auto-plan-review.md | 0 .../index.md | 3 ++ .../plan.md | 49 +++++++++++++++++++ .../usage.md | 39 +++++++++++++++ memory/features/index.md | 2 +- memory/features/simplify-ci-workflow.md | 30 ++++++++++++ memory/index.md | 2 +- memory/log.md | 12 +++++ memory/plan.md | 41 +++++----------- memory/state.md | 10 ++-- memory/usage.md | 25 +++------- 15 files changed, 191 insertions(+), 61 deletions(-) create mode 100644 memory/decisions/auto-plan-review-terminal-reset.md rename memory/features/{ => archive/2026-07-20-auto-plan-review-terminal-reset}/finalize-auto-plan-review.md (100%) create mode 100644 memory/features/archive/2026-07-20-auto-plan-review-terminal-reset/index.md create mode 100644 memory/features/archive/2026-07-20-auto-plan-review-terminal-reset/plan.md create mode 100644 memory/features/archive/2026-07-20-auto-plan-review-terminal-reset/usage.md create mode 100644 memory/features/simplify-ci-workflow.md diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bf51c79..52de193 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,12 +8,6 @@ on: jobs: test: runs-on: ubuntu-latest - strategy: - matrix: - node-version: [18.x, 20.x, 22.x] steps: - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: ${{ matrix.node-version }} - run: npm test diff --git a/memory/backlog/index.md b/memory/backlog/index.md index 43ddcd1..0f1a4aa 100644 --- a/memory/backlog/index.md +++ b/memory/backlog/index.md @@ -2,10 +2,10 @@ type: Backlog title: Iterator backlog description: Saved ideas and bugs kept separate from active plan features. -items: "[]" -timestamp: 2026-07-20T17:48:20.856Z +items: "[{\"id\":\"on-plan-open-work-tab\",\"title\":\"on plan open work tab\",\"details\":\"when pressing in palning tab plan and it starts switch automaticvally to work\",\"kind\":\"bug\",\"selected\":false,\"created\":\"2026-07-21T09:01:21.266Z\",\"updated\":\"2026-07-21T09:01:21.266Z\"}]" +timestamp: 2026-07-21T09:30:45.471Z --- # Backlog -(empty) +* [bug] on plan open work tab diff --git a/memory/decisions/auto-plan-review-terminal-reset.md b/memory/decisions/auto-plan-review-terminal-reset.md new file mode 100644 index 0000000..a70086c --- /dev/null +++ b/memory/decisions/auto-plan-review-terminal-reset.md @@ -0,0 +1,26 @@ +--- +type: Decision +title: Auto plan review resets runtime state +description: The recorded terminal auto plan review is the durable boundary that returns auto mode and the Work surface to a completed manual state. +status: accepted +date: 2026-07-21 +tags: [auto-mode, plan-review, runtime-state, dashboard] +files: ["lib/write.mjs", "lib/pi-tools.mjs", "extensions/iterator.js", "test/write.test.mjs", "test/pi-tools.test.mjs", "test/extension-model-lifecycle.test.mjs"] +timestamp: 2026-07-21T09:00:21.635Z +--- + +## Decision + +Treat a successful agent-authored `record-plan-review` as the durable terminal boundary for an automatic run. It clears auto runtime ownership before the next driver tick; manual plan reviews retain their existing state. + +The extension then converges idempotently: it restores any role model once, clears only its own Work overlay, and refreshes from server-derived state. A completed plan remains available for explicit retirement rather than being retired automatically. + +## Rationale + +Persisting the terminal reset at the review-recording boundary prevents a finishing agent turn or refresh race from leaving the dashboard stuck on “Auto: plan-review”. Keeping the extension as a convergence layer preserves `lib/status.mjs` as the lifecycle authority and avoids browser-local state inference. + +# Retired plan + +Condensed from plan "Finish auto mode after plan review" (1 features, archived under /features/archive/2026-07-20-auto-plan-review-terminal-reset/). + +Token usage: 2040732 in / 21484 out / 15654400 cache-read / 0 cache-write over 75 turns (per-step breakdown in the archived usage.md). diff --git a/memory/decisions/index.md b/memory/decisions/index.md index 585cadc..7fe77ee 100644 --- a/memory/decisions/index.md +++ b/memory/decisions/index.md @@ -3,6 +3,7 @@ Durable product and implementation choices agents should preserve. * [Apply role models to manual turns and reset stale runtime state](/decisions/manual-role-models-and-runtime-reset.md) - Manual Iterator role commands temporarily select configured models, while approved plans and terminal auto runs reset runtime state deterministically. +* [Auto plan review resets runtime state](/decisions/auto-plan-review-terminal-reset.md) - The recorded terminal auto plan review is the durable boundary that returns auto mode and the Work surface to a completed manual state. * [Backlog planning and parallel feature waves](/decisions/backlog-planning-and-feature-waves.md) - Keep low-risk backlog editing available during active work while implementing a fixed ready-feature wave and reviewing its commit-backed results together. * [Consume selected backlog ideas on plan approval](/decisions/consume-accepted-backlog-ideas.md) - Selected idea or bug candidates leave the backlog only after deterministic plan approval. * [Focus feature execution and dashboard ownership](/decisions/focus-feature-execution-and-dashboard-ownership.md) - Implementation now starts in fresh feature sessions, Work owns active plans, Settings preserves context as a shell modal, and red tests are explicit handoffs. diff --git a/memory/features/finalize-auto-plan-review.md b/memory/features/archive/2026-07-20-auto-plan-review-terminal-reset/finalize-auto-plan-review.md similarity index 100% rename from memory/features/finalize-auto-plan-review.md rename to memory/features/archive/2026-07-20-auto-plan-review-terminal-reset/finalize-auto-plan-review.md diff --git a/memory/features/archive/2026-07-20-auto-plan-review-terminal-reset/index.md b/memory/features/archive/2026-07-20-auto-plan-review-terminal-reset/index.md new file mode 100644 index 0000000..68a0963 --- /dev/null +++ b/memory/features/archive/2026-07-20-auto-plan-review-terminal-reset/index.md @@ -0,0 +1,3 @@ +# Features + +* [Finalize auto mode after plan review](finalize-auto-plan-review.md) - ✅ done · medium · Agent plan-review completion resets durable auto state and refreshes Work so the final Auto step cannot remain stuck. diff --git a/memory/features/archive/2026-07-20-auto-plan-review-terminal-reset/plan.md b/memory/features/archive/2026-07-20-auto-plan-review-terminal-reset/plan.md new file mode 100644 index 0000000..ffe16d3 --- /dev/null +++ b/memory/features/archive/2026-07-20-auto-plan-review-terminal-reset/plan.md @@ -0,0 +1,49 @@ +--- +type: Plan +title: Finish auto mode after plan review +description: Return the dashboard to completed manual state after the last automatic plan review records its report. +status: approved +branch: iterator/safe-role-model-handoff +created: 2026-07-20 +timestamp: "2026-07-20T18:20:18.871Z" +plan_reviewed: 2026-07-20 +--- + +# Goal + +Make the final automatic plan-review transition reliably finish the auto run: after the final feature and plan review complete, clear stale auto state, release the Work UI from “Auto: plan-review”, and refresh it to the completed/retirable plan state. + +# Architecture + +- Preserve `lib/status.mjs` as the source of derived plan lifecycle state; the fix only converges runtime state held in `memory/state.md` and the extension’s owned Work overlay. +- Extend the deterministic terminal path around `record-plan-review` / auto dispatch so an agent-authored final review records `plan_reviewed` and resets auto mode to manual, unpaused, terminal state with no active feature, strikes, or escalation. The transition must be idempotent for retries and must not reset a human-initiated plan review. +- Harden `extensions/iterator.js`’s auto completion driver to recognize the recorded terminal review even if the originating agent turn is ending or session refresh races it, restore any role model once, clear its owned overlay, and refresh the Work hub from gathered state. +- Cover the full transition in writer, auto-state-machine, extension lifecycle, and UI/session tests; develop in root `lib/` and extension code, then run `npm run sync` for shipped copies. +- Follow `architecture/workflow-state-ownership`, `decisions/manual-role-models-and-runtime-reset`, and `decisions/focus-feature-execution-and-dashboard-ownership`: state is server-derived and terminal auto runs reset deterministically without browser-local lifecycle inference. + +# Dependencies + +(none) + +# Key decisions + +- An agent’s successful `record-plan-review` is the durable terminal boundary for an auto run; it clears stale runtime ownership before the next driver tick, while manual reviews retain their existing state. +- The extension’s later `kickAuto` completion remains an idempotent convergence and UI-refresh path, not a second lifecycle authority. +- A completed plan remains retirable rather than being auto-retired; this change only removes the stale working state. +- No new dependencies or workflow statuses are introduced. + +# Features + +* [Finalize auto mode after plan review](/features/finalize-auto-plan-review.md) - Agent plan-review completion resets durable auto state and refreshes Work so the final Auto step cannot remain stuck. + +# Plan review + +## 2026-07-20 _(agent review: openai-codex/gpt-5.6-sol)_ + +## Finding + +- **Goal coverage / terminal-boundary decision:** `a0f4243` makes `recordPlanReview` reset runtime ownership only when `b.state.mode === "auto" && !b.state.paused` (`lib/write.mjs`). If the user pauses auto mode while the plan-review agent is already running, the successful agent review still records `plan_reviewed` but returns `autoCompleted: false`; the extension therefore skips model restoration, overlay clearing, and the completed Work refresh, leaving the runtime in paused auto/reviewing state. This contradicts the plan’s unconditional agent-review terminal boundary and its reliability goal. The terminal transition should distinguish a stale/unrelated agent review without excluding an in-flight final review merely because pause was toggled, with regression coverage for that race. + +## Otherwise verified + +The normal unpaused path durably resets state, delayed driver ticks are inert, manual reviews retain runtime ownership, both completion paths honor `auto_retire_prompt`, synced writer copies match, and the full suite passes (392 passed, 4 skipped). The only scope drift is a formatting-only `writeUsage` line in `a0f4243`, with no behavior change. diff --git a/memory/features/archive/2026-07-20-auto-plan-review-terminal-reset/usage.md b/memory/features/archive/2026-07-20-auto-plan-review-terminal-reset/usage.md new file mode 100644 index 0000000..93cfaaf --- /dev/null +++ b/memory/features/archive/2026-07-20-auto-plan-review-terminal-reset/usage.md @@ -0,0 +1,39 @@ +--- +type: Usage +title: Token usage +description: Per-step model/token ledger and optional project-owned pricing for the active plan — written only by the usage op. +totals: "{\"steps\":{\"review\":{\"openai-codex/gpt-5.6-terra\":{\"input\":237934,\"output\":9168,\"cacheRead\":4968960,\"cacheWrite\":0,\"turns\":24},\"openai-codex/gpt-5.6-sol\":{\"input\":463467,\"output\":3871,\"cacheRead\":1914880,\"cacheWrite\":0,\"turns\":18}},\"implement\":{\"openai-codex/gpt-5.6-terra\":{\"input\":968435,\"output\":5724,\"cacheRead\":4179968,\"cacheWrite\":0,\"turns\":16},\"openai-codex/gpt-5.6-sol\":{\"input\":370896,\"output\":2721,\"cacheRead\":4590592,\"cacheWrite\":0,\"turns\":14}},\"hub\":{\"openai-codex/gpt-5.6-terra\":{\"input\":0,\"output\":0,\"cacheRead\":0,\"cacheWrite\":0,\"turns\":3}}},\"features\":{\"finalize-auto-plan-review\":{\"input\":1792296,\"output\":10754,\"cacheRead\":10406400,\"cacheWrite\":0,\"turns\":43},\"retire-plan\":{\"input\":0,\"output\":0,\"cacheRead\":0,\"cacheWrite\":0,\"turns\":3}},\"featureModels\":{\"finalize-auto-plan-review\":{\"openai-codex/gpt-5.6-terra\":{\"input\":968435,\"output\":5724,\"cacheRead\":4179968,\"cacheWrite\":0,\"turns\":16},\"openai-codex/gpt-5.6-sol\":{\"input\":823861,\"output\":5030,\"cacheRead\":6226432,\"cacheWrite\":0,\"turns\":27}},\"retire-plan\":{\"openai-codex/gpt-5.6-terra\":{\"input\":0,\"output\":0,\"cacheRead\":0,\"cacheWrite\":0,\"turns\":3}}}}" +prices: "{}" +timestamp: 2026-07-21T08:59:25.755Z +--- + +# Usage + +## review + +| model | input | output | cache read | cache write | turns | cost | +| --- | ---: | ---: | ---: | ---: | ---: | ---: | +| openai-codex/gpt-5.6-terra | 237934 | 9168 | 4968960 | 0 | 24 | — | +| openai-codex/gpt-5.6-sol | 463467 | 3871 | 1914880 | 0 | 18 | — | + +## implement + +| model | input | output | cache read | cache write | turns | cost | +| --- | ---: | ---: | ---: | ---: | ---: | ---: | +| openai-codex/gpt-5.6-terra | 968435 | 5724 | 4179968 | 0 | 16 | — | +| openai-codex/gpt-5.6-sol | 370896 | 2721 | 4590592 | 0 | 14 | — | + +## hub + +| model | input | output | cache read | cache write | turns | cost | +| --- | ---: | ---: | ---: | ---: | ---: | ---: | +| openai-codex/gpt-5.6-terra | 0 | 0 | 0 | 0 | 3 | — | + +## Per feature + +| feature | input | output | cache read | cache write | turns | cost | +| --- | ---: | ---: | ---: | ---: | ---: | ---: | +| finalize-auto-plan-review | 1792296 | 10754 | 10406400 | 0 | 43 | — | +| retire-plan | 0 | 0 | 0 | 0 | 3 | — | + +Total: 2040732 in / 21484 out / 15654400 cache-read / 0 cache-write over 75 turns. Cost unavailable: add every used model rate. diff --git a/memory/features/index.md b/memory/features/index.md index 68a0963..6bc316c 100644 --- a/memory/features/index.md +++ b/memory/features/index.md @@ -1,3 +1,3 @@ # Features -* [Finalize auto mode after plan review](finalize-auto-plan-review.md) - ✅ done · medium · Agent plan-review completion resets durable auto state and refreshes Work so the final Auto step cannot remain stuck. +* [Simplify CI workflow](simplify-ci-workflow.md) - ⬜ pending · small · Run the repository test suite once in a minimal GitHub Actions job without redundant Node setup or version-matrix executions. diff --git a/memory/features/simplify-ci-workflow.md b/memory/features/simplify-ci-workflow.md new file mode 100644 index 0000000..4a66a38 --- /dev/null +++ b/memory/features/simplify-ci-workflow.md @@ -0,0 +1,30 @@ +--- +type: Feature +title: Simplify CI workflow +description: Run the repository test suite once in a minimal GitHub Actions job without redundant Node setup or version-matrix executions. +status: implemented +size: small +depends_on: [] +files: [".github/workflows/ci.yml"] +timestamp: "2026-07-21T09:32:12.771Z" +tags: [] +--- + +# Implementation notes + +Edit `.github/workflows/ci.yml` only. Preserve the `main` push and pull-request triggers, `ubuntu-latest`, checkout, and `npm test`; remove the matrix strategy, parameterized Node versions, and `actions/setup-node`. Validate the resulting workflow structure and run the unchanged local test suite. + +# Snippets + +```yaml +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: npm test +``` + +# Blast radius + +GitHub Actions checks for pushes to main and all pull requests. diff --git a/memory/index.md b/memory/index.md index ccb7588..3de5f0d 100644 --- a/memory/index.md +++ b/memory/index.md @@ -10,8 +10,8 @@ last_memorized_commit: c5b75e3e4b034bc80a1600e57249e162639d32a8 * [Design](design.md) - A compact dark developer control plane with clear workflow state. * [Backlog](backlog/index.md) - Saved ideas and bugs outside active plan features. * [Settings](settings.md) - Project settings (auto mode, models, git flow). -* [Plan](plan.md) - Return the dashboard to completed manual state after the last automatic plan review records its report. * [Features](features/) - One document per implementation feature. +* [Plan](plan.md) - Remove redundant CI setup and matrix execution while preserving the repository test backstop. * [Architecture](/architecture/) - How the system is structured. * [Decisions](/decisions/) - Durable product and implementation choices agents should preserve. * [Patterns & Conventions](/patterns/) - How code and workflows are written in this repo. diff --git a/memory/log.md b/memory/log.md index 89d2a5b..f36fb2f 100644 --- a/memory/log.md +++ b/memory/log.md @@ -1,5 +1,17 @@ # iterator update log +## 2026-07-21 +* **Implementation**: Committed feature(simplify-ci-workflow) on branch iterator/safe-role-model-handoff; awaiting review. +* **Update**: Applied 1 feature adjustment(s). +* **Creation**: 1 feature(s) written. +* **Creation**: Plan "Simplify the failing CI pipeline" approved on branch iterator/safe-role-model-handoff. Consumed 1 selected backlog candidate(s). +* **Backlog**: delete on-plan-open-work-tab-2. +* **Backlog**: create on-plan-open-work-tab-2. +* **Backlog**: create on-plan-open-work-tab. +* **Retirement**: Plan "Finish auto mode after plan review" condensed into [Auto plan review resets runtime state](/decisions/auto-plan-review-terminal-reset.md). +* **Backlog**: select the-ci-pipeline-fails-remove-unnecessary-steps (selected). +* **Backlog**: create the-ci-pipeline-fails-remove-unnecessary-steps. + ## 2026-07-20 * **Plan review**: Whole-plan review recorded (agent). * **Review**: Reviewed [Finalize auto mode after plan review](/features/finalize-auto-plan-review.md); approved (agent). diff --git a/memory/plan.md b/memory/plan.md index ffe16d3..4fc72b9 100644 --- a/memory/plan.md +++ b/memory/plan.md @@ -1,25 +1,23 @@ --- type: Plan -title: Finish auto mode after plan review -description: Return the dashboard to completed manual state after the last automatic plan review records its report. +title: Simplify the failing CI pipeline +description: Remove redundant CI setup and matrix execution while preserving the repository test backstop. status: approved branch: iterator/safe-role-model-handoff -created: 2026-07-20 -timestamp: "2026-07-20T18:20:18.871Z" -plan_reviewed: 2026-07-20 +created: 2026-07-21 +timestamp: 2026-07-21T09:30:45.467Z --- # Goal -Make the final automatic plan-review transition reliably finish the auto run: after the final feature and plan review complete, clear stale auto state, release the Work UI from “Auto: plan-review”, and refresh it to the completed/retirable plan state. +Restore a reliable CI check by reducing the dependency-free Node.js pipeline to the minimum needed to run the repository test suite on pushes to main and pull requests. # Architecture -- Preserve `lib/status.mjs` as the source of derived plan lifecycle state; the fix only converges runtime state held in `memory/state.md` and the extension’s owned Work overlay. -- Extend the deterministic terminal path around `record-plan-review` / auto dispatch so an agent-authored final review records `plan_reviewed` and resets auto mode to manual, unpaused, terminal state with no active feature, strikes, or escalation. The transition must be idempotent for retries and must not reset a human-initiated plan review. -- Harden `extensions/iterator.js`’s auto completion driver to recognize the recorded terminal review even if the originating agent turn is ending or session refresh races it, restore any role model once, clear its owned overlay, and refresh the Work hub from gathered state. -- Cover the full transition in writer, auto-state-machine, extension lifecycle, and UI/session tests; develop in root `lib/` and extension code, then run `npm run sync` for shipped copies. -- Follow `architecture/workflow-state-ownership`, `decisions/manual-role-models-and-runtime-reset`, and `decisions/focus-feature-execution-and-dashboard-ownership`: state is server-derived and terminal auto runs reset deterministically without browser-local lifecycle inference. +- Keep `.github/workflows/ci.yml` as the CI entry point and preserve its existing push and pull-request triggers. +- Replace the three-version matrix with one `ubuntu-latest` test job that uses the runner’s available Node.js runtime. +- Keep only repository checkout and `npm test`; the project has no install-time package dependencies, build phase, or generated artifacts required before its built-in `node:test` suite runs. +- Preserve the repository’s package-and-skill layout and existing test suite as the CI contract, consistent with `architecture/package-and-skill-layout`. # Dependencies @@ -27,23 +25,10 @@ Make the final automatic plan-review transition reliably finish the auto run: af # Key decisions -- An agent’s successful `record-plan-review` is the durable terminal boundary for an auto run; it clears stale runtime ownership before the next driver tick, while manual reviews retain their existing state. -- The extension’s later `kickAuto` completion remains an idempotent convergence and UI-refresh path, not a second lifecycle authority. -- A completed plan remains retirable rather than being auto-retired; this change only removes the stale working state. -- No new dependencies or workflow statuses are introduced. +- Remove the Node 18/20/22 matrix because repeatedly running the same dependency-free suite is unnecessary for this CI backstop. +- Remove `actions/setup-node` and do not add `npm install`; the hosted runner already provides Node.js and the package declares no installed test dependencies. +- Do not change application code or weaken `npm test`; scope the fix to CI configuration and validate the resulting workflow locally where possible. # Features -* [Finalize auto mode after plan review](/features/finalize-auto-plan-review.md) - Agent plan-review completion resets durable auto state and refreshes Work so the final Auto step cannot remain stuck. - -# Plan review - -## 2026-07-20 _(agent review: openai-codex/gpt-5.6-sol)_ - -## Finding - -- **Goal coverage / terminal-boundary decision:** `a0f4243` makes `recordPlanReview` reset runtime ownership only when `b.state.mode === "auto" && !b.state.paused` (`lib/write.mjs`). If the user pauses auto mode while the plan-review agent is already running, the successful agent review still records `plan_reviewed` but returns `autoCompleted: false`; the extension therefore skips model restoration, overlay clearing, and the completed Work refresh, leaving the runtime in paused auto/reviewing state. This contradicts the plan’s unconditional agent-review terminal boundary and its reliability goal. The terminal transition should distinguish a stale/unrelated agent review without excluding an in-flight final review merely because pause was toggled, with regression coverage for that race. - -## Otherwise verified - -The normal unpaused path durably resets state, delayed driver ticks are inert, manual reviews retain runtime ownership, both completion paths honor `auto_retire_prompt`, synced writer copies match, and the full suite passes (392 passed, 4 skipped). The only scope drift is a formatting-only `writeUsage` line in `a0f4243`, with no behavior change. +* [Simplify CI workflow](/features/simplify-ci-workflow.md) - Run the repository test suite once in a minimal GitHub Actions job without redundant Node setup or version-matrix executions. diff --git a/memory/state.md b/memory/state.md index b0ac5fb..78bef71 100644 --- a/memory/state.md +++ b/memory/state.md @@ -2,13 +2,13 @@ type: State title: Runtime state description: Machine-owned iterator flow state — never hand-edited. -mode: manual +mode: auto paused: false -phase: done -active_feature: null -strikes: "{\"finalize-auto-plan-review\":1}" +phase: implementing +active_feature: simplify-ci-workflow +strikes: "{}" escalation: null -timestamp: 2026-07-20T18:20:24.884Z +timestamp: 2026-07-21T09:31:31.658Z --- Runtime flow state; read via gather, written only by the state op. diff --git a/memory/usage.md b/memory/usage.md index cb3858e..16a72bb 100644 --- a/memory/usage.md +++ b/memory/usage.md @@ -2,38 +2,29 @@ type: Usage title: Token usage description: Per-step model/token ledger and optional project-owned pricing for the active plan — written only by the usage op. -totals: "{\"steps\":{\"review\":{\"openai-codex/gpt-5.6-terra\":{\"input\":237934,\"output\":9168,\"cacheRead\":4968960,\"cacheWrite\":0,\"turns\":24},\"openai-codex/gpt-5.6-sol\":{\"input\":463467,\"output\":3871,\"cacheRead\":1914880,\"cacheWrite\":0,\"turns\":18}},\"implement\":{\"openai-codex/gpt-5.6-terra\":{\"input\":968435,\"output\":5724,\"cacheRead\":4179968,\"cacheWrite\":0,\"turns\":16},\"openai-codex/gpt-5.6-sol\":{\"input\":370896,\"output\":2721,\"cacheRead\":4590592,\"cacheWrite\":0,\"turns\":14}},\"hub\":{\"openai-codex/gpt-5.6-terra\":{\"input\":0,\"output\":0,\"cacheRead\":0,\"cacheWrite\":0,\"turns\":1}}},\"features\":{\"finalize-auto-plan-review\":{\"input\":1792296,\"output\":10754,\"cacheRead\":10406400,\"cacheWrite\":0,\"turns\":43},\"retire-plan\":{\"input\":0,\"output\":0,\"cacheRead\":0,\"cacheWrite\":0,\"turns\":1}},\"featureModels\":{\"finalize-auto-plan-review\":{\"openai-codex/gpt-5.6-terra\":{\"input\":968435,\"output\":5724,\"cacheRead\":4179968,\"cacheWrite\":0,\"turns\":16},\"openai-codex/gpt-5.6-sol\":{\"input\":823861,\"output\":5030,\"cacheRead\":6226432,\"cacheWrite\":0,\"turns\":27}},\"retire-plan\":{\"openai-codex/gpt-5.6-terra\":{\"input\":0,\"output\":0,\"cacheRead\":0,\"cacheWrite\":0,\"turns\":1}}}}" +totals: "{\"steps\":{\"hub\":{\"openai-codex/gpt-5.6-terra\":{\"input\":29149,\"output\":698,\"cacheRead\":59392,\"cacheWrite\":0,\"turns\":7}},\"plan\":{\"openai-codex/gpt-5.6-sol\":{\"input\":75380,\"output\":2872,\"cacheRead\":462336,\"cacheWrite\":0,\"turns\":19}}},\"features\":{\"retire-plan\":{\"input\":29149,\"output\":698,\"cacheRead\":59392,\"cacheWrite\":0,\"turns\":7}},\"featureModels\":{\"retire-plan\":{\"openai-codex/gpt-5.6-terra\":{\"input\":29149,\"output\":698,\"cacheRead\":59392,\"cacheWrite\":0,\"turns\":7}}}}" prices: "{}" -timestamp: 2026-07-20T18:25:32.417Z +timestamp: 2026-07-21T09:31:29.358Z --- # Usage -## review - -| model | input | output | cache read | cache write | turns | cost | -| --- | ---: | ---: | ---: | ---: | ---: | ---: | -| openai-codex/gpt-5.6-terra | 237934 | 9168 | 4968960 | 0 | 24 | — | -| openai-codex/gpt-5.6-sol | 463467 | 3871 | 1914880 | 0 | 18 | — | - -## implement +## hub | model | input | output | cache read | cache write | turns | cost | | --- | ---: | ---: | ---: | ---: | ---: | ---: | -| openai-codex/gpt-5.6-terra | 968435 | 5724 | 4179968 | 0 | 16 | — | -| openai-codex/gpt-5.6-sol | 370896 | 2721 | 4590592 | 0 | 14 | — | +| openai-codex/gpt-5.6-terra | 29149 | 698 | 59392 | 0 | 7 | — | -## hub +## plan | model | input | output | cache read | cache write | turns | cost | | --- | ---: | ---: | ---: | ---: | ---: | ---: | -| openai-codex/gpt-5.6-terra | 0 | 0 | 0 | 0 | 1 | — | +| openai-codex/gpt-5.6-sol | 75380 | 2872 | 462336 | 0 | 19 | — | ## Per feature | feature | input | output | cache read | cache write | turns | cost | | --- | ---: | ---: | ---: | ---: | ---: | ---: | -| finalize-auto-plan-review | 1792296 | 10754 | 10406400 | 0 | 43 | — | -| retire-plan | 0 | 0 | 0 | 0 | 1 | — | +| retire-plan | 29149 | 698 | 59392 | 0 | 7 | — | -Total: 2040732 in / 21484 out / 15654400 cache-read / 0 cache-write over 73 turns. Cost unavailable: add every used model rate. +Total: 104529 in / 3570 out / 521728 cache-read / 0 cache-write over 26 turns. Cost unavailable: add every used model rate. From 08ba3c6c4d318f5b28a759c70a0bf9ad0170490d Mon Sep 17 00:00:00 2001 From: Christoph Maier Date: Tue, 21 Jul 2026 11:32:12 +0200 Subject: [PATCH 02/12] chore(iterator): record feature commit --- memory/features/simplify-ci-workflow.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/memory/features/simplify-ci-workflow.md b/memory/features/simplify-ci-workflow.md index 4a66a38..fe0fad5 100644 --- a/memory/features/simplify-ci-workflow.md +++ b/memory/features/simplify-ci-workflow.md @@ -6,8 +6,12 @@ status: implemented size: small depends_on: [] files: [".github/workflows/ci.yml"] -timestamp: "2026-07-21T09:32:12.771Z" +timestamp: "2026-07-21T09:32:12.847Z" tags: [] +commits: + - sha: 818959c39f190815932ac3d7f9189c7d02e01272 + kind: implement + date: 2026-07-21 --- # Implementation notes From f495fd9c104aa4139cdde171e14ef13b79856e0e Mon Sep 17 00:00:00 2001 From: Christoph Maier Date: Tue, 21 Jul 2026 11:32:48 +0200 Subject: [PATCH 03/12] chore(iterator): record feature commits and memory updates --- memory/features/index.md | 2 +- memory/features/simplify-ci-workflow.md | 5 +++-- memory/log.md | 1 + memory/state.md | 4 ++-- memory/usage.md | 13 ++++++++++--- 5 files changed, 17 insertions(+), 8 deletions(-) diff --git a/memory/features/index.md b/memory/features/index.md index 6bc316c..456f8ee 100644 --- a/memory/features/index.md +++ b/memory/features/index.md @@ -1,3 +1,3 @@ # Features -* [Simplify CI workflow](simplify-ci-workflow.md) - ⬜ pending · small · Run the repository test suite once in a minimal GitHub Actions job without redundant Node setup or version-matrix executions. +* [Simplify CI workflow](simplify-ci-workflow.md) - ✅ done · small · Run the repository test suite once in a minimal GitHub Actions job without redundant Node setup or version-matrix executions. diff --git a/memory/features/simplify-ci-workflow.md b/memory/features/simplify-ci-workflow.md index fe0fad5..38b99f9 100644 --- a/memory/features/simplify-ci-workflow.md +++ b/memory/features/simplify-ci-workflow.md @@ -2,16 +2,17 @@ type: Feature title: Simplify CI workflow description: Run the repository test suite once in a minimal GitHub Actions job without redundant Node setup or version-matrix executions. -status: implemented +status: done size: small depends_on: [] files: [".github/workflows/ci.yml"] -timestamp: "2026-07-21T09:32:12.847Z" +timestamp: "2026-07-21T09:32:48.120Z" tags: [] commits: - sha: 818959c39f190815932ac3d7f9189c7d02e01272 kind: implement date: 2026-07-21 +done: 2026-07-21 --- # Implementation notes diff --git a/memory/log.md b/memory/log.md index f36fb2f..f32cebd 100644 --- a/memory/log.md +++ b/memory/log.md @@ -1,6 +1,7 @@ # iterator update log ## 2026-07-21 +* **Review**: Accepted [Simplify CI workflow](/features/simplify-ci-workflow.md) (committed as feature(simplify-ci-workflow)). * **Implementation**: Committed feature(simplify-ci-workflow) on branch iterator/safe-role-model-handoff; awaiting review. * **Update**: Applied 1 feature adjustment(s). * **Creation**: 1 feature(s) written. diff --git a/memory/state.md b/memory/state.md index 78bef71..c572830 100644 --- a/memory/state.md +++ b/memory/state.md @@ -4,11 +4,11 @@ title: Runtime state description: Machine-owned iterator flow state — never hand-edited. mode: auto paused: false -phase: implementing +phase: reviewing active_feature: simplify-ci-workflow strikes: "{}" escalation: null -timestamp: 2026-07-21T09:31:31.658Z +timestamp: 2026-07-21T09:32:24.734Z --- Runtime flow state; read via gather, written only by the state op. diff --git a/memory/usage.md b/memory/usage.md index 16a72bb..6c4af3e 100644 --- a/memory/usage.md +++ b/memory/usage.md @@ -2,9 +2,9 @@ type: Usage title: Token usage description: Per-step model/token ledger and optional project-owned pricing for the active plan — written only by the usage op. -totals: "{\"steps\":{\"hub\":{\"openai-codex/gpt-5.6-terra\":{\"input\":29149,\"output\":698,\"cacheRead\":59392,\"cacheWrite\":0,\"turns\":7}},\"plan\":{\"openai-codex/gpt-5.6-sol\":{\"input\":75380,\"output\":2872,\"cacheRead\":462336,\"cacheWrite\":0,\"turns\":19}}},\"features\":{\"retire-plan\":{\"input\":29149,\"output\":698,\"cacheRead\":59392,\"cacheWrite\":0,\"turns\":7}},\"featureModels\":{\"retire-plan\":{\"openai-codex/gpt-5.6-terra\":{\"input\":29149,\"output\":698,\"cacheRead\":59392,\"cacheWrite\":0,\"turns\":7}}}}" +totals: "{\"steps\":{\"hub\":{\"openai-codex/gpt-5.6-terra\":{\"input\":29149,\"output\":698,\"cacheRead\":59392,\"cacheWrite\":0,\"turns\":7}},\"plan\":{\"openai-codex/gpt-5.6-sol\":{\"input\":75380,\"output\":2872,\"cacheRead\":462336,\"cacheWrite\":0,\"turns\":19}},\"implement\":{\"openai-codex/gpt-5.6-terra\":{\"input\":92407,\"output\":927,\"cacheRead\":431104,\"cacheWrite\":0,\"turns\":11}}},\"features\":{\"retire-plan\":{\"input\":29149,\"output\":698,\"cacheRead\":59392,\"cacheWrite\":0,\"turns\":7},\"simplify-ci-workflow\":{\"input\":92407,\"output\":927,\"cacheRead\":431104,\"cacheWrite\":0,\"turns\":11}},\"featureModels\":{\"retire-plan\":{\"openai-codex/gpt-5.6-terra\":{\"input\":29149,\"output\":698,\"cacheRead\":59392,\"cacheWrite\":0,\"turns\":7}},\"simplify-ci-workflow\":{\"openai-codex/gpt-5.6-terra\":{\"input\":92407,\"output\":927,\"cacheRead\":431104,\"cacheWrite\":0,\"turns\":11}}}}" prices: "{}" -timestamp: 2026-07-21T09:31:29.358Z +timestamp: 2026-07-21T09:32:24.464Z --- # Usage @@ -21,10 +21,17 @@ timestamp: 2026-07-21T09:31:29.358Z | --- | ---: | ---: | ---: | ---: | ---: | ---: | | openai-codex/gpt-5.6-sol | 75380 | 2872 | 462336 | 0 | 19 | — | +## implement + +| model | input | output | cache read | cache write | turns | cost | +| --- | ---: | ---: | ---: | ---: | ---: | ---: | +| openai-codex/gpt-5.6-terra | 92407 | 927 | 431104 | 0 | 11 | — | + ## Per feature | feature | input | output | cache read | cache write | turns | cost | | --- | ---: | ---: | ---: | ---: | ---: | ---: | | retire-plan | 29149 | 698 | 59392 | 0 | 7 | — | +| simplify-ci-workflow | 92407 | 927 | 431104 | 0 | 11 | — | -Total: 104529 in / 3570 out / 521728 cache-read / 0 cache-write over 26 turns. Cost unavailable: add every used model rate. +Total: 196936 in / 4497 out / 952832 cache-read / 0 cache-write over 37 turns. Cost unavailable: add every used model rate. From eadb89bf9ca7fc3e753bb78d11cc2f4fb114971b Mon Sep 17 00:00:00 2001 From: Christoph Maier Date: Tue, 21 Jul 2026 16:02:20 +0200 Subject: [PATCH 04/12] feature(activate-work-on-plan-start): Activate Work when planning starts Feature: activate-work-on-plan-start --- extensions/iterator.js | 9 ++++ memory/backlog/index.md | 6 +-- memory/decisions/index.md | 1 + .../decisions/minimal-dependency-free-ci.md | 24 ++++++++++ .../features/activate-work-on-plan-start.md | 33 +++++++++++++ .../index.md | 3 ++ .../plan.md | 47 +++++++++++++++++++ .../simplify-ci-workflow.md | 8 +++- .../usage.md | 44 +++++++++++++++++ memory/features/index.md | 3 +- .../features/preserve-runtime-role-model.md | 37 +++++++++++++++ memory/index.md | 2 +- memory/log.md | 10 ++++ memory/plan.md | 28 ++++++----- memory/state.md | 6 +-- memory/usage.md | 19 +++----- test/extension-work-activation.test.mjs | 15 ++++++ 17 files changed, 261 insertions(+), 34 deletions(-) create mode 100644 memory/decisions/minimal-dependency-free-ci.md create mode 100644 memory/features/activate-work-on-plan-start.md create mode 100644 memory/features/archive/2026-07-21-minimal-dependency-free-ci/index.md create mode 100644 memory/features/archive/2026-07-21-minimal-dependency-free-ci/plan.md rename memory/features/{ => archive/2026-07-21-minimal-dependency-free-ci}/simplify-ci-workflow.md (75%) create mode 100644 memory/features/archive/2026-07-21-minimal-dependency-free-ci/usage.md create mode 100644 memory/features/preserve-runtime-role-model.md diff --git a/extensions/iterator.js b/extensions/iterator.js index 59e7328..a1a51ce 100644 --- a/extensions/iterator.js +++ b/extensions/iterator.js @@ -1158,6 +1158,15 @@ export default function iteratorExtension(pi) { } const cmd = actionToCommand(result); if (!cmd) return; + if (result.action === "plan") { + // Planning creates active work: deliberately land on Work before + // showing its owned overlay and starting the planner. + void refreshHub(ctxCwd(), { activateWork: true }).then(() => { + session.showWorking(`Dispatched ${cmd} — Agent is working…`); + dispatch(cmd); + }); + return; + } session.showWorking(`Dispatched ${cmd} — Agent is working…`); dispatch(cmd); }, diff --git a/memory/backlog/index.md b/memory/backlog/index.md index 0f1a4aa..726178f 100644 --- a/memory/backlog/index.md +++ b/memory/backlog/index.md @@ -2,10 +2,10 @@ type: Backlog title: Iterator backlog description: Saved ideas and bugs kept separate from active plan features. -items: "[{\"id\":\"on-plan-open-work-tab\",\"title\":\"on plan open work tab\",\"details\":\"when pressing in palning tab plan and it starts switch automaticvally to work\",\"kind\":\"bug\",\"selected\":false,\"created\":\"2026-07-21T09:01:21.266Z\",\"updated\":\"2026-07-21T09:01:21.266Z\"}]" -timestamp: 2026-07-21T09:30:45.471Z +items: "[]" +timestamp: 2026-07-21T13:59:28.639Z --- # Backlog -* [bug] on plan open work tab +(empty) diff --git a/memory/decisions/index.md b/memory/decisions/index.md index 7fe77ee..a07de67 100644 --- a/memory/decisions/index.md +++ b/memory/decisions/index.md @@ -7,6 +7,7 @@ Durable product and implementation choices agents should preserve. * [Backlog planning and parallel feature waves](/decisions/backlog-planning-and-feature-waves.md) - Keep low-risk backlog editing available during active work while implementing a fixed ready-feature wave and reviewing its commit-backed results together. * [Consume selected backlog ideas on plan approval](/decisions/consume-accepted-backlog-ideas.md) - Selected idea or bug candidates leave the backlog only after deterministic plan approval. * [Focus feature execution and dashboard ownership](/decisions/focus-feature-execution-and-dashboard-ownership.md) - Implementation now starts in fresh feature sessions, Work owns active plans, Settings preserves context as a shell modal, and red tests are explicit handoffs. +* [Keep dependency-free CI minimal](/decisions/minimal-dependency-free-ci.md) - For this dependency-free Node.js package, CI runs the repository test suite once without an unnecessary Node matrix or setup step. * [Memory relevance, usage costs, and dashboard recovery](/decisions/memory-relevance-usage-and-dashboard-recovery.md) - Iterator now bounds implementation context, keeps knowledge/retirement changes reviewed, prices usage only from project-owned rates, and maintains an authoritative active-work dashboard state. * [Parallel feature waves and consolidated review](/decisions/parallel-feature-waves-and-consolidated-review.md) - The dashboard supports fixed dependency-ready implementation waves and commit-backed multi-feature review without weakening explicit acceptance. * [Persist budget prices across plans](/decisions/persistent-budget-prices.md) - Project-owned Budget rates now persist across plans while active and archived cost reports remain reproducible. diff --git a/memory/decisions/minimal-dependency-free-ci.md b/memory/decisions/minimal-dependency-free-ci.md new file mode 100644 index 0000000..6ff3508 --- /dev/null +++ b/memory/decisions/minimal-dependency-free-ci.md @@ -0,0 +1,24 @@ +--- +type: Decision +title: Keep dependency-free CI minimal +description: For this dependency-free Node.js package, CI runs the repository test suite once without an unnecessary Node matrix or setup step. +status: accepted +date: 2026-07-21 +tags: [ci, github-actions, nodejs, testing] +files: [".github/workflows/ci.yml"] +timestamp: 2026-07-21T09:35:38.104Z +--- + +## Decision + +Keep the GitHub Actions workflow as a single `ubuntu-latest` job that checks out the repository and runs `npm test` for pushes to `main` and pull requests. Do not add a Node version matrix, `actions/setup-node`, or dependency-install step while the test suite has no installed dependencies and uses only the runner-provided Node.js runtime. + +## Rationale + +The previous Node 18/20/22 matrix repeated the same dependency-free test suite three times, and explicit Node setup added no value. A minimal workflow provides the required regression backstop with less CI time and fewer failure points. Revisit this decision if the project gains runtime-specific compatibility requirements or install-time test dependencies. + +# Retired plan + +Condensed from plan "Simplify the failing CI pipeline" (1 features, archived under /features/archive/2026-07-21-minimal-dependency-free-ci/). + +Token usage: 281758 in / 5588 out / 1730560 cache-read / 0 cache-write over 52 turns (per-step breakdown in the archived usage.md). diff --git a/memory/features/activate-work-on-plan-start.md b/memory/features/activate-work-on-plan-start.md new file mode 100644 index 0000000..bf094aa --- /dev/null +++ b/memory/features/activate-work-on-plan-start.md @@ -0,0 +1,33 @@ +--- +type: Feature +title: Activate Work when planning starts +description: Starting a plan from Planning immediately opens the Work progress surface while preserving the later plan review and approval landings. +status: implemented +size: small +depends_on: [] +files: ["extensions/iterator.js", "test/extension-work-activation.test.mjs"] +memories: [architecture/package-and-skill-layout, decisions/auto-plan-review-terminal-reset, decisions/backlog-planning-and-feature-waves, decisions/code-exact-red-test-review-and-agent-wording, decisions/focus-feature-execution-and-dashboard-ownership, decisions/iterator-dashboard-feature-workflow, decisions/manual-role-models-and-runtime-reset, decisions/memory-relevance-usage-and-dashboard-recovery] +timestamp: "2026-07-21T14:02:20.284Z" +tags: [] +--- + +# Implementation notes + +Route the unsolicited `plan` dashboard action through an intentional `refreshHub(..., { activateWork: true })` before showing the Work-owned overlay and dispatching the planner command. Keep ordinary refreshes tab-stable, keep the plan review on Planning, and retain approved-plan Work activation. Add a focused extension routing regression; no styling changes are needed. + +# Snippets + +```js +const cmd = actionToCommand(result); +if (!cmd) return; +session.showWorking(`Dispatched ${cmd} — Agent is working…`); +dispatch(cmd); +``` + +```js +await refreshHub(cwd, { activateWork: true }); +``` + +# Blast radius + +Planning-to-Work navigation and visibility of the agent working overlay when plan creation starts. diff --git a/memory/features/archive/2026-07-21-minimal-dependency-free-ci/index.md b/memory/features/archive/2026-07-21-minimal-dependency-free-ci/index.md new file mode 100644 index 0000000..456f8ee --- /dev/null +++ b/memory/features/archive/2026-07-21-minimal-dependency-free-ci/index.md @@ -0,0 +1,3 @@ +# Features + +* [Simplify CI workflow](simplify-ci-workflow.md) - ✅ done · small · Run the repository test suite once in a minimal GitHub Actions job without redundant Node setup or version-matrix executions. diff --git a/memory/features/archive/2026-07-21-minimal-dependency-free-ci/plan.md b/memory/features/archive/2026-07-21-minimal-dependency-free-ci/plan.md new file mode 100644 index 0000000..4b34c6a --- /dev/null +++ b/memory/features/archive/2026-07-21-minimal-dependency-free-ci/plan.md @@ -0,0 +1,47 @@ +--- +type: Plan +title: Simplify the failing CI pipeline +description: Remove redundant CI setup and matrix execution while preserving the repository test backstop. +status: approved +branch: iterator/safe-role-model-handoff +created: 2026-07-21 +timestamp: "2026-07-21T09:33:20.328Z" +plan_reviewed: 2026-07-21 +--- + +# Goal + +Restore a reliable CI check by reducing the dependency-free Node.js pipeline to the minimum needed to run the repository test suite on pushes to main and pull requests. + +# Architecture + +- Keep `.github/workflows/ci.yml` as the CI entry point and preserve its existing push and pull-request triggers. +- Replace the three-version matrix with one `ubuntu-latest` test job that uses the runner’s available Node.js runtime. +- Keep only repository checkout and `npm test`; the project has no install-time package dependencies, build phase, or generated artifacts required before its built-in `node:test` suite runs. +- Preserve the repository’s package-and-skill layout and existing test suite as the CI contract, consistent with `architecture/package-and-skill-layout`. + +# Dependencies + +(none) + +# Key decisions + +- Remove the Node 18/20/22 matrix because repeatedly running the same dependency-free suite is unnecessary for this CI backstop. +- Remove `actions/setup-node` and do not add `npm install`; the hosted runner already provides Node.js and the package declares no installed test dependencies. +- Do not change application code or weaken `npm test`; scope the fix to CI configuration and validate the resulting workflow locally where possible. + +# Features + +* [Simplify CI workflow](/features/simplify-ci-workflow.md) - Run the repository test suite once in a minimal GitHub Actions job without redundant Node setup or version-matrix executions. + +# Plan review + +## 2026-07-21 _(agent review: openai-codex/gpt-5.6-sol)_ + +## Clean bill + +- **Goal coverage:** Commit `818959c` reduces `.github/workflows/ci.yml` to one `ubuntu-latest` job while preserving pushes to `main`, pull requests, checkout, and `npm test`. +- **Architecture and key decisions:** The diff removes exactly the Node 18/20/22 matrix and `actions/setup-node`, adds no install/build steps or dependencies, and leaves the package code and test contract unchanged. +- **Scope and loose ends:** The only changed file is the declared workflow, the sole feature is accepted as done, and the plan diff introduces no unrelated changes or TODO markers. + +The completed work matches the approved plan with no findings. diff --git a/memory/features/simplify-ci-workflow.md b/memory/features/archive/2026-07-21-minimal-dependency-free-ci/simplify-ci-workflow.md similarity index 75% rename from memory/features/simplify-ci-workflow.md rename to memory/features/archive/2026-07-21-minimal-dependency-free-ci/simplify-ci-workflow.md index 38b99f9..2decb8d 100644 --- a/memory/features/simplify-ci-workflow.md +++ b/memory/features/archive/2026-07-21-minimal-dependency-free-ci/simplify-ci-workflow.md @@ -6,13 +6,14 @@ status: done size: small depends_on: [] files: [".github/workflows/ci.yml"] -timestamp: "2026-07-21T09:32:48.120Z" +timestamp: "2026-07-21T09:32:53.217Z" tags: [] commits: - sha: 818959c39f190815932ac3d7f9189c7d02e01272 kind: implement date: 2026-07-21 done: 2026-07-21 +reviewed: 2026-07-21 --- # Implementation notes @@ -33,3 +34,8 @@ jobs: # Blast radius GitHub Actions checks for pushes to main and all pull requests. + +# Review + +## 2026-07-21 +* **Approved** _(agent review: openai-codex/gpt-5.6-sol)_ — Approved: the commit removes only the redundant Node matrix and setup action while preserving triggers, checkout, and the unchanged npm test command. diff --git a/memory/features/archive/2026-07-21-minimal-dependency-free-ci/usage.md b/memory/features/archive/2026-07-21-minimal-dependency-free-ci/usage.md new file mode 100644 index 0000000..3275003 --- /dev/null +++ b/memory/features/archive/2026-07-21-minimal-dependency-free-ci/usage.md @@ -0,0 +1,44 @@ +--- +type: Usage +title: Token usage +description: Per-step model/token ledger and optional project-owned pricing for the active plan — written only by the usage op. +totals: "{\"steps\":{\"hub\":{\"openai-codex/gpt-5.6-terra\":{\"input\":29149,\"output\":698,\"cacheRead\":59392,\"cacheWrite\":0,\"turns\":7}},\"plan\":{\"openai-codex/gpt-5.6-sol\":{\"input\":75380,\"output\":2872,\"cacheRead\":462336,\"cacheWrite\":0,\"turns\":19}},\"implement\":{\"openai-codex/gpt-5.6-terra\":{\"input\":92407,\"output\":927,\"cacheRead\":431104,\"cacheWrite\":0,\"turns\":11}},\"review\":{\"openai-codex/gpt-5.6-sol\":{\"input\":25758,\"output\":1040,\"cacheRead\":719360,\"cacheWrite\":0,\"turns\":13},\"openai-codex/gpt-5.6-terra\":{\"input\":59064,\"output\":51,\"cacheRead\":58368,\"cacheWrite\":0,\"turns\":2}}},\"features\":{\"retire-plan\":{\"input\":29149,\"output\":698,\"cacheRead\":59392,\"cacheWrite\":0,\"turns\":7},\"simplify-ci-workflow\":{\"input\":113143,\"output\":1522,\"cacheRead\":863232,\"cacheWrite\":0,\"turns\":19}},\"featureModels\":{\"retire-plan\":{\"openai-codex/gpt-5.6-terra\":{\"input\":29149,\"output\":698,\"cacheRead\":59392,\"cacheWrite\":0,\"turns\":7}},\"simplify-ci-workflow\":{\"openai-codex/gpt-5.6-terra\":{\"input\":92407,\"output\":927,\"cacheRead\":431104,\"cacheWrite\":0,\"turns\":11},\"openai-codex/gpt-5.6-sol\":{\"input\":20736,\"output\":595,\"cacheRead\":432128,\"cacheWrite\":0,\"turns\":8}}}}" +prices: "{}" +timestamp: 2026-07-21T09:33:26.116Z +--- + +# Usage + +## hub + +| model | input | output | cache read | cache write | turns | cost | +| --- | ---: | ---: | ---: | ---: | ---: | ---: | +| openai-codex/gpt-5.6-terra | 29149 | 698 | 59392 | 0 | 7 | — | + +## plan + +| model | input | output | cache read | cache write | turns | cost | +| --- | ---: | ---: | ---: | ---: | ---: | ---: | +| openai-codex/gpt-5.6-sol | 75380 | 2872 | 462336 | 0 | 19 | — | + +## implement + +| model | input | output | cache read | cache write | turns | cost | +| --- | ---: | ---: | ---: | ---: | ---: | ---: | +| openai-codex/gpt-5.6-terra | 92407 | 927 | 431104 | 0 | 11 | — | + +## review + +| model | input | output | cache read | cache write | turns | cost | +| --- | ---: | ---: | ---: | ---: | ---: | ---: | +| openai-codex/gpt-5.6-sol | 25758 | 1040 | 719360 | 0 | 13 | — | +| openai-codex/gpt-5.6-terra | 59064 | 51 | 58368 | 0 | 2 | — | + +## Per feature + +| feature | input | output | cache read | cache write | turns | cost | +| --- | ---: | ---: | ---: | ---: | ---: | ---: | +| retire-plan | 29149 | 698 | 59392 | 0 | 7 | — | +| simplify-ci-workflow | 113143 | 1522 | 863232 | 0 | 19 | — | + +Total: 281758 in / 5588 out / 1730560 cache-read / 0 cache-write over 52 turns. Cost unavailable: add every used model rate. diff --git a/memory/features/index.md b/memory/features/index.md index 456f8ee..b2d83e0 100644 --- a/memory/features/index.md +++ b/memory/features/index.md @@ -1,3 +1,4 @@ # Features -* [Simplify CI workflow](simplify-ci-workflow.md) - ✅ done · small · Run the repository test suite once in a minimal GitHub Actions job without redundant Node setup or version-matrix executions. +* [Activate Work when planning starts](activate-work-on-plan-start.md) - ⬜ pending · small · Starting a plan from Planning immediately opens the Work progress surface while preserving the later plan review and approval landings. +* [Preserve runtime role-model authentication](preserve-runtime-role-model.md) - ⬜ pending · medium · Configured Iterator roles retain Pi’s active runtime model routing and correctly recognize modern void-returning model switches. diff --git a/memory/features/preserve-runtime-role-model.md b/memory/features/preserve-runtime-role-model.md new file mode 100644 index 0000000..408f239 --- /dev/null +++ b/memory/features/preserve-runtime-role-model.md @@ -0,0 +1,37 @@ +--- +type: Feature +title: Preserve runtime role-model authentication +description: Configured Iterator roles retain Pi’s active runtime model routing and correctly recognize modern void-returning model switches. +status: pending +size: medium +depends_on: [] +files: ["lib/pi-tools.mjs", "extensions/iterator.js", "test/pi-tools.test.mjs", "test/extension-model-lifecycle.test.mjs"] +memories: [architecture/package-and-skill-layout, decisions/auto-plan-review-terminal-reset, decisions/backlog-planning-and-feature-waves, decisions/code-exact-red-test-review-and-agent-wording, decisions/focus-feature-execution-and-dashboard-ownership, decisions/iterator-dashboard-feature-workflow, decisions/manual-role-models-and-runtime-reset, decisions/memory-relevance-usage-and-dashboard-recovery] +timestamp: "2026-07-21T14:01:04.365Z" +tags: [] +--- + +# Implementation notes + +Add pure provider/id identity and role-target resolution helpers in canonical `lib/pi-tools.mjs`. When the configured role model matches `ctx.model`, keep that exact runtime object (or skip a redundant switch) so host proxy/base-URL/auth metadata is not replaced by a registry object. For genuine switches, treat resolved `pi.setModel()` calls returning `undefined` as successful, explicit `false` as legacy failure, and exceptions as failure; arm one-time restoration only after a successful switch. Extend pure helper and extension lifecycle tests, then run `npm run sync` for shipped library copies. + +# Snippets + +```js +const m = lastCtx?.modelRegistry?.find?.(provider, id); +if (m) { + const previousModel = preAutoModel || lastCtx?.model || null; + const ok = await pi.setModel(m); + if (ok) { /* arm restoration */ } +} +``` + +```js +export function roleModelSpec(settings, role) { + // `active` means leave the current runtime model untouched. +} +``` + +# Blast radius + +Manual role turns, automatic role handoffs, model restoration, and Settings-selected planner/tester/implementer/reviewer models. diff --git a/memory/index.md b/memory/index.md index 3de5f0d..7abf880 100644 --- a/memory/index.md +++ b/memory/index.md @@ -11,7 +11,7 @@ last_memorized_commit: c5b75e3e4b034bc80a1600e57249e162639d32a8 * [Backlog](backlog/index.md) - Saved ideas and bugs outside active plan features. * [Settings](settings.md) - Project settings (auto mode, models, git flow). * [Features](features/) - One document per implementation feature. -* [Plan](plan.md) - Remove redundant CI setup and matrix execution while preserving the repository test backstop. +* [Plan](plan.md) - Move active plan creation to Work immediately and preserve Pi runtime model routing when applying role settings. * [Architecture](/architecture/) - How the system is structured. * [Decisions](/decisions/) - Durable product and implementation choices agents should preserve. * [Patterns & Conventions](/patterns/) - How code and workflows are written in this repo. diff --git a/memory/log.md b/memory/log.md index f32cebd..1efaf4a 100644 --- a/memory/log.md +++ b/memory/log.md @@ -1,6 +1,16 @@ # iterator update log ## 2026-07-21 +* **Implementation**: Committed feature(activate-work-on-plan-start) on branch iterator/safe-role-model-handoff; awaiting review. +* **Update**: Applied 2 feature adjustment(s). +* **Creation**: 2 feature(s) written. +* **Creation**: Plan "Focus plan starts and preserve managed model authentication" approved on branch iterator/safe-role-model-handoff. Consumed 2 selected backlog candidate(s). +* **Backlog**: select when-setting-the-mdoel-sin-settings-i-get-an-error-when-using-iterator (selected). +* **Backlog**: select on-plan-open-work-tab (selected). +* **Backlog**: create when-setting-the-mdoel-sin-settings-i-get-an-error-when-using-iterator. +* **Retirement**: Plan "Simplify the failing CI pipeline" condensed into [Keep dependency-free CI minimal](/decisions/minimal-dependency-free-ci.md). +* **Plan review**: Whole-plan review recorded (agent). +* **Review**: Reviewed [Simplify CI workflow](/features/simplify-ci-workflow.md); approved (agent). * **Review**: Accepted [Simplify CI workflow](/features/simplify-ci-workflow.md) (committed as feature(simplify-ci-workflow)). * **Implementation**: Committed feature(simplify-ci-workflow) on branch iterator/safe-role-model-handoff; awaiting review. * **Update**: Applied 1 feature adjustment(s). diff --git a/memory/plan.md b/memory/plan.md index 4fc72b9..a960869 100644 --- a/memory/plan.md +++ b/memory/plan.md @@ -1,23 +1,24 @@ --- type: Plan -title: Simplify the failing CI pipeline -description: Remove redundant CI setup and matrix execution while preserving the repository test backstop. +title: Focus plan starts and preserve managed model authentication +description: Move active plan creation to Work immediately and preserve Pi runtime model routing when applying role settings. status: approved branch: iterator/safe-role-model-handoff created: 2026-07-21 -timestamp: 2026-07-21T09:30:45.467Z +timestamp: 2026-07-21T13:59:28.635Z --- # Goal -Restore a reliable CI check by reducing the dependency-free Node.js pipeline to the minimum needed to run the repository test suite on pushes to main and pull requests. +Make Iterator plan creation visibly move from Planning to the Work progress surface as soon as the planner starts, and make configured role models use Pi’s active runtime model/authentication safely so skill calls do not fail with the managed credential sent to a direct OpenAI endpoint. # Architecture -- Keep `.github/workflows/ci.yml` as the CI entry point and preserve its existing push and pull-request triggers. -- Replace the three-version matrix with one `ubuntu-latest` test job that uses the runner’s available Node.js runtime. -- Keep only repository checkout and `npm test`; the project has no install-time package dependencies, build phase, or generated artifacts required before its built-in `node:test` suite runs. -- Preserve the repository’s package-and-skill layout and existing test suite as the CI contract, consistent with `architecture/package-and-skill-layout`. +- Extend the persistent dashboard dispatch seam in `extensions/iterator.js`: a Planning `plan` action intentionally refreshes and activates Work before showing the owned working overlay and dispatching `/skill:iterator-plan`; the later plan-review round may still activate Planning, and approval continues to land on Work, consistent with `architecture/browser-server-contract` and `decisions/review-navigation-and-work-context`. +- Harden role-model application in `extensions/iterator.js` around Pi’s current extension API: resolve a configured provider/id that matches `ctx.model` to that exact active runtime model object instead of replacing it with `modelRegistry.find(...)`, preserving host/proxy routing and credentials. +- Treat a resolved `pi.setModel()` call as success even when the modern API returns `void`; only an explicit legacy `false` result or a thrown error is failure. Keep restoration armed only after a real switch, preserving the FIFO/manual/auto ownership rules from `decisions/manual-role-models-and-runtime-reset` and `decisions/safe-role-model-restoration`. +- Keep pure model identity/resolution policy in `lib/pi-tools.mjs`, consume it from the extension, and run `npm run sync` so the shipped skill copy remains aligned with `architecture/package-and-skill-layout`. +- Add focused extension routing and model-lifecycle regressions for immediate Work activation, active runtime model preservation, void-return success, failure isolation, and one-time restoration; retain the existing full suite and design parameters without redesigning dashboard UI. # Dependencies @@ -25,10 +26,13 @@ Restore a reliable CI check by reducing the dependency-free Node.js pipeline to # Key decisions -- Remove the Node 18/20/22 matrix because repeatedly running the same dependency-free suite is unnecessary for this CI backstop. -- Remove `actions/setup-node` and do not add `npm install`; the hosted runner already provides Node.js and the package declares no installed test dependencies. -- Do not change application code or weaken `npm test`; scope the fix to CI configuration and validate the resulting workflow locally where possible. +- Starting Plan from Planning is an intentional Work landing because the active agent overlay is Work-owned; ordinary dashboard refreshes still preserve the user’s selected tab. +- An exact provider/id match must retain `ctx.model` as the authoritative runtime model object so proxy/base-URL/auth metadata supplied by Pi is not discarded by a registry re-lookup. +- Follow Pi’s modern `setModel` contract: successful resolution may return `undefined`; failure is an exception, while explicit `false` remains supported for older runtimes. +- Do not probe providers or hard-code the `proxy-managed` credential sentinel; prevent the invalid direct-provider path structurally and leave genuinely unavailable alternate models on the current active model with a warning. +- No workflow statuses, settings keys, external dependencies, or visual redesign are introduced. # Features -* [Simplify CI workflow](/features/simplify-ci-workflow.md) - Run the repository test suite once in a minimal GitHub Actions job without redundant Node setup or version-matrix executions. +* [Activate Work when planning starts](/features/activate-work-on-plan-start.md) - Starting a plan from Planning immediately opens the Work progress surface while preserving the later plan review and approval landings. +* [Preserve runtime role-model authentication](/features/preserve-runtime-role-model.md) - Configured Iterator roles retain Pi’s active runtime model routing and correctly recognize modern void-returning model switches. diff --git a/memory/state.md b/memory/state.md index c572830..5842526 100644 --- a/memory/state.md +++ b/memory/state.md @@ -4,11 +4,11 @@ title: Runtime state description: Machine-owned iterator flow state — never hand-edited. mode: auto paused: false -phase: reviewing -active_feature: simplify-ci-workflow +phase: implementing +active_feature: activate-work-on-plan-start strikes: "{}" escalation: null -timestamp: 2026-07-21T09:32:24.734Z +timestamp: 2026-07-21T14:01:12.954Z --- Runtime flow state; read via gather, written only by the state op. diff --git a/memory/usage.md b/memory/usage.md index 6c4af3e..6b1c260 100644 --- a/memory/usage.md +++ b/memory/usage.md @@ -2,9 +2,9 @@ type: Usage title: Token usage description: Per-step model/token ledger and optional project-owned pricing for the active plan — written only by the usage op. -totals: "{\"steps\":{\"hub\":{\"openai-codex/gpt-5.6-terra\":{\"input\":29149,\"output\":698,\"cacheRead\":59392,\"cacheWrite\":0,\"turns\":7}},\"plan\":{\"openai-codex/gpt-5.6-sol\":{\"input\":75380,\"output\":2872,\"cacheRead\":462336,\"cacheWrite\":0,\"turns\":19}},\"implement\":{\"openai-codex/gpt-5.6-terra\":{\"input\":92407,\"output\":927,\"cacheRead\":431104,\"cacheWrite\":0,\"turns\":11}}},\"features\":{\"retire-plan\":{\"input\":29149,\"output\":698,\"cacheRead\":59392,\"cacheWrite\":0,\"turns\":7},\"simplify-ci-workflow\":{\"input\":92407,\"output\":927,\"cacheRead\":431104,\"cacheWrite\":0,\"turns\":11}},\"featureModels\":{\"retire-plan\":{\"openai-codex/gpt-5.6-terra\":{\"input\":29149,\"output\":698,\"cacheRead\":59392,\"cacheWrite\":0,\"turns\":7}},\"simplify-ci-workflow\":{\"openai-codex/gpt-5.6-terra\":{\"input\":92407,\"output\":927,\"cacheRead\":431104,\"cacheWrite\":0,\"turns\":11}}}}" +totals: "{\"steps\":{\"hub\":{\"openai-codex/gpt-5.6-terra\":{\"input\":4327,\"output\":565,\"cacheRead\":413184,\"cacheWrite\":0,\"turns\":7}},\"plan\":{\"openai-codex/gpt-5.6-sol\":{\"input\":173740,\"output\":9070,\"cacheRead\":3877888,\"cacheWrite\":0,\"turns\":35}}},\"features\":{\"retire-plan\":{\"input\":4327,\"output\":565,\"cacheRead\":413184,\"cacheWrite\":0,\"turns\":7}},\"featureModels\":{\"retire-plan\":{\"openai-codex/gpt-5.6-terra\":{\"input\":4327,\"output\":565,\"cacheRead\":413184,\"cacheWrite\":0,\"turns\":7}}}}" prices: "{}" -timestamp: 2026-07-21T09:32:24.464Z +timestamp: 2026-07-21T14:01:10.469Z --- # Usage @@ -13,25 +13,18 @@ timestamp: 2026-07-21T09:32:24.464Z | model | input | output | cache read | cache write | turns | cost | | --- | ---: | ---: | ---: | ---: | ---: | ---: | -| openai-codex/gpt-5.6-terra | 29149 | 698 | 59392 | 0 | 7 | — | +| openai-codex/gpt-5.6-terra | 4327 | 565 | 413184 | 0 | 7 | — | ## plan | model | input | output | cache read | cache write | turns | cost | | --- | ---: | ---: | ---: | ---: | ---: | ---: | -| openai-codex/gpt-5.6-sol | 75380 | 2872 | 462336 | 0 | 19 | — | - -## implement - -| model | input | output | cache read | cache write | turns | cost | -| --- | ---: | ---: | ---: | ---: | ---: | ---: | -| openai-codex/gpt-5.6-terra | 92407 | 927 | 431104 | 0 | 11 | — | +| openai-codex/gpt-5.6-sol | 173740 | 9070 | 3877888 | 0 | 35 | — | ## Per feature | feature | input | output | cache read | cache write | turns | cost | | --- | ---: | ---: | ---: | ---: | ---: | ---: | -| retire-plan | 29149 | 698 | 59392 | 0 | 7 | — | -| simplify-ci-workflow | 92407 | 927 | 431104 | 0 | 11 | — | +| retire-plan | 4327 | 565 | 413184 | 0 | 7 | — | -Total: 196936 in / 4497 out / 952832 cache-read / 0 cache-write over 37 turns. Cost unavailable: add every used model rate. +Total: 178067 in / 9635 out / 4291072 cache-read / 0 cache-write over 42 turns. Cost unavailable: add every used model rate. diff --git a/test/extension-work-activation.test.mjs b/test/extension-work-activation.test.mjs index 0051ebd..d1a3134 100644 --- a/test/extension-work-activation.test.mjs +++ b/test/extension-work-activation.test.mjs @@ -27,6 +27,21 @@ test("accepted feature breakdown intentionally activates Work", () => { ); }); +test("starting a plan from Planning intentionally activates Work", () => { + const from = source.indexOf('const cmd = actionToCommand(result);'); + assert.notEqual(from, -1); + const section = source.slice(from, from + 800); + assert.match(section, /if \(result\.action === "plan"\)/); + assert.match( + section, + /refreshHub\(ctxCwd\(\), \{ activateWork: true \}\)\.then\(\(\) => \{/, + ); + assert.match( + section, + /session\.showWorking\(`Dispatched \$\{cmd\} — Agent is working…`\);\n\s*dispatch\(cmd\);/, + ); +}); + test("approved plan application intentionally activates Work", () => { const section = sourceSection( "// Apply-on-approve (mirrors lib/app.mjs)", From 109223f45c86687d0667e7ae9918c5b46398b7ed Mon Sep 17 00:00:00 2001 From: Christoph Maier Date: Tue, 21 Jul 2026 16:02:20 +0200 Subject: [PATCH 05/12] chore(iterator): record feature commit --- memory/features/activate-work-on-plan-start.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/memory/features/activate-work-on-plan-start.md b/memory/features/activate-work-on-plan-start.md index bf094aa..0a653b2 100644 --- a/memory/features/activate-work-on-plan-start.md +++ b/memory/features/activate-work-on-plan-start.md @@ -7,8 +7,12 @@ size: small depends_on: [] files: ["extensions/iterator.js", "test/extension-work-activation.test.mjs"] memories: [architecture/package-and-skill-layout, decisions/auto-plan-review-terminal-reset, decisions/backlog-planning-and-feature-waves, decisions/code-exact-red-test-review-and-agent-wording, decisions/focus-feature-execution-and-dashboard-ownership, decisions/iterator-dashboard-feature-workflow, decisions/manual-role-models-and-runtime-reset, decisions/memory-relevance-usage-and-dashboard-recovery] -timestamp: "2026-07-21T14:02:20.284Z" +timestamp: "2026-07-21T14:02:20.366Z" tags: [] +commits: + - sha: eadb89bf9ca7fc3e753bb78d11cc2f4fb114971b + kind: implement + date: 2026-07-21 --- # Implementation notes From 37a06f5a6c19c7114ce0ae72a10f5c9b401040cf Mon Sep 17 00:00:00 2001 From: Christoph Maier Date: Tue, 21 Jul 2026 16:05:11 +0200 Subject: [PATCH 06/12] feature(activate-work-on-plan-start): Keep plan dispatch resilient to refresh failures Feature: activate-work-on-plan-start --- extensions/iterator.js | 20 +++++++--- lib/dashboard-dispatch.mjs | 16 ++++++++ memory/backlog/index.md | 6 +-- .../features/activate-work-on-plan-start.md | 8 +++- memory/log.md | 3 ++ memory/state.md | 4 +- memory/usage.md | 19 +++++++-- test/extension-work-activation.test.mjs | 39 ++++++++++++++++++- 8 files changed, 99 insertions(+), 16 deletions(-) create mode 100644 lib/dashboard-dispatch.mjs diff --git a/extensions/iterator.js b/extensions/iterator.js index a1a51ce..b7956de 100644 --- a/extensions/iterator.js +++ b/extensions/iterator.js @@ -40,6 +40,7 @@ import { relative, resolve } from "node:path"; import { Type } from "typebox"; import { matchConcepts, OKF_AREA_NAMES } from "../lib/bundle.mjs"; +import { dispatchAfterRefresh } from "../lib/dashboard-dispatch.mjs"; import { hydrateMemoryCards } from "../lib/gather.mjs"; import { checkBashCommit, @@ -1160,11 +1161,20 @@ export default function iteratorExtension(pi) { if (!cmd) return; if (result.action === "plan") { // Planning creates active work: deliberately land on Work before - // showing its owned overlay and starting the planner. - void refreshHub(ctxCwd(), { activateWork: true }).then(() => { - session.showWorking(`Dispatched ${cmd} — Agent is working…`); - dispatch(cmd); - }); + // showing its owned overlay and starting the planner. A broken + // refresh is advisory; it must never swallow the requested action. + void dispatchAfterRefresh( + () => refreshHub(ctxCwd(), { activateWork: true }), + () => { + session.showWorking(`Dispatched ${cmd} — Agent is working…`); + dispatch(cmd); + }, + (error) => + notifyUi( + `could not activate Work before planning: ${error.message}`, + "warning", + ), + ); return; } session.showWorking(`Dispatched ${cmd} — Agent is working…`); diff --git a/lib/dashboard-dispatch.mjs b/lib/dashboard-dispatch.mjs new file mode 100644 index 0000000..e233e75 --- /dev/null +++ b/lib/dashboard-dispatch.mjs @@ -0,0 +1,16 @@ +export async function dispatchAfterRefresh( + refresh, + dispatch, + onRefreshError = () => {}, +) { + try { + await refresh(); + } catch (error) { + try { + onRefreshError(error); + } catch { + // Reporting a dashboard refresh failure must not block the action. + } + } + return dispatch(); +} diff --git a/memory/backlog/index.md b/memory/backlog/index.md index 726178f..13ec492 100644 --- a/memory/backlog/index.md +++ b/memory/backlog/index.md @@ -2,10 +2,10 @@ type: Backlog title: Iterator backlog description: Saved ideas and bugs kept separate from active plan features. -items: "[]" -timestamp: 2026-07-21T13:59:28.639Z +items: "[{\"id\":\"after-initial-install-no-update-possible\",\"title\":\"after initial install no update possible\",\"details\":\"it returns that it cannot find the latest version after new start in a repo each time.\",\"kind\":\"bug\",\"selected\":false,\"created\":\"2026-07-21T14:03:15.367Z\",\"updated\":\"2026-07-21T14:03:15.368Z\"}]" +timestamp: 2026-07-21T14:03:15.368Z --- # Backlog -(empty) +* [bug] after initial install no update possible diff --git a/memory/features/activate-work-on-plan-start.md b/memory/features/activate-work-on-plan-start.md index 0a653b2..115dd72 100644 --- a/memory/features/activate-work-on-plan-start.md +++ b/memory/features/activate-work-on-plan-start.md @@ -7,12 +7,13 @@ size: small depends_on: [] files: ["extensions/iterator.js", "test/extension-work-activation.test.mjs"] memories: [architecture/package-and-skill-layout, decisions/auto-plan-review-terminal-reset, decisions/backlog-planning-and-feature-waves, decisions/code-exact-red-test-review-and-agent-wording, decisions/focus-feature-execution-and-dashboard-ownership, decisions/iterator-dashboard-feature-workflow, decisions/manual-role-models-and-runtime-reset, decisions/memory-relevance-usage-and-dashboard-recovery] -timestamp: "2026-07-21T14:02:20.366Z" +timestamp: "2026-07-21T14:05:11.572Z" tags: [] commits: - sha: eadb89bf9ca7fc3e753bb78d11cc2f4fb114971b kind: implement date: 2026-07-21 +reviewed: 2026-07-21 --- # Implementation notes @@ -35,3 +36,8 @@ await refreshHub(cwd, { activateWork: true }); # Blast radius Planning-to-Work navigation and visibility of the agent working overlay when plan creation starts. + +# Review + +## 2026-07-21 +* **Needs changes** _(agent review: openai-codex/gpt-5.6-sol)_ — The new plan path chains dispatch only inside `refreshHub(...).then(...)`. If dashboard gathering/rendering rejects, the promise is unhandled and the requested plan never starts, whereas the prior generic path always dispatched. Wrap the activation in an async helper or catch/finally so refresh failure is reported but `showWorking`/`dispatch(cmd)` still occur exactly once; add a behavioral regression for the rejection path rather than only source-pattern assertions. diff --git a/memory/log.md b/memory/log.md index 1efaf4a..3bfcef0 100644 --- a/memory/log.md +++ b/memory/log.md @@ -2,6 +2,9 @@ ## 2026-07-21 * **Implementation**: Committed feature(activate-work-on-plan-start) on branch iterator/safe-role-model-handoff; awaiting review. +* **Backlog**: create after-initial-install-no-update-possible. +* **Review**: Reviewed [Activate Work when planning starts](/features/activate-work-on-plan-start.md); changes (agent). +* **Implementation**: Committed feature(activate-work-on-plan-start) on branch iterator/safe-role-model-handoff; awaiting review. * **Update**: Applied 2 feature adjustment(s). * **Creation**: 2 feature(s) written. * **Creation**: Plan "Focus plan starts and preserve managed model authentication" approved on branch iterator/safe-role-model-handoff. Consumed 2 selected backlog candidate(s). diff --git a/memory/state.md b/memory/state.md index 5842526..37c4dd0 100644 --- a/memory/state.md +++ b/memory/state.md @@ -6,9 +6,9 @@ mode: auto paused: false phase: implementing active_feature: activate-work-on-plan-start -strikes: "{}" +strikes: "{\"activate-work-on-plan-start\":1}" escalation: null -timestamp: 2026-07-21T14:01:12.954Z +timestamp: 2026-07-21T14:02:58.519Z --- Runtime flow state; read via gather, written only by the state op. diff --git a/memory/usage.md b/memory/usage.md index 6b1c260..55dbee0 100644 --- a/memory/usage.md +++ b/memory/usage.md @@ -2,9 +2,9 @@ type: Usage title: Token usage description: Per-step model/token ledger and optional project-owned pricing for the active plan — written only by the usage op. -totals: "{\"steps\":{\"hub\":{\"openai-codex/gpt-5.6-terra\":{\"input\":4327,\"output\":565,\"cacheRead\":413184,\"cacheWrite\":0,\"turns\":7}},\"plan\":{\"openai-codex/gpt-5.6-sol\":{\"input\":173740,\"output\":9070,\"cacheRead\":3877888,\"cacheWrite\":0,\"turns\":35}}},\"features\":{\"retire-plan\":{\"input\":4327,\"output\":565,\"cacheRead\":413184,\"cacheWrite\":0,\"turns\":7}},\"featureModels\":{\"retire-plan\":{\"openai-codex/gpt-5.6-terra\":{\"input\":4327,\"output\":565,\"cacheRead\":413184,\"cacheWrite\":0,\"turns\":7}}}}" +totals: "{\"steps\":{\"hub\":{\"openai-codex/gpt-5.6-terra\":{\"input\":4327,\"output\":565,\"cacheRead\":413184,\"cacheWrite\":0,\"turns\":7}},\"plan\":{\"openai-codex/gpt-5.6-sol\":{\"input\":173740,\"output\":9070,\"cacheRead\":3877888,\"cacheWrite\":0,\"turns\":35}},\"implement\":{\"openai-codex/gpt-5.6-terra\":{\"input\":170574,\"output\":1849,\"cacheRead\":1737728,\"cacheWrite\":0,\"turns\":12}},\"review\":{\"openai-codex/gpt-5.6-sol\":{\"input\":186110,\"output\":546,\"cacheRead\":852992,\"cacheWrite\":0,\"turns\":6}}},\"features\":{\"retire-plan\":{\"input\":4327,\"output\":565,\"cacheRead\":413184,\"cacheWrite\":0,\"turns\":7},\"activate-work-on-plan-start\":{\"input\":356684,\"output\":2395,\"cacheRead\":2590720,\"cacheWrite\":0,\"turns\":18}},\"featureModels\":{\"retire-plan\":{\"openai-codex/gpt-5.6-terra\":{\"input\":4327,\"output\":565,\"cacheRead\":413184,\"cacheWrite\":0,\"turns\":7}},\"activate-work-on-plan-start\":{\"openai-codex/gpt-5.6-terra\":{\"input\":170574,\"output\":1849,\"cacheRead\":1737728,\"cacheWrite\":0,\"turns\":12},\"openai-codex/gpt-5.6-sol\":{\"input\":186110,\"output\":546,\"cacheRead\":852992,\"cacheWrite\":0,\"turns\":6}}}}" prices: "{}" -timestamp: 2026-07-21T14:01:10.469Z +timestamp: 2026-07-21T14:02:58.191Z --- # Usage @@ -21,10 +21,23 @@ timestamp: 2026-07-21T14:01:10.469Z | --- | ---: | ---: | ---: | ---: | ---: | ---: | | openai-codex/gpt-5.6-sol | 173740 | 9070 | 3877888 | 0 | 35 | — | +## implement + +| model | input | output | cache read | cache write | turns | cost | +| --- | ---: | ---: | ---: | ---: | ---: | ---: | +| openai-codex/gpt-5.6-terra | 170574 | 1849 | 1737728 | 0 | 12 | — | + +## review + +| model | input | output | cache read | cache write | turns | cost | +| --- | ---: | ---: | ---: | ---: | ---: | ---: | +| openai-codex/gpt-5.6-sol | 186110 | 546 | 852992 | 0 | 6 | — | + ## Per feature | feature | input | output | cache read | cache write | turns | cost | | --- | ---: | ---: | ---: | ---: | ---: | ---: | | retire-plan | 4327 | 565 | 413184 | 0 | 7 | — | +| activate-work-on-plan-start | 356684 | 2395 | 2590720 | 0 | 18 | — | -Total: 178067 in / 9635 out / 4291072 cache-read / 0 cache-write over 42 turns. Cost unavailable: add every used model rate. +Total: 534751 in / 12030 out / 6881792 cache-read / 0 cache-write over 60 turns. Cost unavailable: add every used model rate. diff --git a/test/extension-work-activation.test.mjs b/test/extension-work-activation.test.mjs index d1a3134..dc37be4 100644 --- a/test/extension-work-activation.test.mjs +++ b/test/extension-work-activation.test.mjs @@ -1,6 +1,7 @@ import { readFileSync } from "node:fs"; import { test } from "node:test"; import assert from "node:assert/strict"; +import { dispatchAfterRefresh } from "../lib/dashboard-dispatch.mjs"; const source = readFileSync( new URL("../extensions/iterator.js", import.meta.url), @@ -28,13 +29,14 @@ test("accepted feature breakdown intentionally activates Work", () => { }); test("starting a plan from Planning intentionally activates Work", () => { - const from = source.indexOf('const cmd = actionToCommand(result);'); + const from = source.indexOf("const cmd = actionToCommand(result);"); assert.notEqual(from, -1); const section = source.slice(from, from + 800); assert.match(section, /if \(result\.action === "plan"\)/); + assert.match(section, /dispatchAfterRefresh\(/); assert.match( section, - /refreshHub\(ctxCwd\(\), \{ activateWork: true \}\)\.then\(\(\) => \{/, + /\(\) => refreshHub\(ctxCwd\(\), \{ activateWork: true \}\)/, ); assert.match( section, @@ -42,6 +44,39 @@ test("starting a plan from Planning intentionally activates Work", () => { ); }); +test("plan dispatch survives a failed Work refresh exactly once", async () => { + const calls = []; + await dispatchAfterRefresh( + async () => { + calls.push("refresh"); + throw new Error("gather failed"); + }, + () => calls.push("dispatch"), + (error) => calls.push(`warning: ${error.message}`), + ); + assert.deepEqual(calls, [ + "refresh", + "warning: gather failed", + "dispatch", + ]); +}); + +test("plan dispatch survives a broken refresh reporter", async () => { + let dispatched = 0; + await dispatchAfterRefresh( + async () => { + throw new Error("gather failed"); + }, + () => { + dispatched += 1; + }, + () => { + throw new Error("notification failed"); + }, + ); + assert.equal(dispatched, 1); +}); + test("approved plan application intentionally activates Work", () => { const section = sourceSection( "// Apply-on-approve (mirrors lib/app.mjs)", From dcc43f4a3d3139f67064759b71ff5602a9506e72 Mon Sep 17 00:00:00 2001 From: Christoph Maier Date: Tue, 21 Jul 2026 16:05:11 +0200 Subject: [PATCH 07/12] chore(iterator): record feature commit --- memory/features/activate-work-on-plan-start.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/memory/features/activate-work-on-plan-start.md b/memory/features/activate-work-on-plan-start.md index 115dd72..0652d55 100644 --- a/memory/features/activate-work-on-plan-start.md +++ b/memory/features/activate-work-on-plan-start.md @@ -7,12 +7,15 @@ size: small depends_on: [] files: ["extensions/iterator.js", "test/extension-work-activation.test.mjs"] memories: [architecture/package-and-skill-layout, decisions/auto-plan-review-terminal-reset, decisions/backlog-planning-and-feature-waves, decisions/code-exact-red-test-review-and-agent-wording, decisions/focus-feature-execution-and-dashboard-ownership, decisions/iterator-dashboard-feature-workflow, decisions/manual-role-models-and-runtime-reset, decisions/memory-relevance-usage-and-dashboard-recovery] -timestamp: "2026-07-21T14:05:11.572Z" +timestamp: "2026-07-21T14:05:11.641Z" tags: [] commits: - sha: eadb89bf9ca7fc3e753bb78d11cc2f4fb114971b kind: implement date: 2026-07-21 + - sha: 37a06f5a6c19c7114ce0ae72a10f5c9b401040cf + kind: implement + date: 2026-07-21 reviewed: 2026-07-21 --- From b78d14cea84a5ac7de2618531eb64227ff3af60a Mon Sep 17 00:00:00 2001 From: Christoph Maier Date: Tue, 21 Jul 2026 16:05:59 +0200 Subject: [PATCH 08/12] chore(iterator): record feature commits and memory updates --- memory/features/activate-work-on-plan-start.md | 5 +++-- memory/features/index.md | 2 +- memory/log.md | 1 + memory/state.md | 4 ++-- memory/usage.md | 9 +++++---- 5 files changed, 12 insertions(+), 9 deletions(-) diff --git a/memory/features/activate-work-on-plan-start.md b/memory/features/activate-work-on-plan-start.md index 0652d55..85e4227 100644 --- a/memory/features/activate-work-on-plan-start.md +++ b/memory/features/activate-work-on-plan-start.md @@ -2,12 +2,12 @@ type: Feature title: Activate Work when planning starts description: Starting a plan from Planning immediately opens the Work progress surface while preserving the later plan review and approval landings. -status: implemented +status: done size: small depends_on: [] files: ["extensions/iterator.js", "test/extension-work-activation.test.mjs"] memories: [architecture/package-and-skill-layout, decisions/auto-plan-review-terminal-reset, decisions/backlog-planning-and-feature-waves, decisions/code-exact-red-test-review-and-agent-wording, decisions/focus-feature-execution-and-dashboard-ownership, decisions/iterator-dashboard-feature-workflow, decisions/manual-role-models-and-runtime-reset, decisions/memory-relevance-usage-and-dashboard-recovery] -timestamp: "2026-07-21T14:05:11.641Z" +timestamp: "2026-07-21T14:05:59.326Z" tags: [] commits: - sha: eadb89bf9ca7fc3e753bb78d11cc2f4fb114971b @@ -17,6 +17,7 @@ commits: kind: implement date: 2026-07-21 reviewed: 2026-07-21 +done: 2026-07-21 --- # Implementation notes diff --git a/memory/features/index.md b/memory/features/index.md index b2d83e0..09b175a 100644 --- a/memory/features/index.md +++ b/memory/features/index.md @@ -1,4 +1,4 @@ # Features -* [Activate Work when planning starts](activate-work-on-plan-start.md) - ⬜ pending · small · Starting a plan from Planning immediately opens the Work progress surface while preserving the later plan review and approval landings. +* [Activate Work when planning starts](activate-work-on-plan-start.md) - ✅ done · small · Starting a plan from Planning immediately opens the Work progress surface while preserving the later plan review and approval landings. * [Preserve runtime role-model authentication](preserve-runtime-role-model.md) - ⬜ pending · medium · Configured Iterator roles retain Pi’s active runtime model routing and correctly recognize modern void-returning model switches. diff --git a/memory/log.md b/memory/log.md index 3bfcef0..4cb282b 100644 --- a/memory/log.md +++ b/memory/log.md @@ -1,6 +1,7 @@ # iterator update log ## 2026-07-21 +* **Review**: Accepted [Activate Work when planning starts](/features/activate-work-on-plan-start.md) (committed as feature(activate-work-on-plan-start)). * **Implementation**: Committed feature(activate-work-on-plan-start) on branch iterator/safe-role-model-handoff; awaiting review. * **Backlog**: create after-initial-install-no-update-possible. * **Review**: Reviewed [Activate Work when planning starts](/features/activate-work-on-plan-start.md); changes (agent). diff --git a/memory/state.md b/memory/state.md index 37c4dd0..83e9882 100644 --- a/memory/state.md +++ b/memory/state.md @@ -4,11 +4,11 @@ title: Runtime state description: Machine-owned iterator flow state — never hand-edited. mode: auto paused: false -phase: implementing +phase: reviewing active_feature: activate-work-on-plan-start strikes: "{\"activate-work-on-plan-start\":1}" escalation: null -timestamp: 2026-07-21T14:02:58.519Z +timestamp: 2026-07-21T14:05:40.366Z --- Runtime flow state; read via gather, written only by the state op. diff --git a/memory/usage.md b/memory/usage.md index 55dbee0..7da0058 100644 --- a/memory/usage.md +++ b/memory/usage.md @@ -2,9 +2,9 @@ type: Usage title: Token usage description: Per-step model/token ledger and optional project-owned pricing for the active plan — written only by the usage op. -totals: "{\"steps\":{\"hub\":{\"openai-codex/gpt-5.6-terra\":{\"input\":4327,\"output\":565,\"cacheRead\":413184,\"cacheWrite\":0,\"turns\":7}},\"plan\":{\"openai-codex/gpt-5.6-sol\":{\"input\":173740,\"output\":9070,\"cacheRead\":3877888,\"cacheWrite\":0,\"turns\":35}},\"implement\":{\"openai-codex/gpt-5.6-terra\":{\"input\":170574,\"output\":1849,\"cacheRead\":1737728,\"cacheWrite\":0,\"turns\":12}},\"review\":{\"openai-codex/gpt-5.6-sol\":{\"input\":186110,\"output\":546,\"cacheRead\":852992,\"cacheWrite\":0,\"turns\":6}}},\"features\":{\"retire-plan\":{\"input\":4327,\"output\":565,\"cacheRead\":413184,\"cacheWrite\":0,\"turns\":7},\"activate-work-on-plan-start\":{\"input\":356684,\"output\":2395,\"cacheRead\":2590720,\"cacheWrite\":0,\"turns\":18}},\"featureModels\":{\"retire-plan\":{\"openai-codex/gpt-5.6-terra\":{\"input\":4327,\"output\":565,\"cacheRead\":413184,\"cacheWrite\":0,\"turns\":7}},\"activate-work-on-plan-start\":{\"openai-codex/gpt-5.6-terra\":{\"input\":170574,\"output\":1849,\"cacheRead\":1737728,\"cacheWrite\":0,\"turns\":12},\"openai-codex/gpt-5.6-sol\":{\"input\":186110,\"output\":546,\"cacheRead\":852992,\"cacheWrite\":0,\"turns\":6}}}}" +totals: "{\"steps\":{\"hub\":{\"openai-codex/gpt-5.6-terra\":{\"input\":4327,\"output\":565,\"cacheRead\":413184,\"cacheWrite\":0,\"turns\":7}},\"plan\":{\"openai-codex/gpt-5.6-sol\":{\"input\":173740,\"output\":9070,\"cacheRead\":3877888,\"cacheWrite\":0,\"turns\":35}},\"implement\":{\"openai-codex/gpt-5.6-terra\":{\"input\":170574,\"output\":1849,\"cacheRead\":1737728,\"cacheWrite\":0,\"turns\":12},\"openai-codex/gpt-5.6-sol\":{\"input\":30398,\"output\":3717,\"cacheRead\":2566144,\"cacheWrite\":0,\"turns\":14}},\"review\":{\"openai-codex/gpt-5.6-sol\":{\"input\":186110,\"output\":546,\"cacheRead\":852992,\"cacheWrite\":0,\"turns\":6}}},\"features\":{\"retire-plan\":{\"input\":4327,\"output\":565,\"cacheRead\":413184,\"cacheWrite\":0,\"turns\":7},\"activate-work-on-plan-start\":{\"input\":387082,\"output\":6112,\"cacheRead\":5156864,\"cacheWrite\":0,\"turns\":32}},\"featureModels\":{\"retire-plan\":{\"openai-codex/gpt-5.6-terra\":{\"input\":4327,\"output\":565,\"cacheRead\":413184,\"cacheWrite\":0,\"turns\":7}},\"activate-work-on-plan-start\":{\"openai-codex/gpt-5.6-terra\":{\"input\":170574,\"output\":1849,\"cacheRead\":1737728,\"cacheWrite\":0,\"turns\":12},\"openai-codex/gpt-5.6-sol\":{\"input\":216508,\"output\":4263,\"cacheRead\":3419136,\"cacheWrite\":0,\"turns\":20}}}}" prices: "{}" -timestamp: 2026-07-21T14:02:58.191Z +timestamp: 2026-07-21T14:05:40.094Z --- # Usage @@ -26,6 +26,7 @@ timestamp: 2026-07-21T14:02:58.191Z | model | input | output | cache read | cache write | turns | cost | | --- | ---: | ---: | ---: | ---: | ---: | ---: | | openai-codex/gpt-5.6-terra | 170574 | 1849 | 1737728 | 0 | 12 | — | +| openai-codex/gpt-5.6-sol | 30398 | 3717 | 2566144 | 0 | 14 | — | ## review @@ -38,6 +39,6 @@ timestamp: 2026-07-21T14:02:58.191Z | feature | input | output | cache read | cache write | turns | cost | | --- | ---: | ---: | ---: | ---: | ---: | ---: | | retire-plan | 4327 | 565 | 413184 | 0 | 7 | — | -| activate-work-on-plan-start | 356684 | 2395 | 2590720 | 0 | 18 | — | +| activate-work-on-plan-start | 387082 | 6112 | 5156864 | 0 | 32 | — | -Total: 534751 in / 12030 out / 6881792 cache-read / 0 cache-write over 60 turns. Cost unavailable: add every used model rate. +Total: 565149 in / 15747 out / 9447936 cache-read / 0 cache-write over 74 turns. Cost unavailable: add every used model rate. From dc8a42c454df3c803ddae9b2959cab01abaa004d Mon Sep 17 00:00:00 2001 From: Christoph Maier Date: Tue, 21 Jul 2026 16:10:28 +0200 Subject: [PATCH 09/12] feature(preserve-runtime-role-model): Preserve managed runtime model authentication Feature: preserve-runtime-role-model --- extensions/iterator.js | 32 +++++--- lib/pi-tools.mjs | 45 ++++++++++- .../features/activate-work-on-plan-start.md | 3 +- .../features/preserve-runtime-role-model.md | 4 +- memory/log.md | 2 + memory/state.md | 6 +- memory/usage.md | 10 +-- test/extension-model-lifecycle.test.mjs | 77 ++++++++++++++++++- test/pi-tools.test.mjs | 76 ++++++++++++++++++ 9 files changed, 227 insertions(+), 28 deletions(-) diff --git a/extensions/iterator.js b/extensions/iterator.js index b7956de..55722a5 100644 --- a/extensions/iterator.js +++ b/extensions/iterator.js @@ -65,12 +65,14 @@ import { implementationCommand, implementationHandoffState, mergePayload, + modelSwitchSucceeded, nextAutoAction, nextFeatureWaveAction, pauseFeatureWave, projectRoot, roleFromInput, roleModelSpec, + resolveRoleModel, runJson, shouldApplyRole, scriptPath, @@ -665,14 +667,23 @@ export default function iteratorExtension(pi) { let switchedModel = false; try { if (spec.model) { - const slash = spec.model.indexOf("/"); - const provider = spec.model.slice(0, slash); - const id = spec.model.slice(slash + 1); - const m = lastCtx?.modelRegistry?.find?.(provider, id); - if (m) { + const target = resolveRoleModel( + spec.model, + lastCtx?.model, + preAutoModel, + lastCtx?.modelRegistry, + ); + if (!target) { + notifyUi( + `unknown model ${spec.model} for ${role} — staying on the active model`, + "warning", + ); + } else if (target.switchRequired) { const previousModel = preAutoModel || lastCtx?.model || null; - const ok = await pi.setModel(m); - if (ok) { + const result = await pi.setModel(target.model); + // Modern Pi resolves void on success and throws on missing auth; + // retain explicit false support for older extension runtimes. + if (modelSwitchSucceeded(result)) { if (!preAutoModel) preAutoModel = previousModel; switchedModel = true; } else { @@ -681,12 +692,9 @@ export default function iteratorExtension(pi) { "warning", ); } - } else { - notifyUi( - `unknown model ${spec.model} for ${role} — staying on the active model`, - "warning", - ); } + // Otherwise the configured identity is already active. Keeping that + // exact object preserves Pi's host proxy routing and credentials. } if (spec.thinking) pi.setThinkingLevel(spec.thinking); } catch (e) { diff --git a/lib/pi-tools.mjs b/lib/pi-tools.mjs index 060ebeb..7b2efb4 100644 --- a/lib/pi-tools.mjs +++ b/lib/pi-tools.mjs @@ -485,10 +485,51 @@ export function nextAutoAction(sessionPayload, settings, state) { }; } +/** Parse the persisted provider/model identity without losing slashes in ids. */ +export function parseModelSpec(spec) { + const value = String(spec || ""); + const slash = value.indexOf("/"); + if (slash <= 0 || slash === value.length - 1) return null; + return { provider: value.slice(0, slash), id: value.slice(slash + 1) }; +} + +/** Whether a runtime model carries the persisted provider/model identity. */ +export function modelMatchesSpec(model, spec) { + const identity = parseModelSpec(spec); + return Boolean( + identity && + model?.provider === identity.provider && + model?.id === identity.id, + ); +} + +/** + * Resolve a configured role model without discarding host-owned runtime model + * metadata (proxy base URLs, managed credentials, headers). The active model + * wins, then the model saved for restoration, and only then the registry. + */ +export function resolveRoleModel(spec, activeModel, restoreModel, modelRegistry) { + const identity = parseModelSpec(spec); + if (!identity) return null; + if (modelMatchesSpec(activeModel, spec)) { + return { model: activeModel, switchRequired: false }; + } + if (modelMatchesSpec(restoreModel, spec)) { + return { model: restoreModel, switchRequired: true }; + } + const model = modelRegistry?.find?.(identity.provider, identity.id) || null; + return model ? { model, switchRequired: true } : null; +} + +/** Modern Pi resolves void on success; older runtimes may return a boolean. */ +export function modelSwitchSucceeded(result) { + return result !== false; +} + /** * The model/thinking overrides for a role turn: null fields mean "leave the - * session as-is" ('active'). The extension resolves the model string against - * ctx.modelRegistry and applies pi.setModel/pi.setThinkingLevel. + * session as-is" ('active'). The extension resolves the model string while + * preserving matching runtime model objects, then applies model/thinking. */ export function roleModelSpec(settings, role) { const model = settings?.[`${role}_model`]; diff --git a/memory/features/activate-work-on-plan-start.md b/memory/features/activate-work-on-plan-start.md index 85e4227..b3b4b23 100644 --- a/memory/features/activate-work-on-plan-start.md +++ b/memory/features/activate-work-on-plan-start.md @@ -7,7 +7,7 @@ size: small depends_on: [] files: ["extensions/iterator.js", "test/extension-work-activation.test.mjs"] memories: [architecture/package-and-skill-layout, decisions/auto-plan-review-terminal-reset, decisions/backlog-planning-and-feature-waves, decisions/code-exact-red-test-review-and-agent-wording, decisions/focus-feature-execution-and-dashboard-ownership, decisions/iterator-dashboard-feature-workflow, decisions/manual-role-models-and-runtime-reset, decisions/memory-relevance-usage-and-dashboard-recovery] -timestamp: "2026-07-21T14:05:59.326Z" +timestamp: "2026-07-21T14:06:04.307Z" tags: [] commits: - sha: eadb89bf9ca7fc3e753bb78d11cc2f4fb114971b @@ -44,4 +44,5 @@ Planning-to-Work navigation and visibility of the agent working overlay when pla # Review ## 2026-07-21 +* **Approved** _(agent review: openai-codex/gpt-5.6-sol)_ — Approved after rework: plan dispatch waits for intentional Work activation, reports refresh failures without swallowing the action, and behavioral tests prove dispatch occurs exactly once even when refresh or reporting fails. * **Needs changes** _(agent review: openai-codex/gpt-5.6-sol)_ — The new plan path chains dispatch only inside `refreshHub(...).then(...)`. If dashboard gathering/rendering rejects, the promise is unhandled and the requested plan never starts, whereas the prior generic path always dispatched. Wrap the activation in an async helper or catch/finally so refresh failure is reported but `showWorking`/`dispatch(cmd)` still occur exactly once; add a behavioral regression for the rejection path rather than only source-pattern assertions. diff --git a/memory/features/preserve-runtime-role-model.md b/memory/features/preserve-runtime-role-model.md index 408f239..feb225d 100644 --- a/memory/features/preserve-runtime-role-model.md +++ b/memory/features/preserve-runtime-role-model.md @@ -2,12 +2,12 @@ type: Feature title: Preserve runtime role-model authentication description: Configured Iterator roles retain Pi’s active runtime model routing and correctly recognize modern void-returning model switches. -status: pending +status: implemented size: medium depends_on: [] files: ["lib/pi-tools.mjs", "extensions/iterator.js", "test/pi-tools.test.mjs", "test/extension-model-lifecycle.test.mjs"] memories: [architecture/package-and-skill-layout, decisions/auto-plan-review-terminal-reset, decisions/backlog-planning-and-feature-waves, decisions/code-exact-red-test-review-and-agent-wording, decisions/focus-feature-execution-and-dashboard-ownership, decisions/iterator-dashboard-feature-workflow, decisions/manual-role-models-and-runtime-reset, decisions/memory-relevance-usage-and-dashboard-recovery] -timestamp: "2026-07-21T14:01:04.365Z" +timestamp: "2026-07-21T14:10:28.952Z" tags: [] --- diff --git a/memory/log.md b/memory/log.md index 4cb282b..acebe47 100644 --- a/memory/log.md +++ b/memory/log.md @@ -1,6 +1,8 @@ # iterator update log ## 2026-07-21 +* **Implementation**: Committed feature(preserve-runtime-role-model) on branch iterator/safe-role-model-handoff; awaiting review. +* **Review**: Reviewed [Activate Work when planning starts](/features/activate-work-on-plan-start.md); approved (agent). * **Review**: Accepted [Activate Work when planning starts](/features/activate-work-on-plan-start.md) (committed as feature(activate-work-on-plan-start)). * **Implementation**: Committed feature(activate-work-on-plan-start) on branch iterator/safe-role-model-handoff; awaiting review. * **Backlog**: create after-initial-install-no-update-possible. diff --git a/memory/state.md b/memory/state.md index 83e9882..c16200d 100644 --- a/memory/state.md +++ b/memory/state.md @@ -4,11 +4,11 @@ title: Runtime state description: Machine-owned iterator flow state — never hand-edited. mode: auto paused: false -phase: reviewing -active_feature: activate-work-on-plan-start +phase: implementing +active_feature: preserve-runtime-role-model strikes: "{\"activate-work-on-plan-start\":1}" escalation: null -timestamp: 2026-07-21T14:05:40.366Z +timestamp: 2026-07-21T14:06:10.169Z --- Runtime flow state; read via gather, written only by the state op. diff --git a/memory/usage.md b/memory/usage.md index 7da0058..f398b32 100644 --- a/memory/usage.md +++ b/memory/usage.md @@ -2,9 +2,9 @@ type: Usage title: Token usage description: Per-step model/token ledger and optional project-owned pricing for the active plan — written only by the usage op. -totals: "{\"steps\":{\"hub\":{\"openai-codex/gpt-5.6-terra\":{\"input\":4327,\"output\":565,\"cacheRead\":413184,\"cacheWrite\":0,\"turns\":7}},\"plan\":{\"openai-codex/gpt-5.6-sol\":{\"input\":173740,\"output\":9070,\"cacheRead\":3877888,\"cacheWrite\":0,\"turns\":35}},\"implement\":{\"openai-codex/gpt-5.6-terra\":{\"input\":170574,\"output\":1849,\"cacheRead\":1737728,\"cacheWrite\":0,\"turns\":12},\"openai-codex/gpt-5.6-sol\":{\"input\":30398,\"output\":3717,\"cacheRead\":2566144,\"cacheWrite\":0,\"turns\":14}},\"review\":{\"openai-codex/gpt-5.6-sol\":{\"input\":186110,\"output\":546,\"cacheRead\":852992,\"cacheWrite\":0,\"turns\":6}}},\"features\":{\"retire-plan\":{\"input\":4327,\"output\":565,\"cacheRead\":413184,\"cacheWrite\":0,\"turns\":7},\"activate-work-on-plan-start\":{\"input\":387082,\"output\":6112,\"cacheRead\":5156864,\"cacheWrite\":0,\"turns\":32}},\"featureModels\":{\"retire-plan\":{\"openai-codex/gpt-5.6-terra\":{\"input\":4327,\"output\":565,\"cacheRead\":413184,\"cacheWrite\":0,\"turns\":7}},\"activate-work-on-plan-start\":{\"openai-codex/gpt-5.6-terra\":{\"input\":170574,\"output\":1849,\"cacheRead\":1737728,\"cacheWrite\":0,\"turns\":12},\"openai-codex/gpt-5.6-sol\":{\"input\":216508,\"output\":4263,\"cacheRead\":3419136,\"cacheWrite\":0,\"turns\":20}}}}" +totals: "{\"steps\":{\"hub\":{\"openai-codex/gpt-5.6-terra\":{\"input\":4327,\"output\":565,\"cacheRead\":413184,\"cacheWrite\":0,\"turns\":7}},\"plan\":{\"openai-codex/gpt-5.6-sol\":{\"input\":173740,\"output\":9070,\"cacheRead\":3877888,\"cacheWrite\":0,\"turns\":35}},\"implement\":{\"openai-codex/gpt-5.6-terra\":{\"input\":170574,\"output\":1849,\"cacheRead\":1737728,\"cacheWrite\":0,\"turns\":12},\"openai-codex/gpt-5.6-sol\":{\"input\":30398,\"output\":3717,\"cacheRead\":2566144,\"cacheWrite\":0,\"turns\":14}},\"review\":{\"openai-codex/gpt-5.6-sol\":{\"input\":216799,\"output\":1072,\"cacheRead\":2205184,\"cacheWrite\":0,\"turns\":13}}},\"features\":{\"retire-plan\":{\"input\":4327,\"output\":565,\"cacheRead\":413184,\"cacheWrite\":0,\"turns\":7},\"activate-work-on-plan-start\":{\"input\":417771,\"output\":6638,\"cacheRead\":6509056,\"cacheWrite\":0,\"turns\":39}},\"featureModels\":{\"retire-plan\":{\"openai-codex/gpt-5.6-terra\":{\"input\":4327,\"output\":565,\"cacheRead\":413184,\"cacheWrite\":0,\"turns\":7}},\"activate-work-on-plan-start\":{\"openai-codex/gpt-5.6-terra\":{\"input\":170574,\"output\":1849,\"cacheRead\":1737728,\"cacheWrite\":0,\"turns\":12},\"openai-codex/gpt-5.6-sol\":{\"input\":247197,\"output\":4789,\"cacheRead\":4771328,\"cacheWrite\":0,\"turns\":27}}}}" prices: "{}" -timestamp: 2026-07-21T14:05:40.094Z +timestamp: 2026-07-21T14:06:09.898Z --- # Usage @@ -32,13 +32,13 @@ timestamp: 2026-07-21T14:05:40.094Z | model | input | output | cache read | cache write | turns | cost | | --- | ---: | ---: | ---: | ---: | ---: | ---: | -| openai-codex/gpt-5.6-sol | 186110 | 546 | 852992 | 0 | 6 | — | +| openai-codex/gpt-5.6-sol | 216799 | 1072 | 2205184 | 0 | 13 | — | ## Per feature | feature | input | output | cache read | cache write | turns | cost | | --- | ---: | ---: | ---: | ---: | ---: | ---: | | retire-plan | 4327 | 565 | 413184 | 0 | 7 | — | -| activate-work-on-plan-start | 387082 | 6112 | 5156864 | 0 | 32 | — | +| activate-work-on-plan-start | 417771 | 6638 | 6509056 | 0 | 39 | — | -Total: 565149 in / 15747 out / 9447936 cache-read / 0 cache-write over 74 turns. Cost unavailable: add every used model rate. +Total: 595838 in / 16273 out / 10800128 cache-read / 0 cache-write over 81 turns. Cost unavailable: add every used model rate. diff --git a/test/extension-model-lifecycle.test.mjs b/test/extension-model-lifecycle.test.mjs index 674f9c1..e10c411 100644 --- a/test/extension-model-lifecycle.test.mjs +++ b/test/extension-model-lifecycle.test.mjs @@ -21,6 +21,16 @@ test("dashboard dispatch identifies the active Agent", () => { assert.doesNotMatch(extension, /Dispatched \$\{cmd\} — Claude is working…/); }); +test("role switching accepts modern void success and preserves runtime matches", () => { + const extension = readFileSync( + new URL("../extensions/iterator.js", import.meta.url), + "utf8", + ); + assert.match(extension, /resolveRoleModel\(/); + assert.match(extension, /if \(modelSwitchSucceeded\(result\)\)/); + assert.match(extension, /else if \(target\.switchRequired\)/); +}); + test("agent plan review completion converges the auto dashboard immediately", () => { const extension = readFileSync( new URL("../extensions/iterator.js", import.meta.url), @@ -92,7 +102,12 @@ function mockPi() { setThinkingLevel() {}, async setModel(model) { setModels.push(model); - return model !== overrideModel || pi.overrideSucceeds; + if (model === overrideModel && pi.overrideError) { + throw new Error("model auth unavailable"); + } + if (model === overrideModel && pi.overrideReturnsFalse) return false; + // Current Pi resolves void on success. + return undefined; }, }; return { pi, handlers, setModels, currentModel, overrideModel }; @@ -116,6 +131,7 @@ test("failed tester override does not restore or alter the following active impl const root = fixture({ tester_model: "openai/override" }); try { const { pi, handlers, setModels, currentModel, overrideModel } = mockPi(); + pi.overrideReturnsFalse = true; await iteratorExtension(pi); const registry = { find: () => overrideModel }; @@ -137,13 +153,12 @@ test("failed tester override does not restore or alter the following active impl } }); -test("successful manual override restores once and a role input is consumed by one turn", { +test("void-returning manual override restores once and a role input is consumed by one turn", { skip: !extensionDependenciesAvailable, }, async () => { const root = fixture({ tester_model: "openai/override" }); try { const { pi, handlers, setModels, currentModel, overrideModel } = mockPi(); - pi.overrideSucceeds = true; await iteratorExtension(pi); const registry = { find: () => overrideModel }; @@ -160,6 +175,62 @@ test("successful manual override restores once and a role input is consumed by o } }); +test("configured active identity keeps the runtime proxy model object", { + skip: !extensionDependenciesAvailable, +}, async () => { + const root = fixture({ tester_model: "proxy/managed" }); + try { + const { pi, handlers, setModels, currentModel } = mockPi(); + await iteratorExtension(pi); + const registryModel = { + provider: "proxy", + id: "managed", + baseUrl: "https://direct-provider.invalid", + }; + + await handlers.get("input")({ + text: "/iterator-test preserve-runtime-role-model", + }); + await startTurn( + handlers, + root, + { find: () => registryModel }, + { ...currentModel, baseUrl: "https://managed-proxy.test" }, + ); + await handlers.get("agent_end")({}, { cwd: root, hasUI: false }); + + assert.deepEqual(setModels, []); + } finally { + rmSync(root, { recursive: true, force: true }); + } +}); + +test("thrown model switch failure never arms restoration", { + skip: !extensionDependenciesAvailable, +}, async () => { + const root = fixture({ tester_model: "openai/override" }); + try { + const { pi, handlers, setModels, currentModel, overrideModel } = mockPi(); + pi.overrideError = true; + await iteratorExtension(pi); + + await handlers.get("input")({ + text: "/iterator-test preserve-runtime-role-model", + }); + await startTurn( + handlers, + root, + { find: () => overrideModel }, + currentModel, + ); + await handlers.get("agent_end")({}, { cwd: root, hasUI: false }); + + assert.deepEqual(setModels, [overrideModel]); + } finally { + rmSync(root, { recursive: true, force: true }); + } +}); + test("active role settings never call setModel", { skip: !extensionDependenciesAvailable, }, async () => { diff --git a/test/pi-tools.test.mjs b/test/pi-tools.test.mjs index ca12722..415af74 100644 --- a/test/pi-tools.test.mjs +++ b/test/pi-tools.test.mjs @@ -15,6 +15,10 @@ import { extractPathsFromBash, footerText, mergePayload, + modelMatchesSpec, + modelSwitchSucceeded, + parseModelSpec, + resolveRoleModel, runJson, scriptPath, shouldNudge, @@ -793,6 +797,78 @@ test("nextAutoAction escalates on conflicts, prior strikes, drafts, and stuck gr assert.match(a.reason, /cycle or missing/); }); +test("runtime role model resolution preserves managed model objects", () => { + const active = { + provider: "openai-codex", + id: "gpt-5.6-sol", + baseUrl: "https://managed-proxy.test", + }; + const direct = { + provider: "openai-codex", + id: "gpt-5.6-sol", + baseUrl: "https://api.openai.com", + }; + let registryLookups = 0; + const target = resolveRoleModel( + "openai-codex/gpt-5.6-sol", + active, + null, + { + find() { + registryLookups += 1; + return direct; + }, + }, + ); + assert.equal(target.model, active); + assert.equal(target.switchRequired, false); + assert.equal(registryLookups, 0); +}); + +test("runtime role model resolution reuses the restoration model before registry lookup", () => { + const active = { provider: "anthropic", id: "claude-sonnet" }; + const restore = { + provider: "openai-codex", + id: "gpt-5.6-sol", + baseUrl: "https://managed-proxy.test", + }; + const target = resolveRoleModel( + "openai-codex/gpt-5.6-sol", + active, + restore, + { find: () => assert.fail("registry should not replace runtime model") }, + ); + assert.equal(target.model, restore); + assert.equal(target.switchRequired, true); +}); + +test("runtime role model resolution falls back to registry for another model", () => { + const registered = { provider: "anthropic", id: "claude-opus/4.8" }; + const registry = { + find(provider, id) { + assert.equal(provider, "anthropic"); + assert.equal(id, "claude-opus/4.8"); + return registered; + }, + }; + assert.deepEqual(parseModelSpec("anthropic/claude-opus/4.8"), { + provider: "anthropic", + id: "claude-opus/4.8", + }); + assert.equal(modelMatchesSpec(registered, "anthropic/claude-opus/4.8"), true); + assert.deepEqual( + resolveRoleModel("anthropic/claude-opus/4.8", null, null, registry), + { model: registered, switchRequired: true }, + ); + assert.equal(resolveRoleModel("malformed", null, null, registry), null); +}); + +test("model switch success accepts modern void and legacy true only", () => { + assert.equal(modelSwitchSucceeded(undefined), true); + assert.equal(modelSwitchSucceeded(true), true); + assert.equal(modelSwitchSucceeded(false), false); +}); + test("roleModelSpec resolves overrides and leaves active alone", () => { const settings = { reviewer_model: "anthropic/claude-opus-4-8", From 3f351eaae4abd69313e870c702a5e4cb65a25bbe Mon Sep 17 00:00:00 2001 From: Christoph Maier Date: Tue, 21 Jul 2026 16:10:29 +0200 Subject: [PATCH 10/12] chore(iterator): record feature commit --- memory/features/preserve-runtime-role-model.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/memory/features/preserve-runtime-role-model.md b/memory/features/preserve-runtime-role-model.md index feb225d..a627458 100644 --- a/memory/features/preserve-runtime-role-model.md +++ b/memory/features/preserve-runtime-role-model.md @@ -7,8 +7,12 @@ size: medium depends_on: [] files: ["lib/pi-tools.mjs", "extensions/iterator.js", "test/pi-tools.test.mjs", "test/extension-model-lifecycle.test.mjs"] memories: [architecture/package-and-skill-layout, decisions/auto-plan-review-terminal-reset, decisions/backlog-planning-and-feature-waves, decisions/code-exact-red-test-review-and-agent-wording, decisions/focus-feature-execution-and-dashboard-ownership, decisions/iterator-dashboard-feature-workflow, decisions/manual-role-models-and-runtime-reset, decisions/memory-relevance-usage-and-dashboard-recovery] -timestamp: "2026-07-21T14:10:28.952Z" +timestamp: "2026-07-21T14:10:29.023Z" tags: [] +commits: + - sha: dc8a42c454df3c803ddae9b2959cab01abaa004d + kind: implement + date: 2026-07-21 --- # Implementation notes From 3ef140d22f80e7029621f933750d2f64de4be320 Mon Sep 17 00:00:00 2001 From: Christoph Maier Date: Tue, 21 Jul 2026 16:11:21 +0200 Subject: [PATCH 11/12] chore(iterator): record feature commits and memory updates --- memory/features/index.md | 2 +- memory/features/preserve-runtime-role-model.md | 5 +++-- memory/log.md | 1 + memory/state.md | 4 ++-- memory/usage.md | 9 +++++---- 5 files changed, 12 insertions(+), 9 deletions(-) diff --git a/memory/features/index.md b/memory/features/index.md index 09b175a..2f38e97 100644 --- a/memory/features/index.md +++ b/memory/features/index.md @@ -1,4 +1,4 @@ # Features * [Activate Work when planning starts](activate-work-on-plan-start.md) - ✅ done · small · Starting a plan from Planning immediately opens the Work progress surface while preserving the later plan review and approval landings. -* [Preserve runtime role-model authentication](preserve-runtime-role-model.md) - ⬜ pending · medium · Configured Iterator roles retain Pi’s active runtime model routing and correctly recognize modern void-returning model switches. +* [Preserve runtime role-model authentication](preserve-runtime-role-model.md) - ✅ done · medium · Configured Iterator roles retain Pi’s active runtime model routing and correctly recognize modern void-returning model switches. diff --git a/memory/features/preserve-runtime-role-model.md b/memory/features/preserve-runtime-role-model.md index a627458..c585e2f 100644 --- a/memory/features/preserve-runtime-role-model.md +++ b/memory/features/preserve-runtime-role-model.md @@ -2,17 +2,18 @@ type: Feature title: Preserve runtime role-model authentication description: Configured Iterator roles retain Pi’s active runtime model routing and correctly recognize modern void-returning model switches. -status: implemented +status: done size: medium depends_on: [] files: ["lib/pi-tools.mjs", "extensions/iterator.js", "test/pi-tools.test.mjs", "test/extension-model-lifecycle.test.mjs"] memories: [architecture/package-and-skill-layout, decisions/auto-plan-review-terminal-reset, decisions/backlog-planning-and-feature-waves, decisions/code-exact-red-test-review-and-agent-wording, decisions/focus-feature-execution-and-dashboard-ownership, decisions/iterator-dashboard-feature-workflow, decisions/manual-role-models-and-runtime-reset, decisions/memory-relevance-usage-and-dashboard-recovery] -timestamp: "2026-07-21T14:10:29.023Z" +timestamp: "2026-07-21T14:11:21.481Z" tags: [] commits: - sha: dc8a42c454df3c803ddae9b2959cab01abaa004d kind: implement date: 2026-07-21 +done: 2026-07-21 --- # Implementation notes diff --git a/memory/log.md b/memory/log.md index acebe47..871ffba 100644 --- a/memory/log.md +++ b/memory/log.md @@ -1,6 +1,7 @@ # iterator update log ## 2026-07-21 +* **Review**: Accepted [Preserve runtime role-model authentication](/features/preserve-runtime-role-model.md) (committed as feature(preserve-runtime-role-model)). * **Implementation**: Committed feature(preserve-runtime-role-model) on branch iterator/safe-role-model-handoff; awaiting review. * **Review**: Reviewed [Activate Work when planning starts](/features/activate-work-on-plan-start.md); approved (agent). * **Review**: Accepted [Activate Work when planning starts](/features/activate-work-on-plan-start.md) (committed as feature(activate-work-on-plan-start)). diff --git a/memory/state.md b/memory/state.md index c16200d..72a7a7a 100644 --- a/memory/state.md +++ b/memory/state.md @@ -4,11 +4,11 @@ title: Runtime state description: Machine-owned iterator flow state — never hand-edited. mode: auto paused: false -phase: implementing +phase: reviewing active_feature: preserve-runtime-role-model strikes: "{\"activate-work-on-plan-start\":1}" escalation: null -timestamp: 2026-07-21T14:06:10.169Z +timestamp: 2026-07-21T14:10:50.748Z --- Runtime flow state; read via gather, written only by the state op. diff --git a/memory/usage.md b/memory/usage.md index f398b32..8ce44ad 100644 --- a/memory/usage.md +++ b/memory/usage.md @@ -2,9 +2,9 @@ type: Usage title: Token usage description: Per-step model/token ledger and optional project-owned pricing for the active plan — written only by the usage op. -totals: "{\"steps\":{\"hub\":{\"openai-codex/gpt-5.6-terra\":{\"input\":4327,\"output\":565,\"cacheRead\":413184,\"cacheWrite\":0,\"turns\":7}},\"plan\":{\"openai-codex/gpt-5.6-sol\":{\"input\":173740,\"output\":9070,\"cacheRead\":3877888,\"cacheWrite\":0,\"turns\":35}},\"implement\":{\"openai-codex/gpt-5.6-terra\":{\"input\":170574,\"output\":1849,\"cacheRead\":1737728,\"cacheWrite\":0,\"turns\":12},\"openai-codex/gpt-5.6-sol\":{\"input\":30398,\"output\":3717,\"cacheRead\":2566144,\"cacheWrite\":0,\"turns\":14}},\"review\":{\"openai-codex/gpt-5.6-sol\":{\"input\":216799,\"output\":1072,\"cacheRead\":2205184,\"cacheWrite\":0,\"turns\":13}}},\"features\":{\"retire-plan\":{\"input\":4327,\"output\":565,\"cacheRead\":413184,\"cacheWrite\":0,\"turns\":7},\"activate-work-on-plan-start\":{\"input\":417771,\"output\":6638,\"cacheRead\":6509056,\"cacheWrite\":0,\"turns\":39}},\"featureModels\":{\"retire-plan\":{\"openai-codex/gpt-5.6-terra\":{\"input\":4327,\"output\":565,\"cacheRead\":413184,\"cacheWrite\":0,\"turns\":7}},\"activate-work-on-plan-start\":{\"openai-codex/gpt-5.6-terra\":{\"input\":170574,\"output\":1849,\"cacheRead\":1737728,\"cacheWrite\":0,\"turns\":12},\"openai-codex/gpt-5.6-sol\":{\"input\":247197,\"output\":4789,\"cacheRead\":4771328,\"cacheWrite\":0,\"turns\":27}}}}" +totals: "{\"steps\":{\"hub\":{\"openai-codex/gpt-5.6-terra\":{\"input\":4327,\"output\":565,\"cacheRead\":413184,\"cacheWrite\":0,\"turns\":7}},\"plan\":{\"openai-codex/gpt-5.6-sol\":{\"input\":173740,\"output\":9070,\"cacheRead\":3877888,\"cacheWrite\":0,\"turns\":35}},\"implement\":{\"openai-codex/gpt-5.6-terra\":{\"input\":170574,\"output\":1849,\"cacheRead\":1737728,\"cacheWrite\":0,\"turns\":12},\"openai-codex/gpt-5.6-sol\":{\"input\":488447,\"output\":11892,\"cacheRead\":7139840,\"cacheWrite\":0,\"turns\":37}},\"review\":{\"openai-codex/gpt-5.6-sol\":{\"input\":216799,\"output\":1072,\"cacheRead\":2205184,\"cacheWrite\":0,\"turns\":13}}},\"features\":{\"retire-plan\":{\"input\":4327,\"output\":565,\"cacheRead\":413184,\"cacheWrite\":0,\"turns\":7},\"activate-work-on-plan-start\":{\"input\":417771,\"output\":6638,\"cacheRead\":6509056,\"cacheWrite\":0,\"turns\":39},\"preserve-runtime-role-model\":{\"input\":458049,\"output\":8175,\"cacheRead\":4573696,\"cacheWrite\":0,\"turns\":23}},\"featureModels\":{\"retire-plan\":{\"openai-codex/gpt-5.6-terra\":{\"input\":4327,\"output\":565,\"cacheRead\":413184,\"cacheWrite\":0,\"turns\":7}},\"activate-work-on-plan-start\":{\"openai-codex/gpt-5.6-terra\":{\"input\":170574,\"output\":1849,\"cacheRead\":1737728,\"cacheWrite\":0,\"turns\":12},\"openai-codex/gpt-5.6-sol\":{\"input\":247197,\"output\":4789,\"cacheRead\":4771328,\"cacheWrite\":0,\"turns\":27}},\"preserve-runtime-role-model\":{\"openai-codex/gpt-5.6-sol\":{\"input\":458049,\"output\":8175,\"cacheRead\":4573696,\"cacheWrite\":0,\"turns\":23}}}}" prices: "{}" -timestamp: 2026-07-21T14:06:09.898Z +timestamp: 2026-07-21T14:10:50.474Z --- # Usage @@ -26,7 +26,7 @@ timestamp: 2026-07-21T14:06:09.898Z | model | input | output | cache read | cache write | turns | cost | | --- | ---: | ---: | ---: | ---: | ---: | ---: | | openai-codex/gpt-5.6-terra | 170574 | 1849 | 1737728 | 0 | 12 | — | -| openai-codex/gpt-5.6-sol | 30398 | 3717 | 2566144 | 0 | 14 | — | +| openai-codex/gpt-5.6-sol | 488447 | 11892 | 7139840 | 0 | 37 | — | ## review @@ -40,5 +40,6 @@ timestamp: 2026-07-21T14:06:09.898Z | --- | ---: | ---: | ---: | ---: | ---: | ---: | | retire-plan | 4327 | 565 | 413184 | 0 | 7 | — | | activate-work-on-plan-start | 417771 | 6638 | 6509056 | 0 | 39 | — | +| preserve-runtime-role-model | 458049 | 8175 | 4573696 | 0 | 23 | — | -Total: 595838 in / 16273 out / 10800128 cache-read / 0 cache-write over 81 turns. Cost unavailable: add every used model rate. +Total: 1053887 in / 24448 out / 15373824 cache-read / 0 cache-write over 104 turns. Cost unavailable: add every used model rate. From 166a204a476eea13154b1b1877231ae5c50a0ed9 Mon Sep 17 00:00:00 2001 From: Christoph Maier Date: Tue, 21 Jul 2026 16:32:19 +0200 Subject: [PATCH 12/12] fixed model loading --- lib/pi-tools.mjs | 7 +++++- .../features/preserve-runtime-role-model.md | 8 ++++++- memory/log.md | 2 ++ memory/plan.md | 16 ++++++++++++- memory/state.md | 10 ++++---- memory/usage.md | 11 +++++---- test/extension-work-activation.test.mjs | 6 +---- test/pi-tools.test.mjs | 24 +++++++------------ 8 files changed, 50 insertions(+), 34 deletions(-) diff --git a/lib/pi-tools.mjs b/lib/pi-tools.mjs index 7b2efb4..eaa7b6a 100644 --- a/lib/pi-tools.mjs +++ b/lib/pi-tools.mjs @@ -508,7 +508,12 @@ export function modelMatchesSpec(model, spec) { * metadata (proxy base URLs, managed credentials, headers). The active model * wins, then the model saved for restoration, and only then the registry. */ -export function resolveRoleModel(spec, activeModel, restoreModel, modelRegistry) { +export function resolveRoleModel( + spec, + activeModel, + restoreModel, + modelRegistry, +) { const identity = parseModelSpec(spec); if (!identity) return null; if (modelMatchesSpec(activeModel, spec)) { diff --git a/memory/features/preserve-runtime-role-model.md b/memory/features/preserve-runtime-role-model.md index c585e2f..f8cff17 100644 --- a/memory/features/preserve-runtime-role-model.md +++ b/memory/features/preserve-runtime-role-model.md @@ -7,13 +7,14 @@ size: medium depends_on: [] files: ["lib/pi-tools.mjs", "extensions/iterator.js", "test/pi-tools.test.mjs", "test/extension-model-lifecycle.test.mjs"] memories: [architecture/package-and-skill-layout, decisions/auto-plan-review-terminal-reset, decisions/backlog-planning-and-feature-waves, decisions/code-exact-red-test-review-and-agent-wording, decisions/focus-feature-execution-and-dashboard-ownership, decisions/iterator-dashboard-feature-workflow, decisions/manual-role-models-and-runtime-reset, decisions/memory-relevance-usage-and-dashboard-recovery] -timestamp: "2026-07-21T14:11:21.481Z" +timestamp: "2026-07-21T14:11:25.612Z" tags: [] commits: - sha: dc8a42c454df3c803ddae9b2959cab01abaa004d kind: implement date: 2026-07-21 done: 2026-07-21 +reviewed: 2026-07-21 --- # Implementation notes @@ -40,3 +41,8 @@ export function roleModelSpec(settings, role) { # Blast radius Manual role turns, automatic role handoffs, model restoration, and Settings-selected planner/tester/implementer/reviewer models. + +# Review + +## 2026-07-21 +* **Approved** _(agent review: openai-codex/gpt-5.6-sol)_ — Approved: role resolution now preserves active or restorable runtime model objects before registry fallback, avoids redundant proxy-breaking switches, treats void `setModel` resolution as success, and retains explicit-false/throw failure isolation with focused regressions. diff --git a/memory/log.md b/memory/log.md index 871ffba..b87fc9d 100644 --- a/memory/log.md +++ b/memory/log.md @@ -1,6 +1,8 @@ # iterator update log ## 2026-07-21 +* **Plan review**: Whole-plan review recorded (agent). +* **Review**: Reviewed [Preserve runtime role-model authentication](/features/preserve-runtime-role-model.md); approved (agent). * **Review**: Accepted [Preserve runtime role-model authentication](/features/preserve-runtime-role-model.md) (committed as feature(preserve-runtime-role-model)). * **Implementation**: Committed feature(preserve-runtime-role-model) on branch iterator/safe-role-model-handoff; awaiting review. * **Review**: Reviewed [Activate Work when planning starts](/features/activate-work-on-plan-start.md); approved (agent). diff --git a/memory/plan.md b/memory/plan.md index a960869..28713c6 100644 --- a/memory/plan.md +++ b/memory/plan.md @@ -5,7 +5,8 @@ description: Move active plan creation to Work immediately and preserve Pi runti status: approved branch: iterator/safe-role-model-handoff created: 2026-07-21 -timestamp: 2026-07-21T13:59:28.635Z +timestamp: "2026-07-21T14:12:11.619Z" +plan_reviewed: 2026-07-21 --- # Goal @@ -36,3 +37,16 @@ Make Iterator plan creation visibly move from Planning to the Work progress surf * [Activate Work when planning starts](/features/activate-work-on-plan-start.md) - Starting a plan from Planning immediately opens the Work progress surface while preserving the later plan review and approval landings. * [Preserve runtime role-model authentication](/features/preserve-runtime-role-model.md) - Configured Iterator roles retain Pi’s active runtime model routing and correctly recognize modern void-returning model switches. + +# Plan review + +## 2026-07-21 _(agent review: openai-codex/gpt-5.6-sol)_ + +## Clean bill + +- **Goal coverage:** `eadb89b` and `37a06f5` intentionally activate Work before plan dispatch and preserve the requested action through refresh/reporting failures. `dc8a42c` prevents an exact configured provider/id from replacing Pi’s active or restorable runtime model object with a direct registry object. +- **Architecture and key decisions:** Dashboard activation remains an explicit extension-owned landing; ordinary refresh behavior and later plan-review/approval navigation are unchanged. Model identity/resolution is pure in `lib/pi-tools.mjs`, modern void `setModel()` success and legacy failure behavior are explicit, and no credential sentinel, provider probe, workflow status, setting, dependency, or visual redesign was introduced. +- **Verification:** Focused behavioral tests cover refresh rejection, runtime model preservation, restoration-object reuse, registry fallback, void/boolean switch results, and thrown failures. The synchronized full suite passed with 400 tests and 6 environment-dependent skips. +- **Scope and loose ends:** All two features are accepted as done; the three feature commits contain only the planned extension, helper, and regression-test changes, with no introduced TODO markers or unexplained scope drift. + +The completed work matches the approved plan with no findings. diff --git a/memory/state.md b/memory/state.md index 72a7a7a..ecb38f4 100644 --- a/memory/state.md +++ b/memory/state.md @@ -2,13 +2,13 @@ type: State title: Runtime state description: Machine-owned iterator flow state — never hand-edited. -mode: auto +mode: manual paused: false -phase: reviewing -active_feature: preserve-runtime-role-model -strikes: "{\"activate-work-on-plan-start\":1}" +phase: done +active_feature: null +strikes: "{}" escalation: null -timestamp: 2026-07-21T14:10:50.748Z +timestamp: 2026-07-21T14:12:11.624Z --- Runtime flow state; read via gather, written only by the state op. diff --git a/memory/usage.md b/memory/usage.md index 8ce44ad..8b81cba 100644 --- a/memory/usage.md +++ b/memory/usage.md @@ -2,9 +2,9 @@ type: Usage title: Token usage description: Per-step model/token ledger and optional project-owned pricing for the active plan — written only by the usage op. -totals: "{\"steps\":{\"hub\":{\"openai-codex/gpt-5.6-terra\":{\"input\":4327,\"output\":565,\"cacheRead\":413184,\"cacheWrite\":0,\"turns\":7}},\"plan\":{\"openai-codex/gpt-5.6-sol\":{\"input\":173740,\"output\":9070,\"cacheRead\":3877888,\"cacheWrite\":0,\"turns\":35}},\"implement\":{\"openai-codex/gpt-5.6-terra\":{\"input\":170574,\"output\":1849,\"cacheRead\":1737728,\"cacheWrite\":0,\"turns\":12},\"openai-codex/gpt-5.6-sol\":{\"input\":488447,\"output\":11892,\"cacheRead\":7139840,\"cacheWrite\":0,\"turns\":37}},\"review\":{\"openai-codex/gpt-5.6-sol\":{\"input\":216799,\"output\":1072,\"cacheRead\":2205184,\"cacheWrite\":0,\"turns\":13}}},\"features\":{\"retire-plan\":{\"input\":4327,\"output\":565,\"cacheRead\":413184,\"cacheWrite\":0,\"turns\":7},\"activate-work-on-plan-start\":{\"input\":417771,\"output\":6638,\"cacheRead\":6509056,\"cacheWrite\":0,\"turns\":39},\"preserve-runtime-role-model\":{\"input\":458049,\"output\":8175,\"cacheRead\":4573696,\"cacheWrite\":0,\"turns\":23}},\"featureModels\":{\"retire-plan\":{\"openai-codex/gpt-5.6-terra\":{\"input\":4327,\"output\":565,\"cacheRead\":413184,\"cacheWrite\":0,\"turns\":7}},\"activate-work-on-plan-start\":{\"openai-codex/gpt-5.6-terra\":{\"input\":170574,\"output\":1849,\"cacheRead\":1737728,\"cacheWrite\":0,\"turns\":12},\"openai-codex/gpt-5.6-sol\":{\"input\":247197,\"output\":4789,\"cacheRead\":4771328,\"cacheWrite\":0,\"turns\":27}},\"preserve-runtime-role-model\":{\"openai-codex/gpt-5.6-sol\":{\"input\":458049,\"output\":8175,\"cacheRead\":4573696,\"cacheWrite\":0,\"turns\":23}}}}" +totals: "{\"steps\":{\"hub\":{\"openai-codex/gpt-5.6-terra\":{\"input\":4327,\"output\":565,\"cacheRead\":413184,\"cacheWrite\":0,\"turns\":7}},\"plan\":{\"openai-codex/gpt-5.6-sol\":{\"input\":173740,\"output\":9070,\"cacheRead\":3877888,\"cacheWrite\":0,\"turns\":35}},\"implement\":{\"openai-codex/gpt-5.6-terra\":{\"input\":170574,\"output\":1849,\"cacheRead\":1737728,\"cacheWrite\":0,\"turns\":12},\"openai-codex/gpt-5.6-sol\":{\"input\":488447,\"output\":11892,\"cacheRead\":7139840,\"cacheWrite\":0,\"turns\":37}},\"review\":{\"openai-codex/gpt-5.6-sol\":{\"input\":681248,\"output\":3134,\"cacheRead\":4352000,\"cacheWrite\":0,\"turns\":24},\"openai-codex/gpt-5.6-terra\":{\"input\":237542,\"output\":49,\"cacheRead\":236544,\"cacheWrite\":0,\"turns\":2}}},\"features\":{\"retire-plan\":{\"input\":4327,\"output\":565,\"cacheRead\":413184,\"cacheWrite\":0,\"turns\":7},\"activate-work-on-plan-start\":{\"input\":417771,\"output\":6638,\"cacheRead\":6509056,\"cacheWrite\":0,\"turns\":39},\"preserve-runtime-role-model\":{\"input\":912341,\"output\":8904,\"cacheRead\":5768192,\"cacheWrite\":0,\"turns\":30}},\"featureModels\":{\"retire-plan\":{\"openai-codex/gpt-5.6-terra\":{\"input\":4327,\"output\":565,\"cacheRead\":413184,\"cacheWrite\":0,\"turns\":7}},\"activate-work-on-plan-start\":{\"openai-codex/gpt-5.6-terra\":{\"input\":170574,\"output\":1849,\"cacheRead\":1737728,\"cacheWrite\":0,\"turns\":12},\"openai-codex/gpt-5.6-sol\":{\"input\":247197,\"output\":4789,\"cacheRead\":4771328,\"cacheWrite\":0,\"turns\":27}},\"preserve-runtime-role-model\":{\"openai-codex/gpt-5.6-sol\":{\"input\":912341,\"output\":8904,\"cacheRead\":5768192,\"cacheWrite\":0,\"turns\":30}}}}" prices: "{}" -timestamp: 2026-07-21T14:10:50.474Z +timestamp: 2026-07-21T14:12:19.535Z --- # Usage @@ -32,7 +32,8 @@ timestamp: 2026-07-21T14:10:50.474Z | model | input | output | cache read | cache write | turns | cost | | --- | ---: | ---: | ---: | ---: | ---: | ---: | -| openai-codex/gpt-5.6-sol | 216799 | 1072 | 2205184 | 0 | 13 | — | +| openai-codex/gpt-5.6-sol | 681248 | 3134 | 4352000 | 0 | 24 | — | +| openai-codex/gpt-5.6-terra | 237542 | 49 | 236544 | 0 | 2 | — | ## Per feature @@ -40,6 +41,6 @@ timestamp: 2026-07-21T14:10:50.474Z | --- | ---: | ---: | ---: | ---: | ---: | ---: | | retire-plan | 4327 | 565 | 413184 | 0 | 7 | — | | activate-work-on-plan-start | 417771 | 6638 | 6509056 | 0 | 39 | — | -| preserve-runtime-role-model | 458049 | 8175 | 4573696 | 0 | 23 | — | +| preserve-runtime-role-model | 912341 | 8904 | 5768192 | 0 | 30 | — | -Total: 1053887 in / 24448 out / 15373824 cache-read / 0 cache-write over 104 turns. Cost unavailable: add every used model rate. +Total: 1755878 in / 26559 out / 17757184 cache-read / 0 cache-write over 117 turns. Cost unavailable: add every used model rate. diff --git a/test/extension-work-activation.test.mjs b/test/extension-work-activation.test.mjs index dc37be4..3d29e58 100644 --- a/test/extension-work-activation.test.mjs +++ b/test/extension-work-activation.test.mjs @@ -54,11 +54,7 @@ test("plan dispatch survives a failed Work refresh exactly once", async () => { () => calls.push("dispatch"), (error) => calls.push(`warning: ${error.message}`), ); - assert.deepEqual(calls, [ - "refresh", - "warning: gather failed", - "dispatch", - ]); + assert.deepEqual(calls, ["refresh", "warning: gather failed", "dispatch"]); }); test("plan dispatch survives a broken refresh reporter", async () => { diff --git a/test/pi-tools.test.mjs b/test/pi-tools.test.mjs index 415af74..f7823e0 100644 --- a/test/pi-tools.test.mjs +++ b/test/pi-tools.test.mjs @@ -809,17 +809,12 @@ test("runtime role model resolution preserves managed model objects", () => { baseUrl: "https://api.openai.com", }; let registryLookups = 0; - const target = resolveRoleModel( - "openai-codex/gpt-5.6-sol", - active, - null, - { - find() { - registryLookups += 1; - return direct; - }, + const target = resolveRoleModel("openai-codex/gpt-5.6-sol", active, null, { + find() { + registryLookups += 1; + return direct; }, - ); + }); assert.equal(target.model, active); assert.equal(target.switchRequired, false); assert.equal(registryLookups, 0); @@ -832,12 +827,9 @@ test("runtime role model resolution reuses the restoration model before registry id: "gpt-5.6-sol", baseUrl: "https://managed-proxy.test", }; - const target = resolveRoleModel( - "openai-codex/gpt-5.6-sol", - active, - restore, - { find: () => assert.fail("registry should not replace runtime model") }, - ); + const target = resolveRoleModel("openai-codex/gpt-5.6-sol", active, restore, { + find: () => assert.fail("registry should not replace runtime model"), + }); assert.equal(target.model, restore); assert.equal(target.switchRequired, true); });