Files
EscapistsReintroduced/docs/evidence/playtest-refresh-2026-10-03-mounted-pair/preparation/finalize_docs.py
T
jakub 6a667d8deb Capture current mission, AI, map and administration development
Include the current addon, terrain integrations, tools, regression tests and recorded development evidence.
2026-10-13 22:52:53 +02:00

97 lines
11 KiB
Python

#!/usr/bin/env python3
"""Preview only by default; root applies after exact independent review/evidence."""
import argparse,ast,hashlib,json,sys
from pathlib import Path
HERE=Path(__file__).resolve().parent
load=lambda p:json.loads(p.read_text())
sha=lambda p:hashlib.sha256(p.read_bytes()).hexdigest()
ASSEMBLED_README='# Development candidate preparation\n\nMatching source and package hashes are verified in handoff.json. Ordinary packed startup is still pending. This is not a release or Workshop publication.\n'
def main():
p=argparse.ArgumentParser(description=__doc__)
p.add_argument('--verified',action='store_true');p.add_argument('--apply',action='store_true')
p.add_argument('--review',type=Path);p.add_argument('--review-sha256')
a=p.parse_args();assert not a.apply or a.verified,'--apply requires verified evidence'
c=load(HERE/'config.json');r=Path(c['root']);f=Path(c['frozen_root']);b=Path(c['build']);s=Path(c['suite_directory']);ne=Path(c['normal_evidence']);pe=Path(c['package_evidence']);se=Path(c['packed_evidence'])
docs={n:HERE/'docs-baseline'/n for n in ['README.md','docs/current-status.md','docs/playtest-build.md']}
assert all((r/n).read_bytes()==q.read_bytes() for n,q in docs.items()),'Documentation changed: explicitly rebase/review scratch; never overwrite concurrent edits'
frozen=load(s/'frozen-source.json');suite=None;normal=None;packed=None;handoff=None
checks={'docs_before':{n:sha(q) for n,q in docs.items()},'frozen_source_sha256':sha(s/'frozen-source.json'),'source_count':len(frozen),'qualification_source_root':str(f),'live_source_match_not_claimed':True}
if a.verified:
assert a.review and a.review.is_file() and a.review_sha256==sha(a.review),'Require exact parent-approved independent final review'
assert load(a.review).get('complete') is True, 'Independent final review is incomplete'
checks['independent_review']={'path':str(a.review),'sha256':sha(a.review)}
sys.path.insert(0,str(f/'tools'));from source_manifest import addon_manifest
assert addon_manifest(f)==frozen==load(f/'frozen-source.json')
suite=load(s/'suite-result.json');inputs=load(s/'suite-inputs.json')
tree=ast.parse((f/'tools/check.py').read_text());registered=[n.value for n in ast.walk(tree) if isinstance(n,ast.Constant) and isinstance(n.value,str) and n.value.endswith('.py') and (n.value.split('/')[-1].startswith('test_') or n.value.endswith('_regression.py'))]
expected={'tests/'+Path(n).name for n in registered}
assert len(expected)==len(registered)
assert suite['exit']==0 and suite['inputs_unchanged'] and not suite.get('resumed')
assert suite['regression_programs']==len(registered)==len(suite['programs'])
assert {x['path'] for x in suite['programs']}==expected and all(x['exit']==0 for x in suite['programs'])
assert all(inputs.get(n)==h for n,h in frozen.items())
from suite_binding import verify_suite_binding
checks['suite_reuse_binding']=verify_suite_binding(f,s,frozen)
assert 'All repository checks passed.' in (s/'full-suite.log').read_text()
normal=load(ne/'report.json');nr=load(ne/'runner.json.txt')
assert load(ne/'source-sha256.json')==frozen==load(ne/'launch-source-sha256.json')
assert normal['smoke_completions']==1 and not normal['script_or_runtime_failures']
assert nr['cleanup_confirmed'] and nr['source_unchanged_after_run'] and nr['external_addons_unchanged_after_run']
assert sha(ne/'console.log.txt')==nr['console_sha256']
checks['evidence_hashes']={str(q):sha(q) for q in [s/'suite-result.json',s/'suite-inputs.json',s/'full-suite.log',ne/'report.json',ne/'runner.json.txt',ne/'console.log.txt']}
if True:
from source_bundle import inventory as source_inventory
from packed_external import inventory as runtime_inventory
handoff=load(b/'handoff.json');assert handoff==load(pe/'handoff.json')
assert handoff['qualification_source_root']==str(f) and handoff['authored_files']==len(frozen)
assert handoff['repository_regression_programs']==len(registered) and handoff['normal_mission_ready'] and handoff['local_participant_verified']
assert not handoff['release_qualified'] and not handoff['published']
assert load(pe/'authored-before.json')==frozen==source_inventory(b/'source')
assert runtime_inventory(b/'packages')==handoff['runtime_files']
assert sha(b/'source.zip')==handoff['source_zip_sha256']
packed=load(se/'packed-startup-report.json');pr=load(se/'packed-runner.json');manifest=load(se/'packed-input-provenance.json');ar=load(se/'archive-review.json')
assert packed['normal_mission_ready'] and packed['local_participant_verified'] and not packed['script_or_runtime_failures']
assert pr['cleanup_confirmed'] and pr['packed_inputs_unchanged_after_run'] and pr['packed_external_inputs_unchanged_after_run']
assert sha(se/'console.log.txt')==pr['console_sha256']
assert sha(se/'packed-input-provenance.json')==pr['packed_input_provenance_sha256']
assert manifest['artifacts']==handoff['runtime_files'] and manifest['launch_id']==pr['packed_launch_id']
assert ar['raw_console_sha256_verified'] and ar['strict_failure_retained']
assert len(packed['engine_errors'])==handoff['packed_resource_errors']
checks['evidence_hashes'].update({str(q):sha(q) for q in [b/'handoff.json',pe/'package-report.json',se/'packed-startup-report.json',se/'packed-runner.json',se/'archive-review.json']})
assert (b/'README.md').read_text()==ASSEMBLED_README,'Candidate README changed; review before overwrite'
count=suite['regression_programs'] if suite else 'pending'
inclusion='This snapshot adds event-time capture cancellation for original active hunter vehicles, the current inherited terrain presentation, and paired radio interception by two original convoy escorts. Both real order receipts precede detours; finite forces, crew identities, stock and fixed deadlines are preserved. Earlier convoy-survivor, radio interruption and finite-transfer corrections remain included.'
limits='This is an **unqualified development candidate**. Native survivor radio delivery and physical retasking remain unverified, as do physical resupply/interception, complete human escape, real multiplayer/JIP/reconnect/twelve-player play, manual UI behavior, comparative FPS and a clean release. Qualification binds this frozen snapshot; later live edits are excluded. Earlier packages and original missions remain preserved.'
if a.verified:
validation=f"The unchanged authored source, tests and tools reuse the completed **{count}-program regression pass**; four later prose-only documentation updates are separately reviewed. The unchanged-source archived normal Everon route completes **{normal['assertions_passed']} assertions and {normal['smoke_completions']} round**, with zero script/runtime failures and **{len(normal['engine_errors'])} retained engine errors**. Ordinary startup of the exact new runtime bytes verifies the normal mission and local prisoner, with zero script/runtime failures and **{len(packed['engine_errors'])} retained engine errors**. Strict packaging/startup failures remain recorded."
counts=f"**{len(frozen)} authored files**, **{handoff['pak_payload_files']} exact PAK payloads** and **{len(handoff['runtime_files'])} runtime files** match the editable source and handoff manifest."
else:
validation='Verification is pending; this preview claims no new full-suite or packaged-startup result.'
counts=f'{len(frozen)} frozen authored files; package/runtime counts pending evidence.'
title='**3 October 2026 — mounted-pair development handoff:** [package and editable source](../.build/playtest-2026-10-03-mounted-pair/README.md).'
section='\n\n'.join([title,counts,inclusion,validation,limits])
status=docs['docs/current-status.md'].read_text();first,tail=status.split('\n',1)
proposed={'docs/current-status.md':first+'\n\n'+section+'\n\n**Earlier source and package checkpoints (historical):**\n\n'+tail.lstrip('\n')}
guide=docs['docs/playtest-build.md'].read_text();first,tail=guide.split('\n',1)
previous='**2 October 2026 — convoy-survivors development handoff:**'
assert tail.lstrip().startswith(previous),'Unexpected guide latest section; rebase manually'
proposed['docs/playtest-build.md']=first+'\n\n'+section+'\n\n## Previous convoy-survivors handoff (historical)\n\n'+tail.lstrip('\n')
readme=docs['README.md'].read_text();paragraphs=[x for x in readme.split('\n\n') if x.startswith('The [local development playtest handoff]')];assert len(paragraphs)==1
pointer='The [local development playtest handoff](.build/playtest-2026-10-03-mounted-pair/README.md) contains the 3 October mounted-pair snapshot: one combined addon package and matching editable source with the authorized RHS/WCS/BMP dependency closure. '+validation+' '+limits+' See [current status](docs/current-status.md) for retained earlier evidence.'
proposed['README.md']=readme.replace(paragraphs[0],pointer,1)
candidate='# Mounted-pair development candidate — 3 October 2026\n\n'+'\n\n'.join([counts,inclusion,validation,limits])+'\n\nOpen `source/addons/core/addon.gproj` with separately installed RHS, WCS, BMP and Parachute dependencies, then select `Missions/ERR_Everon.conf`. Runtime files are in `packages/core/`; matching editable source is in `source/` and `source.zip`. For ordinary play, omit smoke/input/flight fixture flags. See [handoff manifest](handoff.json), [player route](../../docs/player-route.md) and [build guide](../../docs/playtest-build.md). Nothing is published or release-qualified.\n'
proposed['candidate-README.md']=candidate
out=HERE/'proposed-docs';out.mkdir(exist_ok=True)
for n,content in proposed.items():
q=out/n;q.parent.mkdir(parents=True,exist_ok=True);q.write_text(content)
destinations={n:r/n for n in docs};destinations['candidate-README.md']=b/'README.md'
result={'state':'verified proposal' if a.verified else 'pending preview','checks':checks,'suite_programs':count,'proposed_sha256':{n:sha(out/n) for n in proposed},'destinations':{n:str(q) for n,q in destinations.items()},'target_writes':a.apply,'preservation_review_scope':'Independent review owns original/prior-package/index checks; finalizer modifies only these four documents.'}
(HERE/'docs-proposal.json').write_text(json.dumps(result,indent=2)+'\n')
if a.apply:
assert all((r/n).read_bytes()==q.read_bytes() for n,q in docs.items()),'Docs changed during validation'
assert (b/'README.md').read_text()==ASSEMBLED_README,'Candidate README changed during validation'
for n,dest in destinations.items():dest.write_bytes((out/n).read_bytes())
(HERE/'docs-after.json').write_text(json.dumps({str(q):sha(q) for q in destinations.values()},indent=2)+'\n')
print(json.dumps({'verified':a.verified,'applied':a.apply,'proposal':str(out),'suite_programs':count,'documents':list(proposed)},indent=2))
if __name__=='__main__':main()