Files
TheTree_mock/tests/mvp/test_unique_character_validation_policy.gd
T
Takeshi 5dde0c5ec2 Record original-alignment implementation and traceability checkpoint
Capture current source, content data, tests, asset licenses, and original-specification traceability. Original implementation remains incomplete. The accepted matching UI generation passed 154 suites and 12,253 checks, with eight rendered staff-contract screens reviewed. Latest native Windows and full-original acceptance remain outstanding.
2026-09-30 23:52:24 +09:00

289 lines
17 KiB
GDScript

extends SceneTree
## Boundary coverage for trusted per-person character definitions.
## The synthetic worker borrows existing metadata solely to exercise validators.
## It is not Fine, a proposed profile, recruitment or an active Runtime effect.
const CatalogType := preload("res://scripts/data/mvp_content_catalog.gd")
const FIXTURE_ID: StringName = &"heroine_policy_cleaner_fixture"
class EntryProbe:
extends MvpContentCatalog
func inspect_entry(entry: Dictionary) -> Dictionary:
_reset()
_validate_entry(&"unique_characters", StringName(_value(entry, &"id", &"")), entry)
return get_report()
func inspect_links(entries: Array, staff_index: Dictionary = {}) -> Dictionary:
_reset()
var index: Dictionary = {}
var ids: Array[StringName] = []
for entry: Dictionary in entries:
var entry_id: StringName = StringName(_value(entry, &"id", &""))
var errors_before: int = _errors.size()
_validate_entry(&"unique_characters", entry_id, entry)
if _errors.size() == errors_before:
index[entry_id] = _normalized_entry(entry)
ids.append(entry_id)
ids.sort_custom(_name_less)
_entries_by_type[&"unique_characters"] = index
_entries_by_type[&"staff_candidates"] = staff_index.duplicate(true)
_ordered_ids_by_type[&"unique_characters"] = ids
_validate_cross_references()
return get_report()
func policy_copy(entry_id: StringName) -> Dictionary:
return _unique_validation_policy(entry_id)
class ExplicitWorkerPolicyProbe:
extends EntryProbe
func _unique_validation_policy(entry_id: StringName) -> Dictionary:
if entry_id == &"heroine_policy_cleaner_fixture":
return {
&"character_kind": &"heroine",
&"mechanical_effect_ids": [&"cleaning_work_rate_multiplier"],
}
return super._unique_validation_policy(entry_id)
var checks := 0
var failures := 0
func _initialize() -> void:
call_deferred("run")
func run() -> void:
baseline_contract()
explicit_worker_boundary()
person_effect_isolation()
pair_boundary()
common_safety_boundary()
roster_atomicity_and_recovery()
if failures == 0:
print("PASS: UniqueCharacterValidationPolicy (%d checks)" % checks)
else:
push_error("FAIL: UniqueCharacterValidationPolicy (%d of %d checks failed)" % [failures, checks])
quit(failures)
func expect(ok: bool, label: String) -> void:
checks += 1
if not ok:
failures += 1
push_error("UNIQUE_POLICY: " + label)
func codes(report: Dictionary) -> Array[StringName]:
var result: Array[StringName] = []
for issue: Dictionary in report[&"errors"]:
result.append(StringName(issue[&"code"]))
return result
func documents() -> Dictionary:
var result: Dictionary = {}
for content_type: StringName in CatalogType.DEFAULT_PATHS:
var file := FileAccess.open(CatalogType.DEFAULT_PATHS[content_type], FileAccess.READ)
if file == null:
expect(false, "canonical input readable: " + String(content_type))
return {}
result[content_type] = JSON.parse_string(file.get_as_text())
file.close()
return result
func unique_entry(entry_id: StringName) -> Dictionary:
for entry: Dictionary in documents()[&"unique_characters"]["entries"]:
if StringName(entry["id"]) == entry_id:
return entry.duplicate(true)
return {}
func worker_entry() -> Dictionary:
var entry: Dictionary = unique_entry(&"heroine_anri")
entry["id"] = String(FIXTURE_ID)
entry["display_name"] = "検証専用・架空の清掃担当"
entry["role_id"] = "cleaner"
entry["mechanical_effects"] = {"cleaning_work_rate_multiplier": 3}
entry.erase("counterpart_id")
return entry
func baseline_contract() -> void:
var catalog := CatalogType.new()
var report: Dictionary = catalog.rebuild()
expect(bool(report[&"valid"]) and int(report[&"error_count"]) == 0, "unchanged two-person JSON validates")
expect(catalog.get_unique_character_ids() == [&"heroine_anri", &"rival_rai"], "normal unique roster remains exactly Anri and Rai")
expect(catalog.get_recruitable_staff_ids().size() == 22, "21 paid candidates plus approved Anri only")
expect(catalog.get_recruitment_entry(&"rival_rai").is_empty(), "Rai is not silently made recruitable")
expect(catalog.get_recruitment_entry(&"heroine_fine").is_empty(), "Fine is not registered")
expect(catalog.get_recruitment_entry(FIXTURE_ID).is_empty(), "synthetic worker is not registered")
var anri: Dictionary = catalog.get_entry(&"unique_characters", &"heroine_anri")
var rai: Dictionary = catalog.get_entry(&"unique_characters", &"rival_rai")
expect(anri[&"mechanical_effects"] == {&"assigned_floor_revenue_multiplier_bp": 12000}, "Anri's existing approved revenue definition is preserved")
expect(rai[&"mechanical_effects"] == {&"base_shield_attack": 8, &"night_shield_attack_bonus": 4}, "Rai's existing bounded attack definition is preserved")
expect(anri[&"counterpart_id"] == &"rival_rai" and rai[&"counterpart_id"] == &"heroine_anri", "explicit current MVP pair is preserved")
var payload: Dictionary = catalog.staff_hire_payload(&"heroine_anri")
expect(payload[&"options"][&"employment_kind"] == &"UNIQUE" and payload[&"options"][&"daily_wage"] == 0, "existing Anri hire payload remains free UNIQUE")
var probe := EntryProbe.new()
var policy: Dictionary = probe.policy_copy(&"heroine_anri")
policy[&"mechanical_effect_ids"].clear()
policy[&"counterpart_id"] = &"fabricated"
var pristine: Dictionary = probe.policy_copy(&"heroine_anri")
expect(pristine[&"mechanical_effect_ids"] == [&"assigned_floor_revenue_multiplier_bp"] and pristine[&"counterpart_id"] == &"rival_rai", "returned policy is an owned nested copy")
expect(probe.policy_copy(FIXTURE_ID).is_empty() and probe.policy_copy(&"heroine_fine").is_empty(), "production policy cannot infer synthetic or Fine identities")
func explicit_worker_boundary() -> void:
var probe := ExplicitWorkerPolicyProbe.new()
var entry: Dictionary = worker_entry()
var report: Dictionary = probe.inspect_entry(entry)
expect(int(report[&"error_count"]) == 0, "explicit synthetic policy accepts cleaning 3 without revenue or counterpart")
expect(not entry.has("counterpart_id") and not entry["mechanical_effects"].has("assigned_floor_revenue_multiplier_bp"), "positive fixture has neither an invented partner nor Anri effect")
report = probe.inspect_links([entry])
expect(int(report[&"error_count"]) == 0, "unpaired synthetic worker has no orphan or reciprocal requirement")
var ordinary_probe := EntryProbe.new()
report = ordinary_probe.inspect_entry(entry)
expect(&"missing_unique_policy" in codes(report), "same data without a trusted ID policy rejects")
for raw_counterpart: Variant in [null, "", "rival_rai", FIXTURE_ID, 7, true]:
entry = worker_entry()
entry["counterpart_id"] = raw_counterpart
report = probe.inspect_entry(entry)
expect(&"unexpected_counterpart" in codes(report), "unpaired policy rejects present counterpart value %s" % str(raw_counterpart))
entry = worker_entry()
entry[&"counterpart_id"] = &""
expect(&"unexpected_counterpart" in codes(probe.inspect_entry(entry)), "StringName counterpart presence also rejects")
for raw_value: Variant in [3, 3.0]:
entry = worker_entry()
entry["mechanical_effects"]["cleaning_work_rate_multiplier"] = raw_value
expect(int(probe.inspect_entry(entry)[&"error_count"]) == 0, "integer-compatible exact 3 follows existing numeric contract")
for raw_value: Variant in [0, 1, 2, 4, -3, 1000001, "3", true, null, 3.5, NAN, INF]:
entry = worker_entry()
entry["mechanical_effects"]["cleaning_work_rate_multiplier"] = raw_value
expect(&"invalid_mechanical_effect" in codes(probe.inspect_entry(entry)), "non-exact cleaning multiplier rejects: %s" % str(raw_value))
entry = worker_entry()
entry["id"] = "heroine_unknown_worker"
expect(&"missing_unique_policy" in codes(probe.inspect_entry(entry)), "fixture override does not accept arbitrary other workers")
entry = worker_entry()
entry["unique_policy"] = {"mechanical_effect_ids": ["cleaning_work_rate_multiplier"]}
expect(&"unknown_field" in codes(probe.inspect_entry(entry)), "JSON cannot inject or widen trusted policy")
func person_effect_isolation() -> void:
var probe := ExplicitWorkerPolicyProbe.new()
for person_id: StringName in [&"heroine_anri", &"rival_rai"]:
var entry: Dictionary = unique_entry(person_id)
entry["mechanical_effects"]["cleaning_work_rate_multiplier"] = 3
expect(&"effect_kind_mismatch" in codes(probe.inspect_entry(entry)), "reserved cleaning validator does not grant effect to " + String(person_id))
entry = unique_entry(person_id)
entry["mechanical_effects"] = {"cleaning_work_rate_multiplier": 3}
var issues: Array[StringName] = codes(probe.inspect_entry(entry))
expect(&"missing_mechanical_effect" in issues and &"effect_kind_mismatch" in issues, "replacement cleaning effect cannot satisfy " + String(person_id))
var worker: Dictionary = worker_entry()
worker["mechanical_effects"]["assigned_floor_revenue_multiplier_bp"] = 12000
expect(&"effect_kind_mismatch" in codes(probe.inspect_entry(worker)), "worker cannot acquire Anri's revenue effect")
worker = worker_entry()
worker["mechanical_effects"] = {"assigned_floor_revenue_multiplier_bp": 12000}
var worker_codes: Array[StringName] = codes(probe.inspect_entry(worker))
expect(&"missing_mechanical_effect" in worker_codes and &"effect_kind_mismatch" in worker_codes, "heroine kind is not a fallback to Anri effect")
worker = worker_entry()
worker["mechanical_effects"]["base_shield_attack"] = 8
expect(&"effect_kind_mismatch" in codes(probe.inspect_entry(worker)), "worker cannot acquire Rai's attack")
worker = worker_entry()
worker["mechanical_effects"]["arbitrary_runtime_hook"] = 1
var hook_codes: Array[StringName] = codes(probe.inspect_entry(worker))
expect(&"invalid_mechanical_effect" in hook_codes and &"effect_kind_mismatch" in hook_codes, "unknown hook remains rejected by value and person boundaries")
worker = worker_entry()
worker["mechanical_effects"] = {}
expect(&"missing_mechanical_effect" in codes(probe.inspect_entry(worker)), "an explicit worker still requires its own effect")
var anri: Dictionary = unique_entry(&"heroine_anri")
anri["character_kind"] = "rival"
expect(&"character_policy_mismatch" in codes(probe.inspect_entry(anri)), "known person's kind cannot be forged")
for person_id: StringName in [&"heroine_anri", &"rival_rai"]:
var entry: Dictionary = unique_entry(person_id)
entry["mechanical_effects"] = {"arbitrary_runtime_hook": 1}
var issues: Array[StringName] = codes(probe.inspect_entry(entry))
expect(&"invalid_mechanical_effect" in issues and &"effect_kind_mismatch" in issues and &"missing_mechanical_effect" in issues, "existing arbitrary hook safety contract retained for " + String(person_id))
for raw_value: Variant in [2499, 30001, "12000", true, NAN, INF]:
anri = unique_entry(&"heroine_anri")
anri["mechanical_effects"]["assigned_floor_revenue_multiplier_bp"] = raw_value
expect(&"invalid_mechanical_effect" in codes(probe.inspect_entry(anri)), "existing Anri bounds and type rejection retained")
for raw_value: Variant in [-1, 101, "8", true, NAN, INF]:
var rai: Dictionary = unique_entry(&"rival_rai")
rai["mechanical_effects"]["base_shield_attack"] = raw_value
expect(&"invalid_mechanical_effect" in codes(probe.inspect_entry(rai)), "existing Rai bounds and type rejection retained")
func pair_boundary() -> void:
var probe := ExplicitWorkerPolicyProbe.new()
var anri: Dictionary = unique_entry(&"heroine_anri")
var rai: Dictionary = unique_entry(&"rival_rai")
expect(int(probe.inspect_links([anri, rai, worker_entry()])[&"error_count"]) == 0, "existing explicit pair and a declared unpaired worker coexist at link boundary")
for person_id: StringName in [&"heroine_anri", &"rival_rai"]:
var paired_entry: Dictionary = unique_entry(person_id)
for raw_counterpart: Variant in [null, "", String(person_id), 7, true]:
paired_entry = unique_entry(person_id)
paired_entry["counterpart_id"] = raw_counterpart
expect(&"invalid_counterpart" in codes(probe.inspect_entry(paired_entry)), "paired person retains invalid counterpart rejection: " + String(person_id))
paired_entry = unique_entry(person_id)
paired_entry.erase("counterpart_id")
expect(&"invalid_counterpart" in codes(probe.inspect_entry(paired_entry)), "paired person cannot omit explicit partner: " + String(person_id))
anri = unique_entry(&"heroine_anri")
anri["counterpart_id"] = "missing_actor"
expect(&"missing_counterpart" in codes(probe.inspect_links([anri, rai])), "legacy orphan-reference error remains observable")
anri = unique_entry(&"heroine_anri")
anri["counterpart_id"] = String(FIXTURE_ID)
var issues: Array[StringName] = codes(probe.inspect_links([anri, rai, worker_entry()]))
expect(&"counterpart_policy_mismatch" in issues, "Anri cannot redirect to another declared worker")
expect(&"counterpart_not_reciprocal" in issues and &"counterpart_kind_conflict" in issues, "redirected relation still fails reciprocity and kind boundaries")
issues = codes(probe.inspect_links([worker_entry()], {FIXTURE_ID: {}}))
expect(&"runtime_actor_id_collision" in issues, "unpaired workers still participate in Runtime actor collision validation")
func common_safety_boundary() -> void:
var probe := ExplicitWorkerPolicyProbe.new()
for raw_verified: Variant in [false, "true", 1, null]:
var entry: Dictionary = worker_entry()
entry["adult_verified"] = raw_verified
expect(&"adult_verification_required" in codes(probe.inspect_entry(entry)), "declared policy cannot bypass explicit adult bool")
for raw_age: Variant in [17, 10001, "25", true, NAN, INF]:
var entry: Dictionary = worker_entry()
entry["age"] = raw_age
expect(&"adult_age_required" in codes(probe.inspect_entry(entry)), "declared policy cannot bypass existing age type/bounds")
for trait_id: String in ["unique", "unsellable"]:
var entry: Dictionary = worker_entry()
entry["traits"].erase(trait_id)
expect(&"unique_safety_traits_required" in codes(probe.inspect_entry(entry)), "declared worker still requires " + trait_id)
var entry: Dictionary = worker_entry()
entry["role_id"] = "maid"
expect(&"unknown_role" in codes(probe.inspect_entry(entry)), "policy cannot invent an unregistered role")
entry = worker_entry()
entry["skills"]["operation"] = 101
expect(&"map_value_out_of_range" in codes(probe.inspect_entry(entry)), "existing skill ceiling remains enforced")
entry = worker_entry()
entry["skills"].erase("operation")
expect(&"missing_map_key" in codes(probe.inspect_entry(entry)), "all canonical skills still required")
entry = worker_entry()
entry["mechanical_effects"][42] = 3
expect(&"canonical_key_collision" in codes(probe.inspect_entry(entry)), "non-text effect key cannot be coerced into a trusted effect ID")
entry = worker_entry()
entry["preferred_shift"] = "invalid_shift"
expect(&"unknown_shift" in codes(probe.inspect_entry(entry)), "known policy still requires registered shift")
entry = worker_entry()
entry["display_name"] = ""
expect(&"missing_display_name" in codes(probe.inspect_entry(entry)), "known policy still requires safe visible name")
func roster_atomicity_and_recovery() -> void:
var catalog := ExplicitWorkerPolicyProbe.new()
var baseline: Dictionary = documents()
var report: Dictionary = catalog.rebuild_from_documents(baseline)
expect(bool(report[&"valid"]), "fixture policy override does not alter current full baseline")
var generation: int = catalog.get_manifest_generation()
var changed: Dictionary = documents()
changed[&"unique_characters"]["entries"].append(worker_entry())
report = catalog.rebuild_from_documents(changed)
var issues: Array[StringName] = codes(report)
expect(not bool(report[&"valid"]) and &"mvp_count_mismatch" in issues and &"mvp_id_set_mismatch" in issues, "even explicitly declared third actor cannot enter the unchanged full roster")
expect(catalog.get_unique_character_ids().is_empty() and catalog.get_staff_candidate_ids().is_empty() and catalog.build_all_guest_definitions().is_empty(), "failed roster rebuild exposes no partial content")
expect(catalog.get_recruitable_staff_ids().is_empty() and catalog.staff_hire_payload(&"heroine_anri").is_empty(), "failed catalog cannot generate recruitment payloads")
expect(catalog.get_manifest_generation() == generation + 1, "failed rebuild invalidates transient generation exactly once")
report = catalog.rebuild_from_documents(baseline)
expect(bool(report[&"valid"]) and catalog.get_unique_character_ids() == [&"heroine_anri", &"rival_rai"], "exact baseline recovers without retaining the worker")
expect(catalog.get_manifest_generation() == generation + 2, "recovery invalidates generation exactly once")
changed = documents()
changed[&"unique_characters"]["entries"][0]["id"] = "heroine_unknown"
report = catalog.rebuild_from_documents(changed)
expect(not bool(report[&"valid"]) and &"missing_unique_policy" in codes(report), "same-count unknown identity is rejected before normal exposure")
expect(catalog.get_unique_character_ids().is_empty() and catalog.get_recruitable_staff_ids().is_empty(), "unknown person leaves no accepted or recruitable partial content")
changed = documents()
changed[&"unique_characters"]["entries"][0]["counterpart_id"] = "missing_actor"
var first: Dictionary = catalog.rebuild_from_documents(changed)
var second: Dictionary = catalog.rebuild_from_documents(changed)
expect(first[&"errors"] == second[&"errors"] and &"missing_counterpart" in codes(second), "original deterministic orphan error contract retained")