# @stravica-ai/engineering-pa-migrate-inspect

**Status:** v0.1.0 — active

Host-inspection CLI for migration planning. Produces a structured `inspection.json` describing migration-relevant host state: layout version, runtimes, scheduled tasks, mounts, Dave environment variables, and operator extensions.

## Install / Invoke

### As a `pa` verb (recommended)

```
pa migrate-inspect [options]
```

### As a standalone binary (after pnpm install)

```
migrate-inspect [options]
```

## Commands

| Option | Type | Default | Description |
|---|---|---|---|
| `--out <path>` | string | stdout | Write inspection.json to file |
| `--dave-root <path>` | string | `DAVE_ROOT` or `PA_REPO_ROOT` env | Override Dave root path |
| `--pretty` | boolean | false | Pretty-print JSON output |
| `-h, --help` | — | — | Show help |

### Examples

```bash
# Inspect current host, print to stdout
pa migrate-inspect

# Inspect with explicit Dave root, write to file
pa migrate-inspect --dave-root /home/user/dave --out /tmp/inspect.json

# Pretty-print for human review
pa migrate-inspect --pretty
```

## Exit codes

| Code | Meaning |
|---|---|
| 0 | OK |
| 1 | Usage error |
| 2 | Operational failure |
| 3 | Transport/IO failure |

## Operational discipline

- **Read-only**: this tool never modifies any file except the output file specified by `--out`. It makes no changes to the Dave installation or host configuration.
- **No writes outside log dir**: the only file written is the one explicitly specified by `--out`.
- **No external deps**: uses Node stdlib only (`node:child_process`, `node:fs/promises`, `node:os`, `node:util`, `node:path`).
- **Platform-guarded**: on Linux, `launchdPlists` is always `[]`; `~/Library/LaunchAgents` is never read.

## Output shape

```json
{
  "host": {
    "hostname": "string",
    "os": "darwin | linux | ...",
    "osVersion": "string",
    "arch": "arm64 | x64 | ..."
  },
  "runtimes": {
    "nodeVersion": "24.0.0",
    "pnpmVersion": "10.0.0",
    "gitVersion": "2.40.0"
  },
  "scheduled": {
    "crontab": [{ "schedule": "* * * * *", "command": "..." }],
    "launchdPlists": [{ "label": "...", "program": "...", "args": [], "workingDirectory": "...", "runAtLoad": true, "keepAlive": true }]
  },
  "mounts": [{ "source": "//server/share", "target": "/mnt/share", "fsType": "smbfs" }],
  "daveEnv": {
    "daveRoot": "/path/to/dave",
    "daveRelevantEnvVars": { "DAVE_ROOT": "/path/to/dave" },
    "pathSegments": ["/path/to/dave/node_modules/.bin"]
  },
  "paths": {
    "daveRoot": "/path/to/dave",
    "coreToolsPath": "/path/to/dave/core/tools",
    "operatorPath": "/path/to/dave/operator",
    "layoutVersion": "v1 | v2 | unknown"
  },
  "extensions": [{ "name": "my-ext", "path": "/path/to/dave/operator/extensions/tools/my-ext", "hasManifestEntry": true }],
  "inspectedAt": "2026-05-17T12:00:00.000Z"
}
```

## Project layout

```
packages/cli/migrate-inspect/
  bin/migrate-inspect          shebang shim
  package.json
  src/
    cli.mjs                    arg parsing + exit-code translation
    inspector.mjs              orchestrates platform modules
    platforms/
      macos.mjs                macOS-specific collectors
      linux.mjs                Linux-specific collectors
    runner.mjs                 CHOKEPOINT: all spawns happen here
  test/
    fixtures/
      fake-dave-v1/            minimal v1 fixture tree
      fake-dave-v2/            minimal v2 fixture tree
    cli.test.mjs
    inspector.test.mjs
    runner.test.mjs
```

## Tests

```bash
pnpm --filter @stravica-ai/engineering-pa-migrate-inspect test
# or
node --test 'test/**/*.test.mjs'
```

## Tooling standard reference

- Chokepoint pattern: all subprocess spawning is in `runner.mjs` — never elsewhere.
- No shell interpolation: `spawnCapture` always receives `cmd` and `args` as separate arguments.
- No external npm deps: Node stdlib only.
- `node:test` + `node:assert/strict` for tests.
- Exit codes follow tooling standard §6.
