fix: BOM-tolerant JSON readers, decay persistence on no-match, Windows-safe Python detection (v4.6.2)#25
Open
Luispitik wants to merge 9 commits into
Open
fix: BOM-tolerant JSON readers, decay persistence on no-match, Windows-safe Python detection (v4.6.2)#25Luispitik wants to merge 9 commits into
Luispitik wants to merge 9 commits into
Conversation
JSON.parse throws on a UTF-8 BOM, and every reader wrapped it in a catch that exits 0 — so an index, registry, rules or proposals file saved with a BOM (Windows editors, PowerShell redirects) silently disabled the whole pipeline with no error anywhere. Strip the BOM before parsing in _instinct-activator.sh, _session-learner.sh (5 read sites via a readJson helper), _dream.sh, _eod-gather.sh (canonical + legacy reads), _passive-activator.sh and _project-context.sh. _generate-dashboard.py now reads JSON with encoding='utf-8-sig', which accepts both BOM and BOM-less files. Fixes #16 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The v4.4 decay pass demotes stale instincts (confirmed 60d inactive to draft, draft 90d inactive to archived) before matching, but the only index write sat after the no-match early-exit. On every tool use that matched nothing, demotions were recomputed and then discarded — so in practice stale instincts never actually decayed unless some other instinct happened to match in the same invocation. Extract the atomic index write into persistIndex() (dream-lock check and archived filtering preserved) and call it before the early-exit when decayDirty is set, logging the demotions to _instinct.log as the matched path already did. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
On Windows, python3 commonly resolves to the Microsoft Store alias shim: it answers command -v but does not execute (prints an install notice and exits non-zero). install.sh then aborted the whole install under set -e at PYTHON_VER=$(python3 --version), and observe.sh silently piped every observation into the shim, recording nothing. Iterate candidates — py -3 first (the real Windows launcher), then python3/python/python3.x — and only accept a command whose --version output actually starts with "Python 3.". The version echo in install.sh is guarded with || true so a stray shim cannot abort under set -e. No behaviour change on macOS/Linux, where py does not exist and python3 is accepted on the second iteration. Aligned with PR #24 (credit: juanparisma) with one deliberate deviation: the PR pins minors 3.9-3.13, which silently rejects Python 3.14+ — reproduced locally, where 3.14.0 made observe.sh no-op again. Matching any "Python 3." keeps the original semantics while still rejecting the shim. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ction 12 tests in tests/test-bom-decay-python.sh: - BOM (#16): functional — BOM-prefixed index still injects and increments occurrences; BOM-prefixed rules file still fires; static checks that the strip is present in all 6 core readers and that the dashboard reads utf-8-sig. - Decay: functional — stale confirmed instinct is persisted as draft and stale draft is archived out of the index on a no-match tool use; fresh instincts cause no spurious rewrite. - Python detection: static checks on observe.sh and install.sh plus a functional run where a Store-shim-like python3 is skipped and a Python 3.14 interpreter is accepted and executes the observer. Verified A/B: 11/12 fail on main (the 12th is a both-sides guard), 12/12 pass with the fixes. All 11 pre-existing suites stay green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… hot path
The candidate loop ran cmd=$(echo ... | awk '{print $1}') per candidate,
two forks inside observe.sh which fires on every PreToolUse/PostToolUse
(process spawn is expensive under Git Bash on Windows). Native
${candidate%% *} expansion extracts the first word with zero forks.
Also adds the v4.6.2 CHANGELOG entry covering the three fixes in this
branch (#16 BOM tolerance, decay persistence on no-match, Windows-safe
Python detection aligned with #24).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The final banner still announced '2 global skills' (Step 7 copies 3: sinapsis-learning, sinapsis-instincts, skill-router) and '5 hook scripts' (Step 5 installs 6 plus the dream cycle since v4.5 added _precompact-guard.sh). Cosmetic drift reported in #17. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This was referenced Jun 10, 2026
Open
The new tests/test-bom-decay-python.sh suite guarded #16 and the decay persistence fix only locally — the workflow still ran just the original 5 suites, so a regression would not have been caught on PRs. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The workflow only exercised 5 of the 12 suites; dashboard, eod-gather, install-upgrade, registry-isolation, v4.5 and v4.6 ran only on the maintainer machine. Wire the remaining 6 in so every PR exercises the full battery on the three platforms. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Every hook script was committed with mode 100644, so a fresh clone on Linux/macOS has no executable bit anywhere — surfaced by running test-v45-opus47.sh in CI, where T5 asserts -x on _precompact-guard.sh (it passed on Windows only because Git Bash's -x check is lax). Runtime never noticed because install.sh chmods on install and the suites invoke scripts via bash. Set 100755 on the shebang scripts: core/*.sh, _generate-dashboard.py, install.sh and observe.sh. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Three independently verified fixes, found during a full audit of the learning pipeline (each reproduced A/B against
mainbefore fixing):1. UTF-8 BOM silently disabled the whole pipeline — closes #16
JSON.parsethrows on a UTF-8 BOM and every JSON reader wrapped it in acatch { exit 0 }, so an_instincts-index.json(or rules/registry/proposals file) saved by a Windows editor or a PowerShell redirect stopped occurrence tracking, learning, passive rules, dream, eod and the project-context bridge — with no error anywhere. All 6 core readers now strip the BOM before parsing;_generate-dashboard.pyreads withencoding='utf-8-sig'. Writers never emit a BOM, so the first atomic write self-heals the file. Reported by @juanparisma — thanks for the precise repro.2. Confidence-decay demotions were discarded on the no-match path
The v4.4 decay pass demotes stale instincts before matching, but the only index write sat after the no-match early-exit: on every tool use that matched nothing, demotions were recomputed and thrown away. Stale instincts effectively never decayed unless an unrelated instinct matched in the same invocation. The atomic write is now extracted into
persistIndex()(dream-lock check and archived filtering preserved) and runs before the early-exit, logging demotions to_instinct.logas the matched path already did.3. Microsoft Store python3 shim aborted install.sh and silenced observe.sh
Aligned with #24 (credit: @juanparisma for the diagnosis and the candidate-loop approach). One deliberate deviation: #24 pins minors
3.9-3.13, which silently rejects Python 3.14+ — reproduced locally, where 3.14.0 madeobserve.sha no-op again, the same failure class the fix targets. This branch accepts anyPython 3.and extracts the first word with native${candidate%% *}expansion (no awk forks in the per-tool-use hot path).Tests
tests/test-bom-decay-python.sh: 12 tests (A/B BOM repros, decay persistence/archival on no-match, no spurious rewrites, fake Store shim functional run).test-install-upgrade,test-securityandtest-dashboard.🤖 Generated with Claude Code