@@ -5,6 +5,88 @@ All notable changes to this project.
55The format follows [ Keep a Changelog] ( https://keepachangelog.com/en/1.1.0/ ) ,
66and the project adheres to [ Semantic Versioning] ( https://semver.org/spec/v2.0.0.html ) .
77
8+ ## [ 0.9.1] — 2026-04-26
9+
10+ Patch release that closes the gap between v0.9.0 and a working pi adapter.
11+ Every brew user on v0.9.0 hit the first bug; the rest are quieter but make
12+ the dream cycle and the cross-harness episodic log actually correct.
13+
14+ ### Fixed
15+ - ** ` agentic-stack pi ` crashed for every brew user with `ModuleNotFoundError:
16+ No module named 'harness_manager'`.** The v0.9.0 Formula didn't include
17+ ` harness_manager/ ` in ` pkgshare.install ` , so ` install.sh ` couldn't dispatch.
18+ Adds it back.
19+ - ** Pi dream cycle never fired.** The ` session_shutdown ` handler filtered
20+ on ` event.reason ` , but Pi's ` SessionShutdownEvent ` carries no ` reason `
21+ field — verified against ` pi-coding-agent ` types.d.ts and the emit site
22+ at ` agent-session.js:1638 ` . The filter rejected every event, so
23+ ` auto_dream.py ` never ran. Filter dropped; re-entrancy guard added.
24+ - ** Pi edit reflections lost the diff.** Hook accessed ` event.input.edits[0] `
25+ but Pi's ` EditToolInput ` is flat ` { path, oldText, newText } ` (no ` edits `
26+ array — that's MultiEdit on Claude Code). Reflections silently degraded
27+ to ` Edited <path> ` with no old/new content. Read the flat fields.
28+ - ** ` decay.py ` crashed comparing aware-UTC entries to naive cutoff.** The
29+ new ` session_shutdown ` hook surfaced this on every clean pi exit. Cutoff
30+ is now ` datetime.now(timezone.utc) ` ; entry timestamps are normalised to
31+ UTC before comparison.
32+ - ** Naive-local Python timestamps drifted against the UTC decay window.**
33+ Decay's "naive == UTC" assumption was correct only if writers emitted UTC.
34+ They didn't: ` post_execution ` , ` on_failure ` , ` learn ` , ` graduate ` ,
35+ ` promote ` , ` review_state ` , ` render_lessons ` all wrote naive-local. Every
36+ writer now emits aware UTC; every reader (` salience ` , ` show._human_age `
37+ / ` _daily_counts ` / ` failing_skills ` / ` last_dream_cycle ` ,
38+ ` on_failure._count_recent_failures ` , ` review_state._age_factor ` ,
39+ ` archive ` ) normalises naive timestamps to UTC before comparison.
40+ - ** One bad regex in ` hook_patterns.json ` disabled every user pattern in
41+ the Pi hook.** Pre-fix used a single combined RegExp per list, caught
42+ any error, returned null for both. Now per-fragment validation with
43+ incremental merge — same posture as ` claude_code_post_tool.py ` 's
44+ ` _filter_valid ` / ` _build_with_fallback ` .
45+ - ** ` auto_dream ` lost entries that landed mid-cycle.** Original ` _write_entries `
46+ had a truncate-before-lock window — ` open(path, "w") ` truncates BEFORE
47+ a lock can be taken. The deeper bug: even after fixing the inner race,
48+ any ` append_jsonl() ` between ` _load_entries() ` and ` _write_entries(kept) `
49+ would be truncated away by the rewrite. The cycle now holds a single
50+ exclusive flock on ` AGENT_LEARNINGS.jsonl ` across the entire
51+ read-modify-write window via ` _episodic_locked() ` . Mutually exclusive
52+ with ` _episodic_io.append_jsonl ` (same flock target). POSIX only;
53+ Windows falls back to historical best-effort behaviour.
54+ - ** ` _cachedSha ` went stale after ` git commit ` inside a pi session.** TS
55+ hook cached the SHA per-process for performance, so every entry logged
56+ after a mid-session commit recorded the pre-commit SHA. Cache, but
57+ invalidate on bash commands matching ` git <subcmd> ` for HEAD-moving
58+ subcommands. Allows option flags between ` git ` and the subcommand
59+ (` git -c key=val checkout main ` , ` git -C path switch dev ` ).
60+ - ** ` salience ` over-scored future-skewed legacy rows.** Legacy naive-local
61+ timestamps re-interpreted as UTC could read as a few hours in the future
62+ during the migration window. ` timedelta.days ` then went negative and
63+ recency exceeded the intended cap. Floor age at 0; clamp recency to ≤ 10.
64+ - ** ` decay ` archive filename used local date while cutoff was UTC.**
65+ ` archive_{date}.jsonl ` now uses UTC date so a tz-jumping user gets a
66+ deterministic path.
67+
68+ ### Changed
69+ - ` adapters/pi/adapter.json ` no longer manages
70+ ` .agent/harness/hooks/pi_post_tool.py ` via ` from_stack ` . The TS hook is
71+ self-contained — all scoring + reflection inline, no Python subprocess
72+ per tool call. The .py still ships in the brain template under
73+ ` .agent/harness/hooks/ ` for standalone use.
74+ - ` tests/ ` is now untracked and listed in ` .gitignore ` . CI never ran
75+ these (` .github/workflows/ci.yml ` runs ` test_claude_code_hook.py ` +
76+ ` verify_*.py ` at repo root). Pull from an older tag if you want the
77+ unittest suite locally.
78+
79+ ### Migration
80+ ` brew upgrade agentic-stack ` is enough — there are no on-disk schema
81+ changes. Existing pi installs with the v0.9.0 hook get the new logic on
82+ the next ` ./install.sh pi ` . Existing ` .agent/memory/episodic/AGENT_LEARNINGS.jsonl `
83+ files with naive-local timestamps continue to work — readers normalise
84+ them at compare time and writers emit UTC going forward.
85+
86+ ### Credits
87+ PR #24 by @aliirz ; Codex CLI used for an independent second-opinion review
88+ that surfaced the auto_dream window race + the SHA-regex narrowness.
89+
890## [ 0.9.0] — 2026-04-23
991
1092### Added
0 commit comments