From 634f5f88bec711aae4d678c0b992dc5af0826419 Mon Sep 17 00:00:00 2001 From: firestar5683 <168790843+firestar5683@users.noreply.github.com> Date: Sat, 19 Sep 2026 13:48:20 -0700 Subject: [PATCH] Resolve conservative normal presentation without altering frozen cohorts --- roadscore/prototype/MUSICAL_PRESENTATION.md | 34 ++++++++++++++ roadscore/prototype/app.py | 5 ++- roadscore/prototype/presentation_policy.py | 45 +++++++++++++++++++ roadscore/prototype/runtime_manifest.py | 5 ++- .../prototype/test_presentation_policy.py | 34 ++++++++++++++ .../tools/presentation_conservative_v1.json | 2 +- 6 files changed, 120 insertions(+), 5 deletions(-) create mode 100644 roadscore/prototype/presentation_policy.py create mode 100644 roadscore/prototype/test_presentation_policy.py diff --git a/roadscore/prototype/MUSICAL_PRESENTATION.md b/roadscore/prototype/MUSICAL_PRESENTATION.md index 5b68b9b2bf..4d4cb2fc43 100644 --- a/roadscore/prototype/MUSICAL_PRESENTATION.md +++ b/roadscore/prototype/MUSICAL_PRESENTATION.md @@ -102,3 +102,37 @@ expires its indicator. Engagement exposes `rendered_open_mix` and `rendered_state` (`open`, `transition`, `contained`) after actual processing, plus `rendered_block_end_seconds`. Display it only when enabled, current and actually applied; `active` is input provenance, not proof the ramp has finished. + +## Normal-launch policy resolver + +`presentation_policy.select_launch(...)` is the launcher integration hook. +Fresh normal ACE Prism resolves to gold-core + conservative-v1 automatically. +An explicit `policy='off'` retains raw gold-core; explicit `render_mode='current'` +selects the legacy rendering with new presentation layers off. Stored playback +resolves to current/off and rejects remix flags. Official judging resolves to +current/frozen, retaining its frozen runtime config; adopting another policy +requires a separately bound versioned cohort, not an inherited normal default. + +The launcher must export/forward `ROADSCORE_PRESENTATION_POLICY` from this result +alongside `ROADSCORE_RENDER_MODE`; do not inherit stale environment values. +`effective_config` overlays only presentation keys in memory. It never changes +the global runtime file, seeds, generation policy, profiles or composition. +The runtime manifest records the effective configuration and policy. Absence of +the environment selector preserves frozen behavior for existing internal callers. +Launcher/CLI ownership remains with the composition integration owner. + +## Approved-run procedure after software/plan release + +Current event operating point is100W; no new power investigation gate or sweep. +The sole hardware owner first confirms idle/offroad ownership and preserves +current source/config/archive indices. Stage only the reviewed combined source, +verify actual100W readback and matchingTC_OPT2, weights and prepared plan hashes, +then use the normal one-command route path with a newly persisted session seed. +No special cue timestamps or route-specific settings. Keep output muted unless +separately authorized for attended audio. Capture actual render-mode/policy, +firstaccepted/ready timing, perjob generation/decodeRTF, link health, minbuffer, +underflows/holds, actual rendered cue frames and engagement freshness/mix. +Save exact dry/heard audio, seed/conditioning manifest, source hashes and normal +UI recording; verify causal input times and archive synchronization. Preserve +fault evidence and stop if a fault occurs; no automatic resets/power sweep. +Hardware stays idle until the root releases the reviewed combined plan. diff --git a/roadscore/prototype/app.py b/roadscore/prototype/app.py index 96f7ad8c4d..d2b321beb0 100644 --- a/roadscore/prototype/app.py +++ b/roadscore/prototype/app.py @@ -12,6 +12,7 @@ from phrase import pulse,cadence_runway,mix_cadence from driving_music import DrivingDSP from event_music import EventDSP from input_clock import InputClock +from presentation_policy import effective_config,selected as presentation_policy_selected from engagement_presentation import EngagementPresentation,PresentationConfig,engagement_active from signal_shaker import SignalShaker,assess_grid,profile_tempo_prior from core_apex import CoreApex @@ -51,7 +52,7 @@ from ace_profiles import selected,PROFILES ace_profile=selected() if composer=='ace': from ending_policy import safe_ending_gesture as ending_gesture -config=configuration();validate_render_mode(render_mode,composer,config.get('song_form_experimental',False));identity=config.get('identity','legacy');identity=identity if identity in styles else 'legacy' +config=effective_config(configuration());validate_render_mode(render_mode,composer,config.get('song_form_experimental',False));identity=config.get('identity','legacy');identity=identity if identity in styles else 'legacy' rolling_mode=config.get('rolling',False);rolling_anchors={k:anchor_options(root,k) for k in styles if (root/f'assets/source_{k}.wav').exists()} if rolling_mode and composer!='ace' else {} drive_events=config.get('drive_events',False) or config.get('event_music',False);phrase_runway=config.get('phrase_runway',False) presentation_config=PresentationConfig.read(config.get('engagement_presentation')) @@ -344,7 +345,7 @@ try: req.update(composer='ace',profile=ace_profile,buffer_seconds=buffered,playback_deadline_monotonic=time.monotonic()+buffered) with (run/'jobs.jsonl').open('a') as audit:audit.write(json.dumps(req)+'\n') f=root/'generated/request.tmp';f.write_text(json.dumps(req));f.replace(root/'generated/request.json');inflight=True;budget_waiting=False;job_started=time.monotonic();last_requested_identity=identity - snapshot={'composer':composer,'render_mode':render_mode,'readiness':'DEGRADED' if worker_failed or quality_failures or holding else 'READY','profile':ace_profile if composer=='ace' else None,'safe_extensions':len(safe_extensions),'holding_accepted_music':holding,'quality_failures':quality_failures,'style':PROFILES[ace_profile]['name'] if composer=='ace' else styles.get(identity,{}).get('name',identity),'section':'OUTRO' if ending_start is not None else 'CONTINUATION','identity':identity,'playing_identity':playing_identity,'musical_mode':musical_mode,'route':clock['route'],'route_t':now,'elapsed':frames/rate,'kind':state.get('kind','curve'),'phase':state['phase'],'amount':state['amount'],'lead':state['lead'],'activation':state['activation'],'predicted_peak':state['predicted_peak'],'strength':state['strength'],'predicted_turn_radians':state.get('predicted_turn_radians'),'detector':state.get('detector'),'qualified_since':state.get('qualified_since'),'command_wall':time.monotonic(),'speed':speed,'steering':float(sm['carState'].steeringAngleDeg),'model_age':(sm.logMonoTime['modelV2']-m.timestampEof)/1e9,'source_cutoff_ns':available_ns,'model_mono_ns':sm.logMonoTime['modelV2'],'buffered':buffered,'fallbacks':fallbacks,'underflows':underflows,'job_inflight':inflight,'generation_elapsed_seconds':max(0.,time.monotonic()-job_started) if inflight else None,'worker_failed':worker_failed,'completed_jobs':sum(not j.get('error') and not j.get('quality_rejected') for j in generation),'nav':nav,'nav_revision':nav_revision,'discarded_jobs':len(discarded_jobs),'arrival_at':arrival_at,'replay_late':clock['late']} + snapshot={'composer':composer,'render_mode':render_mode,'presentation_policy':presentation_policy_selected(),'readiness':'DEGRADED' if worker_failed or quality_failures or holding else 'READY','profile':ace_profile if composer=='ace' else None,'safe_extensions':len(safe_extensions),'holding_accepted_music':holding,'quality_failures':quality_failures,'style':PROFILES[ace_profile]['name'] if composer=='ace' else styles.get(identity,{}).get('name',identity),'section':'OUTRO' if ending_start is not None else 'CONTINUATION','identity':identity,'playing_identity':playing_identity,'musical_mode':musical_mode,'route':clock['route'],'route_t':now,'elapsed':frames/rate,'kind':state.get('kind','curve'),'phase':state['phase'],'amount':state['amount'],'lead':state['lead'],'activation':state['activation'],'predicted_peak':state['predicted_peak'],'strength':state['strength'],'predicted_turn_radians':state.get('predicted_turn_radians'),'detector':state.get('detector'),'qualified_since':state.get('qualified_since'),'command_wall':time.monotonic(),'speed':speed,'steering':float(sm['carState'].steeringAngleDeg),'model_age':(sm.logMonoTime['modelV2']-m.timestampEof)/1e9,'source_cutoff_ns':available_ns,'model_mono_ns':sm.logMonoTime['modelV2'],'buffered':buffered,'fallbacks':fallbacks,'underflows':underflows,'job_inflight':inflight,'generation_elapsed_seconds':max(0.,time.monotonic()-job_started) if inflight else None,'worker_failed':worker_failed,'completed_jobs':sum(not j.get('error') and not j.get('quality_rejected') for j in generation),'nav':nav,'nav_revision':nav_revision,'discarded_jobs':len(discarded_jobs),'arrival_at':arrival_at,'replay_late':clock['late']} if presentation is not None: engagement_on,engagement_fresh=engagement_active(engagement[1],engagement[0],engagement[2],engagement[4],engagement[3],time.monotonic()) snapshot.update(presentation.snapshot(presentation_config,engagement_on,engagement_fresh)) diff --git a/roadscore/prototype/presentation_policy.py b/roadscore/prototype/presentation_policy.py new file mode 100644 index 0000000000..66a4b36711 --- /dev/null +++ b/roadscore/prototype/presentation_policy.py @@ -0,0 +1,45 @@ +"""Generic launch presentation policy; never changes composer, seeds or route data.""" +import copy +import os + +POLICIES = ('conservative-v1', 'off', 'frozen') +CONSERVATIVE = { + 'presentation_policy_version': 'conservative-v1', + 'signal_shaker': {'enabled': True}, + 'core_apex': {'enabled': True}, + 'engagement_presentation': {'version': 2, 'enabled': True, 'attack_ms': 220, 'release_ms': 650}, +} + +def select_launch(composer, profile, replay=False, judging=False, render_mode=None, policy=None): + if policy is not None and policy not in POLICIES:raise ValueError('Unknown presentation policy') + if render_mode is not None and render_mode not in ('current','gold-core'):raise ValueError('Unknown rendering mode') + if replay: + if render_mode not in (None,'current') or policy not in (None,'off'): + raise ValueError('Stored playback retains recorded presentation; it cannot be remixed by launch flags') + return {'render_mode':'current','policy':'off'} + if judging: + # Existing official cohorts retain the actual frozen files/configuration. A new + # cohort needs explicit runner/schema binding before adopting a new policy. + if policy not in (None,'frozen') or render_mode not in (None,'current'): + raise ValueError('Judging presentation must remain bound to its frozen configuration') + return {'render_mode':'current','policy':'frozen'} + normal_prism=composer=='ace' and profile=='prism' + mode=render_mode or ('gold-core' if normal_prism else 'current') + chosen=policy or ('conservative-v1' if normal_prism and mode=='gold-core' else 'off') + if chosen=='conservative-v1' and (composer!='ace' or mode!='gold-core'): + raise ValueError('Conservative presentation requires ACE gold-core rendering') + return {'render_mode':mode,'policy':chosen} + +def selected(environ=None): + value=(os.environ if environ is None else environ).get('ROADSCORE_PRESENTATION_POLICY','frozen') + if value not in POLICIES:raise ValueError('Unknown presentation policy: '+value) + return value + +def effective_config(config,environ=None): + """Return a copy; never mutate the global runtime file or an archived policy.""" + result=copy.deepcopy(config);policy=selected(environ) + if policy=='frozen':return result + if policy=='conservative-v1':result.update(copy.deepcopy(CONSERVATIVE)) + else: + result.update(presentation_policy_version='off',signal_shaker={'enabled':False},core_apex={'enabled':False},engagement_presentation={'version':2,'enabled':False}) + return result diff --git a/roadscore/prototype/runtime_manifest.py b/roadscore/prototype/runtime_manifest.py index 80094df90b..2967f9752f 100644 --- a/roadscore/prototype/runtime_manifest.py +++ b/roadscore/prototype/runtime_manifest.py @@ -1,11 +1,12 @@ """Implementation provenance only; no route/model-content reads.""" import hashlib,json,subprocess from render_policy import selected as render_mode_selected +from presentation_policy import effective_config,selected as presentation_policy_selected from pathlib import Path from composer_choice import choice,NAMES from ace_profiles import selected -root=Path('/data/roadscore');files=[root/'prototype'/name for name in ['app.py','engagement_presentation.py','signal_shaker.py','core_apex.py','render_policy.py','worker.py','core.py','musical.py','rolling.py','event_music.py','render_clock.py','song_form.py','section_bank.py','bar_grid.py','audio_policy.py','musical_gestures.py','gesture_bank.py','composition_policy.py','graph_cache.py']]+[Path('/data/sa3-feasibility/native_sa3.py')] -result={'render_mode':render_mode_selected(),'backend':NAMES[choice()],'composer':choice(),'implementation_sha256':{str(p):hashlib.sha256(p.read_bytes()).hexdigest() for p in files if p.exists()},'runtime':json.loads((root/'runtime.json').read_text()),'weight_hash':'not collected in this integration pass'} +root=Path('/data/roadscore');files=[root/'prototype'/name for name in ['app.py','engagement_presentation.py','signal_shaker.py','core_apex.py','presentation_policy.py','render_policy.py','worker.py','core.py','musical.py','rolling.py','event_music.py','render_clock.py','song_form.py','section_bank.py','bar_grid.py','audio_policy.py','musical_gestures.py','gesture_bank.py','composition_policy.py','graph_cache.py']]+[Path('/data/sa3-feasibility/native_sa3.py')] +result={'presentation_policy':presentation_policy_selected(),'render_mode':render_mode_selected(),'backend':NAMES[choice()],'composer':choice(),'implementation_sha256':{str(p):hashlib.sha256(p.read_bytes()).hexdigest() for p in files if p.exists()},'runtime':effective_config(json.loads((root/'runtime.json').read_text())),'weight_hash':'not collected in this integration pass'} source=root/('assets/source_'+result['runtime'].get('identity','legacy')+'.wav') if choice()=='ace': source=root/'generated/ace_initial.wav' diff --git a/roadscore/prototype/test_presentation_policy.py b/roadscore/prototype/test_presentation_policy.py new file mode 100644 index 0000000000..71a4a2f49e --- /dev/null +++ b/roadscore/prototype/test_presentation_policy.py @@ -0,0 +1,34 @@ +import unittest,json +from pathlib import Path +from presentation_policy import select_launch,effective_config,CONSERVATIVE + +class PolicyTests(unittest.TestCase): + def test_inspectable_fragment_matches_runtime_defaults(self): + fragment=Path(__file__).resolve().parents[1]/'tools/presentation_conservative_v1.json' + self.assertEqual(json.loads(fragment.read_text()),CONSERVATIVE) + def test_normal_prism_gets_integrated_policy_without_extra_flags(self): + self.assertEqual(select_launch('ace','prism'),{'render_mode':'gold-core','policy':'conservative-v1'}) + def test_explicit_optouts(self): + self.assertEqual(select_launch('ace','prism',policy='off'),{'render_mode':'gold-core','policy':'off'}) + self.assertEqual(select_launch('ace','prism',render_mode='current'),{'render_mode':'current','policy':'off'}) + def test_stored_and_judging_do_not_inherit_demo_defaults(self): + self.assertEqual(select_launch('ace','prism',replay=True),{'render_mode':'current','policy':'off'}) + self.assertEqual(select_launch('ace','prism',judging=True),{'render_mode':'current','policy':'frozen'}) + with self.assertRaises(ValueError):select_launch('ace','prism',judging=True,policy='conservative-v1') + with self.assertRaises(ValueError):select_launch('ace','prism',replay=True,render_mode='gold-core') + def test_effective_config_does_not_change_generation_or_input(self): + original={'composition_control':True,'rolling':True,'identity':'kpop_control','custom':{'seed':123}} + out=effective_config(original,{'ROADSCORE_PRESENTATION_POLICY':'conservative-v1'}) + for key,value in original.items():self.assertEqual(out[key],value) + self.assertTrue(out['engagement_presentation']['enabled']);self.assertNotIn('signal_shaker',original) + out['custom']['seed']=9;self.assertEqual(original['custom']['seed'],123) + def test_frozen_missing_env_and_off_explicit(self): + original={'signal_shaker':{'enabled':True},'engagement_presentation':{'enabled':True,'version':2}} + self.assertEqual(effective_config(original,{}),original) + off=effective_config(original,{'ROADSCORE_PRESENTATION_POLICY':'off'}) + self.assertFalse(off['signal_shaker']['enabled']);self.assertFalse(off['engagement_presentation']['enabled']) + def test_other_backend_and_legacy_incompatibility(self): + self.assertEqual(select_launch('sa3','prism'),{'render_mode':'current','policy':'off'}) + with self.assertRaises(ValueError):select_launch('ace','prism',render_mode='current',policy='conservative-v1') + with self.assertRaises(ValueError):effective_config({}, {'ROADSCORE_PRESENTATION_POLICY':'typo'}) +if __name__=='__main__':unittest.main() diff --git a/roadscore/tools/presentation_conservative_v1.json b/roadscore/tools/presentation_conservative_v1.json index 907d9bf1ab..0acf0a1118 100644 --- a/roadscore/tools/presentation_conservative_v1.json +++ b/roadscore/tools/presentation_conservative_v1.json @@ -1,5 +1,5 @@ { - "presentation_policy_version": "conservative-v1-review-candidate", + "presentation_policy_version": "conservative-v1", "signal_shaker": {"enabled": true}, "core_apex": {"enabled": true}, "engagement_presentation": {"version": 2, "enabled": true, "attack_ms": 220, "release_ms": 650}