diff --git a/.claude/STATUS.md b/.claude/STATUS.md index fa51b36..50388aa 100644 --- a/.claude/STATUS.md +++ b/.claude/STATUS.md @@ -1,6 +1,6 @@ # STATUS — hal -Last updated: 2026-07-24 +Last updated: 2026-07-28 ## Current Focus @@ -16,6 +16,7 @@ Last updated: 2026-07-24 - [ ] **Ops track — 11 runs Archon, 1 brief par repo** — runbook maître `docs/features/ops-runbook.md` (séquencement, commandes de lancement, étapes manuelles). Phase 1 purge+CI : `ops-1-purge-ci.md` dans hal, edifice, bluegreen-marketplace, renaud-marketplace, auth-gateway. Phase 2 : hal `ops-2-deploy-make.md`, bgm `ops-2-release-script.md`, rm `ops-2-release-improve-map.md` + `ops-2-briefing-headless.md`, ag `ops-2-deploy-script.md`. Phase 3 : `ops-3-night-shift.md` (copié dans bluegreen-ops au bootstrap). Les 3 fichiers `ops-phase-*.md` sont des stubs "superseded" à supprimer au commit. ## Done (current sprint) +- [x] **#82 — Edifice tools artifact-callable (branche `archon/task-feat-artifact-callable-edifice-tools`) — 2026-07-28** — 2 nouveaux tools `hal-mcp` : `get_mission_context(mission_id)` renvoie le `context.json` complet **inline** (header + `observations[]` + `notes[]` + `photos[]` metadata, **zéro URL signée**) — shape portée field-for-field depuis `build_context.py` de bluegreen-marketplace ; `get_mission_photo(photo_id, max_width?)` renvoie une photo redimensionnée en base64 JPEG (magick-wasm `@0.0.41`, wasm fetché du CDN au cold start, cible ~300 Ko, image content block). 12 read tools reçoivent `annotations: { readOnlyHint: true }`, `push_mission_context` explicitement `readOnlyHint: false` — débloque le chargement d'un artifact Claude sans cascade de dialogs Allow/Deny (`anthropics/claude-code#57398`, closed not-planned). Fetch de `get_mission_with_assets` extrait dans `fetchMissionRaw()` **sans changement de contrat**. Aucun changement de schéma `edifice_*`. **Offline vert** : `deno check` + suite Deno (68 tests, dont 5 nouveaux : shape inline sans URL, tools/list readOnlyHint, no-clobber single-field, 2 error-paths photo) + `make test` (157 pytest). ⚠️ **Happy-path resize + 3 critères d'acceptation = à vérifier LIVE post-`make deploy`** contre la mission de référence `3f2bd270-fd5f-4d09-a64e-063a66348dc8` (le resize nécessite le wasm de 14,6 Mo, hors suite offline). Débloque **bluegreen-marketplace#50** Phases 2-3 ; bump `plugins/hal/.mcp.json` = follow-up downstream après deploy. Voir cross-repo-log 2026-07-28. - [x] **#65 — CI migration smoke-test — PR #72 mergée, `main` vert — 2026-07-24** — job `migration-smoke` : charge `supabase/schema.snapshot.sql` (dump réel de prod, 218 Ko, schémas `auth`+`public`+`private`) dans un conteneur éphémère, puis applique les migrations que la branche ajoute. Lancé via Archon `archon-fix-github-issue`. **Le job produit par l'agent ne pouvait pas fonctionner** — 6 causes empilées, aucune visible en relecture, toutes trouvées en exécutant le job en local contre un vrai dump : `postgres:17` n'a ni les rôles cluster Supabase (`role "supabase_admin" does not exist`, ligne 18) ni ses extensions (`type "public.geometry"`, ligne 227) ; se connecter en `postgres` donne `permission denied for schema auth` (ligne 35) ; le schéma `auth` plus ancien de l'image fait que le `CREATE TABLE IF NOT EXISTS` du dump saute `auth.users` (`column "is_sso_user"`, ligne 1866) ; `--schema auth,public` oublie le schéma `private` de prod (ligne 4852). **La 6e est une faute de conception** : « appliquer la migration la plus récente » est impossible — le snapshot *étant* un dump de prod, il la contient déjà, donc `relation ... already exists` à chaque run, indéfiniment. Corrigé en appliquant ce que la branche **ajoute** (`git diff origin/...HEAD`, d'où `fetch-depth: 0`). Image = `public.ecr.aws/supabase/postgres:17.4.1.052`, version **exacte** de prod (`select version()`), la même que celle qu'utilise `supabase db dump` ; postgis/vector/pg_net y résolvent aux versions exactes de prod. **Test négatif exécuté** : un trigger réintroduisant la forme d'avant-fix (`AFTER INSERT ... WHEN (OLD.company_id IS DISTINCT FROM NEW.company_id)`) échoue bien avec `INSERT trigger's WHEN condition cannot reference OLD values` — **l'erreur exacte qui a atteint la prod via PR #60 est attrapée**. 4/4 critères d'acceptation. ⚠️ Le snapshot n'a pu être commité qu'après un détour : un dump de `public` embarquait une clé `service_role` en dur, inlinée dans `edifice_trigger_map_generation()` d'edifice depuis le 2026-05-29 — corrigé côté edifice (Vault puis secret dédié, clés compromises rotées) avant commit. **C'est le smoke-test qui a fait remonter la fuite.** - [x] **PR #73 — `deno check` réparé sur le codec PNG — 2026-07-24** — `main` était rouge depuis `48f89fd` : la v10 déployée d'`edifice-map-generator`, commitée en `444fa3d`, ne passait pas le type-check (2 × `TS2345`). **Toutes les PR ouvertes héritaient de l'échec**, une PR testant son merge avec `main`. Deux causes de typage : (1) `CompressionStream`/`DecompressionStream` déclarent `writable: WritableStream`, plus large qu'`Uint8Array` — le helper demandait plus étroit que ce que ces classes fournissent ; (2) depuis **TypeScript 5.7** les tableaux typés sont génériques sur leur buffer, `Uint8Array` nu = `Uint8Array` (admet `SharedArrayBuffer`) alors que `BufferSource` exige `ArrayBufferView`. Corrigé en typant le chemin du codec `Uint8Array` **plutôt qu'avec un cast** — un `as BufferSource` aurait fait taire le compilateur sans énoncer la contrainte. Diff **types uniquement** : 3 signatures, aucune ligne exécutable, fonction déployée inchangée, aucun redéploiement impliqué. Vérifié avec la toolchain de la CI (image `denoland/deno`). - [x] **Décision — guard `::uuid` non propagé, #67 fermée — 2026-07-23** — après merge de #62 (PR #70), remontée de tous les chemins d'écriture de `raw_app_meta_data.company_id` : `auth-gateway` `invite/form.tsx:101` et `users/[id]/edit/page.tsx:76` sont des `