instar 1.2.81 → 1.2.82

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.
@@ -0,0 +1,127 @@
1
+ # Side-Effects Review — Free-text guard template resolution
2
+
3
+ **Version / slug:** `free-text-guard-template-resolution`
4
+ **Date:** `2026-05-25`
5
+ **Author:** `instar-codey`
6
+ **Second-pass reviewer:** `Echo`
7
+
8
+ ## Summary of the change
9
+
10
+ This change fixes how the post-update migrator finds built-in template files.
11
+ The free-text guard hook was looking only in the compiled-template layout, but
12
+ published packages ship that hook in the source-template layout. The migrator
13
+ now has one shared template loader for hook, script, and playbook templates. The
14
+ free-text guard and existing similar readers use that loader.
15
+
16
+ ## Decision-point inventory
17
+
18
+ This change does not add, remove, or modify any block/allow decision. It changes
19
+ file lookup for a static built-in template. The free-text guard's own behavior is
20
+ passed through unchanged.
21
+
22
+ - `free-text-guard.sh` — pass-through — installed from the packaged template;
23
+ its blocking rules are not changed.
24
+ - `PostUpdateMigrator` template lookup — modified — uses shared lookup instead
25
+ of repeated one-off path checks.
26
+
27
+ ---
28
+
29
+ ## 1. Over-block
30
+
31
+ No new block/allow surface. Over-block is not applicable to the template lookup
32
+ change. The free-text guard may still block exactly the same inputs it blocked
33
+ before; this patch only controls whether the hook is installed.
34
+
35
+ ---
36
+
37
+ ## 2. Under-block
38
+
39
+ This does not change what the guard detects. The remaining failure mode is
40
+ package-shape drift: if a future publish stops shipping both supported template
41
+ locations, the migrator will fail clearly for the required free-text guard and
42
+ skip or fall back for callers that already had softer behavior. The new package
43
+ shape test covers the current published layout.
44
+
45
+ ---
46
+
47
+ ## 3. Level-of-abstraction fit
48
+
49
+ The fix belongs in the migrator because the bug is runtime asset resolution, not
50
+ guard policy. A shared helper is the right layer: it keeps package-layout
51
+ knowledge in one place and lets each caller decide whether a missing template is
52
+ fatal, skippable, or eligible for fallback.
53
+
54
+ ---
55
+
56
+ ## 4. Signal vs authority compliance
57
+
58
+ **Required reference:** [docs/signal-vs-authority.md](../../docs/signal-vs-authority.md)
59
+
60
+ - [x] No — this change has no block/allow surface.
61
+
62
+ The change does not introduce a detector or an authority. It does not decide
63
+ whether a message, action, or user request should be blocked. It only locates a
64
+ static template file so existing migration behavior can install the existing
65
+ hook.
66
+
67
+ ---
68
+
69
+ ## 5. Interactions
70
+
71
+ - **Shadowing:** no existing decision path is shadowed. Existing template
72
+ readers now share one lookup helper.
73
+ - **Double-fire:** no duplicate installer is added. The same migration still
74
+ writes the same built-in hook once.
75
+ - **Races:** no shared persistent state is added. File reads are local and
76
+ synchronous, matching the previous migrator style.
77
+ - **Feedback loops:** none. The resolver does not feed runtime decisions or
78
+ telemetry.
79
+
80
+ ---
81
+
82
+ ## 6. External surfaces
83
+
84
+ Existing agents see the external effect on update: the free-text guard hook can
85
+ be installed again from the package we actually publish. The hook content and
86
+ runtime behavior do not change. There is no new user-facing command, API,
87
+ database field, or external service dependency.
88
+
89
+ ---
90
+
91
+ ## 7. Rollback cost
92
+
93
+ Rollback is a normal patch revert. The change writes no new persistent state and
94
+ does not migrate data. If it misbehaves, revert the shared resolver refactor and
95
+ ship a patch. Agents that already received the hook do not need repair because
96
+ the hook content itself is unchanged.
97
+
98
+ ---
99
+
100
+ ## Conclusion
101
+
102
+ The review found no new decision authority and no new block/allow behavior. The
103
+ main production risk is future package layout drift, and the integration test now
104
+ checks the packed package shape and runs the compiled migrator from that shape.
105
+ This is clear to ship once CI is green.
106
+
107
+ ---
108
+
109
+ ## Second-pass review (if required)
110
+
111
+ **Reviewer:** Echo
112
+ **Independent read of the artifact: concur**
113
+
114
+ Echo reviewed the diagnosis and implementation direction during the Threadline
115
+ collaboration and signed off on the root cause, shared resolver approach, and
116
+ packed-package smoke as the evidence needed before normal CI.
117
+
118
+ ---
119
+
120
+ ## Evidence pointers
121
+
122
+ - Approved spec: `docs/specs/FREE-TEXT-GUARD-TEMPLATE-RESOLUTION-SPEC.md`
123
+ - Plain-language spec overview:
124
+ `docs/specs/FREE-TEXT-GUARD-TEMPLATE-RESOLUTION-SPEC.eli16.md`
125
+ - Focused tests: 6 passing.
126
+ - Build and lint: passing.
127
+ - Packed package smoke: passing.
@@ -0,0 +1,46 @@
1
+ # Side-Effects Review — Threadline notification routing (CMT-519)
2
+
3
+ **Version / slug:** `threadline-notification-routing`
4
+ **Date:** 2026-05-25
5
+ **Author:** Echo
6
+ **Second-pass reviewer:** (pending — required; touches messaging routing + a structural redirect "guard")
7
+
8
+ ## Summary of the change
9
+
10
+ Threadline notifications no longer spawn a Telegram topic per event. `CollaborationSurfacer` gains a `notify()` entry (status/housekeeping → the single SILENT "Threadline" hub, never the parent topic), record-shaped surface state (with a legacy `string[]` read-migration) + bind helpers (`mostRecentUnbound`, `markBound`, `noteInHub`). The loop-gate (`src/commands/server.ts` ~7167) routes through `notify()` instead of `createAttentionItem`. `POST /attention` redirects threadline-class items to the hub. A new `POST /threadline/hub/bind` promotes ("open this") / binds ("tie this to X") a surfaced conversation to a topic — authoritatively setting `boundTopicId` + the commitment's `topicId`. Template + migration teach agents the hub + "open this" behavior. Decision points: the `/attention` reroute (routing, not block/allow), the loop-gate notice destination, the bind mutation.
11
+
12
+ ## Decision-point inventory
13
+
14
+ - `POST /attention` threadline-class redirect — **add** — reroutes threadline/inter-agent/spawn items to the silent hub instead of a per-event topic.
15
+ - Loop-gate wind-down destination (`server.ts`) — **modify** — `createAttentionItem` → `collaborationSurfacer.notify()` (hub, not parent, not per-event topic).
16
+ - `POST /threadline/hub/bind` — **add** — authoritative thread→topic bind.
17
+ - CollaborationSurfacer status vs first-contact surfacing — **modify** — adds the status lane (`notify`) alongside the existing parentless first-contact lane (`surface`).
18
+
19
+ ## 1. Over-block
20
+ No block/allow surface — these are routing/delivery decisions, not gates. The `/attention` redirect could mis-route a *legitimate general* item if its title coincidentally matches `threadline|inter-agent|spawn|relay` — mitigated by the category-first check (`/^(threadline|inter-agent|relay|spawn)/i` on category) plus content sniff only on distinctive phrases (`spawn-storm`, `spawn to receive`, `cannot spawn`, `inter-agent`, `\bthreadline\b`). A generic "spawn a new worker" general item would NOT match (no category prefix, no distinctive phrase). Worst case the item lands in the hub instead of its own topic — recoverable, not lost.
21
+
22
+ ## 2. Under-block
23
+ A threadline alert posted via `/attention` with a *non-threadline category AND no distinctive phrase* would still get its own topic. Acceptable: the in-code threadline emitters (loop-gate) now route correctly; the redirect is a backstop for ad-hoc posts. The `TelegramBridge.mirrorInbound` per-thread topic path is intentionally excluded as a deliberate opt-in feature (default-off — the operator turned it on knowingly), not a notification the routing fix should override.
24
+
25
+ ## 3. Level-of-abstraction fit
26
+ Correct: extended `CollaborationSurfacer` (already the hub owner) rather than a parallel router (convergence Q1). Status notices use a delivery sink (`notify`); real reply *content* still flows via the existing `TopicLinkageHandler` parent-topic path (one emitter per topic — avoids the double-notify the reviewer flagged, H2). The bind endpoint composes existing primitives (`ConversationStore.mutate`, `findOrCreateForumTopic`, `commitmentTracker.mutate`).
27
+
28
+ ## 4. Signal vs authority compliance
29
+ No new blocking authority. The `/attention` redirect is a router (reroute + 201, never a hard block). `notify()`/`surface()` are delivery sinks. The bind endpoint mutates state on explicit operator action. Per `docs/signal-vs-authority.md`: detectors/sinks, not gates.
30
+
31
+ ## 5. Interactions
32
+ - **No double-surface:** status (`notify`) → hub only; content (replies) → parent topic via TopicLinkageHandler only. The loop-gate path `return`s after notify, so it never also hits surface(). `surface()` (parentless first-contact) and `notify()` (status) are distinct lanes; a single inbound triggers at most one.
33
+ - **Bind vs first-write-wins:** `hub/bind` is authoritative — it overrides `captureOriginOnSend`'s anti-poisoning refusal by directly setting `boundTopicId` + the commitment `topicId` (operator intent > heuristic).
34
+ - **Legacy state migration** is read-time + idempotent; new record-shape round-trips.
35
+
36
+ ## 6. External surfaces
37
+ New `transport`-free; new route `POST /threadline/hub/bind` (503 when telegram/conversationStore absent). Hub stays silent (`{silent:true}`) — no new buzzing. Template/migration change is agent-facing (Agent Awareness Standard) + idempotent (Migration Parity).
38
+
39
+ ## 7. Rollback cost
40
+ Localized: CollaborationSurfacer (additive methods + schema with back-compat read), one server.ts callsite, two routes.ts additions, template + migration. Clean `git revert`. The surface-state schema change is forward+backward tolerant (load() reads both shapes); no data migration needed. New agents get the template via `generateClaudeMd`; existing via `migrateClaudeMd` (idempotent).
41
+
42
+ ## Second-pass review
43
+
44
+ **Concur with the review** (independent reviewer, 2026-05-25). Verified all six checks against the diff: (1) the loop-gate `budgetExhausted && collaborationSurfacer` guard is sound (surfacer is `telegram ? new ... : undefined`), and the dropped `createAttentionItem` had no `/ack` consumer — nothing operational lost; (2) `load()` migration round-trips all three shapes (records / legacy string[] / dedicatedTopicId-only) with no loss of `dedicatedTopicId`; (3) the `/attention` redirect runs after `checkOutboundMessage`, matches only category-prefix `^(threadline|inter-agent|relay|spawn)` OR distinctive body tokens (8 realistic inputs tested — "CI failed", "relay race", "Spawning a new initiative" correctly do NOT match), else falls through; (4) `hub/bind` 503/404/409/200 paths correct, authoritative bind sets `boundTopicId` + commitment `topicId` via existing CAS-safe mutates, null-safe field access, all awaits correct, tsc clean; (5) migration content-sniff marker exactly matches the template heading — idempotent; (6) no double-surface — the `budgetExhausted` path `notify()`s then `return`s before `surface()`, and `surface()` early-returns on `hasParentTopic`; mutually exclusive per inbound.
45
+
46
+ Reviewer's one non-blocking gap — the new HTTP routes lacked Tier 2/3 coverage — has been **addressed**: added `tests/integration/threadline/hub-bind-routes.test.ts` (6 tests: 503/400/404/409/200-open/200-tie, asserting `boundTopicId` is set through the real `createRoutes` pipeline). The `/attention` redirect's match logic is covered by the reviewer's verified 8-input analysis + live test-as-self.