MicroVM SDK agent: events file EPERM
An SDK agent run on a MicroVM node fails in the guest. Python and TS SDK agents run to `done` on static nodes (5909 AC-2/AC-3), so this gap is MicroVM only. It blocks the epic's "a tenant's SDK agent runs on the runner" on MicroVM nodes.
**Reproduction (task 5909, dev):** dev tasks 4971 and 4963 picked the Report sample agent on MicroVM node vn5862b. Dispatch and binding work after #5193. The agent then dies with `PermissionError [Errno 1] ... /jaah/report/agent-events.jsonl`.
**Cause (from reading the code; confirm on a live guest with `id -u; id -g` as `jaah` and `stat` on the file):**
- apps/jaahd/microvmd.py:405-417: virtiofsd maps only guest uid 1000 and gid 1000 (`--uid-map=:1000:<daemon uid>:1:`, `--gid-map=:1000:<daemon gid>:1:`).
- apps/jaahd/microvm_seed.py:190-192: the cloud-init `users` entry for `jaah` sets the uid and groups but no primary gid of 1000. A file the guest creates under any other gid is refused on the share.
- apps/jaahd/vendor/agent-sdk/python/jaah_agent/_events.py:19-38: `EventsFile.write` opens `O_CREAT|O_APPEND`, mode 0600, with no OSError handling, so the error kills the agent. The supervisor's writer handles it (tools/jaah_agent_run.py:126-149).
- apps/jaahd/microvm_session.py:622-623 and :804: the host creates report/ as 0700, and the guest events path is `/jaah/report/agent-events.jsonl`.
**Fix:**
1. Pin the guest `jaah` user's primary group to gid 1000 in microvm_seed.py so every file it creates maps through `--gid-map`.
- If the live check shows a different cause, fix that cause instead and record it.
2. In agent-sdk upstream, make the SDK events writer survive an OSError by logging to stderr, as the supervisor does. Also create the file 0640 rather than 0600 (5909 F5). Re-vendor with tools/sync_agent_sdk.py.
3. Add the cross-side contract test from 5909 F8: feed the CP's VM agent launch payload (apps/api/app/microvm_placement.py) into apps/jaahd's agent launch-file builder, so a payload mismatch like the one #5193 fixed fails in CI.
Out of scope: static-node SDK runs, built-in providers' MicroVM sessions (filed separately), and any change to virtiofsd's uid mapping beyond the gid fix.
Done means:
- On dev, a task picking the Report sample on a MicroVM node goes `ready → active → done`, with its report artifact on the task and its sdk_agent session downloadable in Audit > Sessions. Cite the dev task id and a screenshot.
- A unit test asserts the guest user's primary gid is 1000 in the generated user-data.
- A unit test shows the SDK writer survives an unwritable events path.
- The contract test exists and passes.
- `env -u JAAH_PROJECT_MEMORY ./dc check full` is green, the PR is merged to develop, and Jaah Deploy to dev is green.
Outcome
MicroVM SDK agent fixed: guest gid 1000 + recipe-keyed base (#5209), SDK v0.1.1 writer (agent-sdk#2), session end + kept transcript (#5220). Dev task 4994 done, session uploaded. Full gate green, deploys green. Follow-ups in report.
Artifacts
Activity
- Ready
- Runner started
- Runner ended (done)