feat: single source for the system prompt, rendered by both packages - #304
Conversation
|
Preview deployed to Connect ( Deployed from commit de92f9d. |
|
Preview deployed to Connect ( Deployed from commit de92f9d. |
758a91c to
3d0fc40
Compare
|
Cleaned up 2 preview bundle(s) on https://dogfood.team.pct.posit.it: 368317, 368362 |
|
Cleaned up 2 preview bundle(s) on https://connect.staging.pct.posit.it: 2661, 2662 |
The system prompt moves to `prompts/` at the repository root, alongside the citation request text that was a string literal in R. `scripts/sync-shared.sh` (the fixture sync, generalized) copies both into `pkg-r/inst/prompts/` and `pkg-py/src/commons/prompts/`, and `verify-shared-synced.yaml` fails when a committed copy is stale. Since the copies live inside each package directory, a prompt edit now also triggers R-CMD-check and py-check. A shared file can only have one syntax, so the template is Jinja2: Python renders it with jinja2, R with a small renderer covering the subset the template uses. Conditions are plain names, so the two compound conditions move into `system_prompt_data()`, and the citable and non-citable output lists move out of `citations.R` into the template behind one flag per tool. Both renderers are pinned to the same output by `tests/shared/prompt-render.json`, whose expected prompts are what the R implementation produced before this change.
3d0fc40 to
148333a
Compare
simonpcouch
left a comment
There was a problem hiding this comment.
Nice, thanks! Warehouse tests pass.
|
Cleaned up 3 preview bundle(s) on https://dogfood.team.pct.posit.it: 368502, 368615, 368618 |
|
Cleaned up 3 preview bundle(s) on https://connect.staging.pct.posit.it: 2664, 2673, 2677 |
This PR (the first of M5) adds the system prompt to the package sharing mechanism. Python gains prompt rendering, which it did not have before.
Summary
prompts/at the repo root holdssystem-prompt.mdandcitation-request.md, the second of which was previously a string literal in R'scitation_reminder_text().scripts/sync-shared.shgeneralizes the fixture sync to a table of source and destination pairs and copiesprompts/into both packages;verify-shared-synced.yamlreplacesverify-shared-fixtures.yamland fails on a stale copy. Because the copies sit inside each package directory, editing a prompt now also triggers R-CMD-check and py-check.The template language for the prompt is Jinja2: this is directly interpretable using
jinja2in Python, and this PR adds a small renderer in R to handle the subset of jinja the template uses.gluecould not be used as the shared syntax because its conditionals are R expressions, so a Python renderer would have to evaluate R. Jinja2's conditionals are data, and a subset this small is cheap to implement in R and to pin with fixtures.Review notes
The five expected prompts in the test fixtures are the exact text the R implementation produced before this change, so the PR is effectively behavior neutral on the R side.
Two renderers of one template is a standing divergence risk, so both implementations have a test to reject anything outside the subset instead of letting a template render in Python and fail in R.
Out of scope, as planned: Python's
system_prompt_data()and the fields that need a data source. The following files are generated from the shared data and don't need a review::pkg-r/inst/prompts/,pkg-py/src/commons/prompts/, andpkg-r/tests/testthat/fixtures/shared/.Testing
Full R suite: 7023 pass, 0 fail. Python: 920 pass, ruff and pyrefly clean. The built wheel contains
commons/prompts/.R-side summary
@simonpcouch
commons_system_prompt()keeps its signature and returns the same text as before for every input the package can build. Under it,render_system_prompt()uses a new internalrender_template()instead of glue,system_prompt_data()trades the two rendered tool-output lists for one flag per tool, andcitation_reminder_text()reads its words from the generatedinst/prompts/copy.The only reachable behaviour change is
citation_trust_exception(), which names trusted tools in a fixed order rather than registration order. That differs only for a hand-passed tool list.All of this is internal:
system_prompt_data()andrender_system_prompt()are reached only throughcommons_system_prompt(), itself called only byCommons$set_system_prompt(); both call sites ofcitation_reminder_text()get the same words; the two deleted*_tool_output_text()helpers had no other callers.The expected prompts in the shared fixture came from R as it stood before this change, and R still reproduces them exactly, with the full suite passing.