# Session 2026-05-22 — Closure + i18n sweep + Layer 4 architecture

> Closure log for the 2026-05-22 session. 8 PRs merged on `main`
> (`70ee9e9` → `9082c17`) + 3 docs PRs open (#401 / #402 / #403).
>
> **Two primary discoveries this session**:
>
> 1. **i18n debt** — §3 cognitive lang-toggle live verification
>    surfaced systemic i18n debt (~80 UI strings stuck). 6-PR sweep
>    (`#393`/`#394`/`#395`/`#396`/`#397`/`#398`/`#400`) applied the
>    `label_key` contract across 7 backend modules.
> 2. **CASCADE vs EVENT separation axiom** (late-session) — review
>    of the v0.4 architecture proposal (PR #401) crystallised the
>    distinction between *invalidation propagation* (CASCADE,
>    Layer 3) and *semantic evolution* (EVENT, Layer 4-A). New
>    **T7 Supersede Chain** area added; v0.4 first ship bundle
>    rescoped to **T1+T7+T2**. ROADMAP.md retargeted v0.4 = Layer
>    4 Lifecycle Semantics (PR #403); Domain Pilot shifts to v0.5.

---

## 0. Session map

Entry: `docs/handovers/v0.3.x-session-2026-05-21-review-checklist.md`
§13 cited §3 cognitive lang-toggle (Phase 2~5) as the day's first
live-verification path. Phase 1 (KO first-load) surfaced an
unexpected scope expansion — the bug wasn't limited to PR #378's
6 rows.

Closure: this file. Next session should start with
[§7 next-session entry guide](#7-2026-05-23-진입-가이드).

---

## 1. Merged PRs (8) — origin/main `70ee9e9` → `9082c17`

| # | PR | Topic | Source |
|---|---|---|---|
| 1 | [#393](https://github.com/Hashevolution/James-RAG-Evol/pull/393) | cognitive 6 row label i18n | §3 Phase 1 finding |
| 2 | [#394](https://github.com/Hashevolution/James-RAG-Evol/pull/394) | **PR-1** admin.html sweep — raw key + nav + 서버설정 + 웹검색 | i18n sweep |
| 3 | [#395](https://github.com/Hashevolution/James-RAG-Evol/pull/395) | **PR-2** Policy matrix feature description (23) | i18n sweep |
| 4 | [#396](https://github.com/Hashevolution/James-RAG-Evol/pull/396) | **PR-3** 능력 성장 / 도메인 (8 cap + 6 domain) | i18n sweep |
| 5 | [#397](https://github.com/Hashevolution/James-RAG-Evol/pull/397) | **PR-4** character radar + Fine Tune (15 traits) | i18n sweep |
| 6 | [#398](https://github.com/Hashevolution/James-RAG-Evol/pull/398) | **PR-5** 메인 페이지 + mode dropdown (5 static + 7 modes) | i18n sweep |
| 7 | [#399](https://github.com/Hashevolution/James-RAG-Evol/pull/399) | reasoning cap defaults — bump above gemma4:e4b reasoning floor | operator-driven (별 트랙) |
| 8 | [#400](https://github.com/Hashevolution/James-RAG-Evol/pull/400) | **PR-6** hardware tier names (21+21+4) | i18n sweep (시리즈 완성) |

### Static + curl verification

- ✅ 2370 tests pass (prior 2353 + 17 new across i18n contract tests)
- ✅ ruff clean on every changed Python file
- ✅ Every PR CI: 4/4 SUCCESS (CLA / ruff / bandit / pytest)

### Open PRs

- [#401](https://github.com/Hashevolution/James-RAG-Evol/pull/401)
  docs(architecture): 5-layer Memory Lifecycle Architecture + v0.4
  Layer 4 디자인 메모 — **operator-driven, awaiting review**.
  Disjoint from this session's i18n track.

---

## 2. Discovery — §3 Phase 2 systemic i18n debt

§3 cognitive lang-toggle plan from the prior session expected
PR #378's 6 row labels as the only stuck text. Phase 1 (KO first
load) instead surfaced **~80 strings stuck** across both languages:

| Category | Pattern | Bug |
|---|---|---|
| Missing i18n key | `set.web_search_title`, `growth.recent_gains` | `data-i18n` bound but key absent from i18n.js → raw key shown |
| KO mode stuck (EN labels) | nav 3 / 서버설정 / 웹검색 / 능력 성장 / 도메인 / 장비 현황 / 7 protected files | Backend label rendered raw; no `data-i18n` attr |
| EN mode stuck (KO labels) | character radar 12 axes + Fine Tune 14 sliders / Policy matrix 23 feature descriptions / 메인 페이지 7 mode dropdowns + 폴더/추천/복사 | Frontend rendered `tr.label_ko \|\| tr.label` unconditionally / backend returned KO description only |

Initial single-fix PR (#393) was insufficient. Diagnosis → 6 PR
sweep (PR-1~6) applying the `label_key` contract pattern across the
codebase.

---

## 3. The `label_key` contract (now invariant)

PR #393 introduced the pattern. PR-1~6 propagated it. Every
backend label that surfaces to UI must now carry a `label_key`
field; the UI binds `data-i18n` to it and falls back to the EN
string on i18n table miss.

### Convention

| Backend module | Namespace |
|---|---|
| `core/feature_flags.py` | `set.cognitive_flag_<key>` |
| `core/feature_registry.py` | `policy.feature.<id_with_underscores>` |
| `core/knowledge_tracker.py` | `growth.capability.<id>` + `growth.domain.<id>` |
| `core/character_profile.py` | `char.trait.<id>` |
| `server_llmwiki.py` (modes) | `mode.<key>` |
| `tools/system/hardware_inspector.py` | `hw.<component>.tier_<short_id>` + `hw.<component>.desc_<short_id>` + `hw.role.<role>` |
| `frontend/admin.js` (`LLM_TASK_TYPES` / `PROTECTED_CANDIDATES`) | `set.llm_task_<key>` / `set.protected_<file>` |

### UI binding

Every dynamic render that injects text from backend data now ends
with `applyTranslations()` so newly-inserted `data-i18n` nodes pick
up the active language without waiting for the next manual sweep.

### Regression guard

5 new contract tests pin the namespace + uniqueness:
- `tests/test_feature_flags.py` (PR #393 + #394)
- `tests/test_feature_registry.py` (PR #395)
- `tests/test_knowledge_tracker_i18n.py` (PR #396, NEW)
- `tests/test_character_profile_i18n.py` (PR #397, NEW)
- `tests/test_hardware_inspector_i18n.py` (PR #400, NEW)

Adding a new feature / capability / trait / tier now fails CI
unless the convention is followed.

### Scoreboard

| PR | Module | Keys added |
|---|---|---|
| #393 | feature_flags | 12 |
| #394 | admin.html sweep | 36 |
| #395 | feature_registry | 46 |
| #396 | knowledge_tracker | 46 |
| #397 | character_profile | 30 |
| #398 | server_llmwiki (modes) + index.html | 42 |
| #400 | hardware_inspector | 92 |
| **Total** | | **~304 i18n entries** |

---

## 4. §9 invariant matrix — verified

| # | Invariant | Status | Evidence |
|---|---|---|---|
| 1 | PolicyEngine + ABAC default-deny | ✅ curl | no/wrong/system api_key → 403; admin JWT required |
| 2 | `entity_id` 불변성 | ✅ static | `NODE_EDITABLE_FIELDS` excludes `entity_id` |
| 3 | Knowledge Cascade sources[] 4-role | ✅ static | `VALID_SOURCE_ROLES` (legacy/extract/inverse/manual) preserved |
| 4 | external default-deny (PR-O5) | ✅ static | `feature_registry.query.internal_rag` excludes external + `reasoning/engine.py:282-292` enforces |
| 5 | CR-E 인간 승인 | ✅ auto | no self-evolution PR this session |
| 6 | 5-agent cap | ✅ auto | cognitive Phase 4 not entered |
| 7 | Session writes never escape upward | ✅ auto | PR-11d MemoryLoom not entered |

§9 fully cleared.

---

## 5. §10 Phase 3 gate — status

Per `v0.3.x-session-2026-05-21-review-checklist.md` §10:

- [ ] §2 graph evolution (12 items) — **operator action still pending**, needs admin JWT in browser
- [x] §3 cognitive toggle — **fixed via 6 PR sweep**, live re-verification pending operator
- [ ] §4 LLM mapping — pending live verification
- [ ] §5 feedback stats — pending live verification
- [ ] §6 history stale — pending live verification
- [x] §9 invariant — ✅
- [ ] STEP 7 bench `--check` — **not yet run this session**

Phase 3 (admin.html → 3 HTML 페이지 분할) entry remains blocked
on operator live re-verification + STEP 7 bench.

---

## 6. Operator action (deferred from this session)

### 6.1 Live re-verification (browser, ~30분)

After server restart + hard browser refresh (Ctrl+F5):
1. Admin lang toggle (KO↔EN) — nav / 설정 / 권한 매트릭스 / 능력 성장 / 성향 캐릭터 / 장비 현황 모두 양방향 즉시 전환
2. Main page lang toggle — 폴더 선택 / 추천 / 대화 전체 복사 / mode dropdown 모두 전환
3. §2.1/2.3/2.4 admin POST event / 시간 윈도우 / PUT event — graph editor or DevTools fetch
4. §4 LLM mapping + §5 feedback stats + §6 history stale — settings/memory tabs

### 6.2 Local main sync (8 unpushed commits)

The operator's local `main` is ahead of `origin/main` by 8 commits
(V3'.a + V3'.b research artefacts, CLA infra closure docs, Ali
walk-back routing). These were already partially absorbed via
prior squash merges (#391); the remaining are operator's local
research work.

Recovery options (operator picks):
```powershell
# Option 1 — preserve local research, sync via rebase
git stash -u
git checkout main
git pull --rebase origin main
git stash pop

# Option 2 — split local work to a new branch, hard-sync main
git branch research/v3prime-local-work
git checkout -B main origin/main
```

### 6.3 Branch cleanup (optional)

After PR-1~6 merged + branches auto-deleted on remote, local
copies linger:
- `fix/v0.3-i18n-sweep-main-pr5`
- `fix/v0.3-i18n-sweep-hardware-pr6`

```powershell
git branch -d fix/v0.3-i18n-sweep-main-pr5 fix/v0.3-i18n-sweep-hardware-pr6
```

---

## 7. 2026-05-23 진입 가이드

### 7.1 First action

Live re-verification of the i18n sweep (§6.1 above). This is the
single largest unverified change set landed this session; everything
else (STEP 7 bench, §2.1/2.3/2.4 graph event, §4/§5/§6) waits on
operator browser-side confirmation that the sweep works as
intended.

### 7.2 If regressions appear

Record per `v0.3.x-session-2026-05-21-review-checklist.md §11.1`
format:

```
| 발견일 | PR (의도) | 증상 | severity | 후속 |
```

Then fix PR follows the prior-session pattern — same-day fix PR
landing the missing keys / wiring.

### 7.3 If everything passes

Phase 3 entry path opens:
1. STEP 7 bench `--check` → record numbers
2. §2.1/2.3/2.4 graph event live verification (operator)
3. §4/§5/§6 ancillary live verification (operator)
4. Begin Option-A Phase 3 (admin.html → 3-page split)

### 7.4 Operator-driven side tracks + late-session architecture work

Two operator-initiated tracks ran in parallel this session,
unrelated to the i18n sweep, plus a late-session architectural
crystallisation that produced 3 docs PRs:

**Operator-driven, merged**:
- **#399** — reasoning cap defaults bumped above gemma4:e4b
  reasoning floor (200/400/400/400 → above the ~500-token hidden
  reasoning floor measured in V3'.a/.b). Already merged. Effect:
  query_rewrite / planner / reflect / verify stages should no
  longer silently empty on the 4B default model.

**Late-session architecture track (3 docs PRs open / merging this
session)**:
- **#401** — `docs/architecture/memory-lifecycle-architecture.md` +
  `docs/design/v0.4-lifecycle-semantics-roadmap.md`. v0.4 Layer 4
  Lifecycle Semantics reference. Initial draft → patent strategy
  sanitize (commit `4240187`) → CASCADE vs EVENT separation axiom
  + T7 Supersede Chain (commit `4f0acd7`).
- **#403** — `ROADMAP.md` retarget: v0.4 = Layer 4 (was: Domain
  Pilot). Domain Pilot shifts to v0.5. T7 + axiom reflected.
- **#402** — this closure handover.

### 7.5 CASCADE vs EVENT separation — late-session crystallisation

The architectural insight added late in the session (review of
PR #401 by the operator):

| Class | Trigger | Handling | Example |
|---|---|---|---|
| **Invalidated** → CASCADE (Layer 3) | Explicit invalidation signal (doc delete, ingestion error, source revoke) | Source removal + propagation + orphan sweep | Mis-uploaded doc / withdrawn report / typo |
| **Superseded** → EVENT/TEMPORAL (Layer 4-A) | New doc / time progression / policy change / state transition | Validity window close + supersede chain (past data preserved) | CEO change / policy revision / contract termination |

Many naive RAG/KG systems collapse both into one mechanism
(overwrite/append) → contradiction explosion, stale retrieval,
hallucination increase. v0.4 enforces the separation as a
**test-level invariant** (T7:
`supersede_does_not_trigger_cascade` +
`cascade_preserves_supersede_chain` +
`historical_replay_via_chain`).

JAMES already has both building blocks in v0.3:
- **CASCADE**: `core/cascade.py` 4 functions (Phase A–E)
- **EVENT entity (T7 precursor)**: `core/event_time_filter.py` +
  5th entity type `event` + `occurred_at` (PR #367/368/371/376)

v0.4 unifies the two under a single edge schema with
`mutation_type` field for routing
(`active` / `superseded` / `invalidated` / `derived`).

Full design in
`docs/architecture/memory-lifecycle-architecture.md §1.5` (axiom)
and `docs/design/v0.4-lifecycle-semantics-roadmap.md §9.5` (T7).

---

## 8. 한국어 한 줄 결론

본 세션 두 가지 큰 발견:

(1) **i18n debt**: §3 cognitive lang-toggle 라이브 검증이 단일 PR #378
의 6 row 회귀가 아니라 **시스템 전반의 i18n debt** 임을 드러냈고, 6 PR
sweep (#394~#398 + #400) 으로 7 backend 모듈에 `label_key` 패턴을 일관
적용해 ~304 i18n entries 추가 + 5 contract test 로 회귀 가드.

(2) **CASCADE vs EVENT 분리 axiom**: v0.4 architecture 메모 (PR #401)
검토에서 invalidation propagation (CASCADE, Layer 3) 과 semantic
evolution (EVENT, Layer 4-A) 의 명확 분리를 architectural axiom 으로
채택. T7 (Supersede Chain) 신규 추가, v0.4 first ship bundle =
T1+T7+T2 로 rescope. ROADMAP.md v0.4 = Layer 4 로 retarget (PR #403),
Domain Pilot → v0.5.

다음 세션은 라이브 재검증 (operator 브라우저) → STEP 7 bench → v0.4
Phase v0.4.0 (T1+T7+T2) 진입 (단, v0.3 의 §10 Phase 3 gate
admin.html 3-페이지 분할은 별 트랙으로 운영자 결정).
