Summary
In app-server mode the ZCode backend always installs its protocol automation port, so the model is offered CronCreate, CronList, CronUpdate and CronDelete. Every one of those tools is implemented by asking the client over a server→client JSON-RPC request. zcode-acp is that client and handles none of them, so the tools are advertised but can never succeed.
Observed
zcode-acp 0.37.x, ZCode desktop 3.11.2 / CLI 0.16.5. Citations below re-checked against main at 8f61b4a (0.38.0).
CronUpdate on an existing automation id → tool error bridge unsupported: automation/update (observed)
CronDelete → bridge unsupported: automation/delete (observed)
- From the code path, not directly exercised:
CronList → bridge unsupported: automation/list; CronCreate fails with the backend's own message "Cannot verify whether this session belongs to a scheduled task. Try again later.", because its create path first probes automation/checkTaskBinding, swallows the -32601, falls back to automation/list, which the bridge also rejects.
With ZCODE_ACP_DEBUG the bridge logs ⚠ unhandled server→client request: automation/<op> for each call.
Root cause
src/handlers/server-requests.ts handleOne (~358–384): only interaction/requestPermission, interaction/requestUserInput and interaction/requestProviderRuntimeHeaders are handled; everything else reaches sendZcodeError(backend, id, "bridge unsupported: ${method}") (-32601). grep -ri automation src finds no handler, only unrelated comments.
- The backend (
zcode.cjs) exposes five client-facing methods through createProtocolAutomationPort: automation/create, automation/update, automation/checkTaskBinding, automation/list, automation/delete. registerBuiltInTools registers the four Cron tools whenever that port exists (includeAutomation), which in app-server mode is always.
- The backend's inbound RPC table has no
automation* methods, so there is nothing for the bridge to pass through to. Automation storage and scheduling are a host capability that the desktop app provides.
docs/BACKLOG.md already lists automation/* under "not planned (client/config layer)", but nothing stops the backend from advertising the tools.
Suggested fix (minimal)
Stop advertising tools the bridge cannot serve. In src/backend/resolve.ts backendArgs() (~151–153), union a built-in default of CronCreate CronList CronUpdate CronDelete with ZCODE_DISALLOWED_TOOLS instead of forwarding the env var verbatim. registerBuiltInTools applies disallowedTools before the includeAutomation gate, so this removes the tools from the model's view entirely. Keep an opt-in (for example ZCODE_ENABLE_AUTOMATION_TOOLS=1) for a host that does implement the port.
Tests: extend tests/resolve.test.ts for the default argv, the env-merge case and the opt-in. Docs: the ZCODE_DISALLOWED_TOOLS row in the README and the BACKLOG note.
Implementing the port (a persistent automation store under the data root plus a scheduler that drives session/send with automationId) would be a feature rather than this bug.
Workaround for clients today
Pass ZCODE_DISALLOWED_TOOLS="CronCreate CronList CronUpdate CronDelete", merged with anything else you already disallow.
Summary
In app-server mode the ZCode backend always installs its protocol automation port, so the model is offered
CronCreate,CronList,CronUpdateandCronDelete. Every one of those tools is implemented by asking the client over a server→client JSON-RPC request. zcode-acp is that client and handles none of them, so the tools are advertised but can never succeed.Observed
zcode-acp 0.37.x, ZCode desktop 3.11.2 / CLI 0.16.5. Citations below re-checked against
mainat 8f61b4a (0.38.0).CronUpdateon an existing automation id → tool errorbridge unsupported: automation/update(observed)CronDelete→bridge unsupported: automation/delete(observed)CronList→bridge unsupported: automation/list;CronCreatefails with the backend's own message "Cannot verify whether this session belongs to a scheduled task. Try again later.", because its create path first probesautomation/checkTaskBinding, swallows the -32601, falls back toautomation/list, which the bridge also rejects.With
ZCODE_ACP_DEBUGthe bridge logs⚠ unhandled server→client request: automation/<op>for each call.Root cause
src/handlers/server-requests.tshandleOne(~358–384): onlyinteraction/requestPermission,interaction/requestUserInputandinteraction/requestProviderRuntimeHeadersare handled; everything else reachessendZcodeError(backend, id, "bridge unsupported: ${method}")(-32601).grep -ri automation srcfinds no handler, only unrelated comments.zcode.cjs) exposes five client-facing methods throughcreateProtocolAutomationPort:automation/create,automation/update,automation/checkTaskBinding,automation/list,automation/delete.registerBuiltInToolsregisters the four Cron tools whenever that port exists (includeAutomation), which in app-server mode is always.automation*methods, so there is nothing for the bridge to pass through to. Automation storage and scheduling are a host capability that the desktop app provides.docs/BACKLOG.mdalready listsautomation/*under "not planned (client/config layer)", but nothing stops the backend from advertising the tools.Suggested fix (minimal)
Stop advertising tools the bridge cannot serve. In
src/backend/resolve.tsbackendArgs()(~151–153), union a built-in default ofCronCreate CronList CronUpdate CronDeletewithZCODE_DISALLOWED_TOOLSinstead of forwarding the env var verbatim.registerBuiltInToolsappliesdisallowedToolsbefore theincludeAutomationgate, so this removes the tools from the model's view entirely. Keep an opt-in (for exampleZCODE_ENABLE_AUTOMATION_TOOLS=1) for a host that does implement the port.Tests: extend
tests/resolve.test.tsfor the default argv, the env-merge case and the opt-in. Docs: theZCODE_DISALLOWED_TOOLSrow in the README and the BACKLOG note.Implementing the port (a persistent automation store under the data root plus a scheduler that drives
session/sendwithautomationId) would be a feature rather than this bug.Workaround for clients today
Pass
ZCODE_DISALLOWED_TOOLS="CronCreate CronList CronUpdate CronDelete", merged with anything else you already disallow.