Commit Graph
7 Commits
Author SHA1 Message Date
kingwl 1f38b211be Merge origin/master (generic task runtime #219, single-exe closure, package renames)
Semantic resolutions beyond line merges:
- The bash seam keeps resolveMode + the bash/resolve-mode waterfall on
  master's task-free BashExecutor (run/start/resolve only; BashProcess
  handles); tool-bash consults it at its stamping site and escalation
  baseline on master's render/background split, with a waterfall test on
  the recording executor.
- dsh-mode's BASH_FAMILY narrows to ['bash']: bash_output/bash_kill are
  replaced by the kind-generic task_output/task_kill, which span every
  task kind and only observe or stop work, so the access cap withholds
  only the starter it can reason about.
- The plan-mode snapshot suite adopts master's pin grammar (tool-schema
  sidecars; the expectedHeaderSnapshots extension is gone — the exit
  transition deltas, and entering-before-turn-1 needs no second
  snapshot); modes-advertise joins the plan header class (no-model, so
  membership is vacuous). Fixtures re-recorded on the acp-demo bin;
  the replay overlay gains the passthrough sandbox runner.
- examples/plan-acp-agent rewires to @deepseek-ai/dsh-acp-demo and drops
  its tool-bash entry (the spine bundle now composes it); dsh-stdio (the
  renamed stdio-chat home) keeps its /mode command and gains the dsh-mode
  peer edge; the acp bridge keeps the modes surface beside master's
  permission presets.
- mode README gains the Model Experience / Known Limitations sections the
  new README gates require; AGENTS.md ceiling 1370 → 1440 for the kept
  mode/ layout line and Agent efficiency section.
2026-07-15 23:17:18 +08:00
kingwl 1fe2f99580 refactor(mode): drop the per-mode tool allowlist — enforce where an enforcer exists
A ModeDefinition is now exactly { section, access? }; unknown keys (a
tools list included) fail loud at load. What plan mode still does: the
guidance section, the exit_plan_mode visibility rule (plan only, both
soft surfaces), the access cap's bash/resolve-mode clamp, and the two
cap-derived pre-execute guards (the bash trio is withheld when no
confining executor can honor the cap; sandbox escalation is denied
while it holds). The general deny-by-default gate and the assemble
allowlist filter are gone: which tools a mode admits is an effects
question, and a hand-maintained name list mislabels it — it must track
every composed tool and rots silently as tools arrive. The dimension
returns as a consumer of effects self-declaration on tool definitions
(MCP ToolAnnotations as the template) — rationale and restart trigger
archived in the RFC's Alternatives/Deferred; the interim guidance-only
non-shell restraint is priced in Consequences.

Exiting plan is now a pure removal (the exit tool + section), which the
delta encoding CAN express: the re-recorded plan-mode fixture pins one
plan-shaped initial header snapshot plus one header-delta instead of
two snapshots.
2026-07-12 23:20:36 +08:00
kingwl 99650a201b feat(mode): the access cap — plan mode composes with the sandbox instead of banning bash
A ModeDefinition may declare access: the widest sandbox access shell
commands run under while the mode holds, on the SANDBOX_MODES ladder.
The bash seam gains the resolution point to hang it on: BashExecutor.
resolveMode(session) folds override ?? default and dispatches the new
bash/resolve-mode waterfall; dsh-tool-bash consults it at both the
stamping site and the escalation baseline; dsh-mode's clamp listener
takes the ladder minimum per call. Two independent log folds compose at
read time — the mode never writes the sandbox knob, so the two switch
in any order and the knob re-emerges intact on exit.

The built-in plan definition ships access: read-only with the bash trio
allowlisted CONDITIONALLY: both policy layers admit bash/bash_output/
bash_kill only while a confining executor is mounted (an unconfinable
shell cannot honor the cap), and a bash call carrying sandbox_permissions
under a cap is denied at the gate — no widening mid-mode; the widened
step belongs in the plan.

examples/plan-acp-agent swaps bash-local for sandbox-local +
bash-sandbox (workspace-write default, clamped read-only inside plan)
plus the approval seam; the re-recorded plan-mode arc runs a real cat
inside plan under the clamped sandbox, and modes-advertise now pins the
sandbox-mode and approval config options. RFC amended to the landed
shape (access cap section, orthogonality FAQ, deferred item resolved
into effects self-declaration).
2026-07-12 22:51:09 +08:00
kingwl 88db403d9f Merge branch 'worktree-session-modes-rfc' (master: sandbox stack #169, skills #109, prompt snapshots #254)
The stack rebases onto a moved master through its base branch. Beyond
mechanical unions (both branches' demo scripts, example rows, service
roles, tool lists, acp deps, doc budgets — each side fit alone, the
union needs the higher ceilings), three semantic reconciliations:

- The ACP bridge now carries BOTH per-session surfaces: the sandbox
  stack's config options + approval answerer and this branch's session
  modes; session/new and session/load advertise modes AND configOptions
  side by side.
- The feature matrix supersedes the sandbox stance per the RFC's
  second-lander rule: session/set_mode and current_mode_update flip to
  shipped-by-dsh-mode, config-option rows stay as #169 wrote them, and
  §6 records both landed features under the picker-to-modes /
  knobs-to-config-options division.
- The snapshot pin grammar (#254: one header snapshot + declared deltas
  + a Markdown prompt golden) gains a symmetric declaration for what a
  delta cannot express: expectedHeaderSnapshots — a plan-mode flip
  resorts the canonical tool list, so its widening lands as a second
  full snapshot, now its own Markdown section. The pin-less-class and
  model-turn-only-pin amendments carry over; new fixtures cover the
  extended writer paths, and the plan-acp-agent scenarios re-recorded
  under the merged composition (the app now bundles the skill tool)
  with the suite's refresh mode wired through.
2026-07-12 20:08:09 +08:00
kingwl 02e0756b78 feat(mode): ask_user_question joins the plan allowlist; the section steers to the exit tool
Live-session feedback (a real Zed elicitation round-trip): the model
presented its finished plan as a plain reply and asked the USER to
switch modes — the exact reversal the roadmap warns about — because the
shipped section's 'present it with the exit_plan_mode tool' read as a
suggestion. The section now says a finished plan is delivered by
calling exit_plan_mode, preferred over pasting it as a plain reply or
asking the user to switch modes — firmer, without imperatives.

ask_user_question enters the shipped plan allowlist (asking is
read-only-safe), and the section points a blocked decision at it. The
plan-acp-agent example composes the bash family (default mode only —
plan's allowlist keeps excluding it, so the two modes now demo a real
difference) plus tool-ask-user; both recorded scenarios re-recorded:
the pin now shows plan = [ask_user_question, exit_plan_mode, read,
todo_write] and post-exit default = the full eight-tool surface.
2026-07-10 15:05:26 +08:00
kingwl 14f7976e3d fix(mode): an approved exit leaves plan mode at the step boundary, not mid-batch
Review finding: the exit tool's direct mode/set append flipped the
folded mode while the loop could still execute further tool calls from
the SAME assistant response — a same-batch exit_plan_mode + write pair
would sail past tools/pre-execute under 'default' even though the
request was assembled under the plan-shaped header. That broke the
design's own invariant (a step's executions run under the mode its
assembly folded), which the pending-intent flush was built to hold for
user flips.

The tool now records the switch as a pending intent like every other
writer, flushed at this step's end (still in-turn); pending intents
carry a narrate flag so the exit's flush stays silent — the tool result
is its narration — while user flips keep the coalesced boundary notice.
The gate, folding the logged mode only, now provably covers the whole
batch: regression test pins approve-then-write-in-the-same-batch as
denied, and the widened toolset still arrives on the next step.

The recorded scenarios are re-recorded: the fixture now shows mode/set
landing after step/end, before the widened fallback header.
2026-07-10 10:35:43 +08:00
kingwl c5cb7da364 test(mode): record the plan-mode approve and keep-planning scenarios
The with-key recording session the RFC deferred. plan-mode is the 'plan'
header class's pinning scenario and necessarily carries BOTH header
shapes verbatim: the plan-shaped initial snapshot and the widened
fallback snapshot the approved exit produces mid-turn — so the suite
factory's pin guards relax from exactly-one to at-least-one header (the
classmates' uniformity anchor is the pin's FIRST header; transition
headers are legal only in the pin, matching the sandbox stack's
precedent). plan-mode-reject pins the keep-planning branch: the
corrective isError carries the reviewer's free-text feedback verbatim
and the session stays in plan mode, one header, uniform with the pin.

Recording notes, encoded in the prompts: the model is pinned to RELATIVE
paths (a recorded absolute temp path neither replays on another host nor
normalizes — the normalizers scrub the run's own cwd, not the
recording's), and the recorded model never calls a filtered tool, so the
gate's deny path stays pinned at the unit tier — that refusal is the
behavior the soft layer exists to produce. The gen-tool-catalog
meta-test pins exit_plan_mode in the harvested schema list.
2026-07-10 03:39:29 +08:00