instar 1.3.767 → 1.3.768
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.map +1 -1
- package/dist/core/PostUpdateMigrator.js +17 -2
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/scaffold/templates.js +1 -1
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +19 -4
- package/dist/server/routes.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +63 -63
- package/src/scaffold/templates.ts +1 -1
- package/upgrades/1.3.768.md +38 -0
- package/upgrades/side-effects/outbound-advisory-offswitch-config-shape.eli16.md +41 -0
- package/upgrades/side-effects/outbound-advisory-offswitch-config-shape.md +117 -0
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# Side-Effects Review — outbound-advisory off-switch reachable on array-shaped messaging
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `outbound-advisory-offswitch-config-shape`
|
|
4
|
+
**Date:** `2026-07-04`
|
|
5
|
+
**Author:** `Echo`
|
|
6
|
+
**Second-pass reviewer:** `not required (Tier-1)`
|
|
7
|
+
|
|
8
|
+
## Summary of the change
|
|
9
|
+
|
|
10
|
+
The outbound-advisory preflight route read its off-switch (and tuning knobs) at
|
|
11
|
+
`messaging.outboundAdvisory.*`. On a real install `messaging` is a JSON **array** of adapter configs,
|
|
12
|
+
so that dot-path resolves `undefined` → the read's default. For the `enabled` read (default `true`)
|
|
13
|
+
that meant the **documented off-switch (`messaging.outboundAdvisory.enabled: false`) had no effect —
|
|
14
|
+
an operator could not disable the advisory** (the un-DISABLABLE sub-class of the PR #1379 bug). Fix:
|
|
15
|
+
read from the reachable **top-level `outboundAdvisory`** block (canonical), honoring the legacy
|
|
16
|
+
`messaging.outboundAdvisory` as a back-compat fallback. Applied to all four reads
|
|
17
|
+
(`enabled`, `ignoreEscalationThreshold`, `ignoreEscalationSlugThreshold`, `timeClaim.enabled` dev-gate),
|
|
18
|
+
the documented off-switch key in both templates, and an existing-agent CLAUDE.md doc migration.
|
|
19
|
+
Files: `src/server/routes.ts`, `src/core/PostUpdateMigrator.ts`, `src/scaffold/templates.ts`, + test.
|
|
20
|
+
|
|
21
|
+
## Decision-point inventory
|
|
22
|
+
|
|
23
|
+
- `POST /messaging/preflight` `enabled` gate (`routes.ts`) — **modify** — top-level-first resolution.
|
|
24
|
+
- `OutboundAdvisoryAudit` threshold reads (`routes.ts`) — **modify** — top-level-first.
|
|
25
|
+
- `timeClaim.enabled` dev-gate value (`routes.ts`) — **pass-through** — sourced top-level-first;
|
|
26
|
+
`undefined → live-on-dev` semantics unchanged.
|
|
27
|
+
- CLAUDE template off-switch text (both `PostUpdateMigrator` content + `scaffold/templates`) —
|
|
28
|
+
**modify** — documents the reachable top-level key.
|
|
29
|
+
- `PostUpdateMigrator` TIME_CLAIM anchor marker — **modify** — matched on the stable `- Off-switch: \``
|
|
30
|
+
prefix so it still anchors regardless of which key the line carries.
|
|
31
|
+
- New `migrateClaudeMd` swap — **add** — updates an existing agent's stale nested-key off-switch line.
|
|
32
|
+
|
|
33
|
+
## 1. Over-block / 2. Under-block
|
|
34
|
+
|
|
35
|
+
No block/allow surface change of consequence: the advisory is inform-only and never blocks a message.
|
|
36
|
+
The only behavior change is that the **off-switch now actually works** — an operator who sets
|
|
37
|
+
`outboundAdvisory.enabled: false` disables the advisory (previously impossible). Over-block N/A;
|
|
38
|
+
under-block N/A.
|
|
39
|
+
|
|
40
|
+
## 3. Level-of-abstraction fit
|
|
41
|
+
|
|
42
|
+
Right layer — same top-level-first config-read pattern as PR #1379, applied at the read sites. No new
|
|
43
|
+
authority, no new machinery.
|
|
44
|
+
|
|
45
|
+
## 4. Signal vs authority compliance
|
|
46
|
+
|
|
47
|
+
**Required reference:** [docs/signal-vs-authority.md](../../docs/signal-vs-authority.md)
|
|
48
|
+
|
|
49
|
+
- [x] No — no runtime block/allow surface changes; the advisory remains inform-only. This restores a
|
|
50
|
+
broken operator control (an off-switch), it does not add gating authority.
|
|
51
|
+
|
|
52
|
+
## 5. Interactions
|
|
53
|
+
|
|
54
|
+
- **Shadowing:** none — top-level-first read is a superset of prior behavior; on object-messaging the
|
|
55
|
+
legacy fallback resolves identically.
|
|
56
|
+
- **Double-fire / races / feedback loops:** none.
|
|
57
|
+
- **Migration marker:** the TIME_CLAIM anchor now matches the stable `- Off-switch: \`` prefix, so it
|
|
58
|
+
still finds the off-switch line whether CLAUDE.md carries the old nested or the new top-level key —
|
|
59
|
+
verified the substring is present in both.
|
|
60
|
+
|
|
61
|
+
## 6. External surfaces
|
|
62
|
+
|
|
63
|
+
- **Install base / agents:** existing agents get the corrected off-switch DOC via the new
|
|
64
|
+
`migrateClaudeMd` swap (content-sniff, idempotent) on their next update; new agents via the
|
|
65
|
+
templates. The CODE fix ships with the server. No config migration needed to keep working (top-level
|
|
66
|
+
is additive; legacy still honored).
|
|
67
|
+
- **Operator surface:** restores a documented operator control (the off-switch). No new UI/route.
|
|
68
|
+
- **Persistent state / external systems:** none.
|
|
69
|
+
|
|
70
|
+
## 6b. Operator-surface quality
|
|
71
|
+
|
|
72
|
+
No dashboard/approval/form surface — not applicable (the off-switch is a config edit, now at a
|
|
73
|
+
reachable key, documented for the operator).
|
|
74
|
+
|
|
75
|
+
## 7. Multi-machine posture (Cross-Machine Coherence)
|
|
76
|
+
|
|
77
|
+
**machine-local BY DESIGN** — config (`.instar/config.json`) is per-machine; the advisory runs
|
|
78
|
+
per-machine on the sending machine. This change only alters where in the local config the flag is
|
|
79
|
+
read. No cross-machine state, notice, durable state, or URL.
|
|
80
|
+
|
|
81
|
+
## 8. Rollback cost
|
|
82
|
+
|
|
83
|
+
Pure code + doc change — revert the reads + template text + the one migration block. No persistent
|
|
84
|
+
state; the top-level key is additive and the legacy fallback preserves prior behavior. Zero-cost
|
|
85
|
+
back-out.
|
|
86
|
+
|
|
87
|
+
## Conclusion
|
|
88
|
+
|
|
89
|
+
Restores the outbound-advisory off-switch that was silently broken on every real (array-`messaging`)
|
|
90
|
+
install — the un-DISABLABLE sibling of the PR #1379 un-ENABLABLE bug, found by the sibling audit
|
|
91
|
+
(`docs/investigations/messaging-config-unreachable-audit-2026-07-04.md`). Code + docs + existing-agent
|
|
92
|
+
migration + a real-LiveConfig array-shape test. Clear to ship.
|
|
93
|
+
|
|
94
|
+
## Second-pass review (if required)
|
|
95
|
+
|
|
96
|
+
**Reviewer:** not required (Tier-1)
|
|
97
|
+
|
|
98
|
+
## Evidence pointers
|
|
99
|
+
|
|
100
|
+
- `tests/unit/outbound-advisory-config-shape.test.ts` — real LiveConfig + real array-shaped config:
|
|
101
|
+
top-level off-switch disables (was impossible before the fix), default-on when unset, object-shape
|
|
102
|
+
back-compat.
|
|
103
|
+
- Existing `outbound-advisory-routes` / `outbound-advisory` / `telegram-reply-advisory-script` tests
|
|
104
|
+
(58) stay green; `tsc` clean; `lint-no-unreachable-messaging-gate` clean.
|
|
105
|
+
|
|
106
|
+
## Class-Closure Declaration (display-only mirror)
|
|
107
|
+
|
|
108
|
+
- **`defectClass`** — `config-unreachable-on-shape` (the PR #1379 class; this is its un-DISABLABLE
|
|
109
|
+
default-ON sub-class).
|
|
110
|
+
- **`closure`** — `gap` — the #1381 lint catches the default-OFF (un-enablable) sub-class; the
|
|
111
|
+
default-ON un-disablable sub-class (`.get('messaging.*.enabled', true)` with a documented off-switch)
|
|
112
|
+
is not reliably lint-detectable without false positives (documented in the #1381 side-effects
|
|
113
|
+
follow-ups). This fix ships the direct regression test + moves the config to the reachable
|
|
114
|
+
convention; the class-level guard for the un-disablable sub-class remains a tracked gap.
|
|
115
|
+
- **`guardEvidence`** — n/a for `closure: gap`.
|
|
116
|
+
- **`gap`** — tracked in `docs/investigations/messaging-config-unreachable-audit-2026-07-04.md`
|
|
117
|
+
(follow-up 2) + the #1381 side-effects artifact.
|