docs: update specification — fix invariant precedence chain (3-tier→4-tier) and document non_overridable flag #3268

Merged
freemo merged 1 commits from spec/update-m4-invariant-precedence-non-overridable into master 2026-04-05 21:12:59 +00:00
+11 -6
View File
@@ -89,7 +89,7 @@ The following standards are integrated into the architecture:
: A persisted choice point in a plan's decision tree, created during Strategize or Execute. Records the question, chosen option, alternatives, confidence score, rationale, context snapshot, and downstream dependencies. Types: `prompt_definition`, `invariant_enforced`, `strategy_choice`, `subplan_spawn`, `subplan_parallel_spawn`, among others. Supports targeted correction with selective subtree recomputation.
Invariant
: A natural-language constraint on plan execution scoped to global, project, action, or plan level. Action invariants are promoted to plan-level when the action is used, so the runtime precedence chain is three-tier: ==plan > project > global==. Reconciled by the Invariant Reconciliation Actor at the start of Strategize; recorded as `invariant_enforced` decisions that propagate to child plans.
: A natural-language constraint on plan execution scoped to global, project, action, or plan level. The runtime precedence chain is four-tier: ==plan > action > project > global==. Exception: global invariants marked `non_overridable` always win regardless of scope. Reconciled by the Invariant Reconciliation Actor at the start of Strategize; recorded as `invariant_enforced` decisions that propagate to child plans.
Automation Profile
: A named set of confidence thresholds (each `0.0``1.0`) gating which plan operations proceed automatically versus requiring human approval. `0.0` = always automatic; `1.0` = always manual. Eight built-in profiles (`manual` through `full-auto`). Custom profiles namespaced as `[[server:]namespace/]name`. Each profile composes a **Safety Profile** that controls hard safety constraints (sandbox, checkpoint, unsafe-tool gating, skill restrictions, cost/retry limits).
@@ -18977,7 +18977,7 @@ When the action is used:
2. The plan's automation profile is resolved (plan > action > project > global precedence)
3. Any invariants from the action are carried forward as plan-level invariants, combined with any `--invariant` flags provided
4. The plan enters the **Strategize** phase
5. The **Invariant Reconciliation Actor** computes the effective invariant view (resolving conflicts using plan > project > global precedence)
5. The **Invariant Reconciliation Actor** computes the effective invariant view (resolving conflicts using plan > action > project > global precedence)
6. The `strategy_actor` begins analyzing the project(s)
#### What Strategize Does
@@ -18988,7 +18988,7 @@ Strategize is:
* **read-only**, producing a plan of attack,
* responsible for gathering context from project resources,
* responsible for collecting applicable invariants (from global, project, action, and plan scopes), computing the effective invariant view via the **Invariant Reconciliation Actor** (applying plan > project > global precedence), and recording them as `invariant_enforced` decisions,
* responsible for collecting applicable invariants (from global, project, action, and plan scopes), computing the effective invariant view via the **Invariant Reconciliation Actor** (applying plan > action > project > global precedence), and recording them as `invariant_enforced` decisions,
* responsible for generating a strategy and child plan blueprint (using `subplan_spawn` and `subplan_parallel_spawn` decisions),
* not allowed to execute child plans or modify resources.
@@ -19598,10 +19598,13 @@ Invariants are named constraints that guide and constrain plan execution. They c
**Precedence and conflict resolution**: When invariants from different scopes conflict, narrower scopes override broader scopes:
* **Plan-level** invariants override **project-level** and **global-level** invariants.
* **Plan-level** invariants override **action-level**, **project-level**, and **global-level** invariants.
* **Action-level** invariants override **project-level** and **global-level** invariants.
* **Project-level** invariants override **global-level** invariants.
Note: Action invariants are carried forward as plan-level invariants when the action is used (see **Action invariants** above), so they participate in precedence at the plan tier — there is no separate action tier in the precedence chain.
Exception: **Non-overridable global invariants** (marked `non_overridable: true`) always take precedence over all other scopes, including plan-level invariants. See below.
The full precedence chain (highest to lowest): `plan > action > project > global`.
Conflict resolution is performed by the **Invariant Reconciliation Actor** — a dedicated actor responsible for comparing invariants across scopes, identifying conflicts, and producing the final **effective invariant view** for a plan. The Invariant Reconciliation Actor is set at three levels via `--invariant-actor`:
@@ -19615,11 +19618,13 @@ The lookup order is: plan → project → global config. The first Invariant Rec
1. Collecting all invariants from global, project, plan, and action scopes.
2. Identifying conflicts (invariants from different scopes that contradict each other).
3. Applying precedence rules (plan > project > global) to resolve conflicts.
3. Applying precedence rules (plan > action > project > global) to resolve conflicts, with non-overridable global invariants taking absolute precedence.
4. Producing the final set of effective invariants.
Each effective invariant is then recorded as an `invariant_enforced` decision in the plan's decision tree. This makes invariants visible, auditable, and correctable through the standard decision correction mechanism.
**Non-overridable global invariants**: A global invariant may be marked `non_overridable: true`. When set, this invariant takes precedence over all lower-scope invariants regardless of the normal precedence chain -- even plan-level invariants cannot override it. This is intended for system-wide safety constraints that must never be relaxed (e.g., "Never commit secrets to version control"). Non-overridable invariants are set via `agents invariant add --global --non-overridable "<constraint>"`. The `non_overridable` flag is only meaningful on `GLOBAL`-scoped invariants; it is ignored on project, action, and plan invariants.
**Child plan inheritance**: When a top-level plan spawns child plans, the parent's effective invariant view (already reconciled) is passed down to each child plan. Child plans do not re-run reconciliation — they inherit the parent's resolved view.
**Correcting invariants**: The correction mechanism for `invariant_enforced` decisions supports two operations: