Repository navigation
Conversation
[Low impact] The PR appears safe to merge; removing the duplicate check preserves rejection before file access. SummaryThe PR requires an absolute byte-entropy input path in the shared contract, adds contract and MCP tests, and removes the duplicate service check.
Reviews (5) · Last reviewed commit: "refactor(native): remove the superseded ..." · Reviewed by Greptile |
Codex Review Summary: ❌ FailedThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits. |
|
Want your agent to iterate on Greptile's feedback? Try greploops. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9d2d81de60
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
Hey @z2Ace0107, thanks for putting this together, the fix looks useful. What's left: there is 1 unresolved review thread from Codex, about "Remove the superseded service absolute-path guard". Once that's done I'm happy to merge it. |
|
Done — the superseded guard is removed in 694c58c. Verified before removing: The sibling services (Devicetree, ElfNotes, KernelModule, AppleIps, ApkSignature, PythonPyc) keep their guards: their contracts still use Validation: the six affected test files pass (46 tests), |
待发评论(尚未发布,需用户确认)对象:#7759 Rebased nothing yet — the red required check here is pre-existing on
So Separately: the Codex review thread on |
…he description The compact input-schema profile is the production default. It reduces a required property whose schema carries a combinator down to its declared type, so the advertised `path` under that profile keeps no `pattern`, `minLength` or `allOf`; only the property description and canonical server-side validation still carry the requirement. Without an explicit description this property falls back to the generic "Local filesystem path used by this operation.", which says nothing about the requirement. Every sibling native diagnostics contract already describes its absolute path, so this was the one gap in the family.
…ntropy path docs/mcp-contracts.md scopes compact workflow tests to canonical rejection of invalid inputs before provider work, independent of how much detail the selected advertisement retains. The boundary test only read the advertisement back and compared shapes, so it never exercised the rejection the reduced advertisement can no longer express. Connects a real EvidenceMcpServer under the production default profile and calls the tool with a relative path, asserting the call is refused and the message names the requirement. The full-profile test keeps its Ajv assertions over the advertised schema and now names the profile it runs under, since a plain McpServer is not the default. The shared server setup is factored into a helper that hands the caller a connected client, so both profiles share one connect path and the compact branch keeps its EvidenceMcpServer type instead of being widened to McpServer. Corrects a comment in the contract test that described the pre-change state, where a relative path reached the schema and was refused only at runtime.
…jection The compact-profile boundary test searched the whole reply for the shared message text, so a harmless edit to the path message would fail it. That is the same defect class this PR removed from two other assertions, and docs/testing.md asks for error codes and structured facts instead of frozen wording. Moves the wire-level rejection into tests/boundary/mcp/absoluteLocalPathSchema.test.ts, which already drives both input-schema profiles through a real server, asserts the structured issue through parseMcpToolError, and records that the provider was never reached. The tool joins its sibling native diagnostics cases there. That file asserts each tool's issue path and zod issue code. This tool's rejection surfaces as a root-level issue with no field path and reason "invalid_value", where its siblings report a path-scoped "invalid_format"; both are asserted as the structured facts they are rather than matched against prose. toolSchemaValidity.test.ts keeps the advertised-schema assertion it exists for and drops the bespoke server scaffolding.
The previous commit pinned this tool's reported issue as a root-level `invalid_value`, which is what the host it was written on produces. Linux reports a path-scoped `invalid_format` instead, matching its siblings, so CI failed. The issue shape for this tool is not stable across host platforms, so only the platform-stable facts are asserted: the error code, its category, and that the rejection lands at input validation. A companion probe confirmed the service retains its own absolute-path guard, which reports the same code and category as the schema rejection, so the wire-level test cannot separate the two without matching prose. That mutation is carried by the advertised-schema assertion instead, and the limitation is recorded in the PR body.
The service-level `if (!isAbsolute(input.path))` check ran after `parseAnalysisInput` had already validated `path` against `inspectByteEntropyInputSchema`, whose shared owner now requires an absolute local path. Both entry points are covered by that schema: the MCP tool registration uses it directly, and the CLI command resolves its operator-relative argument with `absoluteCallerPath` before constructing the same schema-shaped input. No admitted request can reach the guard, so keeping the `node:path` predicate beside the regex contract left duplicate interpretations of one invariant that could drift. Removes the guard and the now-unused import. The sibling services (Devicetree, ElfNotes, KernelModule, AppleIps, ApkSignature, PythonPyc) keep their guards: their contracts still use `localPathStringSchema`, so for them the guard is the enforcing boundary, not a duplicate. That is the existing drift noted in PR morluto#7449.
694c58c to
1f20e52
Compare
|
Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits. |
Summary
export const inspectByteEntropyInputSchema = z.strictObject({ - path: localPathStringSchema, + path: absoluteLocalPathStringSchema.describe( + "Absolute local filesystem path to the file to profile; relative paths are rejected", + ),localPathStringSchemaonly requires a nonempty, NUL-free string, so theadvertised MCP request schema accepted
{"path":"sample.bin"}. The runtimerefuses that value with
invalid_requestand requires an absolute localfilesystem path, so the advertised contract invited a request that cannot
succeed.
Problem and expected behavior
The stdio MCP server advertises an input schema that accepts
inspect_byte_entropywith{"path":"sample.bin"}, but that request returnsinvalid_requestrequiring an absolute filesystem path. Selecting the same fileby its absolute path returns successful Evidence. Both the compact and full
input profiles exhibit the mismatch, and the canonical producer and MCP request
schemas both accept the relative value, so this is not solely an advertised JSON
Schema conversion discrepancy.
Expected behavior: the advertised schema states the same requirement the runtime
enforces, so an agent is not told a relative path is acceptable.
Change and scope
Constrain the advertised
pathto an absolute local path by reusing the existingabsoluteLocalPathStringSchemaowner insrc/domain/localPath.ts, which alreadycarries the message "must be an absolute local filesystem path" and is used by
sibling contracts (
decompileDirectory,applicationWorkflowInputContracts,electronToolContracts).The property also carries an explicit description, for the same reason its
sibling native diagnostics contracts do (
binaryLayout,nativeExports,peCertificates,peImports,peLoadConfig,peResources,recordedCrash).Without one this property falls back to the generic "Local filesystem path used
by this operation.", which says nothing about the requirement.
PR #7449 (still open) fixes the same class of mismatch for five sibling tools
using an MCP-only schema overlay, leaving the shared producer contract alone.
This tool has no second consumer to protect:
inspect-binary-entropydeclaresits own argument schema, so the contract is corrected directly instead of
overlaid.
The direction follows the repository's own documented intent: the CLI input
helper states that shared MCP contracts reject relative paths and that CLI
workflows resolve operator-relative values before validation. A relative path is
therefore expected to fail over MCP, and the schema is what was wrong.
Review follow-up: the service-level
if (!isAbsolute(input.path))guard inByteEntropyServiceis removed in this change as well. It ran afterparseAnalysisInputhad already validatedpathagainst the contract this PRtightens, and both entry points pass through that schema: the MCP tool
registration uses it directly, and the CLI command resolves its argument with
absoluteCallerPathbefore constructing the same schema-shaped input. Noadmitted request can reach the guard, so keeping a
node:pathpredicate besidethe regex contract left one invariant owned twice. The sibling services keep
their guards because their contracts still use
localPathStringSchema; for themthe guard is the enforcing boundary, not a duplicate (the same drift PR #7449
addresses with an overlay).
Deliberately not included: the CLI path is unchanged.
inspect-binary-entropydeclares its own
localPathStringSchemaargument and resolves it withabsoluteCallerPath, so an operator-relative path keeps working there. This PRtightens the MCP contract only; it does not relax the runtime's absolute-path
requirement.
Known gap this PR does not close
The compact input-schema profile is the production default
(
resolveMcpInputSchemaProfile(undefined)iscompact). It reduces a requiredproperty whose schema carries a combinator down to its declared type, so the
advertised
pathunder that profile keeps nopattern,minLength, orallOf;the requirement survives only as the property description and as canonical
server-side validation.
This is a pre-existing property of the profile, not something this change
introduces: 36 of the 43 tools that advertise an
absoluteLocalPathStringSchemaproperty are already reduced, including
open_binaryand every sibling nativediagnostics tool, and
docs/mcp-contracts.mdrecords the reduction as thedeliberate projection for gateways that cannot translate
allOfon a requiredproperty. What this change does do is move
inspect_byte_entropyfrom the inlinepresentation into that reduced set, because it was the one tool in the family
that previously chained a single pattern. The honest cost is that the compact
advertisement for this tool loses the
minLengthand NUL-free pattern it used tocarry.
Fixing the profile itself would flip 36 tools back to inline and change the whole
compact catalog digest, so it is deliberately out of scope here. The description
above is what keeps the requirement readable on the default profile meanwhile,
and the boundary test asserts the canonical rejection that the reduced
advertisement no longer expresses.
Contract and boundary impact
src/domain/native/byteEntropy.ts,the shared input contract for byte-entropy inspection. Consumers are the MCP
tool registration and the advertised JSON Schema.
a schema and description correction at an existing contract owner, with no
target execution, injection, mutation, or protection recovery.
inspect_byte_entropyinputschema gains the absolute-path constraint, so a request that previously passed
schema validation and then failed at runtime is now refused at the schema.
Canonical server-side validation is unchanged for absolute paths.
absoluteLocalPathStringSchemaselects its pattern by host platform, the sameway the sibling contracts do.
shape changes.
docs/public/product-catalog.jsonis generated andvalidated by CI; it is not committed here. The MCP tool catalog is regenerated
locally from
dist/and rechecked, and is likewise not committed.Expected effects: documentation or usability only; no target interaction.
Evidence
path. The new contract assertion failed with
expected true to be falseforsample.bin, and the new advertised-schema assertion failed the same way,confirming both the canonical contract and the advertised JSON Schema admitted
the value.
sample.bin,./sample.binand../sample.binwhile/filestill parses. Theadvertised-schema test registers the tool on a real MCP server, reads it back
with
listTools, compiles the advertised schema with Ajv, and confirms{"path":"sample.bin"}is refused while{"path":"/file"}is accepted.tests/boundary/mcp/absoluteLocalPathSchema.test.ts, which already drives bothinput-schema profiles through a real server, asserts the structured issue
through
parseMcpToolError, and records that the provider was never reached.That is the scope
docs/mcp-contracts.mdsets for compact workflow tests:canonical rejection before provider work, independent of how much detail the
advertisement retains.
reported issue shape is not stable across host platforms: Linux reports a
path-scoped
invalid_formatlike its siblings, while Windows reports aroot-level
invalid_value. Only the platform-stable facts are asserted for it— the error code, its category, and that the rejection lands at input
validation — rather than a shape that would fail on the other host.
killed overall): dropping the absolute requirement from the schema — killed
by both files; widening the absolute pattern so it matches any prefix —
killed by both files; changing the rejection message — survives;
replacing the property description with the generic fallback text —
survives. The two survivors are deliberate:
docs/testing.mdputsdocumentation wording in review rather than in substring tests, and the
assertions carry the error code and structured facts instead.
survived the wire-level test:
ByteEntropyServicekept its ownabsolute-path guard reporting the same
invalid_requestcode andinvalid_inputcategory, so the wire test could not separate schema fromhandler rejection without matching prose. Removing the superseded guard in
this change closes that gap, and the wire test now kills that mutation too.
Validation performed
vitest run src/domain/native/byteEntropy.test.ts src/contracts/native/binaryDiagnosticsToolContracts.test.ts tests/boundary/mcp/toolSchemaValidity.test.ts tests/boundary/mcp/absoluteLocalPathSchema.test.ts tests/boundary/mcp/compactInputSchemaMcp.test.ts tests/boundary/mcp/binaryDiagnosticsMcp.test.ts— 46 passed.src/application/binaryDiagnostics/ByteEntropyService.tspassesoxfmt --check,oxlint(the three reported warnings are pre-existing on the merge base, and the removal reduces one function by four lines), andnpm run typecheck.vitest run tests/boundary/mcp/compactInputSchemaMcp.test.ts tests/boundary/mcp/binaryDiagnosticsMcp.test.ts— 21 passed. These are the other consumers of the compact profile and of the shared absolute-path contract.npm run compilethennode scripts/generate-mcp-tool-catalog.mjs --check— pass. The description change moves the recorded catalog, so the generated cache is regenerated and rechecked; the catalog itself is not committed.npm run verify:test-discovery— 2,705 files discovered exactly once.npm run verify:module-boundaries— 3,289 source files checked.oxfmt --check .— all matched files correctly formatted.oxlinton the changed files — no new findings; the one reportedcomplexitywarning is pre-existing on unmodified main in the same function.
npm run typecheck— clean.compileusestsconfig.build.json, whichexcludes
tests, sotypecheckis the only command covering the edited testfiles.
Compatibility, safety, and release
pathtoinspect_byte_entropynow fails schema validation instead ofruntime validation. It already failed, so no working caller changes
behaviour; only the error surface moves earlier.
computed locally with no engine, and no target is executed.
paths, or target data are read or logged by this change.
Merge Danger
Door: two-way. Revert the one-line schema change and the tests together.
Blast Radius: the advertised MCP input schema for one tool.
Author readiness
Human owner: @z2Ace0107
Before merge
type(scope): outcome.