jorgex-stack 1.9.71 → 1.9.73

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -35,11 +35,8 @@ The skill never edits artifacts or creates tasks. During audit remediation, the
35
35
  Install and run via npm without cloning the repository:
36
36
 
37
37
  ```bash
38
- # First installation
38
+ # Install (also reapplies mode, models, permissions and browser guidance to the configured runtimes).
39
39
  pnpm dlx jorgex-stack install
40
-
41
- # Already installed: apply the latest published stack while keeping the existing model selection
42
- pnpm dlx jorgex-stack sync
43
40
  ```
44
41
 
45
42
  For a fresh Engram installation, always consult the current published Stack and bypass only the `pnpm dlx` cache:
@@ -70,7 +67,7 @@ Runtime defaults are documented in [docs/references/permissions.md](docs/referen
70
67
 
71
68
  ### Modes: Human and Programmatic
72
69
 
73
- `install` and `sync` accept two mutually-exclusive installation modes. The choice is global (not per runtime) and is saved in `~/.jorgex-stack/install-mode.json` on first run; subsequent `sync` calls reuse it. Re-run `install` with `--mode` to switch.
70
+ `install` accepts two mutually-exclusive installation modes. The choice is global (not per runtime) and is saved in `~/.jorgex-stack/install-mode.json` on first run; subsequent `install` calls reuse it. Re-run `install` with `--mode` to switch.
74
71
 
75
72
  | Mode | Audience | Final assistant response | Subagents |
76
73
  |------|----------|--------------------------|-----------|
@@ -98,7 +95,7 @@ Flags:
98
95
 
99
96
  - `--mode human` cannot be combined with `--subagent-concurrency`.
100
97
  - Without `--mode`, the first run asks interactively; `--yes`, non-TTY, and `--target-dir` default to `human`.
101
- - `pnpm dlx jorgex-stack sync` reuses the saved mode; pass `--mode` to change and save the preference.
98
+ - `pnpm dlx jorgex-stack install` reuses the saved mode; pass `--mode` to change and save the preference.
102
99
 
103
100
  Programmatic mode guarantees:
104
101
 
@@ -118,7 +115,7 @@ El canon de Stack y el paquete Pi mantienen una snapshot de 17 árboles de skill
118
115
 
119
116
  Pi combines the **snapshot v2** package with a Stack-owned shared projection. Package resolution, verification, receipt and recovery behavior are documented in [docs/references/pi-runtime.md](docs/references/pi-runtime.md); historical pins are not a promise that personal Pi installations have migrated.
120
117
 
121
- En Pi nuevo, Stack gestiona `jorgex-pi` y sus seis companions locales, y prepara el provider oficial `gentle-engram` en un stage aislado. Cuando el candidato Pi verificado declara el contrato nativo `mcp-native-v1`, `install` o `update` deliberado ejecuta la fase nativa (`runNativePiMcpPhase`) antes de la promoción del paquete: `mcp.json` pasa a ser la autoridad persistente de los servidores protegidos (`engram`, `context7`, `chrome-devtools`), no se instala `pi-mcp-adapter` y la autoridad granular vive en `pi-projection-receipt.json`. La fase nativa solo **prepara** (`NativeMcpPreparedWrite` con `created`/`removals`/`snapshot`/`backupRoot`); el handoff activo y `mcp.json` los escribe el ciclo de proyección (`runPiProjectionLifecycleSystem`), que aplica el handoff DevTools v3 contra la estampa `receipt.devtools.sha256` y, después del readback, invoca una sola vez `pendingNativeConfigWrite` (CAS de remociones y crements con `restoreOwnedWrite`); sólo entonces publica el receipt y la autoridad final. Cada `install` o `update` deliberado resuelve el `latest` publicado, verifica lock/SRI/árbol y promociona solo el provider gentle en modo nativo (o los dos providers en modo legacy); conserva el enlace y receipt privados de `jorgex-pi`, el host Pi, las entradas npm ajenas y los datos de Engram. Con un receipt Stack válido, `install --agents pi` continúa por la actualización autenticada; el estado manual o ambiguo se bloquea. El [inventario de Pi](docs/references/pi-runtime.md#inventario-operativo-de-pi) distingue componentes obligatorios y opcionales, y la sección de [transporte nativo y autoridad granular](docs/references/pi-runtime.md#transporte-nativo-y-autoridad-granular) describe el contrato nativo verificable (no se infiere por versión del host ni por `testedVersions`); el opt-out explícito de DevTools retira el claim de la autoridad y, cuando la entrada sigue full-stamped, el `mcp.json` la elimina; cuando está personalizada la conserva y queda UNOWNED (no se reclama de vuelta por SHA idéntico y exige resolución manual).
118
+ En Pi nuevo, Stack gestiona `jorgex-pi` y sus seis companions locales, y prepara el provider oficial `gentle-engram` en un stage aislado. Cuando el candidato Pi verificado declara el contrato nativo `mcp-native-v1`, `install` o `update` deliberado ejecuta la fase nativa (`runNativePiMcpPhase`) antes de la promoción del paquete: `mcp.json` pasa a ser la autoridad persistente de los servidores protegidos (`engram`, `context7`, `chrome-devtools`), no se instala `pi-mcp-adapter` y la autoridad granular vive en `pi-projection-receipt.json`. La fase nativa solo **prepara** (`NativeMcpPreparedWrite` con `created`/`removals`/`snapshot`/`backupRoot`); el handoff activo y `mcp.json` los escribe el ciclo de proyección (`runPiProjectionLifecycleSystem`), que aplica el handoff DevTools v3 contra la estampa `receipt.devtools.sha256` y, después del readback, invoca una sola vez `pendingNativeConfigWrite` (CAS de remociones y creaciones con `restoreOwnedWrite`); sólo entonces publica el receipt y la autoridad final. Cada `install` o `update` deliberado resuelve el `latest` publicado, verifica lock/SRI/árbol y promociona solo el provider gentle en modo nativo (o los dos providers en modo legacy); conserva el enlace y receipt privados de `jorgex-pi`, el host Pi, las entradas npm ajenas y los datos de Engram. Con un receipt Stack válido, `install --agents pi` continúa por la actualización autenticada; el estado manual o ambiguo se bloquea. El [inventario de Pi](docs/references/pi-runtime.md#inventario-operativo-de-pi) distingue componentes obligatorios y opcionales, y la sección de [transporte nativo y autoridad granular](docs/references/pi-runtime.md#transporte-nativo-y-autoridad-granular) describe el contrato nativo verificable (no se infiere por versión del host ni por `testedVersions`); el opt-out explícito de DevTools retira el claim de la autoridad y, cuando la entrada sigue full-stamped, el `mcp.json` la elimina; cuando está personalizada la conserva y queda UNOWNED (no se reclama de vuelta por SHA idéntico y exige resolución manual).
122
119
 
123
120
  The following command block is retained as historical reference for that transition:
124
121
 
@@ -130,7 +127,7 @@ pnpm dlx jorgex-stack@1.9.7 sync --agents pi
130
127
  pnpm dlx jorgex-stack@1.9.7 uninstall --agents pi
131
128
  ```
132
129
 
133
- For a deliberate managed install or update, Stack resolves the live published `latest` tag to an exact release, verifies its canonical tarball URL and SRI/bytes, and prepares it in an isolated stage before activation. The stage locks six direct dependencies, copies them byte-identically into the package-local runtime tree, and records those copies only in the tree inventory; the lock remains the verified lock, and the release id uses both lock and tree digests; it then runs the RPC smoke before and after promotion. Stack then backs up state and publishes only its owned package entry. Automatic restoration covers activation/verification failures; if projection or MCP configuration fails after the package is activated and verified, Stack blocks with the backup retained rather than claiming a full rollback. The schema 1 receipt records managed-package evidence for offline verification. `sync`, `models`, `doctor` and `uninstall` do not acquire a new version; they require an authenticated receipt/artifact, with explicit legacy recovery paths where applicable. `update --check` does not download. `--target-dir` neither downloads Pi nor touches the real HOME; with a previously verified candidate/stage injected, it can run isolated smoke/runner code inside the target. Direct Pi installation is separate and does not provide Stack's rollback guarantees. Do not use Pi's native `pi update --extensions` as a Stack repair path: it does not provide the managed receipt or Stack's activation/recovery guarantees. A Pi release is adopted only after its reader declaration, tarball and integrity pass the verified stage; no future version is pinned manually.
130
+ For a deliberate managed install or update, Stack resolves the live published `latest` tag to an exact release, verifies its canonical tarball URL and SRI/bytes, and prepares it in an isolated stage before activation. The stage locks six direct dependencies, copies them byte-identically into the package-local runtime tree, and records those copies only in the tree inventory; the lock remains the verified lock, and the release id uses both lock and tree digests; it then runs the RPC smoke before and after promotion. Stack then backs up state and publishes only its owned package entry. Automatic restoration covers activation/verification failures; if projection or MCP configuration fails after the package is activated and verified, Stack blocks with the backup retained rather than claiming a full rollback. The schema 1 receipt records managed-package evidence for offline verification. `models`, `doctor` and `uninstall` do not acquire a new version; they require an authenticated receipt/artifact, with explicit legacy recovery paths where applicable. Deliberate `install`/`update` can resolve and download Pi and its providers; browser acquisition requires explicit opt-in or a persisted preference. `update --check` does not download. `--target-dir` neither downloads Pi nor touches the real HOME; with a previously verified candidate/stage injected, it can run isolated smoke/runner code inside the target. Direct Pi installation is separate and does not provide Stack's rollback guarantees. Do not use Pi's native `pi update --extensions` as a Stack repair path: it does not provide the managed receipt or Stack's activation/recovery guarantees. A Pi release is adopted only after its reader declaration, tarball and integrity pass the verified stage; no future version is pinned manually.
134
131
 
135
132
  The artifact values in `src/lib/pi-runtime-pin.json` describe frozen historical/reference metadata, not the live install candidate; live artifact URL, version and integrity are resolved from the published registry.
136
133
 
@@ -146,37 +143,37 @@ The historical published artifact has two separate provenance anchors. The local
146
143
 
147
144
  The historical `0.8.0` artifact records two distinct commit identities: the release checkout and tarball producer is `9f999747df3e335947a61d38e581555367973b09` (`main`, release `0.8.0`); and the Stack parity source is `11e7666ea4e40bde1de8bc434610747eb797ab9c`. Registry metadata has no `gitHead`; README does not invent a separate source identity, attestation or signature.
148
145
 
149
- Install, sync and uninstall back up every managed file before changing it and are idempotent. `doctor` reports package and projection drift without repairing it. Uninstall removes only receipt-owned package/projection state, retains shared files also owned by another runtime, and preserves user content outside marked sections. Engram remains user-owned and is never removed; the receipts only carry the verified executable hand-off required by the package.
146
+ Install and uninstall back up every managed file before changing it and are idempotent. `doctor` reports package and projection drift without repairing it. Uninstall removes only receipt-owned package/projection state, retains shared files also owned by another runtime, and preserves user content outside marked sections. Engram remains user-owned and is never removed; the receipts only carry the verified executable hand-off required by the package.
150
147
 
151
148
  The package owns Pi's native primary-model projection: `openai-codex/gpt-5.6-sol`, with a local `contextWindow` request of 872K. It merges only missing compatible fields, records field ownership in `PI_CODING_AGENT_DIR/jorgex-pi/sol-lifecycle.v1.json`, and cleanup removes only still-owned canonical values. Stack does not duplicate that package-owned settings/models logic. The 872K value is local OAuth metadata until a real long-context smoke test confirms backend acceptance; it is not the API context limit.
152
149
 
153
- Engram remains mandatory and user-owned. An existing binary is always preserved. When it is missing and the user authorizes installation, Stack resolves GitHub's current official latest stable release at runtime; GitHub's `releases/latest` endpoint excludes prereleases and drafts, and the installer never uses a branch. It matches the exact platform/architecture asset and validates its live metadata —published state, expected name, positive size and SHA-256— before publishing; missing network or metadata fails closed, with no static or offline fallback. Use `--engram` to authorize that download in non-interactive flows. The release installer writes only `~/.local/bin/engram` (or the platform equivalent) and does not use Brew or Go. `sync`, dry-run and `--target-dir` never download it. Update remains explicit and does not replace an existing binary implicitly. The database and memories are never updated or deleted, and uninstall preserves the official Engram artifacts and never removes the Engram binary. Under `--target-dir`, Stack accepts only `<target>/bin/engram`, isolates Pi/Home/XDG/AppData/temp/npm-cache paths inside the target, and never consults the host Engram or Pi configuration. This rolling channel does not mean that every upstream release was pre-reviewed by Stack.
150
+ Engram remains mandatory and user-owned. An existing binary is always preserved. When it is missing and the user authorizes installation, Stack resolves GitHub's current official latest stable release at runtime; GitHub's `releases/latest` endpoint excludes prereleases and drafts, and the installer never uses a branch. It matches the exact platform/architecture asset and validates its live metadata —published state, expected name, positive size and SHA-256— before publishing; missing network or metadata fails closed, with no static or offline fallback. `install` may download Engram with `--engram` or with interactive confirmation; `update` only offers the explicit native channel confirmation and preserves the existing binary. The release installer writes only `~/.local/bin/engram` (or the platform equivalent) and does not use Brew or Go. El `sync` interno, `dry-run` y `--target-dir` no descargan Engram. Update permanece explícito y no sustituye un binario existente implícitamente. The database and memories are never updated or deleted, and uninstall preserves the official Engram artifacts and never removes the Engram binary. Under `--target-dir`, Stack accepts only `<target>/bin/engram`, isolates Pi/Home/XDG/AppData/temp/npm-cache paths inside the target, and never consults the host Engram or Pi configuration. This rolling channel does not mean that every upstream release was pre-reviewed by Stack.
154
151
 
155
152
  Claude's official plugin still requires stable Engram 2.0.0 or newer: an existing binary below that minimum would make its setup write the obsolete `mcp/engram.json`, so the Claude preflight blocks it before setup. Stack never replaces an existing binary automatically; update it explicitly and rerun `install`. The official Claude plugin contributes hooks and its skill; `engram setup claude-code` registers a separate user-scoped MCP, not a bundled MCP. This integration does not claim an authenticated model-tool smoke.
156
153
 
157
154
  ### Integración oficial de Engram
158
155
 
159
- En una instalación real, `install` delega Claude Code, Codex y OpenCode 1.x a `engram setup <runtime>` una vez por runtime durante esa instalación. Para Pi, si declara transporte nativo (`mcp-native-v1`), Stack ejecuta la fase nativa (`runNativePiMcpPhase`) y no invoca `engram setup pi`; en modo legacy Pi sigue ejecutando `engram setup pi` antes de activar el paquete. El comportamiento del provider oficial permanece sin cambios: Stack no proyecta el protocolo Engram ni filtra sus herramientas. No ejecuta ese setup durante `sync`, `dry-run`, `--target-dir`, `doctor` ni `uninstall`. Stack respalda los archivos afectados, verifica los artefactos oficiales y revierte el cambio si falla; para Pi incluye `settings.json`, `mcp.json` y el árbol `npm`. No modifica `~/.engram`, sus memorias ni reemplaza un binario existente. Los artefactos oficiales se conservan al desinstalar. El `stack/plugins/opencode/engram.ts` legado ya no se despliega y queda retirado por esta integración.
156
+ En una instalación real, `install` delega Claude Code, Codex y OpenCode 1.x a `engram setup <runtime>` una vez por runtime durante esa instalación. Para Pi, si declara transporte nativo (`mcp-native-v1`), Stack ejecuta la fase nativa (`runNativePiMcpPhase`) y no invoca `engram setup pi`; en modo legacy Pi sigue ejecutando `engram setup pi` antes de activar el paquete. El comportamiento del provider oficial permanece sin cambios: Stack no proyecta el protocolo Engram ni filtra sus herramientas. No ejecuta ese setup durante `dry-run`, `--target-dir`, `doctor` ni `uninstall`; `install` lo invoca como parte de la reconciliación interna cuando es necesario. Stack respalda los archivos afectados, verifica los artefactos oficiales y revierte el cambio si falla; para Pi incluye `settings.json`, `mcp.json` y el árbol `npm`. No modifica `~/.engram`, sus memorias ni reemplaza un binario existente. Los artefactos oficiales se conservan al desinstalar. El `stack/plugins/opencode/engram.ts` legado ya no se despliega y queda retirado por esta integración.
160
157
 
161
- Para Codex, Engram 2.0 ignora `CODEX_HOME` y escribe siempre en `$HOME/.codex`; por eso el setup oficial real requiere ese destino predeterminado. Si `CODEX_HOME` apunta a otro directorio, `install` falla cerrado en el preflight, antes de escribir la configuración de Codex, y recomienda usar `$HOME/.codex`. `sync`, `dry-run` y `--target-dir` no invocan el setup oficial.
158
+ Para Codex, Engram 2.0 ignora `CODEX_HOME` y escribe siempre en `$HOME/.codex`; por eso el setup oficial real requiere ese destino predeterminado. Si `CODEX_HOME` apunta a otro directorio, `install` falla cerrado en el preflight, antes de escribir la configuración de Codex, y recomienda usar `$HOME/.codex`. `dry-run` y `--target-dir` no invocan el setup oficial.
162
159
 
163
- La política de complementos distingue estrategias `exact` y `provider-managed`. DevTools MCP y Playwright CLI son `provider-managed`: un `install`/`update` deliberado resuelve y verifica el candidato exacto antes de activarlo, y guarda versión/integridad observadas para reconciliar sin consultar al proveedor en `sync`. Las integraciones oficiales de Engram también son `provider-managed`/rolling, incluido Codex `main`, `pi-mcp-adapter` y el setup oficial de Pi sin pin en Stack. OpenCode 2 queda fuera de alcance y no bloquea esta integración.
160
+ La política de complementos distingue estrategias `exact` y `provider-managed`. DevTools MCP y Playwright CLI son `provider-managed`: un `install`/`update` deliberado resuelve y verifica el candidato exacto antes de activarlo, y guarda versión/integridad observadas para que `install`/`update` posteriores refresquen usando la preferencia persistida o el opt-in explícito. Las integraciones oficiales de Engram también son `provider-managed`/rolling, incluido Codex `main`, `pi-mcp-adapter` y el setup oficial de Pi sin pin en Stack. OpenCode 2 queda fuera de alcance y no bloquea esta integración.
164
161
 
165
162
  Los receipts históricos, incluido `jorgex-pi@0.8.24`, son evidencia para recuperación/migración y no candidatos de instalación nuevos. La selección gestionada resuelve el `latest` publicado a una versión exacta y verifica el artefacto antes de activarlo. No edites receipts o hashes ni borres `HOME`, Engram o la proyección de otro runtime para forzar confianza. La migración y rollback están en [docs/references/pi-runtime.md](docs/references/pi-runtime.md).
166
163
 
167
164
  Stack gestiona la selección dinámica y verificación de Pi en `install`/`update`; esto no significa que una instalación personal de Pi se haya migrado. La automatización Stack ↔ Pi es snapshot-only. La instalación directa de Pi no incluye la etapa aislada ni el rollback de Stack.
168
165
 
169
- `update --agents pi` cambia versiones deliberadamente: resuelve y verifica el paquete Pi y los providers oficiales en stages aislados (con candidato nativo solo `gentle-engram`; con candidato legacy también `pi-mcp-adapter`), aplica la promoción acotada y verifica la configuración MCP. No entra en el updater global de Stack, no actualiza el host Pi ni toca los datos de Engram. `sync --agents pi` reaplica la proyección a partir del paquete autenticado y comprueba el estado MCP existente; no resuelve versiones ni descarga providers. `update --check --agents pi` consulta el runner sin mutar Pi; `doctor --agents pi` diagnostica paquete y proyección. Uninstall respalda los settings y retira solo el paquete exacto acreditado por el receipt, verificando su ausencia y conservando companions y estado ajeno. En modo nativo, `uninstall` corre la comprobación activa de ownership contra el módulo Pi realmente instalado antes de desactivar el paquete privado y respeta la autoridad granular `mcpNative` para decidir qué entradas retira. Consulta los límites de recuperación en la [referencia Pi](docs/references/pi-runtime.md).
166
+ `update --agents pi` cambia versiones deliberadamente: resuelve y verifica el paquete Pi y los providers oficiales en stages aislados (con candidato nativo solo `gentle-engram`; con candidato legacy también `pi-mcp-adapter`), aplica la promoción acotada y verifica la configuración MCP. No entra en el updater global de Stack, no actualiza el host Pi ni toca los datos de Engram. `install --agents pi` reaplica la proyección a partir del paquete autenticado y comprueba el estado MCP existente cuando ya hay receipt; en primera instalación verifica el tarball, normaliza el paquete, proyecta recursos y ejecuta el sync interno para inicializar Pi y escribir ambos receipts. `update --check --agents pi` consulta el runner sin mutar Pi; `doctor --agents pi` diagnostica paquete y proyección. Uninstall respalda los settings y retira solo el paquete exacto acreditado por el receipt, verificando su ausencia y conservando companions y estado ajeno. En modo nativo, `uninstall` corre la comprobación activa de ownership contra el módulo Pi realmente instalado antes de desactivar el paquete privado y respeta la autoridad granular `mcpNative` para decidir qué entradas retira. Consulta los límites de recuperación en la [referencia Pi](docs/references/pi-runtime.md).
170
167
 
171
- ### Variante temporal del provider y recibo separado (candidato, devtool)
168
+ ### Compat del provider #1567 (publicada en 1.9.69) y recibo separado
172
169
 
173
- > **Candidato / devtool — todavía no publicado en npm.** Mientras la corrección upstream `#1567` de `gentle-engram` no se publique, `--engram-typebox-compat` extiende la fase nativa del padre (PR203), ya importada como base, bajo la misma política de input/receipt de la flag candidata verificada y sin duplicar authority, config ni cardinality nativos. El caller nativo del padre (`runNativePiMcpPhase` y sus receipts análogos) no se reutiliza aquí como updater; el candidato no lo sustituye. Esta sección no declara Windows, MCP nativo, autorización personal, instalación nativa fresca, publicación ni aplicación personal como verificadas. La variante descrita es un artefacto local derivado —no es un fork ni un release npm— que aplica sólo el diff de `#1567` sobre bytes oficiales verificados, registra su procedencia en un recibo separado y se retira cuando el release oficial corregido se active como `registry`.
170
+ > **Compat del provider #1567 publicada en Stack 1.9.69.** `--engram-typebox-compat` aplica el diff de `#1567` sobre bytes oficiales verificados y registra su procedencia en un recibo separado, sin sustituir la autoridad de la fase nativa. Los gates CI Windows controlados del release están verdes; la instalación personal en Windows no está probada. Cuando el provider oficial ya viene corregido, se usa sin etapa derivada.
174
171
 
175
- `--engram-typebox-compat` es un booleano explícito; cuando no se pasa, la propiedad queda **realmente ausente** (`undefined`) y no se conserva ninguna preferencia ni se añaden campos obligatorios a flags/fixtures. Sólo se acepta en `install` y `update` deliberados cuyo `--agents` incluya `pi` y **sin** combinar con `--dry-run` ni `--target-dir`; `update --check`, `--dry-run` y `--target-dir` (en `install` o `update`), `sync`, `models`, `doctor`, `uninstall` e `install` sin `pi` rechazan el flag antes de cualquier efecto. `--dry-run` y `--target-dir` siguen sin adquirir providers ni escribir estado personal. Stack registra la procedencia de `gentle-engram` y `pi-mcp-adapter` en `<home>/.jorgex-stack/pi-provider-receipt.json` (schemaVersion 1), un archivo distinto del `pi-receipt.json` del paquete JorgeX Pi y de la autoridad MCP. El campo `provenance` es **opcional** ligado a la adquisición `#1567`-compat: cuando el oficial ya viene corregido el builder devuelve `provenance.origin = "registry"`; mientras no, devuelve `provenance.origin = "derived"`; en ambos casos se descarta el `path` de stage y se conserva el payload original del manifiesto como `manifestBase64` (texto base64 que decodifica al manifiesto bounded —el límite aplica al payload decodificado, no al string literal) junto con su digest y la referencia del patch para verificación offline. Es procedencia local reproducible, no attestation independiente del publisher. `doctor` lee este recibo y diferencia `registry` vs `derived`; no consulta la red, no repara y nunca presenta un error como setup sano. Una `update` deliberada sobre derivado existente conserva la receta sin volver a requerir el flag, sólo si el recibo verificado lo permite; no se autosiembran preferencias y ningún otro comando propaga el opt-in. Las garantías de transacción (backup, idempotencia, rollback, detección de modificaciones ajenas con reporte de `recovery incomplete`), la retirada tras activación verificada del oficial corregido y la advertencia de que operaciones fuera de la transacción gestionada de Stack (comandos manuales, removedores externos, updater nativo de Pi en modo manual) pueden sustituir o degradar los bytes del provider —y que el verificador detecta ese drift sin ser una ACL— se describen en [la referencia Pi](docs/references/pi-runtime.md#variante-temporal-del-provider-y-recibo-separado-candidato-devtool). El updater de providers de **Stack** (función) opera sólo sobre el **transporte legacy**; el transporte nativo lo maneja la **fase nativa del padre** (PR203, `runNativePiMcpPhase`) con la misma política de opt-in y snapshot, sin duplicar la autoridad nativa. Un recibo nativo aún no publicado no debe presentarse como instalación nativa sana; este candidato no declara Windows, cohorte público, publicación npm ni aplicación personal como verificados. La autoridad MCP nativo, el set nativo y la cardinalidad de la cohorte pública pertenecen a PR203; este contrato no los duplica ni los anticipa.
172
+ `--engram-typebox-compat` es un booleano explícito; cuando no se pasa, la propiedad queda **realmente ausente** (`undefined`) y no se conserva ninguna preferencia ni se añaden campos obligatorios a flags/fixtures. Sólo se acepta en `install` y `update` deliberados cuyo `--agents` incluya `pi` y **sin** combinar con `--dry-run` ni `--target-dir`; `update --check`, `--dry-run` y `--target-dir` (en `install` o `update`), `models`, `doctor`, `uninstall` e `install` sin `pi` rechazan el flag antes de cualquier efecto. `--dry-run` y `--target-dir` siguen sin adquirir providers ni escribir estado personal. Stack registra la procedencia de `gentle-engram` y `pi-mcp-adapter` en `<home>/.jorgex-stack/pi-provider-receipt.json` (schemaVersion 1), un archivo distinto del `pi-receipt.json` del paquete JorgeX Pi y de la autoridad MCP. El campo `provenance` es **opcional** ligado a la adquisición `#1567`-compat: cuando el oficial ya viene corregido el builder devuelve `provenance.origin = "registry"`; mientras no, devuelve `provenance.origin = "derived"`; en ambos casos se descarta el `path` de stage y se conserva el payload original del manifiesto como `manifestBase64` (texto base64 que decodifica al manifiesto bounded —el límite aplica al payload decodificado, no al string literal) junto con su digest y la referencia del patch para verificación offline. Es procedencia local reproducible, no attestation independiente del publisher. `doctor` lee este recibo y diferencia `registry` vs `derived`; no consulta la red, no repara y nunca presenta un error como setup sano. Una `update` deliberada sobre derivado existente conserva la receta sin volver a requerir el flag, sólo si el recibo verificado lo permite; no se autosiembran preferencias y ningún otro comando propaga el opt-in. Las garantías de transacción (backup, idempotencia, rollback, detección de modificaciones ajenas con reporte de `recovery incomplete`), la retirada tras activación verificada del oficial corregido y la advertencia de que operaciones fuera de la transacción gestionada de Stack (comandos manuales, removedores externos, updater nativo de Pi en modo manual) pueden sustituir o degradar los bytes del provider —y que el verificador detecta ese drift sin ser una ACL— se describen en [la referencia Pi](docs/references/pi-runtime.md#variante-temporal-del-provider-y-recibo-separado-candidato-devtool). El updater de providers de **Stack** (función) opera sólo sobre el **transporte legacy**; el transporte nativo lo maneja la **fase nativa del padre** (PR203, `runNativePiMcpPhase`) con la misma política de opt-in y snapshot, sin duplicar la autoridad nativa.
176
173
 
177
174
  ### Estilo global de escritura
178
175
 
179
- Stack incluye un prompt genérico de estilo de escritura como parte de su canon. `install` y `sync` lo gestionan en `~/.jorgex-stack/writing-style.md`; en modo humano proyectan el contenido efectivo directamente en una sección independiente de las instrucciones globales de los runtimes seleccionados. El prompt se aplica a la prosa dirigida al usuario, sigue el idioma en el que escribe el usuario salvo que pida otro y conserva las instrucciones técnicas, los formatos de máquina, el código y la configuración nativa. El modo programático conserva la fuente local, pero omite la proyección de prosa.
176
+ Stack incluye un prompt genérico de estilo de escritura como parte de su canon. `install` lo gestiona en `~/.jorgex-stack/writing-style.md`; en modo humano proyecta el contenido efectivo directamente en una sección independiente de las instrucciones globales de los runtimes seleccionados. `install`/`update` reconcilian el canon internamente sin exponer un comando público de sync. El prompt se aplica a la prosa dirigida al usuario, sigue el idioma en el que escribe el usuario salvo que pida otro y conserva las instrucciones técnicas, los formatos de máquina, el código y la configuración nativa. El modo programático conserva la fuente local, pero omite la proyección de prosa.
180
177
 
181
178
  La proyección contiene el canon directamente: Stack no añade un wrapper adicional ni una identidad personal. Si falta el archivo local o está vacío, Stack recrea el bloque gestionado. El corpus de mensajes y los informes privados de análisis no se distribuyen en el paquete. Consulta [configuración, prueba aislada, diagnóstico y límites](docs/references/writing-style.md).
182
179
 
@@ -203,7 +200,7 @@ jorgex-stack browser playwright -s=mi-tarea close
203
200
  pnpm dlx jorgex-stack install --devtools
204
201
  ```
205
202
 
206
- `sync` revalida el receipt local sin resolver ni descargar paquetes browser y retira la guía si el estado gestionado falla. `doctor` revisa receipt, versión, caché Chromium y arranque headless local sin reparar. `update --check` observa solo estado local; `install` o `update` interactivo deliberados pueden adquirir un nuevo release verificado. `uninstall` conserva por defecto el árbol gestionado y los datos del navegador; `--remove-playwright` desactiva preferencia y guía con backup, sin retirar un CLI global ajeno. Una preferencia ilegible bloquea mutaciones y `doctor` señala su ruta. Con `--target-dir` Stack no toca el estado browser del HOME real. Consulta [automatización de navegador](docs/references/browser-automation.md) para receipts, reparación y handoffs Pi.
203
+ `install`/`update` pueden adquirir un nuevo release browser verificado con opt-in explícito o preferencia persistida; no son una alternativa offline al comando retirado `sync`. `doctor` revisa receipt, versión, caché Chromium y arranque headless local sin reparar. `update --check` observa solo estado local. `uninstall` conserva por defecto el árbol gestionado y los datos del navegador; `--remove-playwright` desactiva preferencia y guía con backup, sin retirar un CLI global ajeno. Una preferencia ilegible bloquea mutaciones y `doctor` señala su ruta. Con `--target-dir` Stack no toca el estado browser del HOME real. Consulta [automatización de navegador](docs/references/browser-automation.md) para receipts, reparación y handoffs Pi.
207
204
 
208
205
  ### Update: Interactive Flow
209
206
 
@@ -225,7 +222,7 @@ GitHub authentication: requests use `GH_TOKEN`/`GITHUB_TOKEN` from the environme
225
222
 
226
223
  Goal Mode de OpenCode se ha retirado. Stack ya no instala su plugin ni el comando `/goal`; la continuidad de trabajo usa el lifecycle normal: `work/{name}/PRD.md` y `plan.md` permanecen durante los merges intermedios, `work/{name}/pr/{NN}` conserva cada checkpoint y `work/{name}/done` queda reservado para el cierre final.
227
224
 
228
- La retirada no migra el historial. `sync` sólo puede retirar archivos gestionados cuando dispone de un manifest legible que registre esas rutas como gestionadas y un inventario completo, con backup previo; conserva los datos existentes en `~/.jorgex-stack/goals` y los plugins ajenos cuando el manifest del Stack está íntegro. El registro local no autentica la propiedad ni corrige una lista `owned` editada o inconsistente: si falta, no se puede parsear o el inventario es incompleto, no se borra el legacy. Ante sospecha sobre el manifest, no ejecutes `sync`; revísalo o restáuralo con backup. `--target-dir` no implica limpiar ese estado.
225
+ La retirada no migra el historial. `install`/`update` sólo retiran archivos gestionados cuando disponen de un manifest legible que registre esas rutas como gestionadas y un inventario completo, con backup previo; conservan los datos existentes en `~/.jorgex-stack/goals` y los plugins ajenos cuando el manifest del Stack está íntegro. El registro local no autentica la propiedad ni corrige una lista `owned` editada o inconsistente: si falta, no se puede parsear o el inventario es incompleto, no se borra el legacy. Ante sospecha sobre el manifest, no ejecutes `install`/`update`; revísalo o restáuralo con backup. `--target-dir` no implica limpiar ese estado.
229
226
 
230
227
  La continuidad entre checkpoints sigue requiriendo trabajo aprobado, capacidades disponibles y merge humano explícito. PiGoal conserva su propio lifecycle. No se afirma disponibilidad de una alternativa GoalV2 de OpenCode.
231
228
 
package/dist/cli.d.ts CHANGED
@@ -7,7 +7,7 @@
7
7
  type RuntimeId = "claude-code" | "codex" | "opencode";
8
8
  type SelectableRuntimeId = RuntimeId | "pi";
9
9
 
10
- declare const COMMANDS: readonly ["install", "sync", "models", "update", "doctor", "restore", "uninstall", "quality", "browser"];
10
+ declare const COMMANDS: readonly ["install", "models", "update", "doctor", "restore", "uninstall", "quality", "browser"];
11
11
  type Command = (typeof COMMANDS)[number];
12
12
  interface Flags {
13
13
  agents: SelectableRuntimeId[];
package/dist/cli.js CHANGED
@@ -2480,7 +2480,7 @@ function assertCompatibleContext7(server, value) {
2480
2480
  function ensureObject(parent, key, fieldPath) {
2481
2481
  if (parent[key] === void 0) parent[key] = {};
2482
2482
  const value = objectValue(parent[key]);
2483
- if (value === null) throw new Error(`OpenCode: '${fieldPath}' debe ser un objeto; corr\xEDgelo antes de reintentar sync.`);
2483
+ if (value === null) throw new Error(`OpenCode: '${fieldPath}' debe ser un objeto; corr\xEDgelo antes de reintentar install.`);
2484
2484
  return value;
2485
2485
  }
2486
2486
  function ensureOwnedPrimaryObject(parent, key, field, owned, changes) {
@@ -2921,7 +2921,7 @@ ${gitReadCommands.map((command) => `- \`${command}\``).join("\n")}
2921
2921
  const content = upsertJson(contentSource, (root) => {
2922
2922
  const rawMcp = root["mcp"];
2923
2923
  if (rawMcp !== void 0 && objectValue(rawMcp) === null) {
2924
- throw new Error("OpenCode: la clave 'mcp' debe ser un objeto; corr\xEDgela antes de reintentar sync.");
2924
+ throw new Error("OpenCode: la clave 'mcp' debe ser un objeto; corr\xEDgela antes de reintentar install.");
2925
2925
  }
2926
2926
  const existingMcp = rawMcp;
2927
2927
  const context7 = canonical.servers.context7;
@@ -2933,7 +2933,7 @@ ${gitReadCommands.map((command) => `- \`${command}\``).join("\n")}
2933
2933
  primaryModelOwnership.push({ field: PRIMARY_MODEL_FIELD, owned: true });
2934
2934
  }
2935
2935
  } else if (typeof root[PRIMARY_MODEL_FIELD] !== "string" || root[PRIMARY_MODEL_FIELD].trim() === "") {
2936
- throw new Error("OpenCode: 'model' debe ser un identificador provider/model no vac\xEDo; corr\xEDgelo antes de reintentar sync.");
2936
+ throw new Error("OpenCode: 'model' debe ser un identificador provider/model no vac\xEDo; corr\xEDgelo antes de reintentar install.");
2937
2937
  }
2938
2938
  const provider = ensureOwnedPrimaryObject(root, "provider", PRIMARY_PROVIDER_FIELD, ctx.ownedPrimaryModelFields, primaryModelOwnership);
2939
2939
  const openai = ensureOwnedPrimaryObject(provider, "openai", PRIMARY_OPENAI_FIELD, ctx.ownedPrimaryModelFields, primaryModelOwnership);
@@ -3001,7 +3001,7 @@ ${gitReadCommands.map((command) => `- \`${command}\``).join("\n")}
3001
3001
  if (server.transport === "stdio") {
3002
3002
  if (server.command === "{{ENGRAM_BIN}}" && ctx.engramBin === null) {
3003
3003
  ctx.warnings.push(
3004
- "Engram no detectado: el MCP 'engram' no se registra. Inst\xE1lalo (github.com/Gentleman-Programming/engram) y re-ejecuta sync."
3004
+ "Engram no detectado: el MCP 'engram' no se registra. Inst\xE1lalo (github.com/Gentleman-Programming/engram) y re-ejecuta install."
3005
3005
  );
3006
3006
  continue;
3007
3007
  }
@@ -3600,7 +3600,7 @@ ${agent.body}`,
3600
3600
  const content = upsertJson(readMcpConfig2(file), (root) => {
3601
3601
  const rawServers = root["mcpServers"];
3602
3602
  if (rawServers !== void 0 && !isRecord3(rawServers)) {
3603
- throw new Error("Claude Code: la clave 'mcpServers' debe ser un objeto; corr\xEDgela antes de reintentar sync.");
3603
+ throw new Error("Claude Code: la clave 'mcpServers' debe ser un objeto; corr\xEDgela antes de reintentar install.");
3604
3604
  }
3605
3605
  const existingServers = rawServers;
3606
3606
  const context7 = canonical.servers.context7;
@@ -3639,7 +3639,7 @@ ${agent.body}`,
3639
3639
  if (server.transport === "stdio") {
3640
3640
  if (server.command === "{{ENGRAM_BIN}}" && ctx.engramBin === null) {
3641
3641
  ctx.warnings.push(
3642
- "Engram no detectado: el MCP 'engram' no se registra. Inst\xE1lalo (github.com/Gentleman-Programming/engram) y re-ejecuta sync."
3642
+ "Engram no detectado: el MCP 'engram' no se registra. Inst\xE1lalo (github.com/Gentleman-Programming/engram) y re-ejecuta install."
3643
3643
  );
3644
3644
  continue;
3645
3645
  }
@@ -4308,7 +4308,7 @@ ${body}`
4308
4308
  if (server.transport === "stdio") {
4309
4309
  if (server.command === "{{ENGRAM_BIN}}" && ctx.engramBin === null) {
4310
4310
  ctx.warnings.push(
4311
- "Engram no detectado: el MCP 'engram' no se registra. Inst\xE1lalo (github.com/Gentleman-Programming/engram) y re-ejecuta sync."
4311
+ "Engram no detectado: el MCP 'engram' no se registra. Inst\xE1lalo (github.com/Gentleman-Programming/engram) y re-ejecuta install."
4312
4312
  );
4313
4313
  continue;
4314
4314
  }
@@ -10181,7 +10181,7 @@ async function runInstall(opts) {
10181
10181
  }
10182
10182
  if (promptReconciliationFailed) {
10183
10183
  exitCode = 1;
10184
- p.log.error("Playwright CLI y navegador se han instalado y la preferencia qued\xF3 activa, pero la gu\xEDa de navegador qued\xF3 en estado parcial. Ejecuta 'jorgex-stack sync' para repararla.");
10184
+ p.log.error("Playwright CLI y navegador se han instalado y la preferencia qued\xF3 activa, pero la gu\xEDa de navegador qued\xF3 en estado parcial. Ejecuta 'jorgex-stack install' para repararla.");
10185
10185
  } else {
10186
10186
  const verified = verifiedCapability ?? (preparedEnv === void 0 ? inspectPlaywrightCapability({ browserVerified: true, expectedVersion: candidate.version }) : inspectPlaywrightCapability({ browserVerified: true, env: preparedEnv, expectedVersion: candidate.version }));
10187
10187
  if (verified.effective && verified.cli.status === "current" && verified.cli.binPath !== null && verified.cli.detectedVersion !== null && verified.browserCache.status === "ready") {
@@ -15221,7 +15221,7 @@ function readDoctorTextIfExists(file) {
15221
15221
  }
15222
15222
  }
15223
15223
  var STALE_PERMISSIONS_MARKER = "differs from the stack default and was left untouched";
15224
- var UPGRADE_PERMISSIONS_REMEDY = "jorgex-stack sync --upgrade-permissions --dry-run";
15224
+ var UPGRADE_PERMISSIONS_REMEDY = "jorgex-stack install --upgrade-permissions --dry-run";
15225
15225
  function piAgentDir(targetDir) {
15226
15226
  return targetDir === void 0 ? process.env.PI_CODING_AGENT_DIR ?? path41.join(HOME, ".pi", "agent") : path41.join(targetDir, "pi-agent");
15227
15227
  }
@@ -15258,7 +15258,7 @@ function reportPiPermissions(targetDir) {
15258
15258
  }
15259
15259
  if (receipt !== null) return 0;
15260
15260
  p3.log.warn(
15261
- `Pi: permission policy present without package ownership (${configFile}) and left untouched; Stack never rewrites Pi state \u2014 align it by hand or remove it so a later 'jorgex-stack sync --agents pi' can seed the package default.`
15261
+ `Pi: permission policy present without package ownership (${configFile}) and left untouched; Stack never rewrites Pi state \u2014 align it by hand or remove it so a later 'jorgex-stack install --agents pi' can seed the package default.`
15262
15262
  );
15263
15263
  return 1;
15264
15264
  }
@@ -15288,7 +15288,7 @@ function reportWritingStyle(options, style, mode) {
15288
15288
  p3.log.info(`Estilo de escritura incluido: ${style.canonicalPath}; fuente local ${style.sourcePath}; tama\xF1o ${Buffer.byteLength(style.content, "utf8")} bytes de texto normalizado. La carga nativa no est\xE1 verificada.`);
15289
15289
  if (style.originalContent === style.installedContent) p3.log.success("Archivo local de estilo actualizado con el canon incluido.");
15290
15290
  else {
15291
- p3.log.warn(`Archivo local de estilo ${style.originalContent === null ? "pendiente de instalar" : "desactualizado; pendiente de sincronizar"}; ejecuta install o sync (${style.sourcePath}).`);
15291
+ p3.log.warn(`Archivo local de estilo ${style.originalContent === null ? "pendiente de instalar" : "desactualizado; pendiente de sincronizar"}; ejecuta install (${style.sourcePath}).`);
15292
15292
  problems++;
15293
15293
  }
15294
15294
  const expected = mode.mode !== "programmatic" ? upsertMarkdownSection(null, "writing-style", style.content).trim() : null;
@@ -15307,7 +15307,7 @@ function reportWritingStyle(options, style, mode) {
15307
15307
  const matches = expected === null ? !content.includes(open) && !content.includes(close) : healthy && block === expected;
15308
15308
  if (matches) p3.log.success(`${id}: proyecci\xF3n de estilo coincide (${file})${mode.mode === "programmatic" ? "; omitida en modo programmatic" : ""}.`);
15309
15309
  else {
15310
- p3.log.warn(`${id}: proyecci\xF3n de estilo desactualizada o ausente (${file}); ejecuta sync.`);
15310
+ p3.log.warn(`${id}: proyecci\xF3n de estilo desactualizada o ausente (${file}); ejecuta install.`);
15311
15311
  problems++;
15312
15312
  }
15313
15313
  if (id === "codex") {
@@ -15493,7 +15493,7 @@ async function runDoctor(options = {}) {
15493
15493
  problems++;
15494
15494
  }
15495
15495
  if (pending > 0) {
15496
- p3.log.warn(`${adapter.name}: ${pending} archivos gestionados desactualizados o ausentes \u2192 ejecuta 'sync'.`);
15496
+ p3.log.warn(`${adapter.name}: ${pending} archivos gestionados desactualizados o ausentes \u2192 ejecuta 'install'.`);
15497
15497
  problems++;
15498
15498
  } else if (!stalePermissions) {
15499
15499
  p3.log.success(`${adapter.name}: config del stack al d\xEDa (${detection.configDir}).`);
@@ -15501,7 +15501,7 @@ async function runDoctor(options = {}) {
15501
15501
  const prev = manifest.runtimes[adapter.id];
15502
15502
  const orphans = prev && current.complete ? findOrphans(prev.owned, current.targets) : [];
15503
15503
  if (orphans.length > 0) {
15504
- p3.log.warn(`${adapter.name}: ${orphans.length} archivos hu\xE9rfanos de versiones previas \u2192 ejecuta 'sync'.`);
15504
+ p3.log.warn(`${adapter.name}: ${orphans.length} archivos hu\xE9rfanos de versiones previas \u2192 ejecuta 'install'.`);
15505
15505
  problems++;
15506
15506
  }
15507
15507
  if (adapter.id === "codex" && fs34.existsSync(path41.join(detection.configDir, "hooks.json"))) {
@@ -21954,8 +21954,8 @@ async function completeProjection(operation, packageResult, deps) {
21954
21954
  }
21955
21955
  return projectionResult.kind === "blocked" ? projectionResult : packageResult;
21956
21956
  }
21957
- var INSTALL_INIT_REMEDY = "Corrige la causa y ejecuta sync --agents pi para completar la inicializaci\xF3n.";
21958
- var INSTALL_INIT_TARGET_REMEDY = "Corrige la causa y ejecuta sync --agents pi con el mismo --target-dir para completar la inicializaci\xF3n.";
21957
+ var INSTALL_INIT_REMEDY = "Corrige la causa y ejecuta install --agents pi para completar la inicializaci\xF3n.";
21958
+ var INSTALL_INIT_TARGET_REMEDY = "Corrige la causa y ejecuta install --agents pi con el mismo --target-dir para completar la inicializaci\xF3n.";
21959
21959
  function withInstallInitRemedy(result, fallbackRemedy) {
21960
21960
  return result.remedy === void 0 ? { kind: "blocked", reason: result.reason, remedy: fallbackRemedy } : result;
21961
21961
  }
@@ -22025,7 +22025,7 @@ function managedPackageResult(result) {
22025
22025
  if (result.kind === "manual-existing") {
22026
22026
  return {
22027
22027
  kind: "manual-existing",
22028
- remedy: result.remedy ?? "Pi ya est\xE1 configurado manualmente; conserva esa configuraci\xF3n o elim\xEDnala antes de ejecutar sync --agents pi."
22028
+ remedy: result.remedy ?? "Pi ya est\xE1 configurado manualmente; conserva esa configuraci\xF3n o elim\xEDnala antes de ejecutar install --agents pi."
22029
22029
  };
22030
22030
  }
22031
22031
  if (result.kind === "models") return { kind: "models", models: result.models };
@@ -22602,7 +22602,7 @@ async function runManagedPiSystem(input) {
22602
22602
  return Promise.resolve(result2.kind === "drift" ? {
22603
22603
  kind: "drift",
22604
22604
  paths: result2.paths,
22605
- remedy: "Ejecuta sync --agents pi para reparar la proyecci\xF3n de Pi."
22605
+ remedy: "Ejecuta install --agents pi para reparar la proyecci\xF3n de Pi."
22606
22606
  } : result2);
22607
22607
  },
22608
22608
  prepareProjectionUninstall() {
@@ -22673,7 +22673,7 @@ async function runManagedPiSystem(input) {
22673
22673
  return {
22674
22674
  kind: "blocked",
22675
22675
  reason: "native-checker-conflict",
22676
- remedy: "El paquete Pi qued\xF3 activado; la comprobaci\xF3n nativa detect\xF3 un conflicto de propiedad sobre mcp.json/autoridad. Resu\xE9lvelo y ejecuta sync --agents pi para completar la inicializaci\xF3n."
22676
+ remedy: "El paquete Pi qued\xF3 activado; la comprobaci\xF3n nativa detect\xF3 un conflicto de propiedad sobre mcp.json/autoridad. Resu\xE9lvelo y ejecuta install --agents pi para completar la inicializaci\xF3n."
22677
22677
  };
22678
22678
  }
22679
22679
  const expectedClaims = nativeAuthority === void 0 ? previousNativeClaimNames(nativeHomeDir, authorityRaw) ?? [] : Object.keys(nativeAuthority.entries);
@@ -22689,7 +22689,7 @@ async function runManagedPiSystem(input) {
22689
22689
  return {
22690
22690
  kind: "blocked",
22691
22691
  reason: "native-checker-failed",
22692
- remedy: `El paquete Pi qued\xF3 activado; la comprobaci\xF3n nativa fall\xF3: ${error instanceof Error ? error.message : String(error)}. Inicializaci\xF3n nativa pendiente; ejecuta sync --agents pi para reintentar.`
22692
+ remedy: `El paquete Pi qued\xF3 activado; la comprobaci\xF3n nativa fall\xF3: ${error instanceof Error ? error.message : String(error)}. Inicializaci\xF3n nativa pendiente; ejecuta install --agents pi para reintentar.`
22693
22693
  };
22694
22694
  }
22695
22695
  }
@@ -23750,7 +23750,7 @@ async function installMissingEngram(options = {}) {
23750
23750
 
23751
23751
  // src/cli.ts
23752
23752
  var VERSION = readPackageVersion();
23753
- var COMMANDS = ["install", "sync", "models", "update", "doctor", "restore", "uninstall", "quality", "browser"];
23753
+ var COMMANDS = ["install", "models", "update", "doctor", "restore", "uninstall", "quality", "browser"];
23754
23754
  var QUALITY_REJECTED_VALUE_FLAGS = /* @__PURE__ */ new Set([
23755
23755
  "--agents",
23756
23756
  "--playwright-runtimes",
@@ -23759,15 +23759,15 @@ var QUALITY_REJECTED_VALUE_FLAGS = /* @__PURE__ */ new Set([
23759
23759
  "--mode",
23760
23760
  "--subagent-concurrency"
23761
23761
  ]);
23762
- async function ensureOpenCodeModelsForInstall(command, flags, runtimes) {
23762
+ async function ensureOpenCodeModelsForInstall(flags, runtimes) {
23763
23763
  if (!runtimes.includes("opencode") || loadModelMap().opencode) return true;
23764
- const canPrompt = command === "install" && !flags.yes && !flags.dryRun && process.stdout.isTTY;
23764
+ const canPrompt = !flags.yes && !flags.dryRun && process.stdout.isTTY;
23765
23765
  if (canPrompt) {
23766
23766
  const code = await runModelsPicker({ yes: false, runtimes: ["opencode"] });
23767
23767
  if (code === 0 && loadModelMap().opencode) return true;
23768
23768
  }
23769
23769
  console.error(
23770
- "OpenCode no tiene modelos configurados. Ejecuta 'jorgex-stack models --agents opencode' de forma interactiva antes de install/sync."
23770
+ "OpenCode no tiene modelos configurados. Ejecuta 'jorgex-stack models --agents opencode' de forma interactiva antes de install."
23771
23771
  );
23772
23772
  return false;
23773
23773
  }
@@ -23895,7 +23895,7 @@ Corrige o borra ${preferenceFile}, o vuelve a ejecutar con --mode human|programm
23895
23895
  }
23896
23896
  }
23897
23897
  if (!promptIfMissing) {
23898
- console.error("No hay modo guardado; usa --mode expl\xEDcito para este sync.");
23898
+ console.error("No hay modo guardado; usa --mode expl\xEDcito para esta aplicaci\xF3n.");
23899
23899
  process.exitCode = 1;
23900
23900
  return null;
23901
23901
  }
@@ -23929,7 +23929,7 @@ Corrige o borra ${preferenceFile}, o vuelve a ejecutar con --mode human|programm
23929
23929
  subagentConcurrency: concurrency
23930
23930
  };
23931
23931
  }
23932
- async function resolvePlaywrightToolConsent(command, flags, runtimes) {
23932
+ async function resolvePlaywrightToolConsent(flags, runtimes) {
23933
23933
  const interactive = Boolean(process.stdout.isTTY);
23934
23934
  const supportsPiPlaywright = PI_RUNTIME_CANDIDATE.contract.capabilities.includes("playwright-handoff-v1");
23935
23935
  const supported = runtimes.filter((runtime) => runtime !== "pi" || supportsPiPlaywright);
@@ -23949,13 +23949,13 @@ async function resolvePlaywrightToolConsent(command, flags, runtimes) {
23949
23949
  return null;
23950
23950
  }
23951
23951
  }
23952
- if (command === "install" && flags.playwright && supported.length === 0 && runtimes.includes("pi")) {
23952
+ if (flags.playwright && supported.length === 0 && runtimes.includes("pi")) {
23953
23953
  console.error("Pi no declara el handoff Playwright requerido.");
23954
23954
  process.exitCode = 1;
23955
23955
  return null;
23956
23956
  }
23957
23957
  let confirmed = false;
23958
- if (command === "install" && interactive && !flags.yes && !flags.dryRun && flags.targetDir === void 0) {
23958
+ if (interactive && !flags.yes && !flags.dryRun && flags.targetDir === void 0) {
23959
23959
  const answer = await p6.confirm({
23960
23960
  message: "Recomendado: \xBFinstalar Playwright CLI gestionado y descargar Chromium?",
23961
23961
  initialValue: false
@@ -23965,7 +23965,7 @@ async function resolvePlaywrightToolConsent(command, flags, runtimes) {
23965
23965
  }
23966
23966
  let runtimeSelection;
23967
23967
  const approved = interactive && !flags.yes ? confirmed : flags.yes && flags.playwright;
23968
- if (command === "install" && approved && supported.length > 0) {
23968
+ if (approved && supported.length > 0) {
23969
23969
  let selected = flags.playwrightRuntimes ?? supported;
23970
23970
  if (interactive && !flags.yes && !flags.dryRun && flags.targetDir === void 0 && flags.playwrightRuntimes === void 0) {
23971
23971
  const answer = await p6.multiselect({
@@ -23980,7 +23980,7 @@ async function resolvePlaywrightToolConsent(command, flags, runtimes) {
23980
23980
  runtimeSelection = Object.fromEntries(supported.map((runtime) => [runtime, selected.includes(runtime)]));
23981
23981
  }
23982
23982
  return {
23983
- command,
23983
+ command: "install",
23984
23984
  interactive,
23985
23985
  yes: flags.yes,
23986
23986
  targetDir: flags.targetDir !== void 0,
@@ -23989,7 +23989,7 @@ async function resolvePlaywrightToolConsent(command, flags, runtimes) {
23989
23989
  ...runtimeSelection === void 0 ? {} : { runtimeSelection }
23990
23990
  };
23991
23991
  }
23992
- async function resolveDevtoolsMcpSelection(command, flags, runtimes) {
23992
+ async function resolveDevtoolsMcpSelection(flags, runtimes) {
23993
23993
  if (flags.devtools && flags.noDevtools) {
23994
23994
  console.error("Usa solo uno de --devtools o --no-devtools.");
23995
23995
  process.exitCode = 1;
@@ -23998,7 +23998,7 @@ async function resolveDevtoolsMcpSelection(command, flags, runtimes) {
23998
23998
  if (flags.devtools || flags.noDevtools) {
23999
23999
  return Object.fromEntries(runtimes.map((runtime) => [runtime, flags.devtools]));
24000
24000
  }
24001
- if (command !== "install" || flags.yes || flags.dryRun || flags.targetDir !== void 0 || !process.stdout.isTTY) {
24001
+ if (flags.yes || flags.dryRun || flags.targetDir !== void 0 || !process.stdout.isTTY) {
24002
24002
  return {};
24003
24003
  }
24004
24004
  const file = devtoolsMcpPreferenceFile();
@@ -24199,7 +24199,6 @@ Uso: pnpm dlx jorgex-stack [comando] [opciones]
24199
24199
 
24200
24200
  Comandos:
24201
24201
  install Instala el stack; OpenCode fresh exige elegir modelos conectados
24202
- sync Re-aplica la config y el model-map existente (idempotente; sin picker)
24203
24202
  models Picker por tier o subagente (OpenCode: 'opencode models' en vivo)
24204
24203
  update --check: compara stack/Engram/skills con sus upstreams
24205
24204
  doctor Estado: Engram, drift de config, hooks de Codex, key de context7
@@ -24219,9 +24218,9 @@ Opciones:
24219
24218
  --yes, -y No interactivo
24220
24219
  --playwright Autoriza Playwright CLI gestionado y Chromium (requerido con --yes/sin TTY)
24221
24220
  --engram (install) autoriza instalar el binario Engram si falta
24222
- --devtools (install/sync) activa Chrome DevTools MCP para los runtimes destino (opt-in)
24223
- --no-devtools (install/sync) desactiva Chrome DevTools MCP (incompatible con --devtools)
24224
- --upgrade-permissions (install/sync) re-aplica permisos gestionados sobre config existente (opt-in)
24221
+ --devtools (install) activa Chrome DevTools MCP para los runtimes destino (opt-in)
24222
+ --no-devtools (install) desactiva Chrome DevTools MCP (incompatible con --devtools)
24223
+ --upgrade-permissions (install) re-aplica permisos gestionados sobre config existente (opt-in)
24225
24224
  --engram-typebox-compat (install/update con Pi) opt-in expl\xEDcito a la variante temporal #1567;
24226
24225
  sin el flag no se adquiere ni persiste ninguna preferencia
24227
24226
  --remove-engram (uninstall) desregistra Engram de los runtimes;
@@ -24329,9 +24328,8 @@ Flags disponibles: jorgex-stack --help`
24329
24328
  }
24330
24329
  return;
24331
24330
  }
24332
- case "install":
24333
- case "sync": {
24334
- const runtimes = await resolveRuntimes(flags, command === "install");
24331
+ case "install": {
24332
+ const runtimes = await resolveRuntimes(flags, true);
24335
24333
  if (runtimes === null) return;
24336
24334
  if (runtimes.length === 0) {
24337
24335
  console.error("Ning\xFAn runtime detectado (opencode, claude-code, codex, pi).");
@@ -24363,12 +24361,12 @@ Flags disponibles: jorgex-stack --help`
24363
24361
  }
24364
24362
  const mode = fileRuntimes.length > 0 || flags.mode !== void 0 || flags.subagentConcurrency !== void 0 ? await resolveInstallMode(flags) : void 0;
24365
24363
  if (mode === null) return;
24366
- const devtoolsMcpSelection = await resolveDevtoolsMcpSelection(command, flags, runtimes);
24364
+ const devtoolsMcpSelection = await resolveDevtoolsMcpSelection(flags, runtimes);
24367
24365
  if (devtoolsMcpSelection === null) {
24368
24366
  exitCode = process.exitCode === 1 ? 1 : 0;
24369
24367
  return;
24370
24368
  }
24371
- const playwrightToolConsent = await resolvePlaywrightToolConsent(command, flags, runtimes);
24369
+ const playwrightToolConsent = await resolvePlaywrightToolConsent(flags, runtimes);
24372
24370
  if (playwrightToolConsent === null) {
24373
24371
  exitCode = process.exitCode === 1 ? 1 : 0;
24374
24372
  return;
@@ -24380,20 +24378,17 @@ Flags disponibles: jorgex-stack --help`
24380
24378
  };
24381
24379
  p6.log.info(`Estilo de escritura: ${writingStyle.sourcePath}${flags.dryRun ? " (instalaci\xF3n prevista; sin escrituras)" : ""}.`);
24382
24380
  applyWritingStyle(writingStyle, flags.dryRun);
24383
- if (!await ensureOpenCodeModelsForInstall(command, flags, fileRuntimes)) {
24381
+ if (!await ensureOpenCodeModelsForInstall(flags, fileRuntimes)) {
24384
24382
  exitCode = 1;
24385
24383
  return;
24386
24384
  }
24387
- let engramBin;
24388
- if (command === "install") {
24389
- const engram = await resolveHostEngramForInstall(flags);
24390
- if (!engram.ok) {
24391
- p6.log.error(engram.message);
24392
- exitCode = 1;
24393
- return;
24394
- }
24395
- engramBin = engram.bin;
24385
+ const engram = await resolveHostEngramForInstall(flags);
24386
+ if (!engram.ok) {
24387
+ p6.log.error(engram.message);
24388
+ exitCode = 1;
24389
+ return;
24396
24390
  }
24391
+ const engramBin = engram.bin;
24397
24392
  if (fileRuntimes.length > 0) {
24398
24393
  exitCode = await runInstall({
24399
24394
  runtimes: fileRuntimes,
@@ -24414,7 +24409,7 @@ Flags disponibles: jorgex-stack --help`
24414
24409
  });
24415
24410
  }
24416
24411
  let piCanRun = true;
24417
- if (command === "install" && fileRuntimes.length === 0 && runtimes.includes("pi") && playwrightToolPlan.actions.length > 0) {
24412
+ if (fileRuntimes.length === 0 && runtimes.includes("pi") && playwrightToolPlan.actions.length > 0) {
24418
24413
  if (flags.dryRun) {
24419
24414
  p6.log.info("Playwright CLI: instalaci\xF3n global y navegador previstos (dry-run; no se ejecutan).");
24420
24415
  } else {
@@ -24439,7 +24434,7 @@ Flags disponibles: jorgex-stack --help`
24439
24434
  } else {
24440
24435
  const piExitCode = await runSelectedPi({
24441
24436
  operation: command,
24442
- ...command === "install" && playwrightToolConsent.interactive && !flags.yes && flags.targetDir === void 0 && !playwrightToolConsent.confirmed ? { playwrightRefresh: false } : {},
24437
+ ...playwrightToolConsent.interactive && !flags.yes && flags.targetDir === void 0 && !playwrightToolConsent.confirmed ? { playwrightRefresh: false } : {},
24443
24438
  targetDir: flags.targetDir,
24444
24439
  yes: flags.yes,
24445
24440
  resolvedEngramBin: flags.targetDir === void 0 ? engramBin : void 0,
@@ -24643,9 +24638,9 @@ Flags disponibles: jorgex-stack --help`
24643
24638
  }));
24644
24639
  }
24645
24640
  if (result.syncRequired && fileRuntimes.length > 0 && (result.exitCode !== 0 || !canSync)) {
24646
- p6.log.warn("Skills/stack actualizados, pero el sync con los runtimes sigue pendiente. Ejecuta jorgex-stack sync --mode human|programmatic.");
24641
+ p6.log.warn("Skills/stack actualizados, pero su aplicaci\xF3n a los runtimes sigue pendiente. Ejecuta jorgex-stack install --mode human|programmatic.");
24647
24642
  } else if (!playwrightReconciled && result.exitCode === 0 && result.syncRequired && fileRuntimes.length > 0 && canSync && !flags.yes && process.stdout.isTTY) {
24648
- const apply = await p6.confirm({ message: "\xBFRe-aplicar a los runtimes ahora? (sync)" });
24643
+ const apply = await p6.confirm({ message: "\xBFRe-aplicar a los runtimes ahora?" });
24649
24644
  if (!p6.isCancel(apply) && apply) {
24650
24645
  process.exitCode = await runInstall({
24651
24646
  runtimes: fileRuntimes,
@@ -24657,10 +24652,10 @@ Flags disponibles: jorgex-stack --help`
24657
24652
  ...updateCapability === void 0 ? {} : { playwrightCapability: updateCapability }
24658
24653
  });
24659
24654
  } else {
24660
- console.log("Sin aplicar. Cuando quieras: jorgex-stack sync");
24655
+ console.log("Sin aplicar. Cuando quieras: jorgex-stack install");
24661
24656
  }
24662
24657
  } else if (result.exitCode === 0 && result.syncRequired && fileRuntimes.length > 0 && canSync && (flags.yes || !process.stdout.isTTY)) {
24663
- console.log("Skills/stack actualizados. Ejecuta jorgex-stack sync para aplicarlos a los runtimes.");
24658
+ console.log("Skills/stack actualizados. Ejecuta jorgex-stack install para aplicarlos a los runtimes.");
24664
24659
  }
24665
24660
  if (runtimes.includes("pi")) {
24666
24661
  persistSuccessfulGlobalMode(mode, flags.targetDir, flags.dryRun, process.exitCode ?? result.exitCode);
@@ -24680,14 +24675,14 @@ Flags disponibles: jorgex-stack --help`
24680
24675
  if (runtimes.includes("pi")) code = Math.max(code, await runSelectedPi({ operation: "models", targetDir: flags.targetDir }));
24681
24676
  process.exitCode = code;
24682
24677
  if (code === 0 && fileRuntimes.length > 0 && !flags.yes && process.stdout.isTTY) {
24683
- const apply = await p6.confirm({ message: "\xBFAplicar ahora los modelos a los agentes instalados? (sync)" });
24678
+ const apply = await p6.confirm({ message: "\xBFAplicar ahora los modelos a los agentes instalados?" });
24684
24679
  if (!p6.isCancel(apply) && apply) {
24685
24680
  const preferenceFile = installModePreferenceFile();
24686
24681
  const explicitMode = flags.mode !== void 0 || flags.subagentConcurrency !== void 0;
24687
24682
  const hasSavedMode = hasInstallModePreference(preferenceFile);
24688
24683
  const canResolveMode = flags.targetDir !== void 0 || explicitMode || hasSavedMode;
24689
24684
  if (!canResolveMode) {
24690
- p6.log.warn("Model-map guardado: se omite el sync con los runtimes porque falta un modo. Ejecuta jorgex-stack sync --mode human|programmatic.");
24685
+ p6.log.warn("Model-map guardado: su aplicaci\xF3n a los runtimes requiere un modo. Ejecuta jorgex-stack install --mode human|programmatic.");
24691
24686
  return;
24692
24687
  }
24693
24688
  const mode = await resolveInstallMode(flags, false);
@@ -24702,7 +24697,7 @@ Flags disponibles: jorgex-stack --help`
24702
24697
  ...playwrightCapability === void 0 ? {} : { playwrightCapability }
24703
24698
  });
24704
24699
  } else {
24705
- console.log("Sin aplicar. Cuando quieras: jorgex-stack sync");
24700
+ console.log("Sin aplicar. Cuando quieras: jorgex-stack install");
24706
24701
  }
24707
24702
  }
24708
24703
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jorgex-stack",
3
- "version": "1.9.71",
3
+ "version": "1.9.73",
4
4
  "description": "Harness multi-agente portable: instala la config JorgeX (agentes, skills, hooks, Engram, MCPs) en Claude Code, Codex CLI, OpenCode y Pi",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -35,13 +35,13 @@ Apply the risk, existing-protection, behavior, seam, and non-duplication rules f
35
35
  1. Compare each changed behavior with the actual evidence in existing or changed tests.
36
36
  2. Evaluate refactor resistance, determinism, accidental `test.only`/exclusive-focus slips, stable UI semantics, negative cases, and async/concurrency behavior only where relevant to the diff.
37
37
  3. Report an actionable gap only when the existing evidence cannot catch a meaningful regression. Name that failure, the test considered, the proposed seam, and its criticality.
38
- 4. Separately flag brittle, redundant, nondeterministic, or implementation-coupled tests worth fixing or removing.
38
+ 4. Separately flag brittle, redundant, nondeterministic, or implementation-coupled tests, repeated setup/fixtures/helpers, and suites fragmented by task, delivery or RED/GREEN phase rather than contract. Before supporting Ready, assess whether the assigned test structure can be simplified with equivalent protection and isolation; do not merge setups that protect distinct boundaries. Report structural duplication as a test-quality finding, not a missing-coverage gap; the coordinator routes the fix to its owner.
39
39
 
40
40
  ## Rating guidelines
41
41
 
42
42
  - **8–10 — Critical**: Data loss, security issue, system failure, or substantial business/user failure without sufficient evidence
43
43
  - **5–7 — Important**: Concrete user-facing, business, or operational regression with moderate impact
44
- - **1–4**: Not a missing-test finding; mention only a brittle or redundant existing test worth removing
44
+ - **1–4**: Not a missing-test finding; mention only a brittle or redundant test or setup worth simplifying
45
45
 
46
46
  ## Output format
47
47
 
@@ -51,7 +51,7 @@ Apply the risk, existing-protection, behavior, seam, and non-duplication rules f
51
51
  4. **Test Quality Issues**: Brittle, redundant, nondeterministic, or implementation-coupled tests
52
52
  5. **Positive Observations**: Strong existing decisions and evidence
53
53
 
54
- For every recommendation, state the failure it would catch, why existing protection is insufficient, and why the proposed seam is stronger than another layer.
54
+ For a coverage recommendation, state the failure it would catch, why existing protection is insufficient, and why the proposed seam is stronger than another layer. For a structural quality finding, identify the duplicated preparation, its maintenance cost, the proposed reuse or consolidation, and the contracts and isolation that must remain intact; do not invent missing coverage to justify simplification.
55
55
 
56
56
  ## Result contract
57
57
 
@@ -19,6 +19,8 @@ Your job is to produce the strongest testing evidence for the risk—not to maxi
19
19
 
20
20
  Inspect the complete relevant contract (implementation, public API, docs, configuration, and existing tests), then detect the project's real runner, script/command, setup, scope, and helpers. Mirror local naming and assertion conventions; use tooling already installed. Documented project scripts, including `pnpm`, `npm`, and similar package-manager scripts, are valid. Do not add dependencies or invent a second testing stack; prohibit only invoking or resolving a command that could auto-install a missing runner/tool or require interaction without permission. If a needed suite or boundary infrastructure is absent, propose the missing protection or state the limitation rather than turning absence into a no-test decision.
21
21
 
22
+ Organize suites by behavior or contract, not by task, delivery or RED/GREEN phase. Before creating another suite or setup, reuse relevant existing helpers and fixtures within the assignment. Share only genuinely common preparation; keep distinct boundaries and state isolation separate. One authoritative seam does not mean one test case: preserve meaningful positive, negative, platform and real-SDK cases.
23
+
22
24
  When time/timezone, randomness/IDs, ordering, shared state, filesystem, or network can affect the evidence, control only the relevant sources with isolated temporary fixtures and cleanup; keep expected-error assertions narrow and unexpected output visible.
23
25
 
24
26
  Make one explicit testing decision:
@@ -23,7 +23,7 @@ Spend disproportionate effort here. **Be aggressive. Be creative. Refuse to give
23
23
 
24
24
  ### Ways to construct one — try them in roughly this order
25
25
 
26
- Inspect the project's existing runner, fixtures, helpers and diagnostic commands first. Reuse the closest suitable harness; the options below are not an instruction to build a second testing stack. Apply `lean-code`'s diagnostic tooling policy before adding or retaining tooling.
26
+ Inspect the project's existing runner, fixtures, helpers and diagnostic commands first. Reuse the closest suitable harness; the options below are not an instruction to build a second testing stack. Apply [Lean Code's diagnostic tooling policy](../lean-code/SKILL.md#diagnostic-tooling) before adding or retaining tooling.
27
27
 
28
28
  1. **Failing test** at whatever seam reaches the bug — unit, integration, e2e.
29
29
  2. **Curl / HTTP script** against a running dev server.
@@ -62,7 +62,7 @@ Prefer the narrowest change that solves the real need.
62
62
 
63
63
  ### Diagnostic tooling
64
64
 
65
- Reuse the project's runner, fixtures, helpers and existing diagnostic commands before building a harness. New probes, replay scripts and diagnostic harnesses are temporary by default, with explicit resource ownership and automatic teardown arranged before execution. Keep tooling only for a concrete recurring need: identify its consumer, why the existing harness cannot cover it, and who maintains it in the current task or PR. A successful one-off investigation alone does not justify a permanent command, framework or dependency. Preserve the authoritative regression test and compact reproduction evidence, not the disposable environment.
65
+ Reuse the project's runner, fixtures, helpers and existing diagnostic commands before building a harness. New probes, replay scripts and diagnostic harnesses are temporary by default, with explicit resource ownership and automatic teardown arranged before execution. Keep tooling only for a concrete recurring need within the approved scope: identify its consumer, why the existing harness cannot cover it, and who maintains it in the current task or PR. Seek approval if retaining it expands the scope. A successful one-off investigation alone does not justify a permanent command, framework or dependency. Preserve the authoritative regression test and compact reproduction evidence, not the disposable environment; do not remove meaningful permission, concurrency or deletion protection just to shrink the diff.
66
66
 
67
67
  ### Review / simplification
68
68
 
@@ -29,7 +29,7 @@ The solution to the problem, from the user's perspective.
29
29
 
30
30
  ## User Stories
31
31
 
32
- A LONG, numbered list of user stories. Each user story should be in the format of:
32
+ A numbered list of user stories proportional to the approved scope. Each user story should be in the format of:
33
33
 
34
34
  1. As an <actor>, I want a <feature>, so that <benefit>
35
35
 
@@ -37,7 +37,7 @@ A LONG, numbered list of user stories. Each user story should be in the format o
37
37
  1. As a mobile bank customer, I want to see balance on my accounts, so that I can make better informed decisions about my spending
38
38
  </user-story-example>
39
39
 
40
- This list of user stories should be extremely extensive and cover all aspects of the feature.
40
+ Include only the actors, behaviors and relevant boundary cases supported by the context. Do not invent speculative requirements or pad the list to meet a length target. A small feature may need only one story.
41
41
 
42
42
  ## Clarifications
43
43
 
@@ -33,7 +33,7 @@ Check:
33
33
  3. Every SC is verifiable and has task coverage in the plan table.
34
34
  4. Every formal task resolves and verifies its declared `Spec` reference, task identity and access before execution. An identity mismatch, missing source or absent access is a blocking `gaps` verdict; never reconstruct a missing spec from the PRD.
35
35
  5. Every task references known SCs and has one agent, one bounded scope, affected files, dependencies and a wave consistent with those dependencies.
36
- 6. Each behavior-changing task has a complete testing decision: risk, existing protection, new behavior, chosen seam and action.
36
+ 6. Each behavior-changing task has a complete testing decision: risk, existing protection, new behavior, chosen seam and action. Apply the testing value check below to the proposed protection.
37
37
  7. PR scopes, bases and ordering are compatible with the task dependencies.
38
38
  8. PRD, plan and task specs do not contradict each other or duplicate status/evidence into a second home.
39
39
 
@@ -53,7 +53,7 @@ Check:
53
53
  3. Every in-scope SC has concrete evidence in its canonical checkpoint: command/setup, scope, result and relevant limits.
54
54
  4. The implementation diff and observed behavior stay within the approved PRD, plan and task scopes.
55
55
  - POST cannot legitimize scope changes retroactively. For intentional material contract changes, send scope drift to SPEC through change-first. Defects or bugfixes restoring the approved contract return to EXECUTE.
56
- 5. Tests, typecheck/build, manual checks and external gates are not over-claimed; missing or incomplete execution remains explicit.
56
+ 5. Tests, typecheck/build, manual checks and external gates are not over-claimed; missing or incomplete execution remains explicit. Apply the testing value check below to the implemented protection and actual evidence.
57
57
  6. No accepted requirement, edge case, testing decision, documentation change or cross-repo contract assigned to the current checkpoint is left without implementation or evidence. Future checkpoints remain out of scope.
58
58
 
59
59
  POST verdicts:
@@ -61,6 +61,16 @@ POST verdicts:
61
61
  - `converged` — the available evidence satisfies the approved contract. This does not replace tests, human review, configured Quality Gates or manual validation when applicable.
62
62
  - `gaps` — return actionable findings to the orchestrator and route each to its owning phase; never send every gap unconditionally to EXECUTE. Rerun POST after the fix.
63
63
 
64
+ ## Testing value check — PRE and POST
65
+
66
+ For each added or strengthened test, ask: "What concrete regression does this test detect that existing coverage does not?" PRE checks the proposed answer; POST checks that the actual assertions and evidence support it. Another layer must protect a distinct contract, not repeat the same behavior.
67
+
68
+ For a mechanical test update, `reuse` or `no new test`, check the identified existing protection or other verification and why it is sufficient. Do not demand a new test, extra coverage or a manufactured RED when the risk is already covered.
69
+
70
+ A RED for behavioral protection must fail because the asserted behavior is wrong or missing, not merely because a source string is absent. Structural assertions are valid when structure is itself the contract, such as triggers, permissions, secret handling or suite registration; distinguish that guarantee from runtime behavior and avoid freezing an incidental command recipe, internal ordering or full implementation.
71
+
72
+ Keep this check within the checkpoint's changed behavior and relevant coverage; do not turn it into a suite-wide audit.
73
+
64
74
  ## Read-only boundary
65
75
 
66
76
  - Do not write, edit or modify the PRD, plan, task specs, memory, code, tests, checkboxes or PR state.
@@ -76,7 +76,8 @@ Every formal task has exactly one recoverable `Spec` reference in the plan table
76
76
  | 03 | 02 | [agent] | [bounded scope] | [one declared source] | [descriptive name] | [one-line description] | SC-01 | ⬜ | 2 | 01 |
77
77
  | 04 | 02 | [agent] | [bounded scope] | [one declared source] | [descriptive name] | [one-line description] | SC-02 | ⬜ | 2 | 01, 02 |
78
78
 
79
- **Statuses**: ⬜ Pending → 🔴 RED → 🟢 GREEN → 🔍 Review → ✅ Done
79
+ **Statuses**: ⬜ Pending → In progress → Verified → 🔍 Review → ✅ Done
80
+ For test-first work that adds or strengthens protection, use 🔴 RED → 🟢 GREEN within In progress. Tasks using `reuse` or `no new test` proceed with their chosen verification; do not require a new failing test to advance.
80
81
  ```
81
82
 
82
83
  ---
@@ -111,7 +112,7 @@ Use this adaptable content in the one source declared by the plan's `Spec` colum
111
112
  - **Existing protection**: [specific existing test/evidence, or none]
112
113
  - **New behavior**: [behavior needing new protection, or none]
113
114
  - **Chosen seam**: [closest authoritative seam and why]
114
- - **Action**: [add | update | reuse | no new test] — [concrete reason]
115
+ - **Action**: [add | update | reuse | no new test] — [for new or stronger protection, the concrete regression existing coverage misses; for a mechanical test update, reuse or no new test, why existing protection or other verification is sufficient]
115
116
  ```
116
117
 
117
118
  Use only the headings and fields that are pertinent, except retain the complete testing decision when the task changes behavior. Do not require literal code, input/output blocks or empty heading, section or field. Existing Engram task observations remain compatible; adapt this template only for newly created or materially revised specs.
@@ -137,11 +138,11 @@ Mutation is serialized: the coordinator is the single writer, reads the exact ob
137
138
 
138
139
  ### Atomicity
139
140
 
140
- - **Max ~5 implementation steps** per task. If more → split into two tasks.
141
+ - Bound each task by an independently verifiable behavior or contract and its concrete regression risk. Keep the layers needed for that outcome together; split when outcomes can be verified independently or coupling and risk warrant it, not at a fixed step count.
141
142
 
142
143
  ### Structure
143
144
 
144
- - **Natural order**: data layer → generated types → services/hooks → components/UI.
145
+ - **Vertical slices**: organize tasks by behavior and risk, not by technical layer. Sequence implementation within a task by its real dependencies; data, types, services and UI are not mandatory separate tasks.
145
146
  - **Numbering**: `01`, `02`, `03`... (two digits) — shared by the plan table row and the topic_key.
146
147
 
147
148
  ### Context
@@ -154,7 +155,7 @@ Mutation is serialized: the coordinator is the single writer, reads the exact ob
154
155
 
155
156
  - **VERIFIABLE**: "the type includes X", not "the type is correct".
156
157
  - **SPECIFIC**: no copy-paste of generic criteria.
157
- - **COMPLETE**: cover happy path, edge cases and errors.
158
+ - **COMPLETE**: cover the relevant happy path, boundary cases and errors for the approved contract and concrete risk; do not manufacture speculative scenarios.
158
159
 
159
160
  ### Constraints
160
161