/wheypoint
When to invoke: Mark the current conversation as a durable handoff so a new agent can resume the work. Use when the user wants to preserve state for a later or parallel session. Triggers include âhand this offâ, âwrite a handoffâ, âdrop a wheypointâ, âcheckpoint thisâ, âcompact the conversationâ, and â/wheypointâ. Also use for âwrap upâ or âI need to clear contextâ during a task. Do NOT use for phase handoffs from /cook, /press, /age, or /cure.
/wheypoint records the state a new agent needs to resume the work.
Use it for culture sessions, for work without a phase slug, and for a phaseâs Checkpoint & stop option. A phase checkpoint is a standalone, non-terminal Wheypoint record, not a terminal phase artifact. Workers at a hard limit return observations; the parent, not the worker, runs checkpoint persistence.
- The conversation is the primary input.
- The optional argument shapes only the orientation line.
- The focus never removes a decision, question, blocker, or directive.
Runtime commands
Section titled âRuntime commandsâRun every command through this skillâs archive by its resolved installed bundle path; see ../cheese/references/harness-portability.md.
When the consumer repository lacks skills/, resolve the installed bundle path before execution; never assume the easy-cheese checkout or current working directory.
python3 skills/wheypoint/scripts/wheypoint.pyz turns [--session <id> | --transcript <path>]python3 skills/wheypoint/scripts/wheypoint.pyz show --work-id <id>python3 skills/wheypoint/scripts/wheypoint.pyz validate < intent.jsonpython3 skills/wheypoint/scripts/wheypoint.pyz checkpoint [--compacted <proof.json>] < intent.jsonpython3 skills/wheypoint/scripts/wheypoint.pyz schema checkpoint-intentpython3 skills/wheypoint/scripts/wheypoint.pyz resolve --ref <absolute-path | work-id | slug>python3 skills/wheypoint/scripts/wheypoint.pyz lint <projection-path>python3 skills/wheypoint/scripts/wheypoint.pyz listpython3 skills/wheypoint/scripts/wheypoint.pyz log --work-id <id>resolve, lint, list, log, show, schema, and turns only read; direct invocations return output, and STOP before checkpoint writing.
/cheese --continue uses resolve and never invokes another archive; slash commands are host renderings, not the control model.
The parent delegates persistence as one structured checkpoint task to this capability.
Run validate before checkpoint; workers never invoke either command at a hard limit.
Phase skills use their own wheypoint-resolve --ref <slug> command for resolution.
The command returns authoritative, not-found, legacy, gated, ambiguous, or error.
Use authoritative working_context as the first batched tilth_read; follow references/delta-contract.md for all outcomes and findings.
phase-artifact is fallback context, and the handoff parser exposes its phase_slug.
- Read the userâs words. Run
turnsand keep every user turn in view. - Map each turn to an entry, or write one line that says why the turn is not captured.
- Rehydrate. Run
showfor the work id; a first checkpoint binds the genesis sentinel itself. - After a compaction, rehydrate first and pass a proof with
--compacted. - Write the intent. Follow
references/intent-contract.md. - Put each user-stated constraint or preference in a
directiveentry with its verbatimquote. - Put each choice in a
decisionentry with arationale. - Put each open item in a
questionorblockerentry. - Record a parked fork in
decision_dossierwith its options, evidence, and prior leaning. - Put the report a cold reader needs in
notes. - Put paths and URLs in
artifact_linksandworking_context, not their contents. - Validate. Run
validateand fix every named problem. - Checkpoint. Run
checkpoint. - Report. State the durability the result reports and the resume commands.
What the runtime enforces
Section titled âWhat the runtime enforcesâThe runtime refuses an intent instead of dropping data.
- It refuses an unknown key and names its path.
- It refuses a first checkpoint that carries no entry and no notes.
- It refuses
next: affinagewithout a PR reference inartifact. - It refuses
next: cookornext: cutwithout anartifact. - It refuses text that matches a credential pattern and names the field.
- It refuses an empty
artifact_linksorremove_artifact_linkslist. - It derives
status:from the gating entries per the handback contract; no author sets it. - It refuses a
baselinekey rather than drop it; a Cook baseline stays in the Cook handoff. - It requires a dossier fork for each gating entry.
- It derives every identifier, digest, and revision.
Fix a refused intent and run checkpoint again.
Handoff slug
Section titled âHandoff slugâThe checkpoint command writes the shared preamble at the top of the generated projection; every consumer reads it with parse_handoff_slug().
status: <canonical status field>next: mold | cut | cook | press | age | cure | affinage | briesearch | culture | hold | tasks | doneartifact: <path, or PR#<n> / URL when next is affinage, else empty><one-line orientation: where the session is and what is mid-flight>For next: tasks the projection adds a mode: parallel keyed line after artifact:; the keyed block after the orientation holds the Wheypoint pins.
The projection body shows gates, open entries, decisions, directives, notes, context, artifacts, the dossier, and tasks.
The projection is never the authority; never edit it and never resume from it by hand.
next: values
Section titled ânext: valuesâmold,cut,cook,press,age,cure: the next pipeline phase.next: cookon a standalone checkpoint names the phase to resume; it does not publish a CookâCook phase artifact.affinage: PR review comments or failing CI;artifactnames the PR.briesearch,culture: a read-only next move that/cheese --continuedispatches.tasks: independent moves; seereferences/parallel-handoffs.md.hold: restore orientation and wait for instructions.done: the work is complete; the checkpoint is a record, not a baton.- A missing
next:makes the handoff malformed; useholdwhen no action follows. Derivenext:andstatus:from the open questions and blockers, not from expected success.
Use status: gated: for every human decision; the resumed agent asks through the shared handoff gate before it dispatches.
Handwritten notes, their legacy values, and their provenance fields are in references/legacy-notes.md and references/provenance-fields.md.
- Never run a Git commit, push, or publication to raise durability.
- Never write a note by hand, never edit a generated projection, and never include a secret value.
- Reference each artifact by path or URL; do not copy its contents.
- Use complete sentences; write one sentence per line.
Handoff
Section titled âHandoffâEnd with the orientation and this link: Wheypoint dropped: [.cheese/notes/<slug>.md](<absolute-note-path>).
From the repository run /cheese --continue <slug>; from elsewhere run /cheese --continue <absolute-repo-path>/.cheese/notes/<slug>.md.
/wheypoint bundle commands
Section titled â/wheypoint bundle commandsâscripts/render_generated_regions.py generates this file from the static COMMANDS manifest in src/easy_cheese/skills/wheypoint/commands.py. Do not edit this file. Run each command as python3 skills/wheypoint/scripts/wheypoint.pyz <command> [args...]. Each command returns an integer exit status. Pass --help to a command for its arguments and output format. Keep worked examples in the skill instructions.
| Command | Purpose | Subcommands |
|---|---|---|
checkpoint |
Checkpoint a semantic intent onto the current record | |
handoff |
Render, parse, and dispatch-split handoff preambles | render, parse, dispatch |
lint |
Lint a generated projection against the record | |
list |
List every work item under the corpus root | |
log |
Walk the revisions of one work id, oldest first | |
resolve |
Resolve a slug, work id, or path to the current record | |
schema |
Print the JSON Schema for a registered contract slug | |
show |
Print the current record for a work id | |
turns |
Print the userâs own turns from a session transcript | |
validate |
Validate an intent against its schema without opening the store |
Wheypoint phase delta contract
Section titled âWheypoint phase delta contractâThis contract covers the durable revision written at the end of the Cook, Press, Age, or Cure phase.
The record is keyed by the phase slug and work id.
A terminal phase handoff writes its phase artifact and then commits one revision for that phase.
Mold publication and Plate publication do not call this writer and do not create a wheypoint revision.
No plugin hook is part of this contract. Issue #654 ask 4 (a /compact hook that emits the grounded manifest) is deferred follow-up work until a host-neutral compaction trigger exists; the compaction hook itself is host-specific and out of scope here.
Entry resolution
Section titled âEntry resolutionâEach phase uses its own archive for entry resolution: python3 skills/<phase>/scripts/<phase>.pyz wheypoint-resolve --ref <slug>.
Pass --corpus-root <dir> to read this projectâs corpus from another location; the writer accepts the same flag.
A corpus belonging to another project resolves but gates on project-mismatch, so the flag relocates a corpus rather than borrowing one.
--corpus-root is not accepted with --legacy, which reads a note beside the repository rather than any corpus; the pair exits 2.
Plate also runs this command on entry, but only to resolve; it creates no revision.
The six outcomes are authoritative, not-found, legacy, gated, ambiguous, and error.
An authoritative record is the primary input.
Its working_context is authoritative and supplies the first batched tilth_read.
A not-found result proceeds cold.
A legacy result shows its source and slug before the phase proceeds.
A gated, ambiguous, or error result stops the phase and shows its payload.
Advisory findings display with any outcome.
A result with source: phase-artifact came from the first readable matching file in this order:
.cheese/cure/<slug>.md, .cheese/age/<slug>.md, .cheese/press/<slug>.md, then .cheese/cook/<slug>.md.
The handoff preamble parser supplies phase_slug from that file.
The result has outcome legacy and is not dispatchable as an authoritative record.
Show the source and parsed phase slug before using the artifact as context.
Grounded context
Section titled âGrounded contextâA phase writer accepts one or more --grounded path[#start-end] arguments.
Paths are repository-relative files with optional one-based inclusive line ranges.
A first revision requires at least one grounded entry.
The writer accepts at most 16 grounded entries.
Supplying a grounded list replaces working_context; omitting it carries the existing context.
A # inside a file name is legal; the range is anchored on the last #.
PR#<n> and URL entries in working_context are pointers, not grounded paths; lint skips them.
The writer anchors relative paths and .cheese/ at the git toplevel (or --root), never at the current directory.
Writer exit codes
Section titled âWriter exit codesâExit 2 is caller usage: a bad --grounded entry or a first revision without one; nothing is written.
Exit 4 is a kernel failure before the artifact write; nothing is written.
Exit 5 means the artifact was written but the revision failed; stderr carries wheypoint: artifact-orphaned <path> and the next resolve gates on stale-artifact-link.
Every wheypoint:-tagged line on stderr is one plain-ASCII line, identical on every host.
A refusal, exit 2 or exit 4, is reported by the shared CLI as ERROR: <message> instead.
A successful write prints wheypoint: revision work_id=<id> revision_id=<id> revision_number=<n> retried=<bool>.
A stale-parent retry prints one wheypoint: retry ... line and one wheypoint: retry outcome=... line.
An unexpected failure always prints a traceback to stderr; set EASY_CHEESE_DEBUG or CHEESE_DEBUG to add one to deliberate refusals as well.
Lint findings
Section titled âLint findingsâstale-artifact-link is a gating finding.
It means a digest-bearing phase-artifact link is missing or no longer matches its recorded digest.
Stop instead of dispatching when this finding is present.
stale-commit is advisory.
It means the recorded repository commit exists but is not an ancestor of the current HEAD.
Display the code and detail with the resolved payload, but do not stop solely for this finding.
grounded-path-missing is advisory.
It means a path named in working_context is absolute, escapes the repository root, or is no longer a file; the detail names which.
Display the code and detail with the resolved payload, but do not stop solely for this finding.
Advisory findings never hide the outcome. A gating finding remains a stop even when advisory findings are also present.
The CheckpointIntent contract
Section titled âThe CheckpointIntent contractâcheckpoint accepts one intent and derives everything else.
Run schema checkpoint-intent for the generated JSON Schema.
Run validate for a schema-only dry run that never opens the store.
{ "work_id": "auth-retry-backoff", "orientation": "One or more lines; the first line becomes the record title at genesis.", "working_context": ["src/auth/retry.py", "PR#412"], "notes": "The report a cold reader needs, as Markdown.", "next": "cook", "artifact": ".cheese/specs/auth-retry-backoff.md", "entries": [ {"kind": "decision", "summary": "Cap the backoff at 30s.", "rationale": "Burst callers saturate the pool."}, {"kind": "directive", "summary": "Prose stays STE100.", "quote": "is it all in STE100?"}, {"kind": "question", "summary": "Do we jitter?", "blocks_continuation": true}, {"kind": "blocker", "summary": "Staging is down.", "blocks_continuation": true} ], "decision_dossier": [ {"fork": "Ceiling or jitter first", "options": [{"option": "ceiling", "evidence": ["src/auth/retry.py:88"], "breaks": "burst callers"}], "prior_leaning": "ceiling"} ], "artifact_links": [{"path": ".cheese/specs/auth-retry-backoff.md", "covers_entry_ids": []}], "remove_artifact_links": [".cheese/cook/stale.md"], "transitions": [{"entry_id": "q-0f1e2d3c4b5a", "action": "resolve", "rationale": "Answered in the spec.", "target_entry_id": null}], "tasks": null, "parallel": null, "base_revision_id": null, "session": {"harness": "claude", "session_id": "abc123", "captured_at": "2026-09-05T12:00:00Z"}}work_idis required and becomes one path segment under the corpus.orientationis free text; its first line becomes the title at genesis.working_contextis a list of pointers, not a paragraph.notesis the Markdown body the projection renders under## Notes; omission carries it forward.nextacceptsmold,cut,cook,press,age,cure,affinage,briesearch,culture,hold,tasks, ordone.artifactrides besidenext;affinageneedsPR#<n>or a PR URL, andcookorcutneed a path.entriesholdsProposedEntryvalues of kinddecision,question,blocker, ordirective.- Each entry has
{kind, summary, rationale?, quote?, blocks_continuation}. - Only a question or a blocker can set
blocks_continuation: true. - A
directivecarries the userâs words verbatim inquote. - The runtime derives each
entry_idfrom the parent and the proposal. decision_dossierholds forks{fork, options: [{option, evidence, breaks}], prior_leaning}.- A fork may describe any active question; every gating entry needs a covering fork.
artifact_linksholds{path, covers_entry_ids?}; the runtime computes the digest and pins the revision.- A link replaces the carried link with the same path; links are a set keyed by path.
remove_artifact_linksnames carried paths to drop; an unknown path is refused.- An empty
artifact_linksorremove_artifact_linkslist is refused. transitionsholds{entry_id, action, rationale, target_entry_id};actionisresolve,supersede, orwithdraw.- Only a transition changes a protected entryâs state; no operation removes one.
tasksandparallelcarry independent moves whennextistasks; seeparallel-handoffs.md.base_revision_idpins the revision the intent was written against; omit it to bind the current revision.sessionholds optional{harness, session_id, captured_at}.
- Omission carries data forward;
nullmeans unchanged. - An explicit empty
working_contextordecision_dossierreplaces the carried value. - Identifiers match
[a-z0-9][a-z0-9._-]{0,63}. - Text fields contain at most 2000 characters; lists at most 64 items.
- A first checkpoint must carry at least one entry or a
notesbody. - An unknown key at any depth is refused and named by path.
- Text that matches a credential pattern is refused and named by field.
- An identical intent against the same parent replays the existing receipt.
- A changed intent against a superseded parent is refused as stale.
Compaction proof
Section titled âCompaction proofâAfter a context compaction, rehydrate with show, then pass --compacted <proof.json>.
The proof is a CompactionRecord: {rehydrated_from_revision_id, rehydrated_record_digest, reconciled_entry_ids}.
rehydrated_from_revision_id must equal the current revision and rehydrated_record_digest its record digest.
reconciled_entry_ids must include every protected entry in the record.
The runtime derives prior_compaction_revision_id from stored receipts and refuses a supplied value.
Reply envelope
Section titled âReply envelopeâEvery command prints exactly one JSON object, on one line, to stdout.
A success reply is {"ok": true, "command": "<name>", ...fields}.
A failure reply is {"ok": false, "command": "<name>", "error": {"code": "...", "message": "...", ...extra}}.
checkpointreturnsnote_path,replayed,work_id,revision_id,revision_number,parent_revision_id,status,durability,projection_path,record,revision,markdown.validatereturnsvalidandwork_id.schemareturnsslugandschema.resolvereturnsref,outcome,dispatchable,source,work_id,record,projection,findings,matches,searched,legacy_note,legacy_slug,detail.showreturnswork_id,status,revision_id,revision_number,record.lintreturnspath,clean,findings,projection.listreturnscorpus_root,items, andlines.logreturnswork_id,revisions,lines, andunreadable.turnsreturnstranscript,count,skipped_lines,turns, andlines.
lines is a list of strings, one per row, for a shell caller to read line by line.
Each lines entry is tab-separated columns, in a fixed order per command.
list columns are work_id, revision_number, status, next, detail.
log columns are revision_number, revision_id, captured_at, additions, transitions, compacted.
turns columns are timestamp, text.
A column value escapes a backslash as \\.
A column value escapes a newline as \n.
A column value escapes a tab as \t.
This escaping keeps one line one record.
items (from list) is one untyped JSON object per work item, carrying work_id plus either unreadable, no_record, or the recordâs summary fields.
revisions (from log) is one untyped JSON object per revision, carrying revision_number, revision_id, captured_at, additions, transitions, compacted.
turns (from turns) is one untyped JSON object per user turn, carrying timestamp and text.
unreadable (from log) lists {path, reason} for revision files the scan could not parse.
skipped_lines (from turns) counts transcript lines that could not be parsed as a turn.
count (from turns) is the number of turns returned.
corpus_root (from list) is the resolved root directory the listing scanned.
Exit 0 means the command succeeded; the reply carries the commandâs own fields.
Exit 1 means the command refused the request; the reply carries error.code and error.message.
Exit 2 means the command-line usage was wrong, before any command ran.
Exit 3 means an unexpected internal error; error.code is internal-error and a Python traceback goes to stderr, never into the JSON.
Each refusal names a code:
invalid-json: stdin was not one JSON value.storage-error: the work store could not be opened or read.commit-only-field:checkpointwas asked to authorcompacted,compaction, orexpected_revision_iddirectly.invalid-intent: the intent payload failed schema or delta validation.secret-pattern: a field looked like a credential.record-unreadable: the workâs record exists but could not be parsed.compaction-proof-unreadable: the--compactedproof file could not be read or parsed as JSON.invalid-compaction-proof: the--compactedproof failed schema validation.genesis-conflict: a genesis commit collided with an existing record.stale-parent: the intentâs parent revision has moved on.commit-refused: the commit kernel refused the delta for another reason.note-unwritable: the note directory or mirror file could not be written.pending-corrupt: a pending-mirror ledger entry named a different request than its revision.unknown-contract:schemawas asked for a slug with no registered contract.record-missing:showorlogfound no record for the work id.store-inconsistent:logfound a record but every revision file was dropped as unreadable.session-required:turnswas given neither--sessionnor--transcript.invalid-session: the given--sessionid was not a safe file-name segment.transcript-missing: no transcript file exists at the resolved path.invalid-reference:resolvecould not interpret the given reference.internal-error: an unexpected exception, not a refusal, reachedmain.
Legacy notes
Section titled âLegacy notesâHandwritten legacy notes
Section titled âHandwritten legacy notesâA handwritten note under .cheese/notes/ predates the continuity kernel.
The resolve command still reads it, and a legacy result is never authoritative.
A legacy result gates a resume for a human decision.
Header keys
Section titled âHeader keysâA legacy note accepts mode:, order:, session:, git:, created:, parents:, and baseline: between artifact: and the orientation.
mode: is optional; an omitted mode means mode: single.
In mode: single, next: names the skill that the new agent runs.
For multiple read-only moves, use a next: list with order: parallel | sequential.
Use only briesearch or culture in an inline next: list.
See provenance-fields.md for session:, git:, created:, and parents:.
Legacy status values
Section titled âLegacy status valuesâhalt: <one-line reason>is valid only in a handwritten note.- The runtime never derives
halt; derived status has onlyokandgated:. resolvegates every legacy status whose disposition is notproceed.- A legacy
halttherefore stops: the reader shows the reason and dispatches nothing.
Baseline
Section titled âBaselineâA handwritten note can record a one-line baseline: value.
The baseline is settled state; do not re-ask, re-flag, or re-halt on identical baseline entries.
The canonical record carries no baseline field, so keep a Cook baseline mapping in the Cook handoff.
See ../../cook/references/quality-gates.md.
Resume semantics
Section titled âResume semanticsâ/cheese --continue <slug> resolves the slug through resolve and dispatches next: only from a validated current revision.
An absolute note path resolves as an explicit path first.
Resume preserves mode:, --hard, --open-pr, --safe, and an explicit --auto.
Press corrective work remains continue: press-corrective-cook, not a global Press-to-Cook dispatch.
Multi-move handoffs
Section titled âMulti-move handoffsâUse this contract when one checkpoint starts multiple moves.
tasks and parallel are CheckpointIntent fields; see intent-contract.md.
Set next: tasks and give at least one task.
The projection renders mode: parallel between next: and artifact:, plus a ## Tasks section.
This position keeps mode metadata separate from free-text orientation.
A legacy orientation that starts with mode: remains text.
A single move does not need this contract.
parallel and tasks
Section titled âparallel and tasksâGive each task its exact command; commands can name different skills.
Never run parallel write tasks in one checkout.
Select one isolation strategy:
worktree_strategy |
Use when | Required fields |
|---|---|---|
existing |
The user has durable bench checkouts | each write task has distinct worktree, branch, and branch_from |
create |
No checkouts exist | worktree_root, plus each write task has branch and branch_from |
harness |
The host creates isolated worktrees | each write task has branch and branch_from; the host creates the checkout |
Intent example:
{ "work_id": "kip-ai", "orientation": "KIP-76 and KIP-77 are ready to run as independent PR efforts.", "next": "tasks", "parallel": {"isolation": "git-worktree", "worktree_strategy": "existing"}, "tasks": [ {"slug": "kip-77-ai-test-server", "intent": "cook", "repo": "/path/to/repository", "worktree": "/path/to/worktree-01", "branch": "user/kip-77-ai-test-server", "branch_from": "origin/main", "command": "/cook .cheese/specs/kip-77-ai-test-server.md"}, {"slug": "kip-76-ai-service-spin-up", "intent": "cook", "repo": "/path/to/repository", "worktree": "/path/to/worktree-02", "branch": "user/kip-76-ai-service-spin-up", "branch_from": "origin/main", "command": "/cook .cheese/specs/kip-76-ai-service-spin-up.md"} ]}Rendered projection preamble and tasks block:
status: oknext: tasksmode: parallelartifact:KIP-76 and KIP-77 are ready to run as independent PR efforts.
## Tasks
parallel: isolation: git-worktree worktree_strategy: existingtasks: - slug: kip-77-ai-test-server intent: cook repo: /path/to/repository worktree: /path/to/worktree-01 branch: user/kip-77-ai-test-server branch_from: origin/main command: /cook .cheese/specs/kip-77-ai-test-server.md - slug: kip-76-ai-service-spin-up intent: cook repo: /path/to/repository worktree: /path/to/worktree-02 branch: user/kip-76-ai-service-spin-up branch_from: origin/main command: /cook .cheese/specs/kip-76-ai-service-spin-up.mdFor a new setup, use worktree_strategy: create and add worktree_root.
/cheese --continue derives one checkout from each task slug.
Read-only moves in a legacy note
Section titled âRead-only moves in a legacy noteâA handwritten legacy note may list read-only moves with next: [briesearch "slug1", culture "slug2"].
With order: parallel, /cheese --continue starts one read agent per item in the same turn; with order: sequential, it runs them in listed order.
See legacy-notes.md.
Provenance and lineage
Section titled âProvenance and lineageâA live session can fill four optional header fields.
Two lineage commands remain outside the continuity contract.
Provenance fields
Section titled âProvenance fieldsâPut these optional fields before the orientation line.
Only the live session supplies them.
Pre-provenance notes remain valid.
session: <harness>:<session-id>identifies an active Claude, Codex, or OpenCode session.- Omit the field when it is unavailable.
- Claudeâs newest-file heuristic is
<speculative>. git: <branch>@<short-sha>identifies the branch and short commit.- Use a callable, read-only git inspection capability.
- Run
git status --short --branchandgit rev-parse --short HEAD. - Omit the field when git inspection is unavailable.
- Omit the field outside a git repository.
created: <UTC ISO-8601>gives the UTC capture time.parents: [<slug>, ...]gives the lineage that the commands below write.
Lineage commands
Section titled âLineage commandsâLegacy --join writes parents: [<slugA>, <slugB>].
Each --split child writes parents: [<current-slug>].
These commands remain outside this continuity contract.
They rewrite .cheese/notes/ Markdown and commit no delta.