mirror of
https://github.com/mvschwarz/openrig.git
synced 2026-11-09 11:51:37 -10:00
fix(slice-05): context_packs reject manifest-as-directory (guard B2 repair on d491eca9) (OPR.0.3.2.5)
Per velocity-guard BLOCKING-CONCERN ond491eca9(qitem-…5bd8de60): the manifest-file existence check uses fs.exists() which returns true for BOTH files and directories. A bundle could declare context-packs/foo/ manifest.yaml and include manifest.yaml as a DIRECTORY (not a file). exists() passes; the live consumer's readFileSync(manifestPath) (context-pack-library-service.ts:135) throws on a dir; scan() records an error diagnostic instead of indexing a visible pack. Same false- positive routedCount class at the file-vs-directory discrimination axis guard banked in thed491eca9cycle. Fix: minimal `if (fs.isDirectory(sourceAbs))` check before treating the declared path as routable. Status reuses not_manifest with explicit "exists but is a directory, not a file" detail. No FsOps extension needed. bundle-context-packs-router.ts +8/-1: new isDirectory branch between the manifest-file existence check and the parent-dir isDirectory check. bundle-context-packs-router.test.ts +28/-0: C11 — parent dir exists + sourceAbs exists as DIRECTORY (not file) → routedCount=0, rejectedCount=1, status=not_manifest, NO copyDir. Discriminator-flip BEFORE this commit (PROACTIVELY): removed the new isDirectory branch. Result: 1/11 fail — exactly C11. Clean targeted discriminator (the check is structurally specific to the manifest-is- directory case). Restored, 11/11 + 152/152 across full slice-05 daemon suite. Ninth same-class catch on slice-05's tail. The exists/isDirectory distinction was the SECOND file-vs-dir discrimination axis the consumer uses; my B1 repair fixed file-presence but missed file-vs-dir type discrimination. Banked discipline extension: when a mock supports files-vs-dirs as separate sets (perd491eca9lesson), ALL fs operations used by the router need to be checked against BOTH axes — exists check alone is insufficient because it crosses the file/dir boundary. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
This commit is contained in:
1 parent
d491eca96e
commit
3cd581e3c4
2 files changed
+44
No files matched your search
@@ -156,6 +156,21 @@ export function routeContextPacks(
|
||||
});
|
||||
continue;
|
||||
}
|
||||
// Manifest-type check (banked B2 from d491eca9 guard catch): exists()
|
||||
// returns true for both files AND directories. If sourceAbs exists as
|
||||
// a directory (named manifest.yaml, but a dir not a file), the live
|
||||
// consumer's readFileSync(manifestPath) throws and scan() records an
|
||||
// error diagnostic instead of indexing a visible pack — false-positive
|
||||
// routedCount class. Reject pre-write so routedCount stays truthful at
|
||||
// the consumer-visible boundary.
|
||||
if (fs.isDirectory(sourceAbs)) {
|
||||
records.push({
|
||||
declaredPath: declared,
|
||||
status: "not_manifest",
|
||||
detail: `context_pack manifest '${declared}' exists but is a directory, not a file; consumer requires manifest.yaml to be a readable file`,
|
||||
});
|
||||
continue;
|
||||
}
|
||||
const sourcePackDir = nodePath.dirname(sourceAbs);
|
||||
if (!fs.isDirectory(sourcePackDir)) {
|
||||
records.push({
|
||||
|
||||
@@ -226,6 +226,35 @@ describe("routeContextPacks", () => {
|
||||
expect(result.records[5]!.status).toBe("conflict");
|
||||
});
|
||||
|
||||
// C11 (degenerate-input / banked guard catch on d491eca9):
|
||||
// manifest.yaml exists at the declared path but is a DIRECTORY, not a
|
||||
// file. fs.exists returns true for both shapes; the live consumer
|
||||
// (context-pack-library-service.ts:135 readFileSync) throws on a dir
|
||||
// path and scan() records an error diagnostic instead of indexing the
|
||||
// pack. Router must reject pre-write so routedCount stays truthful.
|
||||
it("manifest.yaml exists but is a directory → status=not_manifest (no false-positive routed)", () => {
|
||||
const fs = mockFs({
|
||||
// Parent dir IS a directory, AND manifest.yaml is ALSO a directory
|
||||
// (not a file). The bare exists check would pass; isDirectory check
|
||||
// catches this.
|
||||
dirs: [
|
||||
`${BUNDLE_ROOT}/context-packs/dirpack`,
|
||||
`${BUNDLE_ROOT}/context-packs/dirpack/manifest.yaml`,
|
||||
],
|
||||
});
|
||||
const result = routeContextPacks(
|
||||
makeInput({ declaredContextPacks: ["context-packs/dirpack/manifest.yaml"] }),
|
||||
fs,
|
||||
);
|
||||
expect(result.records).toHaveLength(1);
|
||||
expect(result.routedCount).toBe(0);
|
||||
expect(result.rejectedCount).toBe(1);
|
||||
expect(result.records[0]!.status).toBe("not_manifest");
|
||||
expect(result.records[0]!.detail).toContain("directory");
|
||||
// CRUCIAL: no copyDir fires (consumer-invisible pack must not route)
|
||||
expect(fs._copyCalls).toHaveLength(0);
|
||||
});
|
||||
|
||||
// C10 (degenerate-input / banked guard catch on a0e7e0e1):
|
||||
// parent dir exists but manifest.yaml file itself is absent —
|
||||
// ContextPackLibraryService.scan skips packs missing manifest.yaml
|
||||
|
||||
Reference in new issue
Block a user