Files
EscapistsReintroduced/docs/evidence/playtest-refresh-2026-10-03-mine-safety/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
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/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(f/'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(f/'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 engineer mine flanks with at least 15 m clearance from nearby road centerlines and more than 200 m from named settlements. Mine dispatch also respects the group’s current native movement envelope before starting and throughout the job. Original items, fixed deadlines and cancellation quarantine remain intact. Earlier paired interception, finite supply and player-recovery changes remain included.'
limits='This is an **unqualified development candidate**. Native mine placement, arming and detonation, physical resupply/interception and survivor retasking remain unverified, as do complete human escape, real multiplayer/JIP/reconnect/twelve-player play, manual UI behavior, comparative FPS and a clean release. An intermittent zero-radius engine diagnostic remains unresolved; the opt-in trace preserves native behavior and is not a fix or proof of the caller. 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**; {len(checks['suite_reuse_binding']['documentation_differences'])} later documentation-only differences 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 — mine-safety development handoff:** [package and editable source](../.build/playtest-2026-10-03-mine-safety/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='**3 October 2026 — mounted-pair 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 mounted-pair 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-mine-safety/README.md) contains the 3 October mine-safety 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='# Mine-safety 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()