fix: enforce absolute log paths, and name the real cause when one cannot be opened - #110
Closed
lukecotter wants to merge 5 commits into
Closed
fix: enforce absolute log paths, and name the real cause when one cannot be opened#110lukecotter wants to merge 5 commits into
lukecotter wants to merge 5 commits into
Conversation
Record the rules the v2 rename follows: the apexlog_ prefix, a verb that states the shape of the result, banned verbs, and eight field rules. Add "don't state what the caller can derive" to the shaping conventions. Refs #107
Every failure to open the log reported "Log file not found", so a permission error, a directory in place of a file, or an exhausted descriptor table all sent the caller to look for a file that was there. Report ENOENT as missing, name the code otherwise, and keep the original error as `cause`. Refs #109
All three analysis tools documented an absolute path and accepted any string. A relative one resolved against the server's working directory, which is where the client spawned the server and not where the caller is, so it read a different file or none and reported neither. Declare the path once in apexLogSource, the module the three tools already share for loading a log, and refine it to absolute. Refinements do not reach the JSON schema, so the tool definitions are unchanged at ~1,053 tokens. Resolve execute_anonymous's outputDir to absolute too, so the filePath it returns stays one the analysis tools accept. A relative outputDir now anchors to the project root, the base the default already used. Refs #109
Only SIGINT was trapped, so a supervised restart, a container stop, or a client that ends a stdio server hit Node's default and exited without the clean close. Refs #109
execute_anonymous created directories anywhere the process could write, from an agent-supplied path. The MCP spec expects a server to work inside the roots the client declares, so report rather than refuse: the log is still written, and both the response and stderr name where it went. Silent for the default outputDir, for one inside a root, and for a client that declares no roots. Symlinks are followed on both sides. Refs #109
lcottercertinia
approved these changes
Aug 12, 2026
lcottercertinia
added this pull request to the merge queue
Aug 12, 2026
github-merge-queue
Bot
removed this pull request from the merge queue due to no response for status checks
Aug 12, 2026
Collaborator
Author
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.
Two fixes from #109, and the naming rules the v2 rename (#107) will follow.
Refuse a relative
logFilePathAll three analysis tools documented an absolute path and accepted any string. A relative one
resolved against the server's working directory — where the client spawned the server, not where
the caller is — so it read a different file or none, and reported neither.
The path is now declared once in
apexLogSource.ts, the module the three tools already share forloading a log, and refined to absolute. Refinements do not reach the JSON schema, so the tool
definitions are unchanged at ~1,053 tokens;
pnpm run evalholds that.execute_anonymousreturns afilePaththat callers feed straight back to those tools, so itsoutputDiris resolved to absolute as well. A relativeoutputDirnow anchors to the project root,the base the default
.apex-log-mcpalready used, instead of the server's working directory.Name the real cause when a log cannot be opened
Every failure to open the log reported
Log file not found, so a permission error, a directory inplace of a file, or an exhausted descriptor table all sent the caller to look for a file that was
there.
ENOENTstill reports as missing; anything else names its code and keeps the original erroras
cause.Close cleanly on
SIGTERMOnly
SIGINTwas trapped, so a supervised restart, a container stop, or a client that ends a stdioserver hit Node's default and exited without the clean close.
Warn when
outputDirleaves the client rootsexecute_anonymouscreated directories anywhere the process could write, from an agent-suppliedpath. The MCP spec expects a server to work inside the roots the client declares, so this reports
rather than refuses: the log is still written, and both the response and stderr name where it went.
Silent for the default
outputDir, for one inside a root, and for a client that declares no roots.Symlinks are followed on both sides, so a link inside a root that points out of one still warns.
Naming rules
DEVELOPING.mdgains a "Naming Tools and Fields" section: theapexlog_prefix, a verb that statesthe shape of the result, the banned verbs, and eight field rules.
CLAUDE.mdpoints at it and adds"don't state what the caller can derive" to the shaping conventions. Docs only — nothing on the wire
changes. It is here because the rename commits that follow depend on it.
Testing
pnpm run build && pnpm run eval— 6 cases pass, definitions ~1,053 tokens.pnpm exec jest— 259 pass.pnpm run lintclean.tsc --noEmitclean.Refs #107
Closes #109