Broaden orphan candidate detection
This commit is contained in:
@@ -10,7 +10,7 @@
|
|||||||
"Title": "Kosmos Storage Audit",
|
"Title": "Kosmos Storage Audit",
|
||||||
"Intro1": "Prüft lokale Medienpfade aus Weltdokumenten, Paket-Packs und Manifesten gegen {dataRoot} und {publicRoot} und meldet nur broken-reference, non-package-to-package-reference und orphan-file.",
|
"Intro1": "Prüft lokale Medienpfade aus Weltdokumenten, Paket-Packs und Manifesten gegen {dataRoot} und {publicRoot} und meldet nur broken-reference, non-package-to-package-reference und orphan-file.",
|
||||||
"Intro2": "Nicht gemeldet werden reguläre Weltverweise auf Modul- oder Systemassets, wenn das Ziel im Owner-Paket selbst sichtbar referenziert ist; Wildcards gelten als gültig, sobald mindestens eine Datei passt.",
|
"Intro2": "Nicht gemeldet werden reguläre Weltverweise auf Modul- oder Systemassets, wenn das Ziel im Owner-Paket selbst sichtbar referenziert ist; Wildcards gelten als gültig, sobald mindestens eine Datei passt.",
|
||||||
"Intro3": "orphan-file wird nur in weltlokalen oder explizit riskanten Bereichen gebildet, nie global für den gesamten {dataRoot}-Root; ChatMessages und andere flüchtige Quellen werden nicht geprüft."
|
"Intro3": "orphan-file wird für alle gefundenen Mediendateien gegen den aktuellen Referenzbestand geprüft; bekannte Sonderfälle wie abgeleitete Scene-Thumbnails sowie ChatMessages und andere flüchtige Quellen werden ausgeschlossen."
|
||||||
},
|
},
|
||||||
"Action": {
|
"Action": {
|
||||||
"Run": "Analyse starten",
|
"Run": "Analyse starten",
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
"Title": "Kosmos Storage Audit",
|
"Title": "Kosmos Storage Audit",
|
||||||
"Intro1": "Checks local media paths from world documents, package packs, and manifests against {dataRoot} and {publicRoot}, and only reports broken-reference, non-package-to-package-reference, and orphan-file.",
|
"Intro1": "Checks local media paths from world documents, package packs, and manifests against {dataRoot} and {publicRoot}, and only reports broken-reference, non-package-to-package-reference, and orphan-file.",
|
||||||
"Intro2": "Regular world references to module or system assets are not reported if the target is visibly referenced by its owning package; wildcards are treated as valid as soon as at least one file matches.",
|
"Intro2": "Regular world references to module or system assets are not reported if the target is visibly referenced by its owning package; wildcards are treated as valid as soon as at least one file matches.",
|
||||||
"Intro3": "orphan-file is only produced for world-local or explicitly risky areas, never globally for the entire {dataRoot} root; ChatMessages and other transient sources are excluded."
|
"Intro3": "orphan-file is checked for every discovered media file against the current reference set; known special cases like derived scene thumbnails, ChatMessages, and other transient sources are excluded."
|
||||||
},
|
},
|
||||||
"Action": {
|
"Action": {
|
||||||
"Run": "Start Analysis",
|
"Run": "Start Analysis",
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"id": "kosmos-storage-audit",
|
"id": "kosmos-storage-audit",
|
||||||
"title": "Kosmos Storage Audit",
|
"title": "Kosmos Storage Audit",
|
||||||
"description": "Analyzes media references and risky storage locations across Foundry data and public roots.",
|
"description": "Analyzes media references and risky storage locations across Foundry data and public roots.",
|
||||||
"version": "0.0.28",
|
"version": "0.0.29",
|
||||||
"compatibility": {
|
"compatibility": {
|
||||||
"minimum": "13",
|
"minimum": "13",
|
||||||
"verified": "13"
|
"verified": "13"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { classifyRisk, createCanonicalLocator, detectMediaKind, inferOwnerHint, isCorePublicPath, isStorageAreaPath } from "./path-utils.js";
|
import { classifyRisk, createCanonicalLocator, detectMediaKind, inferOwnerHint } from "./path-utils.js";
|
||||||
|
|
||||||
function compareOwner(sourceScope, targetOwner) {
|
function compareOwner(sourceScope, targetOwner) {
|
||||||
if (!sourceScope) return "unknown";
|
if (!sourceScope) return "unknown";
|
||||||
@@ -128,7 +128,7 @@ export function buildFindings({ files, references, i18n, packageActivity }={}) {
|
|||||||
if (detectMediaKind(file.path) === "other") continue;
|
if (detectMediaKind(file.path) === "other") continue;
|
||||||
const refs = matchingReferencesForFile(file, refsByLocator, wildcardReferences);
|
const refs = matchingReferencesForFile(file, refsByLocator, wildcardReferences);
|
||||||
if (refs.length) continue;
|
if (refs.length) continue;
|
||||||
if (!shouldReportOrphan(file, resolvedReferences)) continue;
|
if (!shouldReportOrphan(file)) continue;
|
||||||
|
|
||||||
const severity = (file.riskClass === "package-module") || (file.riskClass === "package-system") || (file.riskClass === "release-public")
|
const severity = (file.riskClass === "package-module") || (file.riskClass === "package-system") || (file.riskClass === "release-public")
|
||||||
? "warning"
|
? "warning"
|
||||||
@@ -223,19 +223,9 @@ function wildcardToRegExp(pattern) {
|
|||||||
return new RegExp(`^${escaped}$`, "u");
|
return new RegExp(`^${escaped}$`, "u");
|
||||||
}
|
}
|
||||||
|
|
||||||
function shouldReportOrphan(file, references) {
|
function shouldReportOrphan(file) {
|
||||||
if (isDerivedSceneThumbnail(file)) return false;
|
if (isDerivedSceneThumbnail(file)) return false;
|
||||||
if (file.riskClass === "stable-world") {
|
return true;
|
||||||
const worldId = file.ownerHint.ownerId;
|
|
||||||
return references.some(reference => reference.sourceScope?.ownerType === "world" && reference.sourceScope.ownerId === worldId);
|
|
||||||
}
|
|
||||||
if ((file.riskClass === "package-module") || (file.riskClass === "package-system")) {
|
|
||||||
return isStorageAreaPath(file);
|
|
||||||
}
|
|
||||||
if (file.riskClass === "release-public") {
|
|
||||||
return !isCorePublicPath(file);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function isInactiveModuleTarget(file, packageActivity) {
|
function isInactiveModuleTarget(file, packageActivity) {
|
||||||
|
|||||||
38
tests/global-orphan-candidate-test.mjs
Normal file
38
tests/global-orphan-candidate-test.mjs
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
import assert from "node:assert/strict";
|
||||||
|
import { buildFindings, createFileRecord } from "../scripts/core/finding-engine.js";
|
||||||
|
import { createFileLocator } from "../scripts/core/path-utils.js";
|
||||||
|
|
||||||
|
const files = [
|
||||||
|
createFileRecord(createFileLocator("data", "assets/user-upload/example.webp"), 100),
|
||||||
|
createFileRecord(createFileLocator("data", "worlds/demo-world/assets/maps/map.webp"), 200),
|
||||||
|
createFileRecord(createFileLocator("public", "icons/custom/example.webp"), 300),
|
||||||
|
createFileRecord(createFileLocator("data", "worlds/demo-world/assets/scenes/exampleScene-thumb.webp"), 400)
|
||||||
|
];
|
||||||
|
|
||||||
|
const { findings } = buildFindings({ files, references: [] });
|
||||||
|
|
||||||
|
assert.equal(
|
||||||
|
findings.some(finding => finding.kind === "orphan-file" && finding.target.locator === "data:assets/user-upload/example.webp"),
|
||||||
|
true,
|
||||||
|
"unreferenced user assets should be reported as orphan candidates"
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.equal(
|
||||||
|
findings.some(finding => finding.kind === "orphan-file" && finding.target.locator === "data:worlds/demo-world/assets/maps/map.webp"),
|
||||||
|
true,
|
||||||
|
"unreferenced world assets should be reported as orphan candidates"
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.equal(
|
||||||
|
findings.some(finding => finding.kind === "orphan-file" && finding.target.locator === "public:icons/custom/example.webp"),
|
||||||
|
true,
|
||||||
|
"unreferenced public media should be reported as orphan candidates"
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.equal(
|
||||||
|
findings.some(finding => finding.kind === "orphan-file" && finding.target.locator === "data:worlds/demo-world/assets/scenes/exampleScene-thumb.webp"),
|
||||||
|
false,
|
||||||
|
"derived scene thumbnails must stay excluded from orphan candidates"
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log("global-orphan-candidate-test: ok");
|
||||||
Reference in New Issue
Block a user