Skip to content

Add macOS platform support - #4

Open
jwhonce wants to merge 4 commits into
jnovy:mainfrom
jwhonce:wip/macOS
Open

jwhonce wants to merge 4 commits into
jnovy:mainfrom
jwhonce:wip/macOS

Conversation

@jwhonce

@jwhonce jwhonce commented Sep 24, 2026

Copy link
Copy Markdown

Add Darwin build, loader, plugin, filesystem-watch, and mailbox polling support while retaining Linux inotify behavior.

Use kqueue for native macOS filesystem notifications, adapt dynamic-library conventions and Homebrew dependency paths, and cover macOS watcher/plugin behavior in tests. Restore the Linux mailbox path unchanged to avoid platform regressions.

Mount the local ONNX embedding model into the reusable Linux test container so the embedding test runs there, and propagate per-test failures through the test and test-container targets.

Copilot AI lite review requested due to automatic review settings September 24, 2026 18:17

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Unresolved critical build/runtime issues and moderate filesystem-watcher and test-container issues remain.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 3 High severity · 2 Medium severity

Open (5)
What changed in this PR

Adds macOS/Darwin support for builds, filesystem watching, plugins, polling, and related tests while preserving Linux behavior.

Changes:

  • Adds Darwin build, linking, plugin, subprocess, journal, and polling support.
  • Implements kqueue filesystem watching and macOS test coverage.
  • Updates ONNX model discovery and reusable test-container handling.
File Summary
tests/​test_tool_plugin_dlopen.c Uses platform-specific plugin extensions.
tests/​test_onnx_embed.c Supports current and legacy model paths.
tests/​test_fswatch.c Extends filesystem watcher coverage for macOS.
src/​tools.c Preserves plan-link compatibility and replay behavior.
src/​tool_plugin.c Adds .dylib plugin recognition.
src/​telegram.c Adds non-Linux polling behavior.
src/​subprocess.c Adds macOS-compatible pipe and descriptor handling.
src/​matrix.c Adds Darwin polling and credential clearing; critical: explicit_bzero may conflict with the SDK declaration.
src/​main.c Integrates native watcher readiness and draining.
src/​mailbox.c Adds macOS mailbox polling.
src/​journal.c Uses fsync on macOS with error handling.
src/​fswatch_noop.c Restricts the no-op backend to unsupported platforms.
src/​fswatch_kqueue.c Adds kqueue watching; critical: stale deleted/renamed entries prevent re-registration. Moderate: non-recursive watches become recursive, hidden directories are not skipped, and directory events rescan entire subtrees.
Makefile Adds Darwin builds and container testing; critical: Homebrew linker paths appear too late. Moderate: reusable containers may lack the model mount, and plugins lack a resolvable Darwin runpath.
.gitignore Ignores macOS build artifacts.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread Makefile Outdated
Comment thread src/fswatch_kqueue.c Outdated
Comment thread src/matrix.c Outdated
Comment thread Makefile Outdated
Comment thread src/fswatch_kqueue.c Outdated

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Unresolved critical linking and filesystem-watcher safety issues remain, along with additional watcher and test correctness issues.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 2 High severity · 1 Medium severity

Open (3)
Resolved since last review (5)
Previously missed (2)

In code that hasn't changed since last review

Medium severity Recursive kqueue scan can exhaust file descriptors

src/​fswatch_kqueue.c:117

This recursive scan opens one kqueue vnode fd for every file and directory, with no depth or watch-count bound. The TUI calls this on the whole workspace, so a sufficiently large/deep tree can exhaust macOS file descriptors (after which watch_tree() silently skips paths) or recurse excessively; add bounds/resource handling comparable to the Linux backend or use a strategy that does not require one fd per file.

Medium severity Canonicalize watch paths before generating callbacks

src/​fswatch_kqueue.c:177

The public callback contract requires absolute paths, and the Linux backend canonicalizes the input with realpath, but this backend stores path verbatim. Calling fswatch_add with a relative path therefore produces relative callback paths and can break consumers that compare callbacks with canonical workspace paths. Resolve the input before passing it to watch_tree/add_watch.

Comment thread Makefile Outdated
Comment thread src/fswatch_kqueue.c
Comment thread src/fswatch_kqueue.c Outdated
Add Darwin build, loader, plugin, filesystem-watch, and mailbox polling support while retaining Linux inotify behavior.

Use kqueue for native macOS filesystem notifications, adapt dynamic-library conventions and Homebrew dependency paths, and cover macOS watcher/plugin behavior in tests. Restore the Linux mailbox path unchanged to avoid platform regressions.

Mount the local ONNX embedding model into the reusable Linux test container so the embedding test runs there, and propagate per-test failures through the test and test-container targets.

Signed-off-by: Jhon Honce <jhonce@redhat.com>
Apply the fixes identified by Copilot review: place Homebrew linker paths before dependent libraries, use a project-specific secure-zero helper, and recreate reusable test containers when their ONNX model mount is missing or stale.

Harden the kqueue watcher by removing invalidated vnode entries before re-registration and preserving shallow-watch semantics. Add macOS regressions for recreated paths and non-recursive directory watches.

Signed-off-by: Jhon Honce <jhonce@redhat.com>
Apply the latest Copilot review fixes: add an install-relative Darwin run path, keep kqueue event userdata valid through a drain batch, and seed shallow watcher file entries without emitting false create events.

Add macOS regressions for existing direct files and recursive tree removal.

Signed-off-by: Jhon Honce <jhonce@redhat.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment thread src/fswatch_kqueue.c Outdated
Comment thread src/fswatch_kqueue.c Outdated
Comment thread tests/test_onnx_embed.c
Signed-off-by: Jhon Honce <jhonce@redhat.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Unresolved kqueue correctness/resource issues, subtask-link references, and container model/artifact handling remain.

Review effort: Lite
Findings: 1 Medium severity

Open (1)
Resolved since last review (3)
Previously missed (3)

In code that hasn't changed since last review

Medium severity Stale path match suppresses file recreate events

src/​fswatch_kqueue.c:135

When a watched file is deleted and recreated before the next drain, the old entry is still found by path, so was_known becomes true even though add_watch() will replace the old vnode. The scan then suppresses FSW_CREATE for the replacement and callers miss the recreate event; base this check on vnode identity (or remove stale entries before computing it).

This issue also appears on line 191 of the same file.

Medium severity Nonrecursive watches miss direct child directory deletions

src/​fswatch_kqueue.c:203

When a non-recursive watch is added to a directory, direct child directories are only reported during the initial scan; this branch does not register them with kqueue. If one of those child directories is later removed or renamed, the parent directory produces only a nameless NOTE_WRITE, and watch_direct_files() skips the missing entry, so no FSW_DELETE/FSW_RENAME callback is emitted. Linux inotify reports these direct-child events, so the macOS backend does not preserve the watcher contract; track direct child directories for lifecycle events (without recursively scanning their contents) or otherwise reconcile the directory snapshot on parent events.

Medium severity Subtask link conversion drops result references

src/​tools.c:1025

This conversion drops the optional ref field from every rich subtask-link object. ui_md_gen.c obtains its links through plan_subtask_links() and then calls plan_link_ref() to render the subtask result reference (src/ui_md_gen.c:1865-1870), so after this change those references are always missing from the plan view. Return a duplicate of full_links (the existing plan_link_for() already accepts both numeric and object forms), or update the renderer to consume the rich replay root instead.

Comment thread src/fswatch_kqueue.c
Comment on lines +231 to +238
if (recursive && S_ISDIR(st.st_mode)) {
(void)watch_tree(w, resolved, 0, &failed);
} else if (add_watch(w, resolved, S_ISDIR(st.st_mode), 0) != 0) {
return -1;
} else if (S_ISDIR(st.st_mode)) {
(void)watch_direct_files(w, resolved, 0, &failed);
}
return !failed && find_watch(w, resolved) ? 0 : -1;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants