Skip to content

v0.8.0: always-on — systemd/launchd/Windows templates + /healthz#125

Merged
dfrostar merged 3 commits into
mainfrom
claude/v0.8-always-on
May 18, 2026
Merged

v0.8.0: always-on — systemd/launchd/Windows templates + /healthz#125
dfrostar merged 3 commits into
mainfrom
claude/v0.8-always-on

Conversation

@dfrostar
Copy link
Copy Markdown
Owner

Summary

v0.8 "Always-On" — first beat. Ships the four service templates + the /healthz endpoint + the cross-platform walkthrough. Marketing rollout (LinkedIn, NotebookLM, screencast, cross-doc callouts) deferred per "ship code + minimum docs" scope.

The user-facing claim: neuralmind watch and neuralmind serve now survive reboots and crashes on Linux (systemd), macOS (launchd), and Windows (Task Scheduler). The synapse store accumulates 24/7; the graph view canvas is always at http://127.0.0.1:8765/.

Changes

File What
neuralmind/server.py /healthz route registered before the session-token gate so Docker HEALTHCHECK and systemd ExecStartPost can probe without auth. Returns 200 + {"status": "ok", "version": __version__}.
tests/test_server.py 3 new tests — status+version shape, no-auth, no-Set-Cookie.
scripts/systemd/neuralmind-{watch,serve}.service User-scope units. Restart-on-failure, SIGTERM-clean shutdown, basic hardening. The serve unit's ExecStartPost polls /healthz for up to 5s.
scripts/launchd/com.neuralmind.{watch,serve}.plist macOS user agents. RunAtLoad + KeepAlive + ThrottleInterval.
docs/use-cases/always-on.md New page — per-platform install/verify/uninstall/troubleshooting + Docker HEALTHCHECK snippet.
docs/wiki/Scheduling-Guide.md New "Always-on" section above the existing recurring-audit instructions — two PowerShell Register-ScheduledTask blocks + the /healthz verification snippet.
RELEASE_NOTES_v0.8.0.md Minimal release notes. Marketing arc explicitly deferred.

Deferred

  • Aider integration block in README. Investigated 2026-05-17: current Aider stable has no MCP-client support. Will add when upstream lands it.
  • Cross-doc marketing rollout. README hero callout, wiki Home "What's New" entry, GitHub Pages, LinkedIn drafts, NotebookLM pack, screencast script — all deferred so this release ships code + minimum docs.

Test plan

  • python -m pytest tests/ — 391 passed (3 new), 4 environmental skips
  • ruff check clean on changed files
  • black --check clean on changed files
  • Maintainer to verify: systemctl --user enable --now neuralmind-{watch,serve} works on a real Linux machine
  • Maintainer to verify: launchctl load -w works on a real macOS machine (if you have one)
  • Maintainer to verify: the Windows Register-ScheduledTask blocks land cleanly on a Windows host

Order vs the rename PR (#124)

This PR doesn't depend on #124 merging first. It branched off the same main as #124 and only touches code + new scripts/docs. Merge either order. When #124 lands, this branch can rebase to pick up the v0.7.0 naming in shared docs (LinkedIn drafts, etc.), but nothing here breaks.

Versioning

Two feat(...) commits (the /healthz + templates landing). Per the project's 0.x feat = minor rule (PR #114), this should propose a clean v0.8.0 from release-please once it merges.

Issues

Closes part of #119 — the code + minimum docs. Full close once the marketing pass lands as a v0.8.1 or rolled into v0.8.x.

https://claude.ai/code/session_01SH6iHNAqeMJHXdq7ubVcuJ


Generated by Claude Code

…r v0.8

Always-On release: ship the four service templates + a stdlib /healthz
endpoint so `neuralmind watch` and `neuralmind serve` are first-class
production processes across reboots and crashes.

Changes:
- neuralmind/server.py: /healthz route registered before the
  session-token gate so Docker HEALTHCHECK and systemd ExecStartPost
  can probe without threading auth. Returns 200 + JSON
  {"status": "ok", "version": neuralmind.__version__}.
- tests/test_server.py: 3 new tests — status+version shape, no-auth,
  no-Set-Cookie.
- scripts/systemd/neuralmind-{watch,serve}.service: user-scope units.
  serve unit's ExecStartPost polls /healthz for up to 5s.
- scripts/launchd/com.neuralmind.{watch,serve}.plist: macOS user
  agents with RunAtLoad + KeepAlive + ThrottleInterval.
- docs/wiki/Scheduling-Guide.md: new "Always-on" PowerShell section
  with two Register-ScheduledTask blocks + the /healthz verification
  snippet.
- docs/use-cases/always-on.md: cross-platform walkthrough
  (Linux/macOS/Windows + Docker HEALTHCHECK) with install + verify +
  uninstall + troubleshooting.
- RELEASE_NOTES_v0.8.0.md: minimal release notes. Marketing rollout
  (LinkedIn, NotebookLM, screencast, cross-doc callouts) deferred to
  a follow-up per "ship code + minimum docs" scope.

Aider integration block deferred — current Aider stable has no
MCP-client support per docs check 2026-05-17.

Tests: 391 passing (3 new) + 4 environmental skips.

Closes part of #119 (the code + minimum docs); full close once the
marketing pass lands.

https://claude.ai/code/session_01SH6iHNAqeMJHXdq7ubVcuJ
Copilot AI review requested due to automatic review settings May 17, 2026 19:32
@github-actions github-actions Bot added bug Something isn't working documentation Improvements or additions to documentation enhancement New feature or request question Further information is requested labels May 17, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 17, 2026

NeuralMind self-benchmark

Status: PASS — floor , measured 5.9×.

Phase 1 — Reduction on committed fixture

  • Average reduction: 5.9×
  • Top-k retrieval hit rate: 71.7%
  • Naive baseline: 47,360 tokens (all fixture files concatenated)
  • NeuralMind total: 8,149 tokens across 10 queries
  • Estimated monthly savings @ 100 queries/day on Claude 3.5 Sonnet: ~$35.30
# Query Shape Naive NeuralMind Ratio Hit
1 auth-flow cross-file 4,736 815 5.8× 33.3%
2 api-endpoints focused 4,736 809 5.9× 100.0%
3 billing-flow cross-file 4,736 846 5.6× 33.3%
4 user-storage cross-file 4,736 672 7.0× 50.0%
5 jwt-verify focused 4,736 681 7.0× 100.0%
6 stripe-webhook focused 4,736 838 5.7× 100.0%
7 create-user cross-file 4,736 794 6.0× 50.0%
8 refund focused 4,736 827 5.7× 100.0%
9 db-choice identity 4,736 899 5.3× 100.0%
10 invoice-send cross-file 4,736 968 4.9× 50.0%

Phase 2 — Learning uplift

  • Memory events logged: 20
  • Learned patterns: 20
  • Reduction ratio after neuralmind learn: 5.9× (Δ +0.00× vs. cold)
  • Top-k hit rate after learning: 71.7% (Δ +0.0 points vs. cold)

Note: uplift numbers on a 500-line fixture are intentionally modest — the point is to
verify the learning mechanism persists and applies. On real production repos the lift
is larger; this test only catches regressions in persistence.

Assumptions

  • Baseline: every .py file in tests/fixtures/sample_project/ concatenated.
  • Tokenizer: tiktoken GPT-4o encoding (per-model breakdown in multi_model.json if generated).
  • Pricing: Claude 3.5 Sonnet input @ $3.0/MTok.
  • Regression floor: — well below NeuralMind's typical 40–70× on real repos.

Per-model token reduction

Model Tokenizer Naive NeuralMind Ratio Source
GPT-4o / GPT-4o-mini tiktoken o200k_base 4,739 927 5.1× measured
GPT-4 / GPT-3.5-turbo tiktoken cl100k_base 4,710 918 5.1× measured
Claude 3.5 Sonnet estimated: GPT-4o × 1.08 — install anthropic for an exact count 5,118 1,001 5.1× estimated
Llama 3 (70B) estimated: GPT-4o × 1.22 — Llama tokenizer requires model weights; estimate based on published vocab ratios 5,781 1,130 5.1× estimated

Rows marked measured use the provider's real tokenizer. Rows marked
estimated apply a published vocab-size correction to the GPT-4o count —
honest approximations, not hardcoded claims.


Automated by .github/workflows/ci-benchmark.yml — regenerate locally with python -m tests.benchmark.run.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3f22efecff

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=read-write
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Use a valid ProtectHome value in systemd templates

ProtectHome=read-write is not a valid systemd value, so the hardening line is ignored; systemd-analyze verify scripts/systemd/neuralmind-watch.service (and the same check on neuralmind-serve.service) reports Failed to parse protect home value, ignoring: read-write. This leaves the unit with ProtectSystem=strict but without the intended home-directory override, which can break always-on operation when the service needs to write under the project directory (the default WorkingDirectory is in %h).

Useful? React with 👍 / 👎.

…write

Codex P1 review on #125: ProtectHome only accepts
true/false/read-only/tmpfs — "read-write" is silently ignored by
systemd-analyze, leaving the unit with ProtectSystem=strict but no
home-directory override. Means writes to %h/your-project/.neuralmind/
would fail at runtime under the intended hardening.

Fix: drop the invalid ProtectHome line and add an explicit
ReadWritePaths=%h allowlist that documents the actual intent (the
unit needs to write the project's .neuralmind/ state). Same change
applied symmetrically to neuralmind-serve.service.

Verified locally: systemd-analyze verify on both files now reports
only the expected "ExecStart not executable" template warning, no
more ProtectHome parse errors.

Review: #125 (Codex P1)

https://claude.ai/code/session_01SH6iHNAqeMJHXdq7ubVcuJ
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds the v0.8 always-on foundation for running NeuralMind’s watcher and graph-view server as background services, plus an unauthenticated /healthz endpoint for readiness/monitoring probes.

Changes:

  • Adds /healthz to neuralmind serve and tests its response/auth behavior.
  • Adds systemd and launchd service templates for watch and serve.
  • Adds always-on user docs, Windows Task Scheduler examples, and v0.8.0 release notes.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 16 comments.

Show a summary per file
File Description
neuralmind/server.py Registers unauthenticated /healthz before auth gating.
tests/test_server.py Adds server tests for /healthz.
scripts/systemd/neuralmind-watch.service Adds Linux user service template for neuralmind watch.
scripts/systemd/neuralmind-serve.service Adds Linux user service template for neuralmind serve.
scripts/launchd/com.neuralmind.watch.plist Adds macOS launchd template for watch.
scripts/launchd/com.neuralmind.serve.plist Adds macOS launchd template for serve.
docs/use-cases/always-on.md Adds cross-platform always-on walkthrough.
docs/wiki/Scheduling-Guide.md Adds Windows Task Scheduler always-on examples.
RELEASE_NOTES_v0.8.0.md Adds v0.8.0 release notes.
Comments suppressed due to low confidence (13)

scripts/systemd/neuralmind-watch.service:45

  • ProtectHome=read-write is not a supported ProtectHome value on systemd; the directive will be rejected or ignored, so this template may not load with the intended hardening. Use a supported value and explicitly allow the project write path if needed.
# here so $HOME stays writable; the explicit ReadWritePaths is what

scripts/systemd/neuralmind-serve.service:45

  • ProtectHome=read-write is not a supported ProtectHome value on systemd; the directive will be rejected or ignored, so this template may not load with the intended hardening. Use a supported value and explicitly allow the project write path if needed.
PrivateTmp=true

scripts/systemd/neuralmind-serve.service:34

  • This service starts neuralmind serve without --no-browser, and the CLI opens a browser by default. As a daemon this can spawn a browser or xdg-open attempt on every boot/restart instead of running quietly in the background.
ExecStart=/usr/local/bin/neuralmind serve . --port 8765

scripts/launchd/com.neuralmind.serve.plist:40

  • The launchd service runs neuralmind serve without --no-browser, but the CLI opens a browser by default. A user agent will therefore try to launch a browser on every login/restart instead of running quietly as a background service.
    <string>serve</string>
    <string>.</string>
    <string>--port</string>
    <string>8765</string>

docs/wiki/Scheduling-Guide.md:109

  • Windows scheduled tasks have a default execution time limit (commonly 72 hours). Because this graph-view task is meant to run continuously, the settings should disable the time limit; otherwise serve can be stopped after a few days despite being described as always-on.
  -Settings (New-ScheduledTaskSettingsSet -StartWhenAvailable `
    -RestartCount 3 -RestartInterval (New-TimeSpan -Minutes 1))

docs/use-cases/always-on.md:138

  • Windows scheduled tasks have a default execution time limit (commonly 72 hours). Because this graph-view task is meant to run continuously, the settings should disable the time limit; otherwise serve can be stopped after a few days despite being described as always-on.
  -Settings (New-ScheduledTaskSettingsSet -StartWhenAvailable `
    -RestartCount 3 -RestartInterval (New-TimeSpan -Minutes 1))

docs/use-cases/always-on.md:154

  • The repo-root runtime image is based on python:*-slim and does not install curl, so this HEALTHCHECK will fail in the image the paragraph tells users to use unless they also add curl. Use a stdlib Python probe or document the extra package installation.
HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \
  CMD curl -fsS http://127.0.0.1:8765/healthz || exit 1

scripts/systemd/neuralmind-watch.service:24

  • The instructions suggest using this as an instanced @.service, but the unit does not use %i/%I or an environment file in WorkingDirectory or ExecStart. Multiple instances would still point at the same placeholder project unless each copied unit is edited separately.
# This is a TEMPLATE — change WorkingDirectory and ExecStart to point
# at your project. Multiple projects? Copy the file with a suffix:
#   cp neuralmind-watch.service ~/.config/systemd/user/neuralmind-watch@.service
# and use the @<project> instance form.

scripts/systemd/neuralmind-serve.service:35

  • neuralmind serve builds the index before it starts listening, so this 5-second ExecStartPost can fail and restart the unit on first run or larger projects even though the server is healthy once the build completes. The readiness probe needs a much longer startup window or should be removed from the template.
ExecStartPost=/bin/sh -c 'for i in $(seq 1 20); do curl -fsS http://127.0.0.1:8765/healthz >/dev/null && exit 0; sleep 0.25; done; exit 1'

scripts/systemd/neuralmind-serve.service:38

  • neuralmind serve only handles KeyboardInterrupt; it does not install the SIGTERM handler that watch uses. With this systemd stop signal, the process can terminate without running the server cleanup path for the watcher/event-log bridge, so the template's “clean shutdown” expectation is not actually met.
KillSignal=SIGTERM

RELEASE_NOTES_v0.8.0.md:119

  • These macOS verification steps also assume a repository checkout. A user who just upgraded the package will not have scripts/launchd/ installed from the wheel, so the instructions need a download path or an explicit checkout prerequisite.
# macOS: install + verify launchd plists
cp scripts/launchd/com.neuralmind.{watch,serve}.plist ~/Library/LaunchAgents/
# edit WorkingDirectory + log paths, then:

docs/use-cases/always-on.md:29

  • These commands only work from a source checkout. Since the package wheel does not install top-level scripts/, PyPI/pipx users following the walkthrough need an explicit raw GitHub download command or a note to clone the repository first.
```bash
# 1. Copy the templates
mkdir -p ~/.config/systemd/user
cp scripts/systemd/neuralmind-watch.service ~/.config/systemd/user/
cp scripts/systemd/neuralmind-serve.service ~/.config/systemd/user/

docs/use-cases/always-on.md:76

  • These copy commands only work from a source checkout. Since the package wheel does not install top-level scripts/, PyPI/pipx users following the walkthrough need an explicit raw GitHub download command or a note to clone the repository first.
```bash
# 1. Copy the templates
cp scripts/launchd/com.neuralmind.watch.plist ~/Library/LaunchAgents/
cp scripts/launchd/com.neuralmind.serve.plist ~/Library/LaunchAgents/

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +6 to +7
by default. Use `--host 0.0.0.0` only if you understand the security
implications (see docs/SECURITY-GUIDE.md).
Comment thread docs/wiki/Scheduling-Guide.md Outdated
Register-ScheduledTask -TaskName "NeuralMind-Serve" `
-Action (New-ScheduledTaskAction `
-Execute "neuralmind" `
-Argument "serve C:\path\to\your-project --port 8765") `
Comment thread docs/use-cases/always-on.md Outdated
Register-ScheduledTask -TaskName "NeuralMind-Serve" `
-Action (New-ScheduledTaskAction `
-Execute "neuralmind" `
-Argument "serve C:\path\to\your-project --port 8765") `
Comment on lines +99 to +100
-Settings (New-ScheduledTaskSettingsSet -StartWhenAvailable `
-RestartCount 3 -RestartInterval (New-TimeSpan -Minutes 1))
Comment on lines +128 to +129
-Settings (New-ScheduledTaskSettingsSet -StartWhenAvailable `
-RestartCount 3 -RestartInterval (New-TimeSpan -Minutes 1))
@@ -0,0 +1,52 @@
# NeuralMind graph-view server — user-scope systemd unit.
#
# Keeps `neuralmind serve` reachable across reboots. The graph view is
Comment on lines +8 to +10
Three platforms, same shape: pick the template, point it at your
project, enable it. The templates live in [`scripts/systemd/`](../../scripts/systemd/)
and [`scripts/launchd/`](../../scripts/launchd/) in this repo.
Comment thread RELEASE_NOTES_v0.8.0.md Outdated
Comment on lines +109 to +118
# Linux: install + verify systemd units
mkdir -p ~/.config/systemd/user
cp scripts/systemd/neuralmind-{watch,serve}.service ~/.config/systemd/user/
# edit WorkingDirectory in both, then:
systemctl --user daemon-reload
systemctl --user enable --now neuralmind-watch neuralmind-serve
systemctl --user status neuralmind-watch neuralmind-serve

# macOS: install + verify launchd plists
cp scripts/launchd/com.neuralmind.{watch,serve}.plist ~/Library/LaunchAgents/
Comment thread RELEASE_NOTES_v0.8.0.md Outdated
Comment on lines +32 to +36
- **`scripts/systemd/neuralmind-watch.service`** — user-scope unit for
the file watcher. Restart-on-failure, SIGTERM-clean shutdown, basic
hardening (`NoNewPrivileges`, `PrivateTmp`, `ProtectSystem=strict`).
- **`scripts/systemd/neuralmind-serve.service`** — same for the graph
view, plus an `ExecStartPost` that polls `/healthz` for up to 5
Comment thread tests/test_server.py Outdated
Comment on lines +191 to +194
Avoids polluting the cookie jar of monitoring clients."""
fake_mind = SimpleNamespace(recent_queries=lambda n=20: [])
with _running_server(fake_mind) as base:
with urllib.request.urlopen(base + "/healthz", timeout=5) as resp:
…ws time limit, healthcheck

Bundle of fixes for PR #125 Copilot review:

- scripts/launchd/com.neuralmind.serve.plist: rewrote the XML comment
  to remove the `--host` literal that contained `--`, which the XML
  spec forbids inside comments. xmllint now validates the file.
  Confirmed with `xmllint --noout`.
- scripts/launchd/com.neuralmind.serve.plist + scripts/systemd/neuralmind-serve.service:
  add `--no-browser` to ExecStart / ProgramArguments so the daemon
  doesn't spawn a browser on every login/restart.
- scripts/systemd/neuralmind-serve.service: bump ExecStartPost
  /healthz probe from 5s → 60s. `neuralmind serve` builds the
  embedding index before binding the socket; first runs on large
  projects can exceed 5s.
- scripts/systemd/neuralmind-{watch,serve}.service: inline comments
  now mention `loginctl enable-linger "$USER"` for reboot survival
  without an active login session.
- scripts/systemd/neuralmind-watch.service: drop the misleading
  "@.service instance form" hint — the template didn't actually use
  %i/%I. Replaced with explicit "copy once per project with a
  distinct name" guidance.
- docs/use-cases/always-on.md + docs/wiki/Scheduling-Guide.md: add
  --no-browser to the Windows Register-ScheduledTask serve example
  and -ExecutionTimeLimit (New-TimeSpan -Seconds 0) to both watch +
  serve, disabling the default 72-hour cap.
- docs/use-cases/always-on.md: fix the example /healthz version
  string (0.7.0 → 0.8.0), document how to retrieve the tokenized
  canvas URL from journalctl, fix the Scheduling-Guide anchor to
  match the v0.8 heading suffix, and replace the curl-based Docker
  HEALTHCHECK with a stdlib Python urllib probe (curl isn't in
  python:slim).
- docs/use-cases/always-on.md: new "No checkout? Fetch the templates
  directly" section at the top with raw.githubusercontent.com URLs
  for pip/pipx/uv/Docker users — the wheel doesn't package
  scripts/.
- RELEASE_NOTES_v0.8.0.md: soften "canvas always at 127.0.0.1:8765/"
  claim (the canvas requires the per-session token by default;
  document --no-auth as an opt-in trade-off), soften the 5s readiness
  claim, and update the Verification block to use curl-from-GitHub
  instead of cp-from-checkout.
- tests/test_server.py: expand test_healthz_sets_no_cookie to cover
  the auth-enabled path so a regression that starts a cookie only
  when auth is configured can't slip through.

Skipped: Copilot's SIGTERM claim — fact-checked against cli.py:438-439,
which DOES install both SIGINT and SIGTERM handlers shared by watch
and serve. The "clean shutdown" claim is accurate.

Verified locally: 18 server tests passing, both plists xmllint-clean,
both systemd units systemd-analyze-clean (only the expected
template-placeholder ExecStart note remains).

https://claude.ai/code/session_01SH6iHNAqeMJHXdq7ubVcuJ
@dfrostar dfrostar merged commit 23716e6 into main May 18, 2026
14 checks passed
dfrostar added a commit that referenced this pull request May 18, 2026
PR #125 (v0.8 always-on) was merged with merge-commit title
"v0.8.0: always-on…" instead of conventional-commit format
(feat(serve): …). release-please reads merge-commit titles for
non-squash merges and missed the feat: prefix, so it proposed v0.7.1
(PR #127, now closed) covering only the fix(ci) PAT patch from PR #126.

The always-on code (/healthz, systemd/launchd templates, always-on.md
walkthrough, RELEASE_NOTES_v0.8.0.md) is already on main. This empty
commit's `Release-As: 0.8.0` footer overrides release-please's version
proposal so the next release-please PR proposes v0.8.0 with the
correct combined changelog (always-on + PAT fix).

Process-fix going forward: merge commit titles for non-squash merges
need conventional-commit format (this PR's own merge title is the
example).

Release-As: 0.8.0

https://claude.ai/code/session_01SH6iHNAqeMJHXdq7ubVcuJ
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working documentation Improvements or additions to documentation enhancement New feature or request question Further information is requested

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants