Payload
{
"action": "submitted",
"review": {
"id": 4731486516,
"node_id": "PRR_kwDOSB6EzM8AAAABGgTBNA",
"user": {
"login": "darkmatter[bot]",
"id": 283346107,
"node_id": "BOT_kgDOEOOEuw",
"avatar_url": "https://avatars.githubusercontent.com/in/3663660?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/darkmatter%5Bbot%5D",
"html_url": "https://github.com/apps/darkmatter",
"followers_url": "https://api.github.com/users/darkmatter%5Bbot%5D/followers",
"following_url": "https://api.github.com/users/darkmatter%5Bbot%5D/following{/other_user}",
"gists_url": "https://api.github.com/users/darkmatter%5Bbot%5D/gists{/gist_id}",
"starred_url": "https://api.github.com/users/darkmatter%5Bbot%5D/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/darkmatter%5Bbot%5D/subscriptions",
"organizations_url": "https://api.github.com/users/darkmatter%5Bbot%5D/orgs",
"repos_url": "https://api.github.com/users/darkmatter%5Bbot%5D/repos",
"events_url": "https://api.github.com/users/darkmatter%5Bbot%5D/events{/privacy}",
"received_events_url": "https://api.github.com/users/darkmatter%5Bbot%5D/received_events",
"type": "Bot",
"user_view_type": "public",
"site_admin": false
},
"body": "## Review: streaming responses + build output live\n\nThis is a strong, well-tested implementation. The hardest pieces are handled carefully: NDJSON byte-safe framing, surrogate-pair-aware incremental thought decoding, a single ordered transcript writer with a flush barrier, coalesced ViewModel state, and a narrow streaming-rejection classifier that won't double a billable request. The experimental flag gating and the per-iteration teardown wrapper in `run_evolve` are the right shape. Below are the issues I think are worth addressing before this stops being dev-flagged, ordered by impact.\n\n### Bugs / correctness\n\n1. **OpenAI streamed tool-call announcement can fire on later chunks.** `openai.rs:333` announces when `tool_chunk.id.is_some() && !name.is_empty()`. Per the SSE spec the `id` and `name` arrive together on the first chunk, but OpenAI itself sometimes resends `id` on a subsequent delta (and some compatible gateways always echo it). If that ever coincides with the first chunk carrying only a name fragment, the announcement emits twice. Guard with `tool_calls[index].id.is_empty()` instead of `tool_chunk.id.is_some()` so the announcement fires exactly once — when the local slot transitions from empty to populated.\n\n2. **`on_delta` borrows `delta_batcher` by reference but `completion_streaming` is `&self`-async; the callback runs on the provider task, not the loop's task.** This is fine today because there is exactly one active batcher per iteration and the callback is `&dyn Fn` (shared ref), but the design encodes a hidden invariant: the batcher must outlive the provider future. The `tokio::select!` already drops `fut` (and thus `on_delta`) before `delta_batcher.flush()` runs, so the ordering is safe — but worth a one-line comment at the `on_delta` closure noting that `flush()` is only reached after `fut` completes/drops, since a future refactor that holds `on_delta` across an `.await` boundary would silently deadlock.\n\n3. **Streaming `completion_streaming` is gated by `provider.supports_streaming()`, but the fallback check reads `delta_batcher.received()` *before* the streaming future has necessarily been polled to completion.** In the `Err` arm this is correct (received is only set inside `push`), but the guard's correctness depends on `on_delta` never being invoked from a thread that races the `AtomicBool` store in `push`. It does today (the batcher's `received` store is `Relaxed` and only read after `fut` resolves), but the `Relaxed` ordering is load-bearing across the await boundary. Promote to `Release`/`Acquire` or document that the select's synchronization provides the happens-before.\n\n4. **`dry_run_build_check_streaming` reaps threads after `child.kill()` + `child.wait()`, but the reader threads join the channel via `tx.send`, which will block forever if the receiver loop is parked in `recv_timeout` between batches.** On cancellation you `kill` + `wait`, then `join` the readers. The readers only exit when their pipes close (which `kill` triggers), so this is normally fine — but if `nix` has already exited and closed stdout/stderr before cancellation, the reader threads may already be gone and `join` returns the buffered lines correctly. The actual race: the main loop's `recv_timeout` returns `Disconnected` only after *both* senders drop. If you cancel mid-batch, the loop drains `batch` and returns `Disconnected`, but the `child.wait()` after `kill` can still hang if `nix` spawned its own children that inherit the pipes. Consider `child.wait()` with a timeout or `kill` + best-effort wait.\n\n5. **`--verbose` is unconditionally added in the streaming path but not the blocking path.** `darwin.rs:174` adds `--verbose` only in `dry_run_build_check_streaming`. The two paths now produce observably different output (verbose evaluation lines vs. silent-until-result). The returned `(stdout, stderr)` fed to the model therefore differ between streaming-on and streaming-off for the same config — and since the model uses `first_error_line` / `build_output_tail` to locate failures, a streaming-on run may anchor on a verbose `error:` line that the blocking path wouldn't emit. Either always add `--verbose` in both, or document the divergence; right now the model sees different evidence depending on a UI toggle.\n\n6. **`build_output_tail` anchors on the *last* `error:` line.** `types.rs` walks the whole output and keeps the last match. For outputs with multiple `error:` lines (a real nix failure often prints `error: …` in a trace, then the final `error: …` summary), this is usually right — but if the final summary line doesn't contain `error:` (e.g. `building '...' failed: ...`), the tail anchors on an earlier trace line and cuts the real summary. The test `build_fail_should_keep_the_tail_when_oversized_output_has_no_error_line` covers the no-error case but not the \"error only in trace, not in summary\" case.\n\n### Quality / robustness\n\n7. **`session_log::QUEUE` spawns an unbounded consumer task via `OnceLock::get_or_init` on the first `append_event_ordered` call.** That task runs for the entire app lifetime and is never joined. If the tokio runtime is shut down while items are still queued, the barrier path (`flush_ordered`) will hang because the consumer task is gone but `QUEUE.get()` still returns `Some`. This is partially mitigated by `run_evolve` calling `flush_ordered()` before returning, but any *other* caller of `append_event_ordered` (currently only `emit_evolve_event`) that fires after the runtime starts shutting down will drop silently with a `warn!`. Acceptable for a dev-flagged feature; worth a comment that `flush_ordered` is a contract between `run_evolve` and the queue, not a general runtime-shutdown hook.\n\n8. **Ollama streaming clones `ollama_messages` and `ollama_tools` on every retry iteration.** `ollama.rs:277` clones the full message list each loop. With chat memory that can be large; on a retry that re-sends the whole history. The blocking path already did this, so it's not a regression, but the streaming retry path now does it under the streaming future (holding the iteration's budget). Minor.\n\n9. **`trailingStreamText` collapses blank lines with `/\\n\\s*\\n/g -> \\n`, which also collapses intentional paragraph breaks in assistant prose.** The test `collapses blank lines between thoughts and tool announcements` codifies this. For tool-announcement/thought interleaving this reads well, but if the model emits a genuinely blank line between two paragraphs of reasoning (common in `think`), the visible tail flattens it to one. Cosmetic, and only affects the ephemeral tail (the full text lands as a Narration row afterward), so low impact.\n\n### Non-issues I checked\n\n- **Surrogate pair handling in `decode_json_string_prefix`**: correct, including the split-across-fragment and lone-surrogate cases; tests at every boundary are good.\n- **NDJSON byte framing**: `NdjsonBuffer` buffers raw bytes and only decodes complete records — fixes the `from_utf8_lossy` corruption correctly.\n- **Streaming rejection classifier**: deliberately narrow (param `stream`/`stream_options` or explicit message); the post-review assessment doc correctly drove the dedicated `StreamingUnsupported` variant. Auth/rate-limit/server/transport errors do not retry.\n- **Header clock anchor on `lastEvent` identity**: the coalesced-replacement double-count is fixed; the regression test at `evolve-progress-clock.test.tsx` is the right shape.\n- **`run_evolve` wrapper**: flush-then-clear-then-return ordering is correct for all three exit paths (success, failure, cancel).\n\n### Overall\n\nNet: ship it behind the dev flag. The findings above are mostly about tightening the streaming/blocking output parity (#5), the announcement double-fire edge (#1), and a couple of ordering/synchronization comments that future-you will thank present-you for. None block merging an experimental feature; #1 and #5 are the two I'd want addressed before this moves off the developer toggle.",
"commit_id": "6d04099743c847f1cf5e808403d7ab4b2b7eb5fc",
"state": "commented",
"html_url": "https://github.com/darkmatter/nixmac/pull/561#pullrequestreview-4731486516",
"pull_request_url": "https://api.github.com/repos/darkmatter/nixmac/pulls/561",
"_links": {
"html": {
"href": "https://github.com/darkmatter/nixmac/pull/561#pullrequestreview-4731486516"
},
"pull_request": {
"href": "https://api.github.com/repos/darkmatter/nixmac/pulls/561"
}
},
"submitted_at": "2026-07-19T21:10:47Z",
"updated_at": "2026-07-19T21:10:48Z",
"author_association": "CONTRIBUTOR"
},
"pull_request": {
"url": "https://api.github.com/repos/darkmatter/nixmac/pulls/561",
"id": 4087131301,
"node_id": "PR_kwDOSB6EzM7znKyl",
"html_url": "https://github.com/darkmatter/nixmac/pull/561",
"diff_url": "https://github.com/darkmatter/nixmac/pull/561.diff",
"patch_url": "https://github.com/darkmatter/nixmac/pull/561.patch",
"issue_url": "https://api.github.com/repos/darkmatter/nixmac/issues/561",
"number": 561,
"state": "open",
"locked": false,
"title": "Evolve view: stream responses and build output live",
"user": {
"login": "arximboldi",
"id": 4521138,
"node_id": "MDQ6VXNlcjQ1MjExMzg=",
"avatar_url": "https://avatars.githubusercontent.com/u/4521138?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/arximboldi",
"html_url": "https://github.com/arximboldi",
"followers_url": "https://api.github.com/users/arximboldi/followers",
"following_url": "https://api.github.com/users/arximboldi/following{/other_user}",
"gists_url": "https://api.github.com/users/arximboldi/gists{/gist_id}",
"starred_url": "https://api.github.com/users/arximboldi/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/arximboldi/subscriptions",
"organizations_url": "https://api.github.com/users/arximboldi/orgs",
"repos_url": "https://api.github.com/users/arximboldi/repos",
"events_url": "https://api.github.com/users/arximboldi/events{/privacy}",
"received_events_url": "https://api.github.com/users/arximboldi/received_events",
"type": "User",
"user_view_type": "public",
"site_admin": false
},
"body": "## Summary\r\n\r\nLast part of the evolve view redesign (`docs/2026-07-15-evolve-view-ux.md`); follows up on #549.\r\n\r\nThis implements output streaming, the evolve view now shows the agent's work *as it happens* instead of only between steps. This hopefully adds fluidity to the interface and improves the subjective perception of speed of the agent.\r\n\r\nhttps://github.com/user-attachments/assets/6de4172d-4ab4-4fec-866a-d91b76548f2f\r\n\r\n### What changes for the user\r\n\r\n- **You can watch the build check run.** The dry-run build's output streams live under the active timeline row as a log tail, so a long `nix build` no longer looks like a frozen spinner — you see exactly which derivation it's chewing on. The tail auto-follows, but pauses following while you scroll up to read, and resumes when you scroll back down. When a build fails with oversized output, the excerpt is anchored on the error line rather than an arbitrary tail.\r\n\r\n- **You can watch the agent think (experimental).** With the new *Streaming responses* switch in Settings → Developer, the agent's response is typed into the active row token by token — including the reasoning it produces while composing tool calls, not just prose. Supported for Ollama and OpenAI-compatible providers.\r\n\r\n- **Retries are visible, not mysterious.** If the provider abandons a partial response and retries, the streamed tail resets with an immediate \"Retrying...\" notice instead of silently starting over, and the per-step timer stays anchored to real step boundaries so it doesn't lie about how long the current step has taken.\r\n\r\n- **Streaming never breaks a run.** If a provider or gateway rejects streaming, the run falls back to the regular blocking completion transparently (streaming stays off for the rest of that run); genuine model errors are still surfaced as errors rather than masked by the fallback.\r\n\r\n### Under the hood\r\n\r\n- New `StreamDelta`/`StreamReset` event details carry streamed slices; the raw deltas still flow to the Console mirror and session transcripts, while the timeline renders only the accumulated tail in the active row.\r\n\r\n- SSE (OpenAI-compatible) and NDJSON (Ollama) decoding handle raw-byte boundaries, surrogate pairs, and structured in-stream error payloads, which are classified with the same taxonomy as blocking errors.\r\n\r\n- Stream chunks are coalesced in the viewmodel to keep re-renders cheap; session transcript appends are serialized and flushed before `run_evolve` returns.\r\n\r\n## Test Plan\r\n\r\n- [x] `cargo check --tests` and the `evolve-progress` vitest suite pass after the rebase onto main\r\n- [ ] Manual pass: run an evolution with streaming on (Ollama + OpenAI-compatible) and off, watch build output, scroll during a build, interrupt a stream\r\n\r\n## Docs\r\n\r\n- [x] No docs update needed\r\n",
"created_at": "2026-07-19T20:48:07Z",
"updated_at": "2026-07-19T21:06:19Z",
"closed_at": null,
"merged_at": null,
"merge_commit_sha": "d21d578ac10db598f1b8485f29837f76f57691d8",
"assignees": [],
"requested_reviewers": [
{
"login": "czxtm",
"id": 1325802,
"node_id": "MDQ6VXNlcjEzMjU4MDI=",
"avatar_url": "https://avatars.githubusercontent.com/u/1325802?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/czxtm",
"html_url": "https://github.com/czxtm",
"followers_url": "https://api.github.com/users/czxtm/followers",
"following_url": "https://api.github.com/users/czxtm/following{/other_user}",
"gists_url": "https://api.github.com/users/czxtm/gists{/gist_id}",
"starred_url": "https://api.github.com/users/czxtm/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/czxtm/subscriptions",
"organizations_url": "https://api.github.com/users/czxtm/orgs",
"repos_url": "https://api.github.com/users/czxtm/repos",
"events_url": "https://api.github.com/users/czxtm/events{/privacy}",
"received_events_url": "https://api.github.com/users/czxtm/received_events",
"type": "User",
"user_view_type": "public",
"site_admin": false
},
{
"login": "scottmcmaster",
"id": 3137688,
"node_id": "MDQ6VXNlcjMxMzc2ODg=",
"avatar_url": "https://avatars.githubusercontent.com/u/3137688?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/scottmcmaster",
"html_url": "https://github.com/scottmcmaster",
"followers_url": "https://api.github.com/users/scottmcmaster/followers",
"following_url": "https://api.github.com/users/scottmcmaster/following{/other_user}",
"gists_url": "https://api.github.com/users/scottmcmaster/gists{/gist_id}",
"starred_url": "https://api.github.com/users/scottmcmaster/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/scottmcmaster/subscriptions",
"organizations_url": "https://api.github.com/users/scottmcmaster/orgs",
"repos_url": "https://api.github.com/users/scottmcmaster/repos",
"events_url": "https://api.github.com/users/scottmcmaster/events{/privacy}",
"received_events_url": "https://api.github.com/users/scottmcmaster/received_events",
"type": "User",
"user_view_type": "public",
"site_admin": false
}
],
"requested_teams": [],
"labels": [],
"milestone": null,
"draft": false,
"commits_url": "https://api.github.com/repos/darkmatter/nixmac/pulls/561/commits",
"review_comments_url": "https://api.github.com/repos/darkmatter/nixmac/pulls/561/comments",
"review_comment_url": "https://api.github.com/repos/darkmatter/nixmac/pulls/comments{/number}",
"comments_url": "https://api.github.com/repos/darkmatter/nixmac/issues/561/comments",
"statuses_url": "https://api.github.com/repos/darkmatter/nixmac/statuses/6d04099743c847f1cf5e808403d7ab4b2b7eb5fc",
"head": {
"label": "darkmatter:jp/evolve-streaming",
"ref": "jp/evolve-streaming",
"sha": "6d04099743c847f1cf5e808403d7ab4b2b7eb5fc",
"user": {
"login": "darkmatter",
"id": 17834193,
"node_id": "MDEyOk9yZ2FuaXphdGlvbjE3ODM0MTkz",
"avatar_url": "https://avatars.githubusercontent.com/u/17834193?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/darkmatter",
"html_url": "https://github.com/darkmatter",
"followers_url": "https://api.github.com/users/darkmatter/followers",
"following_url": "https://api.github.com/users/darkmatter/following{/other_user}",
"gists_url": "https://api.github.com/users/darkmatter/gists{/gist_id}",
"starred_url": "https://api.github.com/users/darkmatter/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/darkmatter/subscriptions",
"organizations_url": "https://api.github.com/users/darkmatter/orgs",
"repos_url": "https://api.github.com/users/darkmatter/repos",
"events_url": "https://api.github.com/users/darkmatter/events{/privacy}",
"received_events_url": "https://api.github.com/users/darkmatter/received_events",
"type": "Organization",
"user_view_type": "public",
"site_admin": false
},
"repo": {
"id": 1209959628,
"node_id": "R_kgDOSB6EzA",
"name": "nixmac",
"full_name": "darkmatter/nixmac",
"private": false,
"owner": {
"login": "darkmatter",
"id": 17834193,
"node_id": "MDEyOk9yZ2FuaXphdGlvbjE3ODM0MTkz",
"avatar_url": "https://avatars.githubusercontent.com/u/17834193?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/darkmatter",
"html_url": "https://github.com/darkmatter",
"followers_url": "https://api.github.com/users/darkmatter/followers",
"following_url": "https://api.github.com/users/darkmatter/following{/other_user}",
"gists_url": "https://api.github.com/users/darkmatter/gists{/gist_id}",
"starred_url": "https://api.github.com/users/darkmatter/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/darkmatter/subscriptions",
"organizations_url": "https://api.github.com/users/darkmatter/orgs",
"repos_url": "https://api.github.com/users/darkmatter/repos",
"events_url": "https://api.github.com/users/darkmatter/events{/privacy}",
"received_events_url": "https://api.github.com/users/darkmatter/received_events",
"type": "Organization",
"user_view_type": "public",
"site_admin": false
},
"html_url": "https://github.com/darkmatter/nixmac",
"description": "Home manager and nix-darwin that understands plain English",
"fork": false,
"url": "https://api.github.com/repos/darkmatter/nixmac",
"forks_url": "https://api.github.com/repos/darkmatter/nixmac/forks",
"keys_url": "https://api.github.com/repos/darkmatter/nixmac/keys{/key_id}",
"collaborators_url": "https://api.github.com/repos/darkmatter/nixmac/collaborators{/collaborator}",
"teams_url": "https://api.github.com/repos/darkmatter/nixmac/teams",
"hooks_url": "https://api.github.com/repos/darkmatter/nixmac/hooks",
"issue_events_url": "https://api.github.com/repos/darkmatter/nixmac/issues/events{/number}",
"events_url": "https://api.github.com/repos/darkmatter/nixmac/events",
"assignees_url": "https://api.github.com/repos/darkmatter/nixmac/assignees{/user}",
"branches_url": "https://api.github.com/repos/darkmatter/nixmac/branches{/branch}",
"tags_url": "https://api.github.com/repos/darkmatter/nixmac/tags",
"blobs_url": "https://api.github.com/repos/darkmatter/nixmac/git/blobs{/sha}",
"git_tags_url": "https://api.github.com/repos/darkmatter/nixmac/git/tags{/sha}",
"git_refs_url": "https://api.github.com/repos/darkmatter/nixmac/git/refs{/sha}",
"trees_url": "https://api.github.com/repos/darkmatter/nixmac/git/trees{/sha}",
"statuses_url": "https://api.github.com/repos/darkmatter/nixmac/statuses/{sha}",
"languages_url": "https://api.github.com/repos/darkmatter/nixmac/languages",
"stargazers_url": "https://api.github.com/repos/darkmatter/nixmac/stargazers",
"contributors_url": "https://api.github.com/repos/darkmatter/nixmac/contributors",
"subscribers_url": "https://api.github.com/repos/darkmatter/nixmac/subscribers",
"subscription_url": "https://api.github.com/repos/darkmatter/nixmac/subscription",
"commits_url": "https://api.github.com/repos/darkmatter/nixmac/commits{/sha}",
"git_commits_url": "https://api.github.com/repos/darkmatter/nixmac/git/commits{/sha}",
"comments_url": "https://api.github.com/repos/darkmatter/nixmac/comments{/number}",
"issue_comment_url": "https://api.github.com/repos/darkmatter/nixmac/issues/comments{/number}",
"contents_url": "https://api.github.com/repos/darkmatter/nixmac/contents/{+path}",
"compare_url": "https://api.github.com/repos/darkmatter/nixmac/compare/{base}...{head}",
"merges_url": "https://api.github.com/repos/darkmatter/nixmac/merges",
"archive_url": "https://api.github.com/repos/darkmatter/nixmac/{archive_format}{/ref}",
"downloads_url": "https://api.github.com/repos/darkmatter/nixmac/downloads",
"issues_url": "https://api.github.com/repos/darkmatter/nixmac/issues{/number}",
"pulls_url": "https://api.github.com/repos/darkmatter/nixmac/pulls{/number}",
"milestones_url": "https://api.github.com/repos/darkmatter/nixmac/milestones{/number}",
"notifications_url": "https://api.github.com/repos/darkmatter/nixmac/notifications{?since,all,participating}",
"labels_url": "https://api.github.com/repos/darkmatter/nixmac/labels{/name}",
"releases_url": "https://api.github.com/repos/darkmatter/nixmac/releases{/id}",
"deployments_url": "https://api.github.com/repos/darkmatter/nixmac/deployments",
"created_at": "2026-04-14T00:37:13Z",
"updated_at": "2026-07-19T15:23:06Z",
"pushed_at": "2026-07-19T20:41:50Z",
"git_url": "git://github.com/darkmatter/nixmac.git",
"ssh_url": "org-17834193@github.com:darkmatter/nixmac.git",
"clone_url": "https://github.com/darkmatter/nixmac.git",
"svn_url": "https://github.com/darkmatter/nixmac",
"homepage": "https://nixmac.com",
"size": 688838,
"stargazers_count": 21,
"watchers_count": 21,
"language": "Rust",
"has_issues": true,
"has_projects": false,
"has_downloads": true,
"has_wiki": false,
"has_pages": true,
"has_discussions": true,
"forks_count": 2,
"mirror_url": null,
"archived": false,
"disabled": false,
"open_issues_count": 100,
"license": {
"key": "mit",
"name": "MIT License",
"spdx_id": "MIT",
"url": "https://api.github.com/licenses/mit",
"node_id": "MDc6TGljZW5zZTEz"
},
"allow_forking": true,
"is_template": false,
"web_commit_signoff_required": false,
"has_pull_requests": true,
"pull_request_creation_policy": "all",
"topics": [
"home-manager",
"nix",
"nix-darwin",
"nix-flake",
"opencode"
],
"visibility": "public",
"forks": 2,
"open_issues": 100,
"watchers": 21,
"default_branch": "main",
"allow_squash_merge": true,
"allow_merge_commit": false,
"allow_rebase_merge": true,
"allow_auto_merge": true,
"delete_branch_on_merge": true,
"allow_update_branch": true,
"use_squash_pr_title_as_default": false,
"squash_merge_commit_message": "COMMIT_MESSAGES",
"squash_merge_commit_title": "COMMIT_OR_PR_TITLE",
"merge_commit_message": "PR_TITLE",
"merge_commit_title": "MERGE_MESSAGE"
}
},
"base": {
"label": "darkmatter:main",
"ref": "main",
"sha": "08d30880702b5140224356ef4e0b74d084df2000",
"user": {
"login": "darkmatter",
"id": 17834193,
"node_id": "MDEyOk9yZ2FuaXphdGlvbjE3ODM0MTkz",
"avatar_url": "https://avatars.githubusercontent.com/u/17834193?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/darkmatter",
"html_url": "https://github.com/darkmatter",
"followers_url": "https://api.github.com/users/darkmatter/followers",
"following_url": "https://api.github.com/users/darkmatter/following{/other_user}",
"gists_url": "https://api.github.com/users/darkmatter/gists{/gist_id}",
"starred_url": "https://api.github.com/users/darkmatter/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/darkmatter/subscriptions",
"organizations_url": "https://api.github.com/users/darkmatter/orgs",
"repos_url": "https://api.github.com/users/darkmatter/repos",
"events_url": "https://api.github.com/users/darkmatter/events{/privacy}",
"received_events_url": "https://api.github.com/users/darkmatter/received_events",
"type": "Organization",
"user_view_type": "public",
"site_admin": false
},
"repo": {
"id": 1209959628,
"node_id": "R_kgDOSB6EzA",
"name": "nixmac",
"full_name": "darkmatter/nixmac",
"private": false,
"owner": {
"login": "darkmatter",
"id": 17834193,
"node_id": "MDEyOk9yZ2FuaXphdGlvbjE3ODM0MTkz",
"avatar_url": "https://avatars.githubusercontent.com/u/17834193?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/darkmatter",
"html_url": "https://github.com/darkmatter",
"followers_url": "https://api.github.com/users/darkmatter/followers",
"following_url": "https://api.github.com/users/darkmatter/following{/other_user}",
"gists_url": "https://api.github.com/users/darkmatter/gists{/gist_id}",
"starred_url": "https://api.github.com/users/darkmatter/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/darkmatter/subscriptions",
"organizations_url": "https://api.github.com/users/darkmatter/orgs",
"repos_url": "https://api.github.com/users/darkmatter/repos",
"events_url": "https://api.github.com/users/darkmatter/events{/privacy}",
"received_events_url": "https://api.github.com/users/darkmatter/received_events",
"type": "Organization",
"user_view_type": "public",
"site_admin": false
},
"html_url": "https://github.com/darkmatter/nixmac",
"description": "Home manager and nix-darwin that understands plain English",
"fork": false,
"url": "https://api.github.com/repos/darkmatter/nixmac",
"forks_url": "https://api.github.com/repos/darkmatter/nixmac/forks",
"keys_url": "https://api.github.com/repos/darkmatter/nixmac/keys{/key_id}",
"collaborators_url": "https://api.github.com/repos/darkmatter/nixmac/collaborators{/collaborator}",
"teams_url": "https://api.github.com/repos/darkmatter/nixmac/teams",
"hooks_url": "https://api.github.com/repos/darkmatter/nixmac/hooks",
"issue_events_url": "https://api.github.com/repos/darkmatter/nixmac/issues/events{/number}",
"events_url": "https://api.github.com/repos/darkmatter/nixmac/events",
"assignees_url": "https://api.github.com/repos/darkmatter/nixmac/assignees{/user}",
"branches_url": "https://api.github.com/repos/darkmatter/nixmac/branches{/branch}",
"tags_url": "https://api.github.com/repos/darkmatter/nixmac/tags",
"blobs_url": "https://api.github.com/repos/darkmatter/nixmac/git/blobs{/sha}",
"git_tags_url": "https://api.github.com/repos/darkmatter/nixmac/git/tags{/sha}",
"git_refs_url": "https://api.github.com/repos/darkmatter/nixmac/git/refs{/sha}",
"trees_url": "https://api.github.com/repos/darkmatter/nixmac/git/trees{/sha}",
"statuses_url": "https://api.github.com/repos/darkmatter/nixmac/statuses/{sha}",
"languages_url": "https://api.github.com/repos/darkmatter/nixmac/languages",
"stargazers_url": "https://api.github.com/repos/darkmatter/nixmac/stargazers",
"contributors_url": "https://api.github.com/repos/darkmatter/nixmac/contributors",
"subscribers_url": "https://api.github.com/repos/darkmatter/nixmac/subscribers",
"subscription_url": "https://api.github.com/repos/darkmatter/nixmac/subscription",
"commits_url": "https://api.github.com/repos/darkmatter/nixmac/commits{/sha}",
"git_commits_url": "https://api.github.com/repos/darkmatter/nixmac/git/commits{/sha}",
"comments_url": "https://api.github.com/repos/darkmatter/nixmac/comments{/number}",
"issue_comment_url": "https://api.github.com/repos/darkmatter/nixmac/issues/comments{/number}",
"contents_url": "https://api.github.com/repos/darkmatter/nixmac/contents/{+path}",
"compare_url": "https://api.github.com/repos/darkmatter/nixmac/compare/{base}...{head}",
"merges_url": "https://api.github.com/repos/darkmatter/nixmac/merges",
"archive_url": "https://api.github.com/repos/darkmatter/nixmac/{archive_format}{/ref}",
"downloads_url": "https://api.github.com/repos/darkmatter/nixmac/downloads",
"issues_url": "https://api.github.com/repos/darkmatter/nixmac/issues{/number}",
"pulls_url": "https://api.github.com/repos/darkmatter/nixmac/pulls{/number}",
"milestones_url": "https://api.github.com/repos/darkmatter/nixmac/milestones{/number}",
"notifications_url": "https://api.github.com/repos/darkmatter/nixmac/notifications{?since,all,participating}",
"labels_url": "https://api.github.com/repos/darkmatter/nixmac/labels{/name}",
"releases_url": "https://api.github.com/repos/darkmatter/nixmac/releases{/id}",
"deployments_url": "https://api.github.com/repos/darkmatter/nixmac/deployments",
"created_at": "2026-04-14T00:37:13Z",
"updated_at": "2026-07-19T15:23:06Z",
"pushed_at": "2026-07-19T20:41:50Z",
"git_url": "git://github.com/darkmatter/nixmac.git",
"ssh_url": "org-17834193@github.com:darkmatter/nixmac.git",
"clone_url": "https://github.com/darkmatter/nixmac.git",
"svn_url": "https://github.com/darkmatter/nixmac",
"homepage": "https://nixmac.com",
"size": 688838,
"stargazers_count": 21,
"watchers_count": 21,
"language": "Rust",
"has_issues": true,
"has_projects": false,
"has_downloads": true,
"has_wiki": false,
"has_pages": true,
"has_discussions": true,
"forks_count": 2,
"mirror_url": null,
"archived": false,
"disabled": false,
"open_issues_count": 100,
"license": {
"key": "mit",
"name": "MIT License",
"spdx_id": "MIT",
"url": "https://api.github.com/licenses/mit",
"node_id": "MDc6TGljZW5zZTEz"
},
"allow_forking": true,
"is_template": false,
"web_commit_signoff_required": false,
"has_pull_requests": true,
"pull_request_creation_policy": "all",
"topics": [
"home-manager",
"nix",
"nix-darwin",
"nix-flake",
"opencode"
],
"visibility": "public",
"forks": 2,
"open_issues": 100,
"watchers": 21,
"default_branch": "main",
"allow_squash_merge": true,
"allow_merge_commit": false,
"allow_rebase_merge": true,
"allow_auto_merge": true,
"delete_branch_on_merge": true,
"allow_update_branch": true,
"use_squash_pr_title_as_default": false,
"squash_merge_commit_message": "COMMIT_MESSAGES",
"squash_merge_commit_title": "COMMIT_OR_PR_TITLE",
"merge_commit_message": "PR_TITLE",
"merge_commit_title": "MERGE_MESSAGE"
}
},
"_links": {
"self": {
"href": "https://api.github.com/repos/darkmatter/nixmac/pulls/561"
},
"html": {
"href": "https://github.com/darkmatter/nixmac/pull/561"
},
"issue": {
"href": "https://api.github.com/repos/darkmatter/nixmac/issues/561"
},
"comments": {
"href": "https://api.github.com/repos/darkmatter/nixmac/issues/561/comments"
},
"review_comments": {
"href": "https://api.github.com/repos/darkmatter/nixmac/pulls/561/comments"
},
"review_comment": {
"href": "https://api.github.com/repos/darkmatter/nixmac/pulls/comments{/number}"
},
"commits": {
"href": "https://api.github.com/repos/darkmatter/nixmac/pulls/561/commits"
},
"statuses": {
"href": "https://api.github.com/repos/darkmatter/nixmac/statuses/6d04099743c847f1cf5e808403d7ab4b2b7eb5fc"
}
},
"author_association": "CONTRIBUTOR",
"auto_merge": null,
"assignee": null,
"active_lock_reason": null
},
"repository": {
"id": 1209959628,
"node_id": "R_kgDOSB6EzA",
"name": "nixmac",
"full_name": "darkmatter/nixmac",
"private": false,
"owner": {
"login": "darkmatter",
"id": 17834193,
"node_id": "MDEyOk9yZ2FuaXphdGlvbjE3ODM0MTkz",
"avatar_url": "https://avatars.githubusercontent.com/u/17834193?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/darkmatter",
"html_url": "https://github.com/darkmatter",
"followers_url": "https://api.github.com/users/darkmatter/followers",
"following_url": "https://api.github.com/users/darkmatter/following{/other_user}",
"gists_url": "https://api.github.com/users/darkmatter/gists{/gist_id}",
"starred_url": "https://api.github.com/users/darkmatter/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/darkmatter/subscriptions",
"organizations_url": "https://api.github.com/users/darkmatter/orgs",
"repos_url": "https://api.github.com/users/darkmatter/repos",
"events_url": "https://api.github.com/users/darkmatter/events{/privacy}",
"received_events_url": "https://api.github.com/users/darkmatter/received_events",
"type": "Organization",
"user_view_type": "public",
"site_admin": false
},
"html_url": "https://github.com/darkmatter/nixmac",
"description": "Home manager and nix-darwin that understands plain English",
"fork": false,
"url": "https://api.github.com/repos/darkmatter/nixmac",
"forks_url": "https://api.github.com/repos/darkmatter/nixmac/forks",
"keys_url": "https://api.github.com/repos/darkmatter/nixmac/keys{/key_id}",
"collaborators_url": "https://api.github.com/repos/darkmatter/nixmac/collaborators{/collaborator}",
"teams_url": "https://api.github.com/repos/darkmatter/nixmac/teams",
"hooks_url": "https://api.github.com/repos/darkmatter/nixmac/hooks",
"issue_events_url": "https://api.github.com/repos/darkmatter/nixmac/issues/events{/number}",
"events_url": "https://api.github.com/repos/darkmatter/nixmac/events",
"assignees_url": "https://api.github.com/repos/darkmatter/nixmac/assignees{/user}",
"branches_url": "https://api.github.com/repos/darkmatter/nixmac/branches{/branch}",
"tags_url": "https://api.github.com/repos/darkmatter/nixmac/tags",
"blobs_url": "https://api.github.com/repos/darkmatter/nixmac/git/blobs{/sha}",
"git_tags_url": "https://api.github.com/repos/darkmatter/nixmac/git/tags{/sha}",
"git_refs_url": "https://api.github.com/repos/darkmatter/nixmac/git/refs{/sha}",
"trees_url": "https://api.github.com/repos/darkmatter/nixmac/git/trees{/sha}",
"statuses_url": "https://api.github.com/repos/darkmatter/nixmac/statuses/{sha}",
"languages_url": "https://api.github.com/repos/darkmatter/nixmac/languages",
"stargazers_url": "https://api.github.com/repos/darkmatter/nixmac/stargazers",
"contributors_url": "https://api.github.com/repos/darkmatter/nixmac/contributors",
"subscribers_url": "https://api.github.com/repos/darkmatter/nixmac/subscribers",
"subscription_url": "https://api.github.com/repos/darkmatter/nixmac/subscription",
"commits_url": "https://api.github.com/repos/darkmatter/nixmac/commits{/sha}",
"git_commits_url": "https://api.github.com/repos/darkmatter/nixmac/git/commits{/sha}",
"comments_url": "https://api.github.com/repos/darkmatter/nixmac/comments{/number}",
"issue_comment_url": "https://api.github.com/repos/darkmatter/nixmac/issues/comments{/number}",
"contents_url": "https://api.github.com/repos/darkmatter/nixmac/contents/{+path}",
"compare_url": "https://api.github.com/repos/darkmatter/nixmac/compare/{base}...{head}",
"merges_url": "https://api.github.com/repos/darkmatter/nixmac/merges",
"archive_url": "https://api.github.com/repos/darkmatter/nixmac/{archive_format}{/ref}",
"downloads_url": "https://api.github.com/repos/darkmatter/nixmac/downloads",
"issues_url": "https://api.github.com/repos/darkmatter/nixmac/issues{/number}",
"pulls_url": "https://api.github.com/repos/darkmatter/nixmac/pulls{/number}",
"milestones_url": "https://api.github.com/repos/darkmatter/nixmac/milestones{/number}",
"notifications_url": "https://api.github.com/repos/darkmatter/nixmac/notifications{?since,all,participating}",
"labels_url": "https://api.github.com/repos/darkmatter/nixmac/labels{/name}",
"releases_url": "https://api.github.com/repos/darkmatter/nixmac/releases{/id}",
"deployments_url": "https://api.github.com/repos/darkmatter/nixmac/deployments",
"created_at": "2026-04-14T00:37:13Z",
"updated_at": "2026-07-19T15:23:06Z",
"pushed_at": "2026-07-19T20:41:50Z",
"git_url": "git://github.com/darkmatter/nixmac.git",
"ssh_url": "org-17834193@github.com:darkmatter/nixmac.git",
"clone_url": "https://github.com/darkmatter/nixmac.git",
"svn_url": "https://github.com/darkmatter/nixmac",
"homepage": "https://nixmac.com",
"size": 688838,
"stargazers_count": 21,
"watchers_count": 21,
"language": "Rust",
"has_issues": true,
"has_projects": false,
"has_downloads": true,
"has_wiki": false,
"has_pages": true,
"has_discussions": true,
"forks_count": 2,
"mirror_url": null,
"archived": false,
"disabled": false,
"open_issues_count": 100,
"license": {
"key": "mit",
"name": "MIT License",
"spdx_id": "MIT",
"url": "https://api.github.com/licenses/mit",
"node_id": "MDc6TGljZW5zZTEz"
},
"allow_forking": true,
"is_template": false,
"web_commit_signoff_required": false,
"has_pull_requests": true,
"pull_request_creation_policy": "all",
"topics": [
"home-manager",
"nix",
"nix-darwin",
"nix-flake",
"opencode"
],
"visibility": "public",
"forks": 2,
"open_issues": 100,
"watchers": 21,
"default_branch": "main",
"custom_properties": {}
},
"organization": {
"login": "darkmatter",
"id": 17834193,
"node_id": "MDEyOk9yZ2FuaXphdGlvbjE3ODM0MTkz",
"url": "https://api.github.com/orgs/darkmatter",
"repos_url": "https://api.github.com/orgs/darkmatter/repos",
"events_url": "https://api.github.com/orgs/darkmatter/events",
"hooks_url": "https://api.github.com/orgs/darkmatter/hooks",
"issues_url": "https://api.github.com/orgs/darkmatter/issues",
"members_url": "https://api.github.com/orgs/darkmatter/members{/member}",
"public_members_url": "https://api.github.com/orgs/darkmatter/public_members{/member}",
"avatar_url": "https://avatars.githubusercontent.com/u/17834193?v=4",
"description": ""
},
"enterprise": {
"id": 469843,
"slug": "darkmatter",
"name": "darkmatter",
"node_id": "E_kgDOAAcrUw",
"avatar_url": "https://avatars.githubusercontent.com/b/469843?v=4",
"description": "",
"website_url": "darkmatter.io",
"html_url": "https://github.com/enterprises/darkmatter",
"created_at": "2025-09-07T16:01:00Z",
"updated_at": "2026-07-07T15:59:26Z"
},
"sender": {
"login": "darkmatter[bot]",
"id": 283346107,
"node_id": "BOT_kgDOEOOEuw",
"avatar_url": "https://avatars.githubusercontent.com/in/3663660?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/darkmatter%5Bbot%5D",
"html_url": "https://github.com/apps/darkmatter",
"followers_url": "https://api.github.com/users/darkmatter%5Bbot%5D/followers",
"following_url": "https://api.github.com/users/darkmatter%5Bbot%5D/following{/other_user}",
"gists_url": "https://api.github.com/users/darkmatter%5Bbot%5D/gists{/gist_id}",
"starred_url": "https://api.github.com/users/darkmatter%5Bbot%5D/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/darkmatter%5Bbot%5D/subscriptions",
"organizations_url": "https://api.github.com/users/darkmatter%5Bbot%5D/orgs",
"repos_url": "https://api.github.com/users/darkmatter%5Bbot%5D/repos",
"events_url": "https://api.github.com/users/darkmatter%5Bbot%5D/events{/privacy}",
"received_events_url": "https://api.github.com/users/darkmatter%5Bbot%5D/received_events",
"type": "Bot",
"user_view_type": "public",
"site_admin": false
},
"installation": {
"id": 131074261,
"node_id": "MDIzOkludGVncmF0aW9uSW5zdGFsbGF0aW9uMTMxMDc0MjYx"
}
}