Repository navigation
Proposal: one platform seam plus a CI matrix, so cross-platform PRs become reviewable #67
Description
Activity
@divitsheth @kushagrchitkar — light ping, no urgency, and easy to say no to.
I said in this issue that I would not start building until someone reacted, and I have stuck to that. In the meantime I sent five small PRs that are independent of this proposal, so there is a decision waiting on you here plus some work that is ready whenever you have time.
If you only want to look at one thing, look at #66. It is the smallest and the only one with a user-visible symptom:
$ printf -- '---\ntitle: Notes\n---\n# Notes\n' > almanac/NOTES.MD $ codealmanac search notes codealmanac: wiki page must be markdown: .../almanac/NOTES.MDOne stray filename takes down
search,show,healthandreindex. It reproduces on macOS, not just Windows, becauserglob("*.md")is case-insensitive on APFS whilepage_id_for_pathcompares the suffix exactly. One-line guard at the producer plus a regression test. Tracked in #70.The other four, in the order I would merge them:
PR Why Risk #66 .MDfile breaks every query command, on macOS too (#70)1-line src change #68 3 test fixtures assert against the host platform, not the code tests only #64 uv run pytestwrites your real~/.codealmanacand fails on a second run (#71)tests only #65 is_absolute()does not hold as a containment guard off POSIX (#72)provably a no-op on POSIX #69 IndexStoreis the only store not closing its SQLite connectionsinternal only Things I have already done so this is not work for you:
- They touch zero overlapping files and I test-merged all five onto
main— clean, in any order. - With all five applied, Windows goes from
13 failed, 550 passedto5 failed, 578 passed, and the five survivors are all theos.getuid()call inlaunchd.py— i.e. genuinely macOS-only, tracked in bug: setup --yes crashes on Linux because scheduled automation is macOS/launchd-only #31. - fix(paths): reject every path anchor in repo-relative guards, not just absolute ones #65 and fix(wiki): skip uppercase markdown suffixes so a .MD file cannot break every query #66 are written with explicit
PureWindowsPath/ monkeypatched-glob tests, specifically so the Windows behaviour is verifiable on your existing Ubuntu runner. You do not need a Windows machine to review either one.
One thing I cannot do from my side: the workflow runs on all five are sitting in
action_requiredbecause I am a first-time contributor here, so CI has never actually executed. Everything I have reported is local. If one of you approves the runs, that is probably the cheapest way to get signal on all five at once.On the proposal itself — genuinely fine if the answer is "not now" or "not this shape". I would rather hear that than leave it open. And if #51 is close to acceptable, my preference is still that it lands first and I build on it; I verified it on Windows and left the results on that PR.
Either way I will keep testing things on Windows and reporting what I find, since per #24 that is the box the team does not have.
- They touch zero overlapping files and I test-merged all five onto
This is a proposal, not a PR.
CONTRIBUTING.mdasks for the design choice and rejected alternatives up front, and this touches CI config and a service-layer model, so I would rather get a reaction before writing it. Happy to be told the scope is wrong or that it is not wanted.The problem I think is actually blocking things
There are four PRs open or closed against the same platform gap — #48, #32, #51, and #29 (closed) — plus three issues (#1, #24, #31). None have landed. Reading them together, the pattern is not that any of them is wrong. It is that each one patches a different layer, because there is no agreed place where "which platform are we on" gets decided:
SetupService, before mutationAutomationService.reconcileandconfig setcore/platform.py+ anunsupportedscheduler adaptersystemdadapter next tolaunchdMeanwhile
sys.platformandos.nameappear nowhere insrc/, andapp.pyimportsLaunchdSchedulerAdapterunconditionally. So there is currently no seam to guard at, and any reviewer has to decide the architecture and the fix in the same pass.The second half: nothing is verifiable
All three workflows (
ci.yml,pack-check.yml,publish.yml) runubuntu-latestonly, while the product supports macOS only. That has two consequences that I do not think are obvious:1. The macOS-only automation subsystem is never exercised on macOS.
sync,gardenandupdatescheduling is the product's background loop, and CI has never run it on its target platform.2. The
launchdtests currently pass on Ubuntu by taking error paths.launchd_target()callsos.getuid(), which exists on Linux, so the code proceeds to shell out tolaunchctl. That binary is absent,run_launchctlcatches theOSErrorand converts it toreturncode=1, and the assertions are satisfied by the failure. So green CI on those tests is not evidence that scheduling works — and I only noticed because on Windowsos.getuiddoes not exist at all and the same tests fail loudly instead of quietly.Combined with the note in #24 that none of the devs have a Windows machine, I think this is the real reason platform PRs stall: they are unreviewable. A maintainer is asked to merge code for an OS they cannot run, verified only by the contributor's word.
What I would like to build
Three steps, as separate small PRs, in this order. Each is useful alone and each is revertible.
1. Make the scheduler port platform-neutral. This is the part I think is load-bearing and is not in any of the existing PRs.
plist_pathis currently a field on the service-layerScheduledJobandScheduledJobStatus(services/automation/models.py), and it is part of the public--jsonoutput. So the launchd integration has leaked upward into the service contract — which is what makes "just add another adapter" not actually possible, and is arguably against this repo's own "keep modules honest" rule. I would replace it with something adapter-agnostic (a generic adapter-owned handle field), keeping the current--jsonkey as a macOS-only alias if you want no output break.2. Adopt #51's seam rather than re-inventing it. @YasienDwieb already added
core/platform.pyand anunsupported.pyadapter in #51, which is the layer the others work around. I would rather build on that PR than compete with it — if #51 is close to acceptable, merging it first makes steps 1 and 3 much smaller, and I am happy to review or extend it instead of writing my own. I do not want to duplicate anyone's work here, which is also why I have deliberately stayed out of the OpenCode harness area given #28/#42.3. Add a CI matrix, with honest platform markers.
ubuntu-latest+macos-latest+windows-latestonci.yml, and@pytest.mark.skipif(sys.platform != "darwin")on the tests that genuinely only mean something on macOS (thelaunchdones). The marker half matters as much as the matrix: without it, "green on Windows" is achieved by tests passing for the wrong reason, which is the situation on Ubuntu today.The point of step 3 is specifically to solve the hardware problem. Once it exists, a Windows or Linux PR is verified by the repo's own CI rather than by a contributor's screenshot, and you can review platform changes without owning the platform.
Rejected alternatives
schtasksWindows scheduler now. Out of scope until the port is neutral; degrading cleanly is worth more than scheduling on Windows, and bug: setup --yes crashes on Linux because scheduled automation is macOS/launchd-only #31 shows the crash is the actual user-facing bug.What I am not proposing
No change to the local-only model, the run queue, or the wiki format. No new public env vars or CLI flags. Nothing about hosted features.
Where I am coming from
I am on Windows 11 and have been running the suite there —
13 failed, 550 passedon a clean checkout. I have opened #64, #65 and #66 for three root causes that are independent of this proposal (test-sandbox escape, a path containment guard that does not hold off POSIX, and a.MDglob crash that also affects macOS). Those stand on their own; this issue is about the structural gap underneath the platform ones.Two questions, and I will not start until there is a signal either way:
plist_pathout of the service model) something you would accept?