AGENTS.md@packages/craft-apps/src · git:20261014.bf59830 · 2026-10-14 · sha256 193888c46a31a1df
AGENTS.md@packages/craft-apps/src git:20261014.bf59830A
Immutable. This exact content never changes and is served at /api/v1/blob/193888c46a31a1df.
# DOX — packages/craft-apps/src
Files in this directory. One row per source file.
| File | Purpose |
|------|---------|
| `app-command.ts` | `runAppCommand(app, command, rest, ctx)` shared by `pi-craft <app> …` and the `pi-photocraft` alias: `ensure`/`path` (provision, JSON report / path, exit 69), `exec` (`execPassthrough`: verbatim argv, inherited stdio, exit code propagated), `mcp` (`--register [--allow-unconfined] [--compact]` → `registerMcp`, else `runMcp`). `AppCommandContext` carries prog, usage, register launcher/args. See change: add-craft-apps-core. |
| `command-ids.ts` | `extractCommandIds(text)`: ids from a JSON command/tool list (`id`/`name`/`aliases`) or a text table. Shared by `scripts/record-fixtures.mjs` and the nightly drift test. |
| `launcher-install.ts` | `pi-craft launcher install`: `installerAsset` (dmg / msi / AppImage, `artcraft-launcher-<v>-<host>`), `installLauncher` (latest `storytold/craft-launcher` release → `downloadVerified` fail-closed → OS hand-off `open`/`msiexec`/chmod), `launcherStatus`. Only code that fetches a desktop installer. |
| `launcher.ts` | Craft Launcher *source*: `launcherRoots` (per OS, `CRAFT_LAUNCHER_HOME`), `launcherAppState`, `launcherBinary` → CLI path or reason. Probe 0.3: launcher installs desktop bundles with no CLI (macOS), so it reports "desktop app only". Never downloads. |
| `mcp-proxy.ts` | `runMcp(app, argv, deps)`: unconfined app refuses without `--allow-unconfined`; provision → spawn `<app>-cli mcp` with `--automation-read-root R --automation-write-root R` (`--root R` for PdfCraft; none when unconfined) + optional `--compact`. Line-based JSON-RPC proxy: `tools/call` FIFO, one in flight, released on matching response `id`; non-JSON server stdout → stderr; SIGINT/SIGTERM → exit 130/143; provisioning failure → exit 69, stdout untouched. Rejects `--bridge/--connect/--control-token/--automation-*-root`. `parseMcpArgs`, `mcpUsage`. `notifications/cancelled`: queued call dropped; in-flight slot released after `CANCEL_GRACE_MS`. See change: add-photocraft-plugin, add-craft-apps-core. |
| `mcp-register.ts` | `registerMcp(app, deps)`: read-modify-write `.pi/mcp.json` `mcpServers["craft-<app>"]` (`photocraft` for PhotoCraft) = `{command: execPath, args: [launcher, <app>, "mcp", …flags]}`; unconfined app needs `allowUnconfined` (persisted as `--allow-unconfined`); large app prints tool count + bash/`--compact` advice; malformed file untouched, exit 1. `serverName`, `defaultLauncherPath(name)`. |
| `provision.ts` | `provision(appOrId, deps)`: `<APP>_BIN` → `CRAFT_SOURCE` (`launcher`/`auto` via `launcherBinary`, never downloads) → pin `<APP>_VERSION` → latest (24 h `latest.json`; fallback highest installed) → host→asset candidates from the registry (CLI-only before portable; per-app glibc gate) → `downloadVerified` (`SHA256SUMS.txt` fail-closed, streamed digest) → listing guard (`assertSafeListing`) → extract (`ditto`/`tar`) in `.staging-*` → `locateBinary` → chmod, delete desktop exe, asset marker → atomic rename to `<CRAFT_HOME>/<app>/<version>/` (`PHOTOCRAFT_HOME` for PhotoCraft). `ProvisionError` (exit 69). All effects injectable (`ProvisionDeps`). See change: add-craft-apps-core. |
| `region-replace.ts` | `replace-region` (PhotoCraft only): `parseReplaceArgs`/`REPLACE_USAGE`, geometry (`computeCrop`, `computeMask`, rect helpers), `buildCompositeArgs`, `makeGenerator` + `resolveNanoBananaLauncher`, `replaceRegion` pipeline (info → probe → crop → generate → resize → composite → convert → `commitOutputs`: stage, back up, rename, roll back on failure). Same-file check by dev+inode. Temp under `os.tmpdir()`. |
| `registry.ts` | Typed readonly table of the 13 apps (`CRAFT_APPS`): id, name, purpose, repo `storytold/<id>`, cli, per-host asset templates (`{v}`), CLI dialect (list/describe/run hints), MCP policy (`confinement` false/`automation-roots`/`root`, `compactFlag`, tool class + count, bridge flag), `glibcMin`. `getApp`, `isAppId`, `envPrefix`, `binName`, `desktopName`, `hostKey`, `UnknownAppError`. Values from probes 0.1–0.5. |
| `status.ts` | `appStatus(app, deps)` for `pi-craft status`: installed versions, cache bytes, what would be used (override/pin/latest-cached/download), source. Reads the cache only; never downloads. |
| `verify.ts` | `pi-craft verify`: `parseVerifyArgs`, `runVerify` — duration/streams/size/fps/codec/alpha (ffprobe), loudness/peak/silence (ffmpeg ebur128/volumedetect), `--frame-diff` (luma > 40/255 share), PDF `--pages`/`--text-contains` via provisioned pdfcraft. Text/JSON report; exit 0 pass / 1 fail or missing file / 2 usage / 3 probe tool missing. argv-only spawning via `platform/exec`. |