aboutsummaryrefslogtreecommitdiffstats
path: root/docs/superpowers/specs/2026-10-16-write-design.md
blob: 5ccf60029704baa2918ac373f01a3d4014b70f07 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# Write to a file: design

Date: 2026-10-16. Status: approved in brainstorming, not implemented.

## Goal

The quickshell canvas's To .md operation (quickshell repo,
`docs/superpowers/specs/2026-10-16-file-ops-design.md`) asks the model to
rewrite a PDF as Markdown and wants the reply in a file, not in the chat.
A new command does a one-off request with attachments and writes the
reply to disk.

## Protocol

In: `{"type": "write", "files": [abs paths], "prompt": "...", "dir": "<abs>",
"name": "report.md"}`.

Out, besides the usual `state`:

- `progress {chars}`: the reply's length so far, at most once a second;
- `written {path}`: the file is in place;
- `error {message, turn: true}`: refused or failed, and nothing is written.

## Behaviour

- The request is built like an `ask` (`attach()`, `wire()`, the vision
  check) but carries no history and adds nothing to the conversation or
  `history.db`; no `user` or `token` events are sent.
- Thinking is off for it: no one reads the reasoning, and it delays the
  file. No tools are offered.
- It shares the turn counter: it stops a reply in flight first, and
  `stop` ends it, hanging up on llama-server as for a reply. A stopped or
  failed write leaves no file.
- `dir` must be absolute; it is created if missing. The reply goes to a
  temporary name there and is renamed to the first free name of `name`,
  `name (1)`, `name (2)` with the suffix kept.
- `name` is taken as a base name only; a `/` in it is refused.
- A reply wrapped in one Markdown code fence (models often do) is unwrapped.

## Testing

`--test` gains: a write against the fake server streaming Markdown lands
under a free name next to an existing one, with no conversation row; a
stopped write leaves no file; a fenced reply is unwrapped; a relative `dir`
and a `name` with `/` are refused.