Checkpoint
Overview
Checkpoints record the successful completion of each pipeline phase. They are written after a phase finishes (never during) and enable:
- Resume: Restart a pipeline from a specific phase without re-running prior phases
- Validation: Verify that prior phase outputs are structurally sound before skipping
- Replay: Audit trail of pipeline execution across attempts
- Idempotency: Append-only writes with monotonically increasing attempt numbers
Checkpoints are backed by the omnibase_infra checkpoint node infrastructure and managed through the checkpoint_manager.py CLI wrapper.
Announce at start: "I'm using the checkpoint skill to manage pipeline state."
Backing Status ()
Backed by (real, non-stub): omnibase_infra/src/omnibase_infra/nodes/node_checkpoint_effect/ (EFFECT — read/write/list handlers) and omnibase_infra/src/omnibase_infra/nodes/node_checkpoint_validate_compute/ (COMPUTE — validate handler), invoked in practice via plugins/onex/hooks/lib/checkpoint_manager.py (functional CLI wrapper, no stub markers).
The generated omniclaude shell node_skill_checkpoint_orchestrator (maturity: stub in its contract.yaml) is a Polly-passthrough that is NOT the real dispatch path for this skill — it exists only from the bulk generate_skill_node.py pass and is never actually invoked. skill_functional_audit's naive node_<skill_name> path match doesn't resolve to the real omnibase_infra node names above, which is why it (mis)flags this skill as a facade. Tracked cleanup: (repoint the registry / retire the dead shell).
Storage Layout
Checkpoints are stored as YAML files under the user's home directory:
$ONEX_STATE_DIR/checkpoints/{ticket_id}/{run_id}/phase_{N}_{name}_a{attempt}.yaml
Where:
{ticket_id}-- Linear ticket identifier (e.g.,PROJ-1234){run_id}-- Pipeline run UUID{N}-- Phase ordinal (1-4){name}-- Phase value string{attempt}-- Monotonically increasing attempt counter
Example:
$ONEX_STATE_DIR/checkpoints/{ticket_id}/e3a1b2c4-d5f6-5a78-9bcd-ef1234567890/phase_1_implement_a1.yaml
$ONEX_STATE_DIR/checkpoints/{ticket_id}/e3a1b2c4-d5f6-5a78-9bcd-ef1234567890/phase_2_local_review_a1.yaml
$ONEX_STATE_DIR/checkpoints/{ticket_id}/e3a1b2c4-d5f6-5a78-9bcd-ef1234567890/phase_2_local_review_a2.yaml # retry
$ONEX_STATE_DIR/checkpoints/{ticket_id}/e3a1b2c4-d5f6-5a78-9bcd-ef1234567890/phase_3_create_pr_a1.yaml
Note: Short run IDs (e.g.,
a1b2c3d4) are normalized to deterministic UUID v5 values on disk via_normalize_run_id(). The same short ID always maps to the same full UUID.
Writes are append-only: existing checkpoint files are never modified or overwritten.
Checkpoint Contract
Each checkpoint YAML file contains these fields:
| Field | Type | Description |
|---|---|---|
schema_version |
string | Forward-compatibility version (currently "1.0.0") |
run_id |
UUID | Pipeline run correlation ID |
ticket_id |
string | Linear ticket identifier |
phase |
enum | Pipeline phase that completed |
timestamp_utc |
datetime | UTC timestamp of phase completion (explicitly injected) |
repo_commit_map |
dict[str, str] | Mapping of repo name to commit SHA |
artifact_paths |
tuple[str, ...] | Relative paths of output artifacts |
attempt_number |
int (>=1) | Monotonically increasing attempt counter |
phase_payload |
union | Phase-specific payload (discriminated on phase field) |
Phase Ordinals
| Phase | Ordinal | Value |
|---|---|---|
| Implement | 1 | implement |
| Local Review | 2 | local_review |
| Create PR | 3 | create_pr |
| Ready for Merge | 4 | ready_for_merge |
Per-Phase Payload Reference
implement
| Field | Type | Description |
|---|---|---|
phase |
literal "implement" |
Discriminator |
branch_name |
string | Git branch name created |
commit_sha |
string (7-40 hex) | HEAD commit SHA after implementation |
files_changed |
tuple[str, ...] | Relative paths of changed files |
local_review
| Field | Type | Description |
|---|---|---|
phase |
literal "local_review" |
Discriminator |
iteration_count |
int (>=1) | Number of review-fix iterations |
issue_fingerprints |
tuple[str, ...] | Fingerprints of issues found and resolved |
last_clean_sha |
string (7-40 hex) | Commit SHA of the last clean state |
create_pr
| Field | Type | Description |
|---|---|---|
phase |
literal "create_pr" |
Discriminator |
pr_url |
string | Full URL of the created PR |
pr_number |
int (>=1) | PR number on the remote |
head_sha |
string (7-40 hex) | HEAD SHA pushed to the remote |
ready_for_merge
| Field | Type | Description |
|---|---|---|
phase |
literal "ready_for_merge" |
Discriminator |
label_applied_at |
datetime | UTC timestamp when the merge-ready label was applied |
CLI Usage
All operations use checkpoint_manager.py located at ${CLAUDE_PLUGIN_ROOT}/hooks/lib/checkpoint_manager.py.
Write a Checkpoint
python ${CLAUDE_PLUGIN_ROOT}/hooks/lib/checkpoint_manager.py write \
--ticket-id {ticket_id} \
--run-id a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
--phase implement \
--attempt 1 \
--repo-commit-map '{"omniclaude": "a1b2c3d"}' \
--artifact-paths '["src/foo.py", "tests/test_foo.py"]' \
--payload '{"branch_name": "feat/{ticket_id}", "commit_sha": "a1b2c3d", "files_changed": ["src/foo.py"]}'
Output:
{
"success": true,
"checkpoint_path": "{ticket_id}/a1b2c3d4.../phase_1_implement_a1.yaml",
"correlation_id": "..."
}
Read Latest Checkpoint
python ${CLAUDE_PLUGIN_ROOT}/hooks/lib/checkpoint_manager.py read \
--ticket-id {ticket_id} \
--run-id a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
--phase implement
Output:
{
"success": true,
"correlation_id": "...",
"checkpoint": { ... }
}
Validate a Checkpoint
Reads the checkpoint and then performs structural validation (schema version, path normalization, commit SHA format, phase-payload agreement, timestamp sanity).
python ${CLAUDE_PLUGIN_ROOT}/hooks/lib/checkpoint_manager.py validate \
--ticket-id {ticket_id} \
--run-id a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
--phase implement
Output:
{
"is_valid": true,
"success": true,
"errors": [],
"warnings": [],
"correlation_id": "...",
"checkpoint": { ... }
}
List All Checkpoints
# All checkpoints for a ticket
python ${CLAUDE_PLUGIN_ROOT}/hooks/lib/checkpoint_manager.py list \
--ticket-id {ticket_id}
# Scoped to a specific run
python ${CLAUDE_PLUGIN_ROOT}/hooks/lib/checkpoint_manager.py list \
--ticket-id {ticket_id} \
--run-id a1b2c3d4-e5f6-7890-abcd-ef1234567890
Output:
{
"success": true,
"count": 3,
"checkpoints": [ ... ],
"correlation_id": "..."
}
Integration with ticket-pipeline
The ticket-pipeline skill writes checkpoints after each phase completes and validates them during --skip-to resume. See plugins/onex/skills/ticket-pipeline/prompt.md for the integration details.
Error Handling
- omnibase_infra not installed: CLI prints JSON error and exits with code 1
- Invalid phase name: CLI prints JSON error with valid phase list
- Checkpoint already exists: Handler raises error (increment attempt_number)
- Path traversal: Handler rejects ticket IDs that escape the checkpoint root
- Absolute artifact paths: Rejected by both CLI and handler validation
- Corrupt YAML files: Skipped during list, reported during read
All checkpoint operations in the pipeline context are non-blocking -- write failures log a warning but do not stop the pipeline.
Cron-Closeout Checkpoint Protocol
The headless cron-closeout pattern (scripts/cron-closeout.sh) uses a separate, simpler
checkpoint file for cross-invocation state persistence. This is distinct from the per-ticket
pipeline checkpoints above.
Storage
$ONEX_STATE_DIR/pipeline_checkpoints/cron-closeout-state.yaml
$ONEX_STATE_DIR/pipeline_checkpoints/cron-closeout.lock
Checkpoint Schema
schema_version: "1.0.0"
pass_count: 5 # Total completed passes
last_status: success # success | noop | failure | halt | unknown
last_run_at: 2026-03-28T22:00:00Z # UTC timestamp of last completion
consecutive_failures: 0 # Reset to 0 on success/noop; +1 on failure/halt
dry_run: false # Whether last pass used --dry-run
Lock File
The lock file prevents concurrent cron invocations from overlapping. It contains:
pid: 12345
started_at: 2026-03-28T22:00:00Z
Lock timeout is 45 minutes (matching the autopilot cycle mutex). A new invocation finding a lock older than 45 minutes treats it as stale and removes it.
Circuit Breaker
3 consecutive failures (status failure or halt) prevent further invocations.
To reset: edit consecutive_failures in the checkpoint file to 0, or delete the
checkpoint file entirely.
Relationship to Pipeline Checkpoints
| Aspect | Pipeline Checkpoints | Cron-Closeout Checkpoint |
|---|---|---|
| Scope | Per-ticket, per-phase | Per-cron-loop, aggregate |
| Storage | $ONEX_STATE_DIR/checkpoints/{ticket_id}/ |
$ONEX_STATE_DIR/pipeline_checkpoints/ |
| Schema | Full phase payloads | Simple pass/fail counter |
| Writer | checkpoint_manager.py |
cron-closeout.sh |
| Purpose | Resume mid-pipeline | Track cron loop health |
See Also
ticket-pipelineskill (writes checkpoints after each phase)local-reviewskill (writes checkpoints after each iteration when--checkpointis provided)omnibase_infracheckpoint nodes (infrastructure implementation)scripts/cron-closeout.sh(headless cron pattern)