Skip to content

feat(composer): configurable prompt enhancement with a substantive default prompt - #601

Merged
vastsa merged 6 commits into
mainfrom
merge/pr-586
Sep 18, 2026
Merged

vastsa merged 6 commits into
mainfrom
merge/pr-586

Conversation

@vastsa

@vastsa vastsa commented Sep 18, 2026

Copy link
Copy Markdown
Owner

Lands #586 (panda-z519) onto current main, plus review follow-ups.

From #586

Configurable Composer Enhance prompt: custom user template, enhancement model/reasoning on Settings → Models, 60s request bound, rewritten default prompt.

Review follow-ups

  • Abort the in-flight one-shot on timeout (not just race the promise)
  • Drop the 800-character hard cap; keep the ~2× length brake
  • Stop few-shot Enhanced: labels leaking into the Composer
  • Keep a stale pin visible; no-reasoning models still show Off
  • Restore the zh-CN Voice settings-IA bullet

Does not close #562 (plugin UI hook for the enhance button is still open).

zhangsiqiang and others added 6 commits September 18, 2026 17:46
The old prompt asked for a "clearer, more concise" draft and returned it with
"at most minor polish" when it looked fine, which made the action read as inert
and left the rewrite weak. Replace it with the structure mature coding
assistants use for the same job: role, analysis, rewrite principles, an explicit
do-not list, language-following rules, a length brake, and an output contract.

Two constraints the old text lacked are now explicit. Code, commands, file
paths, identifiers, API names, and other proper nouns are reproduced exactly, so
a rewrite cannot corrupt a draft's technical content. The answer carries no
language meta note such as "The draft is in Chinese".

The user side becomes a template: the draft is injected at a {{draft}}
placeholder inside <draft> tags, with few-shot examples for Chinese, English,
mixed-language input, and the meta-note failure mode. Substitution uses
split/join, so a draft containing $&, $', $` or $1 is inserted literally instead
of expanding as a String.replace pattern, and every occurrence is replaced. One
matching pair of wrapping quotation marks is stripped from the answer.

The defaults live in @pi-desktop/shared so the runtime, the settings UI, and the
restore-default action read one copy; the runtime keeps its existing export
names.
…onfigurable

Issue #562 asks for a way to customize the prompt behind the Composer's Enhance
prompt action. Three surfaces change, each next to the thing it configures.

The prompt card on AI settings carries a switch, `Use a custom template`, and
the settings icon button the subagent rows use for editing, which opens an
editor sheet. The sheet holds only the user template and saves on Save, so
closing it abandons the edit. The switch is the gate, not the text: it is
disabled until a usable template exists, turning on when one is saved, and
turning it off keeps the stored text so turning it back on restores it. Editing
the field back to the exact built-in default clears the override rather than
storing a frozen copy, so a later improvement to the default still reaches users
who never customized it. An insert action writes the draft variable at the
caret, and a save that would leave the template without it is refused locally.

host-core enforces the same rules for any writer: a non-blank user template must
contain {{draft}}, each value is bounded by PROMPT_ENHANCEMENT_TEMPLATE_MAX_LENGTH,
a blank value is stored as absent rather than as an empty string, and a stored
system-prompt override is dropped. The system prompt stays built in because it
carries the contract the spec and E2E scenario assert; a stored override could
silently remove a rule.

The enhancement model and its reasoning effort get their own card on the Model
configuration page, because both are model decisions and the model picker needs
a title and a current value rather than a bare control. The model row reuses the
default-model row's anchored, searchable menu, so the page shows one kind of
picker. An unresolvable pin falls back to the Composer's current model with a
warning: a stale pin must not disable the action. The reasoning row lists the
levels the selected model actually supports, resolved exactly as a turn resolves
them (binding thinkingLevels, then the live catalog, then the provider default),
is disabled when the model supports none, defaults to off, and offers no
follow-the-session entry. Changing model re-clamps and rewrites the stored level,
so a persisted level is always runnable.

One request is now bounded by a 60-second ceiling. The transport only consults
its abort signal between provider retries, so aborting alone cannot release a
stalled call; the handler races the promise to guarantee the caller is freed,
and reports TIMEOUT with the budget rather than retrying on another model, which
would double the wait.

The prompt/enhance payload, process boundaries, and storage ownership are
unchanged. The eight shipped catalogs carry the new copy, and settings search
indexes the new rows.
Revise ADR 0121 rather than adding a second ADR: the one-shot, main-owned
decision stands, so only the prompt shape, the settings surfaces, and the model
pin change. Record the rejected alternatives, including letting the user
override the system prompt (it would let a stored value silently violate a
contract the spec and E2E scenario assert), storing the default text as the
user's value (a later improvement to the default would then never reach those
users), and failing when a pinned model is unresolvable (a stale pin would
disable the action long after the user forgot the choice).

Add D447 for the default-value decisions: the substantive-rewrite orientation,
the proper-noun and no-meta-note rules, the switch semantics, the model page
split, and the model-aware reasoning ladder.

Update the UX spec (request boundary, and the user template, model, and
reasoning sections) with its zh-CN mirror, plus the settings IA and
data-storage specs and their mirrors. Extend E2E-218 and add E2E-259 for the
switch, sheet, restore, validation, timeout, language, proper-noun, and
quote-stripping contract, and refresh the traceability matrix.
Review of PR #586: abort the in-flight one-shot on the 60s ceiling so
retries cannot keep burning tokens, drop the hard 800-character rewrite
limit, stop few-shot labels from leaking into the Composer, keep a stale
pin visible, and restore the zh-CN Voice settings-IA bullet.
Copilot AI lite review requested due to automatic review settings September 18, 2026 13:47

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@vastsa
vastsa merged commit ef594f2 into main Sep 18, 2026
1 of 4 checks passed
@vastsa
vastsa deleted the merge/pr-586 branch September 21, 2026 11:16

This branch was successfully deployed

1 active deployment
Preview — bcebf92a Deployed Sep 18, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]

2 participants