Darkmatter · github-bot stage: prod
preview@internal.darkmatter
Events received
64380
Ignored
64345
Jobs dispatched
35

Event c74143e0…

← All events

Event

Delivery
c74143e0-66ab-11f1-9994-e9f67539b868
Event
workflow_run
Action
requested
Received
2026-06-12T22:12:20.363Z
Signature
valid
Parsed
yes
Sender
github-merge-queue[bot]
Repo
darkmatter/nixmac
Status
ignored — unsupported_event

Headers

{
  "accept": "*/*",
  "accept-encoding": "gzip, br",
  "cf-connecting-ip": "140.82.115.103",
  "cf-ipcountry": "US",
  "cf-ray": "a0ac324b0fc28b3e",
  "cf-visitor": "{\"scheme\":\"https\"}",
  "connection": "Keep-Alive",
  "content-length": "37343",
  "content-type": "application/json",
  "host": "github-bot.darkmatter.io",
  "user-agent": "GitHub-Hookshot/831a06e",
  "x-forwarded-proto": "https",
  "x-github-delivery": "c74143e0-66ab-11f1-9994-e9f67539b868",
  "x-github-event": "workflow_run",
  "x-github-hook-id": "628737947",
  "x-github-hook-installation-target-id": "3663660",
  "x-github-hook-installation-target-type": "integration",
  "x-real-ip": "140.82.115.103"
}

Payload

{
  "action": "requested",
  "workflow_run": {
    "id": 27446041510,
    "name": "Build macOS App",
    "node_id": "WFR_kwLOSB6EzM8AAAAGY-lbpg",
    "head_branch": "develop",
    "head_sha": "9e07bb729bb088d2e44c4a28b9d1b2f2363e8e92",
    "path": ".github/workflows/build.yaml",
    "display_title": "Replace `Slice` by `Observable`, simplify and clean up the `Configura…",
    "run_number": 1400,
    "event": "push",
    "status": "queued",
    "conclusion": null,
    "workflow_id": 260427457,
    "check_suite_id": 73845649688,
    "check_suite_node_id": "CS_kwDOSB6EzM8AAAARMYsxGA",
    "url": "https://api.github.com/repos/darkmatter/nixmac/actions/runs/27446041510",
    "html_url": "https://github.com/darkmatter/nixmac/actions/runs/27446041510",
    "pull_requests": [],
    "created_at": "2026-06-12T22:12:19Z",
    "updated_at": "2026-06-12T22:12:19Z",
    "actor": {
      "login": "github-merge-queue[bot]",
      "id": 118344674,
      "node_id": "BOT_kgDOBw3L4g",
      "avatar_url": "https://avatars.githubusercontent.com/u/9919?v=4",
      "gravatar_id": "",
      "url": "https://api.github.com/users/github-merge-queue%5Bbot%5D",
      "html_url": "https://github.com/apps/github-merge-queue",
      "followers_url": "https://api.github.com/users/github-merge-queue%5Bbot%5D/followers",
      "following_url": "https://api.github.com/users/github-merge-queue%5Bbot%5D/following{/other_user}",
      "gists_url": "https://api.github.com/users/github-merge-queue%5Bbot%5D/gists{/gist_id}",
      "starred_url": "https://api.github.com/users/github-merge-queue%5Bbot%5D/starred{/owner}{/repo}",
      "subscriptions_url": "https://api.github.com/users/github-merge-queue%5Bbot%5D/subscriptions",
      "organizations_url": "https://api.github.com/users/github-merge-queue%5Bbot%5D/orgs",
      "repos_url": "https://api.github.com/users/github-merge-queue%5Bbot%5D/repos",
      "events_url": "https://api.github.com/users/github-merge-queue%5Bbot%5D/events{/privacy}",
      "received_events_url": "https://api.github.com/users/github-merge-queue%5Bbot%5D/received_events",
      "type": "Bot",
      "user_view_type": "public",
      "site_admin": false
    },
    "run_attempt": 1,
    "referenced_workflows": [],
    "run_started_at": "2026-06-12T22:12:19Z",
    "triggering_actor": {
      "login": "github-merge-queue[bot]",
      "id": 118344674,
      "node_id": "BOT_kgDOBw3L4g",
      "avatar_url": "https://avatars.githubusercontent.com/u/9919?v=4",
      "gravatar_id": "",
      "url": "https://api.github.com/users/github-merge-queue%5Bbot%5D",
      "html_url": "https://github.com/apps/github-merge-queue",
      "followers_url": "https://api.github.com/users/github-merge-queue%5Bbot%5D/followers",
      "following_url": "https://api.github.com/users/github-merge-queue%5Bbot%5D/following{/other_user}",
      "gists_url": "https://api.github.com/users/github-merge-queue%5Bbot%5D/gists{/gist_id}",
      "starred_url": "https://api.github.com/users/github-merge-queue%5Bbot%5D/starred{/owner}{/repo}",
      "subscriptions_url": "https://api.github.com/users/github-merge-queue%5Bbot%5D/subscriptions",
      "organizations_url": "https://api.github.com/users/github-merge-queue%5Bbot%5D/orgs",
      "repos_url": "https://api.github.com/users/github-merge-queue%5Bbot%5D/repos",
      "events_url": "https://api.github.com/users/github-merge-queue%5Bbot%5D/events{/privacy}",
      "received_events_url": "https://api.github.com/users/github-merge-queue%5Bbot%5D/received_events",
      "type": "Bot",
      "user_view_type": "public",
      "site_admin": false
    },
    "jobs_url": "https://api.github.com/repos/darkmatter/nixmac/actions/runs/27446041510/jobs",
    "logs_url": "https://api.github.com/repos/darkmatter/nixmac/actions/runs/27446041510/logs",
    "check_suite_url": "https://api.github.com/repos/darkmatter/nixmac/check-suites/73845649688",
    "artifacts_url": "https://api.github.com/repos/darkmatter/nixmac/actions/runs/27446041510/artifacts",
    "cancel_url": "https://api.github.com/repos/darkmatter/nixmac/actions/runs/27446041510/cancel",
    "rerun_url": "https://api.github.com/repos/darkmatter/nixmac/actions/runs/27446041510/rerun",
    "previous_attempt_url": null,
    "workflow_url": "https://api.github.com/repos/darkmatter/nixmac/actions/workflows/260427457",
    "head_commit": {
      "id": "9e07bb729bb088d2e44c4a28b9d1b2f2363e8e92",
      "tree_id": "1f89dd502d747c38b4d838a14e4ca4c1ecac4e03",
      "message": "Replace `Slice` by `Observable`, simplify and clean up the `Configurable` mechanism (#391)\n\n* state: introduce Observable<T> alongside Slice<T>\n\nNew src/observable.rs introduces a typed state holder that fans out\nchanges to a list of subscriber closures. Subscribers run synchronously\nfrom the write guard's Drop, the same point where Slice<T> emits and\nflushes today.\n\nTwo recurring patterns get convenience builders:\n\n  * .emit_to(&app, \"event_name\") — Tauri event emission\n  * .persist_to(backend)         — JSON-serialize and flush via the\n                                   existing Persistence trait\n\nAnything more exotic (debouncing, breadcrumbs, custom backends) is just\n.subscribe(move |value| ...). Persistence stays as a trait so future\nbackends can layer debouncing/batching without touching the core type.\n\nNo callers in this commit; existing Slice<T> users keep working. The new\nmodule carries #![allow(dead_code)] until callers migrate in C2-C5.\n\n* state: migrate EvolutionLimits from Slice to Observable\n\nevolve::config::load_slice becomes load_observable; persistence is now\nattached via the .persist_to() subscriber, and the change-event name flows\nthrough .emit_to() rather than being a struct field of the slice.\n\nThe onboarding fallback that used VolatileJson is now simply: if no\nstorage path is available, build the observable without a persistence\nsubscriber. That deletes VolatileJson (it had no other users) and removes\none layer of indirection.\n\nConfigurable derive updated to look for `Observable<#name>` in tauri::State\nand call `write_sync()` without an emitter argument. EvolutionLimits is\ncurrently the only Configurable in the codebase, so this change is\nisolated.\n\nOther callers updated to use the new type:\n  - storage/store.rs (4 get/set helpers)\n  - commands/settings_io.rs (export + import)\n  - main.rs (two manage() call sites)\n\n* state: migrate EvolveState from Slice to Observable\n\nevolve_state::load_slice becomes load_observable. The change-event name\nflows through .emit_to() and persistence is attached via .persist_to().\n\nget() and set() switch from try_state::<Slice<EvolveState>> to\ntry_state::<Observable<EvolveState>>; write_sync() drops its emitter\nargument. The \"no managed observable\" fallback path (used during early\nstartup before app.manage) keeps its bespoke emit + flush sequence.\n\nmain.rs updated for both manage() call sites.\n\n* state: migrate GlobalPreferences from Slice to Observable\n\nstate::preferences::load_global_slice becomes load_global_observable.\nEvent name flows through .emit_to(); persistence is attached via\n.persist_to(). main.rs updated for both manage() call sites;\ncommands/settings_io.rs switches the export and import paths to\ntry_state::<Observable<GlobalPreferences>>(), and the write_sync call\ndrops its emitter argument.\n\nThis is the last Slice<T> caller. The type itself, SliceWriteGuard, and\nthe SliceEventEmitter trait now have no users; state/slice/mod.rs gets\n#![allow(dead_code)] as a one-commit shim. The next commit (C6) deletes\nthe dead code and moves persistence + json_io under src/observable/.\n\n* state: delete Slice<T>, move persistence under observable\n\nAfter the three caller migrations, Slice<T> has no users left. This\ncommit:\n\n- Deletes Slice, SliceWriteGuard, and the SliceEventEmitter trait from\n  state/slice/mod.rs. The three slice-level tests are absorbed by\n  observable's own tests; persistence + registry tests move with their\n  respective code.\n- Moves apps/native/src-tauri/src/observable.rs to\n  src/observable/mod.rs and pulls persistence.rs + json_io.rs under it.\n  The Persistence trait + AppDataJson + RepoScopedJson are re-exported\n  at crate::observable::*, so callers say\n  `use crate::observable::{AppDataJson, Persistence, Observable}`.\n- Shrinks state/slice/mod.rs to a thin re-export of registry.rs. The\n  module stays as the home for SliceRegistry until B1 retires it.\n- Updates state/mod.rs prose to describe the new shape (observables, not\n  slices).\n\n* configurable: replace SliceRegistry with compile-time inventory\n\nDrops the runtime SliceRegistry / RegisteredSliceConfig pair in favor of\ncompile-time registration via the `inventory` crate, addressing B1 from\ndocs/2026-06-03-pr-review-followups.md.\n\nThe derive now emits one `inventory::submit!{ ConfigurableMeta {...} }`\nper #[derive(Configurable)] struct, alongside the existing Wry-specialized\nshim functions. `ConfigurableMeta` lives in the `configurable` crate and\ncarries the same triple as the old RegisteredSliceConfig (name +\nschema_fn + set_field_fn). The `inventory` crate is re-exported from\n`configurable::inventory` so the derive output never needs the consuming\ncrate to add it as a direct dep.\n\n`commands/dev_configs.rs` walks `inventory::iter::<ConfigurableMeta>()`\ninstead of looking up `tauri::State<SliceRegistry>`; a new test confirms\nthe link-time submit actually lands (\"EvolutionLimits is registered via\ninventory\") so a future toolchain regression on linker sections is\ncaught before dev settings silently goes empty.\n\nDeleted:\n- apps/native/src-tauri/src/state/slice/ (whole directory)\n- evolve::config::register_slice_config\n- the app.manage(SliceRegistry::default()) line in main.rs\n- the register_slice_config(...) call in the Tauri setup hook\n- state/mod.rs stops re-exporting the `slice` submodule\n\nmain.rs no longer references EvolutionLimits or any other Configurable\nstruct directly — registration happens entirely through the derive.\n\n* configurable: split schema from current value\n\nAddresses B3 from docs/2026-06-03-pr-review-followups.md. The schema half\nis now pure static metadata and no longer requires an AppHandle; the\ndynamic half (current store-backed values) is fetched separately and the\ntwo are joined at the IPC boundary.\n\nType changes in the configurable crate:\n  - ConfigField is gone. Split into:\n    * ConfigFieldSchema { key, label, help, ty, default } — static\n    * ConfigFieldValue  { key, current }                  — dynamic\n  - ConfigurableSchema.fields: Vec<ConfigFieldSchema>  (no `current` field)\n  - New ConfigurableSnapshot { schema, values } is what dev_configs_list\n    returns to the frontend.\n  - ConfigurableMeta gains a `load_value_fn` pointer; `schema_fn` drops\n    its AppHandle argument and now returns ConfigurableSchema directly\n    (no Result, no app).\n\nDerive macro:\n  - schema() generated without an `app` parameter; same value every call.\n  - Adds __configurable_load_value_wry that calls Self::load(app) and\n    serializes to serde_json::Value for the IPC join.\n\ncommands/dev_configs.rs:\n  - dev_configs_list returns Vec<ConfigurableSnapshot>.\n  - snapshot_for() joins the static schema with current values by key.\n\nspecta_gen_ts.rs registers the new types; ipc/types.ts regenerated.\n\nFrontend:\n  - tauriAPI.devConfigs.list() returns ConfigurableSnapshot[].\n  - AutoConfigField now takes `field: ConfigFieldSchema` and a separate\n    `current: JsonValue` prop, instead of pulling `current` off the field.\n  - Both auto-tuning-section.tsx and tuning-tab.tsx build a per-snapshot\n    valuesByKey map and pass each field's current value in.\n  - Storybook stories updated to the new snapshot shape.\n\nAcceptance per the followup doc:\n  - `EvolutionLimits::schema()` is callable without an AppHandle.\n  - Same value every call.\n  - IPC payload joins schema and values at the command boundary.\n\n* db: drop the unused queued_summaries table\n\nPR #330 removed the queue-summarizer pipeline (per-hunk grouping replaced\nby a whole-diff pass), but left the queued_summaries table in\n01-initial/up.sql and its Diesel declaration in tables.rs. Every fresh\nnixmac database has been initializing a table that nothing ever touches.\n\nThis commit:\n\n- Adds 03-drop-queued-summaries migration that drops the table and the\n  idx_queued_summaries_status index. The original CREATE in 01-initial\n  stays untouched so existing user_version=1 databases still apply the\n  full migration history when they upgrade.\n- Removes the diesel::table! declaration and the\n  allow_tables_to_appear_in_same_query! entry from db/tables.rs.\n- Deletes the QueuedSummary struct from sqlite_types.rs (it was already\n  marked #[allow(dead_code)] and had no remaining importers).\n- Adds a migration_03_drops_queued_summaries_table test in db/mod.rs\n  that asserts a freshly initialized database does not contain the\n  table.\n- Drops the stale queue_summarizer.rs line from src/README.md.\n\n* docs(readme): refresh summarize and db sections for the whole-diff pipeline\n\nThe src-tauri/README.md still listed the per-hunk grouping module set\nthat PR #330 deleted (assignments.rs, simplify_grouped.rs,\nmodel_output_types.rs, fresh_changeset/evolved_changeset pipelines).\nThe db/ section likewise listed two deleted store_*_changeset.rs files.\n\nRewrites the summarize/ bullet list to match the current tree (mod,\nfind_existing, group_existing, model_calls, build_prompt, token_budgets,\nsumlog) and the pipelines/ entries (whole_diff, history, commit_message).\nAdds a one-line note explaining the whole-diff direction so a future\nreader doesn't have to dig through git log.\n\nIn the db/ section, replaces store_new_changeset / store_evolved_changeset\nwith the surviving store_whole_diff_changeset, and adds pool.rs + tables.rs\nwhich already existed but were missing from the listing.\n\n* configurable: take a whole-struct payload on set\n\nAddresses B4 from docs/2026-06-03-pr-review-followups.md. Replaces the\nper-field set_field(struct_name, key, value) dispatch with a whole-struct\nset(struct_name, value) that lets Serde validate every field in one pass\non the way into a typed Self.\n\nBackend:\n  - ConfigurableMeta.set_field_fn -> set_fn (now takes one Value, no key).\n  - Derive emits `set<R: Runtime>(app, value)` instead of `set_field(app,\n    key, value)`. Body: deserialize the JSON payload into Self via\n    serde_json::from_value, then replace *observable.write_sync() with\n    the new value. One Serde error per failure, not a per-field match arm.\n  - Derive drops the `__configurable_set_field_wry` shim in favor of\n    `__configurable_set_wry`, with the matching inventory::submit! update.\n  - fields.rs::FieldCode drops the set_field_arm fragment, and\n    GeneratedFields drops the set_field_arms vec; generate_fields no longer\n    needs the struct name string.\n  - dev_config_set IPC command drops its `key` parameter; signature is now\n    (app, struct_name, value).\n\nFrontend:\n  - tauriAPI.devConfigs.set(structName, value) — payload is the whole\n    struct (every field), not a partial update.\n  - AutoConfigField swaps the direct tauriAPI call for an `onCommit(key,\n    value)` callback the parent supplies. Parent owns the snapshot; on\n    each field commit it overlays the new value onto the snapshot's\n    existing values, POSTs the full struct, and updates its local state\n    so the next commit reads back the freshly persisted value.\n  - auto-tuning-section.tsx and tuning-tab.tsx both grow a small\n    commitField helper that does the overlay + POST + return-next-snapshot.\n  - Storybook stories pass `onCommit={async () => undefined}` for static\n    rendering.\n\nTradeoff: whole-struct writes clobber any concurrent backend-side edits\nto other fields. Acceptable for the single-user dev settings panel\n(documented in §2.4 of the followup doc); if a multi-actor config surface\never shows up, this assumption would need revisiting.\n\n* configurable: rename load_value_fn -> load_fn for symmetry with set_fn\n\nConfigurableMeta had `load_value_fn` next to `set_fn` and `schema_fn` —\nthe `_value` suffix was meant to flag \"returns JSON, not Self\", but\nevery field on ConfigurableMeta is a fn pointer that operates on\nserde_json::Value at the boundary, so the suffix wasn't carrying\ninformation.\n\nRenames `load_value_fn` to `load_fn` in the ConfigurableMeta struct,\nthe derive's `__configurable_load_value_wry` shim to\n`__configurable_load_wry`, and the one read site in dev_configs.rs.\nThe typed concrete method `EvolutionLimits::load(app) -> Self` was\nalready named symmetrically with `set(app, Value)`; this aligns the\ntype-erased registry shim with the same convention.\n\n* configurable: split dev_configs IPC into schemas and values\n\ndev_configs_list (returning the joined ConfigurableSnapshot) bundled two\nthings that have different cacheability: the static schema (same value\nevery call) and the dynamic current values (change on every set).\nSplitting the IPC into two commands mirrors the type-level split B3\nalready established and lets the frontend cache schemas independently\nof value refreshes.\n\nBackend:\n  - dev_configs_schemas -> Vec<ConfigurableSchema>: static metadata only.\n  - dev_configs_values  -> HashMap<String, serde_json::Value>: current\n    state of every Configurable, keyed by struct name. Each value is the\n    full struct as a JSON object — same shape load_fn already returns.\n  - Deleted dev_configs_list and the snapshot-construction helper.\n  - main.rs registers the two new commands in place of the old one.\n\nType cleanup in the configurable crate:\n  - Deleted ConfigurableSnapshot (frontend joins schemas + values itself).\n  - Deleted ConfigFieldValue (values come back as struct-shaped JSON\n    objects, so a separate {key, current} wrapper carries no information).\n  - ConfigFieldSchema, ConfigurableSchema, FieldType, EnumVariant survive\n    and are the only configurable-domain types on the IPC boundary.\n  - specta_gen_ts.rs updated; ipc/types.ts regenerated.\n\nFrontend:\n  - tauriAPI.devConfigs gains schemas() and values(); list() removed.\n  - AutoTuningSection and TuningTab keep two pieces of state: schemas\n    (ConfigurableSchema[]) and values (Record<string, JsonValue>). They\n    Promise.all both on mount; on commit they overlay the new field on\n    the struct's existing values, POST the whole struct, and update only\n    the values map. Schemas don't need refreshing.\n  - readStructValues helper extracts the struct's value map (handling the\n    \"not yet loaded\" case as an empty object).\n  - Storybook mocks updated to expose schemas() + values() + set()\n    instead of list() + set().\n\nNet concept count in the configurable crate: down from 4 wrapper types\n(ConfigFieldSchema, ConfigFieldValue, ConfigurableSchema,\nConfigurableSnapshot) to 2 (ConfigFieldSchema, ConfigurableSchema).\n\n* evolve: drop silent EvolutionLimits default fallback\n\nAddresses B6 from docs/2026-06-03-pr-review-followups.md. The\ngenerate_evolution loop read configurable limits with:\n\n    EvolutionLimits::load(app)\n        .inspect_err(|e| warn!(\"EvolutionLimits::load failed ({e}); using defaults\"))\n        .unwrap_or_default()\n\nThis was dead-error-handling AND a silent fallback. The derive-generated\n`load` never returns Err today (it either reads the managed observable\nor synthesizes field defaults), but the `.unwrap_or_default()` would\nmask a real misconfiguration if a future refactor missed\n`app.manage(load_observable(handle)?)` in main.rs's setup hook. The\nagent would then run with EvolutionLimits::default() instead of\npanicking visibly.\n\nReplaces with a direct `app.state::<Observable<EvolutionLimits>>()\n.read_sync().clone()`. `app.state` panics naturally on missing managed\nstate, which is the correct behavior for a startup-time misconfig.\n\nInvestigation notes:\n- generate_evolution has exactly one caller (evolve::lifecycle), which\n  is reached only after Tauri setup completes. The observable is always\n  managed by that point in production.\n- No tests reach generate_evolution; no Tauri mock infrastructure\n  anywhere in the codebase. The fallback was purely defensive against\n  a hypothetical setup bug.\n- The derive's `load` keeps its existing contract (Result<Self> with\n  the silent-fallback path) — not changing the derive surface as part\n  of B6 since the call-site fix is sufficient. Future Configurables\n  that want loud-on-missing should call `app.state` directly the same\n  way.\n\nAlso refreshes the stale comment on `impl Default for EvolutionLimits`:\nit was claiming Default catches \"load failures during onboarding,\" but\nConfiguredRepoScopedJson handles the \"no config_dir yet\" case at the\npersistence layer (returns None, never errors). Default is actually\nload-bearing for two reasons: `preferences::load_or_default` falls back\nto it when the JSON file is absent, and `#[serde(default)]` uses it\nwhen a whole-struct payload arrives with missing fields.\n\nIncludes minor treefmt fixups in observable/{mod,persistence}.rs and\ncommands/{dev_configs,settings_io}.rs that the linter applied during\nthis commit's pre-commit pass — import sort, trailing-blank-line trim,\nand an assert_eq! line break. No behavior change.",
      "timestamp": "2026-06-12T22:08:59Z",
      "author": {
        "name": "Juanpe Bolívar",
        "email": "raskolnikov@gnu.org"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com"
      }
    },
    "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"
    },
    "head_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"
    }
  },
  "workflow": {
    "id": 260427457,
    "node_id": "W_kwDOSB6EzM4Phc7B",
    "name": "Build macOS App",
    "path": ".github/workflows/build.yaml",
    "state": "active",
    "created_at": "2026-04-14T00:44:51.000Z",
    "updated_at": "2026-04-14T00:44:51.000Z",
    "url": "https://api.github.com/repos/darkmatter/nixmac/actions/workflows/260427457",
    "html_url": "https://github.com/darkmatter/nixmac/blob/develop/.github/workflows/build.yaml",
    "badge_url": "https://github.com/darkmatter/nixmac/workflows/Build%20macOS%20App/badge.svg"
  },
  "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-06-12T21:59:33Z",
    "pushed_at": "2026-06-12T22:12:18Z",
    "git_url": "git://github.com/darkmatter/nixmac.git",
    "ssh_url": "git@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": 681685,
    "stargazers_count": 5,
    "watchers_count": 5,
    "language": "Rust",
    "has_issues": true,
    "has_projects": false,
    "has_downloads": true,
    "has_wiki": false,
    "has_pages": true,
    "has_discussions": false,
    "forks_count": 1,
    "mirror_url": null,
    "archived": false,
    "disabled": false,
    "open_issues_count": 96,
    "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": 1,
    "open_issues": 96,
    "watchers": 5,
    "default_branch": "develop",
    "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-06-07T16:53:26Z"
  },
  "sender": {
    "login": "github-merge-queue[bot]",
    "id": 118344674,
    "node_id": "BOT_kgDOBw3L4g",
    "avatar_url": "https://avatars.githubusercontent.com/u/9919?v=4",
    "gravatar_id": "",
    "url": "https://api.github.com/users/github-merge-queue%5Bbot%5D",
    "html_url": "https://github.com/apps/github-merge-queue",
    "followers_url": "https://api.github.com/users/github-merge-queue%5Bbot%5D/followers",
    "following_url": "https://api.github.com/users/github-merge-queue%5Bbot%5D/following{/other_user}",
    "gists_url": "https://api.github.com/users/github-merge-queue%5Bbot%5D/gists{/gist_id}",
    "starred_url": "https://api.github.com/users/github-merge-queue%5Bbot%5D/starred{/owner}{/repo}",
    "subscriptions_url": "https://api.github.com/users/github-merge-queue%5Bbot%5D/subscriptions",
    "organizations_url": "https://api.github.com/users/github-merge-queue%5Bbot%5D/orgs",
    "repos_url": "https://api.github.com/users/github-merge-queue%5Bbot%5D/repos",
    "events_url": "https://api.github.com/users/github-merge-queue%5Bbot%5D/events{/privacy}",
    "received_events_url": "https://api.github.com/users/github-merge-queue%5Bbot%5D/received_events",
    "type": "Bot",
    "user_view_type": "public",
    "site_admin": false
  },
  "installation": {
    "id": 131074261,
    "node_id": "MDIzOkludGVncmF0aW9uSW5zdGFsbGF0aW9uMTMxMDc0MjYx"
  }
}