{"number":7,"title":"Contract 0.6: performance metrics (GET/POST /perf) and /status.capabilities (#6)","body":"Closes #6.\n\n**Contract 0.6: performance metrics.** It's additive: older clients and servers are unaffected.\n\n- **`GET /perf[?windows=][&zones=][&frames=][&since=]`:** how much of each frame the program uses, in guest CPU cycles.\n  - `budget`, the frame and its budget;\n  - `current`, the last completed frame: total, work, idle, IRQ and main cycles, instructions, host µs and utilisation;\n  - `windows`, with min/mean/p50/p95/p99/max and overruns;\n  - `zones`, address ranges or regions the guest marks, each with its own windows;\n  - `frames`, raw records: the last n, or every frame `since` one, so a polling harness misses none;\n  - `platform`, for the rest.\n- **`POST /perf`:** a JSON settings body: enabled, targetFps, idleMode, historyFrames, reset, and zones (an address range, or `{name, marker}` naming a guest marker region). A bad body is a 400.\n- **`/status.capabilities`:** the endpoint groups a server serves, whatever level it reaches, so a client can ask for `perf` (or `pointer`) directly. `contract` stays cumulative.\n- **Core:** `get_perf` and `set_perf` callbacks return allocated JSON the core frees, so the core stays platform-neutral. They're marshalled to the emulator thread like `/mem`. A NULL callback gives a 501 and lowers the level.\n- **Also:** a client (`perf`, `perf_config`, `capabilities`), five conformance tests gated on 0.6, a CHANGELOG entry, and the README and SPEC. The SPEC's X16 appendix documents the `$9FBC` markers and the X16 `platform` section (VERA bus per scanline, sprite render time).\n\n**Tested:** the whole conformance suite, **27 of 27**, against the first 0.6 backend, the enhanced X16 emulator (enhanced-x16-emulator #1), launched with `RRDC_EMU_CMD`. The core builds clean with `-Wall -Wextra`.\n\n**Used by:** Metal Gear's harness reads `/perf` to profile the game by phase (metalgear #261).","author":"andymccall","state":"landed","target":"main","source":{"kind":"bookmark","bookmark":"perf-6"},"changes":[{"hash":"8fd33bc520f976b333697dc16f9a615f07227a1534df9906e0932cc843987274","message":"feat: contract 0.6 — GET/POST /perf, the performance metrics (budget, current frame, windows, zones, raw frames since one, a platform section) and their settings, and /status.capabilities; backend callbacks get_perf and set_perf return allocated JSON (#6)","author":{"name":"Andy McCall","email":"mailme@andymccall.co.uk","key":"8bc05e0a32a86508708a7dffa1fdccee1f6601e8c8395275244a6c48a9684c8c","account":null,"note":"signed by a key not linked to any account; its owner links it under Settings → Keys (/settings/keys)"},"when_ms":1791663672124,"deps":["346ca3ee83f41f9495ac5380a55fe6fac1fa0369c3535942913f89d75c1f9f32","398756c0e9b2f3532c7c81dd2fb3be39d579b1b0528363a3f5faf7c14b21ebd0","4c0b050e9a255596eb36b5d40e9ad07da4a9e0a3f8827cf139b9ee8cf9bfc591","674b8447022b15ee7aadad64b89f986e06b7907163d93ba3eab8852da46cbb5a","689a9ccb013881493fa1b09406534311c6ee763e20f85a90e9edc9937aca1cc6","8ac19619e24b6fcb349832849eafdce5a7bee67d1b2d3de35b233ba629b39b1d","961b3c610c66fcdfa5dbc05198d7be5e99f87d35b15d2107e243c879a5a7e129","bed0f1e524fef708c855791a30d54b455bbe957f85f87cf0879a8cf3ff44287e","d44319b1e712ffc17c3b35abeba39046ba94fe6a5336d7b91065ac35b7dfa631"],"head":false,"signature":{"status":"valid","key":"8bc05e0a32a86508708a7dffa1fdccee1f6601e8c8395275244a6c48a9684c8c","sealed":false,"revoked":false}}],"projected_heads":["1b40a077e41ff99aea0d342250dd4b6891315a4150ffcda2edfa7538c4f64e48","3bf01e6e95ae465b33c4034797e0a4fd662cd2be41eb4e8b6fcf2ddc46ac4d81","3de55cb796cd1369d9bde38fd34d1c3a6d5429c2cd2e026d87e19fcb4a10b9e9","45a475bb3fa8e59f7556e9dbf6f58c6625d6d6304ecf8aaabce9eb929b50d8e2","5a9d638a8939973279d4d9242a8b78446dd7cf0226c68a1288438515c73d1fb8","69f777699a51a32488de73712a46a06bcb392a6e1f12896d385bd4b3b44b3884","724e0ab8c620aad822d4240d270e6cd32c71b1a487bb0eb879ae687c7d1282ff","79333fa1febe9028d3120778337b471dca2cb7acc8a49a50283c6040dfc30d49","7c83b415d7cccc720775586617f9af01f0dcb25908ef823cc3d234499b904b45","8fd33bc520f976b333697dc16f9a615f07227a1534df9906e0932cc843987274","d69f9ef6bbac3b168c188ce376da854b72d9244aea5acdfac486b67e6748d7ab","e1cff618586ada12b9e7d8c8b9a9293e8ed6b7d5c6449bbd4198cf5074ca48c0","e60badb602fbbcd6e49e1813cf72fd10079d85b79ec43f4ca50d2c075d750f58","f2dd3b3ac5ad17900cf9b2c25837096ae97c3039f997a8d2a63fac9405addcd9"],"projected_state":"fa9570b9a62220d5061c46184f0b9276abe7121113761a6e3c7cdce98ee01e87","conflicted":false,"approvals":[],"landable":false,"blockers":[],"created_ms":1791666508926,"updated_ms":1791667675086,"url":"https://oxygenhub.io/doomsdayone/retro-remote-debug-controller/proposal/7","repository_url":"https://oxygenhub.io/doomsdayone/retro-remote-debug-controller","source_url":null,"landed":{"by":"andymccall","via":"web","when_ms":1791667675086},"auto_land":null,"requested_reviewers":[],"labels":[{"name":"enhancement","colour":"#a2eeef","description":"New feature or request"}]}