Skip to content

feat(schema): prompt_version.template_messages (Plan A)#11

Merged
gaurav0107 merged 4 commits into
mainfrom
feat/playground-messages-redesign
Jun 7, 2026
Merged

feat(schema): prompt_version.template_messages (Plan A)#11
gaurav0107 merged 4 commits into
mainfrom
feat/playground-messages-redesign

Conversation

@gaurav0107

Copy link
Copy Markdown
Collaborator

Summary

Plan A of the playground messages redesign. Replaces the single-string
prompt_version.template with a structured template_messages jsonb
column. Backfill rewrites every existing row to a single-human-message
shape so production prompts keep loading unchanged.

The api response model carries both fields during one release of
back-compat; the legacy template is derived from template_messages
so old clients still work.

This PR is schema + read-path only. Plans B and C land the api
write path, the playground request shape, and the composer rewrite.

Files

  • schemas/postgres/migrations/0026_prompt_template_messages.sql — the migration
  • services/api/tracebility_api/routers/prompts.pyMessage model, PromptVersionOut extended, hydration centralized in _hydrate_version
  • services/api/tests/unit/test_prompt_response_shape.py — pydantic shape + hydration derivation tests
  • services/api/tests/integration/test_prompts_template_messages.py — live db invariants (column shape, backfill, CHECK constraint)
  • docs/superpowers/specs/2026-06-07-playground-messages-redesign-design.md — spec

Test plan

  • Local docker postgres dry-run: clean
  • Live apply on local: `COMMIT`; column added NOT NULL; backfill verified
  • `uv run pytest services/api/tests/` clean (29 unit + 3 integration)
  • CI green
  • Merge
  • Migrator job runs cleanly on next deploy (skips already-applied migrations via `schema_migrations`)

Companion docs

  • Spec: `docs/superpowers/specs/2026-06-07-playground-messages-redesign-design.md`
  • Plan: `docs/superpowers/plans/2026-06-07-playground-A-schema.md` (gitignored)

🤖 Generated with Claude Code

Captures the brainstormed design for the playground redesign:

- prompt_version.template -> template_messages jsonb (replace, with one
  release of legacy column for safe deploy/rollback)
- system + human messages only for v1; AI/tools/output_schema deferred
- Jinja {{ var }} substitution kept; no f-string selector
- single prompt panel; compare deferred to its own iteration
- save creates a new version always; "New prompt..." entry in the
  picker handles the unloaded case
- empty variables render as empty string

Spec covers schema migration, request/response contracts,
web composer rewrite, dispatcher changes, error semantics, testing
strategy, and a 4-step rollout that lets each PR land independently.

Signed-off-by: Gaurav Dubey <gauravdubey0107@gmail.com>
Signed-off-by: gaurav0107 <gauravdubey0107@gmail.com>
Replace the single-string template with a structured list of typed
messages so the playground can compose system + human turns. Backfills
every existing row to [{role: 'human', content: <old template>}],
preserving exact behavior for prompts in production. Legacy 'template'
column kept for one release as a deploy/rollback safety net.

Companion to docs/superpowers/specs/2026-06-07-playground-messages-redesign-design.md.

Signed-off-by: Gaurav Dubey <gauravdubey0107@gmail.com>
Signed-off-by: gaurav0107 <gauravdubey0107@gmail.com>
…emplate

Adds the structured Message model (system | human) and exposes both
fields on PromptVersionOut so the playground (Plan B) and the web UI
(Plan C) can read the new shape while existing clients keep seeing the
legacy single-string field. The legacy field is derived from
template_messages and is empty when the prompt has more than one
message or any system message — better than lying.

The router's hydration is centralized in _hydrate_version so the three
SELECT paths share one row->model conversion.

Companion to docs/superpowers/specs/2026-06-07-playground-messages-redesign-design.md.

Signed-off-by: gaurav0107 <gauravdubey0107@gmail.com>
Pins the post-migration invariants - column exists NOT NULL, existing
rows have the [{role: human, content: <old template>}] wrap shape, and
the check constraint refuses an empty messages array. Skips cleanly
when the local db has no prompts to inspect.

Signed-off-by: gaurav0107 <gauravdubey0107@gmail.com>
@gaurav0107 gaurav0107 merged commit 0bfd621 into main Jun 7, 2026
3 checks passed
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.

1 participant