From 415cde5f5651d4d8385dda12f8bd16023676dfa9 Mon Sep 17 00:00:00 2001 From: Bastien Chanot Date: Fri, 3 Jul 2026 15:29:20 +0200 Subject: [PATCH] chore(memory): BDR-047 corrob (Opus 4.8 re-audit) + LRN-090 + journal 2026-07-03 Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_01XpphkdTosUzokBDNG7PToS --- .claude/memory/decisions.md | 12 ++++++++++++ .claude/memory/journal.md | 4 ++++ .claude/memory/learnings.md | 6 ++++++ .claude/tasks/TODO.md | 18 ++++++++++++++++++ 4 files changed, 40 insertions(+) diff --git a/.claude/memory/decisions.md b/.claude/memory/decisions.md index f6f149c..6e1cfae 100644 --- a/.claude/memory/decisions.md +++ b/.claude/memory/decisions.md @@ -776,3 +776,15 @@ rules: - **Reference**: read-only clone (scratchpad), 4 parallel analyzer agents + eval-harness spike, this session. No branch on ECC, no import. See [[BDR-045]] (chore/ aiguillage), [[BDR-009]] (caveman registries). +- **Corroboration 2026-07-03** (Opus 4.8 re-audit; repo UNCHANGED — HEAD 81af407 + 2026-06-29, 2232 commits identical, zero commits since 01/07): 6 parallel analyzer + agents re-verified every BDR-047 fact w/ fresh file:line. rules/ inert (paths: 0 + consumers, rules/README.md:333 "cannot distribute rules automatically"); contexts/ + overwrite (the-longform-guide.md:68-74 `--system-prompt`); eval-harness no runner + (/eval absent; gan-harness.sh + skill-improvement/evaluate.js exist but hors-scope, + deliver NEITHER pass@k nor model-upgrade battery); memory auto-capture conflicts + approve-first (continuous-learning-v2 observer-loop.sh:160-164 "Do NOT ask for + permission"); distribution = product scaffolding, N/A. ZERO factual divergence. + ONE scope gap: BDR-047 never opened hooks/ — ECC's only WIRED subsystem. Fruit: + config-protection hook (own idiom, NOT ECC import), shipped + feature/config-protection-hook. Lesson holds + refined by [[LRN-090]]. diff --git a/.claude/memory/journal.md b/.claude/memory/journal.md index 895c878..fdfb1e9 100644 --- a/.claude/memory/journal.md +++ b/.claude/memory/journal.md @@ -308,3 +308,7 @@ rules: - Same branch, 3 doctor false-warns fixed ([[LRN-047]] corrob — a doctor that cries false is ignored): cargo "(RTK unavailable)" → optional info (RTK prebuilt, detect_rtk); check_symlink passes children of dir-level symlinks (hooks/session-start.sh); gstack counts 34 per-skill symlinks not a mythical skills/gstack link (link.sh removes it); token budget vs 200k context window not bogus 11k "session budget" → killed false "92% CRITICAL" (measured ~11.4k [[LRN-088]]; 200k confirmed by user — 1M pin revoked at audit #7, calibrate on default not the exceptional session). - Suites green: gitflow 71/71 (+7), deterministic 13, doc-commit 32, doc-shape 19, reconcile 20, deploy-commit 13, release-candidate 5/5 tag-mode. doctor: 0 false-warn (1 legit survivor = gstack tracks branch=main advisory). shellcheck clean. T12 named to dodge collision with reconcile's own T6c (darwin path, audit #3). - 3 atomic commits (fix gitflow / fix doctor / docs changelog Unreleased) + memory. finish bugfix→develop on GO; user pushes develop. +- ECC 2nd-look (Opus 4.8, 6 agents, repo unchanged since 01/07): all [[BDR-047]] facts corroborated w/ file:line, zero divergence. Scope gap = hooks/ (only wired subsystem) unaudited 01/07 → [[LRN-090]] wired > declarative. +- Shipped config-protection hook (feature/config-protection-hook): PreToolUse blocks Edit/Write to quality-gate files (settings/gitflow/.githooks/doctor/hooks-self/lib-tests/lint). One-shot sentinel .claude/.config-edit-ok (non-empty reason, logged+consumed) — NOT env-var (launch-time = set-and-forget = garde mort). Own idiom, not ECC import. shellcheck clean, test 20/20. +- Live dogfood: hook went active mid-session via symlinked settings (link.sh); v1 (no self-guard) let its OWN edit through → v2 added hooks/*.sh + lib/tests/* self-guard, then blocked the test-file edit; recovered via sentinel. User's self-guard requirement vindicated. +- Next: #2 design-toolchain trigger fix (residual false-fires post-ed2408e, 5× this session). diff --git a/.claude/memory/learnings.md b/.claude/memory/learnings.md index 16e7585..7b8953f 100644 --- a/.claude/memory/learnings.md +++ b/.claude/memory/learnings.md @@ -965,3 +965,9 @@ rules: - **context**: audit 2026-07-02, `lib/gitflow.sh:257` `finish) gitflow_finish "$@"` passed args the function never consulted. Surfaced when a finish "for" one branch merged another (LOT3). [[BLK-015]]. - **future application**: any wrapper/dispatcher forwarding args to a callee that resolves its target from ambient state — either (a) make the callee USE the args as the target, or (b) if the ambient-state contract is deliberate, treat passed args as an ASSERTION and refuse loudly when they disagree with the state. Never let forwarded args be silently dropped: silent-drop = the caller believes they steered, the callee ignored them. Sibling of "presence-flag ≠ capability" [[LRN-087]] — both = a visible signal lying about the real behavior. - **Reference**: `lib/gitflow.sh` gitflow_finish arg-guard, `lib/gitflow-test.sh` T12. [[BLK-015]]. + +## LRN-090 — external-repo audit: open WIRED subsystems before declarative +- **pattern**: auditing external config/framework repo for transferable value → rank subsystems WIRED (executable: hooks/, runners, dispatchers) vs DECLARATIVE (docs, rules/, aspirational frontmatter). Wired > declarative: declarative often inert (ECC rules/ `paths:` = 0 consumers; eval-harness = SKILL.md, no runner — "belle méthodo / vaporware"); wired = a real mechanism worth adapting. +- **context**: ECC 2nd-look 2026-07-03 (Opus 4.8, 6 agents, repo unchanged since 01/07). [[BDR-047]] audit (01/07) inventoried the declarative surface + concluded zero import — right on facts, but hooks/ (ECC's only live subsystem) was OUT of scope and held the sole real adaptation → config-protection PreToolUse guard. +- **future application**: next external-repo value audit → enumerate hooks/, scripts/, runners FIRST; treat rules/docs/SKILL.md as claims to verify ("is it wired?"), not value. Described capability ≠ wired capability. +- **cousin**: [[LRN-087]] presence-flag ≠ capability; [[LRN-089]] forwarded-args silently dropped — same family: a visible signal (a file, a flag, a `paths:`) lying about real behavior. diff --git a/.claude/tasks/TODO.md b/.claude/tasks/TODO.md index 867f37d..81c6fab 100644 --- a/.claude/tasks/TODO.md +++ b/.claude/tasks/TODO.md @@ -1,5 +1,23 @@ # TODO +## 2026-07-03 — config-protection hook (feature/config-protection-hook) +Goal: PreToolUse hook blocks Edit/Write to this config's quality-gate files +(guardrails an agent must not weaken to make an error pass). Adaptation from ECC +second-look (BDR-047 corrob, Opus 4.8 re-audit) — MY idiom (~15-line bash), NOT +ECC's Node dispatcher. Extends config's own doctrine ("backstops déterministes +car l'advisory s'oublie"). Guarded: settings.json (+ .claude/settings*.json), +lib/gitflow.sh, .githooks/*, doctor.sh, lint configs (preemptive, absent today). +Bypass: CONFIG_EDIT_OK="reason" (logged). Mid-session env caveat flagged at gate. + +- [x] hooks/config-protection.sh — case-match guarded path, exit 2 else 0; fail-open +- [x] Guarded: settings.json(+.claude/settings*), lib/gitflow.sh, .githooks/*, doctor.sh, hooks/*.sh (self-guard), lib/tests/* (T6c/LRN-077), lint (preemptive) +- [x] Bypass: one-shot sentinel .claude/.config-edit-ok (non-empty reason, logged+consumed) — NOT env-var (launch-time env = set-and-forget = garde mort) +- [x] lib/tests/config-protection.test.sh — block/allow/self-guard/near-miss/fail-open/sentinel-one-shot/empty-refuse (17 checks) +- [x] settings.json — register PreToolUse matcher Edit|Write|MultiEdit -> hook +- [x] Verify — shellcheck clean + 17/17 PASS + bash -n + bootstrap-safe (hook fires on Edit/Write only, not shell cp/ln) +- [x] GATE passed — guarded list +2 (hooks/, tests/), sentinel over env-var +- [ ] Capitalize (BDR-047 corrob + LRN-090 câblé>déclaratif) + finish this branch only + ## 2026-06-23 — install self-sufficient + gstack on-demand par profil Goal: `make install`/`make plugin`/`make update` installent TOUT sans étape manuelle. Plus le profil-driven gstack on-demand (option 1 user : gstack OFF