fix: require folder data-pack metadata sections

Reject folders without parseable metadata, an object pack section and a non-null description before exposing their contents. Preserve existing parser and format behavior.

Co-Authored-By: Codex <[email protected]>
This commit is contained in:
Florian ERNSTandCodex committed 2026-11-07 03:35:13 +01:00
1 parent 41944ed914
commit 84f6959921
9 files changed
+473 -11

No files matched your search

+113 -5
View File
@@ -141,7 +141,8 @@ impl DataPack {
pub fn discover(world: &Path) -> Vec<DataPack> {
discover_folder(&world.join("datapacks"))
}
/// Packs in Create World's temporary pack folder, before a world exists.
/// `FolderRepositorySource.loadPacks`: packs in Create World's temporary
/// folder or a world's data-pack directory, with required folder metadata.
pub fn discover_folder(dir: &Path) -> Vec<DataPack> {
let Ok(entries) = std::fs::read_dir(dir) else {
return Vec::new();
@@ -150,7 +151,7 @@ pub fn discover_folder(dir: &Path) -> Vec<DataPack> {
for e in entries.flatten() {
let name = e.file_name().to_string_lossy().into_owned();
let path = e.path();
if path.is_dir() && path.join("pack.mcmeta").exists() {
if path.is_dir() && folder_metadata_present(&path) {
packs.push(DataPack {
id: format!("file/{name}"),
source: Source::Dir(path),
@@ -168,6 +169,22 @@ pub fn discover_folder(dir: &Path) -> Vec<DataPack> {
packs.sort_by(|a, b| a.id.cmp(&b.id));
packs
}
/// `Pack.readPackMetadata`: even its fallback codec requires a pack section
/// and description. Keep this folder gate separate from format compatibility
/// and the existing interpretation of the description component.
fn folder_metadata_present(path: &Path) -> bool {
let Some(meta) = std::fs::read(path.join("pack.mcmeta"))
.ok()
.and_then(|bytes| crate::packs::parse_meta(&bytes))
else {
return false;
};
meta.as_object()
.and_then(|root| root.get("pack"))
.and_then(serde_json::Value::as_object)
.and_then(|pack| pack.get("description"))
.is_some_and(|description| !description.is_null())
}
/// The resources root's built-in feature packs (`ServerPacksSource`
/// scanning the game's `data/minecraft/datapacks`): every folder with a
/// `pack.mcmeta`, a feature pack (`PackSource.FEATURE`). Off until a world
@@ -924,6 +941,97 @@ pub fn worldgen_overrides(
mod tests {
use super::*;
#[test]
fn folder_metadata_is_required_before_contents_are_discovered() {
let root =
std::env::temp_dir().join(format!("horizon-folder-metadata-{}", std::process::id()));
let _ = std::fs::remove_dir_all(&root);
for (name, metadata) in [
("broken", Some("{")),
("root_empty", Some("{}")),
("root_array", Some("[]")),
("pack_empty", Some(r#"{"pack":{}}"#)),
("pack_string", Some(r#"{"pack":"bad"}"#)),
("missing", None),
(
"full",
Some(
r#"{"pack":{"description":"full","pack_format":121,"min_format":[121,0],"max_format":[121,0]}}"#,
),
),
(
"description",
Some(r#"{"pack":{"description":"description only"}}"#),
),
("numeric", Some(r#"{"pack":{"description":42}}"#)),
("null", Some(r#"{"pack":{"description":null}}"#)),
("bom", Some("\u{feff}{\"pack\":{\"description\":\"BOM\"}}")),
(
"comment",
Some("{\"pack\":{\"description\":\"comment\"}}\n// trailing"),
),
] {
let dir = root.join(name);
std::fs::create_dir_all(dir.join("data/h146/function")).unwrap();
std::fs::write(
dir.join(format!("data/h146/function/{name}.mcfunction")),
"scoreboard players set admitted h146 1\n",
)
.unwrap();
if let Some(metadata) = metadata {
std::fs::write(dir.join("pack.mcmeta"), metadata).unwrap();
}
}
let packs = discover_folder(&root);
assert_eq!(
packs.iter().map(|p| p.id.as_str()).collect::<Vec<_>>(),
[
"file/bom",
"file/comment",
"file/description",
"file/full",
"file/numeric"
]
);
let store = DataStore::load(&packs.iter().collect::<Vec<_>>());
assert_eq!(
store
.functions
.keys()
.map(String::as_str)
.collect::<Vec<_>>(),
[
"h146:bom",
"h146:comment",
"h146:description",
"h146:full",
"h146:numeric"
]
);
let numeric = packs.iter().find(|p| p.id == "file/numeric").unwrap();
let raw: serde_json::Value =
serde_json::from_slice(&numeric.read("pack.mcmeta").unwrap()).unwrap();
assert_eq!(raw["pack"]["description"], 42);
// Builtin and feature construction still have their independent paths.
let resources = root.join("resources");
let feature = resources.join("data/minecraft/datapacks/feature");
std::fs::create_dir_all(&feature).unwrap();
std::fs::write(
feature.join("pack.mcmeta"),
r#"{"pack":{"description":"feature"}}"#,
)
.unwrap();
assert_eq!(
feature_packs(&resources)
.iter()
.map(|p| p.id.as_str())
.collect::<Vec<_>>(),
["feature"]
);
assert_eq!(DataPack::builtin(&resources).id, "vanilla");
std::fs::remove_dir_all(root).unwrap();
}
#[test]
fn data_map_files_are_content_files_keyed_by_map_namespace_and_registry() {
assert_eq!(
@@ -961,7 +1069,7 @@ mod tests {
std::fs::write(path, t).unwrap();
};
for pack in ["a", "b", "off"] {
write(pack, "pack.mcmeta", "{}");
write(pack, "pack.mcmeta", r#"{"pack":{"description":"fixture"}}"#);
write(pack, "data/minecraft/worldgen/noise/cave.json", pack);
write(pack, "data/p/structure/room/a.nbt", pack);
write(
@@ -1216,13 +1324,13 @@ mod tests {
write(
"fns",
"pack.mcmeta",
r#"{"pack":{"min_format":121,"max_format":121}}"#,
r#"{"pack":{"description":"fixture","min_format":121,"max_format":121}}"#,
);
write("fns", "data/x/function/f.mcfunction", "say hi");
write(
"off",
"pack.mcmeta",
r#"{"pack":{"min_format":121,"max_format":121}}"#,
r#"{"pack":{"description":"fixture","min_format":121,"max_format":121}}"#,
);
std::fs::create_dir_all(&dir).unwrap();
let mut zip = zip::ZipWriter::new(std::fs::File::create(dir.join("old.zip")).unwrap());
+1 -1
View File
@@ -462,7 +462,7 @@ fn read_meta(source: &Source) -> Option<serde_json::Value> {
/// The first JSON value of a `pack.mcmeta`: what follows it is ignored, as some packs sign the
/// file with a comment after the closing brace. Gson reads past a UTF-8 byte order mark;
/// serde_json rejects it.
fn parse_meta(bytes: &[u8]) -> Option<serde_json::Value> {
pub(crate) fn parse_meta(bytes: &[u8]) -> Option<serde_json::Value> {
serde_json::Deserializer::from_slice(bytes.strip_prefix(b"\xEF\xBB\xBF").unwrap_or(bytes))
.into_iter()
.next()?
@@ -2901,7 +2901,11 @@ mod structure_tag_tests {
let game_tags = pack.join("data/minecraft/tags/worldgen/structure");
std::fs::create_dir_all(&tags).unwrap();
std::fs::create_dir_all(&game_tags).unwrap();
std::fs::write(pack.join("pack.mcmeta"), "{}").unwrap();
std::fs::write(
pack.join("pack.mcmeta"),
r#"{"pack":{"description":"fixture"}}"#,
)
.unwrap();
std::fs::write(
tags.join("village.json"),
r##"{"values": ["#minecraft:village", "minecraft:igloo"]}"##,
+5 -1
View File
@@ -2129,7 +2129,11 @@ mod enchantment_snapshot_tests {
let pack = dir.join("datapacks/model");
let tags = pack.join("data/h024/tags/enchantment");
std::fs::create_dir_all(&tags).unwrap();
std::fs::write(pack.join("pack.mcmeta"), "{}").unwrap();
std::fs::write(
pack.join("pack.mcmeta"),
r#"{"pack":{"description":"fixture"}}"#,
)
.unwrap();
std::fs::write(tags.join("empty.json"), r#"{"values":[]}"#).unwrap();
std::fs::write(
dir.join("datapacks.json"),
+133 -2
View File
@@ -1147,7 +1147,11 @@ mod tests {
for name in ["a", "b"] {
let pack = dir.join("datapacks").join(name);
std::fs::create_dir_all(pack.join("data/x/recipe")).unwrap();
std::fs::write(pack.join("pack.mcmeta"), "{}").unwrap();
std::fs::write(
pack.join("pack.mcmeta"),
r#"{"pack":{"description":"fixture"}}"#,
)
.unwrap();
std::fs::write(pack.join("data/x/recipe/r.json"), name).unwrap();
}
let json = serde_json::json!({"enabled": order, "disabled": []});
@@ -1174,7 +1178,11 @@ mod tests {
let _ = std::fs::remove_dir_all(&dir);
let pack = dir.join("datapacks").join("pack");
std::fs::create_dir_all(pack.join("data/pkg/tags/item")).unwrap();
std::fs::write(pack.join("pack.mcmeta"), "{}").unwrap();
std::fs::write(
pack.join("pack.mcmeta"),
r#"{"pack":{"description":"fixture"}}"#,
)
.unwrap();
std::fs::write(
pack.join("data/pkg/tags/item/both.json"),
r#"{"replace": true, "values": ["pkg:from_pack"]}"#,
@@ -1351,4 +1359,127 @@ mod entity_score_tests {
assert!(game.score.board.score(&actors[2].1, "pts").is_none());
assert_eq!(game.world.game_time, time);
}
#[test]
#[ignore = "needs prepared resources in HORIZON_TEST_RESOURCES"]
fn folder_metadata_rejection_reaches_actual_function_commands() {
use crate::game::{Audio, Options, Settings, load_resources};
use std::time::Instant;
let root = std::path::PathBuf::from(std::env::var_os("HORIZON_TEST_RESOURCES").unwrap());
let settings = Settings::default();
let loaded = load_resources(
root.clone(),
None,
&root,
&settings,
Instant::now(),
false,
true,
&crate::game::Progress::new(),
&mut |_, _| unreachable!(),
)
.unwrap();
let mut options = Options::parse(std::iter::empty()).unwrap().unwrap();
options.resources = root.clone();
options.execution_role = crate::game::execution_role::ExecutionRole::IntegratedServer;
let mut game = Game::new(
&loaded.resources,
loaded.pack,
loaded.gui.unwrap(),
options,
settings,
Audio::silent(&root),
None,
)
.unwrap();
game.build_registries();
game.set_allow_commands(true);
let dir = std::env::temp_dir().join(format!(
"horizon-game-folder-metadata-{}",
std::process::id()
));
let _ = std::fs::remove_dir_all(&dir);
let cases = [
("broken", Some("{"), false),
("root_empty", Some("{}"), false),
("root_array", Some("[]"), false),
("pack_empty", Some(r#"{"pack":{}}"#), false),
("pack_string", Some(r#"{"pack":"bad"}"#), false),
("missing", None, false),
(
"full",
Some(
r#"{"pack":{"description":"full","pack_format":121,"min_format":[121,0],"max_format":[121,0]}}"#,
),
true,
),
(
"description",
Some(r#"{"pack":{"description":"description only"}}"#),
true,
),
];
for (name, metadata, _) in cases {
let pack = dir.join("datapacks").join(name);
std::fs::create_dir_all(pack.join("data/h146/function")).unwrap();
std::fs::write(
pack.join(format!("data/h146/function/{name}.mcfunction")),
format!("scoreboard players set {name} h146 17\n"),
)
.unwrap();
if let Some(metadata) = metadata {
std::fs::write(pack.join("pack.mcmeta"), metadata).unwrap();
}
}
game.world_root = dir.clone();
let run = |game: &mut Game<'_>, line: &str| {
game.exec = ExecState::default();
let source = game.player_source();
game.execute_line(line, source)
};
run(&mut game, "scoreboard objectives add h146 dummy").unwrap();
let clock = game.world.game_time;
for reload in [false, true] {
for (name, _, _) in cases {
run(
&mut game,
&format!("scoreboard players set {name} h146 -99"),
)
.unwrap();
}
game.reload_datapacks(reload);
for (name, _, valid) in cases {
assert_eq!(game.score.board.score(name, "h146").unwrap().value, -99);
let result = run(&mut game, &format!("function h146:{name}"));
// Intended old failure: a malformed pack's valid function executes.
assert_eq!(result.is_ok(), valid, "{name}, reload={reload}");
assert_eq!(
game.score.board.score(name, "h146").unwrap().value,
if valid { 17 } else { -99 }
);
assert_eq!(
game.fns
.store
.functions
.contains_key(&format!("h146:{name}")),
valid
);
assert_eq!(
game.ui
.registries
.functions
.contains(&format!("h146:{name}")),
valid
);
assert_eq!(
game.fns
.packs
.iter()
.any(|p| p.id == format!("file/{name}")),
valid
);
}
}
assert_eq!(game.world.game_time, clock);
std::fs::remove_dir_all(dir).unwrap();
}
}
+1 -1
View File
@@ -7543,7 +7543,7 @@ mod tests {
fs::create_dir_all(path.parent().unwrap()).unwrap();
fs::write(path, text).unwrap();
};
write("p", "pack.mcmeta", "{}");
write("p", "pack.mcmeta", r#"{"pack":{"description":"fixture"}}"#);
// A pack's dimension of another id is not vanilla-like.
write(
"p",
@@ -0,0 +1,81 @@
# Folder metadata raw residuals (H146)
Untouched frozen base: **191/241 → fixed 241/241**, with no canonical residuals. All 50 complete strict differences follow; all concern the five malformed folders. The canonical categories were predeclared before capture.
```jsonl
{"label":"initial-broken-availability","expected":{"cmd":"/execute store result score result h146 store success score success h146 run datapack enable \"file/h146-broken\"","messages":[[["Unknown data pack 'file/h146-broken'",[16733525,false,false,false,false,false]]]],"results":[[false,0]]},"actual":{"cmd":"/execute store result score result h146 store success score success h146 run datapack enable \"file/h146-broken\"","messages":[[["Pack 'file/h146-broken' is already enabled!",[16733525,false,false,false,false,false]]]],"results":[[false,0]]}}
{"label":"initial-broken-function","expected":{"cmd":"/execute store result score result h146 store success score success h146 run function h146:broken","messages":[[["Unknown function h146:broken",[16733525,false,false,false,false,false]]]],"results":[[false,0]]},"actual":{"cmd":"/execute store result score result h146 store success score success h146 run function h146:broken","messages":[[["Running function h146:broken",[null,false,false,false,false,false]]]],"results":[]}}
{"label":"initial-broken-function-result","expected":{"cmd":"/scoreboard players get result h146","messages":[[["result has 0 [h146]",[null,false,false,false,false,false]]]],"results":[[true,0]]},"actual":{"cmd":"/scoreboard players get result h146","messages":[[["result has -99 [h146]",[null,false,false,false,false,false]]]],"results":[[true,-99]]}}
{"label":"initial-broken-function-success","expected":{"cmd":"/scoreboard players get success h146","messages":[[["success has 0 [h146]",[null,false,false,false,false,false]]]],"results":[[true,0]]},"actual":{"cmd":"/scoreboard players get success h146","messages":[[["success has -99 [h146]",[null,false,false,false,false,false]]]],"results":[[true,-99]]}}
{"label":"initial-broken-after","expected":{"cmd":"/scoreboard players get broken h146","messages":[[["broken has -99 [h146]",[null,false,false,false,false,false]]]],"results":[[true,-99]]},"actual":{"cmd":"/scoreboard players get broken h146","messages":[[["broken has 11 [h146]",[null,false,false,false,false,false]]]],"results":[[true,11]]}}
{"label":"initial-root_empty-availability","expected":{"cmd":"/execute store result score result h146 store success score success h146 run datapack enable \"file/h146-root_empty\"","messages":[[["Unknown data pack 'file/h146-root_empty'",[16733525,false,false,false,false,false]]]],"results":[[false,0]]},"actual":{"cmd":"/execute store result score result h146 store success score success h146 run datapack enable \"file/h146-root_empty\"","messages":[[["Pack 'file/h146-root_empty' is already enabled!",[16733525,false,false,false,false,false]]]],"results":[[false,0]]}}
{"label":"initial-root_empty-function","expected":{"cmd":"/execute store result score result h146 store success score success h146 run function h146:root_empty","messages":[[["Unknown function h146:root_empty",[16733525,false,false,false,false,false]]]],"results":[[false,0]]},"actual":{"cmd":"/execute store result score result h146 store success score success h146 run function h146:root_empty","messages":[[["Running function h146:root_empty",[null,false,false,false,false,false]]]],"results":[]}}
{"label":"initial-root_empty-function-result","expected":{"cmd":"/scoreboard players get result h146","messages":[[["result has 0 [h146]",[null,false,false,false,false,false]]]],"results":[[true,0]]},"actual":{"cmd":"/scoreboard players get result h146","messages":[[["result has -99 [h146]",[null,false,false,false,false,false]]]],"results":[[true,-99]]}}
{"label":"initial-root_empty-function-success","expected":{"cmd":"/scoreboard players get success h146","messages":[[["success has 0 [h146]",[null,false,false,false,false,false]]]],"results":[[true,0]]},"actual":{"cmd":"/scoreboard players get success h146","messages":[[["success has -99 [h146]",[null,false,false,false,false,false]]]],"results":[[true,-99]]}}
{"label":"initial-root_empty-after","expected":{"cmd":"/scoreboard players get root_empty h146","messages":[[["root_empty has -99 [h146]",[null,false,false,false,false,false]]]],"results":[[true,-99]]},"actual":{"cmd":"/scoreboard players get root_empty h146","messages":[[["root_empty has 12 [h146]",[null,false,false,false,false,false]]]],"results":[[true,12]]}}
{"label":"initial-root_array-availability","expected":{"cmd":"/execute store result score result h146 store success score success h146 run datapack enable \"file/h146-root_array\"","messages":[[["Unknown data pack 'file/h146-root_array'",[16733525,false,false,false,false,false]]]],"results":[[false,0]]},"actual":{"cmd":"/execute store result score result h146 store success score success h146 run datapack enable \"file/h146-root_array\"","messages":[[["Pack 'file/h146-root_array' is already enabled!",[16733525,false,false,false,false,false]]]],"results":[[false,0]]}}
{"label":"initial-root_array-function","expected":{"cmd":"/execute store result score result h146 store success score success h146 run function h146:root_array","messages":[[["Unknown function h146:root_array",[16733525,false,false,false,false,false]]]],"results":[[false,0]]},"actual":{"cmd":"/execute store result score result h146 store success score success h146 run function h146:root_array","messages":[[["Running function h146:root_array",[null,false,false,false,false,false]]]],"results":[]}}
{"label":"initial-root_array-function-result","expected":{"cmd":"/scoreboard players get result h146","messages":[[["result has 0 [h146]",[null,false,false,false,false,false]]]],"results":[[true,0]]},"actual":{"cmd":"/scoreboard players get result h146","messages":[[["result has -99 [h146]",[null,false,false,false,false,false]]]],"results":[[true,-99]]}}
{"label":"initial-root_array-function-success","expected":{"cmd":"/scoreboard players get success h146","messages":[[["success has 0 [h146]",[null,false,false,false,false,false]]]],"results":[[true,0]]},"actual":{"cmd":"/scoreboard players get success h146","messages":[[["success has -99 [h146]",[null,false,false,false,false,false]]]],"results":[[true,-99]]}}
{"label":"initial-root_array-after","expected":{"cmd":"/scoreboard players get root_array h146","messages":[[["root_array has -99 [h146]",[null,false,false,false,false,false]]]],"results":[[true,-99]]},"actual":{"cmd":"/scoreboard players get root_array h146","messages":[[["root_array has 13 [h146]",[null,false,false,false,false,false]]]],"results":[[true,13]]}}
{"label":"initial-pack_empty-availability","expected":{"cmd":"/execute store result score result h146 store success score success h146 run datapack enable \"file/h146-pack_empty\"","messages":[[["Unknown data pack 'file/h146-pack_empty'",[16733525,false,false,false,false,false]]]],"results":[[false,0]]},"actual":{"cmd":"/execute store result score result h146 store success score success h146 run datapack enable \"file/h146-pack_empty\"","messages":[[["Pack 'file/h146-pack_empty' is already enabled!",[16733525,false,false,false,false,false]]]],"results":[[false,0]]}}
{"label":"initial-pack_empty-function","expected":{"cmd":"/execute store result score result h146 store success score success h146 run function h146:pack_empty","messages":[[["Unknown function h146:pack_empty",[16733525,false,false,false,false,false]]]],"results":[[false,0]]},"actual":{"cmd":"/execute store result score result h146 store success score success h146 run function h146:pack_empty","messages":[[["Running function h146:pack_empty",[null,false,false,false,false,false]]]],"results":[]}}
{"label":"initial-pack_empty-function-result","expected":{"cmd":"/scoreboard players get result h146","messages":[[["result has 0 [h146]",[null,false,false,false,false,false]]]],"results":[[true,0]]},"actual":{"cmd":"/scoreboard players get result h146","messages":[[["result has -99 [h146]",[null,false,false,false,false,false]]]],"results":[[true,-99]]}}
{"label":"initial-pack_empty-function-success","expected":{"cmd":"/scoreboard players get success h146","messages":[[["success has 0 [h146]",[null,false,false,false,false,false]]]],"results":[[true,0]]},"actual":{"cmd":"/scoreboard players get success h146","messages":[[["success has -99 [h146]",[null,false,false,false,false,false]]]],"results":[[true,-99]]}}
{"label":"initial-pack_empty-after","expected":{"cmd":"/scoreboard players get pack_empty h146","messages":[[["pack_empty has -99 [h146]",[null,false,false,false,false,false]]]],"results":[[true,-99]]},"actual":{"cmd":"/scoreboard players get pack_empty h146","messages":[[["pack_empty has 14 [h146]",[null,false,false,false,false,false]]]],"results":[[true,14]]}}
{"label":"initial-pack_string-availability","expected":{"cmd":"/execute store result score result h146 store success score success h146 run datapack enable \"file/h146-pack_string\"","messages":[[["Unknown data pack 'file/h146-pack_string'",[16733525,false,false,false,false,false]]]],"results":[[false,0]]},"actual":{"cmd":"/execute store result score result h146 store success score success h146 run datapack enable \"file/h146-pack_string\"","messages":[[["Pack 'file/h146-pack_string' is already enabled!",[16733525,false,false,false,false,false]]]],"results":[[false,0]]}}
{"label":"initial-pack_string-function","expected":{"cmd":"/execute store result score result h146 store success score success h146 run function h146:pack_string","messages":[[["Unknown function h146:pack_string",[16733525,false,false,false,false,false]]]],"results":[[false,0]]},"actual":{"cmd":"/execute store result score result h146 store success score success h146 run function h146:pack_string","messages":[[["Running function h146:pack_string",[null,false,false,false,false,false]]]],"results":[]}}
{"label":"initial-pack_string-function-result","expected":{"cmd":"/scoreboard players get result h146","messages":[[["result has 0 [h146]",[null,false,false,false,false,false]]]],"results":[[true,0]]},"actual":{"cmd":"/scoreboard players get result h146","messages":[[["result has -99 [h146]",[null,false,false,false,false,false]]]],"results":[[true,-99]]}}
{"label":"initial-pack_string-function-success","expected":{"cmd":"/scoreboard players get success h146","messages":[[["success has 0 [h146]",[null,false,false,false,false,false]]]],"results":[[true,0]]},"actual":{"cmd":"/scoreboard players get success h146","messages":[[["success has -99 [h146]",[null,false,false,false,false,false]]]],"results":[[true,-99]]}}
{"label":"initial-pack_string-after","expected":{"cmd":"/scoreboard players get pack_string h146","messages":[[["pack_string has -99 [h146]",[null,false,false,false,false,false]]]],"results":[[true,-99]]},"actual":{"cmd":"/scoreboard players get pack_string h146","messages":[[["pack_string has 15 [h146]",[null,false,false,false,false,false]]]],"results":[[true,15]]}}
{"label":"reloaded-broken-availability","expected":{"cmd":"/execute store result score result h146 store success score success h146 run datapack enable \"file/h146-broken\"","messages":[[["Unknown data pack 'file/h146-broken'",[16733525,false,false,false,false,false]]]],"results":[[false,0]]},"actual":{"cmd":"/execute store result score result h146 store success score success h146 run datapack enable \"file/h146-broken\"","messages":[[["Pack 'file/h146-broken' is already enabled!",[16733525,false,false,false,false,false]]]],"results":[[false,0]]}}
{"label":"reloaded-broken-function","expected":{"cmd":"/execute store result score result h146 store success score success h146 run function h146:broken","messages":[[["Unknown function h146:broken",[16733525,false,false,false,false,false]]]],"results":[[false,0]]},"actual":{"cmd":"/execute store result score result h146 store success score success h146 run function h146:broken","messages":[[["Running function h146:broken",[null,false,false,false,false,false]]]],"results":[]}}
{"label":"reloaded-broken-function-result","expected":{"cmd":"/scoreboard players get result h146","messages":[[["result has 0 [h146]",[null,false,false,false,false,false]]]],"results":[[true,0]]},"actual":{"cmd":"/scoreboard players get result h146","messages":[[["result has -99 [h146]",[null,false,false,false,false,false]]]],"results":[[true,-99]]}}
{"label":"reloaded-broken-function-success","expected":{"cmd":"/scoreboard players get success h146","messages":[[["success has 0 [h146]",[null,false,false,false,false,false]]]],"results":[[true,0]]},"actual":{"cmd":"/scoreboard players get success h146","messages":[[["success has -99 [h146]",[null,false,false,false,false,false]]]],"results":[[true,-99]]}}
{"label":"reloaded-broken-after","expected":{"cmd":"/scoreboard players get broken h146","messages":[[["broken has -99 [h146]",[null,false,false,false,false,false]]]],"results":[[true,-99]]},"actual":{"cmd":"/scoreboard players get broken h146","messages":[[["broken has 11 [h146]",[null,false,false,false,false,false]]]],"results":[[true,11]]}}
{"label":"reloaded-root_empty-availability","expected":{"cmd":"/execute store result score result h146 store success score success h146 run datapack enable \"file/h146-root_empty\"","messages":[[["Unknown data pack 'file/h146-root_empty'",[16733525,false,false,false,false,false]]]],"results":[[false,0]]},"actual":{"cmd":"/execute store result score result h146 store success score success h146 run datapack enable \"file/h146-root_empty\"","messages":[[["Pack 'file/h146-root_empty' is already enabled!",[16733525,false,false,false,false,false]]]],"results":[[false,0]]}}
{"label":"reloaded-root_empty-function","expected":{"cmd":"/execute store result score result h146 store success score success h146 run function h146:root_empty","messages":[[["Unknown function h146:root_empty",[16733525,false,false,false,false,false]]]],"results":[[false,0]]},"actual":{"cmd":"/execute store result score result h146 store success score success h146 run function h146:root_empty","messages":[[["Running function h146:root_empty",[null,false,false,false,false,false]]]],"results":[]}}
{"label":"reloaded-root_empty-function-result","expected":{"cmd":"/scoreboard players get result h146","messages":[[["result has 0 [h146]",[null,false,false,false,false,false]]]],"results":[[true,0]]},"actual":{"cmd":"/scoreboard players get result h146","messages":[[["result has -99 [h146]",[null,false,false,false,false,false]]]],"results":[[true,-99]]}}
{"label":"reloaded-root_empty-function-success","expected":{"cmd":"/scoreboard players get success h146","messages":[[["success has 0 [h146]",[null,false,false,false,false,false]]]],"results":[[true,0]]},"actual":{"cmd":"/scoreboard players get success h146","messages":[[["success has -99 [h146]",[null,false,false,false,false,false]]]],"results":[[true,-99]]}}
{"label":"reloaded-root_empty-after","expected":{"cmd":"/scoreboard players get root_empty h146","messages":[[["root_empty has -99 [h146]",[null,false,false,false,false,false]]]],"results":[[true,-99]]},"actual":{"cmd":"/scoreboard players get root_empty h146","messages":[[["root_empty has 12 [h146]",[null,false,false,false,false,false]]]],"results":[[true,12]]}}
{"label":"reloaded-root_array-availability","expected":{"cmd":"/execute store result score result h146 store success score success h146 run datapack enable \"file/h146-root_array\"","messages":[[["Unknown data pack 'file/h146-root_array'",[16733525,false,false,false,false,false]]]],"results":[[false,0]]},"actual":{"cmd":"/execute store result score result h146 store success score success h146 run datapack enable \"file/h146-root_array\"","messages":[[["Pack 'file/h146-root_array' is already enabled!",[16733525,false,false,false,false,false]]]],"results":[[false,0]]}}
{"label":"reloaded-root_array-function","expected":{"cmd":"/execute store result score result h146 store success score success h146 run function h146:root_array","messages":[[["Unknown function h146:root_array",[16733525,false,false,false,false,false]]]],"results":[[false,0]]},"actual":{"cmd":"/execute store result score result h146 store success score success h146 run function h146:root_array","messages":[[["Running function h146:root_array",[null,false,false,false,false,false]]]],"results":[]}}
{"label":"reloaded-root_array-function-result","expected":{"cmd":"/scoreboard players get result h146","messages":[[["result has 0 [h146]",[null,false,false,false,false,false]]]],"results":[[true,0]]},"actual":{"cmd":"/scoreboard players get result h146","messages":[[["result has -99 [h146]",[null,false,false,false,false,false]]]],"results":[[true,-99]]}}
{"label":"reloaded-root_array-function-success","expected":{"cmd":"/scoreboard players get success h146","messages":[[["success has 0 [h146]",[null,false,false,false,false,false]]]],"results":[[true,0]]},"actual":{"cmd":"/scoreboard players get success h146","messages":[[["success has -99 [h146]",[null,false,false,false,false,false]]]],"results":[[true,-99]]}}
{"label":"reloaded-root_array-after","expected":{"cmd":"/scoreboard players get root_array h146","messages":[[["root_array has -99 [h146]",[null,false,false,false,false,false]]]],"results":[[true,-99]]},"actual":{"cmd":"/scoreboard players get root_array h146","messages":[[["root_array has 13 [h146]",[null,false,false,false,false,false]]]],"results":[[true,13]]}}
{"label":"reloaded-pack_empty-availability","expected":{"cmd":"/execute store result score result h146 store success score success h146 run datapack enable \"file/h146-pack_empty\"","messages":[[["Unknown data pack 'file/h146-pack_empty'",[16733525,false,false,false,false,false]]]],"results":[[false,0]]},"actual":{"cmd":"/execute store result score result h146 store success score success h146 run datapack enable \"file/h146-pack_empty\"","messages":[[["Pack 'file/h146-pack_empty' is already enabled!",[16733525,false,false,false,false,false]]]],"results":[[false,0]]}}
{"label":"reloaded-pack_empty-function","expected":{"cmd":"/execute store result score result h146 store success score success h146 run function h146:pack_empty","messages":[[["Unknown function h146:pack_empty",[16733525,false,false,false,false,false]]]],"results":[[false,0]]},"actual":{"cmd":"/execute store result score result h146 store success score success h146 run function h146:pack_empty","messages":[[["Running function h146:pack_empty",[null,false,false,false,false,false]]]],"results":[]}}
{"label":"reloaded-pack_empty-function-result","expected":{"cmd":"/scoreboard players get result h146","messages":[[["result has 0 [h146]",[null,false,false,false,false,false]]]],"results":[[true,0]]},"actual":{"cmd":"/scoreboard players get result h146","messages":[[["result has -99 [h146]",[null,false,false,false,false,false]]]],"results":[[true,-99]]}}
{"label":"reloaded-pack_empty-function-success","expected":{"cmd":"/scoreboard players get success h146","messages":[[["success has 0 [h146]",[null,false,false,false,false,false]]]],"results":[[true,0]]},"actual":{"cmd":"/scoreboard players get success h146","messages":[[["success has -99 [h146]",[null,false,false,false,false,false]]]],"results":[[true,-99]]}}
{"label":"reloaded-pack_empty-after","expected":{"cmd":"/scoreboard players get pack_empty h146","messages":[[["pack_empty has -99 [h146]",[null,false,false,false,false,false]]]],"results":[[true,-99]]},"actual":{"cmd":"/scoreboard players get pack_empty h146","messages":[[["pack_empty has 14 [h146]",[null,false,false,false,false,false]]]],"results":[[true,14]]}}
{"label":"reloaded-pack_string-availability","expected":{"cmd":"/execute store result score result h146 store success score success h146 run datapack enable \"file/h146-pack_string\"","messages":[[["Unknown data pack 'file/h146-pack_string'",[16733525,false,false,false,false,false]]]],"results":[[false,0]]},"actual":{"cmd":"/execute store result score result h146 store success score success h146 run datapack enable \"file/h146-pack_string\"","messages":[[["Pack 'file/h146-pack_string' is already enabled!",[16733525,false,false,false,false,false]]]],"results":[[false,0]]}}
{"label":"reloaded-pack_string-function","expected":{"cmd":"/execute store result score result h146 store success score success h146 run function h146:pack_string","messages":[[["Unknown function h146:pack_string",[16733525,false,false,false,false,false]]]],"results":[[false,0]]},"actual":{"cmd":"/execute store result score result h146 store success score success h146 run function h146:pack_string","messages":[[["Running function h146:pack_string",[null,false,false,false,false,false]]]],"results":[]}}
{"label":"reloaded-pack_string-function-result","expected":{"cmd":"/scoreboard players get result h146","messages":[[["result has 0 [h146]",[null,false,false,false,false,false]]]],"results":[[true,0]]},"actual":{"cmd":"/scoreboard players get result h146","messages":[[["result has -99 [h146]",[null,false,false,false,false,false]]]],"results":[[true,-99]]}}
{"label":"reloaded-pack_string-function-success","expected":{"cmd":"/scoreboard players get success h146","messages":[[["success has 0 [h146]",[null,false,false,false,false,false]]]],"results":[[true,0]]},"actual":{"cmd":"/scoreboard players get success h146","messages":[[["success has -99 [h146]",[null,false,false,false,false,false]]]],"results":[[true,-99]]}}
{"label":"reloaded-pack_string-after","expected":{"cmd":"/scoreboard players get pack_string h146","messages":[[["pack_string has -99 [h146]",[null,false,false,false,false,false]]]],"results":[[true,-99]]},"actual":{"cmd":"/scoreboard players get pack_string h146","messages":[[["pack_string has 15 [h146]",[null,false,false,false,false,false]]]],"results":[[true,15]]}}
```
## Predeclared raw traces
Complete original reference and native trace records follow. Absolute startup clocks are unequal raw values; the separate relative-zero invariant remains strict. Full pack lists can also reflect independent feature-pack behavior; no full list equality or metadata-schema closure is claimed. All repeated fresh Java traces and complete loader logs are retained privately without normalization.
```jsonl
{"capture":"java-v1/java","record":{"cmd":"/execute store result score start h146 run time query gametime","messages":[[["The game time is 313 tick(s)",[null,false,false,false,false,false]]]],"results":[[true,313]]}}
{"capture":"java-v1/java","record":{"cmd":"/datapack list enabled","messages":[[["There are 3 data pack(s) enabled: ",[null,false,false,false,false,false]],["[",[5635925,false,false,false,false,false]],["vanilla (built-in)",[11184810,false,false,false,false,false]],["]",[5635925,false,false,false,false,false]],[", ",[11184810,false,false,false,false,false]],["[",[5635925,false,false,false,false,false]],["file/h146-description (world)",[11184810,false,false,false,false,false]],["]",[5635925,false,false,false,false,false]],[", ",[11184810,false,false,false,false,false]],["[",[5635925,false,false,false,false,false]],["file/h146-valid (world)",[11184810,false,false,false,false,false]],["]",[5635925,false,false,false,false,false]]]],"results":[[true,3]]}}
{"capture":"java-v1/java","record":{"cmd":"/datapack list available","messages":[[["There are no more data packs available",[null,false,false,false,false,false]]]],"results":[[true,0]]}}
{"capture":"java-v1/java","record":{"cmd":"/datapack list enabled","messages":[[["There are 6 data pack(s) enabled: ",[null,false,false,false,false,false]],["[",[5635925,false,false,false,false,false]],["vanilla (built-in)",[11184810,false,false,false,false,false]],["]",[5635925,false,false,false,false,false]],[", ",[11184810,false,false,false,false,false]],["[",[5635925,false,false,false,false,false]],["file/h146-description (world)",[11184810,false,false,false,false,false]],["]",[5635925,false,false,false,false,false]],[", ",[11184810,false,false,false,false,false]],["[",[5635925,false,false,false,false,false]],["file/h146-valid (world)",[11184810,false,false,false,false,false]],["]",[5635925,false,false,false,false,false]],[", ",[11184810,false,false,false,false,false]],["[",[5635925,false,false,false,false,false]],["minecart_improvements (feature)",[11184810,false,false,false,false,false]],["]",[5635925,false,false,false,false,false]],[", ",[11184810,false,false,false,false,false]],["[",[5635925,false,false,false,false,false]],["redstone_experiments (feature)",[11184810,false,false,false,false,false]],["]",[5635925,false,false,false,false,false]],[", ",[11184810,false,false,false,false,false]],["[",[5635925,false,false,false,false,false]],["trade_rebalance (feature)",[11184810,false,false,false,false,false]],["]",[5635925,false,false,false,false,false]]]],"results":[[true,6]]}}
{"capture":"java-v1/java","record":{"cmd":"/datapack list available","messages":[[["There are no more data packs available",[null,false,false,false,false,false]]]],"results":[[true,0]]}}
{"capture":"java-v1/java","record":{"cmd":"/execute store result score end h146 run time query gametime","messages":[[["The game time is 313 tick(s)",[null,false,false,false,false,false]]]],"results":[[true,313]]}}
{"capture":"old-v1/rust","record":{"cmd":"/execute store result score start h146 run time query gametime","messages":[[["The game time is 0 tick(s)",[null,false,false,false,false,false]]]],"results":[[true,0]]}}
{"capture":"old-v1/rust","record":{"cmd":"/datapack list enabled","messages":[[["There are 8 data pack(s) enabled: ",[null,false,false,false,false,false]],["[",[5635925,false,false,false,false,false]],["vanilla (built-in)",[11184810,false,false,false,false,false]],["]",[5635925,false,false,false,false,false]],[", ",[11184810,false,false,false,false,false]],["[",[5635925,false,false,false,false,false]],["file/h146-broken (world)",[11184810,false,false,false,false,false]],["]",[5635925,false,false,false,false,false]],[", ",[11184810,false,false,false,false,false]],["[",[5635925,false,false,false,false,false]],["file/h146-description (world)",[11184810,false,false,false,false,false]],["]",[5635925,false,false,false,false,false]],[", ",[11184810,false,false,false,false,false]],["[",[5635925,false,false,false,false,false]],["file/h146-pack_empty (world)",[11184810,false,false,false,false,false]],["]",[5635925,false,false,false,false,false]],[", ",[11184810,false,false,false,false,false]],["[",[5635925,false,false,false,false,false]],["file/h146-pack_string (world)",[11184810,false,false,false,false,false]],["]",[5635925,false,false,false,false,false]],[", ",[11184810,false,false,false,false,false]],["[",[5635925,false,false,false,false,false]],["file/h146-root_array (world)",[11184810,false,false,false,false,false]],["]",[5635925,false,false,false,false,false]],[", ",[11184810,false,false,false,false,false]],["[",[5635925,false,false,false,false,false]],["file/h146-root_empty (world)",[11184810,false,false,false,false,false]],["]",[5635925,false,false,false,false,false]],[", ",[11184810,false,false,false,false,false]],["[",[5635925,false,false,false,false,false]],["file/h146-valid (world)",[11184810,false,false,false,false,false]],["]",[5635925,false,false,false,false,false]]]],"results":[[true,8]]}}
{"capture":"old-v1/rust","record":{"cmd":"/datapack list available","messages":[[["There are no more data packs available",[null,false,false,false,false,false]]]],"results":[[true,0]]}}
{"capture":"old-v1/rust","record":{"cmd":"/datapack list enabled","messages":[[["There are 8 data pack(s) enabled: ",[null,false,false,false,false,false]],["[",[5635925,false,false,false,false,false]],["vanilla (built-in)",[11184810,false,false,false,false,false]],["]",[5635925,false,false,false,false,false]],[", ",[11184810,false,false,false,false,false]],["[",[5635925,false,false,false,false,false]],["file/h146-broken (world)",[11184810,false,false,false,false,false]],["]",[5635925,false,false,false,false,false]],[", ",[11184810,false,false,false,false,false]],["[",[5635925,false,false,false,false,false]],["file/h146-description (world)",[11184810,false,false,false,false,false]],["]",[5635925,false,false,false,false,false]],[", ",[11184810,false,false,false,false,false]],["[",[5635925,false,false,false,false,false]],["file/h146-pack_empty (world)",[11184810,false,false,false,false,false]],["]",[5635925,false,false,false,false,false]],[", ",[11184810,false,false,false,false,false]],["[",[5635925,false,false,false,false,false]],["file/h146-pack_string (world)",[11184810,false,false,false,false,false]],["]",[5635925,false,false,false,false,false]],[", ",[11184810,false,false,false,false,false]],["[",[5635925,false,false,false,false,false]],["file/h146-root_array (world)",[11184810,false,false,false,false,false]],["]",[5635925,false,false,false,false,false]],[", ",[11184810,false,false,false,false,false]],["[",[5635925,false,false,false,false,false]],["file/h146-root_empty (world)",[11184810,false,false,false,false,false]],["]",[5635925,false,false,false,false,false]],[", ",[11184810,false,false,false,false,false]],["[",[5635925,false,false,false,false,false]],["file/h146-valid (world)",[11184810,false,false,false,false,false]],["]",[5635925,false,false,false,false,false]]]],"results":[[true,8]]}}
{"capture":"old-v1/rust","record":{"cmd":"/datapack list available","messages":[[["There are no more data packs available",[null,false,false,false,false,false]]]],"results":[[true,0]]}}
{"capture":"old-v1/rust","record":{"cmd":"/execute store result score end h146 run time query gametime","messages":[[["The game time is 0 tick(s)",[null,false,false,false,false,false]]]],"results":[[true,0]]}}
{"capture":"fixed-v1/rust","record":{"cmd":"/execute store result score start h146 run time query gametime","messages":[[["The game time is 0 tick(s)",[null,false,false,false,false,false]]]],"results":[[true,0]]}}
{"capture":"fixed-v1/rust","record":{"cmd":"/datapack list enabled","messages":[[["There are 3 data pack(s) enabled: ",[null,false,false,false,false,false]],["[",[5635925,false,false,false,false,false]],["vanilla (built-in)",[11184810,false,false,false,false,false]],["]",[5635925,false,false,false,false,false]],[", ",[11184810,false,false,false,false,false]],["[",[5635925,false,false,false,false,false]],["file/h146-description (world)",[11184810,false,false,false,false,false]],["]",[5635925,false,false,false,false,false]],[", ",[11184810,false,false,false,false,false]],["[",[5635925,false,false,false,false,false]],["file/h146-valid (world)",[11184810,false,false,false,false,false]],["]",[5635925,false,false,false,false,false]]]],"results":[[true,3]]}}
{"capture":"fixed-v1/rust","record":{"cmd":"/datapack list available","messages":[[["There are no more data packs available",[null,false,false,false,false,false]]]],"results":[[true,0]]}}
{"capture":"fixed-v1/rust","record":{"cmd":"/datapack list enabled","messages":[[["There are 3 data pack(s) enabled: ",[null,false,false,false,false,false]],["[",[5635925,false,false,false,false,false]],["vanilla (built-in)",[11184810,false,false,false,false,false]],["]",[5635925,false,false,false,false,false]],[", ",[11184810,false,false,false,false,false]],["[",[5635925,false,false,false,false,false]],["file/h146-description (world)",[11184810,false,false,false,false,false]],["]",[5635925,false,false,false,false,false]],[", ",[11184810,false,false,false,false,false]],["[",[5635925,false,false,false,false,false]],["file/h146-valid (world)",[11184810,false,false,false,false,false]],["]",[5635925,false,false,false,false,false]]]],"results":[[true,3]]}}
{"capture":"fixed-v1/rust","record":{"cmd":"/datapack list available","messages":[[["There are no more data packs available",[null,false,false,false,false,false]]]],"results":[[true,0]]}}
{"capture":"fixed-v1/rust","record":{"cmd":"/execute store result score end h146 run time query gametime","messages":[[["The game time is 0 tick(s)",[null,false,false,false,false,false]]]],"results":[[true,0]]}}
```
+55
View File
@@ -0,0 +1,55 @@
# Folder required data-pack metadata (H146)
The repair admits a folder only after the existing metadata parser succeeds, its root and `pack` section are objects, and `description` is present and non-null. This is **required-section/description-presence admission**, not full component/schema/format validation. The official `Pack.readPackMetadata` fallback still requires the description; description-only packs are a positive control.
## Frozen runtime proof
Base: `41944ed91474c6af28572d2e2273b6b2bd0bcf1e`. Eight independent folders contain valid ordinary functions with distinct score effects and no function tags. They are measured at initial load and after actual `/reload`.
| Metadata | Fresh Java | Untouched Game |
| --- | --- | --- |
| broken JSON `{` | unavailable, score -99 | exposed, score 11 |
| empty root `{}` | unavailable, score -99 | exposed, score 12 |
| array root `[]` | unavailable, score -99 | exposed, score 13 |
| empty `pack` object | unavailable, score -99 | exposed, score 14 |
| string `pack` | unavailable, score -99 | exposed, score 15 |
| missing metadata file | unavailable, score -99 | unavailable, score -99 |
| full valid metadata | admitted, score 17 | admitted, score 17 |
| description-only metadata | admitted, score 18 | admitted, score 18 |
The predeclared **241-record** program keeps all complete command feedback/styles, callbacks, fresh result/success stores, per-pack availability and function calls, score sentinels, actual owner identity/body, floor/load and relative-zero-clock controls strict. Complete pack lists and absolute startup clocks are separate raw diagnostics declared before capture. Their differences do not change the canonical denominator. Each valid file independently proves pack/content admission.
Untouched Game matches **191/241**. All 50 residuals concern the five malformed folders, at both phases. The missing-file negative and both passing metadata controls match. The fixed Game matches **241/241**, using the same original script and byte-identical fresh Java reference.
- Program SHA-256: `fac040797aea7b8a7190919581677fa0566b0c1105c7c31c07b0ee27f3206656`.
- Emitted script SHA-256: `3e72d31d7b03e10c1051cad53f15a76bc252d94ae39412d74174ce5308720c89`.
- Fresh Java reference SHA-256: `59972462b2579fd5a4f035ad0147d0505c9ebb823f77db463da9bb62e7911b98`.
- Untouched binary SHA-256: `a378b4f7dff3d35c3dbe56cf5106d326c0a9497f19c912182d464512d62a11a4`.
```sh
PATH=/opt/homebrew/opt/openjdk/bin:$PATH PYTHONPATH=tools \
python3 tools/test_folder_datapack_metadata_parity.py \
--work-dir .local/folder-metadata-java --reference-only
PATH=/opt/homebrew/opt/openjdk/bin:$PATH PYTHONPATH=tools \
python3 tools/test_folder_datapack_metadata_parity.py \
--work-dir .local/folder-metadata-game --binary /path/to/horizon-client \
--reference .local/folder-metadata-java/vanilla.jsonl
```
Each runtime capture uses the same program and checks fresh Java canonical bytes against the retained reference. The production gate never executes commands to validate metadata; the fixture invokes functions only after availability checks to measure actual side effects. There is no H144 syntax or H145 tag prerequisite in these files.
## Source reach and regression controls
The condition is local to the directory branch of `datapack::discover_folder`. Its world-discovery list feeds `pack_stack`/enabled selection and the content consumers, so invalid folders are excluded before files are exposed. Runtime coverage here is functions; the independently implemented Create World pack screen still uses `packs::folder` and is not changed or claimed. `packs::parse_meta` gains only `pub(crate)` visibility; its first-JSON/BOM behavior is unchanged. Existing resource-pack folder/ZIP callers keep the same parser and behavior. Data-pack ZIP discovery, builtin/feature constructors, metadata interpretation, format policy, overlays and priority are unchanged.
The real discovery/DataStore unit and resource-backed Game function-command unit fail old and pass fixed. The Game control exercises both initial load and reload and proves invalid folders cannot expose or run their valid functions. Numeric description, null rejection, BOM, trailing comment, builtin and feature-construction controls are supplemental units; the runtime matrix remains the original eight forms. No JSON value is routed through the NbtOps component decoder. Numeric description bytes remain numeric; existing description interpretation is preserved.
Older positive-only synthetic pack fixtures now provide a valid description instead of empty/missing required metadata. Their assertions, content and model state are unchanged. The same test-only corrections are used old/fixed; the common test patch and raw intended failures are retained. The Game unit is placed away from H144's concrete insertion point. No pending H144/H145 production is imported, and the actual function lifecycle/tag code is untouched.
## Limits and evidence
Unmeasured malformed rich descriptions may still be admitted. The next action for full description-codec validity is a separately scoped JSON component admission review; this patch is not full H146 schema closure. ZIP/resource/feature validation and format compatibility are not claimed. H144 ordinary syntax and H145 required tags remain independent.
Complete loader logs, original declarations/program/reference, runtime records, test failures, raw diagnostics, binaries and manifests are retained in `.local/h146/`. [The residual report](folder-datapack-metadata-residuals.md) publishes all old strict differences and the predeclared raw trace records. No all-pack-list or raw absolute-clock equality is claimed.
Fixed binary SHA-256: `a2e9779136effbbbf31852b588cb5907f1bfd73bd225994e300d580156480c89`. Required local checks are reported in the PR; the 241-record runtime pair is separate from the wider harness list.
@@ -0,0 +1,79 @@
#!/usr/bin/env python3
"""Folder pack metadata admission using real independent functions."""
import hashlib,json,sys,tempfile
from pathlib import Path
import test_command_exec_parity as driver
PACKS={
'broken':'{', 'root_empty':'{}', 'root_array':'[]',
'pack_empty':'{"pack":{}}', 'pack_string':'{"pack":"bad"}',
'missing':None,
'valid':'{"pack":{"description":"H146 full","pack_format":121,"min_format":[121,0],"max_format":[121,0]}}',
'description':'{"pack":{"description":"H146 description only"}}',
}
VALUES={name:i+11 for i,name in enumerate(PACKS)}
VALID={'valid','description'}
def program():
ops=[]
def cmd(text,label,result=None,admission=True,trace=False):
o=dict(op='cmd',cmd=text,label=label,admission=admission)
if result is not None:o['expect_result']=result
if trace:o.update(record=False,trace=True)
ops.append(o)
cmd('/tick freeze','freeze');cmd('/gamerule spawn_mobs false','no-spawn');cmd('/gamerule advance_time false','no-daylight')
cmd('/forceload add 0 0','force',1);ops.append(dict(op='settle',required_chunks=[[0,0]]))
cmd('/fill 0 199 0 15 199 15 stone','floor',256);cmd('/tp @s 4.5 200 4.5 0 0','owner-pos',1);cmd('/gamemode creative @s','owner-mode')
cmd('/execute if entity @s[type=player,name=Player,nbt={Health:20f,playerGameType:1,Pos:[4.5d,200d,4.5d]}]','owner-body',1);cmd('/data get entity @s UUID','owner-uuid',4)
cmd('/execute if loaded 4 200 4','loaded',1);cmd('/execute if block 4 199 4 stone','support',1)
cmd('/scoreboard objectives add h146 dummy','objective');cmd('/execute store result score start h146 run time query gametime','clock-start',trace=True)
for phase in ['initial','reloaded']:
if phase=='reloaded':
for name in PACKS:cmd(f'/scoreboard players set {name} h146 -99',f'{phase}-{name}-before-reload',-99)
cmd('/reload','reload')
for name in PACKS:cmd(f'/scoreboard players get {name} h146',f'{phase}-{name}-after-reload',-99)
cmd('/datapack list enabled',phase+'-enabled',trace=True);cmd('/datapack list available',phase+'-available',trace=True)
for name in PACKS:
label=f'{phase}-{name}'
cmd(f'/scoreboard players set {name} h146 -99',label+'-reset',-99);cmd(f'/scoreboard players get {name} h146',label+'-before',-99)
for operation in ['availability','function']:
for key in ['result','success']:cmd(f'/scoreboard players set {key} h146 -99',f'{label}-{operation}-reset-{key}',-99)
action=f'datapack enable "file/h146-{name}"' if operation=='availability' else f'function h146:{name}'
cmd(f'/execute store result score result h146 store success score success h146 run {action}',f'{label}-{operation}',admission=False)
for key in ['result','success']:cmd(f'/scoreboard players get {key} h146',f'{label}-{operation}-{key}',admission=False)
cmd(f'/scoreboard players get {name} h146',label+'-after',VALUES[name] if name in VALID else -99,admission=name in VALID)
cmd('/execute if entity @s[type=player,nbt={Health:20f,Pos:[4.5d,200d,4.5d]}]',phase+'-owner-still-valid',1)
cmd('/execute store result score end h146 run time query gametime','clock-end',trace=True)
cmd('/scoreboard players operation end h146 -= start h146','clock-delta-operation',0);cmd('/scoreboard players get end h146','clock-delta',0)
return ops
def main():
reference=None
if '--reference' in sys.argv:
i=sys.argv.index('--reference');reference=Path(sys.argv[i+1]).resolve();del sys.argv[i:i+2]
if '--work-dir' not in sys.argv:
parent=Path(tempfile.mkdtemp(prefix='folder-metadata-',dir=driver.lab.LOCAL));sys.argv+=['--work-dir',str(parent/'run')]
build=Path(sys.argv[sys.argv.index('--work-dir')+1]).resolve();assert not build.exists(),'preserve attempts';build.mkdir(parents=True)
ops=program();recorded=[o for o in ops if o['op']=='cmd' and o.get('record',True)]
(build/'declaration.json').write_text(json.dumps(dict(script_sha256=hashlib.sha256(Path(__file__).read_bytes()).hexdigest(),records=len(recorded),labels=[o['label'] for o in recorded],packs=PACKS,values=VALUES,scope='all complete canonical records strict; complete pack lists/absolute clocks separate predeclared raw traces'),indent=2)+'\n')
install=driver.install_datapack_fixtures
def install_packs(world,*args,**kwargs):
install(world,*args,**kwargs)
for name,meta in PACKS.items():
pack=world/'datapacks'/f'h146-{name}';target=pack/'data/h146/function'/f'{name}.mcfunction';target.parent.mkdir(parents=True,exist_ok=True)
target.write_text(f'scoreboard players set {name} h146 {VALUES[name]}\n')
if meta is not None:(pack/'pack.mcmeta').write_text(meta)
driver.install_datapack_fixtures=install_packs
driver.corpus_module.function_return_fixtures=lambda names:{}
driver.corpus_module.groups=lambda:[('Folder metadata admission',ops)]
expected=reference.read_bytes() if reference else None
sys.argv.append('--allow-gaps');driver.main()
java_bytes=(build/'vanilla.jsonl').read_bytes()
if expected is not None:assert java_bytes==expected and reference.read_bytes()==expected,'reference bytes changed'
if '--reference-only' in sys.argv:return
java=[json.loads(x) for x in java_bytes.splitlines()];native=[json.loads(x) for x in (build/'rust.jsonl').read_bytes().splitlines()];assert len(recorded)==len(java)==len(native)
residuals=[dict(label=o['label'],expected=a,actual=b) for o,a,b in zip(recorded,java,native) if a!=b]
report=dict(records=len(recorded),passed=len(recorded)-len(residuals),residuals=residuals,reference_sha256=hashlib.sha256(java_bytes).hexdigest());(build/'strict-report.json').write_text(json.dumps(report,indent=2)+'\n')
for o,a,b in zip(recorded,java,native):
if o['admission']:assert a==b,('admission',o,a,b)
print(f'Strict records: {report["passed"]}/{report["records"]}')
if residuals:raise SystemExit(1)
if __name__=='__main__':main()