Merge commit '265ce30f81b1302ca374330f7129f02d6fde4697' into HEAD

This commit is contained in:
Agent Control Runner
2026-10-15 23:13:10 +09:00
19 changed files with 3436 additions and 11 deletions
@@ -2,6 +2,28 @@
"schema_version": 1,
"scope": "exact per-suite completion label/schema; all check counts from actual raw only",
"rows": [
{
"test": "tests/s4/test_original_relationship_model.gd",
"template": "Original relationship model: <checks> checks, <failures> failures",
"required": true,
"fixed_check_count_used": false,
"source_sha256_at_schema_audit": "c74b243dbbb54dba9bbc165e29508cca910f0beb63e32d25ebbb8ea606dccce9",
"authority": {
"path": "docs/spec/acceptance/P18-01-code-r01.json",
"scope": "new backend suite marker; native execution pending"
}
},
{
"test": "tests/s4/test_original_relationship_runtime.gd",
"template": "Original relationship runtime: <checks> checks, <failures> failures",
"required": true,
"fixed_check_count_used": false,
"source_sha256_at_schema_audit": "c56bdb99dd43a4e7ceb3ca2861e8db39972c5c4e805126a77e2f7da32ca5bdc9",
"authority": {
"path": "docs/spec/acceptance/P18-01-code-r01.json",
"scope": "new backend suite marker; native execution pending"
}
},
{
"test": "tests/ui/test_selection_departure.gd",
"template": "Selection departure: <checks> checks, <failures> failures",
@@ -0,0 +1,356 @@
# 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 d2a1f80a613e7c77b02b941026bc49c2d85db863 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 d2a1f80a613e7c77b02b941026bc49c2d85db863.
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 separate `original_relationships`.
Top-level `relationships` is a compatibility projection for existing consumers;
disagreement with `legacy.relationships` is 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_relationship` with the complete payload.
Runtime validates the protagonist against `player`, 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
have `configured: false` and 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 0084760ee05a97adfcbd783a71161491f3629918.
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.
### Repair 6 — actual Opus high/medium feedback
Preserved the held implementation and all representative inputs. Added strict
candidate field validation matching `_register_threshold_candidate`: identifiers
and actor identities accept String/StringName, deduplication_key is String,
threshold/created_at are int, requires_unlock_event is bool, and actor_ids is
an Array of two identities. No numeric bounds or gameplay policy were added.
Unknown candidate fields remain raw facts.
The new Runtime suite now keeps nested legacy and compatibility projection
identical for the exclusive-route positive control and empty-route-only negative
control. Both exercise normal restore and real checksum-valid SaveService package
recovery. Negative checks retain whole Runtime bytes, service identity/bytes,
caller bytes, RESTORE_FAILED, restore_committed=false and no forbidden repair.
Producer-created typed candidates traverse v1, v2 and package recovery; String
identifier compatibility and unknown raw extensions have positive controls.
Each reviewed wrong field type exercises service, normal Runtime and recovery
rejection for both v1 and v2. Native execution remains pending Root ownership.
Ordering disposition: preserve restored raw collection order under the explicit
lossless round-trip contract. Fresh snapshots retain their existing sorted output.
The actual producer issues zero-padded monotonic ids; after restore, new candidates
append without disturbing raw facts. Added a real producer mutation check for
that boundary. No new sorting policy was introduced. The unrelated absolute-path
historical inspector limitation remains deferred.
Static diff whitespace checks passed. All five existing suites retain the exact
SHA-256 values forwarded by Root. Both new test pins remain exact (model unchanged;
Runtime c56bdb99dd43a4e7ceb3ca2861e8db39972c5c4e805126a77e2f7da32ca5bdc9).
Prepare-only: seven suites, 308 parse paths, 1,311 source files, zero engines/stages,
no executed checks and formal_acceptance=false. No native/default-profile/full
regression, git writes, Runner operations, integration or agents were used.
P18-01 remains 30/88, in progress; submitted for Root verification, not accepted.
The final repair-6-prepare.json receipt records 67,504,813 source bytes,
2,674,012,160 free bytes and 382,077,613 single-set admission bytes. Two sets
at the retained conservative 474 MiB estimate require 994,050,048 bytes and fit
at this preview. Capacity is not reserved and must be checked at collection time.
@@ -0,0 +1,94 @@
"""Read-only equivalent of SaveService's ZSTD/Variant reader; no engine invocation."""
import base64
import hashlib
import json
from pathlib import Path
import struct
import subprocess
CONTEXT = Path('/Users/korizatou114/Projects/TheTree-managed-worktrees/p18-01-model/.runtime/P18-01-CODE/build/p02-01-fixed-inputs-for-p18-r05')
HERE = Path(__file__).parent
class VariantReader:
def __init__(self, data):
self.data, self.offset = data, 0
def unpack(self, fmt):
value = struct.unpack_from('<' + fmt, self.data, self.offset)[0]
self.offset += struct.calcsize('<' + fmt)
return value
def read(self):
header = self.unpack('I')
kind = header & 0xffff
wide = bool(header & 0x10000)
if kind == 0:
return None
if kind == 1:
return bool(self.unpack('I'))
if kind == 2:
return self.unpack('q' if wide else 'i')
if kind == 3:
return self.unpack('d' if wide else 'f')
if kind in (5, 6, 7, 8, 9, 10, 12, 13):
count = {5: 2, 6: 2, 7: 4, 8: 4, 9: 3, 10: 3, 12: 4, 13: 4}[kind]
fmt = 'i' if kind in (6, 8, 10, 13) else ('d' if wide else 'f')
return tuple(self.unpack(fmt) for _ in range(count))
if kind in (4, 21):
size = self.unpack('I')
value = self.data[self.offset:self.offset + size].decode('utf-8')
self.offset += (size + 3) & ~3
return value
if kind == 27:
count = self.unpack('I') & 0x7fffffff
result = {}
for _ in range(count):
key = self.read()
result[key] = self.read()
return result
if kind == 28:
if (header >> 16) & 3:
assert (header >> 16) & 3 == 1, 'only builtin typed arrays supported'
self.unpack('I') # element Variant type, values remain individually tagged
return [self.read() for _ in range(self.unpack('I') & 0x7fffffff)]
raise ValueError(f'unsupported Variant {kind} at {self.offset - 4}')
def inspect():
manifest_bytes = (CONTEXT / 'input-manifest.json').read_bytes()
provenance = json.loads((CONTEXT / 'ROOT_COPY_PROVENANCE.json').read_bytes())
digest = hashlib.sha256(manifest_bytes).hexdigest()
assert digest == provenance['original_manifest_sha256'] == 'd07b6c42ecca11bf3557ee5034ce9cc70b5a750f7b08b6b40f9ef09cdbe787c2'
manifest = json.loads(manifest_bytes)
for entry in provenance['copy_files']:
path = Path(entry['target'])
assert path.is_relative_to(CONTEXT), str(path)
data = path.read_bytes()
assert len(data) == entry['bytes'] and hashlib.sha256(data).hexdigest() == entry['sha256'], str(path)
evidence = {'manifest_sha256': digest, 'verified_copy_files': len(provenance['copy_files']), 'members': {}, 'packages': {}}
for package, members in manifest['original_packages'].items():
for member, pin in members.items():
path = CONTEXT / 'saves' / package / member
data = path.read_bytes()
assert len(data) == pin['bytes'] and hashlib.sha256(data).hexdigest() == pin['sha256'], str(path)
evidence['members'][f'{package}/{member}'] = {'bytes': len(data), 'sha256': pin['sha256']}
world = (CONTEXT / 'saves' / package / 'world.bin').read_bytes()
magic, version, size = struct.unpack('<4sIQ', world[:16])
assert magic == b'TTWB' and version == 1
save_manifest = json.loads((CONTEXT / 'saves' / package / 'manifest.json').read_bytes())
assert hashlib.sha256(world[16:]).hexdigest() == save_manifest['checksum_world']
raw = subprocess.run(['zstd', '-d', '-q', '-c'], input=world[16:], check=True, capture_output=True).stdout
assert len(raw) == size
reader = VariantReader(raw)
snapshot = reader.read()
assert reader.offset == len(raw)
relationships = snapshot['systems']['runtime']['relationships']
evidence['packages'][package] = {'world_bytes': len(world), 'raw_bytes': size, 'relationship_payload': relationships,
'collection_present': 'relationships' in relationships, 'collection_type': type(relationships.get('relationships')).__name__,
'collection_count': len(relationships['relationships']), 'metric_shield_day_types': 'not observed: empty relationship collection'}
return evidence
if __name__ == '__main__':
print(json.dumps(inspect(), indent=2))
@@ -0,0 +1 @@
{"roster": ["tests/s4/test_original_relationship_model.gd", "tests/s4/test_original_relationship_runtime.gd", "tests/s4/test_relationship_event_service.gd", "tests/s4/test_runtime_relationship_events.gd", "tests/s6/test_runtime_snapshot_serialization.gd", "tests/s6/test_runtime_save_lifecycle.gd", "tests/ui/test_staff_management.gd"], "source_files": 1311, "source_bytes": 67319279, "free_bytes": 3396403200, "conservative_required_bytes": 381892079, "capacity_available": true, "parse_paths": 308, "future_native_phases": 9, "actual_checks": null, "engines": 0, "stages": 0, "formal_acceptance": false}
@@ -0,0 +1,158 @@
{
"manifest_sha256": "d07b6c42ecca11bf3557ee5034ce9cc70b5a750f7b08b6b40f9ef09cdbe787c2",
"verified_copy_files": 28,
"members": {
"initial/journal.log": {
"bytes": 35,
"sha256": "1ec35136aeb728392a832cd3b9197b270f96779cb09c7fe9c51ed385e30f158d"
},
"initial/world.bin": {
"bytes": 7523,
"sha256": "df91b4624c9afdeea2d366ff38d9f545fcff3f5f99223e3c04ae66d04b2f9fab"
},
"initial/manifest.json": {
"bytes": 420,
"sha256": "e9c4f7a8ea4ce9897c1e66c7861779fcd558f2dc314e08dbaef1b59bd145f419"
},
"initial/thumbnail.png": {
"bytes": 83,
"sha256": "0ef55674eca98b6748ae5ccca85a14b042c1545a143810c9c47b487119895c32"
},
"operating/journal.log": {
"bytes": 35,
"sha256": "2c7f851e72867d6d44247baa7624af46d22abaa31cb16dff197e8e5914d1e866"
},
"operating/world.bin": {
"bytes": 48631,
"sha256": "93732bb0bc042f4da0f90879a03dc3f3e374b3b45000840b0cbae142c42601c6"
},
"operating/manifest.json": {
"bytes": 422,
"sha256": "9c8b2c813c78ea1e19f43af31e77ff1547d707ca93f0d142c9e0df5e9bee8bd6"
},
"operating/thumbnail.png": {
"bytes": 83,
"sha256": "0ef55674eca98b6748ae5ccca85a14b042c1545a143810c9c47b487119895c32"
},
"moving/journal.log": {
"bytes": 35,
"sha256": "5f5f1cbb5a4b1c94945f503ae9c62989f628aa1db498974e3d5c3fe04cb89120"
},
"moving/world.bin": {
"bytes": 27413,
"sha256": "a577b190cb3b18cfc5cca1ef15d26521ea950bf5f3d3da68d19b1c8f43672158"
},
"moving/manifest.json": {
"bytes": 416,
"sha256": "52e87c19e39d7e4e922b47ef5979f4fecbe3211bd3f193ab30fd5418fffc5c73"
},
"moving/thumbnail.png": {
"bytes": 83,
"sha256": "0ef55674eca98b6748ae5ccca85a14b042c1545a143810c9c47b487119895c32"
},
"date-boundary/journal.log": {
"bytes": 35,
"sha256": "6fe4347f04e624f74a77d0eb85738508f653103e7522a0d37ed811519b5fe34f"
},
"date-boundary/world.bin": {
"bytes": 26686,
"sha256": "d4443f0bd42c2e9d6a5dd07d1949deade5d7526036f1320b56336b5637c9fcc3"
},
"date-boundary/manifest.json": {
"bytes": 430,
"sha256": "5e604491f863537d390f9db11f9dcc2473fcbf7fc0bced8d326caae893572ea2"
},
"date-boundary/thumbnail.png": {
"bytes": 83,
"sha256": "0ef55674eca98b6748ae5ccca85a14b042c1545a143810c9c47b487119895c32"
},
"defense/journal.log": {
"bytes": 35,
"sha256": "1ec35136aeb728392a832cd3b9197b270f96779cb09c7fe9c51ed385e30f158d"
},
"defense/world.bin": {
"bytes": 10110,
"sha256": "34ab140d64743b89425c292b785827fdb82c2bf92510688a4038461a2fe7a5d7"
},
"defense/manifest.json": {
"bytes": 418,
"sha256": "91d209a9bc295eadfa761359670a0c53ec7799a1f2ab53eedaacc14b2430b015"
},
"defense/thumbnail.png": {
"bytes": 83,
"sha256": "0ef55674eca98b6748ae5ccca85a14b042c1545a143810c9c47b487119895c32"
}
},
"packages": {
"initial": {
"world_bytes": 7523,
"raw_bytes": 61132,
"relationship_payload": {
"version": 1,
"relationships": [],
"threshold_candidates": [],
"next_candidate_sequence": 1
},
"collection_present": true,
"collection_type": "list",
"collection_count": 0,
"metric_shield_day_types": "not observed: empty relationship collection"
},
"operating": {
"world_bytes": 48631,
"raw_bytes": 1020364,
"relationship_payload": {
"version": 1,
"relationships": [],
"threshold_candidates": [],
"next_candidate_sequence": 1
},
"collection_present": true,
"collection_type": "list",
"collection_count": 0,
"metric_shield_day_types": "not observed: empty relationship collection"
},
"moving": {
"world_bytes": 27413,
"raw_bytes": 390624,
"relationship_payload": {
"version": 1,
"relationships": [],
"threshold_candidates": [],
"next_candidate_sequence": 1
},
"collection_present": true,
"collection_type": "list",
"collection_count": 0,
"metric_shield_day_types": "not observed: empty relationship collection"
},
"date-boundary": {
"world_bytes": 26686,
"raw_bytes": 579376,
"relationship_payload": {
"version": 1,
"relationships": [],
"threshold_candidates": [],
"next_candidate_sequence": 1
},
"collection_present": true,
"collection_type": "list",
"collection_count": 0,
"metric_shield_day_types": "not observed: empty relationship collection"
},
"defense": {
"world_bytes": 10110,
"raw_bytes": 78904,
"relationship_payload": {
"version": 1,
"relationships": [],
"threshold_candidates": [],
"next_candidate_sequence": 1
},
"collection_present": true,
"collection_type": "list",
"collection_count": 0,
"metric_shield_day_types": "not observed: empty relationship collection"
}
}
}
@@ -0,0 +1,22 @@
{
"roster": [
"tests/s4/test_original_relationship_model.gd",
"tests/s4/test_original_relationship_runtime.gd",
"tests/s4/test_relationship_event_service.gd",
"tests/s4/test_runtime_relationship_events.gd",
"tests/s6/test_runtime_snapshot_serialization.gd",
"tests/s6/test_runtime_save_lifecycle.gd",
"tests/ui/test_staff_management.gd"
],
"source_files": 1311,
"source_bytes": 67498284,
"free_bytes": 3390361600,
"conservative_required_bytes": 382071084,
"capacity_available": true,
"parse_paths": 308,
"future_native_phases": 9,
"actual_checks": null,
"engines": 0,
"stages": 0,
"formal_acceptance": false
}
@@ -0,0 +1,11 @@
{
"autoload/simulation_runtime.gd": "0c8c9356a78bf9df16c362e202a362e044bae018f40efb54145713582d69a2d2",
"docs/plans/original-completion-2026-10-02/execution/completion_marker_contracts.json": "ea74b503b41d7a38f0ee26f8a7d03626edd7d941329d2355ce235d65d2bf4855",
"docs/plans/original-completion-2026-10-02/execution/p18-01-code/IMPLEMENTATION.md": "28fa682dcc4f6b33347d6e10046d093f3bfb43bae04bb3411d368885d53cc8bc",
"scripts/relationship/relationship_service.gd": "2d137a4dc3712356434b2609723b88292fb717625241e07f9e60984d830df80a",
"tests/s4/test_original_relationship_model.gd": "c74b243dbbb54dba9bbc165e29508cca910f0beb63e32d25ebbb8ea606dccce9",
"tests/s4/test_original_relationship_runtime.gd": "349271cc8b8a4750ef339ecac6905852bd7a5d006cca68ee10d5d0c737f426de",
"tools/regression/suite-policy.json": "2145ef977e72e490d27fddd550c0c00827b52a2e0b844d60e6f86df9a666d5ae",
"tools/run_p18_relationship_tests.py": "ccc8976dd9e9863366d102719dc0ae21d3a57da45dec39b4c72a3fc8c9f31a9b",
"docs/plans/original-completion-2026-10-02/execution/p18-01-code/repair-4-prepare.json": "9d0ae1b3f1e91d44ac84a2a55388bc56e96637dec925f42ecc9757de1c3a3a28"
}
@@ -0,0 +1 @@
{"roster": ["tests/s4/test_original_relationship_model.gd", "tests/s4/test_original_relationship_runtime.gd", "tests/s4/test_relationship_event_service.gd", "tests/s4/test_runtime_relationship_events.gd", "tests/s6/test_runtime_snapshot_serialization.gd", "tests/s6/test_runtime_save_lifecycle.gd", "tests/ui/test_staff_management.gd"], "source_files": 1311, "source_bytes": 67504813, "free_bytes": 2674012160, "conservative_required_bytes": 382077613, "capacity_available": true, "parse_paths": 308, "future_native_phases": 9, "actual_checks": null, "engines": 0, "stages": 0, "formal_acceptance": false}
@@ -0,0 +1,80 @@
# P18-01-CODE recorded repair 2/2: collection / verification split
Resumes candidate `f76ad96990a4d7371b6ab667df0a068cc06be798`. No counter reset,
game/test reconstruction, Runner change, commit or integration. Changes are confined
to the narrow collector and this note. Existing game behavior evidence remains the
retained Astra preflight; this worker did not rerun or reinterpret it as final proof.
## Modes
- Default: `python -B tools/run_p18_relationship_tests.py --output {build_dir}/p18-relationship-evidence`.
Read-only verification in the ordinary registered sandbox. No subprocess call,
process discovery, native launch, or access to the external player/private profiles.
Current checkout source/settings/support/marker bytes and the locally configured
`godot` binary are read for pins. Receipt-provided paths never select an external
file to open. Original absolute paths remain historical identity strings.
- `--collect`: Root orchestration only, outside Seatbelt. Uses the existing
`source_refs`, private source copy, `execute_phase`, owned_outer, Guard, logger,
diagnostic, marker and bounded cleanup contracts unchanged. Fresh output outside
the checkout, with an existing parent, is required. Runs import, all 308 scripts,
and exactly the seven fixed tests once. Owned profile bytes are archived after
each phase. The final verifier runs after collection; no duplicate regression.
“Root” identifies the authorized orchestrator, not a requirement to run as Unix uid 0.
- `--prepare-only`: reports source bytes, available capacity, 308 parse paths and
the exact seven-test/nine-phase roster; creates no stage/profile and starts no engine.
Only `--output`, `--collect`, `--prepare-only` and help are accepted. Duplicate,
abbreviated, unknown and malformed flags, combined modes, traversal, symlinks,
nonregular evidence and hardlinked evidence reject. Verification never rewrites
raw paths or files. The ordinary-owner pure proof reader maps only the original
output prefix to the supplied output and checks confinement before opening files.
## Receipt schema
`receipt.json` (`guarded-p18-v2`) is written last after successful collection.
It contains the full relative source content map (bytes/SHA-256, no checkout-path
dependency), its canonical JSON SHA-256, project and marker-contract SHA-256,
engine SHA-256, and a complete relative file inventory with byte sizes/SHA-256.
The inventory covers the retained private source, engine bytes, bootstraps,
starters, raw stdout/stderr/native logger, phase receipts, START/END/process and
both cleanup records, Guard reports, ordinary/audio ownership proofs, typed
snapshots, and complete archived startup/runtime profiles. Only the enclosing
receipt itself is outside its own inventory.
Verification checks the inventory and recomputes raw marker/diagnostic gates,
source and helper pins, exact commands, START/END identity, all nine distinct PIDs
and bounded cleanup, Guard conditions, proof gates, complete player before/after
inventory equality, and seven test rows against nine phase receipts. It requires
one exact `FULL_DEPENDENCY_PARSE checks=308 failures=0` marker. Old v1, absent,
incomplete, mismatched or altered evidence rejects. A source change, including
this collector, requires fresh Root collection; no source exemptions exist.
## Worker checks and environment observations
AST/in-memory compile and prepare-only passed. Prepare-only found 1311 source
files, 308 parse scripts, seven tests and nine future phases, with sufficient
reported capacity. Synthetic negative checks rejected missing receipts, changed
hashes, symlinks, relative and absolute escapes, incomplete files and invalid or
duplicate flags/mode combinations. Those checks replaced subprocess entry points
and default-player access with fail-fast functions; neither was called. No native
test, full regression, `--collect`, Runner operation or review was executed.
Environment evidence: a shell here-document failed with
`zsh:1: can't create temp file for here document: operation not permitted`.
The `python` alias was unavailable (`zsh:1: command not found: python`);
worker checks used `/usr/bin/python3 -B`. Ordinary authorized file edits and
temporary negative fixtures under the task allocation succeeded. No isolation
or permission policy was changed. Root/Runner must provide the configured
`python` command used by the fixed validator argv.
## Root next steps
1. On the final unchanged source, run the native `--collect` exactly once outside
Seatbelt into the allocation build directory's fresh `p18-relationship-evidence`.
Do not reuse old v1 evidence or run collection from ordinary Runner validation.
2. Run ordinary Runner validation using the fixed default verify-only argv.
3. Obtain a separate Opus review, then perform the authorized integration and
affected final validation. This worker submits implementation, not acceptance.
P18-01 remains incomplete: ordinary UI rendering/display equality, approved initial
values, the full final roster and applicable Windows final acceptance remain unmet.