fix(context): refresh get_docs when packages change on disk - #117
Open
gsdali wants to merge 1 commit into
Open
Conversation
`context add` writes to ~/.context/packages from a separate process, but a running `serve` reads that directory once at startup. A long-lived stdio server therefore kept serving the package list it saw when it launched, and `get_docs` reported a package as missing when it was already installed. The only way out was to reconnect the client. The mechanism to avoid that already existed and was wired to a single trigger. refreshGetDocsTool rebuilds the tool's `library` enum and calls sendToolListChanged, which is the MCP notification telling a client to re-fetch the tool list; it was called only from the download_package handler, so packages that arrived any other way were invisible. This adds a second trigger rather than a second mechanism. - watch.ts: a small debounced directory watcher. Debounced because one install is several filesystem events (a temp file, then a rename), which would otherwise rebuild the schema three or four times. The watcher is unref'd so it never keeps the process alive on its own, and a callback that throws cannot tear it down. - serve: watches the data directory, reloads the store and refreshes the tool. Skipped when --libs is set, because that flag pins the session to a fixed library set on purpose and picking up new packages would defeat it. - refreshGetDocsTool is now public, since the trigger lives outside the class. - loadPackages now syncs rather than only adding. It is called repeatedly now, so a package removed from disk has to leave the store too, which the add-only version could not express. HTTP transport needed no change: it builds a fresh ContextServer per session over the same store, so a session started after an install already sees it. Only the long-lived stdio server needed the live notification. Tests cover the watcher directly: a single change fires once, a burst collapses to one call, stopping prevents further calls, a throwing callback does not kill the watcher, and a missing directory is a no-op. Verified discriminating by removing the debounce, which fails three of the five. Local `pnpm test` shows 40 pre-existing failures in this environment, identical before and after this change: better-sqlite3 11.10.0 does not build against Node v26, so every sqlite-backed test errors on the missing bindings. The five new tests pass (181 to 186 passing). pnpm lint and pnpm build are clean.
🦋 Changeset detectedLatest commit: f093bce The changes in this PR will be included in the next version bump. This PR includes changesets to release 2 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
gsdali
added a commit
to SecondMouseAU/OCCTMCP
that referenced
this pull request
Aug 21, 2026
Two corrections, one of which was actively costing time. **The per-class OCCT reference manual IS indexed**, as `occt-refman`, 37,008 sections. This copy said it was not, which sent an agent to the bundled headers or to WebFetch as a first resort rather than a last one. Those routes remain, scoped to the case that needs them: a class genuinely absent after an OCCT bump, before the package is rebuilt. **`context query` is now a lookup step in its own right.** `get_docs` takes its `library` from an enum fixed when the MCP server connected, and the server rebuilds that list only for packages arriving through its own download_package tool. Anything installed by `context add` is therefore invisible to `get_docs` for the rest of the session while `context query` sees it immediately. The failure reads as "package missing", which an agent takes at face value and escalates on, so the policy now says plainly that it means "not in the list I was handed". Fixed upstream in neuledge/context#117. Also records that the `ecosystem` package is indexed, so this standard and every shared policy are themselves queryable, and what a version in the cache means: a package is pinned to a release and does not follow its repo. Copied verbatim from SecondMouseAU/ecosystem okf/policies/context-first.md.
gsdali
added a commit
to SecondMouseAU/OCCTSwiftAIS
that referenced
this pull request
Aug 21, 2026
Two corrections, one of which was actively costing time. **The per-class OCCT reference manual IS indexed**, as `occt-refman`, 37,008 sections. This copy said it was not, which sent an agent to the bundled headers or to WebFetch as a first resort rather than a last one. Those routes remain, scoped to the case that needs them: a class genuinely absent after an OCCT bump, before the package is rebuilt. **`context query` is now a lookup step in its own right.** `get_docs` takes its `library` from an enum fixed when the MCP server connected, and the server rebuilds that list only for packages arriving through its own download_package tool. Anything installed by `context add` is therefore invisible to `get_docs` for the rest of the session while `context query` sees it immediately. The failure reads as "package missing", which an agent takes at face value and escalates on, so the policy now says plainly that it means "not in the list I was handed". Fixed upstream in neuledge/context#117. Also records that the `ecosystem` package is indexed, so this standard and every shared policy are themselves queryable, and what a version in the cache means: a package is pinned to a release and does not follow its repo. Copied verbatim from SecondMouseAU/ecosystem okf/policies/context-first.md.
gsdali
added a commit
to SecondMouseAU/OCCTSwiftInteraction
that referenced
this pull request
Aug 21, 2026
Two corrections, one of which was actively costing time. **The per-class OCCT reference manual IS indexed**, as `occt-refman`, 37,008 sections. This copy said it was not, which sent an agent to the bundled headers or to WebFetch as a first resort rather than a last one. Those routes remain, scoped to the case that needs them: a class genuinely absent after an OCCT bump, before the package is rebuilt. **`context query` is now a lookup step in its own right.** `get_docs` takes its `library` from an enum fixed when the MCP server connected, and the server rebuilds that list only for packages arriving through its own download_package tool. Anything installed by `context add` is therefore invisible to `get_docs` for the rest of the session while `context query` sees it immediately. The failure reads as "package missing", which an agent takes at face value and escalates on, so the policy now says plainly that it means "not in the list I was handed". Fixed upstream in neuledge/context#117. Also records that the `ecosystem` package is indexed, so this standard and every shared policy are themselves queryable, and what a version in the cache means: a package is pinned to a release and does not follow its repo. Copied verbatim from SecondMouseAU/ecosystem okf/policies/context-first.md.
gsdali
added a commit
to SecondMouseAU/OCCTSwiftIO
that referenced
this pull request
Aug 21, 2026
Two corrections, one of which was actively costing time. **The per-class OCCT reference manual IS indexed**, as `occt-refman`, 37,008 sections. This copy said it was not, which sent an agent to the bundled headers or to WebFetch as a first resort rather than a last one. Those routes remain, scoped to the case that needs them: a class genuinely absent after an OCCT bump, before the package is rebuilt. **`context query` is now a lookup step in its own right.** `get_docs` takes its `library` from an enum fixed when the MCP server connected, and the server rebuilds that list only for packages arriving through its own download_package tool. Anything installed by `context add` is therefore invisible to `get_docs` for the rest of the session while `context query` sees it immediately. The failure reads as "package missing", which an agent takes at face value and escalates on, so the policy now says plainly that it means "not in the list I was handed". Fixed upstream in neuledge/context#117. Also records that the `ecosystem` package is indexed, so this standard and every shared policy are themselves queryable, and what a version in the cache means: a package is pinned to a release and does not follow its repo. Copied verbatim from SecondMouseAU/ecosystem okf/policies/context-first.md.
gsdali
added a commit
to SecondMouseAU/OCCTSwiftMesh
that referenced
this pull request
Aug 21, 2026
Two corrections, one of which was actively costing time. **The per-class OCCT reference manual IS indexed**, as `occt-refman`, 37,008 sections. This copy said it was not, which sent an agent to the bundled headers or to WebFetch as a first resort rather than a last one. Those routes remain, scoped to the case that needs them: a class genuinely absent after an OCCT bump, before the package is rebuilt. **`context query` is now a lookup step in its own right.** `get_docs` takes its `library` from an enum fixed when the MCP server connected, and the server rebuilds that list only for packages arriving through its own download_package tool. Anything installed by `context add` is therefore invisible to `get_docs` for the rest of the session while `context query` sees it immediately. The failure reads as "package missing", which an agent takes at face value and escalates on, so the policy now says plainly that it means "not in the list I was handed". Fixed upstream in neuledge/context#117. Also records that the `ecosystem` package is indexed, so this standard and every shared policy are themselves queryable, and what a version in the cache means: a package is pinned to a release and does not follow its repo. Copied verbatim from SecondMouseAU/ecosystem okf/policies/context-first.md.
gsdali
added a commit
to SecondMouseAU/OCCTSwiftScripts
that referenced
this pull request
Aug 21, 2026
Two corrections, one of which was actively costing time. **The per-class OCCT reference manual IS indexed**, as `occt-refman`, 37,008 sections. This copy said it was not, which sent an agent to the bundled headers or to WebFetch as a first resort rather than a last one. Those routes remain, scoped to the case that needs them: a class genuinely absent after an OCCT bump, before the package is rebuilt. **`context query` is now a lookup step in its own right.** `get_docs` takes its `library` from an enum fixed when the MCP server connected, and the server rebuilds that list only for packages arriving through its own download_package tool. Anything installed by `context add` is therefore invisible to `get_docs` for the rest of the session while `context query` sees it immediately. The failure reads as "package missing", which an agent takes at face value and escalates on, so the policy now says plainly that it means "not in the list I was handed". Fixed upstream in neuledge/context#117. Also records that the `ecosystem` package is indexed, so this standard and every shared policy are themselves queryable, and what a version in the cache means: a package is pinned to a release and does not follow its repo. Copied verbatim from SecondMouseAU/ecosystem okf/policies/context-first.md.
gsdali
added a commit
to SecondMouseAU/OCCTSwiftTools
that referenced
this pull request
Aug 21, 2026
Two corrections, one of which was actively costing time. **The per-class OCCT reference manual IS indexed**, as `occt-refman`, 37,008 sections. This copy said it was not, which sent an agent to the bundled headers or to WebFetch as a first resort rather than a last one. Those routes remain, scoped to the case that needs them: a class genuinely absent after an OCCT bump, before the package is rebuilt. **`context query` is now a lookup step in its own right.** `get_docs` takes its `library` from an enum fixed when the MCP server connected, and the server rebuilds that list only for packages arriving through its own download_package tool. Anything installed by `context add` is therefore invisible to `get_docs` for the rest of the session while `context query` sees it immediately. The failure reads as "package missing", which an agent takes at face value and escalates on, so the policy now says plainly that it means "not in the list I was handed". Fixed upstream in neuledge/context#117. Also records that the `ecosystem` package is indexed, so this standard and every shared policy are themselves queryable, and what a version in the cache means: a package is pinned to a release and does not follow its repo. Copied verbatim from SecondMouseAU/ecosystem okf/policies/context-first.md.
gsdali
added a commit
to SecondMouseAU/OCCTSwiftViewport
that referenced
this pull request
Aug 21, 2026
Two corrections, one of which was actively costing time. **The per-class OCCT reference manual IS indexed**, as `occt-refman`, 37,008 sections. This copy said it was not, which sent an agent to the bundled headers or to WebFetch as a first resort rather than a last one. Those routes remain, scoped to the case that needs them: a class genuinely absent after an OCCT bump, before the package is rebuilt. **`context query` is now a lookup step in its own right.** `get_docs` takes its `library` from an enum fixed when the MCP server connected, and the server rebuilds that list only for packages arriving through its own download_package tool. Anything installed by `context add` is therefore invisible to `get_docs` for the rest of the session while `context query` sees it immediately. The failure reads as "package missing", which an agent takes at face value and escalates on, so the policy now says plainly that it means "not in the list I was handed". Fixed upstream in neuledge/context#117. Also records that the `ecosystem` package is indexed, so this standard and every shared policy are themselves queryable, and what a version in the cache means: a package is pinned to a release and does not follow its repo. Copied verbatim from SecondMouseAU/ecosystem okf/policies/context-first.md.
gsdali
added a commit
to SecondMouseAU/simpleOCCTVP
that referenced
this pull request
Aug 21, 2026
Two corrections, one of which was actively costing time. **The per-class OCCT reference manual IS indexed**, as `occt-refman`, 37,008 sections. This copy said it was not, which sent an agent to the bundled headers or to WebFetch as a first resort rather than a last one. Those routes remain, scoped to the case that needs them: a class genuinely absent after an OCCT bump, before the package is rebuilt. **`context query` is now a lookup step in its own right.** `get_docs` takes its `library` from an enum fixed when the MCP server connected, and the server rebuilds that list only for packages arriving through its own download_package tool. Anything installed by `context add` is therefore invisible to `get_docs` for the rest of the session while `context query` sees it immediately. The failure reads as "package missing", which an agent takes at face value and escalates on, so the policy now says plainly that it means "not in the list I was handed". Fixed upstream in neuledge/context#117. Also records that the `ecosystem` package is indexed, so this standard and every shared policy are themselves queryable, and what a version in the cache means: a package is pinned to a release and does not follow its repo. Copied verbatim from SecondMouseAU/ecosystem okf/policies/context-first.md.
gsdali
added a commit
to SecondMouseAU/SwiftDXF
that referenced
this pull request
Aug 21, 2026
Two corrections, one of which was actively costing time. **The per-class OCCT reference manual IS indexed**, as `occt-refman`, 37,008 sections. This copy said it was not, which sent an agent to the bundled headers or to WebFetch as a first resort rather than a last one. Those routes remain, scoped to the case that needs them: a class genuinely absent after an OCCT bump, before the package is rebuilt. **`context query` is now a lookup step in its own right.** `get_docs` takes its `library` from an enum fixed when the MCP server connected, and the server rebuilds that list only for packages arriving through its own download_package tool. Anything installed by `context add` is therefore invisible to `get_docs` for the rest of the session while `context query` sees it immediately. The failure reads as "package missing", which an agent takes at face value and escalates on, so the policy now says plainly that it means "not in the list I was handed". Fixed upstream in neuledge/context#117. Also records that the `ecosystem` package is indexed, so this standard and every shared policy are themselves queryable, and what a version in the cache means: a package is pinned to a release and does not follow its repo. Copied verbatim from SecondMouseAU/ecosystem okf/policies/context-first.md.
gsdali
added a commit
to SecondMouseAU/SwiftJWW
that referenced
this pull request
Aug 21, 2026
Two corrections, one of which was actively costing time. **The per-class OCCT reference manual IS indexed**, as `occt-refman`, 37,008 sections. This copy said it was not, which sent an agent to the bundled headers or to WebFetch as a first resort rather than a last one. Those routes remain, scoped to the case that needs them: a class genuinely absent after an OCCT bump, before the package is rebuilt. **`context query` is now a lookup step in its own right.** `get_docs` takes its `library` from an enum fixed when the MCP server connected, and the server rebuilds that list only for packages arriving through its own download_package tool. Anything installed by `context add` is therefore invisible to `get_docs` for the rest of the session while `context query` sees it immediately. The failure reads as "package missing", which an agent takes at face value and escalates on, so the policy now says plainly that it means "not in the list I was handed". Fixed upstream in neuledge/context#117. Also records that the `ecosystem` package is indexed, so this standard and every shared policy are themselves queryable, and what a version in the cache means: a package is pinned to a release and does not follow its repo. Copied verbatim from SecondMouseAU/ecosystem okf/policies/context-first.md.
gsdali
added a commit
to SecondMouseAU/SwiftMeshHeal
that referenced
this pull request
Aug 21, 2026
Two corrections, one of which was actively costing time. **The per-class OCCT reference manual IS indexed**, as `occt-refman`, 37,008 sections. This copy said it was not, which sent an agent to the bundled headers or to WebFetch as a first resort rather than a last one. Those routes remain, scoped to the case that needs them: a class genuinely absent after an OCCT bump, before the package is rebuilt. **`context query` is now a lookup step in its own right.** `get_docs` takes its `library` from an enum fixed when the MCP server connected, and the server rebuilds that list only for packages arriving through its own download_package tool. Anything installed by `context add` is therefore invisible to `get_docs` for the rest of the session while `context query` sees it immediately. The failure reads as "package missing", which an agent takes at face value and escalates on, so the policy now says plainly that it means "not in the list I was handed". Fixed upstream in neuledge/context#117. Also records that the `ecosystem` package is indexed, so this standard and every shared policy are themselves queryable, and what a version in the cache means: a package is pinned to a release and does not follow its repo. Copied verbatim from SecondMouseAU/ecosystem okf/policies/context-first.md.
gsdali
added a commit
to SecondMouseAU/SwiftPMX
that referenced
this pull request
Aug 21, 2026
Two corrections, one of which was actively costing time. **The per-class OCCT reference manual IS indexed**, as `occt-refman`, 37,008 sections. This copy said it was not, which sent an agent to the bundled headers or to WebFetch as a first resort rather than a last one. Those routes remain, scoped to the case that needs them: a class genuinely absent after an OCCT bump, before the package is rebuilt. **`context query` is now a lookup step in its own right.** `get_docs` takes its `library` from an enum fixed when the MCP server connected, and the server rebuilds that list only for packages arriving through its own download_package tool. Anything installed by `context add` is therefore invisible to `get_docs` for the rest of the session while `context query` sees it immediately. The failure reads as "package missing", which an agent takes at face value and escalates on, so the policy now says plainly that it means "not in the list I was handed". Fixed upstream in neuledge/context#117. Also records that the `ecosystem` package is indexed, so this standard and every shared policy are themselves queryable, and what a version in the cache means: a package is pinned to a release and does not follow its repo. Copied verbatim from SecondMouseAU/ecosystem okf/policies/context-first.md.
gsdali
added a commit
to SecondMouseAU/SwiftX
that referenced
this pull request
Aug 21, 2026
Two corrections, one of which was actively costing time. The per-class OCCT reference manual IS indexed, as occt-refman, 37,008 sections. This copy said it was not, which sent an agent to the bundled headers or to WebFetch as a first resort rather than a last one. And context query is now a lookup step in its own right: get_docs takes its library from an enum fixed when the MCP server connected, so anything installed by context add is invisible to it for the rest of the session while the CLI sees it immediately. Fixed upstream in neuledge/context#117. Copied verbatim from SecondMouseAU/ecosystem okf/policies/context-first.md.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
context addwrites to~/.context/packagesfrom a separate process, but a runningservereads that directory once at startup. A long-lived stdio server therefore keeps serving the package list it saw when it launched, soget_docsreports a package as missing when it is already installed, and the only way out is to reconnect the client.I hit this adding a locally-built docs package while a Claude Code session was open:
context querysaw it instantly,get_docscould not see it at all.The mechanism already existed
refreshGetDocsToolrebuilds the tool'slibraryenum and callssendToolListChanged, the MCP notification that tells a client to re-fetch the tool list. It had exactly one caller, thedownload_packagehandler, so a package arriving any other way was invisible.This adds a second trigger, not a second mechanism.
The change
watch.ts, a small debounced directory watcher. Debounced because one install is several filesystem events (a temp file, then a rename into place), which would otherwise rebuild the schema three or four times for one logical change. The watcher isunref'd so it never holds the process open by itself, and a callback that throws cannot tear it down.servewatches the data directory, reloads the store, refreshes the tool. Skipped when--libsis set, since that flag pins the session to a fixed library set on purpose and picking up new packages would defeat it.refreshGetDocsToolis now public, because the trigger lives outside the class. That is the only public surface change; happy to bump the changeset tominorif you would rather treat it as one.loadPackagesnow syncs rather than only adding. It is called repeatedly now, so a package removed from disk has to leave the store too, which the add-only version could not express.HTTP needed no change. It builds a fresh
ContextServerper session over the same store, so a session started after an install already sees it. Only the long-lived stdio server needed the live notification.Tests
Five, against the watcher directly: a single change fires once, a burst collapses to one call, stopping prevents further calls, a throwing callback does not kill the watcher, and a missing directory is a no-op.
Verified discriminating rather than merely passing: removing the debounce fails three of the five.
The watcher went into its own module partly so it could be tested at all.
cli.tsbuilds acommanderprogram at module scope, so importing it from a test would run the CLI.About the local test run
pnpm lintandpnpm buildare clean.pnpm testreports 40 failures in my environment, identical before and after this change (I ran the baseline on a stash to be sure). They are allbetter-sqlite3@11.10.0failing to build against Node v26, so every sqlite-backed test errors on missing bindings:My five new tests pass, taking the suite from 181 to 186 passing. I could not verify the sqlite-backed suites locally, so those are worth a look on your CI rather than taking my word for it.
Housekeeping
Followed the
CLAUDE.mdconventions: searched open and recently closed PRs and/.plans/first (nothing related), and added a changeset. No plan file to delete, since there was none to claim.