docs(process): handoff — F0+F1 EJECUTADAS; turnkey F2 (lote mecánico) + doctrina AUX-1

- continue-cleanroom: bloque de ARRANQUE para la próxima sesión (F2 en 6
  pasos ordenados, barato→delicado, no-cascada) + registro de ejecución de
  F1 (EID-1 anillo fundación→outline con :where() — el reset global que lo
  justificaba NO existía y el anillo viejo pintaba en paralelo con los de
  receta; EID-2 opacidades→tokens; F1.3 3 guards de fundación; SEM-1
  prioridad=intent pinneada con liveRegionFixtureMorfo) + cola lateral
  nueva: accordion outline:none+box-shadow = cero anillo en HCM (a F2).
- sema.md §Announce: doctrina AUX-1 "who owns what" — 1 sink
  (uix.announce), 2 emisores (runtime a11y + AnnounceChannel), <Announce>
  = región de app; UNA política de prioridad (SEM-1) pinneada en ambos lados.

Gates al cierre: matriz 135/0/0 · contracts 38/38 · eidos 309/309 ·
sema 178 · baseline 57.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
menubar-v4-safe
dev 3 months ago
parent 4addfd7dbf
commit 29e621b17c

@ -649,6 +649,28 @@ announcer (`{ announce }`, e.g. `ActiveUix.announce`, one shared region) or a
self-owned pair of live regions built from the injected `dom`. Fire-and-forget,
never rejects. Supersedes `book-deviations.md` D.8's deferral.
**Live-region doctrine — who owns what (AUX-1 / SEM-1, 2026-07-11).** The
framework has ONE sink, two emitters, and an app-level component:
- `uix.announce` (ActiveUix) owns the SHARED pair of live regions — the
low-level sink (its zwsp-toggle re-announce is an implementation detail of
that sink, not a third policy).
- The two framework **emitters** both prefer delegating to it: the soma
runtime's a11y commitments (`a11ySemantic.requiresLiveRegion` →
`sources.announce`) and this channel (inject `{ announce: uix.announce }`;
its self-owned clear-then-set regions are ONLY the no-uix fallback).
- The soma `<Announce>` component is different in kind: an app-authored,
declarative region for app-level messages — not a vehicle for framework
event announcements.
Priority is ONE policy everywhere (SEM-1 — the runtime used to add a
`family === 'signal'` conjunct, making a threat-tinted commit announce
polite on one path and assertive on the other): the evaluative INTENT alone
— `threat` / `loss` → `assertive`, else `polite` — implemented identically
in `priorityForIntent` (`chans/announce.ts`) and the runtime's a11y step
(`runtime.svelte.ts`), pinned by tests on both sides
(`announce.test.ts` · `runtime.svelte.test.ts` SEM-1).
### Per-channel reductions — `engine.preferences`
`BK-REDUCTIONS` (ch. 32 §12 / ch. 33 §7): a symmetric reduction story per

@ -20,6 +20,35 @@
- Badge R-4.3 (única violación R-4.x viva en su §5.3) ✅ cerrada en el censo
R-1.x (`ee9786bc`). Su matriz (102/32/0) es previa: hoy **134/0/0**.
## ⏭️ ARRANQUE PRÓXIMA SESIÓN → F2 (lote mecánico)
Estado al cierre 2026-07-11: **F0 ✅ + F1 ✅** (commiteadas — `4addfd7d` +
el handoff posterior). Gates vigentes que deben MANTENERSE: matriz
**135/0/0** · contracts **38/38** · eidos **309/309** · sema 178 · baseline
**57** · vocab exit 0. Leer los bloques «EJECUTADA» de F0/F1 (abajo) para
el contexto y arrancar F2 directo — es el lote SIN decisiones de usuario.
Orden sugerido (barato → delicado, no-cascada: ítem → gates → siguiente):
1. **DEP-2** ogl fuera de package.json (+lockfile) · **DEP-1** clsx
inlineado (cerrar el "pending" de soma.md §12).
2. One-liners: **THM-7** (ejemplo sema.md → semaSelector) · **THM-6**
(menu-dial `--radius-full, 1px` → 9999px) · **EID-4** ("31-scale" → 33 ×2).
3. **MOR-1** escape/validación en semaSelector (isomorfo, sin CSS.escape
del DOM) + tests con `"` y `]` · **MOR-2** des-duplicar convención de
marker · **MOR-3** `_resetCompileCache` implementar-o-borrar.
4. **SOM-2** keydown `continue` en match sin handler + test · **SOM-1**
censo de handlers async → si 0, quitar el await (si hay, DECISIÓN #3).
5. **SEM-2** logging por defecto (dev) en canales sin logger + vía
`void trigger` sin unhandled rejection (throw intacto para awaiters) ·
**SEM-3** fallback muerto applyDominance + cancelar timer de
awaitExpression · **SEC-1** serializador renderCssVariables rechaza
`;`/`}` embebidos + test.
6. **accordion → outline** (hallazgo F1: `outline:none` + box-shadow = cero
anillo en HCM) — con verificación visual, patrón tabs.css:102.
Después de F2 → F3 (censos SOM-3◐/SOM-4/THM-5/THM-4). Las iniciativas F4
(THM-2 paleta · SEM-4 firma dormida · DOC-1/2 · GAP-\*) esperan decisión.
## Principios de secuencia
1. **La máquina primero.** Los fixes que amplían el enforcement (THM-1,
@ -76,7 +105,38 @@
**Salida de F0**: matriz 135/0/0 · contracts 38/38 · suite eidos 306/306.
## F1 — Coherencia P1: foco y voz (≈1 sesión)
## F1 — Coherencia P1: foco y voz ✅ EJECUTADA 2026-07-11
> Resultado: matriz **135/0/0** · contracts 38/38 · eidos **309/309** (+3
> guards de fundación) · sema 178/178 · soma 1041 verde (2 rojos ajenos:
> chronos = pista rota pre-existente · attr-audit = timeout de contención,
> PASA aislado) · baseline 57. Hallazgos de la ejecución:
>
> - **EID-1**: el `outline: none !important` global que justificaba el
> box-shadow **no existe** — la única mención en TODO el árbol era el
> propio comentario de archetypes.css (fósil de la era Tailwind). Y el
> anillo de fundación pintaba EN PARALELO con los de receta (propiedades
> distintas, mismos tokens → duplicación invisible, verificado en vivo).
> Migrado a outline + `--focus-ring-*` envuelto en `:where()` (la
> fundación pierde ante cualquier receta al compartir ya la propiedad);
> `--focus-ring-bg` era hook muerto (0 consumidores) — retirado.
> Verificación en vivo: Close de dialog = UN anillo (el de Button, box-shadow
> none) · sonda desnuda `data-archetype` = anillo de fundación · light+dark.
> Asientos en reference §32 + changelog §32; bloque forced-colors queda
> como suelo defensivo.
> - **EID-2**: disabled `0.5` → `var(--opacity-disabled)` (=0.4 — las
> recetas YA usaban el token: disabled se veía distinto según la capa) ×3
> + close hover `0.85` → `var(--opacity-hover)` (=0.9, token por rol).
> Verificado en vivo (0.4 computado).
> - **F1.3**: 3 guards nuevos en recipe-css-contract ("Foundation CSS
> discipline": color/typo/opacity sobre `eidos/*.css` + `lib/*.css`,
> enumeración dinámica) + fallback fantasma `#fff` pagado en
> menu-indicator. picker-shell/spin-field ya entraban por dir.
> - **SEM-1**: runtime alineado al canal — prioridad = INTENT solo
> (threat/loss → assertive); pinneado con `liveRegionFixtureMorfo`
> (commit+threat = el caso divergente) en runtime.svelte.test. **AUX-1**:
> doctrina "who owns what" en sema.md §Announce (1 sink `uix.announce` ·
> 2 emisores · `<Announce>` app-level).
| Ítem | Qué | Tamaño |
| --- | --- | --- |
@ -251,6 +311,12 @@ Deuda "sin urgencia" desde 2026-05/06 — ponerle fecha (**DECISIÓN #5**):
## Cola lateral (no bloqueante, registrada)
- **accordion: anillo box-shadow + `outline: none` (§32 stray)** — el censo
S5 no lo vio (accordion.css:165 `outline: none` + anillo box-shadow con
tokens propios). Consecuencia real: en forced-colors/HCM su
`outline: none` (0,2,0) gana al suelo defensivo generado (0,1,0) → **cero
anillo en HCM**. Migrar a outline en el lote F2 (mecánico, con
verificación visual).
- **Cascada de entrada vs firmas de evento (sistémico, shipped)**: las
reglas generadas `[data-stagger][data-state='open'] >
[data-animation-style='…']` (0,3,0) siguen reclamando `animation` tras

Loading…
Cancel
Save

Powered by TurnKey Linux.