instar 1.3.32 → 1.3.34
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/commands/server.d.ts.map +1 -1
- package/dist/commands/server.js +47 -1
- package/dist/commands/server.js.map +1 -1
- package/dist/core/types.d.ts +16 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/feedback-factory/dryrun/dryRunCompare.d.ts +82 -0
- package/dist/feedback-factory/dryrun/dryRunCompare.d.ts.map +1 -0
- package/dist/feedback-factory/dryrun/dryRunCompare.js +88 -0
- package/dist/feedback-factory/dryrun/dryRunCompare.js.map +1 -0
- package/dist/feedback-factory/processor/parity.d.ts +111 -0
- package/dist/feedback-factory/processor/parity.d.ts.map +1 -0
- package/dist/feedback-factory/processor/parity.js +118 -0
- package/dist/feedback-factory/processor/parity.js.map +1 -0
- package/dist/feedback-factory/store/ReadOnlyShadowStore.d.ts +59 -0
- package/dist/feedback-factory/store/ReadOnlyShadowStore.d.ts.map +1 -0
- package/dist/feedback-factory/store/ReadOnlyShadowStore.js +88 -0
- package/dist/feedback-factory/store/ReadOnlyShadowStore.js.map +1 -0
- package/dist/messaging/TelegramAdapter.d.ts +12 -1
- package/dist/messaging/TelegramAdapter.d.ts.map +1 -1
- package/dist/messaging/TelegramAdapter.js +28 -7
- package/dist/messaging/TelegramAdapter.js.map +1 -1
- package/dist/monitoring/StopNotifier.d.ts +88 -0
- package/dist/monitoring/StopNotifier.d.ts.map +1 -0
- package/dist/monitoring/StopNotifier.js +105 -0
- package/dist/monitoring/StopNotifier.js.map +1 -0
- package/dist/server/AgentServer.d.ts +2 -0
- package/dist/server/AgentServer.d.ts.map +1 -1
- package/dist/server/AgentServer.js +1 -0
- package/dist/server/AgentServer.js.map +1 -1
- package/dist/server/routes.d.ts +4 -0
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +13 -0
- package/dist/server/routes.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +47 -47
- package/upgrades/1.3.31.md +9 -10
- package/upgrades/1.3.33.md +36 -0
- package/upgrades/1.3.34.md +37 -0
- package/upgrades/side-effects/feedback-factory-dryrun.md +93 -0
- package/upgrades/side-effects/notify-on-stop-layer-b.md +34 -0
- package/upgrades/side-effects/telegram-adapter-multi-instance.md +61 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Side-Effects Review — Notify-on-Stop, Layer B (gate-fed unjustified-stall notice)
|
|
2
|
+
|
|
3
|
+
**Spec:** docs/specs/NOTIFY-ON-STOP-SPEC.md (approved: true) — Layer B of two. Layer A (autonomous-run-ended notice) shipped in a prior PR.
|
|
4
|
+
|
|
5
|
+
When the UnjustifiedStopGate (shadow/enforce) classifies a stop as unjustified-but-unblockable (`continue` in `shadow` — the gate wants to continue but shadow can't block, so the session silently stalls) or ambiguous (`escalate`), an UNATTENDED session can go quiet mid-task and the user never hears about it. Layer B turns those specific classifications into ONE coalesced heads-up.
|
|
6
|
+
|
|
7
|
+
## What changed
|
|
8
|
+
- `src/monitoring/StopNotifier.ts` (new) — thin DECISION layer: `isNotifyWorthyStop` (shadow+continue OR escalate; everything else silent) + attended-gate (unattended/autonomous only, default) + per-session dedup (30-min cooldown) + master enable (default ON). Delivery is delegated to an injected `escalate` sink.
|
|
9
|
+
- `src/commands/server.ts` — constructs a dedicated `SentinelNotifier` (telegramEscalation **on** — distinct from the housekeeping sentinel notifier, which stays default-off) reusing the lifeline-topic `sendConsolidated` transport + a JSONL log; wraps it in a `StopNotifier`. Null when telegram isn't wired or config disables it.
|
|
10
|
+
- `src/server/routes.ts` — the `/internal/stop-gate/evaluate` route computes `autonomousActive` (via `getHotPathState`) and, after the authority decision, calls `ctx.stopNotifier?.maybeNotify({ sessionId, mode, decision, autonomousActive })`. Fire-and-forget; never affects the gate decision or the HTTP response.
|
|
11
|
+
- `src/server/AgentServer.ts` — accepts + forwards `stopNotifier` to the routes ctx.
|
|
12
|
+
- `src/core/types.ts` — `monitoring.notifyOnStop?: { enabled?, unattendedOnly?, cooldownMs? }`.
|
|
13
|
+
- Tests: `StopNotifier.test.ts` (21 — both sides of every decision boundary, attended-gate, dedup window/expiry/per-session, master gate, throwing-sink safety) + `stop-notifier-wiring.test.ts` (6 — route→notifier→sink→server→AgentServer chain, guards the PR#334 dead-code failure mode).
|
|
14
|
+
|
|
15
|
+
## Signal vs authority
|
|
16
|
+
The Stop-hook router is a dumb thin client; the decision to ALARM the user lives server-side in StopNotifier, where the gate decision + attended-state + dedup ledger all exist. StopNotifier adds NO blocking authority — it's a delivery decision only. It never changes the gate's `decision`.
|
|
17
|
+
|
|
18
|
+
## Near-silent compliance
|
|
19
|
+
Default-on is the deliberate exception Justin explicitly asked for ("tell me why it stopped"), and it is tightly bounded: only two genuinely-stuck decision classes, only unattended sessions, at most once per session per 30 min, coalesced into one message on the single lifeline topic. Routine turn-ends (`allow`), blocked-and-continued (`continue` in enforce), continue-ceiling (`force_allow`), and fail-open are all silent. A single config flag (`monitoring.notifyOnStop.enabled=false`) kills it with no redeploy.
|
|
20
|
+
|
|
21
|
+
## Over/under-notify
|
|
22
|
+
- OVER: a shadow-mode `continue` could occasionally be a gate misjudgment (the CONTINUE_CEILING exists because the authority can be wrong). Mitigated by attended-gate + 30-min dedup; the alternative (a silent autonomous stall) is exactly what Justin wants eliminated.
|
|
23
|
+
- UNDER: when the gate is `off` (no evaluate call) there's no Layer B notice — but Layer A still covers autonomous terminal exits, and the gate runs in `shadow` on real agents.
|
|
24
|
+
|
|
25
|
+
## Migration parity
|
|
26
|
+
Default-on works WITHOUT any config key present (`enabled !== false` ⇒ true when undefined), so existing agents get it on update to this version with no migrateConfig step. The wiring is server-side; no agent-installed-file change.
|
|
27
|
+
|
|
28
|
+
## Rollback
|
|
29
|
+
`monitoring.notifyOnStop.enabled=false` (instant, no redeploy) or revert the 6 files + 2 tests.
|
|
30
|
+
|
|
31
|
+
## Tests / verification
|
|
32
|
+
- Tier 1 unit: StopNotifier.test.ts (decision matrix both sides + gates).
|
|
33
|
+
- Wiring-integrity: stop-notifier-wiring.test.ts (no dead code).
|
|
34
|
+
- Tier 3 live: test-as-self before merge — drive a synthetic shadow+continue on an autonomous session through the real route and confirm the lifeline-topic heads-up fires once (and a routine `allow` stays silent).
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Side-Effects Review — TelegramAdapter multi-instance isolation + Message-type extension (PR 2a)
|
|
2
|
+
|
|
3
|
+
**Spec:** `docs/specs/MENTOR-LIVE-READINESS-SPEC.md` §Fix 2b "Implementation surface" items
|
|
4
|
+
1-2 + round-2 integration F1 (converged, approved). PR 2 of the staged build, part a.
|
|
5
|
+
**Change:** Make `TelegramAdapter` safe to run as a second (non-primary) instance in one
|
|
6
|
+
process, and expose the Telegram fields the a2a spoof-defense needs. **Ships dark** — no
|
|
7
|
+
caller passes the new options yet; the new Message fields are additive-optional.
|
|
8
|
+
**Files:** `src/messaging/TelegramAdapter.ts`, `tests/unit/telegram-adapter-multi-instance.test.ts` (new).
|
|
9
|
+
|
|
10
|
+
## What changed
|
|
11
|
+
|
|
12
|
+
1. **Constructor opts `{ subDir?, suppressLifelineAutoCreate? }`** (3rd param, optional). When
|
|
13
|
+
`subDir` is set, the four per-bot state files (registry / message-log / poll-offset /
|
|
14
|
+
attention) live under `{stateDir}/{subDir}/` via a new `botStateDir`. The PRIMARY bot
|
|
15
|
+
(no `subDir`) gets `botStateDir === stateDir` → **paths are byte-for-byte unchanged**.
|
|
16
|
+
2. **`suppressLifelineAutoCreate`** — `start()` skips `ensureLifelineTopic()` when true, so a
|
|
17
|
+
non-primary bot can't create a second Lifeline topic in the chat.
|
|
18
|
+
3. **Message-type extension** — `message.from.is_bot?: boolean` + `message.sender_chat?` added
|
|
19
|
+
to `TelegramUpdate`. These are the structural inputs to the a2a user-spoof defense (a
|
|
20
|
+
human typing an `[a2a:…]` marker has `is_bot:false` and no `sender_chat`).
|
|
21
|
+
|
|
22
|
+
## The seven questions
|
|
23
|
+
|
|
24
|
+
1. **Over-block.** N/A — no gate. The only behavior gate is `suppressLifelineAutoCreate`,
|
|
25
|
+
default false (primary unaffected).
|
|
26
|
+
2. **Under-block.** The reviewer-flagged collision (two adapters sharing
|
|
27
|
+
`telegram-poll-offset.json` → `poll()`'s cross-token detection fires continuously) is
|
|
28
|
+
eliminated: non-primary state is namespaced. Test asserts the two adapters share NO
|
|
29
|
+
state-file path.
|
|
30
|
+
3. **Level-of-abstraction fit.** The isolation is at construction (one place), not scattered
|
|
31
|
+
per-callsite. `botStateDir` is the single source for per-bot paths.
|
|
32
|
+
4. **Signal vs authority.** N/A.
|
|
33
|
+
5. **Interactions — THE risk, and how it's bounded.** This file runs Echo's own (primary)
|
|
34
|
+
Telegram — the channel to the user. The change is built so the primary path is
|
|
35
|
+
**identical** (when `subDir` is undefined, `botStateDir === stateDir`). A dedicated test
|
|
36
|
+
asserts the four primary paths are byte-for-byte the historical `{stateDir}/...` values,
|
|
37
|
+
and the existing TelegramAdapter suites (71 tests across 5 files) pass unchanged — the
|
|
38
|
+
regression guard for "did I break my own comms." The new code only branches when `subDir`
|
|
39
|
+
is set, and nothing sets it yet (dark). Media/dashboard dirs still resolve off `stateDir`
|
|
40
|
+
inline — NOT isolated — which is fine: the reviewer flagged only the four constructor
|
|
41
|
+
state files, and the mentor bot (the only future `subDir` user) does no media/dashboard.
|
|
42
|
+
6. **External surfaces.** None. No routes, no config consumed yet. The Message-type fields
|
|
43
|
+
are additive-optional (every existing reader ignores them).
|
|
44
|
+
7. **Rollback cost.** Trivial — revert restores the 2-param constructor; no data, no migration
|
|
45
|
+
(the primary never wrote to a subDir).
|
|
46
|
+
|
|
47
|
+
## Testing
|
|
48
|
+
|
|
49
|
+
- `tests/unit/telegram-adapter-multi-instance.test.ts` (3 tests): **primary paths byte-for-byte
|
|
50
|
+
unchanged** (the load-bearing safety assertion); subDir namespaces all four state files +
|
|
51
|
+
shares no path with primary + creates the sub-dir; `suppressLifelineAutoCreate` recorded
|
|
52
|
+
(false default for primary).
|
|
53
|
+
- Regression: existing Telegram suites (`TelegramAdapter`, `telegram-format-wireup`,
|
|
54
|
+
`telegram-adapter`) + the PR-1 `AgentTelegramComms` suite — 71 tests, all green.
|
|
55
|
+
- `tsc --noEmit` clean.
|
|
56
|
+
|
|
57
|
+
## Migration parity
|
|
58
|
+
|
|
59
|
+
None — additive constructor option + additive optional Message fields. No agent-installed
|
|
60
|
+
file change, no config consumed yet. PR 2b wires `sendAgentMessage` + the recipient handler;
|
|
61
|
+
PR 3's config/migration is per the spec's §Migration parity.
|