Include the current addon, terrain integrations, tools, regression tests and recorded development evidence.
97 lines
11 KiB
Python
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(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 finite engineer reuse at genuinely newer radio-delivered road posts: four consumed attempts per original force and thirty-two per mission, with every new post more than 160 m from consumed posts. Original stock, native movement envelopes, fixed deadlines and unresolved-removal quarantine remain intact. Ordinary small-arms supply now refuses trucks lacking compatible nonempty original magazines before spending a report or claiming forces. Earlier mine-flank safety, paired interception and player-recovery changes remain included.'
|
|
limits='This is an **unqualified development candidate**. Native repeated mining and route avoidance, mine placement/arming/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 — ground-supply development handoff:** [package and editable source](../.build/playtest-2026-10-03-ground-supply/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 — mine-safety 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 mine-safety 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-ground-supply/README.md) contains the 3 October ground-supply 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='# Ground-supply 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()
|