20 KiB
P18-01-CODE implementation handoff
Status: repair 5 submitted for Root native and Runner verification; no acceptance or unit completion claimed. P02-01 inputs are now readable and verified. The repair-3/4 notes below are retained history; repair 5 supersedes their input availability gap.
Repair 3 historical failure (2026-10-15)
Historical record only: stopping independent repairs over decoder permissiveness was wrong. The commander producer-evidence interpretation supersedes this old policy concern; the following describes the failed repair-3 attempt, not the current policy.
Inspected baseline d2a1f80a61 using read-only git show.
RelationshipState.from_snapshot delegates to configure; _value preserves canonical
key precedence. Numeric fields use int(), with clampi/maxi where applicable.
Thus finite fractional numbers are truncated as well as integral JSON floats;
numeric strings such as metrics.affection = "42" are also converted. The baseline
RelationshipService._parse_snapshot similarly converts version and candidate
sequence with int(). These are broader than a finite-integral-float-only policy.
No acceptance policy for these conflicting formats has been selected here.
Baseline normalization also replaces non-Dictionary metrics, action_counts, daily_metric_deltas, flags and crossed_thresholds with defaults, coerces flags with bool(), and ignores non-Array threshold collections. The immutable spec requires wrong types to reject, while the repair direction requires baseline legitimate acceptance without a new restriction or loosening. In particular, accepting or rejecting numeric strings cannot satisfy both without an explicit policy decision. Non-numeric/non-finite input, wrong containers, future versions, duplicates, invalid references, corrupt original records and projection mismatches remain required rejections under the spec; this report does not waive any.
Baseline Runtime restore delegates legacy relationships to RelationshipService without the added actor-existence loop. Baseline GuestService.despawn_guest retains the departed guest in persistent_records and removes it from active guests. The held actor loop is therefore still an unresolved repair item. Candidate catalog selection, lifecycle tests, mutation-through-alias tests, atomic rejection coverage and source-pin updates are also still outstanding. The numeric Reader helpers in SimulationSnapshot and SaveService accept bounded finite integral JSON floats for their own envelope fields; they do not establish a policy overriding RelationshipState's coercions. P02-01 representative-save applicability has not been established; no fixture acceptance claim is made.
Only this handoff and prepare-only evidence were changed. Production code, test sources and marker/policy pins were left untouched pending policy resolution. Prepare-only exited 0: 1,311 source files, 67,310,742 bytes; 3,384,279,040 free bytes; 381,883,542 conservative required bytes; capacity available. Seven suites: original_relationship_model, original_relationship_runtime, relationship_event_service, runtime_relationship_events, runtime_snapshot_serialization, runtime_save_lifecycle, staff_management. 308 future parse paths and nine future native phases; engines/stages = 0, actual_checks = null, formal_acceptance = false. The first invocation omitted required --output and exited 2; the corrected invocation used the allowed p18-01-code/repair-3-prepare output path. Native checks were not run. P18-01 remains 30/88, in progress, with no partial credit.
Scope: dedicated original relationship state, lossless legacy snapshot preservation, Runtime registration and read projection, and the contract-listed tests and collector. Production initial values and gameplay coefficients are not supplied or inferred.
Validation: worker static inspection only; authoritative native local and affected validation, independent review, and integration belong to Runner.
Source inspection: HEAD matches d2a1f80a61.
The acceptance specification without its final newline matches the contract SHA256
04e9ae701b6ee1e399542564add695ca7fce54499e52dd2e907b1dbdc23a366d.
Submitted behavior
- OriginalRelationshipState stores explicit directional subject/protagonist/rival facts with Affection, Lust, Netorare and shield current/max. All fields are required for a configured record. Numeric inputs must be finite numbers; shield current must be nonnegative and at most max, and max equals Affection. No additional emotion ranges, coefficients or production values are imposed.
- RelationshipService retains its five-axis API. Its v2 snapshot contains the
whole v1 payload under
legacy, plus separateoriginal_relationships. Top-levelrelationshipsis a compatibility projection for existing consumers; disagreement withlegacy.relationshipsis rejected. Additional legacy fields, raw aliases, collection order and untouched values survive migration. The existing normalized state remains usable; only actual legacy changes are merged into retained raw facts. Aliases never initialize original fields. - Registration uses
register_original_relationshipwith the complete payload. Runtime validates the protagonist againstplayer, the subject against hired UNIQUE staff and its canonical role, and heroine/rival identities and reciprocal counterpart references against the existing unique-character catalog. Rival catalog membership does not invent recruitment. No new original update policy, contact, route, attack, threshold or duel behavior is defined. - Snapshot restore validates candidates before replacing live services, then rebinds the identity validator to live staff. Legacy relationships retain the original acceptance of departed guests; original records separately validate staff/person/catalog references.
- Every staff-management row exposes
original_relationship. Missing records haveconfigured: falseand null values, distinct from explicit zero. Configured projections are copies, so reads and caller edits cannot change service state.
Validation and handoff
Two new s4 suites exercise explicit/unset/zero data, malformed and nonfinite values, identity invariants, lossless raw aliases/extensions, new and mixed round trips, atomic service/Runtime rejection, actual hiring/commands, restore/rebind and reports. Existing test bodies and limits are unchanged. New marker and suite-policy rows are pinned to the exact new test sources.
python3 -B tools/run_p18_relationship_tests.py --prepare-only previews the exact
seven-suite roster, source bytes, capacity and all-script parse count without
engines, profiles, stage creation or test execution. The native collector reuses
run_all_tests.source_refs/execute_phase and the existing Guard, owned_outer,
diagnostic, artifact, PID, marker and cleanup gates. It stops at the first failure;
Runner owns repair/validation sequencing and independent review.
Worker checks: Python AST syntax, JSON/source-marker consistency, allowed-path
inspection, unchanged pre-existing marker/policy records, and git diff whitespace.
Native import, GDScript parse and all seven suites remain unexecuted by worker.
Worker reinspection on 2026-10-13 confirmed the existing submitted implementation
and repeated Python AST, specification digest, exact new marker/policy source
hashes, unchanged existing marker/policy records, and git diff --check.
Prepare-only exited 0: seven suites, 1,311 source files / 67,287,056 bytes,
308 parse paths, nine future native phases, 381,859,856 conservative required
bytes and 1,773,187,072 available bytes. Engines and stages were both zero;
actual checks were null and formal acceptance was false. Capacity is a preview
at that instant, not a reservation or native result.
An initial shell here-document temporary-file attempt was denied with
operation not permitted; normal allowed-path patch edits worked. No isolation
rule or permission was relaxed.
P18-C-1 through P18-C-3 are implementation submissions, not accepted results. P18-C-4 awaits Runner native local/affected evidence, separate Opus review, integration and final affected validation. The original P18-01 unit remains in_progress: ordinary Japanese UI rendering/equality, approved production values, all-seven recruitment, final full required roster and applicable Windows final acceptance remain outstanding. No git writes, other agents or Runner controls were used by worker.
Repair 4 producer interpretation and independent repairs
The unchanged wrong-types/valid-legacy contract follows legitimate producers,
not corrupt-input coercions. RelationshipState.create_snapshot
(scripts/relationship/relationship_state.gd:132-152) emits String ids/route,
int numeric fields, named route_lock, Dictionary numeric/bool collections and
Array thresholds. Its validity check (:99-101) requires int metrics.
Read-only git log identifies 423fd6d as the only history entry for that file;
git show of that producer (:132-152) also emits the enum NAME String, not int.
Actual writer scripts/core/save_service.gd:874-878 serializes the snapshot with var_to_bytes and ZSTD; Reader :1021-1028 uses bytes_to_var. Thus world numeric ints remain ints. JSON decoding (:970-978) applies to the manifest, not relationship payloads. Integral JSON floats are not an established relationship save format on this path. Accept int legacy values, named route_lock and producer collections. Reject numeric strings, null, bool-as-number, fractional/nonfinite numbers, float relationship numbers, int route_lock, wrong containers and invalid enum names. Unknown extensions remain opaque; canonical values precede aliases, and aliases, unknown facts and collection order remain raw retained facts. Neither old axis configures original Affection/Lust/Netorare.
relationship_service.gd _legacy_types_valid now also checks collection key types and restricts route_lock to producer enum names. The pre-existing int/container checks implement the producer policy. No conversion or rewrite of raw input occurs. Runtime candidate validation now takes restored_catalog; command/service binding uses the live catalog. Removed only the added active legacy actor loop. GuestService.despawn_guest (scripts/guest/guest_service.gd:954-978) retains the persistent record and removes the active guest, so that loop rejected valid saves. Original identity/person validation remains in place. Existing StaffService.remove_staff (:897-898) and retire_staff (:942-943) already refuse UNIQUE departures before changes; tests assert refusal and saved original record survival. No new departure rule or record deletion was added.
The two new suites now cover real Service and Runtime affection/dependence mutations from v1 affinity/obligation, canonical precedence, raw extensions and order, null original values, v2 restore/rebind, departed persistent guest acceptance, and atomic malformed candidates. Rejection checks retain service identity/state, whole Runtime bytes and caller input. The five existing suites remain unchanged. Fixtures are validation inputs, not production values or newly hired characters.
Collector derives every sorted .gd path from the exact shared.source_refs map. Verification binds parse-paths.json, the receipt count, the unique zero-failure FULL_DEPENDENCY_PARSE marker, actual_parse_checks and the whole retained stage to that same source map. No count-specific skips or other provenance changes. This frozen map has 308 paths; expanded maps must verify their own full count.
Precise remaining context gap
The P02-01 input manifest referenced by docs/plans/original-completion-2026-10-02/execution/multi-agent-dev-handoff/delivery_contract_proposal.json:333 is absent at artifacts/original-completion-2026-10-02/p02-01-fixed-baseline-r01/input-manifest.json in this worktree. Reading the exact production-root counterpart returns Operation not permitted. Production-root listing/search is also denied. No representative save bytes or decoded fixture are available in this checkout; .review-material is absent. Accordingly their exact types/applicability have NOT been verified, no older conflicting producer shape is asserted, and no replacement representative fixture has been invented. Runner/owner must supply readable pinned manifest and applicable save members to finish that mandatory evidence and test. This gap did not stop the independent repairs. No native checks were executed. UI, values, routes, contacts and duel remain untouched. P18-01 remains 30/88, in progress. Native seven-suite frozen evidence, p18-model validation, separate Opus review, latest-main integration and fresh merged-source evidence remain Root/Runner work; no completion claim is made.
Worker static/prepare evidence (repair 4)
Python AST parsed successfully. git diff --check passed. Both new suite SHA-256 pins match their final source in marker contracts and suite-policy; all other rows are unchanged. The five existing suite files are byte-identical to HEAD. No engine, native collector, default profile or full regression was run.
Prepare-only roster (seven): original_relationship_model, original_relationship_runtime, relationship_event_service, runtime_relationship_events, runtime_snapshot_serialization, runtime_save_lifecycle, staff_management. Full paths are the unchanged ROSTER in tools/run_p18_relationship_tests.py:17-25. Initial repair-4 preview: 1,311 files, 67,318,770 source bytes, 3,388,039,168 free bytes, conservative single-set admission 381,891,570 bytes, 308 parse paths, nine future phases, engines/stages zero, actual_checks null, formal_acceptance false. A final preview after final edits is retained separately as repair-4-prepare.json. No native pass is implied by this preview.
Using the supplied old output estimate conservatively as 474 MiB per full set (including 351 MiB engine), two fresh sets require 948 MiB = 994,050,048 bytes. They fit the observed ~3.39 GB free space, with ~2.39 GB left before other new consumers. This is capacity arithmetic, not a reservation or a measured new run; actual output growth remains Root's admission responsibility.
Repair 5: readable fixed inputs and representative binding
All work continues from preserved HEAD 0084760ee0.
Before edits, the nine dirty files were hashed; exact paths and SHA-256 are in
repair-5-start-shas.json. The command direction supplies no nine-file publication
hash table, and no publication table is present in the supplied input context.
Therefore full publication equality cannot independently be asserted. Both
existing test hashes matched their repair-4 marker/policy pins. Current bytes
were preserved and independent work continued; no reset/reimplementation occurred.
Only the supplied p02-01-fixed-inputs-for-p18-r05 context was used for external input. No production absolute path in the manifest was followed. Manifest SHA: d07b6c42ecca11bf3557ee5034ce9cc70b5a750f7b08b6b40f9ef09cdbe787c2. ROOT_COPY_PROVENANCE.json's manifest hash, all 28 copy-file size/hash entries, and all 20 original member size/hash entries verified successfully. No missing file or mismatch occurred. Exact per-member evidence is retained in repair-5-input-evidence.json; inspect_repair5_inputs.py reproduces the read-only verification and equivalent little-endian typed Variant decoding. It checks TTWB/version/header size, compressed-world checksum, ZSTD expansion length and complete Variant stream consumption. Unsupported types fail explicitly.
Observed package evidence
All five contain a Dictionary v1 relationship payload with an Array relationships collection, empty; threshold_candidates is empty, and version and next_candidate_sequence are typed ints. Metric/shield/day fields are absent because there are no relationship records: their Variant types are unobserved, not float, int, null or guessed defaults.
| Package | world.bin bytes | Expanded Variant bytes | world.bin SHA-256 |
|---|---|---|---|
| initial | 7523 | 61132 | df91b4624c9afdeea2d366ff38d9f545fcff3f5f99223e3c04ae66d04b2f9fab |
| operating | 48631 | 1020364 | 93732bb0bc042f4da0f90879a03dc3f3e374b3b45000840b0cbae142c42601c6 |
| moving | 27413 | 390624 | a577b190cb3b18cfc5cca1ef15d26521ea950bf5f3d3da68d19b1c8f43672158 |
| date-boundary | 26686 | 579376 | d4443f0bd42c2e9d6a5dd07d1949deade5d7526036f1320b56336b5637c9fcc3 |
| defense | 10110 | 78904 | 34ab140d64743b89425c292b785827fdb82c2bf92510688a4038461a2fe7a5d7 |
Type decision and applicability
Actual producer scripts/core/save_service.gd:874 uses var_to_bytes(snapshot); :878 compresses ZSTD. Actual Reader :1021-1028 expands then bytes_to_var. Manifest JSON (:1754) carries identity metadata, not relationship values. RelationshipState.create_snapshot (scripts/relationship/relationship_state.gd:132-152) emits typed int metric/shield/day values. No actual relationship JSON-float path was found. Keep the repair-4 int-only legacy checks closed to floats (scripts/relationship/relationship_service.gd:544-587); no production type change was required. Strings, null, bool-as-number, floats including NaN/Inf and wrong containers remain rejected. No synthetic float producer was invented.
The empty real collections prove compatibility only for those actual snapshots; they do not prove every non-empty metric shape, alias or historical producer. Existing focused alias/mutation fixtures and explicit original fixtures provide non-empty coverage and remain validation inputs, never production approval.
Binding: all five exact world.bin files are embedded in the already source-hashed test_original_relationship_runtime.gd REPRESENTATIVE_SAVES constant. TTWB payloads are already ZSTD compressed, so the base64 contains compressed bytes, not expanded Variant streams. Embedded manifests retain the actual checksums. Each test verifies world.bin size and full SHA before writing only into its owned user://saves/p18_* fixture directory. It invokes the actual SaveService._load_snapshot_absolute_v1 Reader with validation, then actual Runtime.restore_snapshot. It asserts exact legacy facts, null/unconfigured original projections (including the no-staff case), input preservation, read nonmutation, actual SaveService writer/Reader v2 relationship round trip and Runtime equality. Physical package format is selected by SaveService; relationship v2 does not invent a new physical save format.
Corruption candidates derive from each decoded representative, changing the actual relationships collection to String, Dictionary or null, and assert rejection preserves service identity, service/whole-Runtime bytes and input bytes. Empty representatives cannot provide corrupt per-record metric examples; existing focused non-empty numeric-string/container tests cover those shapes separately. Fixture package directories are removed after each applicable test. No loose fixture binaries or collector fixture-map exceptions were added. All source-map, stage, per-phase/final inventory guards and source-proof semantics are unchanged.
The five existing suites remain byte-identical to HEAD. Production scripts, original values, UI, routes, contacts and duel are untouched in repair 5. Both new-test pins in marker contracts and suite-policy are refreshed to exact final source digests. Native suites and GDScript engine parse remain unexecuted. P18-01 remains 30/88, in progress. Fresh native seven, strict p18-model, separate Opus review, latest-main integration and fresh merged native evidence are the next Root/Runner gates, not backend acceptance or unit completion.
Repair-5 static/prepare result
Python AST, independent extraction of all five embedded compressed streams and their size/SHA checks, exact marker/policy pins, unchanged non-P18 policy/marker records, five existing suite byte equality, and git diff --check passed. Preserved Runtime/service/model/collector and repair-4-prepare hashes still match the repair-5 starting bytes. No engine, native collector, full regression, Runner, git write, branch/main operation or additional agent was used.
Final prepare-only receipt is repair-5-prepare.json. Roster (7): original_relationship_model, original_relationship_runtime, relationship_event_service, runtime_relationship_events, runtime_snapshot_serialization, runtime_save_lifecycle, staff_management. The exact shared source_refs map yields 1,311 files, 67,498,284 bytes and 308 sorted .gd parse paths; nine future native phases. Empty actual checks, engines/stages = 0 and formal_acceptance = false. Free space at preview: 3,390,361,600 bytes (about 3.39 GB); single-set admission 382,071,084 bytes. At the conservative prior estimate of 474 MiB per set, two fresh native sets require 994,050,048 bytes and fit, leaving about 2.39 GB. Capacity remains a point-in-time preview, not reserved disk or native evidence.