Skip to content

feat(sync): integrate repository sources with planning and link - #995

Merged
ctawiah merged 1 commit into
mainfrom
ctawiah/sync-source-planner-3bbf
Nov 10, 2026
Merged

ctawiah merged 1 commit into
mainfrom
ctawiah/sync-source-planner-3bbf

Conversation

@ctawiah

@ctawiah ctawiah commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

Context

The planner must compare repository projections with LaunchDarkly and the baseline, enforce the sync setting of each resource, and run the link workflow.

What changes

  • Plan descriptor-backed variations, tools, and skills with the same three-way comparison as managed files.
  • Convert each source prompt to the mode of its config in one place.
  • Read and enforce the LaunchDarkly sync setting of every linked resource. A row that the setting decides says so in its reason.
  • Send pulls through checked source publication, one document group at a time.
  • Run the link workflow: preview the descriptor and the plan, write the descriptor after the review, then sync the resource.

Design notes

  • Conflict granularity is one resource.
  • A resource that a link rebinds is not blocked by its stale baseline, because the user reviews the new mapping in the same command.

Review focus

  • Can one field sync when another field is read-only?
  • Is the sync setting checked before every write?

Verification

  • make build
  • go test ./...
  • golangci-lint run ./...

Related changes

  1. refactor(sync): remove Phase 1 source references #1005: Phase 1 reference removal
  2. feat(sync): add projection and problem core #987: projection and problem core
  3. feat(sync): add the adapter core and the Markdown adapter #988: adapter core and Markdown
  4. feat(sync): add the structured document adapters #989: structured adapters
  5. feat(sync): add the Python adapter #991: Python adapter
  6. feat(sync): add the TypeScript and JavaScript adapters #992: TypeScript and JavaScript adapters
  7. feat(sync): add source descriptor storage #993: descriptor storage
  8. feat(sync): compile and publish repository sources #994: compile and publish
  9. feat(sync): detach descriptor-backed sources #1003: descriptor detach
  10. feat(sync): prepare repository source links #997: link preparation
  11. This PR: planning and link
  12. feat(sync): add the link commands #998: link commands

🤖 Generated with Claude Code


Note

Overview
Adds LaunchDarkly sync settings lookup (SyncDirections on the API client) and threads code/server-canonical direction through planning so linked variations, tools, and skills use projection-based three-way comparison instead of whole-file fingerprints.

Introduces SourceLinkAction to create .ref.yaml descriptors and run a scoped sync: validate the mapping, preview the plan (with confirmation / --yes), write the descriptor after review, then reconcile while keeping user source files in place.

Execution is reworked for descriptor-backed resources: pulls edit sources via atomic document groups (ReplaceSources, shared-file grouping, pre-write validation), pushes merge mapped fields onto the latest LaunchDarkly copy with post-review drift checks, handle read-only mapped fields and indexed selection changes, and coordinate linked tool/skill rows with sync settings during variation pushes and conflict resolution.

Plan/outcome JSON now includes source metadata and structured problem codes; manifest/lock recording stores adapter behavior, mapping digests, and projection fingerprints.

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

@ctawiah
ctawiah added this pull request to stack #1000 October 30, 2026 20:15
@ctawiah
ctawiah force-pushed the ctawiah/sync-source-planner-3bbf branch 2 times, most recently from 3fdb247 to ff510c9 Compare November 2, 2026 02:26
@ctawiah
ctawiah force-pushed the ctawiah/sync-source-planner-3bbf branch from ff510c9 to ccc230e Compare November 2, 2026 02:50
@ctawiah
ctawiah force-pushed the ctawiah/sync-source-planner-3bbf branch from ccc230e to 498b3bc Compare November 3, 2026 00:29
@ctawiah ctawiah changed the title feat(sync): integrate repository sources with planning feat(sync): integrate repository sources with planning and link Nov 3, 2026
@ctawiah
ctawiah removed this pull request from stack #1000 November 3, 2026 00:32
@ctawiah
ctawiah changed the base branch from ctawiah/sync-source-publication-3bbf to ctawiah/sync-link-preparation-3bbf November 3, 2026 00:34
@ctawiah
ctawiah added this pull request to stack #1004 November 3, 2026 00:34
@ctawiah
ctawiah removed this pull request from stack #1004 November 3, 2026 00:53
@ctawiah
ctawiah added this pull request to stack #1006 November 3, 2026 00:53
@ctawiah
ctawiah force-pushed the ctawiah/sync-source-planner-3bbf branch from 498b3bc to 57e4d36 Compare November 4, 2026 19:46
@ctawiah
ctawiah force-pushed the ctawiah/sync-source-planner-3bbf branch from 57e4d36 to 987f4ff Compare November 4, 2026 21:54

@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/prompt/sync.go Resolved

@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/prompt/plan.go Resolved

@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/settings.go Resolved
Comment thread internal/sync/prompt/execute.go Resolved

@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/prompt/plan.go Resolved

@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/prompt/execute.go Resolved

@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/prompt/state.go Resolved

@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/prompt/execute.go Resolved

@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/prompt/state.go Resolved

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

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

@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/prompt/sync.go Resolved

@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/prompt/execute.go Resolved
Comment thread internal/sync/prompt/plan.go Resolved

@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/prompt/plan.go Resolved

@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/prompt/plan.go Resolved

@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/prompt/state.go Resolved

@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/prompt/execute.go Resolved

@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/prompt/execute.go Resolved

@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/prompt/execute.go Resolved

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

@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/prompt/plan.go Resolved

@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/prompt/state.go Resolved

@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/prompt/execute.go Resolved

@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/prompt/state.go Resolved

@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/prompt/execute.go Resolved

@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/prompt/execute.go Resolved
assert.Len(t, directions, syncSettingsPageLimit)
require.Len(t, transport.Requests, 2, "a full page without a total count is followed by a request for the next page")
assert.Equal(t, []string{"100"}, transport.Requests[1].Query["offset"])
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

When a single GET to the sync settings endpoint asks for both a variation and a tool, we return a '400 unsupported resource kind' and the whole call fails, variation included. The test below is currently failing.

Should we even be supporting both tools and skills here, or should the client only send variations? If this is intended behavior lmk and I can stamp!

Suggested change
}
}
func TestSyncDirectionsAsksOnlyForVariationSettings(t *testing.T) {
transport := &recordingClient{Responses: [][]byte{[]byte(`{"items": [
{"resourceKind":"variation","resourceLookupKey":"support/default","direction":"both"}
]}`)}}
client := NewClient(transport, "token", "https://example.com")
variation := syncdomain.VariationID("project", "support", "default")
tool := syncdomain.ResourceID{Kind: syncdomain.KindTool, ProjectKey: "project", LookupKey: "search"}
_, err := client.SyncDirections("project", []syncdomain.ResourceID{variation, tool})
require.NoError(t, err)
require.Len(t, transport.Requests, 1)
for _, resource := range transport.Requests[0].Query["resources"] {
assert.True(t, strings.HasPrefix(resource, "variation:"), "gonfalon answers 400 unsupported resource kind to %q", resource)
}
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thank you, that was a real failure: one 400 for the tool took the variations down with it. SyncDirections now asks for each resource kind in a request of its own, so a variation request never carries a tool or a skill. A kind that LaunchDarkly answers with 400 unsupported resource kind has no settings, and any other 400 still fails the call. A linked tool or skill without a setting then gets the existing sync_setting_unavailable problem, which says that LaunchDarkly does not provide that setting yet and suggests detach, so the variations of a plan sync and the tool or skill is blocked rather than guessed. That keeps the client ready for the day the endpoint supports tools and skills, and the acceptance tests that fake those settings still hold. TestSyncDirectionsAsksForEachKindAlone and TestSyncDirectionsTreatsAnUnsupportedKindAsHavingNoSetting cover it. One open question for you: do you want a linked tool or skill to sync as both until LaunchDarkly has a setting for it, instead of the block? That is a one-line change in applySourceDirections and I will make it if you prefer it.

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

@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 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 00ffbf4. Configure here.

Comment thread internal/sync/prompt/state.go Resolved
Comment thread internal/sync/prompt/execute.go Resolved
Plan descriptor-backed variations, tools, and skills with the same three-way comparison as managed files. Convert each source prompt to the mode of its config once. Enforce the LaunchDarkly sync setting of every linked resource. Run the link workflow: preview the descriptor and the plan, write the descriptor after the review, and sync the resource.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
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