diff --git a/docs/specification.md b/docs/specification.md
index dbe7bd381..094995923 100644
--- a/docs/specification.md
+++ b/docs/specification.md
@@ -361,7 +361,7 @@ The following standards are integrated into the architecture:
agents config list [--filter-values <REGEX>] [<REGEX>]
agents invariant add [--global] [(--project|-p) PROJECT] [--plan PLAN_ID]...
- [--action ACTION]... <INVARIANT_TEXT>
+ [--action ACTION]... [--non-overridable] <INVARIANT_TEXT>
agents invariant list [--global] [(--project|-p) PROJECT] [--plan PLAN_ID] [--action ACTION]
[--effective] [<REGEX>]
agents invariant remove [--yes|-y] <INVARIANT_ID>
@@ -17884,7 +17884,7 @@ None.
##### agents invariant add
agents invariant add [--global] [(--project|-p) PROJECT] [--plan PLAN_ID]...
- [--action ACTION]... <INVARIANT_TEXT>
+ [--action ACTION]... [--non-overridable] <INVARIANT_TEXT>
**Purpose**
Add an invariant at the specified scope.
@@ -17896,6 +17896,7 @@ Add an invariant at the specified scope.
- `--project/-p PROJECT`: Attach to a project (applies to all plans targeting this project).
- `--plan PLAN_ID`: Attach to a plan (plan-level invariant). Repeatable.
- `--action ACTION`: Attach to an action (action-level invariant). Repeatable.
+- `--non-overridable`: Mark this invariant as non-overridable. **Only valid with `--global`.** When set, this global invariant takes absolute precedence over all other scopes — even plan-level invariants cannot override it. Intended for system-wide safety constraints that must never be relaxed (e.g., "Never commit secrets to version control"). Silently ignored if used with any non-global scope flag.
At least one scope flag (`--global`, `--project`, `--plan`, or `--action`) must be provided. `--plan` and `--action` can be repeated to attach the same invariant to multiple plans or actions.
@@ -17946,6 +17947,17 @@ At least one scope flag (`--global`, `--project`, `--plan`, or `--action`) must
╰────────────────────────────────────────────────────────────────────────╯
✓ OK Invariant added
+
+ $ agents invariant add --global --non-overridable "Never commit secrets to version control"
+
+ ╭─ Invariant Added ──────────────────────────────────────────────────────────╮
+ │ Invariant: Never commit secrets to version control │
+ │ Scope: global │
+ │ Non-overridable: true │
+ │ ID: inv_01HXM9J5C │
+ ╰────────────────────────────────────────────────────────────────────────────╯
+
+ ✓ OK Invariant added (non-overridable — takes absolute precedence over all scopes)
=== "Plain"
@@ -17989,6 +18001,16 @@ At least one scope flag (`--global`, `--project`, `--plan`, or `--action`) must
ID: inv_01HXM9H4B
[OK] Invariant added
+
+ $ agents invariant add --global --non-overridable "Never commit secrets to version control"
+
+ Invariant Added
+ Invariant: Never commit secrets to version control
+ Scope: global
+ Non-overridable: true
+ ID: inv_01HXM9J5C
+
+ [OK] Invariant added (non-overridable — takes absolute precedence over all scopes)
```
=== "JSON"
@@ -18063,7 +18085,7 @@ At least one scope flag (`--global`, `--project`, `--plan`, or `--action`) must
[--effective] [<REGEX>]
**Purpose**
-List invariants at a given scope. Use `--effective` with `--plan` to show the final reconciled view of invariants (after precedence resolution) rather than just the invariants directly attached at that scope.
+List invariants at a given scope. Use `--effective` with `--plan` or `--action` to show the final reconciled view of invariants (after precedence resolution) rather than just the invariants directly attached at that scope.
**Arguments**
@@ -18071,7 +18093,7 @@ List invariants at a given scope. Use `--effective` with `--plan` to show the fi
- `--project/-p PROJECT`: List invariants attached to a project.
- `--plan PLAN_ID`: List invariants attached to a plan.
- `--action ACTION`: List invariants attached to an action.
-- `--effective`: (Only with `--plan`) Show the reconciled invariant view after precedence resolution across all scopes.
+- `--effective`: Show the reconciled invariant view after precedence resolution across all scopes. Valid with `--plan` or `--action`. When used with `--plan`, shows the fully resolved effective invariant set for that plan (merging global, project, action, and plan scopes). When used with `--action`, shows the effective invariant set that would apply to any plan instantiated from that action (merging global and action scopes). Not valid with `--global` or `--project` alone (those scopes have no higher-priority overrides to merge).
**Examples**
@@ -18104,6 +18126,17 @@ List invariants at a given scope. Use `--effective` with `--plan` to show the fi
│ parameterized statements" │
✓ OK 3 effective invariants (1 global, 1 project, 1 plan; 1 conflict resolved)
+
+ $ agents invariant list --action local/deploy --effective
+
+ ╭─ Effective Invariants (Action local/deploy) ───────────────────────────────────────────╮
+ │ ID Source Text │
+ │ ────────────── ─────── ────────────────────────────────────────────────────── │
+ │ inv_01HXM9A1B global All public APIs must maintain backward compatibility │
+ │ inv_01HXM9H4B action Action requires approval before execution │
+ ╰───────────────────────────────────────────────────────────────────────────────────────╯
+
+ ✓ OK 2 effective invariants (1 global, 1 action)
=== "Plain"
@@ -18133,6 +18166,16 @@ List invariants at a given scope. Use `--effective` with `--plan` to show the fi
parameterized statements"
[OK] 3 effective invariants (1 global, 1 project, 1 plan; 1 conflict resolved)
+
+ $ agents invariant list --action local/deploy --effective
+
+ Effective Invariants (Action local/deploy)
+ ID Source Text
+ -------------- ------- --------------------------------------------------
+ inv_01HXM9A1B global All public APIs must maintain backward compatibility
+ inv_01HXM9H4B action Action requires approval before execution
+
+ [OK] 2 effective invariants (1 global, 1 action)
```
=== "JSON"
@@ -19798,8 +19841,8 @@ The system collects, reconciles, and checks invariants:
or self.get_global_invariant_actor()
)
- # 3. Reconcile: apply precedence (plan > project > global), resolve conflicts
- effective = reconciler.reconcile(raw, precedence=['plan', 'project', 'global'])
+ # 3. Reconcile: apply precedence (plan > action > project > global), resolve conflicts
+ effective = reconciler.reconcile(raw, precedence=['plan', 'action', 'project', 'global'])
return effective
def collect_all_invariants(self, plan):