sync-scaffold-gen
SyncScaffoldGen
Scaffold a sync rule $ARGUMENTS with trigger patterns, where-clause conditions (filter/guard/query/not), and sequential then blocks.
When to use: Use when creating a new sync rule to connect concepts. Generates a .sync file with when/where/then clauses including filter() and guard() conditions, multi-then sequential blocks, query bindings, and not() negation from trigger and effect configurations.
Design Principles
- Declarative Wiring: Syncs declare what happens when — they never contain imperative logic, loops, or conditionals beyond pattern matching.
- Concept Independence: Syncs reference concepts by name but concepts never know about syncs. The sync is the only place where concept names appear together.
- Pattern Completeness: The when clause must match specific action completions (concept/action with variant). The then clause invokes specific actions.
- Purpose Clause Quality: Every sync must have a purpose clause that explains the causal chain — 'When X happens, do Y because Z'. Never just restate the sync name or omit the purpose entirely.
Step-by-Step Process
Step 1: Register Generator
Self-register with PluginRegistry so KindSystem can track SyncConfig → SyncSpec transformations. Registration is also handled automatically by register-generator-kinds.sync.
Examples: Register the sync scaffold generator
const result = await syncScaffoldGenHandler.register({}, storage);
Step 2: Preview Changes
Dry-run the generation using Emitter content-addressing to classify each output file as new, changed, or unchanged. No files are written.
Arguments: $0 name (string), $1 trigger (trigger), $2 conditions (condition[]), $3 effects (effect[]), $4 thenBlocks (effect[][])
Step 3: Generate Sync Rule
Generate a well formed . sync file with when where then clauses from the provided trigger and effect configurations . Supports condition types : bind , query , any , not , compare , filter ( filter by expression ) , and guard ( boolean guard ) . Supports multiple then blocks for grouping effects ( no ordering implied ) .
Arguments: $0 name (string), $1 trigger (trigger), $2 conditions (condition[]), $3 effects (effect[]), $4 thenBlocks (effect[][])
Checklist:
- Sync name is PascalCase?
- Tier annotation matches intended behavior ([eager], [required], [recommended])?
- When clause references a valid concept/action?
- Variable bindings in where clause use ?prefix?
- Then clause references a valid concept/action?
- Purpose statement explains the causal chain?
- Where clause uses filter()/guard() for simple conditions?
- Multiple then blocks used for sequential effects?
- All files written through Emitter (not directly to disk)?
- Source provenance attached to each file?
- Generation step recorded in GenerationPlan?
Examples: Generate a simple sync
clef scaffold sync --name CreateProfile --from User/create --to Profile/init
Generate an eager sync
clef scaffold sync --name ValidateOrder --tier required --eager
Generate with filter condition
clef scaffold sync --name LargeOrderAlert --from Order/place --to Alert/send --conditions filter
Step 4: Edit the Sync Rule
Refine the generated .sync file: 1. Set the tier annotation: [eager], [required], or [recommended]. 2. Write a purpose clause explaining why this sync exists (the causal chain). 3. Define the when clause: Concept/action with input field bindings and => variant result. 4. Add where-clause conditions: bind(?expr as ?local), query(Concept/action: [...] as ?result), filter(?var = "value"), guard(?condition), any(cond1; cond2), not(cond). 5. Define one or more then clauses with effect actions and ?variable references. 6. Verify all variables used in then are bound in when or where.
References
Supporting Materials
Quick Reference
| Input | Type | Purpose |
|---|---|---|
| name | String | PascalCase sync name |
| tier | String | Sync tier (required, recommended) |
| eager | Boolean | Fire immediately (default: true) |
| trigger | Trigger | When clause (concept, action, params, variant) |
| conditions | list Condition | Where clause guards |
| effects | list Effect | Then clause actions |
Anti-Patterns
Missing or restated purpose
Sync has no purpose clause, or the purpose just restates the sync name — readers can't understand why the sync exists.
Bad:
sync CreateProfile [eager]
when { ... }
then { Profile/create: [owner: ?u] }
Good:
sync CreateProfile [eager]
purpose: "Initialize an empty profile automatically when a new user registers"
when { ... }
then { Profile/create: [owner: ?u] }
Sync with imperative logic
Sync tries to express conditionals or loops instead of pattern matching.
Bad:
# Pseudo-code in sync — not valid!
if user.isAdmin then
AdminPanel/grant: [user: ?u]
Good:
where {
bind(?meta.role as ?role)
any(?role = "admin")
}
then {
AdminPanel/grant: [user: ?u]
}
Validation
Generate a sync scaffold:
npx tsx cli/src/index.ts scaffold sync --name CreateProfile --from User/create --to Profile/init
Validate generated sync:
npx tsx cli/src/index.ts sync validate syncs/create-profile.sync
Run scaffold generator tests:
npx vitest run tests/scaffold-generators.test.ts
Related Skills
| Skill | When to Use |
|---|---|
/sync-designer |
Design syncs using formal patterns before generating |
/create-concept |
Generate concept specs referenced by the sync |
/sync-validator |
Validate compiled syncs |