# MEMORY.md rotator — uchg i fail-closed recovery, MC #900028

# MEMORY.md rotator — uchg i fail-closed recovery, MC #900028

**Datum:** 2026-08-21  
**Komponenta:** `~/system/tools/memory-md-rotator.js`  
**Core fix commit:** `fbda56bc5`  
**P1 closeout commit:** `14667cdc259e8ab5d94edc47c6c70987c9db8330`  
**Validation:** Opus 5 high acceptance gate + GPT-5.6 Sol high builder; nezavisni Claude peer

## Problem

`MEMORY.md` namjerno nosi macOS `uchg` flag kako dvije sesije ne bi jedna drugoj pregazile indeks direktnim truncate-writeom. Sankcionisani `memory-writer.js` privremeno skida flag, piše i vraća zaštitu.

Rotator je ranije pisao direktnim `writeFileSync`, bez upravljanja flagom. Rezultat je bio EPERM, daemon exit 1 i rast indeksa preko kontekstnog limita.

## Core popravka

Rotator sada:

- čita stvarne BSD flagove;
- skida `uchg` samo ako je prethodno bio postavljen;
- vraća ga u `finally`;
- ne dodaje lock prvobitno nezaključanom `--file` fixtureu;
- radi compare-and-swap provjeru prije archive mutacije i prekida na konkurentnom upisu.

Živi ishod:

```text
MEMORY.md: 21.781 B, ispod 22 KiB triggera
flag: uchg
latest daemon exit: 0
latest scheduled run: 8 unosa rotirano, 23.75 KiB -> 20.78 KiB
```

Aktivni Write/Edit hook i dalje blokira direktan upis u live MEMORY.md.

## P1 pronađen nezavisnim peerom

Prva verzija je na neuspjehu završnog `chflags uchg` ispisala upozorenje, ali je API ipak vraćao success i CLI izlazio 0. Fajl je mogao ostati writable bez mašinski vidljivog kvara.

Nezavisni validator je fault injectionom dokazao:

- re-lock pokušaj se stvarno desio;
- chflags je simulirano pao;
- fajl je ostao writable;
- CLI je pogrešno izlazio 0 i ispisao `Rotated ...`.

## Fail-closed korekcija

Kod sada pravi error s kodom:

```text
MEMORY_MD_UCHG_RESTORE_FAILED
```

Ako vraćanje zaštite padne:

- stderr eksplicitno imenuje fajl i writable stanje;
- API baca grešku umjesto success rezultata;
- CLI izlazi nonzero;
- nema lažnog `Rotated N entries` success sažetka.

## Testovi

Fokusirani testovi koriste samo disposable `/tmp` fixturee i PATH shim koji deterministički obara `chflags uchg` nakon uspješnog `nouchg`.

```text
focused restore-failure tests: 2/2 PASS
full system suite: 33/33 PASS
Fusion immutable gate: 38/38 PASS
mutation control: pre-P1 source 0/2 PASS, očekivano odbijen
```

Dodatno dokazano:

- locked rotacija uspije i vrati flag;
- unlocked fixture ostaje unlocked;
- repeat/no-candidate je idempotentan;
- konkurentni upis abortira prije archive mutacije;
- direktni Write/Edit hook ostaje blokirajući.

## Evidence

- `/Users/makinja/system/evidence/900028/fix-verification-2026-08-20.md`
- `/Users/makinja/system/evidence/900028/peer-validator-claude-sonnet-2026-08-21.md`
- `/Users/makinja/system/.claude/worktrees/flowforge-107073-33d6-verify/evidence/900028/p1-fail-closed-2026-08-21.md`
- `/tmp/fusion-harness-RndOmb/summary.json`
- `/tmp/fusion-harness-RndOmb/gate-round-1.txt`

## Preostalo, neblokirajuće

- 20 KiB target nije uvijek dostižan uz 14-dnevnu retention politiku; trenutni fajl je ipak ispod 22 KiB triggera.
- Arhive 18/19.08. nose redundantne kopije iz pre-fix partial runova; nema gubitka podataka.
- Shared alert/memory state locking je zasebna arhitektonska tema, nije dio ovog patcha.

## Rollback

```bash
cd /Users/makinja/system
git revert 14667cdc259e8ab5d94edc47c6c70987c9db8330
```

Rollback vraća P1 (exit 0 nakon neuspješnog re-locka) i zato nije preporučen osim kao hitna dijagnostika.