Commit 90d77d9
codejunkie99
harden episodic writes: fcntl lock + fix pi skills orphan sync
Two pre-existing infrastructure bugs flagged during the PR #17 cross-model
review, fixed here against master because they predate that PR and
affect every harness.
## 1. Concurrent writes to AGENT_LEARNINGS.jsonl
post_execution.py and on_failure.py both did plain `open(EPISODIC, "a")`
→ `f.write(json.dumps(entry) + "\n")`. POSIX O_APPEND makes single
`write(2)` calls atomic only up to PIPE_BUF (4 KB on Linux/macOS).
In practice most entries stay under that ceiling and the unlocked code
never corrupts, but the `reflection` field is uncapped in log_execution
and can easily exceed 4 KB on high-importance failure logs. Every
downstream reader (auto_dream.py, cluster.py, context_budget.py,
show.py) skips `json.JSONDecodeError` lines silently — so one
over-PIPE_BUF interleave = one episodic entry gone with no signal.
Fix: new `_episodic_io.append_jsonl()` helper that opens in append-
binary mode (no Python text-mode buffering quirks) and wraps the
write in `fcntl.flock(LOCK_EX)`. Shared by both writers. On platforms
without fcntl (native Windows Python) behavior falls back to the
pre-fix unlocked append; WSL, git-bash/Cygwin, macOS, Linux all have
fcntl.
Verified: 40 concurrent writers × 500 entries × 2 KB reflection each
→ 20,000 parseable lines, zero corruption.
## 2. pi install.sh silently leaves stale skills on re-install
`ln -sfn src dest` where `dest` is a REAL directory (e.g. from an
earlier copy-fallback install) silently creates `dest/<basename-of-src>`
INSIDE the dir and exits 0. The existing `if ln -sfn; then` branch
took the success path, the `rm -rf + cp` fallback never ran, and
orphans stuck around forever. Verified on macOS, confirmed the
symlink-inside-dir behavior.
Fix: check `-L` (symlink) and `-d` (real dir) explicitly before
calling `ln -sfn`, mirror the pattern used by the codex adapter
(PR #16 follow-up). Existing symlink → cheap repoint. Real directory
→ rsync --delete when available, rm+cp otherwise. Non-existent →
symlink or copy fallback. Same three-branch shape, no more silent
wrong behavior.
Verified: re-install after orphan-skill was added to a real-dir
`.pi/skills` → rsync --delete removes the orphan.1 parent 63bbbd9 commit 90d77d9
4 files changed
Lines changed: 72 additions & 15 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
| 4 | + | |
4 | 5 | | |
5 | 6 | | |
6 | 7 | | |
| |||
69 | 70 | | |
70 | 71 | | |
71 | 72 | | |
72 | | - | |
73 | | - | |
74 | | - | |
75 | | - | |
| 73 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | | - | |
| 2 | + | |
3 | 3 | | |
| 4 | + | |
4 | 5 | | |
5 | 6 | | |
6 | 7 | | |
| |||
15 | 16 | | |
16 | 17 | | |
17 | 18 | | |
18 | | - | |
19 | 19 | | |
20 | 20 | | |
21 | 21 | | |
| |||
31 | 31 | | |
32 | 32 | | |
33 | 33 | | |
34 | | - | |
35 | | - | |
36 | | - | |
| 34 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
133 | 133 | | |
134 | 134 | | |
135 | 135 | | |
136 | | - | |
137 | | - | |
138 | | - | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
139 | 143 | | |
140 | | - | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
141 | 158 | | |
142 | 159 | | |
143 | | - | |
144 | | - | |
| 160 | + | |
145 | 161 | | |
146 | 162 | | |
147 | 163 | | |
| |||
0 commit comments