Skip to content

feat(sync): establish prompt sync foundations - #810

Merged
ctawiah merged 1 commit into
mainfrom
ctawiah/AIC-3447/sync-foundations
Sep 28, 2026
Merged

ctawiah merged 1 commit into
mainfrom
ctawiah/AIC-3447/sync-foundations

Conversation

@ctawiah

@ctawiah ctawiah commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor

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

  • Defines resource identity, supported variation fields, validation, and stable fingerprints.
  • Reads projects, configs, and prompt variations through existing public APIs.
  • Creates, updates, and archives variations with mode-specific payloads.
  • Treats archived variations returned by the config API as absent while keeping lifecycle state out of canonical fingerprints.

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

  • Are fingerprints stable and limited to fields the public APIs round-trip?
  • Are agent and completion payloads kept separate?
  • Are archived variations correctly treated as unavailable for sync?

Verification

  • go test ./internal/sync/...
  • git diff --check

Related changes

Review the stack in this order:

  1. Sync foundations
  2. Prompt reference workspaces
  3. Prompt sync manifests
  4. Local prompt workspaces
  5. Bootstrap prompt workspaces
  6. Link and detach prompt resources
  7. Prompt reconciliation
  8. Prompt sync orchestration
  9. Prompt sync command

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/sync package adds resource identity (.launchdarkly), agent/completion Variation models, ValidateDirectAPIVariation, and FingerprintVariation (SHA-256 over API-round-trippable fields, with mode-specific prompt normalization and rejection of outputFormat).

internal/sync/api adds CatalogClient (paginated projects/configs, model configs, agent/completion-only config filter, parent mode copied onto variations, archived variations stripped on decode) and Client for read/create/update/archive via variation endpoints, with mode-specific request bodies and MutationMayHaveSucceeded for ambiguous write failures.

Reviewed by Cursor Bugbot for commit 3888fcb. Bugbot is set up for automated code reviews on this repo. Configure here.

@cursor cursor Bot 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.

Stale Bugbot comment from a previous run.

Comment thread internal/sync/api/client.go
@ctawiah
ctawiah marked this pull request as draft September 24, 2026 04:33
@ctawiah
ctawiah marked this pull request as ready for review September 24, 2026 14:50
@ctawiah
ctawiah force-pushed the ctawiah/AIC-3447/sync-foundations branch from 754405d to a48a630 Compare September 24, 2026 17:32
@ctawiah
ctawiah requested a review from a team as a code owner September 24, 2026 17:32

@cursor cursor Bot 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.

Stale Bugbot comment from a previous run.

Comment thread internal/sync/api/client.go Outdated
@ctawiah
ctawiah force-pushed the ctawiah/AIC-3447/sync-foundations branch 2 times, most recently from e4c3e85 to 7566ae9 Compare September 24, 2026 17:57
@ctawiah
ctawiah removed this pull request from stack #815 September 24, 2026 17:59
@ctawiah
ctawiah added this pull request to stack #821 September 24, 2026 17:59

@cursor cursor Bot 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.

Stale Bugbot comment from a previous run.

Comment thread internal/sync/api/catalog.go

@nieblara nieblara left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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.

@ctawiah
ctawiah force-pushed the ctawiah/AIC-3447/sync-foundations branch 3 times, most recently from de0ae97 to d289cf9 Compare September 25, 2026 16:07

@cursor cursor Bot 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.

Stale Bugbot comment from a previous run.

Comment thread internal/sync/api/client.go
@ctawiah

ctawiah commented Sep 28, 2026

Copy link
Copy Markdown
Contributor Author

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.

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.

Good callout, thank you! I’ve created a follow-up ticket to track it and address it in a focused follow-up PR.

@ctawiah
ctawiah force-pushed the ctawiah/AIC-3447/sync-foundations branch from d289cf9 to 3888fcb Compare September 28, 2026 21:35
@ctawiah
ctawiah merged commit 568dff6 into main Sep 28, 2026
10 checks passed
@ctawiah
ctawiah deleted the ctawiah/AIC-3447/sync-foundations branch September 28, 2026 21:38

@cursor cursor Bot 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.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

Reviewed by Cursor Bugbot for commit 3888fcb. Configure here.

}
if len(normalized.Messages) == 0 {
normalized.Messages = nil
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 3888fcb. Configure here.

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.

2 participants