sysprompt: remind claude of the output style on every turn - #1
Merged
Conversation
bubbles' textarea caps content at MaxHeight (default 99) and truncates a longer paste in silence. newPromptArea already cleared CharLimit but left MaxHeight, so a paste over 99 lines lost its tail with no message. The display height is computed separately by syncPromptHeight and capped at maxPromptRows, so the content cap buys nothing. Clear it.
The output style delivers the user's standing instructions and the delivery was never in doubt: the text is visible in claude's system prompt and the init line names the resolved style. Adherence was the part that failed. claude's harness appends its own response-shaping sections after the output style, so the style stops holding the last word and the built-in guidance wins on length and format. Take the last word back with the one lever that is ours at runtime. The system prompt is fixed at launch, but every turn is composed here, so sendTurn now appends a two-line reminder after the prompt, where recency favours it. The reminder is not the user's words, so it rides in a <cathode-reminder> tag: the transcript shows the typed text, and replay strips a trailing block back out on resume. It is skipped for anything starting with "/", because a forwarded slash command is an argument list and appending prose to /compact rewrites its arguments. The default says nothing about what to write, only which instructions govern, because that is the actual failure and cathode does not know which of the user's rules matter. A prompt needing other wording marks its own block with <!-- reminder --> … <!-- /reminder -->. Give "is a style loaded" one owner while adding its second consumer. sysPromptArgs already wrote the style file and composed the flag, but newModel re-derived the same fact by reading the prompt file from the setting. Those answer different questions and part company when writing the style file fails: main starts without the flag, yet sysPromptSeen was still set. Harmless while the only consumer was the edited-file check, not harmless once a reminder fires every turn about a style claude never loaded. sysPromptArgs now returns the text its flag selects and main hands it to newModel.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
/syspromptdelivered the user's standing instructions but did not change the replies. Delivery was never the problem: the style text is visible in claude's system prompt, and thesystem/initline names the style it resolved. Adherence was.claude's harness appends its own response-shaping sections after the output style. The style stops holding the last word, and the built-in guidance wins on length and format.
What
The system prompt is fixed at launch, but every turn is composed here.
sendTurnnow appends a two-line reminder after the user's text, where recency favours it.<cathode-reminder>. The transcript shows the typed text, andreplay.gostrips a trailing block back out on resume./compactrewrites its arguments. Load-bearing, not defensive:pickerkeys.goandmcp.goboth send commands throughsendTurn.<!-- reminder -->…<!-- /reminder -->.One owner for "is a style loaded"
Adding a second consumer surfaced a latent split.
sysPromptArgswrote the style file and composed the flag;newModelre-derived the same fact by reading the prompt file from the setting. Those answer different questions and part company when writing the style file fails:mainstarts without the flag, yetsysPromptSeenwas still set.Harmless while the only consumer was the edited-file check. Not harmless once a reminder fires every turn about a style claude never loaded.
sysPromptArgsnow returns the text its flag selects andmainhands it tonewModel.Tests
remind_test.gocovers the gate, the slash-command skip, the marked-block override with both malformed cases, the strip round trip, and text that quotes the tag.TestSysPromptArgsReportsNothingAppliedWhenTheStyleFileFailspins the invariant above. Full suite green,go vetclean.Not verified
Unit-tested only. I have not watched the reminder work in a live session — that needs a rebuilt binary and a fresh instance.