Skip to content

Operator Guide

This guide is for people and agents maintaining a Slipway workspace.

Path Role Git policy
.slipway.yaml Repository-local Slipway configuration. Commit when project defaults change.
artifacts/changes/<slug>/change.yaml Current lifecycle and routing authority for an active change. Archived snapshots stay in the owning workspace, omit machine-local worktree_path, and use archive-local artifact paths. Trackable project record.
artifacts/changes/<slug>/*.md Intent, research, requirements, decisions, tasks, and assurance. Trackable project records.
artifacts/changes/<slug>/events/lifecycle.jsonl Append-only trace for mutating lifecycle events. Local-only raw proof by default.
artifacts/changes/<slug>/verification/*.yaml Skill and verification evidence. Local-only raw proof by default.
.git/slipway/runtime/changes/<slug>/evidence/** Runtime task evidence consumed by wave execution and freshness diagnostics. Git-internal local runtime state.
.git/slipway/runtime/changes/<slug>/handoff.md Optional advisory continuation notes for a fresh AI session on the active change. It is not lifecycle authority, governed evidence, freshness input, or a gate. Git-internal local runtime state.
.git/slipway/locks/change-create.lock, .git/slipway/locks/repair.lock Workspace/scope-level coordination locks for change creation and repair. These remain global because those critical sections start before or outside a stable per-change lock. Git-internal local runtime state.
artifacts/codebase/** Advisory codebase maps generated by slipway codebase-map. Trackable project record; git-tracked by default (existing repos auto-migrate on the next managed-block rewrite).
.worktrees/<slug> Dedicated governed worktree checkout. Local-only by default.

Do not treat events/lifecycle.jsonl as a replacement for change.yaml. It is audit evidence only. Do not write runtime task evidence into the active bundle; slipway evidence task records it under .git/slipway/runtime/changes/<slug>/evidence/tasks/. If continuation notes are useful, write them to .git/slipway/runtime/changes/<slug>/handoff.md after resolving <slug> from fresh status or next output. Do not derive lifecycle state, skill choice, or freshness from handoff text. slipway init, slipway new, and slipway codebase-map maintain the Slipway local-state .gitignore block idempotently.

Governed work may be bound to a dedicated worktree under .worktrees/<slug>. Use the worktree that owns the active governed diff:

Terminal window
git status --short --branch
go run . status --json

Avoid deciding readiness from main...HEAD alone. Pair branch comparisons with direct worktree status and diff checks. The durable codebase map under artifacts/codebase/** is exempt from scope-contract changed-file accounting: when only those context files are dirty, they stay out of scope_contract.changed_files and scope_contract.out_of_scope_files, and scope_contract.status stays pass. To keep that filtering visible rather than inferred from a git diff disagreement, the exempted files are disclosed in the scope_contract.exempt_context_files field surfaced by slipway validate, slipway status --json, and slipway review --json. After slipway done, Git-safe archived records remain in the owning worktree; commit or merge them before removing that worktree. When a worktree-bound change still has uncommitted source or non-active governance changes, done archives anyway and returns a non-blocking worktree_dirty_warning with worktree_dirty_files so the operator commits those files together with the archived bundle. done does not remove the worktree, and git worktree remove refuses to drop a dirty worktree, so the advisory is sufficient. The active artifacts/changes/<slug>/ bundle is excluded from the advisory because done rewrites it into artifacts/changes/archived/<slug>/; a dirty sibling or archived bundle is listed in the advisory.

Inspect before mutating:

Terminal window
slipway health --doctor --json
slipway validate
slipway status --json

Run repair only when the doctor output matches the observed issue:

Terminal window
slipway repair --json

Repair is intended for bounded local integrity issues such as stale locks, unheld lock anchors, interrupted archives, corrupt config, or repairable layout drift. It reports legacy repo-level runtime handoff files such as .git/slipway/runtime/handoff.md so an operator can migrate useful context to the current per-change handoff path before deleting them. In JSON output, applied_repairs lists fixes that were performed, while unrepaired_drift lists drift that still needs operator action with a target, reason, and next action. Do not edit freshness fields or timestamps by hand; regenerate the named evidence or make a same-intent change amendment to the source artifact instead. For ready execution summaries that are stale only because runtime task evidence is newer, repair can rebuild the summary from current wave-backed task evidence. Planning-source drift remains unrepaired and points back to planning or review evidence refresh instead.

Health findings include active-change impact. Codebase-map warnings are advisory by default and should be marked non-blocking for the current gate, with a refresh path or command when the map needs to be rebuilt.

Execution freshness diagnostics are structural rather than hash-based. Current execution summaries record task freshness inputs such as change_id, run_summary_version, task_id, and guardrail_domain; old hash-only summaries are treated as stale and must be regenerated.

next --json --diagnostics, run --json --diagnostics, validate, and status --json expose freshness failures with stale source/evidence pairs, first stale cause, downstream evidence chain, expected/current task input values, authoritative bundle and runtime paths, and a safe next action. Missing task evidence blockers include the runtime task evidence directory, record_command=slipway evidence task --result-file <path> --json, and the compact executor result schema: task_id,verdict,evidence_ref,changed_files,no_op_justification,blockers,session_id. Repeat --result-file to import multiple task result files atomically; Slipway preflights the whole batch and writes no task evidence if any file is invalid or duplicates another task ID. The directory is .git/slipway/runtime/changes/<slug>/evidence/tasks/ for the active change; bundle-local events/ and verification/ remain under artifacts/changes/<slug>/.

Reason-code code values are the stable machine contract for blockers, recovery routing, JSON consumers, and generated skills. The canonical enum is the key set in internal/model/reason_code.go’s canonicalReasonDefinitions, and internal/model/reason_code_contract_test.go freezes that set and each code’s severity with snapshot tests. Treat message as presentation prose: reason/error payload tests and skill logic must assert stable fields such as code, detail, error_code, category, exit_code, or structured details instead of matching message text. The repo-local AST lint enforces that rule for syntactically recognizable reason/error payload surfaces (ReasonCode, CLIError, HealthFinding, known constructors/helpers, and blocker/reason collections); other fields named Message remain review-owned unless they become part of that reason/error payload surface. If a producer emits an unrecognized token, normalization fails closed to unknown_reason_code and preserves the original token in detail so the producer can be fixed and added to the canonical enum. Bridges from CLI errors to reason payloads must only preserve canonical reason codes directly; non-reason-domain error_code values must be carried in the detail of a canonical wrapper reason instead of being normalized as standalone reason codes.

Review handoffs use exact layer tokens. Spec-compliance evidence records layer:R0=pass and, when the guardrail domain requires it, layer:R3=pass. Code-quality evidence records layer:IR1=pass and, when required, layer:IR3=pass. Tokens such as layer:CORRECTNESS=pass, layer:SAFETY=pass, or layer:QUALITY=pass are not gate-satisfying substitutes.

Status artifact DAG entries include blocking and blocking_reason. A draft planning artifact can be informational after the lifecycle has moved past the planning gate; treat the flag as the current gate signal.

Use targeted checks while implementing:

Terminal window
go test ./internal/stringutil ./internal/engine/progression ./internal/engine/governance -run 'TestHasBlockingOpenQuestions|TestFirstBlockingOpenQuestion|TestAdvanceIntake_OpenQuestionsUseChecklistStructure|TestOpenQuestionsRoutingNoteNamesEntryAndEscapeHatch|TestTraceability.*OpenQuestions|TestGovernanceReadinessUsesTraceabilitySnapshot' -count=1

Use the full proof before closeout:

Terminal window
go test -timeout=20m ./... -count=1
go build ./...
go vet ./...
(cd website && npm run build)

Run the docs build (Astro Starlight) only when Node dependencies are available locally; run cd website && npm install first. CI runs the same docs build for verification.

State-read-heavy lifecycle commands have a repeatable built-binary baseline in state-read-performance-baseline.json. Refresh it after intentional state-read performance work:

Terminal window
go run ./internal/perfbaseline/cmd/state-read-baseline \
-mode refresh \
-out state-read-performance-baseline.json

The tool builds a temporary slipway binary unless -binary <path> is passed, creates a synthetic fixture by default, warms each command once, and records the fastest of seven timed samples for:

  • root worktree status --json;
  • bound worktree status --json;
  • bound worktree next --json --diagnostics;
  • bound worktree validate;
  • root worktree status --json --change <slug>.

The default fixture includes at least 25 Git worktrees, 300 change.yaml files, and 100 verification records. Temporary fixture directories are removed after the run unless -keep-fixture is set.

Check a new local measurement against the committed baseline with the default 30% real-time regression budget. Check mode requires an explicit -out path so it cannot overwrite the committed baseline by accident:

Terminal window
go run ./internal/perfbaseline/cmd/state-read-baseline \
-mode check \
-baseline state-read-performance-baseline.json \
-out /tmp/slipway-state-read-current.json

The check reports the specific command whose real_ms exceeds the allowed threshold. By default it runs up to three independent measurement attempts and passes as soon as one attempt stays within the 30% budget; persistent regressions must exceed the budget on every attempt. Write the output measurement to a temporary path or to the active change’s ignored verification/ directory when keeping local governed evidence.

Refresh generated AI-tool surfaces after changing templates or command contracts:

Terminal window
slipway init --tools all --refresh

Check generated path changes before committing. Codex command surfaces live under .codex/skills/slipway-<command>/SKILL.md; Codex refresh no longer touches host-global $CODEX_HOME/prompts files.

Before done:

  1. Confirm go run . validate reports the relevant active-change gates approved. This is a pre-archive freshness/readiness gate, not a promise that the same archived bundle can be revalidated after done.
  2. Confirm task evidence is fresh for the current run version.
  3. Confirm git diff --check.
  4. Stage intended files only.
  5. Confirm git diff --cached --check.
  6. Run slipway done when the change is done-ready. The active change bundle does not need a pre-done commit.
  7. If worktree_dirty_warning is returned, the change is already archived; commit the listed worktree_dirty_files together with the archived bundle before removing the worktree.

After done, use the archived change.yaml and bundle contents as frozen project records. validate --change <slug> intentionally rejects archived slugs with archived_change_not_validatable; a read-only archived audit would be a separate command surface.