Mode Guards and Convergence — Active Partner and Refinement Loop in the Mode Schema

Accepted

ontoref
Reflection modes executed procedures as typed DAGs but lacked two capabilities that caused real failures: (1) modes could run against projects in invalid states — missing ontology files, unavailable

Context

Reflection modes executed procedures as typed DAGs but lacked two capabilities that caused real failures: (1) modes could run against projects in invalid states — missing ontology files, unavailable tools, incomplete manifests — because preconditions were informational text, not executable checks. An agent following the protocol would execute sync-ontology on a project without core.ncl and get an opaque nickel error instead of a clear block. (2) Modes like sync-ontology require iteration — scan, diff, propose, apply, then verify that drift is zero. If drift remained after one pass, the mode reported success and the agent moved on. There was no mechanism for the protocol to say 'keep going until this condition is met'. Both gaps were identified during a systematic comparison against 45 augmented coding patterns (lexler.github.io/augmented-coding-patterns): Active Partner (#1) requires the system to push back on invalid actions, and Refinement Loop (#36) requires iteration until convergence. A separate action subsystem (ext/action) was considered and rejected in favor of extending the existing mode schema.

Decision

Extend reflection/schema.ncl with two new optional fields on ModeBase: guards (Array Guard) for pre-flight executable checks, and converge (Converge) for post-execution convergence loops. Guards run before any step and can Block (abort) or Warn (continue with message). Converge evaluates a condition command after all steps complete and re-executes failed or all steps up to max_iterations times. Both are backward-compatible — all existing modes export unchanged with guards defaulting to [] and converge being optional.

Constraints

  • Hard reflection/schema.ncl exports a Guard type with id, cmd, reason, and severity fields
  • Hard reflection/schema.ncl exports a Converge type with condition, max_iterations, and strategy fields
  • Hard The mode executor in reflection/nulib/modes.nu evaluates guards before executing steps

Alternatives considered

  • ext/action — separate action contract schema with gates, events, and convergencerejected: Creates a parallel execution abstraction competing with modes. Consumer projects would need to learn both modes and actions, and the boundary between them would be ambiguous. The mode schema already has steps, dependencies, and error strategies — guards and converge are natural extensions of the same concept.
  • Executable preconditions — make existing preconditions[] run commands instead of being textrejected: Preconditions serve a different purpose: they document what the human should verify. Making them executable would lose the documentation function. Guards are a separate concept: machine-checked pre-flight blocks. Both can coexist — preconditions for humans, guards for machines.
  • External convergence via Vapora workflows — let the orchestrator handle iterationrejected: Convergence is a property of the mode itself, not of the orchestrator. sync-ontology should declare that it iterates until zero drift regardless of whether it runs via CLI, Vapora, or CI. Pushing this to the orchestrator means every orchestrator must know which modes need iteration and under what conditions — that knowledge belongs in the mode contract.

Related ADRs

ADR-002

Was this useful? Rate it
Got something to add? Tell me what you think, what you'd suggest, or whether we should keep exploring this topic.
· reads

We use cookies to help this site function, understand service usage, and support marketing efforts. Cookie Policy for more info.