Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
fcc0395
feat: add versioned strategic plans
EvanProgramming Oct 16, 2026
befb08c
fix: address strategic plan review findings
EvanProgramming Oct 16, 2026
42d6e59
docs: plan strategic revision approvals
EvanProgramming Oct 16, 2026
b51e602
fix: require approval for material strategic revisions
EvanProgramming Oct 16, 2026
73173fe
fix: preserve strategic work across revisions
EvanProgramming Oct 16, 2026
b810d1d
fix: address strategic plan review findings
EvanProgramming Oct 16, 2026
c47a006
test: align strategic acceptance fixture with bounds
EvanProgramming Oct 16, 2026
f5a9a68
fix: normalize scoped structured mutation arguments
EvanProgramming Oct 16, 2026
3ccb6c7
test: correct strategic workflow task sequence
EvanProgramming Oct 16, 2026
178c0bf
test: verify strategic edits before task completion
EvanProgramming Oct 16, 2026
de1f6d1
fix: preserve legacy receipt matching and operation identity
EvanProgramming Oct 16, 2026
72142a4
fix: bind delegated writes to approved strategic contracts
EvanProgramming Oct 17, 2026
50a24cb
fix: verify strategic read criteria against file contents
EvanProgramming Oct 17, 2026
b8bc73f
test: add predicates to strategic workflow acceptance
EvanProgramming Oct 17, 2026
1ba8bb8
fix: keep plan guidance within compact prompt budget
EvanProgramming Oct 17, 2026
690fd18
fix: close strategic plan review gaps
EvanProgramming Oct 17, 2026
ea5a9ac
fix: synchronize strategic reapproval with latest base
EvanProgramming Oct 17, 2026
07d5e4e
docs: record final strategic reapproval validation
EvanProgramming Oct 17, 2026
581ec7e
fix: close strategic reapproval review findings
EvanProgramming Oct 17, 2026
9de73cd
docs: record strategic reapproval review validation
EvanProgramming Oct 17, 2026
e9e5c68
fix: close strategic plan review gaps
EvanProgramming Oct 17, 2026
0a733a4
fix: reject stale strategic plan completion
EvanProgramming Oct 17, 2026
0f165dc
merge: incorporate strategic plan review fixes
EvanProgramming Oct 17, 2026
4b28dae
docs: record strategic plan review follow-up
EvanProgramming Oct 17, 2026
b4dc345
docs: record plan reapproval review follow-up
EvanProgramming Oct 17, 2026
2277ae7
Merge branch 'Evan/v3-245-strategic-plans' of https://github.com/Evan…
EvanProgramming Oct 17, 2026
a0648c6
docs: record baseline provider timeout result
EvanProgramming Oct 17, 2026
fce2694
docs: record final plan review validation
EvanProgramming Oct 17, 2026
34e3b34
Merge branch 'Evan/v3-245-strategic-plans' of https://github.com/Evan…
EvanProgramming Oct 17, 2026
68f611b
Merge remote-tracking branch 'origin/main' into Evan/v3-246-plan-reap…
EvanProgramming Oct 17, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ This index covers the current product guides, developer references, and dated en
- [V3 SQLite migration plan](superpowers/plans/2026-10-14-v3-issue-264.md) records ordered schema migrations, backups, persisted approval history, and verification for issue #264.
- [V3 Working Plan contract](superpowers/plans/2026-10-14-v3-issue-241.md) records plan ownership, complexity policy, lifecycle, persistence, and verification for issue #241.
- [V3 atomic Working Plan edits](superpowers/plans/2026-10-16-v3-issue-242.md) records revision-checked operations, atomic persistence, ordering, dependencies, and validation for issue #242.
- [V3 Strategic Plan contract](superpowers/plans/2026-10-16-v3-issue-245.md) records approval versions, execution bounds, task links, and acceptance evidence for issue #245.
- [V3 Strategic Plan reapproval](superpowers/plans/2026-10-16-v3-issue-246.md) records revision materiality, pending-mutation pause, and atomic reapproval for issue #246.
- [V3 plan index](superpowers/plans/index.md) links the issue-specific implementation plans and identifies their coverage.
- [V3 execution receipt implementation plan](superpowers/plans/2026-10-14-v3-issue-236.md) records receipt identity, explicit task binding, structured effect verification, compatibility, and validation for issue #236.
- [V3 runtime events implementation plan](superpowers/plans/2026-10-14-v3-issue-255.md) records the canonical event contract, correlation, interface adapters, and validation for issue #255.
Expand Down
167 changes: 167 additions & 0 deletions docs/superpowers/plans/2026-10-16-v3-issue-245.md

Large diffs are not rendered by default.

67 changes: 67 additions & 0 deletions docs/superpowers/plans/2026-10-16-v3-issue-246.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# V3 Issue #246 — Material Strategic Plan revisions

**Issue:** [#246 — Require reapproval for material Strategic Plan revisions](https://github.com/EvanProgramming/OpenKyrozen/issues/246)
**Requirements:** R074–R076, R078
**Branch:** `Evan/v3-246-plan-reapproval`, stacked on the current #245 branch
**Delivery:** one GPG-signed PR stacked on #245; leave both unmerged and #246 open.

## Goal and boundaries

Allow Working Plan replanning only within the currently accepted Strategic Plan. Investigation, verification, ordering, dependencies, and task decomposition that preserve approved objectives, acceptance criteria, workspace, effects, capabilities, and risk may proceed automatically. Objective/acceptance changes, expanded authority or scope, increased risk, and unprovable effects require a new user-approved Strategic Plan version.

Keep the accepted version authoritative while a material proposal is pending. Do not dispatch further mutations under an unresolved proposal. Approval authorizes only the revised strategic bounds; it does not grant capabilities, approve tools, or replay prior work. Preserve existing tool approval and evidence gates.

## Indexed implementation plan

### Task 1 — Deterministic materiality policy

- [x] Add regressions for accepted-plan bounds, path normalization, materiality, and invalid risk-ceiling values.
- [x] Compare proposed strategy against the persisted accepted fingerprint and bounds; require approval for material expansion or uncertain scope.
- [x] Keep model/Jev advice out of the authoritative policy path.

### Task 2 — Stage and correlate material proposals

- [x] Stage material changes as versioned proposals while retaining the accepted plan and current tasks.
- [x] Pause state-changing actions while a material proposal is pending; keep cancellation available.
- [x] Bind acceptance to plan ID, version, fingerprint, and expected Working Plan revision.
- [x] Reject stale approvals and keep duplicate acceptance idempotent.

### Task 3 — Recheck and apply atomically

- [x] Recheck proposal fingerprint and plan revision before acceptance; transaction guards reject concurrent changes.
- [x] Apply the accepted version, linked Working Plan updates, and approval event in the existing transaction.
- [x] Reuse succeeded task work only when its objective, acceptance, execution contract, and evidence still match; preserve prior evidence.

### Task 4 — Shared runtime boundaries and delivery

- [x] Enforce the mutation pause and accepted-plan bounds at shared runtime and delegated execution boundaries.
- [x] Run focused tests on Python 3.12, `make check`, `make lint`, `make docs-check`, Go TUI tests, fixture subagent acceptance, and TUI acceptance.
- [x] Reproduce and resolve prior Codex findings; resolve review threads on the existing PR.
- [x] Run final-head CI and confirm GitHub signature verification; leave the PR unmerged and issue open.

## Review focus

Check that ordinary Working Plan evolution remains possible inside approved bounds, but no unapproved scope/risk/authority change or uncertain effect reaches mutation dispatch; approval is fresh after waits and revision races; no approval changes tool authorization; and rejection does not damage the accepted plan or existing evidence.

## Validation record

Planning preceded implementation. The existing #246 PR had a completed implementation and resolved Codex findings, but its base was stale. The current #245 head was merged into the #246 branch without rewriting its published history, and the PR remains stacked and unmerged.

Validation on the merged source: **PASS** — 227 focused Python 3.12 tests across tool registry, Working Plans, interaction, execution receipts, and delegation, plus the delegated revision-pause regression; `make check`; `make lint`; `make docs-check`; fixture `make subagent-acceptance`; and `make tui-acceptance` (including Go tests, approval, task, and cancellation flows). **BLOCKED** — full `make test` ran 888 tests but could not pass in this sandbox: local HTTP/browser tests cannot bind localhost, distribution tests cannot write `/Users/evangong/.kyrozen/update.lock`, and packaging checks cannot reach PyPI; the unmodified test run reported 32 errors and 4 failures from those constraints. Browser integration therefore errored at local server setup rather than being skipped. Python 3.13 runtime dependencies are absent, and live `make agent-acceptance` cannot bind localhost.

Final-head CI run [#38992739392](https://github.com/EvanProgramming/OpenKyrozen/actions/runs/38992739392) passed its Python 3.12/3.13, browser, agent workflow, Docker persistence, wheel install, TUI, and installed-update jobs; the core test job was skipped by path filtering. GitHub reports the signed merge commit as verified. CodeRabbit's status is successful and all existing Codex inline threads are resolved; a fresh Codex review was requested after synchronizing the base but had not returned at the time this record was written.

## Follow-up review fixes

- [x] Compare the complete objective execution contract when deciding whether a revision is material; changed tool arguments now require approval.
- [x] Allocate versions after both proposed and auto-accepted revisions.
- [x] Append automatic narrowing through a scoped SQLite transaction that verifies the latest accepted plan state, preventing stale controllers from widening bounds. A cancelled proposal leaves the last accepted state eligible for a later safe narrowing.
- [x] Bind material proposals to the current Working Plan revision at staging and reject edits made while approval is pending.
- [x] Exempt `update_plan` from task-action matching while retaining strategic bounds, pending-revision pause, capability and approval checks. Legacy JSON arguments are passed to its typed registry executor after schema validation.
- [x] Add regression tests for all five findings and for narrowing after cancelling a material proposal.

Follow-up validation: `tests.test_interaction` passed (85 tests); `tests.test_task_consistency`, `make lint`, and `git diff --check` passed. `make check` and `make docs-check` are blocked locally because the available Python 3.12 environment lacks `requests`. `tests.test_durable_tasks_gateway` had one environment-blocked local-server test because sandbox socket binding is denied. Final-head GitHub Actions run [#38993811316](https://github.com/EvanProgramming/OpenKyrozen/actions/runs/38993811316) passed both full Python suites, wheel install, Docker persistence, TUI, and installed-update checks on Ubuntu/macOS/Windows; `core-test` was skipped by path filtering. GitHub verified the signed follow-up commit. CodeRabbit skipped review because reviews are disabled for this stacked base; a fresh Codex review request has not returned.

Additional findings: explicit file-objective paths are now exact; stale completion is rejected both in the controller and in a scoped SQLite compare-and-swap; restored pending proposals block automatic acceptance. `tests.test_interaction`, `make check`, and `make lint` pass on the updated stack. GitHub key inventory shows `piggyevan123@gmail.com` verified for the signing key and the noreply identity unverified; this follow-up uses the verified identity.

Latest local validation: the full Python 3.12 suite passes (903 tests) on the updated #286 stack. The #285 local full run has one unrelated pre-existing provider-timeout test failure, reproduced on `main` at `146bb19`; the final-head CI runs are being refreshed after the signature and review updates.
3 changes: 3 additions & 0 deletions docs/superpowers/plans/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@
- [V3 #264 — Version SQLite state and migrate safely](2026-10-14-v3-issue-264.md)
- [V3 #241 — Working Plans and task lifecycle](2026-10-14-v3-issue-241.md)
- [V3 #242 — Atomic Working Plan edits](2026-10-16-v3-issue-242.md)
- [V3 #245 — Versioned, user-approved Strategic Plans](2026-10-16-v3-issue-245.md)
- [V3 #236 — Execution receipts and task association](2026-10-14-v3-issue-236.md)
- [V3 #255 — Shared typed runtime events](2026-10-14-v3-issue-255.md)

Add a linked issue-specific plan here before coding any later V3 issue.

- [V3 #246 — Reapproval for material Strategic Plan revisions](2026-10-16-v3-issue-246.md)
2 changes: 2 additions & 0 deletions docs/tasks-and-automation.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ Task IDs and records are actor/workspace/session scoped. The web task API expose

Simple work does not require a plan, and a plan is optional for medium work. Complex direct work uses a durable Working Plan with runtime-owned stable IDs and explicit acceptance criteria. The typed `update_plan` boundary applies revision-checked batches of add, update, cancel, reorder, and dependency operations; legacy `complexity`/`tasks` input is adapted through the same validation path. A changed task must still be pending and unexecuted; executed task records and evidence are preserved, and changed work is represented by a new task after cancellation. Scheduling follows plan order and waits for every dependency to succeed. A plan completes only when every task succeeds with acceptance evidence; recovery also reconciles a crash between the final task write and the plan status write. Clearing an active plan cancels its unfinished steps. The existing foreground text protocol continues to use Plan/TaskList compatibility until the native foreground loop is migrated.

Plan Mode can produce a versioned Strategic Plan before execution. Acceptance records the exact objectives, acceptance criteria, workspace paths, capabilities, effect categories, and risk ceiling alongside its linked Working Plan. A step may also carry a visible, fingerprinted `execution` contract for one exact `write_file` or `edit_file` call; delegated file mutations require this explicit contract and still pass assigned-file, workspace-bound, and tool-approval checks. Each criterion should include a `verification` action and exact object arguments. A `read_file` verifier must also include one case-sensitive `expect` predicate (`equals` or nonempty `contains`); the returned text must satisfy it before the criterion is recorded. Plain-text criteria remain readable for legacy proposals but cannot satisfy the per-criterion completion gate without a verifier. Runtime tool dispatch checks each tool's catalog policy and supplied paths against those accepted bounds; shell processes are denied because this runtime cannot confine arbitrary commands to those paths. An unbounded legacy proposal receives read-only defaults. Strategic acceptance does not grant capabilities, bypass tool approvals, or establish completion evidence.

For a typed plan step, include an optional `execution` object with the canonical tool `action` and object `arguments`. Native tool calls associate with a task only when the runtime receives that task's explicit ID; matching action and arguments alone never select a task. A successful associated receipt may add execution evidence, but it cannot satisfy acceptance criteria by itself. A delegated assignment may carry that explicit Working Plan task ID; the parent records task evidence only after the independent review succeeds. The legacy text adapter retains its bounded matching behavior for compatibility. Plan IDs and task IDs are returned as structured result data so later updates can retain runtime-owned task identities.

## Sub-agents
Expand Down
33 changes: 28 additions & 5 deletions openkyrozen/agent/delegation_runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -361,11 +361,34 @@ def _delegation_tool_access(self, action, args):
if path not in owned:
raise ValueError("Sub-agent write is outside its assigned files")
parent = getattr(self.current_session, "_delegation_parent", None)
if parent and parent.interaction.state().get("executing_plan") and self._is_state_changing_action(action, args):
structured = json.dumps(args, ensure_ascii=False, sort_keys=True) if isinstance(args, dict) else str(args)
allowed, reason = parent.tasks.mutation_matches_current_task(action, structured)
if not allowed:
raise ValueError("Sub-agent action does not match accepted plan: " + reason)
parent_state = parent.interaction.state() if parent else {}
parent_plan = parent_state.get("executing_plan") if parent_state else None
if parent and parent_plan:
from openkyrozen.agent.executor import (
_awaiting_revision_mutation, _legacy_object_arguments, _strategic_plan_denial,
)
arguments = args if isinstance(args, dict) else None
spec = getattr(getattr(self, "tool_registry", None), "specs", {}).get(action)
if arguments is None and isinstance(args, str):
if spec is not None:
normalized = _legacy_object_arguments(args, spec)
arguments = normalized if normalized else None
match_args = (json.dumps(arguments, ensure_ascii=False, sort_keys=True, separators=(",", ":"))
if arguments is not None else str(args))
parent_runtime = parent if callable(getattr(parent, "_is_state_changing_action", None)) else self
if _awaiting_revision_mutation(parent_state, action, arguments if arguments is not None else args,
spec, parent_runtime):
raise PermissionError("Parent Strategic Plan revision is awaiting approval")
denial = _strategic_plan_denial(
parent_plan, action, arguments if arguments is not None else args,
spec, parent.workspace.root,
)
if denial:
raise PermissionError(f"Sub-agent operation exceeds the accepted Strategic Plan: {denial}")
if self._is_state_changing_action(action, args):
allowed, reason = parent.tasks.mutation_matches_current_task(action, match_args)
if not allowed:
raise ValueError("Sub-agent action does not match accepted plan: " + reason)
guarded = action in {"read_file", "write_file", "edit_file", "search_files"} or self._is_state_changing_action(action, args) or action in {"git_diff", "git_show"}
if access and guarded:
cancelled = (lambda: coordinator.cancelled[context.child_run_id].is_set()) if coordinator else (lambda: False)
Expand Down
Loading
Loading