The proposal is a fenced dsh-action JSON object at the end of the final
answer instead of a suggest_action tool call. The projection reads the
last valid block of an assistant message, keeps one card per turn, and
marks a proposal written while queuedMessageLimit user messages are
queued as suppressed; the chat hides dsh- fences from rendered answers.
The Web replay fixture, tool catalog and READMEs follow the toolless
mechanism.
Follow the tool executor refactor: the tool/ptc-dispatch event type now comes
from dsh-tool-executor-ptc, and the tests invoke tools through dsh-tool-testkit.
Regenerate the doc graphs, tool catalog and persistence schema after the merge
and re-record their translation pairing.
Mint the check-run token from a dedicated approval App instead of a shared
automation App, so the identity that owns the decision check suite is specific to
this gate. The workflow reads `vars.DSH_APPROVAL_APP_CLIENT_ID` and
`secrets.DSH_APPROVAL_APP_PRIVATE_KEY`, and the token stays scoped to
`checks: write`.
Drop the preflight sandbox fence. It derived writable roots in the local
process, so under the SSH provider it threw on remote additionalWritableRoots
and compared remote targets against local temp roots; write and edit never
fenced in the tool layer. The provider now refuses a denied operation at
commit, and a commit whose first operation failed without any change rejects
like a preflight refusal so the sandbox escalation path keeps its error code.
Classify FS_ABORTED as unknown: a cancelled remote request rejects while the
provider may still be writing, so no stat comparison can settle it. Document
that a cancelled call receives the registry's abort result like every tool.
Store no diff for creations, matching write, and bound the move source basis
by diffBasisMaxBytes so persisted metadata never holds whole files;
FsMoveOutcome.sourceBefore becomes nullable. Omit deletions from the call
preview and from result diffs without a basis instead of rendering them as
empty creations, and count distinct files in the preview title.
Reject a NUL byte beyond the read sampling window in preflight, name targets
by display path in atomic-write diagnostics, align the apply_patch guidance
with the edit wording and mention delete and move, read the stopped flag and
applied diffs tool-agnostically in the client models, skip the permission-bit
snapshot under root, list fs/delete-intent in the tool catalog, and refresh
the fs-patch description, group README, fs-sandbox summary, and ui-tool README.
Integrate exact origin/master b9bdd062c8ffd3dc234ebea7f5dff55ff26d87ad. Preserve the Session Markdown copy lifecycle and dictionary while adopting the Japanese locale, regenerate the client slot catalog, and add the Japanese quote-removal string required by the merged locale type.
Address the review of this pull request:
- A failed image upload keeps the Host's attachment refusal reason. The
thumbnail of a refused image names the reason instead of offering a
retry that cannot succeed, and Enter while uploads hold the send names
the first failure; a transport failure still offers retry, and an
image without a file name uses the pending-image label.
- An image upload stops reading at the smaller of the per-image and
per-message byte limits.
- A carried image draft moving to a Session that sends images inline
drops its upload instead of staging it again.
- The image upload ready state no longer carries an unread image ref.
- Docs describe stored-image admission and the command image path, and
the attachment rail test builds typed props instead of casting through
unknown.
The decision check run kept its job-token check suite out of the pull request's
merge box: GitHub associates check runs with a pull request through the check
suite of the workflow run, and a `pull_request_target` run is not associated.
Mint a token from the repository App scoped to `checks: write` and publish only
the check run with it, so the merge box lists the label; the commit status gate
keeps using the job token and is unaffected when the token or the write fails.
Pin the token step, its single secret reference, and the client split in the
workflow and approval tests, and record the measured association limit in the
Agent Note and review-ownership README.
A patch creates files like write and updates them like edit, so
applyPatch now defaults to `write && edit` instead of an independent
true. Compositions that disable both text mutation tools lose
apply_patch without naming it, and a user config override of the
tool-fs row cannot bring the tool back; the sdk-minimal and Web
minimal presets drop their explicit applyPatch: false. An explicit
value still overrides the derivation.
Align the fs-patch package version with the 0.2.1-rc.2 root, and add
apply_patch to the standard preset tool list, the subagent-inheritance
expected session, and the Python SDK dynamic-tools snapshot.
Keyless session, SDK, ACP, and Web snapshots, the subagent-inheritance
expected output, and the Python dynamic-tools snapshot no longer list
exit_plan_mode outside plan mode, and the collapse-timing goldens count one
fewer added tool. In plan-review, the approved exit now removes the tool on
the next step: its header records a change that starts a series and a
tool-removal developer message, which the expanded Web timeline shows.
cordis-inspect-jsdoc records the new tools service signatures. The pwsh
tool-turn pins are edited by hand because pwsh is unavailable for a local
refresh; their only change is the removed schema.
ctx.tools.register(definition, { when }) adds a synchronous or asynchronous
condition. AgentLoop resolves conditions once per proposed step with the
agent, the model selection that step preparation captured, and the turn
signal, before prompt assembly and agent/pre-step. The resulting
ResolvedToolSet governs tool declarations, Native dispatch, PTC bindings,
and nested calls for that step and its retries, and the turn disposes it
when the proposal is rejected or fails, when no step opens, and after the
step. A false condition removes the tool everywhere; a thrown condition
ends the turn with TOOL_ACTIVATION_FAILED. Calls whose registration was
replaced or removed during the step return UNKNOWN_TOOL.
system-prompt/assemble now transforms PromptPresentation without a tool
array, so tool declarations stay provider-owned. exit_plan_mode is declared
only for steps whose selected plan state is active, the same state that
renders plan guidance; it still rejects a call before the selection is
logged.
Model selection stays as master defines it; this change adds no model
selection event or Agent field.