instar 1.3.759 → 1.3.760
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/PostUpdateMigrator.d.ts +15 -0
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +44 -0
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/testing/selfActionRegistry.d.ts +88 -0
- package/dist/testing/selfActionRegistry.d.ts.map +1 -0
- package/dist/testing/selfActionRegistry.js +202 -0
- package/dist/testing/selfActionRegistry.js.map +1 -0
- package/package.json +2 -2
- package/scripts/class-closure-declare.mjs +69 -4
- package/scripts/class-closure-lint.mjs +61 -5
- package/scripts/instar-dev-precommit.js +100 -2
- package/scripts/lib/self-action-detect.mjs +162 -0
- package/scripts/lint-no-unregistered-self-action.js +204 -0
- package/skills/instar-dev/templates/side-effects-artifact.md +8 -1
- package/src/data/builtin-manifest.json +19 -19
- package/upgrades/1.3.760.md +100 -0
- package/upgrades/side-effects/self-action-convergence.md +62 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "./builtin-manifest.schema.json",
|
|
3
3
|
"schemaVersion": 1,
|
|
4
|
-
"generatedAt": "2026-07-
|
|
5
|
-
"instarVersion": "1.3.
|
|
4
|
+
"generatedAt": "2026-07-04T20:03:31.063Z",
|
|
5
|
+
"instarVersion": "1.3.760",
|
|
6
6
|
"entryCount": 202,
|
|
7
7
|
"entries": {
|
|
8
8
|
"hook:session-start": {
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"domain": "identity",
|
|
12
12
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
13
13
|
"installedPath": ".instar/hooks/instar/session-start.sh",
|
|
14
|
-
"contentHash": "
|
|
14
|
+
"contentHash": "ae15e23b7525213595701aaac82b83f9ca3f74f99b0b6ab498930096d16ace7a",
|
|
15
15
|
"since": "2025-01-01"
|
|
16
16
|
},
|
|
17
17
|
"hook:dangerous-command-guard": {
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"domain": "safety",
|
|
21
21
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
22
22
|
"installedPath": ".instar/hooks/instar/dangerous-command-guard.sh",
|
|
23
|
-
"contentHash": "
|
|
23
|
+
"contentHash": "ae15e23b7525213595701aaac82b83f9ca3f74f99b0b6ab498930096d16ace7a",
|
|
24
24
|
"since": "2025-01-01"
|
|
25
25
|
},
|
|
26
26
|
"hook:grounding-before-messaging": {
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"domain": "safety",
|
|
30
30
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
31
31
|
"installedPath": ".instar/hooks/instar/grounding-before-messaging.sh",
|
|
32
|
-
"contentHash": "
|
|
32
|
+
"contentHash": "ae15e23b7525213595701aaac82b83f9ca3f74f99b0b6ab498930096d16ace7a",
|
|
33
33
|
"since": "2025-01-01"
|
|
34
34
|
},
|
|
35
35
|
"hook:compaction-recovery": {
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"domain": "identity",
|
|
39
39
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
40
40
|
"installedPath": ".instar/hooks/instar/compaction-recovery.sh",
|
|
41
|
-
"contentHash": "
|
|
41
|
+
"contentHash": "ae15e23b7525213595701aaac82b83f9ca3f74f99b0b6ab498930096d16ace7a",
|
|
42
42
|
"since": "2025-01-01"
|
|
43
43
|
},
|
|
44
44
|
"hook:external-operation-gate": {
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"domain": "safety",
|
|
48
48
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
49
49
|
"installedPath": ".instar/hooks/instar/external-operation-gate.js",
|
|
50
|
-
"contentHash": "
|
|
50
|
+
"contentHash": "ae15e23b7525213595701aaac82b83f9ca3f74f99b0b6ab498930096d16ace7a",
|
|
51
51
|
"since": "2025-01-01"
|
|
52
52
|
},
|
|
53
53
|
"hook:deferral-detector": {
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"domain": "safety",
|
|
57
57
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
58
58
|
"installedPath": ".instar/hooks/instar/deferral-detector.js",
|
|
59
|
-
"contentHash": "
|
|
59
|
+
"contentHash": "ae15e23b7525213595701aaac82b83f9ca3f74f99b0b6ab498930096d16ace7a",
|
|
60
60
|
"since": "2025-01-01"
|
|
61
61
|
},
|
|
62
62
|
"hook:self-stop-guard": {
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
"domain": "coherence",
|
|
66
66
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
67
67
|
"installedPath": ".instar/hooks/instar/self-stop-guard.js",
|
|
68
|
-
"contentHash": "
|
|
68
|
+
"contentHash": "ae15e23b7525213595701aaac82b83f9ca3f74f99b0b6ab498930096d16ace7a",
|
|
69
69
|
"since": "2025-01-01"
|
|
70
70
|
},
|
|
71
71
|
"hook:post-action-reflection": {
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
"domain": "evolution",
|
|
75
75
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
76
76
|
"installedPath": ".instar/hooks/instar/post-action-reflection.js",
|
|
77
|
-
"contentHash": "
|
|
77
|
+
"contentHash": "ae15e23b7525213595701aaac82b83f9ca3f74f99b0b6ab498930096d16ace7a",
|
|
78
78
|
"since": "2025-01-01"
|
|
79
79
|
},
|
|
80
80
|
"hook:external-communication-guard": {
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
"domain": "safety",
|
|
84
84
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
85
85
|
"installedPath": ".instar/hooks/instar/external-communication-guard.js",
|
|
86
|
-
"contentHash": "
|
|
86
|
+
"contentHash": "ae15e23b7525213595701aaac82b83f9ca3f74f99b0b6ab498930096d16ace7a",
|
|
87
87
|
"since": "2025-01-01"
|
|
88
88
|
},
|
|
89
89
|
"hook:scope-coherence-collector": {
|
|
@@ -92,7 +92,7 @@
|
|
|
92
92
|
"domain": "coherence",
|
|
93
93
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
94
94
|
"installedPath": ".instar/hooks/instar/scope-coherence-collector.js",
|
|
95
|
-
"contentHash": "
|
|
95
|
+
"contentHash": "ae15e23b7525213595701aaac82b83f9ca3f74f99b0b6ab498930096d16ace7a",
|
|
96
96
|
"since": "2025-01-01"
|
|
97
97
|
},
|
|
98
98
|
"hook:scope-coherence-checkpoint": {
|
|
@@ -101,7 +101,7 @@
|
|
|
101
101
|
"domain": "coherence",
|
|
102
102
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
103
103
|
"installedPath": ".instar/hooks/instar/scope-coherence-checkpoint.js",
|
|
104
|
-
"contentHash": "
|
|
104
|
+
"contentHash": "ae15e23b7525213595701aaac82b83f9ca3f74f99b0b6ab498930096d16ace7a",
|
|
105
105
|
"since": "2025-01-01"
|
|
106
106
|
},
|
|
107
107
|
"hook:free-text-guard": {
|
|
@@ -110,7 +110,7 @@
|
|
|
110
110
|
"domain": "safety",
|
|
111
111
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
112
112
|
"installedPath": ".instar/hooks/instar/free-text-guard.sh",
|
|
113
|
-
"contentHash": "
|
|
113
|
+
"contentHash": "ae15e23b7525213595701aaac82b83f9ca3f74f99b0b6ab498930096d16ace7a",
|
|
114
114
|
"since": "2025-01-01"
|
|
115
115
|
},
|
|
116
116
|
"hook:claim-intercept": {
|
|
@@ -119,7 +119,7 @@
|
|
|
119
119
|
"domain": "coherence",
|
|
120
120
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
121
121
|
"installedPath": ".instar/hooks/instar/claim-intercept.js",
|
|
122
|
-
"contentHash": "
|
|
122
|
+
"contentHash": "ae15e23b7525213595701aaac82b83f9ca3f74f99b0b6ab498930096d16ace7a",
|
|
123
123
|
"since": "2025-01-01"
|
|
124
124
|
},
|
|
125
125
|
"hook:claim-intercept-response": {
|
|
@@ -128,7 +128,7 @@
|
|
|
128
128
|
"domain": "coherence",
|
|
129
129
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
130
130
|
"installedPath": ".instar/hooks/instar/claim-intercept-response.js",
|
|
131
|
-
"contentHash": "
|
|
131
|
+
"contentHash": "ae15e23b7525213595701aaac82b83f9ca3f74f99b0b6ab498930096d16ace7a",
|
|
132
132
|
"since": "2025-01-01"
|
|
133
133
|
},
|
|
134
134
|
"hook:stop-gate-router": {
|
|
@@ -137,7 +137,7 @@
|
|
|
137
137
|
"domain": "safety",
|
|
138
138
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
139
139
|
"installedPath": ".instar/hooks/instar/stop-gate-router.js",
|
|
140
|
-
"contentHash": "
|
|
140
|
+
"contentHash": "ae15e23b7525213595701aaac82b83f9ca3f74f99b0b6ab498930096d16ace7a",
|
|
141
141
|
"since": "2025-01-01"
|
|
142
142
|
},
|
|
143
143
|
"hook:auto-approve-permissions": {
|
|
@@ -146,7 +146,7 @@
|
|
|
146
146
|
"domain": "safety",
|
|
147
147
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
148
148
|
"installedPath": ".instar/hooks/instar/auto-approve-permissions.js",
|
|
149
|
-
"contentHash": "
|
|
149
|
+
"contentHash": "ae15e23b7525213595701aaac82b83f9ca3f74f99b0b6ab498930096d16ace7a",
|
|
150
150
|
"since": "2025-01-01"
|
|
151
151
|
},
|
|
152
152
|
"job:health-check": {
|
|
@@ -1562,7 +1562,7 @@
|
|
|
1562
1562
|
"type": "subsystem",
|
|
1563
1563
|
"domain": "updates",
|
|
1564
1564
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
1565
|
-
"contentHash": "
|
|
1565
|
+
"contentHash": "ae15e23b7525213595701aaac82b83f9ca3f74f99b0b6ab498930096d16ace7a",
|
|
1566
1566
|
"since": "2025-01-01"
|
|
1567
1567
|
},
|
|
1568
1568
|
"subsystem:scheduler": {
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# Upgrade Guide — vNEXT
|
|
2
|
+
|
|
3
|
+
<!-- assembled-by: assemble-next-md -->
|
|
4
|
+
<!-- bump: patch -->
|
|
5
|
+
|
|
6
|
+
## What Changed
|
|
7
|
+
|
|
8
|
+
Maintainer-only development machinery — the first product-code member of the
|
|
9
|
+
class-closure program (#1347), and the constitution standard it enforces.
|
|
10
|
+
|
|
11
|
+
- **New defect class `unbounded-self-action`** in `docs/defect-classes.json`
|
|
12
|
+
(severity `critical`, seeded-closed at the 20 already-fixed instances). A
|
|
13
|
+
post-seed recurrence fires the deterministic re-raise at lint time.
|
|
14
|
+
- **The live guard** — `tests/unit/self-action-convergence.test.ts` drives every
|
|
15
|
+
controller in the new `src/testing/selfActionRegistry.ts` registry N ticks
|
|
16
|
+
under a pinned sustained-pressure fixture (all accounts hot / veto never clears
|
|
17
|
+
/ no progress) and asserts the action count SETTLES to a small bound that does
|
|
18
|
+
NOT scale with the horizon. Seeded with faithful convergence models of four
|
|
19
|
+
real controllers (proactive swap monitor, age-kill backoff, promise-beacon
|
|
20
|
+
notify, and a declared Eternal-Sentinel liveness heartbeat exercising the P19
|
|
21
|
+
exemption).
|
|
22
|
+
- **The forcing lint** — `scripts/lint-no-unregistered-self-action.js`
|
|
23
|
+
(emit-anchored, fail-closed once enforcing) refuses an unregistered self-action
|
|
24
|
+
controller emit so a NEW self-action inherits the invariant. **Report-only by
|
|
25
|
+
default** — it reports the population of unregistered controllers and exits 0
|
|
26
|
+
until `prGate.classClosure.dryRun:false`.
|
|
27
|
+
- **The detector + scope** — `scripts/lib/self-action-detect.mjs` is the single
|
|
28
|
+
shared source (emit set + controller-shape predicate + the gate decision). It
|
|
29
|
+
widens the class-closure CI lint's scope (`scripts/class-closure-lint.mjs`) so
|
|
30
|
+
a self-action diff requires a `classClosure` declaration, adds a
|
|
31
|
+
convergence-addressed check (a per-tick-cap-only `howCaught` is flagged), and
|
|
32
|
+
powers `assertSelfActionDeclared` in `scripts/instar-dev-precommit.js` — the
|
|
33
|
+
early arm at the LIGHT commit path #1035 (swap-thrash) slipped through. Both new
|
|
34
|
+
hard-violation conditions land report-only under the existing
|
|
35
|
+
`prGate.classClosure.dryRun` default.
|
|
36
|
+
- **`scripts/class-closure-declare.mjs`** gains `--to-trace` (write the block into
|
|
37
|
+
the instar-dev trace, the E3 declaration host) and an explicit negative
|
|
38
|
+
declaration (`--closure n/a --reason`), the trace-level analog of the lint's
|
|
39
|
+
allowlist.
|
|
40
|
+
- **The standard** "Capacity Safety — No Unbounded Self-Action" added to
|
|
41
|
+
`docs/STANDARDS-REGISTRY.md` (operator-ratified 2026-07-04) — BBR's temporal
|
|
42
|
+
twin: BBR bounds instantaneous MASS, this bounds steady-state FREQUENCY under
|
|
43
|
+
feedback.
|
|
44
|
+
- **Migration Parity** — `migrateClassClosureTemplateSelfActionClause` extends the
|
|
45
|
+
deployed side-effects template's Class-Closure trigger with the self-action
|
|
46
|
+
clause for existing agents.
|
|
47
|
+
|
|
48
|
+
Named follow-on increments (own specs, NOT built here): the unified default-on
|
|
49
|
+
self-action backpressure primitive (the obfuscation-resistant funnel), and the
|
|
50
|
+
swap decoupling / live credential re-pointing (the durable swap fix).
|
|
51
|
+
<!-- tracked: CMT-1911 -->
|
|
52
|
+
|
|
53
|
+
## What to Tell Your User
|
|
54
|
+
|
|
55
|
+
This is maintainer-only development machinery — there is nothing for you to do or
|
|
56
|
+
notice in day-to-day use. If your operator asks "why do we keep fighting the same
|
|
57
|
+
runaway loops (account swaps, notification floods, the reaper firing thousands of
|
|
58
|
+
kill requests)?" — the answer is: those were 20 instances of ONE unnamed defect
|
|
59
|
+
class, and this change names it (unbounded self-action) and builds the automatic
|
|
60
|
+
CI test that proves any self-triggered action settles under sustained pressure
|
|
61
|
+
instead of running away. It ships report-only first (it logs what it would flag)
|
|
62
|
+
and only starts blocking after a clean soak, per the class-closure gate's own dark
|
|
63
|
+
default — so it changes nothing about how I respond to you today.
|
|
64
|
+
|
|
65
|
+
## Summary of New Capabilities
|
|
66
|
+
|
|
67
|
+
- **A new defect class + its guard.** "Unbounded / oscillating self-action" is now
|
|
68
|
+
a registered class with a live CI ratchet (`tests/unit/self-action-convergence.test.ts`)
|
|
69
|
+
that drives every self-triggered controller under worst-case pressure and fails
|
|
70
|
+
the build if the action count doesn't converge — the temporal twin of Bounded
|
|
71
|
+
Blast Radius (which caps how many run at once; this caps how often one fires).
|
|
72
|
+
- **A forcing lint + a shared detector** so a NEW self-triggered action inherits
|
|
73
|
+
the convergence check instead of earning a bespoke brake after it breaks
|
|
74
|
+
something — caught at both the commit gate and CI.
|
|
75
|
+
- **A ratified constitution standard** — "Capacity Safety — No Unbounded
|
|
76
|
+
Self-Action" (`docs/STANDARDS-REGISTRY.md`).
|
|
77
|
+
- No user-facing surface, no routes, no config to set. Report-only until the
|
|
78
|
+
operator flips enforcing.
|
|
79
|
+
|
|
80
|
+
## Evidence
|
|
81
|
+
|
|
82
|
+
- `tests/unit/self-action-convergence.test.ts` — the ratchet: 26 cases, every
|
|
83
|
+
registered controller settles (count ≤ boundK, horizon-independent at 2×ticks,
|
|
84
|
+
no single target thrashed), the Eternal-Sentinel honors its P19 rate floor,
|
|
85
|
+
wiring-integrity (no vacuous/no-op controllers), verb-superset coherence, and
|
|
86
|
+
grader-parity (the three new guards grade ratchet/lint/gate).
|
|
87
|
+
- `tests/unit/self-action-detect.test.ts` — the shared detector + the pure gate
|
|
88
|
+
decision (both precommit call sites): emit true-positives, comment/prose
|
|
89
|
+
false, fail-open on empty diff, all declaration branches.
|
|
90
|
+
- `tests/unit/lint-no-unregistered-self-action.test.ts` — the forcing lint's pure
|
|
91
|
+
evaluator: unmarked → violation, marked+registered → clean, marked-unregistered
|
|
92
|
+
→ violation, allowlisted → clean, no-emit / non-shape → skipped.
|
|
93
|
+
- `tests/integration/class-closure-lint-self-action.test.ts` — the CI lint's
|
|
94
|
+
self-action scope arm over synthetic diffs: good guard declaration → clean; no
|
|
95
|
+
declaration → hard violation (report-only exit 0, enforcing exit 1); a
|
|
96
|
+
per-tick-cap-only `howCaught` → convergence-addressed violation.
|
|
97
|
+
- `tests/unit/migrate-class-closure-self-action-clause.test.ts` — the migration:
|
|
98
|
+
stock template updated, idempotent, customized-left-untouched, no-op when absent.
|
|
99
|
+
- Full lint chain (`npm run lint`) green — including the new forcing lint
|
|
100
|
+
(report-only) and the class-closure grader-parity. `tsc --noEmit` clean.
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Side-Effects Review — Self-Action Convergence (the class-closure guard for self-inflicted loops)
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `self-action-convergence`
|
|
4
|
+
**Date:** `2026-07-04`
|
|
5
|
+
**Author:** `echo`
|
|
6
|
+
**Second-pass reviewer:** `not required — additive dev-tooling (a defect-class entry, a test ratchet, two lints, a shared detector, a precommit arm, a template clause, a migration, a constitution standard). No runtime decision surface, no routes, no user-facing behavior, no data migration. Everything ships report-only under the pre-existing prGate.classClosure dark default.`
|
|
7
|
+
|
|
8
|
+
## Summary of the change
|
|
9
|
+
|
|
10
|
+
Registers `unbounded-self-action` as a formal defect class in the class-closure registry (#1347) — the FIRST product-code member of that program — and builds the live guard that ends it: an N-tick sustained-pressure convergence ratchet (`tests/unit/self-action-convergence.test.ts` + the `src/testing/selfActionRegistry.ts` controller registry), a fail-closed forcing lint (`scripts/lint-no-unregistered-self-action.js`), a shared detector (`scripts/lib/self-action-detect.mjs`), a scope+convergence arm added to the class-closure CI lint (`scripts/class-closure-lint.mjs`), an early-detection arm at instar-dev commit time (`assertSelfActionDeclared` in `scripts/instar-dev-precommit.js`), a `--to-trace`/negative-declaration mode in `scripts/class-closure-declare.mjs`, a one-line side-effects-template clause, its migration (`migrateClassClosureTemplateSelfActionClause`), and the ratified constitution standard "Capacity Safety — No Unbounded Self-Action."
|
|
11
|
+
|
|
12
|
+
This is the structural fix for the entire self-inflicted-loop class (swap-thrash being the presenting case). It is BBR's temporal twin: Bounded Blast Radius bounds instantaneous MASS; this bounds steady-state FREQUENCY under feedback.
|
|
13
|
+
|
|
14
|
+
Files touched: `docs/defect-classes.json`, `docs/STANDARDS-REGISTRY.md`, `docs/specs/self-action-convergence.md` (+ `.eli16.md`), `scripts/lib/self-action-detect.mjs` (new), `src/testing/selfActionRegistry.ts` (new), `tests/unit/self-action-convergence.test.ts` (new), `scripts/lint-no-unregistered-self-action.js` (new), `scripts/class-closure-lint.mjs`, `scripts/class-closure-declare.mjs`, `scripts/instar-dev-precommit.js`, `skills/instar-dev/templates/side-effects-artifact.md`, `src/core/PostUpdateMigrator.ts`, `package.json`, plus tests (`tests/unit/self-action-detect.test.ts`, `tests/unit/lint-no-unregistered-self-action.test.ts`, `tests/unit/migrate-class-closure-self-action-clause.test.ts`, `tests/integration/class-closure-lint-self-action.test.ts`).
|
|
15
|
+
|
|
16
|
+
## Decision-point inventory
|
|
17
|
+
|
|
18
|
+
- **`unbounded-self-action` defect class** — add (registry semantics) — a protected-path registry entry. Governs fix-time declarations; does not gate runtime.
|
|
19
|
+
- **Convergence ratchet + controller registry** — add (CI test) — drives modeled controllers under a pinned worst-case fixture; fails the build (once green) if a registered controller does not settle. Zero runtime authority.
|
|
20
|
+
- **Forcing lint** — add (CI lint) — refuses an unregistered self-action controller emit. **Report-only by default** (exits 0 unless `prGate.classClosure.enabled && !dryRun`).
|
|
21
|
+
- **Class-closure CI lint scope arm + convergence check** — modify (CI lint) — a self-action diff now requires a declaration; a per-tick-cap-only `howCaught` is flagged. Hard-violations recorded; **fail the build only when enforcing** (dark default).
|
|
22
|
+
- **`assertSelfActionDeclared` precommit arm** — add (commit gate) — blocks a self-action src/ change with no declaration/negative. FAIL-OPEN on tooling failure; a genuine one-shot costs one attested negative line.
|
|
23
|
+
- **Shared detector** — add (pure library) — the single source for the emit set + scope predicate + the gate decision. Deterministic; never LLM-guesses.
|
|
24
|
+
- **Side-effects template clause + migration** — modify (skill template) — the Class-Closure Declaration trigger now names the self-action case; the migration reaches existing agents (Migration Parity).
|
|
25
|
+
- **Constitution standard** — add (standards text) — "Capacity Safety — No Unbounded Self-Action," ratified by the operator 2026-07-04.
|
|
26
|
+
- **All existing gates** — pass-through — the tone gate, coherence gate, external-operation gate, class-closure gate's existing behavior are unchanged; this composes with #1347, it does not fork it.
|
|
27
|
+
|
|
28
|
+
## 1. Over-block
|
|
29
|
+
|
|
30
|
+
**No runtime block/allow surface — over-block N/A.** The only new blocking paths are DEV-TIME gates (the precommit arm + the CI lints), and both ship report-only under the pre-existing `prGate.classClosure` dark default. The precommit arm fails OPEN on any tooling failure (empty diff, no src/ file, unreadable artifact) and offers an explicit one-line negative-declaration escape, so a genuine one-shot / user-driven action is never unescapably blocked. The forcing lint is scoped to controller-SHAPE files to avoid flagging every `retry(` in src/.
|
|
31
|
+
|
|
32
|
+
## 2. Under-block
|
|
33
|
+
|
|
34
|
+
**No runtime under-block surface.** The completeness guarantee (every controller registered) is report-only until the operator flips enforcing on measured declaration population, per #1347's own criterion. Until then a NEW self-action can still ship un-registered — the honest, deliberate soak posture; the E2 CI lint + E3 precommit arm are the earlier backstops, and the string-based scope is named as an accident-deterrent (the obfuscation-resistant closure is the follow-on funnel, Part B).
|
|
35
|
+
|
|
36
|
+
## 3. Ordering / idempotency
|
|
37
|
+
|
|
38
|
+
The migration is idempotent (marker short-circuit). The declare `--to-trace` mode is idempotent (identical block → no change). The ratchet + lints are pure re-runnable evaluations. No persistent runtime state, no ordering dependency.
|
|
39
|
+
|
|
40
|
+
## 4. Signal vs. Authority
|
|
41
|
+
|
|
42
|
+
Compliant. The detector is DETERMINISTIC — it forces a declaration, it never LLM-guesses (Signal vs. Authority). The ratchet + lints are structure, not willpower. The convergence proof is a CI ratchet, not discretionary prose. No new blocking authority is granted to any LLM path.
|
|
43
|
+
|
|
44
|
+
## 5. Feedback loops
|
|
45
|
+
|
|
46
|
+
**This spec IS the answer to the feedback-loop question** the swap-thrash review never answered. The change adds NO new runtime control loop — it adds a CI/commit-time invariant that PROVES other control loops converge. It cannot itself spiral (it is a stateless test/lint run per CI invocation).
|
|
47
|
+
|
|
48
|
+
## 6. External surfaces
|
|
49
|
+
|
|
50
|
+
None. No HTTP routes, no external API calls, no network egress. All new surfaces are local dev-tooling (a test, two lints, a shared library, a commit-gate arm, a registry entry, a template clause, a migration, a standard).
|
|
51
|
+
|
|
52
|
+
## 7. Multi-machine posture
|
|
53
|
+
|
|
54
|
+
`unified` (repo-resident). The registry entry, the lints, the detector, the ratchet, and the standard all ride the git repo itself (the replication medium), reaching every checkout on `git pull` — matching #1347's declared posture. The template clause reaches existing deployed agents through the PostUpdateMigrator migration. No machine-local state, no per-machine divergence.
|
|
55
|
+
|
|
56
|
+
## Class-Closure Declaration (display-only mirror)
|
|
57
|
+
|
|
58
|
+
- **`defectClass`** — `unbounded-self-action` (this change REGISTERS the class AND builds its closing guard; the self-referential canonical closure).
|
|
59
|
+
- **`closure`** — `guard`.
|
|
60
|
+
- **`guardEvidence`** — `{ enforcementType: ratchet, citation: tests/unit/self-action-convergence.test.ts, howCaught: the ratchet drives every registered self-action controller N ticks under a pinned sustained-pressure fixture (all accounts hot / veto never clears / no progress) and asserts the action count SETTLES to a small bound that does NOT scale with the horizon — steady-state convergence via each controller's settling brake (all-hot / projected-load / exponential-backoff+breaker / suppress-unchanged), with the declared Eternal-Sentinel exemption asserting a P19 rate floor instead. A per-tick cap would NOT satisfy this — it bounds one pass, never the loop. }`
|
|
61
|
+
|
|
62
|
+
The machine-readable counterpart lives in the commit's decision-audit entry (persisted from the instar-dev trace by `writeDecisionAudit`), which the CI class-closure lint reads. This mirror is display-only and is never summed with it (C1).
|