Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

RFC-0006: Loop Execution Model

Version: 0.4.0 | Status: normative | Phase: impl


1. Summary

[RFC-0006:C-SUMMARY] Summary (Informative)

This RFC defines the loop execution model for coordinating local agent execution rounds around one or more Work Items.

A loop is a first-class local execution concept that tracks one or more Work Items through dependency-aware rounds of implementation, verification evidence collection, and refinement. Loops support:

  • Single Work Item execution context: Create resumable local round state for one Work Item
  • Multi-Work Item batch execution context: Coordinate several Work Items with dependency resolution and deterministic readiness ordering
  • Failure and blocker propagation: Represent failed, blocked, or cancelled loop-level outcomes without adding new Work Item lifecycle states
  • Resumption: Resume interrupted execution from loop state and round artifacts

The loop model maintains clear separation between:

  • Work Items: Durable outcome artifacts that contain scope (description), success criteria (acceptance_criteria), durable memory (notes), references, dependencies, and verification policy
  • Loop state: Local execution state that tracks rounds, selected work, summary evidence, blockers, and next action

This separation ensures Work Items remain clean outcome artifacts while enabling rich local execution traceability for debugging and resumption.

Loops interact with Work Item lifecycle exclusively through existing govctl work semantics. govctl loop run advances local round state; it does not implement code, tick acceptance criteria, add notes, or mark Work Items done on behalf of the agent.

Tags: core

Since: v0.1.0


2. Specification

[RFC-0006:C-LOOP-DEFINITION] Loop Definition (Normative)

A loop is a local execution session that coordinates one or more Work Items through iterative rounds of agent implementation, verification evidence collection, and refinement.

Each loop MUST:

  1. Be initialized from an explicit, finite root set of Work Items
  2. Resolve the transitive dependency closure before execution begins
  3. Recompute the transitive dependency closure after any successful scope mutation defined by RFC-0006:C-LOOP-SCOPE-MUTATION
  4. Track execution state independently of Work Item files
  5. Store transient round evidence in loop-local artifacts rather than Work Item fields
  6. Terminate when all Work Items in the current resolved loop set reach terminal loop-level outcomes or a failure condition is met

A loop MAY support explicit scope mutation after start. A scope mutation MUST be requested through loop commands; implementations MUST NOT treat unrelated Work Item file edits as implicit loop scope changes.

A loop MUST NOT:

  1. Modify Work Item files directly except by invoking existing govctl work command semantics where explicitly required
  2. Persist execution trace to Work Item fields; execution trace belongs in loop state and round artifacts
  3. Assume a specific implementation order (sequential or parallel) beyond dependency readiness
  4. Introduce parallel replacements for Work Item notes, depends_on, acceptance criteria, or verification guards

Rationale: Loops are a first-class execution concept that coordinates Work Item completion without becoming a second Work Item model. By keeping loops separate from Work Item files, govctl preserves the boundary between local execution trace (ephemeral) and governance artifacts (durable). Work Item notes hold durable constraints and learnings that should survive future work; loop state holds transient execution evidence. Explicit scope mutation lets long cleanup loops adapt without replacing the execution session identity.

Tags: core

Since: v0.1.0

[RFC-0006:C-LOOP-LIFECYCLE] Loop Lifecycle (Normative)

A loop MUST have exactly one of the following lifecycle states:

  1. pending — Initial state. The loop is defined but execution has not started.
  2. active — The loop is currently executing rounds on work items.
  3. paused — Execution stopped before a terminal outcome and may be resumed.
  4. completed — All work items in the resolved loop set reached non-failed terminal loop outcomes (done or cancelled) without any failed or blocked loop outcomes.
  5. failed — A failure condition was met (max rounds exceeded, critical error, failed work item, or blocked dependency chain).

Valid transitions:

  • pending → active (loop execution begins)
  • active → paused (loop pauses for resumption)
  • paused → active (loop execution resumes)
  • active → completed (all work items finish without failed or blocked outcomes)
  • active → failed (failure condition met)
  • paused → failed (resumption detects unrecoverable state)

Invalid transitions (MUST be rejected):

  • completed → any (terminal state)
  • failed → any (terminal state)
  • pending → completed (cannot complete without being active)
  • pending → failed (cannot fail without being active)
  • paused → completed (completion requires active execution)

Rationale: The loop lifecycle provides clear semantics for tracking execution progress and enables resumption after interruption. A distinct paused state avoids overloading pending, which means execution has not started. Terminal states (completed, failed) indicate the loop has finished and cannot be restarted.

Tags: lifecycle, core

Since: v0.1.0

[RFC-0006:C-DEPENDENCY-SEMANTICS] Work Item Dependency Semantics (Normative)

Work items MAY declare dependencies on other work items using the depends_on field in the [govctl] section. The depends_on field MUST contain a list of work item IDs.

The depends_on field is an optional Work Item metadata field for repositories implementing this RFC. Implementations that validate Work Items against a JSON Schema MUST include govctl.depends_on as an optional array of Work Item IDs in that schema.

At loop start, and after every scope mutation, the loop MUST resolve the dependency closure for the current explicit root set. The resolved loop set MUST include every transitive depends_on dependency needed by the current root set. If any dependency ID does not identify an existing Work Item, the loop start or scope mutation MUST be rejected before the new state becomes authoritative.

Dependency rules:

  1. Acyclicity: The dependency graph MUST be acyclic. Implementations MUST detect cycles at loop start and after scope mutation and reject the operation before the new state becomes authoritative. The diagnostic MUST include at least one Work Item ID from the detected cycle.

  2. Selection readiness: A work item MUST NOT be selected for new round work until every dependency has a terminal loop-level outcome.

  3. Outcome checking: After a dependency reaches a terminal loop-level outcome, the loop MUST check that outcome:

    • If all dependencies are done: the dependent work item MAY be selected for round work
    • If any dependency is cancelled, failed, or blocked: the dependent work item MUST be marked as blocked in loop state and MUST NOT be selected
  4. Distinction from refs: The depends_on field is distinct from refs:

    • refs: informational cross-references to related artifacts (RFCs, ADRs, work items)
    • depends_on: blocking execution dependencies (work items only)
  5. Failure propagation: When a work item is marked as blocked, all work items that depend on it (directly or transitively) MUST also be marked as blocked.

Loop-level status tracking: The blocked, failed, and cancelled states are loop-level execution statuses tracked in loop state, not additional Work Item status field values. Work Items maintain their own lifecycle states (queue, active, done, cancelled) per RFC-0001:C-WORK-STATUS. A Work Item with Work Item status cancelled MUST be represented as cancelled in loop state when it is part of the resolved loop set.

Rationale: Dependencies enable complex workflows where work items must be selected in a specific order. By keeping depends_on separate from refs, we maintain clear semantics: refs are informational, depends_on are blocking. Resolving a dependency closure preserves an explicit root set while ensuring the loop has every prerequisite needed for deterministic planning. Re-resolving after explicit scope mutation lets a long-running loop adapt to corrected or newly discovered work without losing its execution session. Loop-level status tracking avoids polluting the Work Item status field with execution-specific states.

Tags: lifecycle, validation, work-items

Since: v0.1.0

[RFC-0006:C-ROUND-EXECUTION] Round Execution (Normative)

Loop rounds are local execution-protocol checkpoints for one loop, not automatic implementation performed by govctl.

A loop round MAY cover one or more work items from the loop’s current resolved dependency closure. The selected work set for a round MUST be derived from the loop state, dependency readiness, and any explicit --work selector accepted by RFC-0006:C-LOOP-COMMAND-SURFACE.

Round lifecycle:

Each round MUST have one of these local round states:

  1. open — govctl has created the round skeleton and the agent is expected to implement, verify, and fill the summary evidence.
  2. submitted — the round summary evidence has been provided but has not yet been incorporated into authoritative loop state.
  3. closed — govctl has validated the round evidence and updated loop state.

govctl loop run LOOP-ID MUST advance the local round protocol. It MUST NOT implement repository changes itself. It MUST NOT mark a Work Item done directly merely because loop-local criteria appear satisfied. Work Item lifecycle transitions remain owned by govctl work move per RFC-0002:C-LIFECYCLE-VERBS.

Opening a round:

When no open round exists, loop run MUST:

  1. Load and validate the loop state.
  2. Re-read current Work Item files for the selected work set.
  3. Verify dependency readiness using RFC-0006:C-DEPENDENCY-SEMANTICS.
  4. Create a loop-level round artifact under the loop directory.
  5. Write a summary skeleton that records where the agent MUST provide actions, changed paths, verification evidence, blockers, and note candidates.
  6. Display the round artifact path and the next required agent action.

Opening a round MAY update loop-local item statuses and round counters, but MUST NOT write transient execution trace into Work Item files.

Closing a round:

When an open round exists, loop run MUST validate the round summary before advancing loop state. A round summary MUST distinguish:

  • actions performed during the round
  • changed paths or explicitly state that no file changes were made
  • verification evidence, including existing govctl verify --work WI-ID or project guard output when applicable
  • blockers or open questions
  • note candidates that may become durable Work Item notes through explicit govctl work add <WI-ID> notes ...

If required summary evidence is missing, loop run MUST return a Diagnostic that names the round artifact to complete and MUST leave loop state unchanged.

If blockers prevent progress, loop run MUST keep the loop non-terminal and record the next action in loop state. Durable retry rules MAY be added to Work Item notes, but only through explicit Work Item commands.

If the relevant Work Items have already reached terminal Work Item lifecycle states through govctl work move, loop run MUST reflect those lifecycle states in loop-local item status and MAY mark the loop completed when every current resolved item is terminal without failed or blocked loop outcomes.

Rationale: govctl can coordinate local execution state, Work Item metadata, dependency readiness, and verification evidence, but the agent performs implementation work. This keeps loop execution trace in local loop artifacts, preserves Work Items as durable outcome artifacts, and reuses existing notes, depends_on, verify, and work move mechanisms instead of inventing parallel systems.

Tags: core, validation

Since: v0.1.0

[RFC-0006:C-WORK-ITEM-INTERACTION] Work Item Interaction (Normative)

Loops interact with work items by reading Work Item lifecycle state, mapping it into loop-local item state, and recording local execution evidence. Loops MUST NOT own Work Item lifecycle transitions.

Lifecycle ownership:

  1. Work Items in the resolved loop set MUST remain valid Work Items whose lifecycle state is one of queue, active, done, or cancelled.
  2. govctl loop run MUST NOT transition a Work Item from queue to active.
  3. govctl loop run MUST NOT transition a Work Item from active to done.
  4. Work Item lifecycle transitions remain owned by govctl work move and its existing acceptance-criteria and verification-guard gates.
  5. A Work Item with lifecycle state done MUST be represented as done in loop state when reflected by a loop operation.
  6. A Work Item with lifecycle state cancelled MUST be represented as cancelled in loop state when reflected by a loop operation and MUST NOT be selected for new round work.

Validation requirements:

Before a Work Item is transitioned to done, the Work Item lifecycle command MUST verify the existing gate conditions defined by RFC-0001:C-GATE-CONDITIONS. A loop MAY record verification evidence in round summary artifacts, but that evidence does not replace the Work Item lifecycle gate.

Durable work item context:

The work item notes field is reserved for durable context that should persist across sessions:

  • Key decisions made during implementation
  • Blockers encountered and how they were resolved
  • Important technical insights

Execution trace, including round-by-round progress, MUST be tracked in loop state and round artifacts, not in Work Item fields.

Loop-level work item status:

The loop tracks additional execution status for each work item in loop state:

  • pending: Work item has not been selected or reflected as active/done/cancelled in this loop
  • active: Work item is selected for local execution protocol or remains in progress
  • done: Work item completed successfully through Work Item lifecycle state
  • failed: Local loop execution evidence records an unrecoverable failure and dependents must not be selected
  • blocked: Work item cannot be selected because dependencies failed, blocked, or were cancelled
  • cancelled: Work item has Work Item status cancelled and is not selected

The loop-level statuses are independent of Work Item status field values except where explicitly mapped above. done, failed, blocked, and cancelled are terminal loop-level outcomes for dependency planning.

Rationale: Existing Work Item commands already provide lifecycle validation, acceptance criteria, verification guards, and durable governance history. Loops provide resumable local execution protocol state around those commands without becoming a second Work Item lifecycle engine. Separating loop-level status from Work Item status and notes maintains clear boundaries between execution state and governed artifacts.

Tags: lifecycle, validation, work-items

Since: v0.1.0

[RFC-0006:C-LOOP-RESUMPTION] Loop Resumption (Normative)

A loop MAY be paused and resumed across CLI invocations or agent sessions.

If a loop implementation supports resumption, it MUST:

  1. Persist loop state using the storage contract defined by RFC-0006:C-LOOP-STATE-STORAGE
  2. Resume existing loop operations by positional LOOP-ID as defined by RFC-0006:C-LOOP-COMMAND-SURFACE
  3. Resume from the last recorded state and open round artifact rather than starting fresh when the requested loop state exists and is non-terminal
  4. Reject operations that require a non-terminal loop when the loop is terminal

Discovery semantics:

Loop discovery MUST be separate from loop execution. Implementations MAY discover existing loops by listing persisted state, by filtering list output, or by reusing an existing non-terminal loop during loop start [--id LOOP-ID] WI-ID... when the requested work set matches exactly.

A stored loop matches a requested work set when its current editable work field contains the same Work Item IDs as the request, ignoring order. If a command performs work-set discovery and exactly one matching non-terminal loop exists, the implementation MAY select that loop. If more than one matching non-terminal loop exists, the implementation MUST reject the discovery attempt as ambiguous and require a positional LOOP-ID.

loop run MUST NOT perform work-set discovery and MUST NOT start a new loop.

Resumption semantics:

When resuming a loop:

  • Work items in done loop state MUST NOT be selected for new round work
  • Work items in active loop state MAY be selected again only through the local round protocol
  • Work items in blocked, failed, or cancelled loop state MUST remain terminal for dependency planning unless an explicit scope mutation recomputes a dependency-derived blocked outcome
  • Work items in pending loop state MAY be selected in dependency order when opening a round unless an explicit run selector narrows execution per RFC-0006:C-LOOP-COMMAND-SURFACE
  • If loop.current_round points at an open round artifact, loop run MUST validate or reject that artifact before opening another round

State preservation:

The loop state MUST preserve:

  • Execution status of each current work item (pending, active, done, failed, blocked, cancelled)
  • Round count for each current work item
  • Last selected round for each current work item when known
  • Current editable work field values
  • Dependency graph at last planning time
  • Current loop-level round number when known
  • Next required action when known

The loop state MAY preserve:

  • Detailed round history
  • Guard execution result summaries
  • Agent context and decision history inside local round artifacts

Rationale: Resumption enables long-running multi-WI loops to survive agent session boundaries without losing progress. Positional loop IDs provide precise lookup that matches the CLI’s noun/verb/object shape. Work-set matching remains a discovery convenience for start/list workflows, not an execution command mode. By persisting state independently of work item files, we maintain the separation between execution state and governed artifacts. Scope mutation makes the stored work set current rather than historical, so discovery continues to match the loop the user intends to resume.

Tags: lifecycle

Since: v0.1.0

[RFC-0006:C-LOOP-STATE-STORAGE] Loop State Storage (Normative)

Loop execution state MUST be stored under .govctl/loops/<loop-id>/.

A loop ID is local execution-state identity, not a governed resource ID. A generated loop ID MUST match ^LOOP-\d{4}-\d{2}-\d{2}-\d{3}$. The date component MUST use ISO 8601 calendar date format YYYY-MM-DD for the local date when the ID is generated. The sequence component MUST be a three-digit positive sequence starting at 001 for each date. Implementations MUST choose the first available sequence for the date that does not collide with an existing .govctl/loops/<loop-id>/ directory. Implementations MUST generate a loop ID when one is omitted. Implementations MUST reject explicit loop IDs that do not match the canonical loop ID pattern. A loop ID MUST NOT contain /, \, or .. path traversal segments.

Each loop directory MUST contain state.toml as its authoritative current-state file. The state.toml file MUST use the following top-level shape:

[loop]
id = "<loop-id>"
state = "pending|active|paused|completed|failed"
work = ["WI-YYYY-MM-DD-NNN"]
resolved = ["WI-YYYY-MM-DD-NNN"]
current_round = 0
next_action = "start|write_summary|continue|resolve_blocker|complete"

[dependencies]
"WI-YYYY-MM-DD-NNN" = ["WI-YYYY-MM-DD-NNN"]

[items."WI-YYYY-MM-DD-NNN"]
status = "pending|active|done|failed|blocked|cancelled"
round_count = 0
last_round = 0

The loop.id value MUST match the <loop-id> directory name. The loop.state value MUST be one of the loop lifecycle states defined by RFC-0006:C-LOOP-LIFECYCLE. The loop.work array MUST preserve the current explicit work item set for the loop. The loop.resolved array MUST contain the current resolved dependency closure and MUST include every loop.work entry. The loop.work and loop.resolved arrays MUST NOT contain duplicate Work Item IDs.

The optional loop.current_round value records the latest loop-level round number known to state. The optional loop.next_action value records the next required human or agent action. Older state files that omit these fields MAY be upgraded in place when written.

The [dependencies] table MUST contain one entry for each work item in loop.resolved. Each dependency entry MUST be an array of Work Item IDs. Each dependency ID MUST also appear in loop.resolved. Dependency arrays MUST NOT contain duplicate Work Item IDs.

The [items.<WI-ID>] table MUST contain one entry for each work item in loop.resolved. Each item status MUST be one of the loop-level work item statuses defined by RFC-0006:C-WORK-ITEM-INTERACTION. Each round_count MUST be a non-negative integer. The optional last_round value records the last loop-level round that selected or updated the item.

Loop state storage MUST be keyed by loop ID, not by work item ID. A multi-work-item loop MUST have one shared loop state root so dependency planning, failure propagation, and resumption use the same authoritative state.

Loop round artifacts MUST be stored under .govctl/loops/<loop-id>/rounds/round-NNN.toml, where NNN is the three-digit loop-level round number. A round artifact MUST identify the loop ID, round number, selected work item IDs, round state, summary evidence, blockers, and note candidates. Round artifacts are local execution trace and MUST NOT be written to Work Item fields.

Round artifacts MAY mention Work Item IDs when evidence applies to specific work, but the storage root is loop-level. Implementations MUST NOT require per-work-item round directories for the canonical state model.

Loop state is local execution state, not a governed artifact. Deleting .govctl/loops/ MUST NOT invalidate RFCs, ADRs, Work Items, Guards, or rendered governance projections, but MAY remove resumability and local execution trace.

Rationale: A loop can drive multiple work items, so a per-work-item state root cannot represent the loop lifecycle, dependency graph, aggregate outcome, or round evidence. A single loop directory keeps execution state separate from Work Item files while preserving enough protocol state for resumption. Canonical generated loop IDs follow the existing artifact style of a type prefix, date, and sequence while avoiding collision-prone plain-text IDs.

Tags: core

Since: v0.1.0

[RFC-0006:C-LOOP-SCOPE-MUTATION] Loop Scope Mutation (Normative)

A loop implementation MAY support explicit scope mutation for a non-terminal loop. A scope mutation changes or refreshes the loop’s current editable work field and recomputes the resolved dependency closure without creating a new loop ID.

Scope mutation MUST support these operations:

  1. Replan: keep the current editable work field and recompute its dependency closure from the current work item files.
  2. Add work: add one Work Item ID to the current editable work field, then recompute the dependency closure.
  3. Remove work: remove one Work Item ID from the current editable work field, then recompute the dependency closure.

Implementations MUST reject scope mutation for terminal loops. Implementations MUST reject scope mutation that would leave the editable work field empty. Implementations MUST validate added or removed work values as Work Item IDs. Implementations MUST store the explicit work set without duplicates.

A scope mutation MUST build a candidate loop state before replacing the stored state. The candidate state MUST use the current explicit work set after the requested add/remove/replan operation. The candidate state MUST resolve dependencies using the rules in RFC-0006:C-DEPENDENCY-SEMANTICS. If dependency resolution fails, the implementation MUST leave the previously stored loop state unchanged.

For work items that remain in the resolved dependency closure, scope mutation MUST preserve round_count. Scope mutation MUST preserve explicit terminal execution outcomes done, failed, and cancelled. Scope mutation MUST recompute blocked outcomes from the current dependency graph and current terminal dependency outcomes; a previously blocked work item MAY return to pending when its current dependencies no longer require blocking. Non-terminal work items MUST NOT be selected for a new round until their current dependencies satisfy RFC-0006:C-DEPENDENCY-SEMANTICS.

For newly introduced work items, scope mutation MUST initialize loop-level item state using the same Work Item status mapping used at loop start. For work items that no longer appear in the resolved dependency closure, scope mutation MUST remove their entries from loop.resolved, [dependencies], and [items] in state.toml. Removing a work item from current loop state MUST NOT undo any Work Item lifecycle transitions that already happened through govctl work commands. Optional historical round artifacts for removed work items MAY remain under the loop directory, but they MUST NOT be treated as part of the current loop state.

Rationale:

Long-running cleanup and implementation loops often discover that the original batch is missing work, contains unnecessary work, or needs dependency files re-read after edits. Scope mutation keeps one execution session identity while making the current work field and dependency closure explicit, validated, and recoverable. Modeling this as a field mutation keeps loop commands aligned with the existing edit model while preserving loop-specific replanning behavior.

Since: v0.2.0

[RFC-0006:C-LOOP-LISTING] Loop Listing (Normative)

If provided, the listing command MUST enumerate persisted loop state from .govctl/loops/*/state.toml without requiring a caller to know a loop ID or work item set first. The command MUST validate each canonical loop state it lists using the storage contract in RFC-0006:C-LOOP-STATE-STORAGE.

The listing command MUST produce deterministic output ordered by loop ID. Each listed loop MUST include at least the loop ID, lifecycle state, editable work field values, resolved work item count, and aggregate round count across current loop items. Machine-readable output, when supported, MUST expose the same user-facing fields.

The listing command MAY support filters by lifecycle state, loop ID substring, or work item ID substring. Filtering MUST NOT mutate loop state and MUST NOT select a loop for execution by itself.

Rationale: Work-set discovery is useful only after the caller has a stable loop identity. A listing command gives agents and humans a stable discovery entrypoint for interrupted or long-running batch loops while preserving the rule that loop state remains local execution state rather than a governed artifact. The caller can then pass the listed loop ID as the positional object to commands such as loop run, loop show, or loop resume.

Since: v0.3.0

[RFC-0006:C-LOOP-COMMAND-SURFACE] Loop Command Surface (Normative)

Implementations that expose a govctl loop command MUST treat it as a project-level local execution-state command namespace as defined by RFC-0002:C-GLOBAL-COMMANDS. Loop state is not a governed artifact resource, so loop commands MUST NOT expose unrestricted resource CRUD field-editing verbs for arbitrary loop state. Loop commands MAY expose specified editable fields whose semantics are defined by this RFC.

Argument roles:

Loop command arguments MUST have stable roles:

  1. A positional LOOP-ID argument identifies an existing persisted local loop state directory.
  2. A --id LOOP-ID flag MAY be used only by commands that create a loop state, where it requests the ID to create or reuse.
  3. Positional WI-ID... arguments identify explicit loop work field values for loop creation or field mutation.
  4. Positional WI-ID... arguments MUST NOT mean an execution target subset.
  5. Execution target selection MUST use an explicit selector flag.
  6. Loop field mutation MUST use the same add and remove field-position shape used by governed artifact resources.

Canonical subcommands:

The canonical loop subcommands are:

  1. loop list [filter]: read persisted loop states. This command MUST be read-only.
  2. loop show LOOP-ID: read one persisted loop state by loop ID. This command MUST be read-only.
  3. loop start [--id LOOP-ID] WI-ID...: create or reuse a loop for an explicit work field set.
  4. loop resume LOOP-ID: select and display an existing non-terminal loop by loop ID. This command MUST be read-only and MUST NOT advance rounds.
  5. loop run LOOP-ID [--work WI-ID ...] [--max-rounds N]: advance the local round protocol for an existing loop state.
  6. loop replan LOOP-ID: recompute the dependency closure for the current explicit work field set.
  7. loop add LOOP-ID work WI-ID: add a Work Item ID to the loop’s editable work field and replan.
  8. loop remove LOOP-ID work WI-ID: remove a Work Item ID from the loop’s editable work field and replan.

The work field is the only canonical user-facing field name for the loop’s explicit work set. Implementations MUST accept wi as a shorthand alias for work. User-facing help SHOULD prefer loop add LOOP-ID work WI-ID and loop remove LOOP-ID work WI-ID while documenting the alias.

Discovery semantics:

loop start [--id LOOP-ID] WI-ID... MAY reuse an existing non-terminal loop with the same current explicit work field set instead of creating a new loop. If more than one non-terminal loop matches the requested work set, the implementation MUST reject the operation as ambiguous and require the caller to use loop list and then pass a positional LOOP-ID to the desired operation.

loop list [filter] MUST support discovering loop state without requiring a caller to know a loop ID first per RFC-0006:C-LOOP-LISTING. Work-set discovery is a discovery behavior, not an execution selector.

loop run MUST NOT start a new loop and MUST NOT discover a loop by positional Work Item IDs. It operates only on the positional LOOP-ID argument.

Run selection semantics:

The --work WI-ID flag selects execution targets inside the loop identified by the positional LOOP-ID. Implementations MUST reject duplicate --work values. Implementations MUST reject any --work value that is not a Work Item ID in the current loop.resolved array. These validations MUST complete before writing loop state.

If no --work selector is provided, loop run LOOP-ID MUST consider every current work item in the loop’s resolved dependency closure when opening a round, subject to dependency readiness.

If one or more --work selectors are provided, loop run LOOP-ID --work WI-ID... MUST restrict the opened or advanced round to the selected target work items and their current in-loop transitive dependencies. The implementation MUST NOT select unrelated work items for that round. The implementation MAY update derived loop-level dependency outcomes, such as blocked dependents, when required to keep loop state consistent with RFC-0006:C-DEPENDENCY-SEMANTICS.

Targeted run selection MUST NOT replace, shrink, expand, or otherwise mutate the loop’s editable work field. Scope changes MUST use replan, add, or remove.

loop run MUST NOT silently perform repository implementation work, tick acceptance criteria, add Work Item notes, or move Work Items to done. Agents and humans MUST perform those operations through the existing Work Item and verification command surfaces. loop run records and validates local round evidence so those existing operations have resumable execution context.

Rationale:

The loop command namespace coordinates several governed resources but stores its own local execution state, so it is neither a governed artifact resource nor a simple single global command. Existing-loop operations use positional LOOP-ID arguments to match the rest of the CLI’s noun/verb/object shape. Stable argument roles prevent hidden mode switches: positional work item IDs in add and remove are field values for the loop’s work field, while --work is the explicit work-item execution selector. Keeping the field position visible preserves the CLI edit model while making loop-specific replanning a domain side effect of changing the field. Reusing run as the round-protocol advancement command preserves existing skill guidance while removing the misleading interpretation that govctl itself implements code.

Since: v0.4.0


3. Rationale

[RFC-0006:C-UNIFIED-MODEL] Unified Model Rationale (Informative)

The unified loop model (single primitive for both single-WI and multi-WI execution) was chosen over separate /loop and /batch skills because:

  1. Work items naturally form DAGs: Agents frequently create multiple related work items with dependencies, then iterate through them as a batch. Separate skills would force users to choose between /loop WI-001 and /batch WI-001 WI-002 WI-003 when the underlying mechanism is identical.

  2. Simpler mental model: “A loop drives work items to completion” is one concept. “A loop drives one work item, a batch drives multiple” is two concepts with overlapping semantics.

  3. Consistent state model: .govctl/loops/<loop-id>/ works the same whether the loop contains one work item or ten. Execution logs, state file, and round logs scale naturally.

  4. Downstream flexibility: The loop does not prescribe sequential or parallel execution. Downstream applications (agents, CI systems) can choose the execution model that fits their constraints.

Tags: core

Since: v0.1.0

[RFC-0006:C-EXECUTION-STATE-SEPARATION] Execution State Separation Rationale (Informative)

Execution state lives in .govctl/loops/<loop-id>/ (not in work item TOML) because:

  1. Work items are outcome artifacts: They should contain scope (description), success criteria (acceptance_criteria), and durable context (notes). They should not accumulate execution logs during active work.

  2. Rich execution traceability: Loops need to track round-by-round progress, guard results, criteria addressed per round, and detailed logs. This is too much data for a work item TOML file.

  3. Clean diffs: Work item TOML files remain stable and reviewable. Execution state changes frequently during a loop and is not meant for code review.

  4. Ephemeral by design: Loop state is local to the developer’s machine. It can be deleted without losing governance artifacts. The work item’s notes field captures durable learnings.

  5. Shared loop coordination: Multi-work-item loops need one state root for lifecycle, dependency graph, failure propagation, and resumption. A per-work-item state root would force the loop to reconstruct shared state from fragments.

Tags: core

Since: v0.1.0

[RFC-0006:C-DEPENDENCY-SEPARATION] Dependency Separation Rationale (Informative)

The depends_on field is separate from refs because they serve different purposes:

  • refs: Informational cross-references (“this work item is related to that RFC”). Does not block execution. Used for traceability and navigation.

  • depends_on: Execution dependencies (“this work item cannot start until that work item completes”). Blocks execution. Used for dependency resolution and failure propagation.

Conflating these would force the loop to guess whether a ref is a hard dependency or just a related artifact. Separate fields make intent explicit.

Tags: core, work-items

Since: v0.1.0


Changelog

v0.4.0 (2026-06-03)

Define loop command surface

Added

  • Loop command surface defines canonical loop subcommands and argument roles

Changed

  • Loop run advances an existing local round protocol by LOOP-ID with explicit –work target selection

v0.3.0 (2026-06-01)

Define loop listing discovery

Added

  • Loop listing command discovers persisted local loop state

v0.2.0 (2026-06-01)

Define loop scope mutation and canonical loop IDs

Added

  • Loop scope mutation supports replan plus add/remove of the editable work field

Changed

  • Loop IDs use LOOP-YYYY-MM-DD-NNN canonical format

v0.1.0 (2026-05-31)

Initial draft