feat(sync): establish prompt sync foundations - #810
Conversation
754405d to
a48a630
Compare
e4c3e85 to
7566ae9
Compare
nieblara
left a comment
There was a problem hiding this comment.
COOL!!!! Seems like everything downstream assumes that the same content produces the same fingerprint, so it might be nice to have some sort of round-trip test that pins that down. Take a realistic server variation, render it to a .prompt.md, compile it back, and check that the fingerprint matches the server's.
Some fixture cases that came to mind:
- UI-authored text with leading or trailing whitespace
- model responses that come back with defaulted parameters: {} / custom: {}
- numeric params that show up as 1 and then turn into 1.0
I think as it is right now any of these can make a clean sync look like it changed. Seems like the #813 bugbot finding is related to this.
We can ask an agent to update this so that it can either:
- Normalize inside FingerprintVariation. Trim the content, drop empty nested maps, and canonicalize numbers so both sides hash the same.
- Keep the fingerprint strict and make the file writer preserve content exactly, which means the renderer stops trimming. The upside here is that an intended whitespace or model-param change can't get reported as "in sync."
looks good to me otherwise though! we can always follow up with this in a future pr if its easier.
de0ae97 to
d289cf9
Compare
Good callout, thank you! I’ve created a follow-up ticket to track it and address it in a focused follow-up PR. |
d289cf9 to
3888fcb
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
Reviewed by Cursor Bugbot for commit 3888fcb. Configure here.
| } | ||
| if len(normalized.Messages) == 0 { | ||
| normalized.Messages = nil | ||
| } |
There was a problem hiding this comment.
Fingerprints miss defaulted model maps
Medium Severity
FingerprintVariation only collapses an empty top-level model. It still treats defaulted nested parameters and custom objects as real content, so the same variation can hash differently after a server round-trip or after VariationModel fills those objects in. Later sync layers that assume identical content yields the same fingerprint would then plan false updates.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 3888fcb. Configure here.


Context
This stack adds a Git-based workflow for synchronizing LaunchDarkly prompt variations with repository files. This first layer defines the shared domain and direct API behavior; it does not create local files or expose a command.
What changes
The canonical shape passed to later layers is complete rather than patch-based:
{ "mode": "completion", "key": "default", "name": "Default support prompt", "messages": [{"role": "system", "content": "Be concise and helpful."}] }Review focus
Verification
go test ./internal/sync/...git diff --checkRelated changes
Review the stack in this order:
Note
Overview
Introduces the first layer of Git-based prompt variation sync: shared domain types and HTTP clients that talk to existing LaunchDarkly AI config APIs (no CLI or local files yet).
The
internal/syncpackage adds resource identity (.launchdarkly), agent/completionVariationmodels,ValidateDirectAPIVariation, andFingerprintVariation(SHA-256 over API-round-trippable fields, with mode-specific prompt normalization and rejection ofoutputFormat).internal/sync/apiaddsCatalogClient(paginated projects/configs, model configs, agent/completion-only config filter, parent mode copied onto variations, archived variations stripped on decode) andClientfor read/create/update/archive via variation endpoints, with mode-specific request bodies andMutationMayHaveSucceededfor ambiguous write failures.Reviewed by Cursor Bugbot for commit 3888fcb. Bugbot is set up for automated code reviews on this repo. Configure here.