feat(agents): implement blit agents sync write path#15
Conversation
Add the full `blit agents sync` write path alongside the existing `--check` read mode. Sync regenerates the installed kit's agent files in memory, then applies the 4.10 ownership model: kit-owned files are overwritten when unmodified, shared files (AGENTS.md, CLAUDE.md) have only their managed region rewritten, and user-edited kit-owned files are three-way merged via `git merge-file` with a `<file>.new` fallback when git is unavailable or the merge conflicts. The manifest and pristine `.blit/base/` copies are refreshed afterward, and `--force [path...]` restores the kit version on demand. To regenerate deterministically regardless of environment, the scaffolder now records the scaffold-time template vars in the manifest (BlitManifest.vars), and the adapter generation is ported into a new generate-to-memory module (packages/kit/src/adapters.ts) that stays byte-identical to the scaffolder's adapters. The Cursor adapter config now lists the generated `.cursor/hooks/` script in its emits. Add four sync tests (clean Claude + Cursor parity, --force restore, CLAUDE.md managed-region merge preserving a user note); 15/15 pass. Assisted-by: Claude Opus 4.8 Signed-off-by: Vaclav Vancura <commit@vancura.dev>
|
Warning Review limit reached
More reviews will be available in 1 hour, 43 minutes, and 38 seconds. Learn how PR review limits work. Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file). ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
WalkthroughThis PR implements deterministic ChangesManifest-driven sync regeneration
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
@coderabbitai review |
✅ Action performedReview finished.
|
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/kit/src/commands/agents.ts`:
- Around line 227-230: regenerate currently computes vars = manifest.vars ??
fallbackVars(root) but never persists those fallbacked values back into the
manifest, so projects without pre-existing vars keep being re-detected on each
sync; update regenerate to assign the resolved vars back to manifest.vars when
manifest.vars was originally undefined (e.g., if (!manifest.vars) manifest.vars
= vars) and ensure the downstream refresh/write logic (the same sync path that
previously only wrote when manifest.vars existed) always writes the updated
manifest so the persisted manifest contains the resolved vars.
- Around line 473-491: The manifest rewrite currently records orphaned paths in
tally.orphaned but never removes them from entryByPath, so stale entries get
written back; before constructing refreshed (and before writeFileSync), remove
those orphaned entries from entryByPath: collect orphaned paths exactly as you
do now (using manifest.files, entry.class === 'user-owned' and
regenerated.has(entry.path')), push them to tally.orphaned, then for each
orphaned path call entryByPath.delete(path) so the subsequent refreshed.files
(built from entryByPath.values()) no longer includes stale entries; keep the
existing logic that preserves manifest.createdAt and manifest.vars when writing
the refreshed manifest.
- Around line 451-462: The code is promoting the user-merged content (merged)
into the kit baseline by calling writeBase(...) and setting entry.sha256 from
merged; instead preserve the refreshed kit/generated content as the new base and
hash instead of the merged result: after a successful gitThreeWayMerge(onDisk,
basePath, incoming) where merged !== null, call writeBase(root, relPath,
incoming) and set entry.sha256 = sha256Text(incoming) (so the
kit-generated/ancestor state remains the baseline). If you still need to record
the user-accepted merge result, add a separate field (e.g., entry.acceptedSha256
= sha256Text(merged)) rather than overwriting the generated baseline; keep
writeRel(root, relPath, merged) and tally.merged.push(relPath) as-is.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 749e3548-ef03-4d3e-b430-13b96a5835aa
📒 Files selected for processing (6)
packages/create-blit-tech/src/index.tspackages/create-blit-tech/src/scaffold.tspackages/create-blit-tech/test/scaffold.test.mjspackages/kit/content/agents.config.jsonpackages/kit/src/adapters.tspackages/kit/src/commands/agents.ts
…tence Three fixes to the `blit agents sync` write path: - Kit-owned clean merges now keep the kit-generated version as the base and sha256 baseline instead of the merged result. Recording the merged file (which carries the user's edits) as the baseline made the next sync treat those edits as the kit default and overwrite them. - Orphaned manifest entries (files the new kit no longer ships) are now removed from the tracked set, so the refreshed manifest stops carrying stale entries. - Resolved fallback template vars are written back onto the manifest the first time they are detected, so a project scaffolded before vars were tracked stops re-detecting the package manager on every sync. Assisted-by: Claude Opus 4.8 Signed-off-by: Vaclav Vancura <commit@vancura.dev>
Add the full
blit agents syncwrite path alongside the existing--checkread mode. Sync regenerates the installed kit's agent files in memory, then applies the 4.10 ownership model: kit-owned files are overwritten when unmodified, shared files (AGENTS.md, CLAUDE.md) have only their managed region rewritten, and user-edited kit-owned files are three-way merged viagit merge-filewith a<file>.newfallback when git is unavailable or the merge conflicts. The manifest and pristine.blit/base/copies are refreshed afterward, and--force [path...]restores the kit version on demand.To regenerate deterministically regardless of environment, the scaffolder now records the scaffold-time template vars in the manifest (BlitManifest.vars), and the adapter generation is ported into a new generate-to-memory module (packages/kit/src/adapters.ts) that stays byte-identical to the scaffolder's adapters. The Cursor adapter config now lists the generated
.cursor/hooks/script in its emits.Add four sync tests (clean Claude + Cursor parity, --force restore, CLAUDE.md managed-region merge preserving a user note); 15/15 pass.
Overview
This pull request implements the complete "blit agents sync" write path, enabling deterministic regeneration and application of kit-managed agent files with support for the 4.10 ownership model. Previously, the sync feature only supported read-only checking. Now it includes full regeneration logic, conflict resolution for user-edited files, and a
--forceoption to restore kit-owned content on demand.Key Changes
Manifest Enhancement
BlitManifestnow includes avars: Record<string, string>field that captures template variables at scaffold time. These variables are essential for deterministic regeneration during sync operations, ensuring that regenerated files remain byte-identical to the original scaffold output.New Adapter Generation Module
A new
packages/kit/src/adapters.tsmodule provides in-memory generation functions for kit adapter files, replacing the need for shell-based generation during sync. This module includes:generateClaudeAdapter()- ProducesCLAUDE.mdwith managed-region markers for content that can be updated without losing user edits outside the marked regiongenerateCursorAdapter()- Generates.cursor/rules/*.mdcfiles from kit rules and skillscollectDocs()andagentsFile()- Handle documentation and agent file collectionreplaceManagedRegion()- Intelligently updates shared files by only rewriting managed sections, preserving user additions elsewhereSync Command Expansion
packages/kit/src/commands/agents.tsnow implements the full sync workflow (runFullSync):<file>.newfile for manual review--force [path...]option to selectively restore kit versionsTest Coverage
Four new integration tests verify critical sync behaviors:
agents sync(and subsequent--checkpasses)--forceproperly restores kit-managed content and clears driftConfiguration Updates
The Cursor adapter configuration now explicitly lists the generated
.cursor/hooks/script in itsemitsfield, documenting the full set of generated artifacts.Test Results
All 15 tests pass, including the 4 new sync-specific tests covering clean scaffold parity, force restoration, and managed-region preservation.