fix: bind identity and coverage to the producing rule (#1513)

* fix: bind identity and coverage to the producing rule

Logical paths, container families, examined bytes, path-segment conventions, destination collisions, file-id leases, Mach-O CPU selection, and firmware cleanup now follow the observation that owns each rule.

* fix: fail unmatched Mach-O slices and keep firmware roots independent

A fat target whose architecture lipo did not list now stops before slice tools run. Chained fixups still count unread LC_DYLD_INFO rebase bytes, and a firmware cleanup failure no longer blocks the next workspace.

* test: cover path identity and runtime families at the projection boundary

NFC joins and segment conventions are now asserted by the path resolver, the Apple projection, and a real APK inventory instead of helper unit tests.

* test: expect unread dyld rebase bytes in the Apple dispatch fixture

The legacy LC_DYLD_INFO fixture keeps a rebase range this reader does not decode, so the public CLI and MCP check now requires that partial coverage beside the bind opcodes.

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
This commit is contained in:
morlutoandCursor Agent authored and GitHub committed 2026-10-10 17:14:47 +08:00
1 parent 7a56fe6260
commit b4db35f092
48 files changed
+1251 -266

No files matched your search

@@ -1,6 +1,10 @@
import { isBuiltin } from "node:module";
import { posix } from "node:path";
import {
normalizeJoinedLogicalPath,
logicalPathEscapesRoot,
} from "../../domain/artifactIdentity.js";
import type { JavaScriptArtifactFile } from "../../domain/javascript/javascriptArtifactFiles.js";
import {
admitsCanonicalPathSyntax,
@@ -326,12 +330,8 @@ const confineCandidate = (
input: ResolveArtifactPathInput,
candidate: string,
): string | ArtifactPathResolution => {
const normalized = posix.normalize(candidate);
if (
normalized === ".." ||
normalized.startsWith("../") ||
normalized.startsWith("/")
)
const normalized = normalizeJoinedLogicalPath(candidate);
if (logicalPathEscapesRoot(normalized))
return unresolvedOutcome(input, "rejected", [
"The resolved candidate escapes the canonical artifact root.",
]);