| name | programming-inference |
| description | Transform raw Programming/Movement Source Sheet rows into Rubicon's programming write operations (create_node, patch_node, create_edge, patch_edge), applying conjugate-method coaching conventions and resolving movement IDs via movement_catalog_search. Use this as stage 2 of the Rubicon programming pipeline, after sheet-read and before preview. |
Programming Inference
Stage 2 of 4 in the Rubicon coach programming pipeline:
sheet-read → programming-inference → preview → publish
Input: raw rows from the Programming Source Sheet and/or Movement Source
Sheet (from the sheet-read skill). Output: a batch of Rubicon programming
write operations — nothing is sent to Rubicon yet. That happens in
preview (dry run) and publish (real write), which come after this skill.
Operation shapes
These are the real operation shapes accepted by Rubicon's Coach MCP Surface
write tools (programming_write_dry_run / programming_write_publish).
Copy them exactly — do not invent additional fields or rename these.
create_node
{
kind: "create_node",
nodeId: string,
type:
| "program"
| "track"
| "session"
| "wod"
| "block"
| "movement"
| "movement_variant"
| "benchmark"
| "collection",
title: string,
status: "draft" | "published" | "archived",
format:
| "for_load"
| "for_reps"
| "for_time"
| "rounds_reps"
| "emom"
| "amrap"
| "interval"
| "checklist"
| "text"
| null,
scoreFormat:
| "load"
| "reps"
| "time"
| "rounds_reps"
| "calories"
| "distance"
| "points"
| "checkbox"
| "text"
| null,
payload: unknown,
sessionDate: string | null,
slug: string,
sourceId: string,
sourceTable: string,
trackId: string,
weekNumber: number,
}
patch_node
{
kind: "patch_node",
nodeId: string,
patch: Partial<Omit<CreateNodeOp, "kind" | "type" | "nodeId">>,
}
create_edge
{
kind: "create_edge",
edgeId: string,
parentNodeId: string,
childNodeId: string,
position: number,
role:
| "contains"
| "variant_of"
| "source_movement"
| "canonical_movement"
| "max_effort"
| "dynamic_effort"
| "repetition_effort"
| "accessory"
| "conditioning"
| "warm_up"
| "activation"
| "individual_prep"
| "skill"
| "finisher"
| "recovery"
| "test",
metadata: unknown,
}
patch_edge
{
kind: "patch_edge",
edgeId: string,
patch: Partial<Omit<CreateEdgeOp, "kind" | "edgeId">>,
}
Batching rule
Max 25 operations per write call. This is enforced server-side by the
Coach MCP Surface, not a suggestion. If a sheet import produces more than 25
operations, split it into multiple sequential batches (e.g. by week, by
session, or by track), and run each batch through its own
preview → publish cycle rather than trying to push everything at once.
Tell the coach how you split it and why.
Resolving movement IDs — never guess
Before building a create_edge with role source_movement,
canonical_movement, max_effort, dynamic_effort, repetition_effort,
accessory, conditioning, warm_up, activation, individual_prep,
skill, finisher, recovery, or test that points at a movement, call
the movement_catalog_search MCP tool (Coach MCP Surface) to resolve the
canonical movement nodeId. This tool may be new / still being built in
parallel with this plugin — reference it by name and treat "tool not found"
as a signal to stop and tell the coach, not as license to fabricate a
nodeId. Never guess or hand-roll a movement nodeId from the sheet text.
Typical flow per movement mentioned in a sheet row:
- Extract the movement name/variant as written in the sheet.
- Call
movement_catalog_search with that name (and any qualifiers like
equipment or variant).
- If there's a single clear match, use its
nodeId for the edge.
- If there are multiple plausible matches or no match, surface the
ambiguity to the coach instead of picking one — a wrong movement mapping
silently corrupts the programming graph.
Conjugate-method coaching conventions
This section encodes how Chris's conjugate-method programming (Max Effort /
Dynamic Effort / Repetition Effort — standard, publicly documented Westside
Barbell / conjugate-system terminology, not proprietary or secret) maps onto
Rubicon's edge roles. This is intentionally public: unlike sheet identity
and credentials, coaching methodology is not something this plugin treats as
sensitive.
Role mapping
max_effort — the max-effort (ME) exercise for the session: a near-max
single (or low-rep top set) on a rotating main lift variation. Map the
session's ME movement to an edge with role max_effort from the
session/block node to the resolved movement node.
dynamic_effort — the dynamic-effort (DE) work: sub-maximal loads moved
at maximal bar speed, typically across banded/chained wave sets. Map to
role dynamic_effort.
repetition_effort — repetition-effort (RE) / hypertrophy-style accessory
work taken to or near failure at moderate loads. Map to role
repetition_effort.
accessory, warm_up, activation, individual_prep, skill,
finisher, recovery, conditioning, test — use these for exactly
what they say; don't overload accessory for things that are really
warm-up or conditioning work just because it's convenient.
DE wave progression convention
Dynamic Effort work is typically organized in short waves (commonly ~3
weeks) with a deliberate week-over-week progression across the wave:
- Week 1 → Week 3: intensity (percentage of max used for the dynamic sets)
trends up (~+5% bar weight per week in Chris's programming).
- Week 1 → Week 3: target bar speed trends down slightly as a natural
consequence of rising intensity — the athlete is still moving the bar as
fast as possible for the load, but the load itself is heavier (Chris's
velocity targets: 0.9 / 0.8 / 0.7 m/s).
- Week 1 → Week 3: set volume holds then drops slightly (12×2, 12×2, 10×2).
- The start cadence does not tighten across the wave. Chris currently
prefers a constant 45-second start cadence; his older squat waves
progressed 30s → 40s → 45s (looser, not tighter, as load rises). Speed
pulls always run on 45-second starts.
When a sheet row encodes a wave number/position (e.g. "DE Wk 2 of 3"),
reflect that in weekNumber on the relevant node and make sure
percentage/interval values in payload are internally consistent with this
progression direction. If the sheet's numbers contradict this convention
(e.g. intensity going down week-over-week inside a DE wave), don't silently
"correct" it — flag the discrepancy to the coach; the sheet is the source of
truth for actual numbers, this convention is only a sanity check.
Chris's confirmed conventions
Source: Chris's 8 Loom walkthroughs plus one Slack addendum, 2026-07-11.
Transcripts and per-video analyses (with timestamped quotes) are archived in
the rubicon repo at imports/looms/2026-07-11/. Everything below is stated
by Chris on camera or in Slack — nothing here is invented.
Weekly template
- Monday / Tuesday / Thursday / Friday are the heavy primary days: two
upper-body and two lower-body days.
- Wednesday / Saturday are supplemental days: Olympic-lift technique work
(light, position-first — ideally not another heavy exposure; even PVC
work counts), gymnastics skill work, aerobic-flush intervals (rower,
SkiErg, Echo Bike), occasional strongman/odd-object work (sleds, yokes,
sandbags), and therapeutic movements (Turkish get-ups, ATG split-squat
series, foot/ankle work).
Session ordering
- General warm-up: 3–5 minutes of simple pulse-raising, then joint prep
for the day's lifts (full ranges, not technical).
- Specific warm-up: on primary days, 3 movement-specific activation
exercises interleaved with progressive build-up sets, ending ~1–2
build-up sets short of the first working weight.
- Primary piece (ME, DE, or RE) immediately after the warm-up.
- DE lower days always have two primaries: speed squat, then
speed pulls immediately after.
- RE upper primaries are followed by a pull/pull-up slot (strict, not
kipping; a pull-up variation appears ~2–3 weeks out of 4; the slot
may host chest-to-bar or muscle-up development for CrossFit athletes).
- Accessories.
- Finisher (including the week's midline work).
Max-effort (ME) 1RM protocol
- Default 7×1 building to the day's target: ~60%, 70%, 80%, 86–87%, 93%,
97%, 100%.
- Lower-body clock: 0:00, 2:30, 5:00, 7:30, 10:00, 13:00, 16:30. Upper-body
clock (less rest): 0:00, 2:00, 4:00, 6:00, 9:00, 12:00, 15:00.
- Athlete-dependent: stop at 6 sets on a bad day; allow an 8th for newer
athletes establishing a max.
- Band tension generally 20–40%. Set a target the athlete can hit — no
planned misses. Safety pins/spotters set up before lifting.
Dynamic-effort (DE) lower
- 3-week waves: 0.9 / 0.8 / 0.7 m/s, ~+5% bar weight per week,
12×2 / 12×2 / 10×2, same scheme for speed squat and speed pull.
- Week 1 loading guidance: ~40% bar weight plus band tension.
- 45-second start cadence (see wave-progression section above).
- Bands/chains a majority of the time, with occasional straight-weight
waves for pure bar-speed practice.
- Rotate the variation after each 3-week wave; pick DE variations that
offset the week's ME pattern (e.g. Manta Ray back squat against a banded
front squat ME) to avoid pattern overload. A practiced DE movement may
later be tested as an ME, optionally after a week away.
- Chris's percentages run deliberately below published Westside
recommendations — his athletes don't hit the literature numbers. Don't
"correct" sheet loads upward toward Westside tables.
Dynamic-effort bench (Slack addendum, 2026-07-11)
- Bench is usually trained with the repetition-effort method, but DE bench
cycles occur: 9×3, 9×3, 9×3 (sets/reps constant across all three weeks),
on the minute, at percentages slightly lower than DE squat/pull.
- Grip rotation: week 1 wide, week 2 narrow, week 3 normal — or within a
single session, 3 sets wide, 3 middle, 3 narrow.
Repetition-effort (RE)
- Primary RE is not to failure — failure work belongs in the finisher.
- Default progression: week 1 = 8×8, one constant load, sets every 2
minutes, starting ~50–60% of 1RM (closer to the middle); week 2 = 8×8
heavier; week 3 = 8×6 heavier again (48 total reps) — progressive
overload inside the microcycle.
- RE spans a heavy 5-rep effort through a 20-rep max; don't hard-code one
rep range as "the" RE range.
Accessory sequencing
- Accessories come after primaries, sequenced by "small fish feed medium
fish, medium fish feed big fish" (e.g. rotator cuff → scaps → lats).
- First accessory complements the primary by shifting emphasis (heavy
below-parallel front squat → posterior-chain RDL), second slot is
single-leg work at 8–12 reps (step-ups, reverse lunges, split squats),
third slot is usually higher-rep and loads the body differently (e.g.
open-chain reverse hyper after closed-chain RDL).
- Upper-body accessories always cover back/lats and generally hit triceps
hard; chest is already covered by the primary; delts/biceps sprinkled in.
Finisher
- Strategies: repetition effort to failure, very-high-rep (~100–200)
super-low-intensity band/bodyweight flush work for joint-capsule blood
flow, and isometrics (e.g. 3 sets single-leg hip-bridge iso; planks and
plank marching count).
- Midline work lives here, split into three categories — erectors,
abdominals, obliques — distributed across the week so all three get an
effective dose. GHD hip extensions classify as posterior-chain midline.
- Upper-body-day finishers bias rear delts and rotator cuff to offset
bench-pattern overload.
Programming workflow (sheet mechanics)
- Chris starts in the Conjugate Monthly tab (red lines = 3-week wave
boundaries), uses it to audit trained vs. neglected patterns, then
transfers into Conjugate Daily and adds per-lift bullet points.
- Primary and accessory pieces generally share the same 3-week format.
- Warm-ups (general and specific) are programmed last, after all
primary/accessory/finisher details are entered.
Open items — resolve from the sheet, not by asking
The sheet is the source of truth and Chris writes explicit numbers on it
every week. Do not ask him to recite values the sheet archive already
records (his spoken recall can contradict his own written sheets — see
the DE cadence correction above). Derive these from sheet/prod history
and record the answer here with a receipt:
- Exact DE bench percentages (read off the next DE bench cycle).
- DE lower week-1 loading and band range (transcript garbles
"15, 20 to 40" — actual loads are on the sheet).
- Accessory set counts and the third-slot rep range (prescriptions like
"4x6 - OT2:15-2:30" appear verbatim in blocks).
- Whether finishers follow the 3-week wave (diff finisher blocks across
a wave).
- Whether constant 45s DE cadence supersedes 30/40/45 (compare recent
vs. older waves).
- ME set 4 86 vs. 87: moot — encode 86–87%, midpoint, round to plate
increments. 1% at set 4 is below barbell resolution.
Resolved intent rules (Joel, verified against transcripts where noted)
-
The denominator — differs by method.
- ME: percentages reference that day's target weight, not a
stored 1RM. The transcript is explicit: "we set a target so you
can see we have a hundred percent target there... set five 93
percent... and then the target weight would be the final set"
(max-effort Loom [00:00]). Sets 1–6 scale to the target; set 7 IS
the target. Prefill math:
set_pct × day_target.
- RE: percent of 1RM — "roughly between 50 and 60 of your one
rep max" (repetition-effort Loom [00:00]).
- DE: percent of 1RM — bar-weight recommendations are "based on
your one rep max" (dynamic-effort Loom [04:01]).
-
Autoregulation: mark the miss and move on. No in-session redo,
no plan mutation. The program is built to avoid failure and ride the
edge of effort; misses get logged as failed and the session
continues. Transcript support: ME builds abort early when the day
isn't there ("sometimes it's not going right so you finish on the
sixth set"), and RE week 1 is deliberately set so "you don't want to
miss your set." App implication: record failed sets, don't
auto-adjust the prescription.
-
After week 3: start a new wave (rotate the movement). No
programmed deload week. Optionally the coach tests the trained
movement in week 4 or 5 — sometimes after a week away from it
("almost like a little deload week from the movement") — but it's
explicitly coach's choice, "not always... just kind of depends"
(dynamic-effort Loom [02:01]; also "after the three weeks we switch
it up" [06:05]). The RE "four format" is transcription garble: only
3 weeks exist; "two to three weeks out of four" [02:03] describes
how often the post-RE slot is a pull-up, not a 4-week wave.
-
ME day-target: a conversation, not a formula (Joel 2026-07-12).
The target is set by coach–athlete chat, anchored to recent
performance on that variation ("around where we were") and adjusted
by same-day feel — a "lift for the day," biased toward NOT failing.
"There's always tomorrow" is the operating vibe. App implication:
prefill a suggestion from the athlete's last exposure to the
variation, but the target field is athlete-owned and editable —
never auto-escalate it, and never treat a conservative target as an
error.
-
DE/RE denominator: "the most obvious 1RM," resolved along the
movement graph (Joel 2026-07-12). The reference 1RM for a
percentage falls back from the specific variation (with mods, bands,
specialty bars) toward the core lift until a known max exists —
e.g. manta-ray back squat w/ bands resolves up to back-squat 1RM if
the variation has never been tested. App implication: implement
denominator lookup as a walk over movement-family edges (rubicon's
data) from specific → core, taking the nearest
ancestor with a recorded 1RM. A stale core-lift 1RM makes every
prefill run hot for an athlete trading strength for engine —
recency-weight or flag old maxes rather than blindly using all-time
PRs.
All questions from https://rubicon-loom-followups-2026-07-11.wzrrd.sh/
are now resolved. Band-tension measurement basis (top/bottom/vs. what)
remains parked until the app ever recommends band setups — it currently
doesn't.
Handoff
Once the operation batch (≤25 ops) is built, hand off to the preview
skill to run programming_write_dry_run before anything is written.