diff --git a/cmd/bd/formula.go b/cmd/bd/formula.go index 35bad954..f26d45a5 100644 --- a/cmd/bd/formula.go +++ b/cmd/bd/formula.go @@ -18,8 +18,8 @@ var formulaCmd = &cobra.Command{ Short: "Manage workflow formulas", Long: `Manage workflow formulas - the source layer for molecule templates. -Formulas are YAML/JSON files that define workflows with composition rules. -They are "cooked" into proto beads which can then be poured or wisped. +Formulas are JSON files (.formula.json) that define workflows with composition rules. +They are "cooked" into ephemeral protos which can then be poured or wisped. The Rig → Cook → Run lifecycle: - Rig: Compose formulas (extends, compose) diff --git a/docs/MOLECULES.md b/docs/MOLECULES.md index 4dba4cec..5e3f62b1 100644 --- a/docs/MOLECULES.md +++ b/docs/MOLECULES.md @@ -238,18 +238,49 @@ bd wisp gc # Garbage collect old wisps For reference, here's how the layers stack: ``` -Formulas (JSON compile-time macros) ← optional, for complex composition - ↓ -Protos (template issues) ← optional, for reusable patterns - ↓ -Molecules (bond, squash, burn) ← workflow operations +Formulas (.formula.json) ← SOURCE: shareable workflow definitions + ↓ cook (ephemeral) +[Protos] ← TRANSIENT: compiled templates (auto-deleted) + ↓ pour/wisp +Molecules (bond, squash, burn) ← EXECUTION: workflow operations ↓ Epics (parent-child, dependencies) ← DATA PLANE (the core) ↓ Issues (JSONL, git-backed) ← STORAGE ``` -**Most users only need the bottom two layers.** Protos and formulas are for reusable patterns and complex composition. +**Protos are ephemeral**: When you `bd pour formula-name` or `bd wisp create formula-name`, the formula is cooked into a temporary proto, used to spawn the mol/wisp, then automatically deleted. Protos are an implementation detail, not something users manage directly. + +**Most users only need the bottom two layers.** Formulas are for sharing reusable patterns. + +## Distillation: Extracting Patterns + +The lifecycle is circular - you can extract formulas from completed work: + +``` +Formulas ──cook──→ Mols/Wisps ──distill──→ Formulas +``` + +**Use cases for distillation:** +- **Emergent patterns**: Manually structured an epic that worked well +- **Modified execution**: Poured a formula but added custom steps +- **Learning from success**: Extract what made a complex mol succeed + +```bash +bd distill -o my-workflow.formula.json # Extract formula from mol +``` + +## Sharing: The Mol Mall + +All workflow sharing happens via formulas: + +```bash +bd mol publish my-workflow.formula.json # Share to GitHub repo +bd mol install github.com/org/mol-code-review # Install from GitHub +bd pour mol-code-review --var repo=myproject # Use installed formula +``` + +Formulas are clean source code: composable, versioned, parameterized. Mols contain execution-specific context and aren't shared directly. ## Commands Quick Reference diff --git a/internal/formula/types.go b/internal/formula/types.go index d7821595..ef90c445 100644 --- a/internal/formula/types.go +++ b/internal/formula/types.go @@ -249,16 +249,20 @@ type LoopSpec struct { // OnCompleteSpec defines actions triggered when a step completes (gt-8tmz.8). // Used for runtime expansion over step output (the for-each construct). // -// Example YAML: +// Example JSON: // -// step: survey-workers -// on_complete: -// for_each: output.polecats -// bond: mol-polecat-arm -// vars: -// polecat_name: "{item.name}" -// rig: "{item.rig}" -// parallel: true +// { +// "id": "survey-workers", +// "on_complete": { +// "for_each": "output.polecats", +// "bond": "mol-polecat-arm", +// "vars": { +// "polecat_name": "{item.name}", +// "rig": "{item.rig}" +// }, +// "parallel": true +// } +// } type OnCompleteSpec struct { // ForEach is the path to the iterable collection in step output. // Format: "output." or "output.."