L3 Academy

Module 4: The Sync Engine

Understand how L3 distributes managed files across all repos.

Estimated time: 15 minutes

What Gets Synced

The Distribution Engine ensures every registered repo has the same standardized set of workflows, skills, and configurations. Here's the full list of managed files:

Global Scope (distributed to every repo)

FilePurpose
claude-code.ymlFull Claude Code implementation workflow
claude-code-plan.ymlClaude planning-only workflow
assign-linear-project.ymlLinear project verification on issue creation
standardize-issue.ymlAuto-standardize new issues via Claude
l3-lifecycle skillLifecycle states, labels, GitFlow conventions
linear-issue-routing skillRules for creating and routing Linear issues
settings.jsonClaude Code permissions and plugin config
.claudeignoreFiles Claude should ignore
husky/pre-commitGit pre-commit hook

Optional Scope (only for repos that include them)

FilePurposeUsed By
fe-vite-project skillFrontend project conventionsdata-intel-fe, kv-internal-crm-fe, compass-fe
process-meetings skillMeeting processing conventionsRepos that handle meeting data

How Scope Resolution Works

When the sync engine runs for a given repo, it resolves which files to distribute using this algorithm:

  1. If the repo has an explicit files: key — use only those files (full override, bypasses scope logic)
  2. Otherwise:
    • Start with all scope: global files
    • Remove any keys in the repo's exclude: list
    • Add any keys in the repo's include: list (must be scope: optional)
  3. Cleanup: Any managed file already present in the target repo that is NOT in the resolved set gets deleted

For example, greylockit/data-intel-fe has include: ["fe-vite-project"], so it receives all 9 global files plus the frontend skill. A backend repo with no include gets only the 9 global files.

How Sync Runs

The sync engine is a shell script (.ops/sync.sh) that can be run:

.ops/sync.sh                       # sync all repos
.ops/sync.sh --repo org/name       # sync a single repo
.ops/sync.sh --dry-run             # show what would happen

Per-Repo Process

For each registered repo (except l3-platform itself, which has sync: false):

  1. Resolve the file list using the scope algorithm
  2. Select the correct GitHub token (GH_TOKEN_KV for Khosla repos, GH_TOKEN_GENERAL for everything else)
  3. Shallow-clone the target repo (gh repo clone --depth 1)
  4. Copy all resolved source files from .ops/ into the clone
  5. Delete any managed files that aren't in the resolved set
  6. Generate .github/linear-project.json from the repo's Linear config in sync.yml
  7. Commit as l3-platform[bot] with message: chore(ops): sync managed files from l3-platform
  8. Push strategy:
    • First attempt: direct push to main
    • If rejected (branch protection): create a timestamped branch ops-sync/YYYYMMDD-HHMMSS, push it, and open a PR
    • If a dev branch exists, also push there directly
  9. Apply branch protection rulesets via the GitHub API
  10. Set delete_branch_on_merge=true on the repo

Automatic Trigger

The ops-sync.yml workflow runs sync.sh automatically on any push to main that touches .ops/. It also supports manual runs via workflow_dispatch with dry-run and single-repo targeting options.

Branch Protection Rulesets

The sync engine applies two rulesets to every registered repo:

Ruleset 1: Branch Protection

  • Protects main and dev branches
  • Prevents deletion and force pushes
  • Requires PRs (but 0 approving reviews required)
  • Only repo admins can bypass

Ruleset 2: Branch Naming

Enforces a naming convention for all branches (except main, dev, develop, staging):

^(feature|bugfix|hotfix|spike)/[A-Za-z0-9]+-.*$
^release/[0-9]+\.[0-9]+\.[0-9]+.*$
^ops-sync/.*$

This means branches must follow patterns like feature/PL-42-add-auth or bugfix/GL-58-fix-dates. The ops-sync/* pattern whitelists the sync engine's own branches.

First-Time Setup: install.sh

For new repos not yet receiving synced files, .ops/install.sh handles the bootstrap:

  • Installs a core set of workflows, skills, and configs
  • Generates linear-project.json from the repo's Linear team config
  • Can run locally (--repo org/name) or remotely via curl from GitHub

For developer onboarding, install.sh --dev-setup ensures you have yq and gh installed and guides you through setting up the superpowers Claude Code plugin.

Check Your Understanding

What's the difference between 'global' and 'optional' scope?
What happens when the sync engine's direct push to main is rejected?

Checkpoints

I've read through sync.yml and identified the managed files
I understand the difference between global and optional scope
I've found the branch naming regex in sync.yml

Module Assessment

Module Assessment

1. Where is the canonical source for a managed workflow like claude-code.yml?

2. What does the sync engine do with managed files that are no longer in a repo's resolved set?

3. Which repos receive the 'fe-vite-project' skill?

4. What file does the sync engine generate (not copy) per repo?