jorgex-stack 1.9.70 → 1.9.72

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.70",
3
+ "version": "1.9.72",
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",
@@ -31,10 +31,10 @@ You fix comments directly instead of reporting suggestions: trivial comment work
31
31
 
32
32
  1. **Factual accuracy**: comments that no longer match what the code does → correct them.
33
33
  2. **Worthless comments**: comments that restate obvious code → remove them.
34
- 3. **Missing critical context**: an undocumented assumption or non-obvious "why" worth one line → add it.
34
+ 3. **Missing critical context**: a verified, undocumented assumption or non-obvious "why" needed to use or change the code safely → add it.
35
35
  4. **Misleading elements**: wording that could be misread → clarify.
36
36
 
37
- Match the project's comment conventions: density, language, format. When in doubt, fewer comments — explain why, not what.
37
+ Apply the shared system prompt's **Code comments** policy; follow local language and format, not density. Leave comments that already provide useful, accurate context untouched; cleanup is not a quota or a requirement to produce edits. Do not edit docstrings used as runtime metadata within this comments-only scope: report necessary contract changes to their owner.
38
38
 
39
39
  ## Output format
40
40
 
@@ -23,6 +23,8 @@ 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.
27
+
26
28
  1. **Failing test** at whatever seam reaches the bug — unit, integration, e2e.
27
29
  2. **Curl / HTTP script** against a running dev server.
28
30
  3. **CLI invocation** with a fixture input, diffing stdout against a known-good snapshot.
@@ -38,7 +40,7 @@ Build the right feedback loop, and the bug is 90% fixed.
38
40
 
39
41
  ### Tighten the loop
40
42
 
41
- Treat the loop as a product. Once you have _a_ loop, **tighten it**:
43
+ Tighten the loop for this investigation, not into a permanent product:
42
44
 
43
45
  - Can I make it faster? (Cache setup, skip unrelated init, narrow the test scope.)
44
46
  - Can I make the signal sharper? (Assert on the specific symptom, not "didn't crash".)
@@ -134,7 +136,9 @@ Required before declaring done:
134
136
  - [ ] Original repro no longer reproduces (re-run the Phase 1 loop)
135
137
  - [ ] Regression test passes (or absence of seam is documented)
136
138
  - [ ] All `[DEBUG-...]` instrumentation removed (`grep` the prefix)
137
- - [ ] Throwaway prototypes deleted (or moved to a clearly-marked debug location)
139
+ - [ ] Throwaway probes, scripts, harnesses and their owned resources cleaned up; moving them to a debug folder is not cleanup. Retain tooling only when the recurring need, consumer, harness gap and maintenance owner are justified under `lean-code`; preserve the regression test.
138
140
  - [ ] The hypothesis that turned out correct is stated in the commit / PR message — so the next debugger learns
139
141
 
142
+ Keep compact, redacted, reproducible evidence in the existing task or PR: exact command, relevant environment/version and fixture or seed, observed failure and post-fix result. Distinguish verified observations from hypotheses. Preserve the first failure and any necessary diagnostic artifact when it carries unique evidence; do not retain full dumps or disposable environments by default. Report cleanup that could not safely finish.
143
+
140
144
  **Then ask: what would have prevented this bug?** If the answer involves architectural change (no good test seam, tangled callers, hidden coupling) hand off to the `/improve-codebase-architecture` skill with the specifics. Make the recommendation **after** the fix is in, not before — you have more information now than when you started.
@@ -60,6 +60,10 @@ Do not add a new dependency unless the task explicitly requires it or the projec
60
60
  Before adding a new helper, wrapper, abstraction, or dependency, run the ladder again.
61
61
  Prefer the narrowest change that solves the real need.
62
62
 
63
+ ### Diagnostic tooling
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.
66
+
63
67
  ### Review / simplification
64
68
 
65
69
  Use it as a bloat filter: delete, stdlib, native/platform, reuse, or shrink.
@@ -275,7 +275,9 @@ async def get_user(user_id: str) -> Dict[str, Any]:
275
275
 
276
276
  ## Tool Docstrings
277
277
 
278
- Every tool must have comprehensive docstrings with explicit type information:
278
+ Every tool needs a concise docstring describing the contract clients need: purpose, non-obvious input constraints, output shape, side effects and relevant errors. Preserve information used to generate MCP descriptions or schemas; these docstrings are runtime metadata, not merely code comments. Do not repeat types or field descriptions already exposed by the generated schema unless needed to disambiguate behavior. Document dict/JSON return structure when it is not exposed by an output schema.
279
+
280
+ The example below illustrates possible contract details, not mandatory sections for every tool:
279
281
 
280
282
  ```python
281
283
  async def search_users(params: UserSearchInput) -> str:
@@ -419,7 +421,7 @@ def _handle_api_error(e: Exception) -> str:
419
421
  async def example_search_users(params: UserSearchInput) -> str:
420
422
  '''Search for users in the Example system by name, email, or team.
421
423
 
422
- [Full docstring as shown above]
424
+ [Concise tool contract docstring]
423
425
  '''
424
426
  try:
425
427
  # Make API request using validated parameters
@@ -692,8 +694,8 @@ Before finalizing your Python MCP server implementation, ensure:
692
694
  - [ ] Annotations correctly set (readOnlyHint, destructiveHint, idempotentHint, openWorldHint)
693
695
  - [ ] All tools use Pydantic BaseModel for input validation with Field() definitions
694
696
  - [ ] All Pydantic Fields have explicit types and descriptions with constraints
695
- - [ ] All tools have comprehensive docstrings with explicit input/output types
696
- - [ ] Docstrings include complete schema structure for dict/JSON returns
697
+ - [ ] All tools expose concise, sufficient contract descriptions without duplicating generated schema information
698
+ - [ ] Dict/JSON return structure is exposed through an output schema or documented when no schema is exposed
697
699
  - [ ] Pydantic models handle input validation (no manual validation needed)
698
700
 
699
701
  ### Advanced Features (where applicable)
@@ -716,4 +718,4 @@ Before finalizing your Python MCP server implementation, ensure:
716
718
  - [ ] Server runs successfully: `python your_server.py --help`
717
719
  - [ ] All imports resolve correctly
718
720
  - [ ] Sample tool calls work as expected
719
- - [ ] Error scenarios handled gracefully
721
+ - [ ] Error scenarios handled gracefully
@@ -54,13 +54,13 @@ For a manual xreview without an explicit work context, continue without PRD/plan
54
54
 
55
55
  ## 4. Comment pass FIRST (conditional)
56
56
 
57
- If the diff adds or changes comments/docstrings, run `comment-fixer` ALONE before the analysts — it edits comments in place (comments only, never code), so the analysts then review a diff already clean of comment noise instead of re-reporting it or mistaking its edits for contamination.
57
+ Inspect relevant comment/docstring hunks first. Run `comment-fixer` ALONE before the analysts when source-code comments/docstrings need an accuracy, usefulness or critical-context pass under the shared system prompt's **Code comments** policy. It already owns comment cleanup; do not add a separate cleanup agent. Instruction prose, documentation pages and illustrative code fences alone do not trigger this pass. It edits comments in place (comments only, never code), so analysts review the resulting working state rather than mistaking its edits for contamination.
58
58
 
59
59
  - Pass the frozen refs or working-state identity and the relevant comment/docstring scope.
60
60
  - When the orchestrator supplied one, pass it the same exact work context path as every other review subagent.
61
61
  - If it changed anything and the scope is a committed diff (branch/PR): comment-fixer itself never commits — YOU commit its fixes before launching reviewers, staging ONLY its files (never `-a`/`-A`). Then freeze the new candidate SHA and refresh scopes. If a commit cannot be made, report the uncommitted state; it cannot certify the committed candidate.
62
62
  - For working-tree reviews: leave its edits uncommitted (they join the user's pending work) and say so in the report.
63
- - If the diff touches no comments, skip it and move on.
63
+ - If no comment pass is needed, skip it and state why. A pass that leaves all comments unchanged is valid.
64
64
 
65
65
  ## 5. Launch the remaining subagents in PARALLEL
66
66
 
@@ -26,6 +26,10 @@ Ask questions when something isn't clear instead of assuming it's correct.
26
26
  - Do not add dependencies without explicit user approval.
27
27
  - Run lint and typecheck after significant changes when available.
28
28
 
29
+ ### Code comments
30
+
31
+ Add comments only when they carry information the code does not make clear: a non-obvious reason, invariant, constraint or operational hazard. Do not narrate obvious code, mirror existing comment density, or add comments just because a function or test is new. Preserve contractual documentation, legal notices, directives, and critical security, concurrency or deletion context; docstrings used as runtime metadata are part of the contract, not disposable prose. Follow local language and format, without line-count or density quotas. Leaving already-clear code uncommented is valid.
32
+
29
33
  ---
30
34
 
31
35
  ## Default Architecture