instar 1.2.12 → 1.2.14

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.
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "$schema": "./builtin-manifest.schema.json",
3
3
  "schemaVersion": 1,
4
- "generatedAt": "2026-05-21T21:24:25.485Z",
5
- "instarVersion": "1.2.12",
4
+ "generatedAt": "2026-05-21T23:32:22.253Z",
5
+ "instarVersion": "1.2.14",
6
6
  "entryCount": 191,
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": "e32c85f03cb2d4d440172949fb5f7654c7c224a7cd64c78ed1c7b83759e1c2c9",
14
+ "contentHash": "c05e308a956d13c08a2aecdbec64591b4a94ef3c083e4b4ce95202b03ebce284",
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": "e32c85f03cb2d4d440172949fb5f7654c7c224a7cd64c78ed1c7b83759e1c2c9",
23
+ "contentHash": "c05e308a956d13c08a2aecdbec64591b4a94ef3c083e4b4ce95202b03ebce284",
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": "e32c85f03cb2d4d440172949fb5f7654c7c224a7cd64c78ed1c7b83759e1c2c9",
32
+ "contentHash": "c05e308a956d13c08a2aecdbec64591b4a94ef3c083e4b4ce95202b03ebce284",
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": "e32c85f03cb2d4d440172949fb5f7654c7c224a7cd64c78ed1c7b83759e1c2c9",
41
+ "contentHash": "c05e308a956d13c08a2aecdbec64591b4a94ef3c083e4b4ce95202b03ebce284",
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": "e32c85f03cb2d4d440172949fb5f7654c7c224a7cd64c78ed1c7b83759e1c2c9",
50
+ "contentHash": "c05e308a956d13c08a2aecdbec64591b4a94ef3c083e4b4ce95202b03ebce284",
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": "e32c85f03cb2d4d440172949fb5f7654c7c224a7cd64c78ed1c7b83759e1c2c9",
59
+ "contentHash": "c05e308a956d13c08a2aecdbec64591b4a94ef3c083e4b4ce95202b03ebce284",
60
60
  "since": "2025-01-01"
61
61
  },
62
62
  "hook:post-action-reflection": {
@@ -65,7 +65,7 @@
65
65
  "domain": "evolution",
66
66
  "sourcePath": "src/core/PostUpdateMigrator.ts",
67
67
  "installedPath": ".instar/hooks/instar/post-action-reflection.js",
68
- "contentHash": "e32c85f03cb2d4d440172949fb5f7654c7c224a7cd64c78ed1c7b83759e1c2c9",
68
+ "contentHash": "c05e308a956d13c08a2aecdbec64591b4a94ef3c083e4b4ce95202b03ebce284",
69
69
  "since": "2025-01-01"
70
70
  },
71
71
  "hook:external-communication-guard": {
@@ -74,7 +74,7 @@
74
74
  "domain": "safety",
75
75
  "sourcePath": "src/core/PostUpdateMigrator.ts",
76
76
  "installedPath": ".instar/hooks/instar/external-communication-guard.js",
77
- "contentHash": "e32c85f03cb2d4d440172949fb5f7654c7c224a7cd64c78ed1c7b83759e1c2c9",
77
+ "contentHash": "c05e308a956d13c08a2aecdbec64591b4a94ef3c083e4b4ce95202b03ebce284",
78
78
  "since": "2025-01-01"
79
79
  },
80
80
  "hook:scope-coherence-collector": {
@@ -83,7 +83,7 @@
83
83
  "domain": "coherence",
84
84
  "sourcePath": "src/core/PostUpdateMigrator.ts",
85
85
  "installedPath": ".instar/hooks/instar/scope-coherence-collector.js",
86
- "contentHash": "e32c85f03cb2d4d440172949fb5f7654c7c224a7cd64c78ed1c7b83759e1c2c9",
86
+ "contentHash": "c05e308a956d13c08a2aecdbec64591b4a94ef3c083e4b4ce95202b03ebce284",
87
87
  "since": "2025-01-01"
88
88
  },
89
89
  "hook:scope-coherence-checkpoint": {
@@ -92,7 +92,7 @@
92
92
  "domain": "coherence",
93
93
  "sourcePath": "src/core/PostUpdateMigrator.ts",
94
94
  "installedPath": ".instar/hooks/instar/scope-coherence-checkpoint.js",
95
- "contentHash": "e32c85f03cb2d4d440172949fb5f7654c7c224a7cd64c78ed1c7b83759e1c2c9",
95
+ "contentHash": "c05e308a956d13c08a2aecdbec64591b4a94ef3c083e4b4ce95202b03ebce284",
96
96
  "since": "2025-01-01"
97
97
  },
98
98
  "hook:free-text-guard": {
@@ -101,7 +101,7 @@
101
101
  "domain": "safety",
102
102
  "sourcePath": "src/core/PostUpdateMigrator.ts",
103
103
  "installedPath": ".instar/hooks/instar/free-text-guard.sh",
104
- "contentHash": "e32c85f03cb2d4d440172949fb5f7654c7c224a7cd64c78ed1c7b83759e1c2c9",
104
+ "contentHash": "c05e308a956d13c08a2aecdbec64591b4a94ef3c083e4b4ce95202b03ebce284",
105
105
  "since": "2025-01-01"
106
106
  },
107
107
  "hook:claim-intercept": {
@@ -110,7 +110,7 @@
110
110
  "domain": "coherence",
111
111
  "sourcePath": "src/core/PostUpdateMigrator.ts",
112
112
  "installedPath": ".instar/hooks/instar/claim-intercept.js",
113
- "contentHash": "e32c85f03cb2d4d440172949fb5f7654c7c224a7cd64c78ed1c7b83759e1c2c9",
113
+ "contentHash": "c05e308a956d13c08a2aecdbec64591b4a94ef3c083e4b4ce95202b03ebce284",
114
114
  "since": "2025-01-01"
115
115
  },
116
116
  "hook:claim-intercept-response": {
@@ -119,7 +119,7 @@
119
119
  "domain": "coherence",
120
120
  "sourcePath": "src/core/PostUpdateMigrator.ts",
121
121
  "installedPath": ".instar/hooks/instar/claim-intercept-response.js",
122
- "contentHash": "e32c85f03cb2d4d440172949fb5f7654c7c224a7cd64c78ed1c7b83759e1c2c9",
122
+ "contentHash": "c05e308a956d13c08a2aecdbec64591b4a94ef3c083e4b4ce95202b03ebce284",
123
123
  "since": "2025-01-01"
124
124
  },
125
125
  "hook:auto-approve-permissions": {
@@ -128,7 +128,7 @@
128
128
  "domain": "safety",
129
129
  "sourcePath": "src/core/PostUpdateMigrator.ts",
130
130
  "installedPath": ".instar/hooks/instar/auto-approve-permissions.js",
131
- "contentHash": "e32c85f03cb2d4d440172949fb5f7654c7c224a7cd64c78ed1c7b83759e1c2c9",
131
+ "contentHash": "c05e308a956d13c08a2aecdbec64591b4a94ef3c083e4b4ce95202b03ebce284",
132
132
  "since": "2025-01-01"
133
133
  },
134
134
  "job:health-check": {
@@ -1472,7 +1472,7 @@
1472
1472
  "type": "subsystem",
1473
1473
  "domain": "updates",
1474
1474
  "sourcePath": "src/core/PostUpdateMigrator.ts",
1475
- "contentHash": "e32c85f03cb2d4d440172949fb5f7654c7c224a7cd64c78ed1c7b83759e1c2c9",
1475
+ "contentHash": "c05e308a956d13c08a2aecdbec64591b4a94ef3c083e4b4ce95202b03ebce284",
1476
1476
  "since": "2025-01-01"
1477
1477
  },
1478
1478
  "subsystem:scheduler": {
@@ -0,0 +1,42 @@
1
+ # Upgrade Guide — vNEXT (current-time injection in agent hooks)
2
+
3
+ <!-- bump: patch -->
4
+ <!-- patch = behavior fix that closes a recurring failure mode, no new surface -->
5
+
6
+ ## What Changed
7
+
8
+ **Fix: every instar agent now sees the current wall-clock time at session start AND on every user prompt.**
9
+
10
+ Claude Code's harness injects `currentDate: YYYY-MM-DD` into the agent's system prompt — but NOT the current time of day. In long-running sessions (hours, days), agents that try to say "it's 2am" or "you've been up X hours" or "we just talked an hour ago" were either hallucinating clock times outright or pulling stale time strings from earlier conversation context. Iris hit this on 2026-05-21: she told a user "it's 2am" when it was actually 5:45am, and only realized it after the user contradicted her with a timestamped screenshot.
11
+
12
+ The fix is structural, not behavioral. Two existing hooks every instar agent already runs now emit a `--- CURRENT TIME ---` block backed by a live `date(1)` call:
13
+
14
+ - **`session-start.sh`** (SessionStart hook, startup / resume / clear) — emits the time block immediately after `=== SESSION START ===`, before any other context. Refreshed on every session lifecycle event including post-compaction resume.
15
+ - **`telegram-topic-context.sh`** (UserPromptSubmit hook) — emits the time block on **every** user prompt, BEFORE the `[telegram:N]` prefix early-exit. So agents get a fresh wall-clock anchor on every turn, not just at session start, regardless of whether the prompt arrived via Telegram or direct CLI use.
16
+
17
+ Format: `2026-05-21 14:15:29 -0500 (CDT)` — ISO date + 24h time + signed offset + tz abbreviation. Same line every time. Agents are told explicitly: "Quote this — do not carry stale clock times from prior context."
18
+
19
+ The hook content lives inline in `src/core/PostUpdateMigrator.ts` (functions `getSessionStartHook()` and `getTelegramTopicContextHook()`), which is the source of truth that both `init` (new agents) and `migrate` (existing agents) write to disk. Built-in hooks are unconditionally overwritten on every migration run, so existing agents pick up the fix automatically on their next `npx instar` invocation — no manual migration required.
20
+
21
+ ## What to Tell Your User
22
+
23
+ If your agent has ever made a clock-time claim that turned out to be wrong (saying it's the middle of the night when it isn't, miscalculating "how long ago" something happened, mismatching AM/PM), that failure mode is closed after this release. Your agent now sees the actual current time on every interaction and is structurally instructed to quote it rather than guess.
24
+
25
+ No action needed from you. The next time your agent updates, the fix lands.
26
+
27
+ ## Summary of New Capabilities
28
+
29
+ | Capability | How to Use |
30
+ |-----------|-----------|
31
+ | Wall-clock time injected at session start | Automatic — `--- CURRENT TIME ---` block at the top of session-start output |
32
+ | Wall-clock time refreshed on every user prompt | Automatic — same block emitted ahead of telegram-topic-context every UserPromptSubmit |
33
+
34
+ ## Evidence
35
+
36
+ - New test: `tests/unit/PostUpdateMigrator-time-injection.test.ts` — 13 cases. Static assertions on the inlined bash (date format, guard, delimiters, ordering) PLUS end-to-end execution of both hook scripts against a fresh sandboxed temp dir, asserting the actual emitted output matches the expected `YYYY-MM-DD HH:MM:SS +ZZZZ (TZ)` shape.
37
+ - Existing tests still pass: `tests/unit/PostUpdateMigrator-sharedState.test.ts` (Integrated-Being session-start regression) and `tests/unit/scaffold-identity-hooks.test.ts` (scaffold integrity) verified green against the patched migrator.
38
+ - Side-effects review: `upgrades/side-effects/inject-current-time-into-hooks.md`.
39
+
40
+ ## Original Incident
41
+
42
+ Iris session, Business Plan topic, 2026-05-21 ~5:45am CDT. Agent said "It's 2am. The laptop can wait. Goodnight." User's actual local time was 5:45am Central. Memory note `feedback_clock_time_must_call_date.md` captured the rule per-agent; this release lifts the fix to the framework so every instar agent benefits without each agent having to learn the lesson independently.
@@ -0,0 +1,79 @@
1
+ # Upgrade Guide — v1.2.14 (wizard validation + composing indicator)
2
+
3
+ <!-- bump: patch -->
4
+ <!-- patch = bug fixes, refactors, test additions, doc updates -->
5
+
6
+ ## What Changed
7
+
8
+ **Fix: the wizard now catches buffered-Enter and surfaces a visible
9
+ indicator during Codex narrative calls.**
10
+
11
+ End-to-end testing v1.2.13 on a real Codex install surfaced a UX
12
+ failure. The user typed an answer and pressed Enter, then — because
13
+ the next Codex-narrative call took several seconds with no visible
14
+ feedback — pressed Enter again thinking the terminal was frozen. The
15
+ extra Enter buffered in stdin, was consumed by the next prompt as
16
+ an empty submission, and the wizard silently defaulted the agent's
17
+ name to "agent". The user ended up with an agent that had a generic
18
+ identity they never picked.
19
+
20
+ Two structural fixes, both in `src/commands/setup-wizard/`:
21
+
22
+ 1. **Per-state validators** on the state machine. Each
23
+ narrative-then-prompt state can now declare a `validate` function
24
+ that rejects invalid input and surfaces a friendly retry message
25
+ without re-generating the Codex narrative paragraph (cheap loop,
26
+ no extra LLM calls). Reusable validators:
27
+ - `requireNonEmpty(fieldLabel)`: rejects whitespace-only
28
+ submissions on required text fields with an explicit
29
+ "did an extra Enter slip through?" nudge.
30
+ - `requireChoice(choices)`: rejects unmatched input on choice
31
+ prompts with a "try one of these numbers" nudge.
32
+
33
+ Wired on every narrative state in the fresh-project-install
34
+ graph. Bounded at 5 retry attempts to prevent infinite loops
35
+ on wedged input.
36
+
37
+ 2. **Composing spinner** during codex narrative calls. A braille
38
+ spinner ("⠋ composing…") animates on a single line while
39
+ `codex exec` runs; clears cleanly when the paragraph arrives.
40
+ On non-TTY (CI, piped output) it prints "composing…" once and
41
+ stops. Eliminates the silent-dead-air window that triggered
42
+ buffered-Enter in the first place.
43
+
44
+ The silent-default fallback that accepted empty agent-name as
45
+ "agent" is removed. With validators upstream, the state machine
46
+ only ever sees valid input.
47
+
48
+ Spec: `specs/dev-infrastructure/wizard-validation.md`.
49
+ ELI16: `specs/dev-infrastructure/wizard-validation.eli16.md`.
50
+ Side-effects review: `upgrades/side-effects/fix-wizard-validation.md`.
51
+
52
+ ## What to Tell Your User
53
+
54
+ The setup wizard now shows a spinner while it's thinking, so you
55
+ can tell the system is working during the longer steps. If you
56
+ accidentally press Enter twice (which is easy to do during the
57
+ think pauses), the wizard will catch it and re-ask the question
58
+ instead of silently moving on with a blank answer.
59
+
60
+ ## Summary of New Capabilities
61
+
62
+ No new capabilities. UX hardening on top of v1.2.13's hybrid wizard.
63
+
64
+ ## Evidence
65
+
66
+ Reproduction prior to fix: v1.2.13 install on `instar-codey` with
67
+ Codex CLI. User entered "1" + Enter at welcome, then pressed Enter
68
+ again during the silent codex-narrative call. The second Enter was
69
+ consumed by the agent-name prompt as an empty submission;
70
+ agentName defaulted to "agent"; wizard proceeded with the generic
71
+ identity.
72
+
73
+ After fix:
74
+ - 14 new state-machine unit tests cover the two validator helpers
75
+ and the per-state validator wiring (welcome, agent-name,
76
+ agent-role, user-name, autonomy, messaging).
77
+ - Existing 12 state-graph tests still pass.
78
+ - Existing 5 dispatch canary tests still pass.
79
+ - Manual end-to-end re-test pending on publish.
@@ -0,0 +1,98 @@
1
+ # Side-effects review — Wizard input validation + spinner
2
+
3
+ Per L6. Seven dimensions.
4
+
5
+ ## 1. Over-block / under-block
6
+
7
+ Before: UNDER. The v1.2.13 hybrid wizard accepted empty submissions
8
+ on required identity fields with a silent fallback default
9
+ (agentName: 'agent'). Combined with the invisible-latency window on
10
+ codex-narrative calls, this produced the buffered-Enter bug Justin
11
+ hit on his first real Codex install — agent named "agent" without
12
+ the user ever typing a name.
13
+
14
+ After: precisely targeted. Validators enforce non-empty input on
15
+ required text fields and reject unmatched input on choice prompts.
16
+ Spinner during codex calls eliminates the silent-dead-air window
17
+ that triggers buffered-Enter in the first place. No over-block:
18
+ optional/derived fields keep their defaults; the validation
19
+ machinery only kicks in for fields the wizard explicitly marks as
20
+ required.
21
+
22
+ ## 2. Level-of-abstraction fit
23
+
24
+ The `validate?` field is an optional addition to the existing
25
+ `NarrativeState` interface. Two reusable validators
26
+ (`requireNonEmpty`, `requireChoice`) live alongside the state
27
+ graph in `state-machine.ts`. The driver's `renderNarrativeState`
28
+ adds a bounded retry loop around `askUser`. The spinner is a
29
+ single utility function with a `{stop}` handle pattern.
30
+
31
+ No new module, no new abstraction layer. The state machine's API
32
+ grew by exactly one optional field.
33
+
34
+ ## 3. Signal vs Authority compliance
35
+
36
+ - The validator's return value is the AUTHORITY for "is this
37
+ answer accepted." The driver respects it without second-guessing.
38
+ - The user's input remains the SIGNAL; the validator transforms
39
+ invalid SIGNALs into "retry with this hint" rather than silently
40
+ defaulting.
41
+ - The spinner is purely visual feedback — no authority, no signal.
42
+
43
+ ## 4. Interactions with adjacent systems
44
+
45
+ - **State machine `next` functions**: simplified. The pre-fix code
46
+ on agent-name etc. was `answer.trim() || 'agent'`; post-fix is
47
+ `answer.trim()`. The validator ensures `next` only sees non-empty
48
+ trimmed input.
49
+ - **Codex driver dispatch in setup.ts**: unchanged. setup.ts still
50
+ routes codex-cli installs through `runCodexWizard`.
51
+ - **runCodexNarrative**: now wraps its spawnSync in a spinner
52
+ start/stop. Spinner is a no-op on non-TTY (CI, piped output) so
53
+ test environments aren't affected.
54
+ - **Existing canary test** (`tests/unit/setup-codex-model-canary.test.ts`):
55
+ unchanged. Asserts the same dispatch contract; the validator
56
+ additions don't touch the dispatch shape.
57
+ - **State-machine unit tests**: expanded from 12 to 26 cases.
58
+ Added validator-specific tests (requireNonEmpty, requireChoice,
59
+ per-state validator wiring).
60
+ - **Claude wizard path**: completely unaffected. Validators live on
61
+ the state-machine API, but the Claude path doesn't go through
62
+ the state machine — it spawns the existing /setup-wizard
63
+ slash-command directly.
64
+
65
+ ## 5. Rollback cost
66
+
67
+ Low. New optional `validate` field on NarrativeState; new
68
+ validators; new spinner helper; one retry loop in the driver.
69
+ `git revert` restores v1.2.13 (with the buffered-Enter bug).
70
+
71
+ ## 6. Backwards compatibility / drift surface
72
+
73
+ Fully backwards-compatible.
74
+
75
+ - States without a `validate` function skip validation entirely
76
+ and accept the answer immediately. No existing state is broken
77
+ by the addition.
78
+ - Validators are pure functions with stable contracts. Drift
79
+ surface: validator messages. If a message text needs to change,
80
+ update the validator's return value — visible in PR diff.
81
+ - No config schema change. No agent-installed-files change. No
82
+ PostUpdateMigrator work.
83
+
84
+ ## 7. Authorization / Trust posture
85
+
86
+ No new authority. The validator is run inside the same wizard
87
+ process with the same user. No new privilege, no new sandbox, no
88
+ new auth.
89
+
90
+ ## Outcome
91
+
92
+ Ship. Closes the broken-on-buffered-Enter UX hole that the
93
+ instar-codey real-user test surfaced. Structural validation +
94
+ visible composing indicator together address the failure-mode
95
+ chain (silent latency → user reflex → buffered Enter → empty
96
+ submission accepted). Validator extensibility lands cleanly on
97
+ the existing state-machine API. 26 unit tests cover the
98
+ validators + wiring.
@@ -0,0 +1,63 @@
1
+ # Side-Effects Review — inject current time into agent hooks
2
+
3
+ **Version / slug:** `inject-current-time-into-hooks`
4
+ **Date:** `2026-05-21`
5
+ **Author:** `echo`
6
+ **Second-pass reviewer:** `not required` (Layer 1 hook-template content change, signal-only, no gate authority — Phase 5 trigger inventory below)
7
+
8
+ ## Summary of the change
9
+
10
+ `PostUpdateMigrator.getSessionStartHook()` and `getTelegramTopicContextHook()` (the inlined bash templates that get unconditionally overwritten onto every agent's disk on update) now each emit a `--- CURRENT TIME ---` block backed by a fresh `date(1)` invocation. The block contains an ISO-formatted wall-clock timestamp with signed offset and timezone abbreviation, plus a one-line instruction to the agent: "Quote this — do not carry stale clock times from prior context."
11
+
12
+ **Files touched:**
13
+ - `src/core/PostUpdateMigrator.ts` — 14 lines added to `getSessionStartHook()` (after the `=== SESSION START ===` echo, before the TOPIC CONTEXT block); 14 lines added to `getTelegramTopicContextHook()` (immediately before the [telegram:N] early-exit, so the block fires on every UserPromptSubmit regardless of prefix).
14
+ - `tests/unit/PostUpdateMigrator-time-injection.test.ts` — new file, 13 test cases. Static assertions on the inlined bash (date format string, non-empty guard, delimiter strings, relative ordering within each hook) PLUS end-to-end `execFileSync` of each hook script against a fresh temp dir, asserting the actual emitted output matches the expected `YYYY-MM-DD HH:MM:SS +ZZZZ (TZ)` shape on a non-telegram prompt, a telegram-prefixed prompt, and a session-start invocation.
15
+ - `upgrades/NEXT.md` — new vNEXT entry, classified `patch` (behavior fix, no new surface).
16
+
17
+ ## Decision-point inventory
18
+
19
+ - **Where the time block lands in session-start output** — *modify*. Placed AFTER `=== SESSION START ===` and BEFORE the TOPIC CONTEXT block. Rationale: the wall-clock is generic orientation, not topic-specific — it belongs at the top of the orientation frame, ahead of the per-conversation context. Asserted by test `places the time block BEFORE the TOPIC CONTEXT block`.
20
+ - **Where the time block lands in UserPromptSubmit** — *modify*. Placed BEFORE the `[telegram:N]` early-exit. Rationale: the script's filename suggests telegram-only, but UserPromptSubmit fires on every prompt — emitting the time block before the early-exit makes the fix universal (Telegram and direct-CLI sessions both get it). Asserted by test `emits the time block BEFORE the [telegram:N] early-exit`.
21
+ - **Output guard against a broken `date(1)`** — *new*. Wrap the emission in `if [ -n "$NOW" ]; then ... fi` so a hypothetical environment where `date(1)` returns empty (extremely unlikely on macOS/Linux) doesn't produce a `--- CURRENT TIME ---` header with no value. Asserted by test `wraps the emission in a non-empty guard`.
22
+ - **Date format choice** — *new*. `'%Y-%m-%d %H:%M:%S %z (%Z)'`. Portable across BSD date (macOS) and GNU date (Linux); produces both machine-parseable (`%z`) and human-readable (`%Z`) timezone forms. Verified by the end-to-end test which `execFileSync`s the hook and regex-matches the emitted body.
23
+ - **Delimiter style** — *match existing*. `--- CURRENT TIME ---` / `--- END CURRENT TIME ---` mirrors the dashed delimiters already used in session-start for other blocks (`--- CONVERSATION CONTEXT ---`, `--- INTEGRATED-BEING ---`, `--- PROJECT CONTEXT ---`). No new visual convention introduced.
24
+
25
+ ## Level-of-abstraction fit
26
+
27
+ This is a Layer 1 (hook content) change. It belongs at the migrator level — both because the migrator is the source of truth for hook content (init and update both write from `getSessionStartHook()` / `getTelegramTopicContextHook()`) and because the failure mode (stale clock in long agent sessions) is a cross-cutting infrastructure gap, not a per-agent or per-feature concern. Solving it per-agent (e.g. Iris's memory file `feedback_clock_time_must_call_date.md`) closed the gap for one agent. Lifting it to the framework means every instar agent gets the same anchor without each one having to learn the lesson independently — which matches the **Structure > Willpower** principle stated in CLAUDE.md.
28
+
29
+ ## Signal-vs-authority compliance
30
+
31
+ The hook injection emits text. It does not gate, block, modify, or veto any agent action. It is pure signal — the agent reads the wall-clock and is told to quote it. Authority over whether to use the time, what time to claim, or whether to call `date` again later remains entirely with the agent. No new blocking authority introduced.
32
+
33
+ ## Interactions
34
+
35
+ - **Compaction recovery** (`compaction-recovery.sh`): On `compact` event, `session-start.sh` `exec`s away to `compaction-recovery.sh` BEFORE the time block is reached. So the time block does not run during compact-recovery. Compaction-recovery's own injection pipeline is separate and is not regressed by this change. The block DOES run on resume, which fires after compaction completes. No double-emission.
36
+ - **Telegram early-exit**: Adding output BEFORE the `[telegram:N]` early-exit means the hook now produces output on every UserPromptSubmit, including non-telegram prompts. This is intentional — direct-CLI sessions need the time anchor too. Effect on Claude Code: an additional ~3-line block in the agent's prompt buffer per turn. Token cost negligible (~30 tokens).
37
+ - **Integrated-Being v2 session-bind**: The session-bind block in `session-start.sh` lives AFTER the time block but runs independently. Time injection produces output via stdout; session-bind makes HTTP calls and writes a token file. No shared variables, no ordering dependency.
38
+ - **Existing PostUpdateMigrator-sharedState test**: Asserts the integrated-being injection survives in `getSessionStartHook()`. The new time block sits BEFORE the integrated-being block; the existing assertion (`expect(hook).toContain('/shared-state/render?limit=50')`) continues to pass — verified in test run.
39
+
40
+ ## Over/under-block check
41
+
42
+ - **Under-block**: Could the fix miss any cases where an agent says a clock time?
43
+ - **Mid-session tool-result handoffs**: If an agent receives a Claude Code tool result and immediately replies with a time claim, the most recent time anchor is the previous UserPromptSubmit. Up to 5 minutes stale in fast back-and-forths, less for slow ones. Acceptable — within a single turn, ±a-few-minutes is fine. Worst-case would be a multi-hour autonomous-mode tool loop without user prompts, in which case the agent could go stale. Mitigated separately by autonomous-mode's existing periodic re-orientation; not in scope here.
44
+ - **Subagent invocations**: Sub-agents started via the `Agent` tool inherit the parent's prompt context, not the live hook output. So a subagent's time anchor is the parent's at-spawn time. Acceptable — subagents are short-lived and rarely make wall-clock claims; their job is task execution.
45
+ - **Over-block**: Could the fix cause an unintended block, refusal, or behavior change elsewhere?
46
+ - **Hook timeout (5s budget for UserPromptSubmit)**: Adding a `date` call adds <1ms. No timeout risk.
47
+ - **Token bloat in long sessions**: ~30 tokens per turn × thousands of turns = a few hundred-K tokens over a long session. Compared to the existing telegram-topic-context block (~500 tokens / turn for recent history), this is a rounding error.
48
+ - **Test pollution**: The end-to-end test uses `mkdtempSync` + per-test env var override, no persistent state. No effect on parallel test runs.
49
+
50
+ ## Rollback cost
51
+
52
+ Two-line `git revert` of the migrator edit, plus deleting the new test file. Hooks are unconditionally overwritten on next migration run, so a revert propagates to all deployed agents on their next `npx instar`. No data migration, no persistent state, no fan-out — zero rollback friction.
53
+
54
+ ## Phase 5 trigger check
55
+
56
+ Was a second-pass reviewer required? No.
57
+
58
+ - **Not a gate change**: No new authority, no blocking, no veto, no permission alteration. Signal-only.
59
+ - **Not a security-sensitive surface**: No new file reads outside the hook's existing scope (it only adds a `date` call); no new network calls; no new credential or token handling.
60
+ - **No new persistent state**: Output flows to stdout, consumed by Claude Code's prompt injector. No disk writes, no SQLite, no JSONL.
61
+ - **No cross-agent or cross-machine effect**: Per-agent hook content. No threadline message, no shared state, no remote operation.
62
+
63
+ The change crosses **none** of the second-pass triggers from the side-effects review standard. A single-pass review by the author with this written record is sufficient.