Skip to content

[Plan Mode 3/8] Advanced plan interactions#70015

Closed
100yenadmin wants to merge 3 commits into
openclaw:mainfrom
electricsheephq:restack/68939-pr4-advanced-plan-interactions
Closed

[Plan Mode 3/8] Advanced plan interactions#70015
100yenadmin wants to merge 3 commits into
openclaw:mainfrom
electricsheephq:restack/68939-pr4-advanced-plan-interactions

Conversation

@100yenadmin

Copy link
Copy Markdown
Contributor

Summary

[Plan Mode 3/8] — part of the 8-part decomposition of #68939, stacking on #69449 (Part 1).

Stacks on: previous part (see [Plan Mode 2/8] / [Plan Mode 1/9 #69449]).

Adds clarifying questions + plan restate + section-targeted review notes + revision markers. Stacks on Part 2/8.

Lines: ~5860

Diff note

This PR is opened cross-repo (head: 100yenadmin:restack/68939-pr4-advanced-plan-interactions) against openclaw:main. Because GitHub doesn't support stacked-PR bases that point at fork refs, the displayed diff cumulatively includes all previous parts in the stack. Reviewers should focus on the changes specific to this part — see commit list for the new content beyond what previous parts established.

Test status

After post-v2026.4.21 rebase: all targeted plan-mode tests pass (53/53 in unit-fast for approval + integration suites). The full suite has pre-existing vitest workspace project-name conflicts unrelated to this work.

Related

Copilot AI review requested due to automatic review settings April 22, 2026 06:20
@openclaw-barnacle openclaw-barnacle Bot added app: macos App: macos app: web-ui App: web-ui gateway Gateway runtime agents Agent runtime and tooling size: XL labels Apr 22, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR advances “plan mode” interactions and runtime wiring: plan-mode tool registration, mutation gating, approval/question interactions, skill plan-template seeding, plan persistence helpers, and additional retry/auto-continue behavior in the embedded runner.

Changes:

  • Add/extend plan-mode protocol/schema + runner wiring (planMode/planApproval/lastPlanSteps, pending injection plumbing, mutation gate hook).
  • Introduce new plan-mode tools and prompt steering (enter_plan_mode, ask_user_question, plan archetype prompt/persistence helpers).
  • Add skill plan-template parsing/seeding and broaden test coverage across plan-mode components.

Reviewed changes

Copilot reviewed 57 out of 57 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/gateway/protocol/schema/sessions.ts Adds sessions.patch fields for planMode/planApproval/lastPlanSteps with TypeBox schema + docs.
src/config/zod-schema.ts Adds config cap for skill plan-template step seeding.
src/config/zod-schema.agent-defaults.ts Adds embeddedPi autoContinue config schema + planMode enabled flag schema.
src/config/types.skills.ts Documents/exports maxPlanTemplateSteps limit.
src/config/types.agent-defaults.ts Adds embeddedPi autoContinue config typing + planMode enabled typing; tweaks compaction notifyUser docs.
src/auto-reply/reply/agent-runner-execution.ts Threads “fresh” session state + pending injection consumption into agent run execution.
src/agents/tools/update-plan-tool.parity.test.ts Adds parity + merge-mode tests for update_plan behavior.
src/agents/tools/exit-plan-mode-tool.test.ts Adds exit_plan_mode subagent-gate + archetype-field tests.
src/agents/tools/enter-plan-mode-tool.ts Adds enter_plan_mode tool implementation.
src/agents/tools/ask-user-question-tool.ts Adds ask_user_question tool implementation + validation.
src/agents/tools/ask-user-question-tool.test.ts Adds tests for ask_user_question tool behavior.
src/agents/tool-description-presets.ts Adds plan-mode tool display summaries and richer plan-mode tool descriptions.
src/agents/tool-catalog.ts Registers plan-mode tools in the catalog (gated by config).
src/agents/test-helpers/fast-openclaw-tools-sessions.ts Updates update_plan mock signature + exported statuses for tests.
src/agents/skills/workspace.ts Carries resolvedPlanTemplates into skill snapshot so seeding works in snapshot-backed runs.
src/agents/skills/types.ts Adds planTemplate typing to skill metadata + snapshot.
src/agents/skills/skill-planner.ts Implements plan-template normalization (dedupe/truncate) + helpers.
src/agents/skills/skill-planner.test.ts Adds tests for skill plan-template payload building + seeding paths.
src/agents/skills/frontmatter.ts Parses plan-template frontmatter (kebab/camel + content alias) into metadata.
src/agents/skills/frontmatter.test.ts Adds tests for plan-template frontmatter parsing and precedence.
src/agents/plan-store.test.ts Adds comprehensive PlanStore behavior/security tests (namespaces, locking, confinement).
src/agents/plan-mode/types.ts Adds plan-mode state types + approvalId generation + decision injection builder.
src/agents/plan-mode/plan-archetype-prompt.ts Adds plan archetype prompt fragment + filename/slug helpers.
src/agents/plan-mode/plan-archetype-prompt.test.ts Tests prompt fragment and filename helper behavior.
src/agents/plan-mode/plan-archetype-persist.ts Persists plan markdown artifacts safely (collision handling, confinement, error classification).
src/agents/plan-mode/plan-archetype-persist.test.ts Tests plan persistence behavior, collisions, confinement, and error wrapping.
src/agents/plan-mode/mutation-gate.ts Implements plan-mode mutation gate (default-deny + exec read-only allowlist).
src/agents/plan-mode/mutation-gate.test.ts Tests mutation gate behavior and exec whitelist rules.
src/agents/plan-mode/integration.test.ts End-to-end wiring smoke test for plan-mode gating + tool enablement.
src/agents/plan-mode/index.ts Barrel exports for plan-mode module.
src/agents/plan-mode/approval.ts Implements plan approval state machine resolver + approved-plan injection helper.
src/agents/plan-mode/approval.test.ts Tests approval state transitions, stale-id guard, and injection builders.
src/agents/plan-hydration.ts Adds post-compaction plan hydration formatter.
src/agents/plan-hydration.test.ts Tests plan hydration formatting/filtering.
src/agents/pi-tools.ts Threads planMode into before-tool-call hook context.
src/agents/pi-tools.before-tool-call.ts Enforces mutation gate in before_tool_call pipeline when planMode is active.
src/agents/pi-embedded-runner/skills-runtime.ts Adds skill plan-template resolution + seeding + snapshot fallback.
src/agents/pi-embedded-runner/run/params.ts Adds planMode param to embedded runner entrypoint params.
src/agents/pi-embedded-runner/run/incomplete-turn.ts Adjusts planning-only retry limits/instructions; adds auto-continue fast-path instruction; introduces planModeActive gating.
src/agents/pi-embedded-runner/run/attempt.ts Seeds plan from skill templates; injects plan-mode prompt fragments into system prompt; forwards planMode.
src/agents/pi-embedded-runner/run/attempt.spawn-workspace.test-support.ts Stubs skill-template seeder in spawn-workspace test support.
src/agents/pi-embedded-runner/run.ts Threads planMode through run → attempt; adds autoContinue loop behavior; modifies retry instruction escalation; changes hook selection call.
src/agents/pi-embedded-runner/run.incomplete-turn.test.ts Updates/increases retry expectations; adds tests for auto-continue and escalation helper.
src/agents/openclaw-tools.ts Registers plan-mode tools (gated) and threads runId into update_plan + sessions_spawn.
src/agents/openclaw-tools.registration.ts Adds plan-mode tool enablement gate based on config.
apps/shared/OpenClawKit/Sources/OpenClawProtocol/GatewayModels.swift Regenerates Swift protocol structs to include new sessions.patch fields; removes ChannelsStartParams.
apps/macos/Sources/OpenClawProtocol/GatewayModels.swift Same Swift regeneration for macOS target.
Comments suppressed due to low confidence (1)

src/agents/pi-embedded-runner/run.ts:312

  • resolveHookModelSelection supports passing attachments into the before_model_resolve hook, but this call site no longer supplies attachments derived from params.images. That changes plugin behavior for vision-capable prompts (hooks can no longer route based on image presence/mimeType). If this wasn't intentional, pass buildBeforeModelResolveAttachments(params.images) again so hooks keep the full context.
      const hookSelection = await resolveHookModelSelection({
        prompt: params.prompt,
        provider,
        modelId,
        hookRunner,
        hookContext: hookCtx,
      });

Comment on lines +239 to +244
* Per-variant requirements:
* - `approve` / `edit`: only `approvalId` (optional but
* recommended for staleness protection).
* - `reject`: optional `feedback` (capped to 8 KiB to bound
* the prompt-cache hash explosion vector — PR-11 H4).
* - `answer`: REQUIRES `answer` text and `approvalId` (Codex P1

Copilot AI Apr 22, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The doc comment says the reject planApproval variant has optional feedback, but the schema below makes feedback required (minLength: 1). Update the per-variant requirements bullet to match the actual contract so clients don't implement against the wrong semantics.

Copilot uses AI. Check for mistakes.
Comment on lines +33 to +36
import {
composePromptWithPendingInjection,
consumePendingAgentInjection,
} from "../../agents/pi-embedded-runner/pending-injection.js";

Copilot AI Apr 22, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This import points at ../../agents/pi-embedded-runner/pending-injection.js, but there is no pending-injection module under src/agents/pi-embedded-runner/ in the repo. As-is, this will fail build/tsc at module resolution time. Add the missing module (with these exports) or update the import to the correct existing file.

Copilot uses AI. Check for mistakes.
} from "../../pi-tool-definition-adapter.js";
import { createOpenClawCodingTools, resolveToolLoopDetectionConfig } from "../../pi-tools.js";
import { PLAN_ARCHETYPE_PROMPT } from "../../plan-mode/plan-archetype-prompt.js";
import { PLAN_MODE_REFERENCE_CARD } from "../../plan-mode/reference-card.js";

Copilot AI Apr 22, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PLAN_MODE_REFERENCE_CARD is imported from ../../plan-mode/reference-card.js, but there is no src/agents/plan-mode/reference-card.ts/js in this PR/repo. This will fail module resolution at build time. Either add the missing reference-card module or remove/replace this import (and the usage) with an existing source.

Suggested change
import { PLAN_MODE_REFERENCE_CARD } from "../../plan-mode/reference-card.js";
const PLAN_MODE_REFERENCE_CARD = "";

Copilot uses AI. Check for mistakes.
import { createMusicGenerateTool } from "./tools/music-generate-tool.js";
import { createNodesTool } from "./tools/nodes-tool.js";
import { createPdfTool } from "./tools/pdf-tool.js";
import { createPlanModeStatusTool } from "./tools/plan-mode-status-tool.js";

Copilot AI Apr 22, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

createPlanModeStatusTool is imported from ./tools/plan-mode-status-tool.js, but there is no corresponding module under src/agents/tools/ in the repo. This will fail compilation/module resolution. Add the missing tool implementation file (and ensure it's exported/registered appropriately), or remove the import/usage if it was not meant to land in this slice.

Suggested change
import { createPlanModeStatusTool } from "./tools/plan-mode-status-tool.js";

Copilot uses AI. Check for mistakes.
Comment on lines +47 to +48
"update_plan",
"exit_plan_mode",

Copilot AI Apr 22, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PLAN_MODE_ALLOWED_TOOLS omits newly introduced plan-mode tools (e.g. ask_user_question, enter_plan_mode, plan_mode_status). Because this gate is default-deny, those tool calls will be blocked while planMode is active, breaking the intended plan-mode interactions. Add the missing tool names to the allowlist (and add/adjust mutation-gate tests to cover them).

Suggested change
"update_plan",
"exit_plan_mode",
"update_plan",
"ask_user_question",
"enter_plan_mode",
"exit_plan_mode",
"plan_mode_status",

Copilot uses AI. Check for mistakes.
@greptile-apps

greptile-apps Bot commented Apr 22, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds the core advanced plan-mode interactions: clarifying questions (ask_user_question), plan archetypes (analysis/assumptions/risks/verification fields on exit_plan_mode), a two-layer accept-edits gate, a persistent cross-session plan store (PlanStore), and the full approval state machine wired into sessions.patch. The implementation is thorough and well-defended (atomic writes, symlink confinement, PID-liveness stale-lock eviction, prototype-pollution-safe JSON parsing), but two functional regressions were introduced.

  • error-codes.ts not updated: ErrorCodes.PLAN_APPROVAL_EXPIRED and ErrorCodes.PLAN_APPROVAL_GATE_STATE_UNAVAILABLE resolve to undefined at runtime, falling back to \"INVALID_REQUEST\" via the ?? guard — client-side UX branches keyed on these codes silently never fire.
  • ask_user_question blocked in plan mode: The mutation gate's fail-closed default denies any tool not in PLAN_MODE_ALLOWED_TOOLS; ask_user_question is absent from that set, making it unusable during the phase it was designed for.

Confidence Score: 4/5

Two P1 regressions block intended UX paths; safe to merge after fixing both.

Both P1 findings are contained to the plan-mode feature (not core agent execution or data integrity), but one makes ask_user_question completely non-functional in plan mode and the other silently degrades all plan-approval error discrimination to generic INVALID_REQUEST. Fixes are small: four lines to error-codes.ts and two lines to mutation-gate.ts.

src/gateway/protocol/schema/error-codes.ts (missing plan-mode error code definitions) and src/agents/plan-mode/mutation-gate.ts (PLAN_MODE_ALLOWED_TOOLS missing ask_user_question/enter_plan_mode).

Prompt To Fix All With AI
This is a comment left during a code review.
Path: src/gateway/sessions-patch.ts
Line: 798

Comment:
**New plan-mode error codes missing from `error-codes.ts`**

`ErrorCodes.PLAN_APPROVAL_EXPIRED` (line 798) and `ErrorCodes.PLAN_APPROVAL_GATE_STATE_UNAVAILABLE` (line 850) access keys that don't exist on the `ErrorCodes` const object — they evaluate to `undefined` at runtime. Because `invalid()` uses `code ?? ErrorCodes.INVALID_REQUEST`, both calls silently fall back to `"INVALID_REQUEST"`. Client code that branches on these specific codes (e.g. the "auto-dismiss stale approval card" logic described in the inline comment for `PLAN_APPROVAL_EXPIRED`) will never match and the intended UX behaviour is permanently suppressed.

The two string-literal forms on lines 879 and 890 (`"PLAN_APPROVAL_BLOCKED_BY_SUBAGENTS"`, `"PLAN_APPROVAL_WAITING_FOR_SUBAGENT_SETTLE"`) survive at runtime but are TypeScript type errors because they are not assignable to `ErrorCode`.

All four codes need to be added to `src/gateway/protocol/schema/error-codes.ts`:

```typescript
export const ErrorCodes = {
  // ... existing codes ...
  PLAN_APPROVAL_EXPIRED: "PLAN_APPROVAL_EXPIRED",
  PLAN_APPROVAL_GATE_STATE_UNAVAILABLE: "PLAN_APPROVAL_GATE_STATE_UNAVAILABLE",
  PLAN_APPROVAL_BLOCKED_BY_SUBAGENTS: "PLAN_APPROVAL_BLOCKED_BY_SUBAGENTS",
  PLAN_APPROVAL_WAITING_FOR_SUBAGENT_SETTLE: "PLAN_APPROVAL_WAITING_FOR_SUBAGENT_SETTLE",
} as const;
```

Then replace the two string literals in `sessions-patch.ts` with `ErrorCodes.*` references for consistency.

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: src/agents/plan-mode/mutation-gate.ts
Line: 41-50

Comment:
**`ask_user_question` blocked by default-deny during plan mode**

`ask_user_question` is not in `PLAN_MODE_ALLOWED_TOOLS` and does not match any suffix pattern, so the mutation gate's fail-through default deny blocks it whenever `planMode === "plan"`. The tool's own description explicitly states "Plan-mode safety: questions DO NOT exit plan mode. The session stays in plan mode while waiting" — but an agent in plan mode calling `ask_user_question` will receive `Tool "ask_user_question" is not in the plan-mode allowlist and is blocked by default` before any question reaches the user.

`enter_plan_mode` has the same omission (calling it again while already in plan mode should not be blocked).

```suggestion
const PLAN_MODE_ALLOWED_TOOLS = new Set([
  "read",
  "web_search",
  "web_fetch",
  "memory_search",
  "memory_get",
  "update_plan",
  "exit_plan_mode",
  "ask_user_question",
  "enter_plan_mode",
  "session_status",
]);
```

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "feat(plan-mode): split PR4 advanced plan..." | Re-trigger Greptile

// (/plan off, another channel approved, timeout, compaction).
return invalid(
"planApproval requires an active plan-mode session (the approval window may have expired or been resolved on another channel)",
ErrorCodes.PLAN_APPROVAL_EXPIRED,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 New plan-mode error codes missing from error-codes.ts

ErrorCodes.PLAN_APPROVAL_EXPIRED (line 798) and ErrorCodes.PLAN_APPROVAL_GATE_STATE_UNAVAILABLE (line 850) access keys that don't exist on the ErrorCodes const object — they evaluate to undefined at runtime. Because invalid() uses code ?? ErrorCodes.INVALID_REQUEST, both calls silently fall back to "INVALID_REQUEST". Client code that branches on these specific codes (e.g. the "auto-dismiss stale approval card" logic described in the inline comment for PLAN_APPROVAL_EXPIRED) will never match and the intended UX behaviour is permanently suppressed.

The two string-literal forms on lines 879 and 890 ("PLAN_APPROVAL_BLOCKED_BY_SUBAGENTS", "PLAN_APPROVAL_WAITING_FOR_SUBAGENT_SETTLE") survive at runtime but are TypeScript type errors because they are not assignable to ErrorCode.

All four codes need to be added to src/gateway/protocol/schema/error-codes.ts:

export const ErrorCodes = {
  // ... existing codes ...
  PLAN_APPROVAL_EXPIRED: "PLAN_APPROVAL_EXPIRED",
  PLAN_APPROVAL_GATE_STATE_UNAVAILABLE: "PLAN_APPROVAL_GATE_STATE_UNAVAILABLE",
  PLAN_APPROVAL_BLOCKED_BY_SUBAGENTS: "PLAN_APPROVAL_BLOCKED_BY_SUBAGENTS",
  PLAN_APPROVAL_WAITING_FOR_SUBAGENT_SETTLE: "PLAN_APPROVAL_WAITING_FOR_SUBAGENT_SETTLE",
} as const;

Then replace the two string literals in sessions-patch.ts with ErrorCodes.* references for consistency.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/gateway/sessions-patch.ts
Line: 798

Comment:
**New plan-mode error codes missing from `error-codes.ts`**

`ErrorCodes.PLAN_APPROVAL_EXPIRED` (line 798) and `ErrorCodes.PLAN_APPROVAL_GATE_STATE_UNAVAILABLE` (line 850) access keys that don't exist on the `ErrorCodes` const object — they evaluate to `undefined` at runtime. Because `invalid()` uses `code ?? ErrorCodes.INVALID_REQUEST`, both calls silently fall back to `"INVALID_REQUEST"`. Client code that branches on these specific codes (e.g. the "auto-dismiss stale approval card" logic described in the inline comment for `PLAN_APPROVAL_EXPIRED`) will never match and the intended UX behaviour is permanently suppressed.

The two string-literal forms on lines 879 and 890 (`"PLAN_APPROVAL_BLOCKED_BY_SUBAGENTS"`, `"PLAN_APPROVAL_WAITING_FOR_SUBAGENT_SETTLE"`) survive at runtime but are TypeScript type errors because they are not assignable to `ErrorCode`.

All four codes need to be added to `src/gateway/protocol/schema/error-codes.ts`:

```typescript
export const ErrorCodes = {
  // ... existing codes ...
  PLAN_APPROVAL_EXPIRED: "PLAN_APPROVAL_EXPIRED",
  PLAN_APPROVAL_GATE_STATE_UNAVAILABLE: "PLAN_APPROVAL_GATE_STATE_UNAVAILABLE",
  PLAN_APPROVAL_BLOCKED_BY_SUBAGENTS: "PLAN_APPROVAL_BLOCKED_BY_SUBAGENTS",
  PLAN_APPROVAL_WAITING_FOR_SUBAGENT_SETTLE: "PLAN_APPROVAL_WAITING_FOR_SUBAGENT_SETTLE",
} as const;
```

Then replace the two string literals in `sessions-patch.ts` with `ErrorCodes.*` references for consistency.

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +41 to +50
const PLAN_MODE_ALLOWED_TOOLS = new Set([
"read",
"web_search",
"web_fetch",
"memory_search",
"memory_get",
"update_plan",
"exit_plan_mode",
"session_status",
]);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 ask_user_question blocked by default-deny during plan mode

ask_user_question is not in PLAN_MODE_ALLOWED_TOOLS and does not match any suffix pattern, so the mutation gate's fail-through default deny blocks it whenever planMode === "plan". The tool's own description explicitly states "Plan-mode safety: questions DO NOT exit plan mode. The session stays in plan mode while waiting" — but an agent in plan mode calling ask_user_question will receive Tool "ask_user_question" is not in the plan-mode allowlist and is blocked by default before any question reaches the user.

enter_plan_mode has the same omission (calling it again while already in plan mode should not be blocked).

Suggested change
const PLAN_MODE_ALLOWED_TOOLS = new Set([
"read",
"web_search",
"web_fetch",
"memory_search",
"memory_get",
"update_plan",
"exit_plan_mode",
"session_status",
]);
const PLAN_MODE_ALLOWED_TOOLS = new Set([
"read",
"web_search",
"web_fetch",
"memory_search",
"memory_get",
"update_plan",
"exit_plan_mode",
"ask_user_question",
"enter_plan_mode",
"session_status",
]);
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/agents/plan-mode/mutation-gate.ts
Line: 41-50

Comment:
**`ask_user_question` blocked by default-deny during plan mode**

`ask_user_question` is not in `PLAN_MODE_ALLOWED_TOOLS` and does not match any suffix pattern, so the mutation gate's fail-through default deny blocks it whenever `planMode === "plan"`. The tool's own description explicitly states "Plan-mode safety: questions DO NOT exit plan mode. The session stays in plan mode while waiting" — but an agent in plan mode calling `ask_user_question` will receive `Tool "ask_user_question" is not in the plan-mode allowlist and is blocked by default` before any question reaches the user.

`enter_plan_mode` has the same omission (calling it again while already in plan mode should not be blocked).

```suggestion
const PLAN_MODE_ALLOWED_TOOLS = new Set([
  "read",
  "web_search",
  "web_fetch",
  "memory_search",
  "memory_get",
  "update_plan",
  "exit_plan_mode",
  "ask_user_question",
  "enter_plan_mode",
  "session_status",
]);
```

How can I resolve this? If you propose a fix, please make it concise.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a30794aaa0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/infra/agent-events.ts
Comment on lines +376 to +378
const handler = getAgentEventState().persistPlanModeSubagentGateState;
if (!handler) {
return;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Wire subagent gate persistence before approval gating

The subagent approval gate relies on persisted blockingSubagentRunIds when the parent run context is gone, but this persistence path is effectively disabled: persistPlanModeSubagentGateState exits immediately when no handler is set, and I could not find any call site that registers setPlanModeSubagentGatePersistenceHandler in the repo. In the common flow where clearAgentRunContext(runId) runs before a delayed approval arrives, the gate in sessions-patch.ts can see an empty persisted set and allow approve/edit even though subagents are still running. Please register the persistence handler during gateway/session-store initialization (or fail closed when persistence is unavailable).

Useful? React with 👍 / 👎.

Comment on lines +144 to +147
if (verifiedCriteria && !acceptanceCriteria) {
throw new ToolInputError(
`plan[${index}].verifiedCriteria requires plan[${index}].acceptanceCriteria to be set`,
);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Permit verifiedCriteria-only deltas in merge mode

This validation rejects any step update that includes verifiedCriteria without also resending acceptanceCriteria. That breaks the intended incremental merge workflow (marking criteria as verified over time) because callers must echo the full acceptance list on every update, and a normal delta like merge: true + updated verifiedCriteria against an existing step is rejected before merge. Validate verifiedCriteria against the merged step's acceptance criteria (existing + incoming) instead of requiring acceptanceCriteria in every delta payload.

Useful? React with 👍 / 👎.

@100yenadmin

Copy link
Copy Markdown
Contributor Author

Closed for sequential rollout — please disregard cumulative diff.

This PR was opened with --base main against the upstream repo. Cross-repo PRs can't reference fork branches as bases, so opening all 8 stack parts simultaneously produced cumulative diffs (each PR included all prior parts, 10k → 30k lines). That's review-hostile and reproduces exactly the problem the original umbrella #68939 had.

The fix: sequential rollout. Each [Plan Mode N/9] PR opens only AFTER the previous one merges to main, so its diff is incremental.

Currently open:

Next: when 1/9 merges, [Plan Mode 2/9] Core backend MVP opens with a clean ~2,000-line diff. Etc.

This PR's branch is preserved on the fork and will be reopened with a clean diff in its turn.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling app: macos App: macos app: web-ui App: web-ui gateway Gateway runtime size: XL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants