instar 1.3.326 → 1.3.327

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.
Files changed (33) hide show
  1. package/dist/commands/server.d.ts.map +1 -1
  2. package/dist/commands/server.js +2 -1
  3. package/dist/commands/server.js.map +1 -1
  4. package/dist/core/ForwardedTopicContext.d.ts.map +1 -1
  5. package/dist/core/ForwardedTopicContext.js +4 -6
  6. package/dist/core/ForwardedTopicContext.js.map +1 -1
  7. package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
  8. package/dist/core/PostUpdateMigrator.js +23 -5
  9. package/dist/core/PostUpdateMigrator.js.map +1 -1
  10. package/dist/lifeline/TelegramLifeline.d.ts.map +1 -1
  11. package/dist/lifeline/TelegramLifeline.js +2 -1
  12. package/dist/lifeline/TelegramLifeline.js.map +1 -1
  13. package/dist/memory/TopicMemory.d.ts.map +1 -1
  14. package/dist/memory/TopicMemory.js +3 -2
  15. package/dist/memory/TopicMemory.js.map +1 -1
  16. package/dist/messaging/shared/compactionResumePayload.d.ts.map +1 -1
  17. package/dist/messaging/shared/compactionResumePayload.js +2 -1
  18. package/dist/messaging/shared/compactionResumePayload.js.map +1 -1
  19. package/dist/server/routes.d.ts.map +1 -1
  20. package/dist/server/routes.js +3 -2
  21. package/dist/server/routes.js.map +1 -1
  22. package/dist/utils/localTime.d.ts +42 -0
  23. package/dist/utils/localTime.d.ts.map +1 -0
  24. package/dist/utils/localTime.js +60 -0
  25. package/dist/utils/localTime.js.map +1 -0
  26. package/package.json +1 -1
  27. package/src/data/builtin-manifest.json +67 -67
  28. package/src/templates/hooks/compaction-recovery.sh +15 -3
  29. package/src/templates/hooks/slack-channel-context.sh +1 -1
  30. package/src/templates/hooks/telegram-topic-context.sh +8 -2
  31. package/upgrades/1.3.327.md +57 -0
  32. package/upgrades/local-time-coherence.eli16.md +11 -0
  33. package/upgrades/side-effects/local-time-coherence.md +89 -0
@@ -105,6 +105,12 @@ fi
105
105
  # Format and output context with unanswered message detection
106
106
  echo "$RECENT_MSGS" | python3 -c "
107
107
  import sys, json
108
+ def _localts(raw):
109
+ try:
110
+ from datetime import datetime
111
+ return datetime.fromisoformat(str(raw).replace('Z', '+00:00')).astimezone().strftime('%Y-%m-%d %H:%M %Z')
112
+ except Exception:
113
+ return str(raw)[:16].replace('T', ' ')
108
114
  try:
109
115
  data = json.load(sys.stdin)
110
116
  msgs = data.get('messages', [])
@@ -114,7 +120,7 @@ try:
114
120
  print('TOPIC ${TOPIC_ID} RECENT HISTORY (auto-injected — read this before responding):')
115
121
 
116
122
  for m in msgs:
117
- ts = m.get('timestamp', '')[:16].replace('T', ' ')
123
+ ts = _localts(m.get('timestamp', ''))
118
124
  from_user = m.get('fromUser', m.get('direction', 'in') == 'in')
119
125
  text = m.get('text', '').strip()
120
126
  sender = 'User' if from_user else 'Agent'
@@ -139,7 +145,7 @@ try:
139
145
  print('*** UNANSWERED MESSAGE(S) FROM USER ***')
140
146
  for pm in pending_user:
141
147
  pm_text = pm.get('text', '')[:200]
142
- pm_ts = pm.get('timestamp', '')[:16].replace('T', ' ')
148
+ pm_ts = _localts(pm.get('timestamp', ''))
143
149
  print(f' [{pm_ts}] \"{pm_text}\"')
144
150
  print()
145
151
  print('You MUST address these messages substantively. Do NOT respond with just')
@@ -0,0 +1,57 @@
1
+ # Upgrade Guide — vNEXT
2
+
3
+ <!-- assembled-by: assemble-next-md -->
4
+ <!-- bump: patch -->
5
+
6
+ ## What Changed
7
+
8
+ Fixes a **time-incoherency** class of bug: every context block that shows an
9
+ agent its conversation history rendered timestamps as **unlabeled UTC**
10
+ (`[21:23:10]`), while the CURRENT TIME hook block speaks labeled local time.
11
+ Agents read both as one clock — live incident 2026-06-05: an agent told its
12
+ user "you heard nothing between **9:23pm** and now" about an event at
13
+ **2:23pm** the user's local time.
14
+
15
+ Now every agent-facing timestamp renders in the **host's local timezone with
16
+ an explicit tz label and date**: `[2026-06-05 14:23 PDT]`.
17
+
18
+ Surfaces covered:
19
+
20
+ - Bootstrap Thread History (new/respawned sessions), auto-spawn history
21
+ - Moved-session context relay (multi-machine transfers)
22
+ - Per-message Telegram topic history hook + unanswered-messages block
23
+ - Post-compaction recovery context (Telegram + Slack blocks)
24
+ - Session-start RECENT MESSAGES, TopicMemory context blocks
25
+ - Slack channel context (tz label added)
26
+ - Lifeline "Last healthy" status line
27
+
28
+ New shared helper `src/utils/localTime.ts` (`formatLocalTimestamp`); hook
29
+ python blocks carry an equivalent `_localts()` with a safe fallback to the
30
+ old rendering on any parse failure. Stored timestamps remain ISO-UTC —
31
+ rendering only. Existing agents pick the hook changes up automatically
32
+ (built-in hooks are always-overwritten on migration).
33
+
34
+ ## What to Tell Your User
35
+
36
+ Your agent no longer gets confused about what time things happened. Before
37
+ this, the agent saw conversation history stamped in UTC but the current time
38
+ in your local timezone — and could misquote a 2pm event as "9pm." Now every
39
+ timestamp it reads carries your local time and timezone, so "when did I last
40
+ hear from you?" answers come out right.
41
+
42
+ ## Summary of New Capabilities
43
+
44
+ - None user-invocable — this is a correctness fix to how agents perceive
45
+ time. (Internal: `formatLocalTimestamp()` in `src/utils/localTime.ts` is
46
+ the one helper all history/status renderers now use.)
47
+
48
+ ## Evidence
49
+
50
+ - New `tests/unit/localTime.test.ts` pins local-not-UTC semantically
51
+ (TZ-portable: compares against the same instant's local Date getters),
52
+ including the verbatim incident instant `2026-06-05T21:23:10Z`.
53
+ - Hook python smoke test: the incident payload now renders
54
+ `[2026-06-05 14:23 PDT] Agent: executing now` (was `[2026-06-05 21:23]`).
55
+ - Updated `ForwardedTopicContext` / `compactionResumePayload` /
56
+ `telegram-autospawn-history` tests to TZ-portable assertions through the
57
+ helper; affected-area suites green; `tsc --noEmit` clean.
@@ -0,0 +1,11 @@
1
+ # The agent stops misreading its own clock
2
+
3
+ The agent kept two clocks without knowing it. Every hook that tells the agent "here's the current time" speaks in YOUR local time ("5:49pm PDT") — but every block that shows it conversation history spoke in unlabeled UTC ("[21:23]"). The agent has no way to tell those apart, so it did the natural thing: read both as the same clock. That's how it told Justin "you heard nothing between **9:23pm** and now" about a message sent at **2:23pm** his time — off by exactly the 7-hour UTC gap. The user experiences this as the agent being confused about basic reality.
4
+
5
+ The fix makes every timestamp the agent ever sees speak ONE language: the machine's local time, with the timezone written right on it — `[2026-06-05 14:23 PDT]` instead of `[21:23:10]`. History lines also now carry the date, so a conversation spanning midnight can't be misread either ("was that 12:30am today or yesterday?" stops being a guess).
6
+
7
+ Where this applies — every surface that renders history or status timestamps into an agent's context: the thread history a new session boots with, the history relayed when a conversation moves between machines, the recent-messages block injected on every Telegram message, the post-compaction recovery context, the Slack channel context, the session-start recent messages, and the lifeline's "last healthy" status line. One new shared helper does the rendering in code; the hook scripts get a tiny equivalent helper with a safe fallback (if a timestamp ever fails to parse, it renders the old way instead of crashing the hook).
8
+
9
+ Existing agents get this automatically: the built-in hook scripts are always refreshed on update, and the code paths ship with the next release. Nothing about WHEN things happen changes — only how the time is written down. There is no new config, no new decision surface, and the worst possible failure (a malformed timestamp) renders the way it used to render rather than breaking anything.
10
+
11
+ What you need to decide: nothing — this is a pure rendering fix for a live mis-statement the agent made to you. The PR is the review surface.
@@ -0,0 +1,89 @@
1
+ # Side-Effects Review — Local-time + tz-label rendering for all agent-facing timestamps
2
+
3
+ **Version / slug:** `local-time-coherence`
4
+ **Date:** `2026-06-05`
5
+ **Author:** `echo`
6
+ **Second-pass reviewer:** `not required (no block/allow surface, no lifecycle decisions — pure rendering)`
7
+
8
+ ## Summary of the change
9
+
10
+ Every surface that renders timestamps into agent-facing context blocks switched from unlabeled UTC (`toISOString().slice(11, 19)` in TS, `timestamp[:16].replace('T', ' ')` in hook python) to host-local time with an explicit timezone label and date (`[2026-06-05 14:23 PDT]`). New shared helper `src/utils/localTime.ts` (`formatLocalTimestamp`, `localTzAbbreviation`); call sites: `ForwardedTopicContext.ts`, `TopicMemory.ts` ×2, `commands/server.ts` (bootstrap Thread History), `server/routes.ts` ×2 (auto-spawn/respawn history), `compactionResumePayload.ts`, `TelegramLifeline.ts` (status line). Hook python blocks get an equivalent `_localts()` helper with parse-failure fallback to the old rendering: `templates/hooks/telegram-topic-context.sh`, `templates/hooks/compaction-recovery.sh` (telegram + slack blocks), `templates/hooks/slack-channel-context.sh` (tz label only), and the `PostUpdateMigrator.ts` inline copies (session-start, telegram-topic-context, compaction-recovery). Driven by the 2026-06-05 live incident: the agent reported a 14:23-local event as "9:23pm" because history was unlabeled UTC while CURRENT TIME blocks are local-labeled.
11
+
12
+ ## Decision-point inventory
13
+
14
+ No decision-point surface. This change renders strings; it adds, removes, or modifies no block/allow decision, no gate, no lifecycle action. The only conditional logic is "did the timestamp parse?" with a render-the-old-way fallback.
15
+
16
+ ---
17
+
18
+ ## 1. Over-block
19
+
20
+ No block/allow surface — over-block not applicable.
21
+
22
+ ---
23
+
24
+ ## 2. Under-block
25
+
26
+ No block/allow surface — under-block not applicable.
27
+
28
+ ---
29
+
30
+ ## 3. Level-of-abstraction fit
31
+
32
+ Right layer: a formatting primitive at the render chokepoints. The alternative — teaching agents (prompt-level) that history is UTC — is exactly the willpower-dependent design that caused the incident. A lower-level primitive did not exist (`formatLocalTimeHHMM` in `RestartCascadeDampener.ts` is HH:MM-only, no tz label, no date, not exported for this purpose); this PR creates the shared primitive and routes all sites through it. Hook python cannot import TS, so it carries a minimal equivalent — acceptable duplication at the language boundary, kept identical across all blocks.
33
+
34
+ ---
35
+
36
+ ## 4. Signal vs authority compliance
37
+
38
+ **Required reference:** [docs/signal-vs-authority.md](../../docs/signal-vs-authority.md)
39
+
40
+ - [x] No — this change has no block/allow surface.
41
+
42
+ Pure rendering. Nothing here holds authority over any action.
43
+
44
+ ---
45
+
46
+ ## 5. Interactions
47
+
48
+ - **Shadowing:** none — no checks run before/after; the rendered string feeds the same downstream consumers (context injection, tmux paste) unchanged in shape (`[ts] Sender: text`).
49
+ - **Double-fire:** none — formatting is idempotent and side-effect-free.
50
+ - **Races:** none — no shared mutable state; `Intl.DateTimeFormat` is constructed per call.
51
+ - **Feedback loops:** one considered: agents QUOTE history timestamps back into conversation, and those quotes can land in future history. Since both the injected history and the CURRENT TIME hook now speak local-labeled time, the loop converges toward coherence instead of propagating UTC misreads.
52
+ - **Unanswered-message detection:** verified untouched — detection logic compares message order/sender, never parses the rendered timestamp.
53
+ - **Tests that mirror renderers:** `telegram-autospawn-history.test.ts` contains a local mirror of the routes.ts logic; updated in the same PR so the mirror stays faithful.
54
+
55
+ ---
56
+
57
+ ## 6. External surfaces
58
+
59
+ - **Other agents on the same machine:** the hook-template changes reach every instar agent on next update (built-in hooks are always-overwritten by `PostUpdateMigrator`). The change is rendering-only; no agent behavior contract depends on UTC timestamps (verified: no consumer parses the bracketed time back out of context blocks — grepped for consumers of the rendered format).
60
+ - **External systems:** none — Telegram/Slack/GitHub payloads unchanged; only locally-injected context strings change.
61
+ - **Persistent state:** none written. Stored timestamps remain ISO-UTC everywhere (JSONL, SQLite); ONLY rendering changes. No migration of stored data.
62
+ - **Timing/runtime:** `%Z` in python `strftime` and `Intl` tz short-names vary by platform locale data; on a host where no label resolves, the label is simply omitted (TS) or the naive fallback renders (python) — degraded to the status quo, never an error.
63
+
64
+ ---
65
+
66
+ ## 7. Rollback cost
67
+
68
+ Pure code + template change — revert and ship a patch. No persistent state, no data migration, no agent state repair. During a rollback window, agents would briefly render local-labeled and then UTC again; cosmetic only.
69
+
70
+ ---
71
+
72
+ ## Conclusion
73
+
74
+ The review confirmed no decision surface and no persistence surface; the main risks identified and addressed were (a) hook python crashing on unparseable timestamps — covered by the try/except fallback to the previous rendering, and (b) test mirrors drifting from real renderers — the mirror was updated in the same change. One pre-existing inconsistency was found and normalized: `formatInlineHistory` treated numeric-0 timestamps as missing while `ForwardedTopicContext` rendered them; the shared helper renders them (epoch is a valid instant). Clear to ship.
75
+
76
+ ---
77
+
78
+ ## Second-pass review (if required)
79
+
80
+ **Reviewer:** not required
81
+ **Independent read of the artifact:** not required — no messaging block/allow, no session lifecycle, no sentinel/gate/guard surface.
82
+
83
+ ---
84
+
85
+ ## Evidence pointers
86
+
87
+ - `tests/unit/localTime.test.ts` — semantic local-not-UTC pinning incl. the verbatim incident instant `2026-06-05T21:23:10Z`.
88
+ - Hook python smoke test: incident payload renders `[2026-06-05 14:23 PDT] Agent: executing now` (was `[2026-06-05 21:23]`).
89
+ - Full local suite (74 min on a loaded box): 28329 passed / 8 failed across 5 files. The one failure whose identity survived output truncation (`session-management-e2e`, a waitFor timeout) re-ran green in isolation; a full re-run with complete capture was started for the rest, and CI (clean, sharded runners) is the merge gate either way.