deadline:raise TimeoutError('marker_deadline') + time.sleep(.05) + records=[json.loads((root/(name+'.json')).read_text()) for name in ('main','detached-child')] + before=show(unit);write(root/'before-private.json',before) + before_members=members(before['ControlGroup']);write(root/'before-members-private.json',before_members) + checks['native_main_identity_matches']=int(before['MainPID'])==records[0]['pid'] + checks['child_has_distinct_session']=records[1]['sid']==records[1]['pid'] and records[1]['sid']!=records[0]['sid'] + checks['both_in_owned_service_cgroup']=all(r['pid'] in before_members and before['ControlGroup'] in r['cgroup'] for r in records) + checks['term_ignored_by_fixture']=all(r['ignores_term'] for r in records) + if not all(checks.values()):raise RuntimeError('detached_fixture_preconditions_failed') + write(root/'main-kill-private.json',kill_main(unit)) + process.wait(timeout=20);wait_empty(before['ControlGroup']) + after=show(unit);write(root/'after-private.json',after) + checks['main_native_sigkill_recorded']=after['ExecMainCode']=='2' and after['ExecMainStatus']=='9' + checks['all_original_identities_stopped']=not any(same_alive(r) for r in records) + checks['owned_cgroup_empty']=members(before['ControlGroup'])==[] + checks['no_native_restart']=after['NRestarts']=='0' + except Exception as exc:failure={'type':type(exc).__name__,'reason':str(exc)} + finally: + cleanup_result=cleanup(unit) + if process.poll() is None:process.wait(timeout=10) + out.close();err.close() + result={'status':'passed' if failure is None and all(checks.values()) else 'failed','kind':'native_cli_deterministic_containment','model_calls':0,'checks':checks,'failure':failure,'native_launcher_exit':process.returncode,'elapsed_seconds':round(time.monotonic()-started,3),'cleanup':cleanup_result,'source_sha256':hashlib.sha256(Path(__file__).read_bytes()).hexdigest()} + write(root/'result-private.json',result) + print(json.dumps({'status':result['status'],'checks':checks,'model_calls':0},indent=2)) + return 0 if result['status']=='passed' else 1 + + +if __name__=='__main__': + p=argparse.ArgumentParser(description=__doc__);p.add_argument('--run-dir');p.add_argument('--fixture');a=p.parse_args() + if a.fixture:fixture(Path(a.fixture)) + elif a.run_dir:raise SystemExit(run(Path(a.run_dir))) + else:p.error('choose --run-dir or --fixture') diff --git a/blueprints/convergence-practice/worker-recovery/control.py b/blueprints/convergence-practice/worker-recovery/control.py new file mode 100644 index 000000000..4565fbfe0 --- /dev/null +++ b/blueprints/convergence-practice/worker-recovery/control.py @@ -0,0 +1,44 @@ +"""Read-only parent observations; no checkpoint or final effect writes.""" +import json +from pathlib import Path +import sys +import time + +ROOT = Path(__file__).resolve().parent + + +def alive(marker): + try: + fields=Path('/proc/'+str(marker['pid'])+'/stat').read_text().rsplit(')',1)[1].split() + return fields[0]!='Z' and fields[19]==marker['start_ticks'] + except (FileNotFoundError, ProcessLookupError): + return False + + +def main(action): + deadline=time.monotonic()+120 + if action=='await-cancel-wait': + while not (ROOT/'cancel-wait.json').exists(): + if time.monotonic()>deadline: raise TimeoutError('cancel_wait_not_ready') + time.sleep(.1) + assert alive(json.loads((ROOT/'cancel-wait.json').read_text())) + elif action=='verify-cancelled': + marker=json.loads((ROOT/'cancel-wait.json').read_text()) + while alive(marker): + if time.monotonic()>deadline: raise TimeoutError('cancelled_wait_still_alive') + time.sleep(.1) + assert [json.loads(x)['action'] for x in (ROOT/'actions.jsonl').read_text().splitlines()]==['checkpoint','cancel-wait'] + elif action=='await-crash-wait': + while not (ROOT/'crash-wait.json').exists(): + if time.monotonic()>deadline: raise TimeoutError('crash_wait_not_ready') + time.sleep(.1) + assert alive(json.loads((ROOT/'crash-wait.json').read_text())) + elif action=='supervisor-hold': + time.sleep(300) + raise TimeoutError('supervisor_did_not_interrupt') + else: + raise ValueError('unknown_control') + print(json.dumps({'action':action,'passed':True})) + + +if __name__=='__main__': main(sys.argv[1]) diff --git a/blueprints/convergence-practice/worker-recovery/executed-runner.py.txt b/blueprints/convergence-practice/worker-recovery/executed-runner.py.txt new file mode 100644 index 000000000..ae7d7a6f9 --- /dev/null +++ b/blueprints/convergence-practice/worker-recovery/executed-runner.py.txt @@ -0,0 +1,151 @@ +#!/usr/bin/env python3 +"""One explicitly authorized native child cancellation/crash/resume trial.""" +import argparse +from datetime import datetime, timezone +import hashlib +import importlib.util +import json +import os +from pathlib import Path +import shutil +import signal +import subprocess +import sys +import time +import uuid + +HERE=Path(__file__).resolve().parent +LEGACY=HERE.parent/'native-recovery/claude' +sys.path.insert(0,str(LEGACY)) +from run import NativeCLI, identity, private_directory +spec=importlib.util.spec_from_file_location('owned_worker_stage',HERE/'stage.py') +fixture=importlib.util.module_from_spec(spec); spec.loader.exec_module(fixture) + + +def write(path,data): + path.write_text(json.dumps(data,indent=2,sort_keys=True)+'\n') + + +def sha(path): return hashlib.sha256(path.read_bytes()).hexdigest() + + +def calls(events): + return [(event,block) for event in list(events) if event.get('type')=='assistant' + for block in event.get('message',{}).get('content',[]) if block.get('type')=='tool_use'] + + +def alive(marker): + current=identity(marker['pid']) + return current is not None and current['state']!='Z' and current['start_ticks']==marker['start_ticks'] + + +def stop_owned_wait(path,workspace): + if not path.is_file():return False + marker=json.loads(path.read_text()) + if not alive(marker):return False + pid=marker['pid'] + command=Path(f'/proc/{pid}/cmdline').read_bytes().split(b'\0') + if b'stage.py' not in command or Path(f'/proc/{pid}/cwd').resolve()!=workspace: + raise RuntimeError('owned_wait_identity_mismatch') + try:os.kill(pid,signal.SIGKILL) + except ProcessLookupError:pass + end=time.monotonic()+5 + while alive(marker) and time.monotonic()deadline:raise TimeoutError('child_crash_wait_deadline') + time.sleep(.05) + # A native SendMessage follows the native TaskStop; retain identities verbatim privately. + native_calls=calls(initial.events) + agent_calls=[b for _,b in native_calls if b['name']=='Agent'] + stops=[b for _,b in native_calls if b['name']=='TaskStop'] + messages=[b for _,b in native_calls if b['name']=='SendMessage'] + if len(agent_calls)!=1 or len(stops)!=1 or len(messages)!=1:raise RuntimeError('native_child_control_sequence_missing') + child_id=messages[0]['input'].get('to') or messages[0]['input'].get('recipient') + if not isinstance(child_id,str) or not child_id:raise RuntimeError('native_child_identity_missing') + checks['one_native_child_spawn']=True + checks['native_taskstop_then_message_observed']=True + checks['cancelled_wait_stopped']=not alive(json.loads((workspace/'cancel-wait.json').read_text())) + checks['child_second_wait_pending']=alive(json.loads((workspace/'crash-wait.json').read_text())) + checks['pre_crash_journal_exact']=fixture.actions(workspace)==['checkpoint','cancel-wait','crash-wait'] + before=(workspace/'checkpoint.json').read_bytes() + if not all(checks.values()) or before!=fixture.EXPECTED:raise RuntimeError('pre_crash_acceptance_failed') + write(root/'pre-crash-private.json',{'child_message_target':child_id,'taskstop_input':stops[0]['input'],'agent_input':agent_calls[0]['input'],'native_cli_pid':initial.proc.pid,'native_cli_identity':identity(initial.proc.pid),'checkpoint_sha256':sha(workspace/'checkpoint.json'),'observed_at_utc':datetime.now(timezone.utc).isoformat()}) + os.killpg(initial.proc.pid,signal.SIGKILL); initial.proc.wait(timeout=10) + cleanup['initial_exit']=initial.proc.returncode; initial.close() + cleanup['crash_wait_additional_cleanup']=stop_owned_wait(workspace/'crash-wait.json',workspace) + checks['owned_runtime_sigkill_exit']=initial.proc.returncode==-signal.SIGKILL + checks['owned_crash_wait_stopped']=not alive(json.loads((workspace/'crash-wait.json').read_text())) + (workspace/'resume-authorized.json').write_text('{}\n') + prompt=f'Resume the SAME native child agent {child_id} using SendMessage only; do not invoke Agent again and do not perform fixture effects yourself. Its runtime was deliberately killed after the unchanged checkpoint and crash-wait. Tell that child: "Continue the same task. Run ONLY python3 stage.py finalize. The supervisor has authorized this final stage. Do not recreate checkpoint or run waits again." Wait for that child to finish and report its result. Native provider/quota/permission errors must be reported without fallback or retry.' + (root/'resume-prompt-private.txt').write_text(prompt) + commands['resumed']=common+['--resume',session];write(root/'commands-private.json',commands) + resumed=NativeCLI(commands['resumed'],prompt,workspace,root,'resumed');clients.append(resumed) + resumed.proc.wait(timeout=args.timeout);resumed.close() + inits=[[e for e in c.events if e.get('type')=='system' and e.get('subtype')=='init'] for c in clients] + checks['same_parent_session']=all(len(x)==1 and x[0].get('session_id')==session for x in inits) + checks['native_model_preserved']=all(len(x)==1 and x[0].get('model')=='claude-opus-5' for x in inits) + follow=calls(resumed.events) + checks['no_replacement_child']=not any(b['name']=='Agent' for _,b in follow) + checks['same_child_message_target']=any(b['name']=='SendMessage' and (b['input'].get('to') or b['input'].get('recipient'))==child_id for _,b in follow) + checks['checkpoint_unchanged']=before==(workspace/'checkpoint.json').read_bytes()==fixture.EXPECTED + checks['single_effect_journal']=fixture.actions(workspace)==fixture.ORDER + checks['final_matches_oracle']=json.loads((workspace/'final.json').read_text())=={'checkpoint_sha256':hashlib.sha256(fixture.EXPECTED).hexdigest(),'execution_count':1,'status':'complete'} + results=[e for e in resumed.events if e.get('type')=='result'] + checks['resumed_native_success']=resumed.proc.returncode==0 and len(results)==1 and results[0].get('is_error') is False + except Exception as exc: + failure={'type':type(exc).__name__,'reason':str(exc)} + finally: + for c in clients: + try: + if not c.out.closed:c.close() + except Exception as exc:cleanup['errors'].append(type(exc).__name__) + for name in ('cancel-wait.json','crash-wait.json'): + try:cleanup[name+'_forced_cleanup']=stop_owned_wait(workspace/name,workspace) + except Exception as exc:cleanup['errors'].append(type(exc).__name__) + checks['owned_cli_processes_stopped']=bool(clients) and all(c.proc.poll() is not None for c in clients) + checks['cleanup_errors_absent']=not cleanup['errors'] + summaries=[] + for c in clients: + terminals=[e for e in c.events if e.get('type')=='result'] + summaries.append({'phase':c.label,'exit_code':c.proc.returncode,'invalid_stream_lines':c.invalid_lines,'terminal_count':len(terminals),'terminal_usage':[e.get('usage') for e in terminals],'model_usage':[e.get('modelUsage') for e in terminals]}) + write(root/'attempt.json',{'status':'passed_pending_independent_audit' if failure is None and all(checks.values()) else 'failed','elapsed_seconds':round(time.monotonic()-start,3),'checks':checks,'cleanup':cleanup,'failure':failure,'native_invocations':summaries,'complete_parent_child_usage':None,'billing':None,'savings_claim':None}) + print(json.dumps({'status':json.loads((root/'attempt.json').read_text())['status'],'checks':checks,'failure':failure},indent=2)) + return 0 if failure is None and all(checks.values()) else 1 + + +if __name__=='__main__': + p=argparse.ArgumentParser(description=__doc__);p.add_argument('--run-dir',required=True);p.add_argument('--claude',default='claude');p.add_argument('--timeout',type=int,default=240) + raise SystemExit(run(p.parse_args())) diff --git a/blueprints/convergence-practice/worker-recovery/executed-systemd-runner.py.txt b/blueprints/convergence-practice/worker-recovery/executed-systemd-runner.py.txt new file mode 100644 index 000000000..2c2a7a0d5 --- /dev/null +++ b/blueprints/convergence-practice/worker-recovery/executed-systemd-runner.py.txt @@ -0,0 +1,198 @@ +#!/usr/bin/env python3 +"""One explicitly authorized native child cancellation/crash/resume trial.""" +import argparse +from datetime import datetime, timezone +import hashlib +import importlib.util +import json +import os +from pathlib import Path +import shutil +import signal +import subprocess +import sys +import time +import uuid + +HERE=Path(__file__).resolve().parent +LEGACY=HERE.parent/'native-recovery/claude' +sys.path.insert(0,str(LEGACY)) +support_spec=importlib.util.spec_from_file_location('claude_recovery_support',LEGACY/'run.py') +support=importlib.util.module_from_spec(support_spec);support_spec.loader.exec_module(support) +NativeCLI,identity,private_directory=support.NativeCLI,support.identity,support.private_directory +spec=importlib.util.spec_from_file_location('owned_worker_stage',HERE/'stage.py') +fixture=importlib.util.module_from_spec(spec); spec.loader.exec_module(fixture) +service_spec=importlib.util.spec_from_file_location('worker_owned_service',HERE/'service.py') +service=importlib.util.module_from_spec(service_spec);service_spec.loader.exec_module(service) + + +def write(path,data): + path.write_text(json.dumps(data,indent=2,sort_keys=True)+'\n') + + +def sha(path): return hashlib.sha256(path.read_bytes()).hexdigest() + + +def calls(events): + return [(event,block) for event in list(events) if event.get('type')=='assistant' + for block in event.get('message',{}).get('content',[]) if block.get('type')=='tool_use'] + + +def alive(marker): + current=identity(marker['pid']) + return current is not None and current['state']!='Z' and current['start_ticks']==marker['start_ticks'] + + +def native_summary(events, session): + """Native background-task delivery can emit multiple init/result messages.""" + inits=[e for e in events if e.get('type')=='system' and e.get('subtype')=='init'] + terminals=[e for e in events if e.get('type')=='result'] + return (bool(inits) and all(e.get('session_id')==session for e in inits), + bool(inits) and all(e.get('model')=='claude-opus-5' for e in inits), + bool(terminals) and all(e.get('subtype')=='success' and e.get('is_error') is False for e in terminals)) + + +def service_ready(unit,client): + deadline=time.monotonic()+15 + while True: + state=service.show(unit) + if int(state.get('MainPID','0'))>0:return state + if client.proc.poll() is not None or time.monotonic()>deadline:raise RuntimeError('owned_service_not_ready') + time.sleep(.05) + + +def stop_owned_wait(path,workspace): + if not path.is_file():return False + marker=json.loads(path.read_text()) + if not alive(marker):return False + pid=marker['pid'] + command=Path(f'/proc/{pid}/cmdline').read_bytes().split(b'\0') + if b'stage.py' not in command or Path(f'/proc/{pid}/cwd').resolve()!=workspace: + raise RuntimeError('owned_wait_identity_mismatch') + try:os.kill(pid,signal.SIGKILL) + except ProcessLookupError:pass + end=time.monotonic()+5 + while alive(marker) and time.monotonic()deadline:raise TimeoutError('child_crash_wait_deadline') + time.sleep(.05) + # A native SendMessage follows the native TaskStop; retain identities verbatim privately. + native_calls=calls(initial.events) + agent_calls=[b for _,b in native_calls if b['name']=='Agent'] + stops=[b for _,b in native_calls if b['name']=='TaskStop'] + messages=[b for _,b in native_calls if b['name']=='SendMessage'] + if len(agent_calls)!=1 or len(stops)!=1 or len(messages)!=1:raise RuntimeError('native_child_control_sequence_missing') + child_id=messages[0]['input'].get('to') or messages[0]['input'].get('recipient') + if not isinstance(child_id,str) or not child_id:raise RuntimeError('native_child_identity_missing') + checks['one_native_child_spawn']=True + checks['native_taskstop_then_message_observed']=True + checks['cancelled_wait_stopped']=not alive(json.loads((workspace/'cancel-wait.json').read_text())) + checks['child_second_wait_pending']=alive(json.loads((workspace/'crash-wait.json').read_text())) + checks['pre_crash_journal_exact']=fixture.actions(workspace)==['checkpoint','cancel-wait','crash-wait'] + before=(workspace/'checkpoint.json').read_bytes() + if not all(checks.values()) or before!=fixture.EXPECTED:raise RuntimeError('pre_crash_acceptance_failed') + write(root/'pre-crash-private.json',{'child_message_target':child_id,'taskstop_input':stops[0]['input'],'agent_input':agent_calls[0]['input'],'native_cli_pid':initial.proc.pid,'native_cli_identity':identity(initial.proc.pid),'checkpoint_sha256':sha(workspace/'checkpoint.json'),'observed_at_utc':datetime.now(timezone.utc).isoformat()}) + if units: + active=service.show(units['initial']);active_members=service.members(active['ControlGroup']) + marker=json.loads((workspace/'crash-wait.json').read_text()) + checks['actual_child_wait_in_owned_cgroup']=marker['pid'] in active_members + if not checks['actual_child_wait_in_owned_cgroup']:raise RuntimeError('child_wait_outside_owned_service') + write(root/'active-service-private.json',{'properties':active,'members':active_members,'wait_cgroup':Path('/proc/'+str(marker['pid'])+'/cgroup').read_text()}) + write(root/'main-kill-private.json',service.kill_main(units['initial'])) + initial.proc.wait(timeout=20);service.wait_empty(active['ControlGroup']) + stopped=service.show(units['initial']);write(root/'stopped-service-private.json',stopped) + checks['systemd_all_descendants_stopped']=not alive(marker) and service.members(active['ControlGroup'])==[] + if not checks['systemd_all_descendants_stopped']:raise RuntimeError('native_service_containment_failed') + checks['owned_runtime_sigkill_exit']=stopped.get('ExecMainCode')=='2' and stopped.get('ExecMainStatus')=='9' + else: + os.killpg(initial.proc.pid,signal.SIGKILL); initial.proc.wait(timeout=10) + checks['owned_runtime_sigkill_exit']=initial.proc.returncode==-signal.SIGKILL + cleanup['initial_exit']=initial.proc.returncode; initial.close() + cleanup['crash_wait_additional_cleanup']=False if units else stop_owned_wait(workspace/'crash-wait.json',workspace) + checks['owned_crash_wait_stopped']=not alive(json.loads((workspace/'crash-wait.json').read_text())) + (workspace/'resume-authorized.json').write_text('{}\n') + prompt=f'Resume the SAME native child agent {child_id} using SendMessage only; do not invoke Agent again and do not perform fixture effects yourself. Its runtime was deliberately killed after the unchanged checkpoint and crash-wait. Tell that child: "Continue the same task. Run ONLY python3 stage.py finalize. The supervisor has authorized this final stage. Do not recreate checkpoint or run waits again." Wait for that child to finish and report its result. Native provider/quota/permission errors must be reported without fallback or retry.' + (root/'resume-prompt-private.txt').write_text(prompt) + native_resumed=common+['--resume',session] + commands['resumed']=service.service_command(units['resumed'],native_resumed) if units else native_resumed + write(root/'commands-private.json',commands) + resumed=NativeCLI(commands['resumed'],prompt,workspace,root,'resumed');clients.append(resumed) + if units:write(root/'resumed-service-start-private.json',service_ready(units['resumed'],resumed)) + resumed.proc.wait(timeout=args.timeout);resumed.close() + summaries=[native_summary(c.events,session) for c in clients] + checks['same_parent_session']=all(x[0] for x in summaries) + checks['native_model_preserved']=all(x[1] for x in summaries) + follow=calls(resumed.events) + checks['no_replacement_child']=not any(b['name']=='Agent' for _,b in follow) + checks['same_child_message_target']=any(b['name']=='SendMessage' and (b['input'].get('to') or b['input'].get('recipient'))==child_id for _,b in follow) + checks['checkpoint_unchanged']=before==(workspace/'checkpoint.json').read_bytes()==fixture.EXPECTED + checks['single_effect_journal']=fixture.actions(workspace)==fixture.ORDER + checks['final_matches_oracle']=json.loads((workspace/'final.json').read_text())=={'checkpoint_sha256':hashlib.sha256(fixture.EXPECTED).hexdigest(),'execution_count':1,'status':'complete'} + checks['resumed_native_success']=resumed.proc.returncode==0 and summaries[-1][2] + except Exception as exc: + failure={'type':type(exc).__name__,'reason':str(exc)} + finally: + for c in clients: + try: + if not c.out.closed:c.close() + except Exception as exc:cleanup['errors'].append(type(exc).__name__) + for name in ('cancel-wait.json','crash-wait.json'): + try:cleanup[name+'_forced_cleanup']=stop_owned_wait(workspace/name,workspace) + except Exception as exc:cleanup['errors'].append(type(exc).__name__) + if units: + cleanup['owned_services']={} + for phase,unit in units.items(): + try:cleanup['owned_services'][phase]=service.cleanup(unit) + except Exception as exc:cleanup['errors'].append(type(exc).__name__) + checks['owned_cli_processes_stopped']=bool(clients) and all(c.proc.poll() is not None for c in clients) + checks['cleanup_errors_absent']=not cleanup['errors'] + summaries=[] + for c in clients: + terminals=[e for e in c.events if e.get('type')=='result'] + summaries.append({'phase':c.label,'exit_code':c.proc.returncode,'invalid_stream_lines':c.invalid_lines,'terminal_count':len(terminals),'terminal_usage':[e.get('usage') for e in terminals],'model_usage':[e.get('modelUsage') for e in terminals]}) + write(root/'attempt.json',{'status':'passed_pending_independent_audit' if failure is None and all(checks.values()) else 'failed','elapsed_seconds':round(time.monotonic()-start,3),'checks':checks,'cleanup':cleanup,'failure':failure,'native_invocations':summaries,'complete_parent_child_usage':None,'billing':None,'savings_claim':None}) + print(json.dumps({'status':json.loads((root/'attempt.json').read_text())['status'],'checks':checks,'failure':failure},indent=2)) + return 0 if failure is None and all(checks.values()) else 1 + + +if __name__=='__main__': + p=argparse.ArgumentParser(description=__doc__);p.add_argument('--run-dir',required=True);p.add_argument('--claude',default='claude');p.add_argument('--timeout',type=int,default=240) + p.add_argument('--supervision',choices=['process-group','systemd'],default='process-group') + raise SystemExit(run(p.parse_args())) diff --git a/blueprints/convergence-practice/worker-recovery/executed-systemd-service.py.txt b/blueprints/convergence-practice/worker-recovery/executed-systemd-service.py.txt new file mode 100644 index 000000000..bd54b7969 --- /dev/null +++ b/blueprints/convergence-practice/worker-recovery/executed-systemd-service.py.txt @@ -0,0 +1,76 @@ +"""Only uniquely owned transient user services; no persistent configuration.""" +import os +from pathlib import Path +import re +import subprocess +import time + +PROPERTIES='Id,Type,ActiveState,SubState,Result,MainPID,ControlGroup,KillMode,SendSIGKILL,TimeoutStopUSec,Restart,NRestarts,ExecMainCode,ExecMainStatus' + + +def validate_unit(unit): + if re.fullmatch(r'foundation-recovery-[0-9a-f]{12}-(initial|resumed|probe|readiness)',unit) is None: + raise ValueError('only_uniquely_owned_recovery_units_allowed') + return unit + + +def service_command(unit,command,environment_names=None): + validate_unit(unit) + # Some WSL variables (for example PROGRAMFILES(X86)) are not valid systemd + # environment names. Native paths and ordinary variables remain unchanged. + names=sorted((name for name in os.environ if re.fullmatch(r'[A-Za-z_][A-Za-z0-9_]*',name)) + if environment_names is None else environment_names) + if not all(re.fullmatch(r'[A-Za-z_][A-Za-z0-9_]*',name) for name in names): + raise ValueError('invalid_environment_name') + return ['systemd-run','--user','--wait','--pipe','--quiet','--same-dir','--expand-environment=no', + '--unit='+unit,'--property=Type=exec','--property=RuntimeMaxSec=300s', + '--property=TimeoutStopSec=2s','--property=KillMode=control-group', + '--property=SendSIGKILL=yes','--property=Restart=no', + *['--setenv='+name for name in names],*command] + + +def show(unit): + validate_unit(unit) + result=subprocess.run(['systemctl','--user','show',unit+'.service','--property='+PROPERTIES],capture_output=True,text=True,check=True) + return dict(line.split('=',1) for line in result.stdout.splitlines() if '=' in line) + + +def members(group): + if not group:return [] + root=Path('/sys/fs/cgroup') + target=(root/group.lstrip('/')).resolve() + if not target.is_relative_to(root):raise ValueError('invalid_cgroup_path') + if not target.exists():return [] + result=set() + for path in target.rglob('cgroup.procs'): + try:result.update(int(x) for x in path.read_text().split()) + except FileNotFoundError:pass + return sorted(result) + + +def kill_main(unit): + before=show(unit) + if int(before.get('MainPID','0'))<=0 or before.get('KillMode')!='control-group': + raise RuntimeError('owned_main_not_ready') + before_members=members(before['ControlGroup']) + command=['systemctl','--user','kill','--kill-whom=main','--signal=SIGKILL',unit+'.service'] + result=subprocess.run(command,capture_output=True,text=True,check=True) + return {'command':command,'exit_code':result.returncode,'before':before,'before_members':before_members} + + +def wait_empty(group,timeout=15): + deadline=time.monotonic()+timeout + while members(group): + if time.monotonic()>deadline:raise TimeoutError('owned_cgroup_not_empty') + time.sleep(.05) + return [] + + +def cleanup(unit): + current=show(unit) + stop_needed=current.get('ActiveState') in ('active','activating','deactivating') + if stop_needed:subprocess.run(['systemctl','--user','stop',unit+'.service'],capture_output=True,text=True,check=True) + after=show(unit) + remaining=wait_empty(current.get('ControlGroup','')) + subprocess.run(['systemctl','--user','reset-failed',unit+'.service'],capture_output=True,text=True,check=False) + return {'stop_needed':stop_needed,'after':after,'remaining_members':remaining} diff --git a/blueprints/convergence-practice/worker-recovery/executed-systemd-test-oracle.py.txt b/blueprints/convergence-practice/worker-recovery/executed-systemd-test-oracle.py.txt new file mode 100644 index 000000000..7ce9f207b --- /dev/null +++ b/blueprints/convergence-practice/worker-recovery/executed-systemd-test-oracle.py.txt @@ -0,0 +1,117 @@ +"""A repeated or unauthorized effect must fail before a native worker runs.""" +import importlib.util +import hashlib +import json +from pathlib import Path +import tempfile +import unittest + +HERE = Path(__file__).resolve().parents[1] / 'blueprints/convergence-practice/worker-recovery' + + +class WorkerRecoveryFixtureTests(unittest.TestCase): + def setUp(self): + spec = importlib.util.spec_from_file_location('worker_recovery_stage', HERE / 'stage.py') + self.module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(self.module) + temp = tempfile.TemporaryDirectory() + self.addCleanup(temp.cleanup) + self.root = Path(temp.name) + (self.root / 'input.json').write_text('{"records":[{"id":"b","value":7},{"id":"a","value":5}]}') + + def test_checkpoint_is_exact_and_repetition_is_rejected(self): + self.module.execute(self.root, 'checkpoint') + self.assertEqual((self.root / 'checkpoint.json').read_bytes(), b'{"ids":["a","b"],"total":12}\n') + with self.assertRaisesRegex(ValueError, 'order'): + self.module.execute(self.root, 'checkpoint') + + def test_finalize_refuses_missing_interruption_or_supervisor_authorization(self): + self.module.execute(self.root, 'checkpoint') + with self.assertRaisesRegex(ValueError, 'order'): + self.module.execute(self.root, 'finalize') + (self.root / 'actions.jsonl').write_text('\n'.join(json.dumps({'action':x}) for x in ['checkpoint','cancel-wait','crash-wait'])+'\n') + with self.assertRaisesRegex(ValueError, 'authorization'): + self.module.execute(self.root, 'finalize') + + def test_finalize_writes_one_effect_and_keeps_checkpoint(self): + self.module.execute(self.root, 'checkpoint') + before = (self.root / 'checkpoint.json').read_bytes() + (self.root / 'actions.jsonl').write_text('\n'.join(json.dumps({'action':x}) for x in ['checkpoint','cancel-wait','crash-wait'])+'\n') + (self.root / 'resume-authorized.json').write_text('{}') + self.module.execute(self.root, 'finalize') + self.assertEqual((self.root / 'checkpoint.json').read_bytes(), before) + self.assertEqual(json.loads((self.root / 'final.json').read_text())['execution_count'], 1) + with self.assertRaisesRegex(ValueError, 'order'): + self.module.execute(self.root, 'finalize') + + def test_changed_checkpoint_or_input_is_not_accepted(self): + (self.root / 'input.json').write_text('{"records":[]}') + with self.assertRaisesRegex(ValueError, 'oracle'): + self.module.execute(self.root, 'checkpoint') + self.assertFalse((self.root / 'checkpoint.json').exists()) + + def test_changed_checkpoint_cannot_be_finalized(self): + self.module.execute(self.root, 'checkpoint') + (self.root / 'actions.jsonl').write_text('\n'.join(json.dumps({'action':x}) for x in ['checkpoint','cancel-wait','crash-wait'])+'\n') + (self.root / 'resume-authorized.json').write_text('{}') + (self.root / 'checkpoint.json').write_text('changed') + with self.assertRaisesRegex(ValueError, 'checkpoint_changed'): + self.module.execute(self.root, 'finalize') + self.assertFalse((self.root / 'final.json').exists()) + + +class NativeStreamSummaryTests(unittest.TestCase): + def setUp(self): + spec = importlib.util.spec_from_file_location('worker_recovery_runner', HERE / 'run.py') + self.module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(self.module) + + def test_repeated_native_init_and_terminal_events_keep_same_identity(self): + events = [{'type':'system','subtype':'init','session_id':'same','model':'claude-opus-5'}, + {'type':'result','subtype':'success','is_error':False}, + {'type':'system','subtype':'init','session_id':'same','model':'claude-opus-5'}, + {'type':'result','subtype':'success','is_error':False}] + self.assertEqual(self.module.native_summary(events, 'same'), (True, True, True)) + events[-2]['session_id'] = 'different' + self.assertEqual(self.module.native_summary(events, 'same'), (False, True, True)) + events[-1]['is_error'] = True + self.assertEqual(self.module.native_summary(events, 'same'), (False, True, False)) + + def test_missing_native_init_and_terminals_are_unknown(self): + self.assertEqual(self.module.native_summary([], 'same'), (False, False, False)) + + +class PublishedEffectTests(unittest.TestCase): + def test_retained_outputs_satisfy_single_effect_oracle(self): + accepted = HERE / 'accepted' + expected = b'{"ids":["a","b"],"total":12}\n' + self.assertEqual((accepted / 'checkpoint.json').read_bytes(), expected) + self.assertEqual([json.loads(line)['action'] for line in (accepted / 'actions.jsonl').read_text().splitlines()], + ['checkpoint', 'cancel-wait', 'crash-wait', 'finalize']) + self.assertEqual(json.loads((accepted / 'final.json').read_text()), + {'checkpoint_sha256':hashlib.sha256(expected).hexdigest(), 'execution_count':1, 'status':'complete'}) + + +class OwnedServiceCommandTests(unittest.TestCase): + def setUp(self): + spec = importlib.util.spec_from_file_location('owned_service', HERE / 'service.py') + self.module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(self.module) + + def test_service_keeps_native_arguments_and_environment_values_out_of_argv(self): + command = self.module.service_command('foundation-recovery-0123456789ab-initial', + ['claude', '-p', 'literal $text'], ['PATH', 'EXAMPLE_PRIVATE']) + self.assertEqual(command[-3:], ['claude', '-p', 'literal $text']) + self.assertIn('--expand-environment=no', command) + self.assertIn('--setenv=EXAMPLE_PRIVATE', command) + self.assertIn('--property=KillMode=control-group', command) + self.assertIn('--property=Restart=no', command) + + def test_shared_unit_names_are_refused_before_any_process_operation(self): + for name in ['dbus', 'default.target', 'foundation-recovery-../other', '']: + with self.subTest(name=name), self.assertRaises(ValueError): + self.module.validate_unit(name) + + +if __name__ == '__main__': + unittest.main() diff --git a/blueprints/convergence-practice/worker-recovery/executed-test-oracle.py.txt b/blueprints/convergence-practice/worker-recovery/executed-test-oracle.py.txt new file mode 100644 index 000000000..22f6c5a83 --- /dev/null +++ b/blueprints/convergence-practice/worker-recovery/executed-test-oracle.py.txt @@ -0,0 +1,54 @@ +"""A repeated or unauthorized effect must fail before a native worker runs.""" +import importlib.util +import json +from pathlib import Path +import tempfile +import unittest + +HERE = Path(__file__).resolve().parents[1] / 'blueprints/convergence-practice/worker-recovery' + + +class WorkerRecoveryFixtureTests(unittest.TestCase): + def setUp(self): + spec = importlib.util.spec_from_file_location('worker_recovery_stage', HERE / 'stage.py') + self.module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(self.module) + temp = tempfile.TemporaryDirectory() + self.addCleanup(temp.cleanup) + self.root = Path(temp.name) + (self.root / 'input.json').write_text('{"records":[{"id":"b","value":7},{"id":"a","value":5}]}') + + def test_checkpoint_is_exact_and_repetition_is_rejected(self): + self.module.execute(self.root, 'checkpoint') + self.assertEqual((self.root / 'checkpoint.json').read_bytes(), b'{"ids":["a","b"],"total":12}\n') + with self.assertRaisesRegex(ValueError, 'order'): + self.module.execute(self.root, 'checkpoint') + + def test_finalize_refuses_missing_interruption_or_supervisor_authorization(self): + self.module.execute(self.root, 'checkpoint') + with self.assertRaisesRegex(ValueError, 'order'): + self.module.execute(self.root, 'finalize') + (self.root / 'actions.jsonl').write_text('\n'.join(json.dumps({'action':x}) for x in ['checkpoint','cancel-wait','crash-wait'])+'\n') + with self.assertRaisesRegex(ValueError, 'authorization'): + self.module.execute(self.root, 'finalize') + + def test_finalize_writes_one_effect_and_keeps_checkpoint(self): + self.module.execute(self.root, 'checkpoint') + before = (self.root / 'checkpoint.json').read_bytes() + (self.root / 'actions.jsonl').write_text('\n'.join(json.dumps({'action':x}) for x in ['checkpoint','cancel-wait','crash-wait'])+'\n') + (self.root / 'resume-authorized.json').write_text('{}') + self.module.execute(self.root, 'finalize') + self.assertEqual((self.root / 'checkpoint.json').read_bytes(), before) + self.assertEqual(json.loads((self.root / 'final.json').read_text())['execution_count'], 1) + with self.assertRaisesRegex(ValueError, 'order'): + self.module.execute(self.root, 'finalize') + + def test_changed_checkpoint_or_input_is_not_accepted(self): + (self.root / 'input.json').write_text('{"records":[]}') + with self.assertRaisesRegex(ValueError, 'oracle'): + self.module.execute(self.root, 'checkpoint') + self.assertFalse((self.root / 'checkpoint.json').exists()) + + +if __name__ == '__main__': + unittest.main() diff --git a/blueprints/convergence-practice/worker-recovery/freeze.json b/blueprints/convergence-practice/worker-recovery/freeze.json new file mode 100644 index 000000000..1f6c324ab --- /dev/null +++ b/blueprints/convergence-practice/worker-recovery/freeze.json @@ -0,0 +1,12 @@ +{ + "at_utc": "2026-09-20T18:36:25.664495+00:00", + "sha256": { + "control.py": "e25f7758b5d374fea206b3b7936baa99e4ac5abeb9fd8aed2e83f1cae21006a7", + "input.json": "69741926414949ad09864359cb41523db6a94d093d5c44dc822982c8aab3ef2d", + "plan.json": "37dd427636fe5d9eef1dfbd5c9932d0343f2c8729962e9971a716f38bafb0b2e", + "prompt.txt": "a68ee7b3ce1bc73b4393b348d8e267ce34bee1337d2bc43c8b046df8f0e1811c", + "run.py": "7e3f40af6bd4be3996ffbee200e0c9ade2ce4eb142cde8ad8d0636ae28796a35", + "stage.py": "fdadd66e4b137940ee638c8e89747cfbf882241084cccb0a4e09b9c00d927214", + "test_oracle": "2761382a6b638eaa880463c94205404ef92920940868fbb33c5a9641af3176c6" + } +} diff --git a/blueprints/convergence-practice/worker-recovery/independent-audit.json b/blueprints/convergence-practice/worker-recovery/independent-audit.json new file mode 100644 index 000000000..470952e64 --- /dev/null +++ b/blueprints/convergence-practice/worker-recovery/independent-audit.json @@ -0,0 +1,107 @@ +{ + "action_journal": [ + "checkpoint", + "cancel-wait", + "crash-wait", + "finalize" + ], + "checkpoint_sha256": "55bff20c10c5625554ca7b553ecc8ffe0557592135463d331469c208d855167c", + "checkpoint_unchanged": true, + "child_effect_commands": [ + "python3 stage.py checkpoint", + "python3 stage.py cancel-wait", + "python3 stage.py crash-wait", + "python3 stage.py finalize" + ], + "cleanup": { + "crash_descendant_containment": "not_accepted", + "fixture_cwd_processes_remaining": 0, + "original_wait_identities_not_alive": true, + "surviving_owned_wait_required_explicit_identity_checked_SIGKILL": true + }, + "extra_child_command": { + "command": "ls -1 && git status --porcelain", + "denied_or_error": true + }, + "final_sha256": "b00398342db51dd3aa75cff5dd9f7768418af09b9b3b03f799d21093cb0dc238", + "fixture_tracked_changes": [], + "frozen_sources_unchanged": true, + "limitations": [ + "Not native crash descendant containment, independent child-process isolation or remote provider cancellation.", + "No power-loss, independent-host, billing-cessation or distributed exactly-once acceptance.", + "The child attempted an extra read-only command which was refused; exact requested tool-only behavior did not pass.", + "Original failed recorder result is retained; audit changes made no model calls." + ], + "native_child_control": [ + "Agent", + "TaskStop", + "SendMessage", + "runtime_SIGKILL", + "parent_resume", + "SendMessage" + ], + "native_child_spawn_count": 1, + "native_cli_invocations": 2, + "original_recorder_status": "failed", + "outer_native_attempts": 1, + "parent_control_commands": [ + "python3 control.py await-cancel-wait", + "python3 control.py verify-cancelled", + "python3 control.py await-crash-wait" + ], + "recorder_false_negative": "Resumed native background-task delivery emitted three init and three success results; the original recorder required exactly one.", + "same_child_identity": true, + "same_child_run_count": 3, + "same_parent_identity": true, + "scope": "One same-host native child local-writing continuation after native cancellation and abrupt shared-runtime failure, with explicit coordinator descendant cleanup.", + "single_final_effect": true, + "status": "accepted_within_scope_after_explicit_cleanup", + "usage": { + "billing": null, + "complete_parent_child_retry_total": null, + "completed_child_run_usage": { + "duration_ms": 12777, + "tool_uses": 2, + "total_tokens": 11334 + }, + "initial_terminal_missing_due_to_SIGKILL": true, + "one_observed_cumulative_model_view": { + "claude-opus-5": { + "cacheCreationInputTokens": 7002, + "cacheReadInputTokens": 85797, + "canonicalModel": "claude-opus-5", + "contextWindow": 1000000, + "costBasis": "list", + "costUSD": 0.24804849999999998, + "inputTokens": 12, + "maxOutputTokens": 64000, + "outputTokens": 5725, + "provider": "firstParty", + "thinkingTokens": 3378, + "webSearchRequests": 0 + } + }, + "repeated_final_model_usage_count": 2, + "resumed_terminal_category_views": [ + { + "cache_creation_input_tokens": 0, + "cache_read_input_tokens": 0, + "input_tokens": 0, + "output_tokens": 0 + }, + { + "cache_creation_input_tokens": 3496, + "cache_read_input_tokens": 37747, + "input_tokens": 4, + "output_tokens": 636 + }, + { + "cache_creation_input_tokens": 1358, + "cache_read_input_tokens": 20957, + "input_tokens": 2, + "output_tokens": 2850 + } + ], + "savings_claim": null + } +} diff --git a/blueprints/convergence-practice/worker-recovery/input.json b/blueprints/convergence-practice/worker-recovery/input.json new file mode 100644 index 000000000..714989f56 --- /dev/null +++ b/blueprints/convergence-practice/worker-recovery/input.json @@ -0,0 +1 @@ +{"records":[{"id":"b","value":7},{"id":"a","value":5}]} diff --git a/blueprints/convergence-practice/worker-recovery/plan.json b/blueprints/convergence-practice/worker-recovery/plan.json new file mode 100644 index 000000000..9bfb524f9 --- /dev/null +++ b/blueprints/convergence-practice/worker-recovery/plan.json @@ -0,0 +1,21 @@ +{ + "schema_version": 1, + "kind": "native_child_cancellation_crash_resume_plan", + "frozen_before_model_execution": true, + "public_base_commit": "10354bc0576165c617b6851e6760fe1dc9e54675", + "outer_attempts": 1, + "native_route": "Existing first-party Claude subscription; no sign-in changes or fallback", + "model": "claude-opus-5", + "effort": "ultracode", + "child_model": "inherit", + "parent_max_turns": 16, + "child_max_turns": 8, + "native_phase_deadline_seconds": 240, + "fixture": "One private Git fixture; child is sole writer of checkpoint, action journal and final effect. Parent control operations only observe.", + "sequence": ["one native Agent background child", "child checkpoint and pending cancel-wait", "native TaskStop", "same-child SendMessage", "child pending crash-wait", "supervisor SIGKILL of owned shared CLI process group", "same-parent CLI resume", "same-child SendMessage finalize"], + "acceptance": ["actual child delegation and same child identity", "cancelled owned wait stops", "second child wait unfinished at abrupt shared runtime failure", "same parent session and child continue", "checkpoint bytes and hash unchanged", "action journal exactly checkpoint,cancel-wait,crash-wait,finalize", "one final effect", "frozen input and code hashes unchanged", "owned processes stopped"], + "stop_conditions": ["quota or account refusal", "unsupported native child control", "permission refusal", "unexpected write or repeated effect", "deadline"], + "usage": "Retain native terminal/model/task views separately. SIGKILL can prevent a complete terminal ledger; unknown total stays unknown. No savings or billing claim.", + "limitations": ["Same physical WSL host and synthetic local writes", "Child agents share native CLI runtime; SIGKILL is shared-runtime failure, not an independently addressable child OS process", "Not remote provider cancellation, cost cessation, power loss or distributed exactly-once acceptance"], + "sources": ["https://code.claude.com/docs/en/sub-agents#resume-subagents", "https://code.claude.com/docs/en/cli-reference"] +} diff --git a/blueprints/convergence-practice/worker-recovery/prompt.txt b/blueprints/convergence-practice/worker-recovery/prompt.txt new file mode 100644 index 000000000..f6bf7f657 --- /dev/null +++ b/blueprints/convergence-practice/worker-recovery/prompt.txt @@ -0,0 +1,9 @@ +Qualify exactly one native background foundation-recovery-worker in this owned fixture. You are the read-only native parent. All fixture writes must be made by the child, never by you. Do not inspect unrelated files, use MCP, change settings, spawn another worker, or repeat failed operations. + +1. Use Agent exactly once with subagent_type foundation-recovery-worker, run_in_background true, and prompt: "Run exactly python3 stage.py checkpoint, then python3 stage.py cancel-wait with timeout 300000. This is your only owned output fixture. Wait for explicit parent continuation; never recreate the checkpoint." +2. Retain that actual child agent/task identity. Run only python3 control.py await-cancel-wait using Bash with timeout 180000. +3. Use native TaskStop to stop that same child. Run python3 control.py verify-cancelled with timeout 180000. If that fails, stop and report failure; do not repair it yourself. +4. Use SendMessage to the SAME child agent ID (not a new Agent invocation), content: "Continue the same owned task. The checkpoint already exists and is immutable. Run ONLY python3 stage.py crash-wait with timeout 300000. Do not finalize, recreate files, or run checkpoint again." +5. Run python3 control.py await-crash-wait with timeout 180000, then python3 control.py supervisor-hold with timeout 300000. The external supervisor will abruptly terminate this owned native runtime while the child wait is pending. Do not stop the child again, finalize anything, or finish the conversation while waiting. + +Do not interpret a task cancellation as user withdrawal of this explicitly authorized test. Use TaskStop, not shutdown messaging. If any native capability is unavailable or a quota/permission error occurs, report that exact boundary and stop. Use the requested inherited Opus model without a fallback. diff --git a/blueprints/convergence-practice/worker-recovery/receipt.json b/blueprints/convergence-practice/worker-recovery/receipt.json new file mode 100644 index 000000000..62f1f8a15 --- /dev/null +++ b/blueprints/convergence-practice/worker-recovery/receipt.json @@ -0,0 +1,96 @@ +{ + "accepted_claims": [ + "Native TaskStop cancelled the child first wait; native SendMessage resumed that same child.", + "After owned runtime SIGKILL, the same parent session resumed and sent a message to the same child; no replacement Agent call occurred.", + "The child performed checkpoint,cancel-wait,crash-wait,finalize with exact frozen source and an unchanged checkpoint; one final effect exists.", + "After explicit identity-checked cleanup, both original wait identities were no longer alive and no process retained the fixture working directory." + ], + "child_model": "inherit", + "effort_requested": "ultracode", + "elapsed_seconds": 43.012, + "kind": "native_model_e2e", + "limitations": [ + "One synthetic local fixture and one physical WSL host, not arbitrary application state.", + "Actual native child identities and paths remain private; hashes bind retained streams.", + "Native original runtime SIGKILL is a shared-process failure; task identity and effect continuation are distinct from process containment.", + "The updated runner parser is regression-tested offline; the one native attempt executed the separately retained source." + ], + "model": "claude-opus-5", + "native_child_spawns": 1, + "native_cli_invocations": 2, + "native_cli_version": "2.1.278", + "native_executable_hash_captured_after_attempt": true, + "native_executable_sha256": "5c4735937844e84f8a93306e841a5b0e12252909b07870f789b190468da147ab", + "outer_attempts": 1, + "private_evidence": { + "attempt.json": { + "bytes": 5153, + "sha256": "69e1d2fe530a5a8caf5422bf49abd8c3acbce3ed16cd44e68433ec61cfa4070c" + }, + "commands-private.json": { + "bytes": 2485, + "sha256": "9f6bd92f4fb3ad52548b30ad78ee2032d9ae6f0cd410f636aadc5a3f4af98e49" + }, + "freeze.json": { + "bytes": 727, + "sha256": "0089affc3c4bbfd5676b801113a1a02fae46bc5bcd2420f83007db9a2aa9b05e" + }, + "initial.stderr.txt": { + "bytes": 0, + "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "initial.stream.jsonl": { + "bytes": 68933, + "sha256": "5e19b6c8037e82e5b5ff1a716ccbeb2fbb5235ce7997562b068d55a61671e42d" + }, + "native-help.txt": { + "bytes": 21401, + "sha256": "ae85d661e9c086f05637ebcd868f5702b477ff6e55e2e65b8ada7807cd51a4b6" + }, + "native-identity.json": { + "bytes": 66, + "sha256": "06b8c81b35358afe7d88047c5447dafb5de96a9c81a9d4c3c61652a261192970" + }, + "pre-crash-private.json": { + "bytes": 746, + "sha256": "e6dc93d6d0b7e1517fec1690a58e04e805df101aceecdaf761c0f25d9f6f6e27" + }, + "resume-prompt-private.txt": { + "bytes": 541, + "sha256": "be003aade5da4764f1db010de98447f093019e30fa3b3fdd9ca30165f22cc0d3" + }, + "resumed.stderr.txt": { + "bytes": 0, + "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "resumed.stream.jsonl": { + "bytes": 80258, + "sha256": "78a6b4555fa022716655e7aedafc48c0a2c3517f30eae897f0ea8f6120938538" + } + }, + "recorded_at_utc": "2026-09-20T18:42:46.825886+00:00", + "retained_recorder_failure": { + "audit": "independent-audit.json", + "executed_runner": "executed-runner.py.txt", + "model_rerun_after_correction": false, + "reason": "Original recorder assumed one init/result per CLI; resumed background-task delivery emitted three of each, all with the same session/model and success results.", + "source": "recorder-outcome.json", + "status": "failed" + }, + "same_child_runs": 3, + "schema_version": 1, + "scope": "One actual native Claude background writing child on Linux/WSL; cancellation and same-child continuation after shared runtime SIGKILL, with explicit coordinator cleanup of its surviving owned wait.", + "status": "partial_acceptance", + "unaccepted_claims": [ + "Automatic native crash descendant containment: the crash wait survived and needed supervisor SIGKILL.", + "Exact requested tool-only behavior: the child attempted an extra read-only ls/git-status command, which was refused.", + "Remote provider cancellation, billing cessation, independent child-process isolation, off-host recovery, power-loss durability and distributed exactly-once effects." + ], + "usage": { + "billing": null, + "complete_parent_child_retry_total": null, + "initial_terminal_missing_due_to_sigkill": true, + "native_views": "See independent-audit.json and recorder-outcome.json; repeated model views and task estimates are not additive.", + "savings_claim": null + } +} diff --git a/blueprints/convergence-practice/worker-recovery/recorder-outcome.json b/blueprints/convergence-practice/worker-recovery/recorder-outcome.json new file mode 100644 index 000000000..fc4febc59 --- /dev/null +++ b/blueprints/convergence-practice/worker-recovery/recorder-outcome.json @@ -0,0 +1,174 @@ +{ + "billing": null, + "checks": { + "cancelled_wait_stopped": true, + "checkpoint_unchanged": true, + "child_second_wait_pending": true, + "cleanup_errors_absent": true, + "final_matches_oracle": true, + "native_model_preserved": false, + "native_taskstop_then_message_observed": true, + "no_replacement_child": true, + "one_native_child_spawn": true, + "owned_cli_processes_stopped": true, + "owned_crash_wait_stopped": true, + "owned_runtime_sigkill_exit": true, + "pre_crash_journal_exact": true, + "resumed_native_success": false, + "same_child_message_target": true, + "same_parent_session": false, + "single_effect_journal": true + }, + "cleanup": { + "cancel-wait.json_forced_cleanup": false, + "crash-wait.json_forced_cleanup": false, + "crash_wait_additional_cleanup": true, + "errors": [], + "initial_exit": -9 + }, + "complete_parent_child_usage": null, + "elapsed_seconds": 43.012, + "failure": null, + "native_invocations": [ + { + "exit_code": -9, + "invalid_stream_lines": 0, + "model_usage": [], + "phase": "initial", + "terminal_count": 0, + "terminal_usage": [] + }, + { + "exit_code": 0, + "invalid_stream_lines": 0, + "model_usage": [ + {}, + { + "claude-opus-5": { + "cacheCreationInputTokens": 7002, + "cacheReadInputTokens": 85797, + "canonicalModel": "claude-opus-5", + "contextWindow": 1000000, + "costBasis": "list", + "costUSD": 0.24804849999999998, + "inputTokens": 12, + "maxOutputTokens": 64000, + "outputTokens": 5725, + "provider": "firstParty", + "thinkingTokens": 3378, + "webSearchRequests": 0 + } + }, + { + "claude-opus-5": { + "cacheCreationInputTokens": 7002, + "cacheReadInputTokens": 85797, + "canonicalModel": "claude-opus-5", + "contextWindow": 1000000, + "costBasis": "list", + "costUSD": 0.24804849999999998, + "inputTokens": 12, + "maxOutputTokens": 64000, + "outputTokens": 5725, + "provider": "firstParty", + "thinkingTokens": 3378, + "webSearchRequests": 0 + } + } + ], + "phase": "resumed", + "terminal_count": 3, + "terminal_usage": [ + { + "cache_creation": { + "ephemeral_1h_input_tokens": 0, + "ephemeral_5m_input_tokens": 0 + }, + "cache_creation_input_tokens": 0, + "cache_read_input_tokens": 0, + "inference_geo": "", + "input_tokens": 0, + "iterations": [], + "output_tokens": 0, + "output_tokens_details": { + "thinking_tokens": 0 + }, + "server_tool_use": { + "web_fetch_requests": 0, + "web_search_requests": 0 + }, + "service_tier": "standard", + "speed": "standard" + }, + { + "cache_creation": { + "ephemeral_1h_input_tokens": 3496, + "ephemeral_5m_input_tokens": 0 + }, + "cache_creation_input_tokens": 3496, + "cache_read_input_tokens": 37747, + "inference_geo": "not_available", + "input_tokens": 4, + "iterations": [ + { + "cache_creation": { + "ephemeral_1h_input_tokens": 671, + "ephemeral_5m_input_tokens": 0 + }, + "cache_creation_input_tokens": 671, + "cache_read_input_tokens": 20286, + "input_tokens": 2, + "output_tokens": 82, + "type": "message" + } + ], + "output_tokens": 636, + "output_tokens_details": { + "thinking_tokens": 388 + }, + "server_tool_use": { + "web_fetch_requests": 0, + "web_search_requests": 0 + }, + "service_tier": "standard", + "speed": "standard" + }, + { + "cache_creation": { + "ephemeral_1h_input_tokens": 1358, + "ephemeral_5m_input_tokens": 0 + }, + "cache_creation_input_tokens": 1358, + "cache_read_input_tokens": 20957, + "inference_geo": "not_available", + "input_tokens": 2, + "iterations": [ + { + "cache_creation": { + "ephemeral_1h_input_tokens": 1358, + "ephemeral_5m_input_tokens": 0 + }, + "cache_creation_input_tokens": 1358, + "cache_read_input_tokens": 20957, + "input_tokens": 2, + "output_tokens": 2850, + "type": "message" + } + ], + "output_tokens": 2850, + "output_tokens_details": { + "thinking_tokens": 1827 + }, + "server_tool_use": { + "web_fetch_requests": 0, + "web_search_requests": 0 + }, + "service_tier": "standard", + "speed": "standard" + } + ] + } + ], + "savings_claim": null, + "status": "failed" +} diff --git a/blueprints/convergence-practice/worker-recovery/run.py b/blueprints/convergence-practice/worker-recovery/run.py new file mode 100644 index 000000000..0f3331d73 --- /dev/null +++ b/blueprints/convergence-practice/worker-recovery/run.py @@ -0,0 +1,209 @@ +#!/usr/bin/env python3 +"""One explicitly authorized native child cancellation/crash/resume trial.""" +import argparse +from datetime import datetime, timezone +import hashlib +import importlib.util +import json +import os +from pathlib import Path +import shutil +import signal +import subprocess +import sys +import time +import uuid + +HERE=Path(__file__).resolve().parent +LEGACY=HERE.parent/'native-recovery/claude' +sys.path.insert(0,str(LEGACY)) +support_spec=importlib.util.spec_from_file_location('claude_recovery_support',LEGACY/'run.py') +support=importlib.util.module_from_spec(support_spec);support_spec.loader.exec_module(support) +NativeCLI,identity,private_directory=support.NativeCLI,support.identity,support.private_directory +spec=importlib.util.spec_from_file_location('owned_worker_stage',HERE/'stage.py') +fixture=importlib.util.module_from_spec(spec); spec.loader.exec_module(fixture) +service_spec=importlib.util.spec_from_file_location('worker_owned_service',HERE/'service.py') +service=importlib.util.module_from_spec(service_spec);service_spec.loader.exec_module(service) + + +def write(path,data): + path.write_text(json.dumps(data,indent=2,sort_keys=True)+'\n') + + +def sha(path): return hashlib.sha256(path.read_bytes()).hexdigest() + + +def calls(events): + return [(event,block) for event in list(events) if event.get('type')=='assistant' + for block in event.get('message',{}).get('content',[]) if block.get('type')=='tool_use'] + + +def alive(marker): + current=identity(marker['pid']) + return current is not None and current['state']!='Z' and current['start_ticks']==marker['start_ticks'] + + +def native_summary(events, session): + """Native background-task delivery can emit multiple init/result messages.""" + inits=[e for e in events if e.get('type')=='system' and e.get('subtype')=='init'] + terminals=[e for e in events if e.get('type')=='result'] + return (bool(inits) and all(e.get('session_id')==session for e in inits), + bool(inits) and all(e.get('model')=='claude-opus-5' for e in inits), + bool(terminals) and all(e.get('subtype')=='success' and e.get('is_error') is False for e in terminals)) + + +def permission_refused(events): + for event in list(events): + if event.get('type')!='user':continue + for block in event.get('message',{}).get('content',[]): + if not isinstance(block,dict) or block.get('type')!='tool_result' or block.get('is_error') is not True:continue + content=str(block.get('content','')).casefold() + if 'permission' in content and 'denied' in content:return True + return False + + +def service_ready(unit,client): + deadline=time.monotonic()+15 + while True: + state=service.show(unit) + if int(state.get('MainPID','0'))>0:return state + if client.proc.poll() is not None or time.monotonic()>deadline:raise RuntimeError('owned_service_not_ready') + time.sleep(.05) + + +def stop_owned_wait(path,workspace): + if not path.is_file():return False + marker=json.loads(path.read_text()) + if not alive(marker):return False + pid=marker['pid'] + command=Path(f'/proc/{pid}/cmdline').read_bytes().split(b'\0') + if b'stage.py' not in command or Path(f'/proc/{pid}/cwd').resolve()!=workspace: + raise RuntimeError('owned_wait_identity_mismatch') + try:os.kill(pid,signal.SIGKILL) + except ProcessLookupError:pass + end=time.monotonic()+5 + while alive(marker) and time.monotonic()deadline:raise TimeoutError('child_crash_wait_deadline') + time.sleep(.05) + # A native SendMessage follows the native TaskStop; retain identities verbatim privately. + native_calls=calls(initial.events) + agent_calls=[b for _,b in native_calls if b['name']=='Agent'] + stops=[b for _,b in native_calls if b['name']=='TaskStop'] + messages=[b for _,b in native_calls if b['name']=='SendMessage'] + if len(agent_calls)!=1 or len(stops)!=1 or len(messages)!=1:raise RuntimeError('native_child_control_sequence_missing') + child_id=messages[0]['input'].get('to') or messages[0]['input'].get('recipient') + if not isinstance(child_id,str) or not child_id:raise RuntimeError('native_child_identity_missing') + checks['one_native_child_spawn']=True + checks['native_taskstop_then_message_observed']=True + checks['cancelled_wait_stopped']=not alive(json.loads((workspace/'cancel-wait.json').read_text())) + checks['child_second_wait_pending']=alive(json.loads((workspace/'crash-wait.json').read_text())) + checks['pre_crash_journal_exact']=fixture.actions(workspace)==['checkpoint','cancel-wait','crash-wait'] + before=(workspace/'checkpoint.json').read_bytes() + if not all(checks.values()) or before!=fixture.EXPECTED:raise RuntimeError('pre_crash_acceptance_failed') + write(root/'pre-crash-private.json',{'child_message_target':child_id,'taskstop_input':stops[0]['input'],'agent_input':agent_calls[0]['input'],'native_cli_pid':initial.proc.pid,'native_cli_identity':identity(initial.proc.pid),'checkpoint_sha256':sha(workspace/'checkpoint.json'),'observed_at_utc':datetime.now(timezone.utc).isoformat()}) + if units: + active=service.show(units['initial']);active_members=service.members(active['ControlGroup']) + marker=json.loads((workspace/'crash-wait.json').read_text()) + checks['actual_child_wait_in_owned_cgroup']=marker['pid'] in active_members + if not checks['actual_child_wait_in_owned_cgroup']:raise RuntimeError('child_wait_outside_owned_service') + write(root/'active-service-private.json',{'properties':active,'members':active_members,'wait_cgroup':Path('/proc/'+str(marker['pid'])+'/cgroup').read_text()}) + write(root/'main-kill-private.json',service.kill_main(units['initial'])) + initial.proc.wait(timeout=20);service.wait_empty(active['ControlGroup']) + stopped=service.show(units['initial']);write(root/'stopped-service-private.json',stopped) + checks['systemd_all_descendants_stopped']=not alive(marker) and service.members(active['ControlGroup'])==[] + if not checks['systemd_all_descendants_stopped']:raise RuntimeError('native_service_containment_failed') + checks['owned_runtime_sigkill_exit']=stopped.get('ExecMainCode')=='2' and stopped.get('ExecMainStatus')=='9' + else: + os.killpg(initial.proc.pid,signal.SIGKILL); initial.proc.wait(timeout=10) + checks['owned_runtime_sigkill_exit']=initial.proc.returncode==-signal.SIGKILL + cleanup['initial_exit']=initial.proc.returncode; initial.close() + cleanup['crash_wait_additional_cleanup']=False if units else stop_owned_wait(workspace/'crash-wait.json',workspace) + checks['owned_crash_wait_stopped']=not alive(json.loads((workspace/'crash-wait.json').read_text())) + (workspace/'resume-authorized.json').write_text('{}\n') + prompt=f'Resume the SAME native child agent {child_id} using SendMessage only; do not invoke Agent again and do not perform fixture effects yourself. Its runtime was deliberately killed after the unchanged checkpoint and crash-wait. Tell that child: "Continue the same task. Run ONLY python3 stage.py finalize. The supervisor has authorized this final stage. Do not recreate checkpoint or run waits again." Wait for that child to finish and report its result. Native provider/quota/permission errors must be reported without fallback or retry.' + (root/'resume-prompt-private.txt').write_text(prompt) + native_resumed=common+['--resume',session] + commands['resumed']=service.service_command(units['resumed'],native_resumed) if units else native_resumed + write(root/'commands-private.json',commands) + resumed=NativeCLI(commands['resumed'],prompt,workspace,root,'resumed');clients.append(resumed) + if units:write(root/'resumed-service-start-private.json',service_ready(units['resumed'],resumed)) + resumed.proc.wait(timeout=args.timeout);resumed.close() + summaries=[native_summary(c.events,session) for c in clients] + checks['same_parent_session']=all(x[0] for x in summaries) + checks['native_model_preserved']=all(x[1] for x in summaries) + follow=calls(resumed.events) + checks['no_replacement_child']=not any(b['name']=='Agent' for _,b in follow) + checks['same_child_message_target']=any(b['name']=='SendMessage' and (b['input'].get('to') or b['input'].get('recipient'))==child_id for _,b in follow) + checks['checkpoint_unchanged']=before==(workspace/'checkpoint.json').read_bytes()==fixture.EXPECTED + checks['single_effect_journal']=fixture.actions(workspace)==fixture.ORDER + checks['final_matches_oracle']=json.loads((workspace/'final.json').read_text())=={'checkpoint_sha256':hashlib.sha256(fixture.EXPECTED).hexdigest(),'execution_count':1,'status':'complete'} + checks['resumed_native_success']=resumed.proc.returncode==0 and summaries[-1][2] + except Exception as exc: + failure={'type':type(exc).__name__,'reason':str(exc)} + finally: + for c in clients: + try: + if not c.out.closed:c.close() + except Exception as exc:cleanup['errors'].append(type(exc).__name__) + for name in ('cancel-wait.json','crash-wait.json'): + try:cleanup[name+'_forced_cleanup']=stop_owned_wait(workspace/name,workspace) + except Exception as exc:cleanup['errors'].append(type(exc).__name__) + if units: + cleanup['owned_services']={} + for phase,unit in units.items(): + try:cleanup['owned_services'][phase]=service.cleanup(unit) + except Exception as exc:cleanup['errors'].append(type(exc).__name__) + checks['owned_cli_processes_stopped']=bool(clients) and all(c.proc.poll() is not None for c in clients) + checks['cleanup_errors_absent']=not cleanup['errors'] + summaries=[] + for c in clients: + terminals=[e for e in c.events if e.get('type')=='result'] + summaries.append({'phase':c.label,'exit_code':c.proc.returncode,'invalid_stream_lines':c.invalid_lines,'terminal_count':len(terminals),'terminal_usage':[e.get('usage') for e in terminals],'model_usage':[e.get('modelUsage') for e in terminals]}) + write(root/'attempt.json',{'status':'passed_pending_independent_audit' if failure is None and all(checks.values()) else 'failed','elapsed_seconds':round(time.monotonic()-start,3),'checks':checks,'cleanup':cleanup,'failure':failure,'native_invocations':summaries,'complete_parent_child_usage':None,'billing':None,'savings_claim':None}) + print(json.dumps({'status':json.loads((root/'attempt.json').read_text())['status'],'checks':checks,'failure':failure},indent=2)) + return 0 if failure is None and all(checks.values()) else 1 + + +if __name__=='__main__': + p=argparse.ArgumentParser(description=__doc__);p.add_argument('--run-dir',required=True);p.add_argument('--claude',default='claude');p.add_argument('--timeout',type=int,default=240) + p.add_argument('--supervision',choices=['process-group','systemd'],default='process-group') + raise SystemExit(run(p.parse_args())) diff --git a/blueprints/convergence-practice/worker-recovery/service.py b/blueprints/convergence-practice/worker-recovery/service.py new file mode 100644 index 000000000..bd54b7969 --- /dev/null +++ b/blueprints/convergence-practice/worker-recovery/service.py @@ -0,0 +1,76 @@ +"""Only uniquely owned transient user services; no persistent configuration.""" +import os +from pathlib import Path +import re +import subprocess +import time + +PROPERTIES='Id,Type,ActiveState,SubState,Result,MainPID,ControlGroup,KillMode,SendSIGKILL,TimeoutStopUSec,Restart,NRestarts,ExecMainCode,ExecMainStatus' + + +def validate_unit(unit): + if re.fullmatch(r'foundation-recovery-[0-9a-f]{12}-(initial|resumed|probe|readiness)',unit) is None: + raise ValueError('only_uniquely_owned_recovery_units_allowed') + return unit + + +def service_command(unit,command,environment_names=None): + validate_unit(unit) + # Some WSL variables (for example PROGRAMFILES(X86)) are not valid systemd + # environment names. Native paths and ordinary variables remain unchanged. + names=sorted((name for name in os.environ if re.fullmatch(r'[A-Za-z_][A-Za-z0-9_]*',name)) + if environment_names is None else environment_names) + if not all(re.fullmatch(r'[A-Za-z_][A-Za-z0-9_]*',name) for name in names): + raise ValueError('invalid_environment_name') + return ['systemd-run','--user','--wait','--pipe','--quiet','--same-dir','--expand-environment=no', + '--unit='+unit,'--property=Type=exec','--property=RuntimeMaxSec=300s', + '--property=TimeoutStopSec=2s','--property=KillMode=control-group', + '--property=SendSIGKILL=yes','--property=Restart=no', + *['--setenv='+name for name in names],*command] + + +def show(unit): + validate_unit(unit) + result=subprocess.run(['systemctl','--user','show',unit+'.service','--property='+PROPERTIES],capture_output=True,text=True,check=True) + return dict(line.split('=',1) for line in result.stdout.splitlines() if '=' in line) + + +def members(group): + if not group:return [] + root=Path('/sys/fs/cgroup') + target=(root/group.lstrip('/')).resolve() + if not target.is_relative_to(root):raise ValueError('invalid_cgroup_path') + if not target.exists():return [] + result=set() + for path in target.rglob('cgroup.procs'): + try:result.update(int(x) for x in path.read_text().split()) + except FileNotFoundError:pass + return sorted(result) + + +def kill_main(unit): + before=show(unit) + if int(before.get('MainPID','0'))<=0 or before.get('KillMode')!='control-group': + raise RuntimeError('owned_main_not_ready') + before_members=members(before['ControlGroup']) + command=['systemctl','--user','kill','--kill-whom=main','--signal=SIGKILL',unit+'.service'] + result=subprocess.run(command,capture_output=True,text=True,check=True) + return {'command':command,'exit_code':result.returncode,'before':before,'before_members':before_members} + + +def wait_empty(group,timeout=15): + deadline=time.monotonic()+timeout + while members(group): + if time.monotonic()>deadline:raise TimeoutError('owned_cgroup_not_empty') + time.sleep(.05) + return [] + + +def cleanup(unit): + current=show(unit) + stop_needed=current.get('ActiveState') in ('active','activating','deactivating') + if stop_needed:subprocess.run(['systemctl','--user','stop',unit+'.service'],capture_output=True,text=True,check=True) + after=show(unit) + remaining=wait_empty(current.get('ControlGroup','')) + subprocess.run(['systemctl','--user','reset-failed',unit+'.service'],capture_output=True,text=True,check=False) + return {'stop_needed':stop_needed,'after':after,'remaining_members':remaining} diff --git a/blueprints/convergence-practice/worker-recovery/source-review.json b/blueprints/convergence-practice/worker-recovery/source-review.json new file mode 100644 index 000000000..0cdad6949 --- /dev/null +++ b/blueprints/convergence-practice/worker-recovery/source-review.json @@ -0,0 +1,32 @@ +{ + "checked_at": "2026-09-20", + "native_help_sha256": "ae85d661e9c086f05637ebcd868f5702b477ff6e55e2e65b8ada7807cd51a4b6", + "native_runtime": { + "version": "2.1.278 (Claude Code)", + "executable_sha256": "5c4735937844e84f8a93306e841a5b0e12252909b07870f789b190468da147ab", + "captured_after_native_attempt": true + }, + "sources": [ + { + "url": "https://code.claude.com/docs/en/sub-agents", + "reviewed_via": "official documentation page opened with web retrieval before native execution", + "relevant_protocol": "TaskStop-stopped child can resume via SendMessage; same child transcript persists across parent-session restart.", + "full_source_sha256": null + }, + { + "url": "https://code.claude.com/docs/en/cli-reference", + "reviewed_via": "official documentation page and actual local CLI help before native execution", + "relevant_protocol": "Native --agents, stream-json, scoped tools, --session-id and --resume.", + "full_source_sha256": null + } + ], + "direct_source_capture": { + "url": "https://code.claude.com/docs/en/sub-agents.md", + "outcome": "HTTP403", + "retried": false + }, + "limitations": [ + "Official pages were reviewed before execution; full web-page bytes were not retained. A later direct Markdown capture was refused.", + "Executable hash is a post-attempt local read; the native stream independently records the running CLI version." + ] +} diff --git a/blueprints/convergence-practice/worker-recovery/stage.py b/blueprints/convergence-practice/worker-recovery/stage.py new file mode 100644 index 000000000..f529c45f2 --- /dev/null +++ b/blueprints/convergence-practice/worker-recovery/stage.py @@ -0,0 +1,58 @@ +"""Owned local writing effects; native worker is the only effect writer.""" +import hashlib +import json +import os +from pathlib import Path +import signal +import sys +import time + +EXPECTED = b'{"ids":["a","b"],"total":12}\n' +ORDER = ['checkpoint', 'cancel-wait', 'crash-wait', 'finalize'] + + +def durable(path, data): + with path.open('xb') as out: + out.write(data) + out.flush() + os.fsync(out.fileno()) + + +def actions(root): + path = Path(root) / 'actions.jsonl' + return [json.loads(x)['action'] for x in path.read_text().splitlines()] if path.exists() else [] + + +def execute(root, action): + root = Path(root) + before = actions(root) + if action not in ORDER or before != ORDER[:ORDER.index(action)]: + raise ValueError('effect_order_violation') + if action == 'checkpoint': + records = json.loads((root / 'input.json').read_text())['records'] + payload = (json.dumps({'ids':sorted(x['id'] for x in records), 'total':sum(x['value'] for x in records)}, separators=(',', ':'))+'\n').encode() + if payload != EXPECTED: + raise ValueError('input_oracle_mismatch') + durable(root / 'checkpoint.json', payload) + elif action == 'finalize': + if not (root / 'resume-authorized.json').is_file(): + raise ValueError('supervisor_authorization_missing') + if (root / 'checkpoint.json').read_bytes() != EXPECTED: + raise ValueError('checkpoint_changed') + durable(root / 'final.json', (json.dumps({'checkpoint_sha256':hashlib.sha256(EXPECTED).hexdigest(), 'execution_count':1, 'status':'complete'},sort_keys=True)+'\n').encode()) + with (root / 'actions.jsonl').open('a') as out: + out.write(json.dumps({'action':action})+'\n'); out.flush(); os.fsync(out.fileno()) + if action in ('cancel-wait', 'crash-wait'): + stat = Path('/proc/self/stat').read_text().rsplit(')',1)[1].split() + durable(root / (action+'.json'), (json.dumps({'pid':os.getpid(),'start_ticks':stat[19]})+'\n').encode()) + def stopped(number, _frame): + durable(root / (action+'-interrupted.json'), (json.dumps({'signal':number})+'\n').encode()) + raise SystemExit(128+number) + signal.signal(signal.SIGINT, stopped); signal.signal(signal.SIGTERM, stopped) + time.sleep(300) + raise RuntimeError('wait_was_not_interrupted') + return {'action':action, 'execution_count':actions(root).count('checkpoint')} + + +if __name__ == '__main__': + print(json.dumps(execute(Path(__file__).resolve().parent, sys.argv[1]))) diff --git a/blueprints/convergence-practice/worker-recovery/systemd-freeze.json b/blueprints/convergence-practice/worker-recovery/systemd-freeze.json new file mode 100644 index 000000000..c51283d7a --- /dev/null +++ b/blueprints/convergence-practice/worker-recovery/systemd-freeze.json @@ -0,0 +1,13 @@ +{ + "at_utc": "2026-09-20T18:52:18.341693+00:00", + "sha256": { + "control.py": "e25f7758b5d374fea206b3b7936baa99e4ac5abeb9fd8aed2e83f1cae21006a7", + "input.json": "69741926414949ad09864359cb41523db6a94d093d5c44dc822982c8aab3ef2d", + "prompt.txt": "a68ee7b3ce1bc73b4393b348d8e267ce34bee1337d2bc43c8b046df8f0e1811c", + "run.py": "a79887b79f719b520292177dffe8153d28cce67e8ec6a5cba884ebd58aaf91ad", + "service.py": "88b2922a5c415238c0abf06fb4e6fd3f13b98c884e1ee113802e9a85e0b3dae5", + "stage.py": "fdadd66e4b137940ee638c8e89747cfbf882241084cccb0a4e09b9c00d927214", + "systemd-plan.json": "5e8e69cea6fbc3d802a8e8ccbb6af724f828fb868b9850d8896f86381ab3a5da", + "test_oracle": "009730174a3ced99e5902edd555ff00c85c25497df807a3bd01ef264db886ca8" + } +} diff --git a/blueprints/convergence-practice/worker-recovery/systemd-plan.json b/blueprints/convergence-practice/worker-recovery/systemd-plan.json new file mode 100644 index 000000000..f91eb7949 --- /dev/null +++ b/blueprints/convergence-practice/worker-recovery/systemd-plan.json @@ -0,0 +1,18 @@ +{ + "schema_version": 1, + "kind": "native_child_cgroup_containment_plan", + "frozen_before_model_execution": true, + "base_partial_acceptance_commit": "533c6ee17f414fe7306ee3a64a7b01f9415e3fdf", + "concrete_gap": "The prior native crash wait survived process-group SIGKILL and needed direct coordinator cleanup.", + "changed_input": "Each native CLI is an owned transient systemd user service: Type=exec, KillMode=control-group, TimeoutStopSec=2s, SendSIGKILL=yes, Restart=no, RuntimeMaxSec=300s, native stdio pipes. Only service MainPID is deliberately killed.", + "preserved_inputs": ["same stage/control/input/prompt fixture", "claude-opus-5 and ultracode", "child model inherit", "native account and permission configuration", "all valid inherited environment names including PATH/HOME"], + "omitted_unsupported_environment_names": ["PROGRAMFILES(X86)"], + "preconditions": ["deterministic native setsid TERM-ignoring descendant proof", "no-model native sign-in/version/PATH/HOME readiness under service"], + "outer_native_attempts": 1, + "native_cli_invocations": 2, + "native_phase_deadline_seconds": 240, + "acceptance": ["one actual native child and same parent/child continuation", "native TaskStop cancellation first", "actual pending crash wait observed in owned service cgroup", "kill only owned service MainPID", "systemd removes every cgroup member and original wait without direct PID cleanup", "resume same task with unchanged checkpoint and one final effect", "no native restart or lingering owned unit/process"], + "usage": "SIGKILL prevents complete initial terminal accounting. Keep native terminal/model/task views separate; no billing or savings claim.", + "limitations": ["one WSL host and synthetic task", "not manager or host crash, remote provider cancellation, power loss, independent-host recovery or distributed exactly-once effects", "original direct-process survivor and recorder failure remain retained"], + "sources": ["https://raw.githubusercontent.com/systemd/systemd/v255/man/systemd.kill.xml", "https://raw.githubusercontent.com/systemd/systemd/v255/man/systemd-run.xml"] +} diff --git a/blueprints/convergence-practice/worker-recovery/systemd-recorder-outcome.json b/blueprints/convergence-practice/worker-recovery/systemd-recorder-outcome.json new file mode 100644 index 000000000..a9fdcf7ae --- /dev/null +++ b/blueprints/convergence-practice/worker-recovery/systemd-recorder-outcome.json @@ -0,0 +1,68 @@ +{ + "billing": null, + "checks": { + "cleanup_errors_absent": true, + "owned_cli_processes_stopped": true + }, + "cleanup": { + "cancel-wait.json_forced_cleanup": false, + "crash-wait.json_forced_cleanup": false, + "errors": [], + "owned_services": { + "initial": { + "after": { + "ActiveState": "failed", + "ExecMainCode": "2", + "ExecMainStatus": "9", + "KillMode": "control-group", + "MainPID": "0", + "NRestarts": "0", + "Restart": "no", + "Result": "signal", + "SendSIGKILL": "yes", + "SubState": "failed", + "TimeoutStopUSec": "2s", + "Type": "exec" + }, + "remaining_members": [], + "stop_needed": false + }, + "resumed": { + "after": { + "ActiveState": "inactive", + "ExecMainCode": "0", + "ExecMainStatus": "0", + "KillMode": "control-group", + "MainPID": "0", + "NRestarts": "0", + "Restart": "no", + "Result": "success", + "SendSIGKILL": "yes", + "SubState": "dead", + "TimeoutStopUSec": "1min 30s", + "Type": "" + }, + "remaining_members": [], + "stop_needed": false + } + } + }, + "complete_parent_child_usage": null, + "elapsed_seconds": 99.481, + "failure": { + "reason": "initial_native_exit_before_child_crash_wait", + "type": "RuntimeError" + }, + "native_invocations": [ + { + "exit_code": 255, + "invalid_stream_lines": 0, + "model_usage": [], + "phase": "initial", + "terminal_count": 0, + "terminal_usage": [] + } + ], + "savings_claim": null, + "status": "failed" +} diff --git a/blueprints/token-native-focus/saturation-audit.json b/blueprints/token-native-focus/saturation-audit.json index 8ebd626c4..339ce73c6 100644 --- a/blueprints/token-native-focus/saturation-audit.json +++ b/blueprints/token-native-focus/saturation-audit.json @@ -31,13 +31,13 @@ ] }, "counts": { - "selected_components": 66, - "catalog_identities": 512, - "nonselected_catalog_identities": 446, + "selected_components": 68, + "catalog_identities": 513, + "nonselected_catalog_identities": 445, "exclusive_identity_groups": { "star_review": 275, - "component_record": 66, - "catalog_card": 115, + "component_record": 68, + "catalog_card": 114, "research_supplement": 54, "legacy_candidate": 2 } @@ -5766,6 +5766,193 @@ "matched_lifetime_provider_baseline": "not_established", "regression_policy": "Keep the cheaper adequate native path when a candidate expands tokens or fails required information/quality checks." } + }, + { + "component_id": "tavily-cli", + "repository": "https://github.com/tavily-ai/tavily-cli", + "version": "0.1.8", + "profile": "supporting", + "role": "On-demand authenticated web Search/Extract and official global skills for native Codex/Claude", + "installation_assessment": "Native installation and selected upstream operation recorded in the referenced receipt", + "current_host_recertified_by_this_audit": false, + "native_integration": { + "recipe_source": "adoption/manifest.json#/recipe_map/tavily-cli", + "documented_commands": [ + "tvly auth --json", + "tvly search \"Tavily Search API\" --json", + "tvly extract \"$SELECTED_PUBLIC_URL\" --json" + ], + "scope": "Use the selected native recipe only when its task applies.", + "recipe_document": "recipes/tavily.md", + "lifecycle_guide": "adoption/lifecycle.md" + }, + "functional_evidence": { + "public_receipts": [ + { + "id": "native-tavily-cli-20260920", + "path": "evidence/receipts/native-tavily-cli-20260920.json", + "kind": "native_cli_e2e" + } + ], + "retained_operation_ids": [], + "scope": "Upstream Tavily CLI0.1.8 installation, authenticated live Search/Extract and eight official skills passed scoped native discovery; Desktop-home probe required an isolated session-only SQLite path." + }, + "artifact_baselines": [], + "exact_causal_lifetime_provider_tokens_saved": null, + "next_action": "Reuse applicable dated acceptance; rerun only after changed inputs or a concrete failed operation.", + "integration_mode": "Explicit native CLI, MCP or SDK operation for the selected task.", + "lifecycle_evidence": { + "assessment": "bounded_role_evidence", + "scope": "Dated role evidence is separated into install, use, persistence, restart, cleanup and recovery below. An unestablished stage is not inferred from runtime availability.", + "all_optional_features_exercised": false + }, + "remaining_install_gap": null, + "remaining_install_gap_reason": "No additional useful installation gap identified for the selected role in this bounded evidence review; full lifecycle/optional-feature limits remain explicit.", + "lifecycle_stages": { + "install": { + "status": "accepted_within_scope", + "scope": "Official installer selected uv and installed CLI0.1.8; official skill installer installed eight native skills.", + "evidence_refs": [ + "evidence/receipts/native-tavily-cli-20260920.json" + ] + }, + "use": { + "status": "accepted_within_scope", + "scope": "Live Search returned four official sources; Extract returned one result and zero failures.", + "evidence_refs": [ + "evidence/receipts/native-tavily-cli-20260920.json" + ] + }, + "persistence": { + "status": "partial_acceptance", + "scope": "Native auth persisted across separate commands; private config mode0600. Key recovery was not exercised.", + "evidence_refs": [ + "evidence/receipts/native-tavily-cli-20260920.json" + ] + }, + "restart": { + "status": "partial_acceptance", + "scope": "Fresh Codex probes discovered eight skills in both homes. Desktop probe needed a temporary sqlite_home after a retained failure; current Desktop registry is unverified.", + "evidence_refs": [ + "evidence/receipts/native-tavily-cli-20260920.json" + ] + }, + "cleanup": { + "status": "accepted_within_scope", + "scope": "Owned app-server probes exited and none remained in process checks. Package uninstall was not replayed.", + "evidence_refs": [ + "evidence/receipts/native-tavily-cli-20260920.json" + ] + }, + "recovery": { + "status": "not_established", + "scope": "Independent host and credential recovery remain untested.", + "evidence_refs": [] + } + }, + "baseline_applicability": { + "category": "supporting_workflow", + "scope": "This role supports quality, execution, state or observation. A direct token-saving claim needs a separately defined same-task comparison; installation alone has no token baseline.", + "retained_artifact_comparisons": 0, + "matched_lifetime_provider_baseline": "not_established", + "regression_policy": "Keep the cheaper adequate native path when a candidate expands tokens or fails required information/quality checks." + } + }, + { + "component_id": "nautilus-trader", + "repository": "https://github.com/nautechsystems/nautilus_trader", + "version": "2.0.0rc5", + "profile": "optional", + "role": "User-selected trading-engine destination; isolated upstream synthetic FX acceptance, separate from equity data and broker adapters", + "installation_assessment": "Native installation and selected upstream operation recorded in the referenced receipt", + "current_host_recertified_by_this_audit": false, + "native_integration": { + "recipe_source": "adoption/manifest.json#/recipe_map/nautilus-trader", + "documented_commands": [ + "uv pip install --python \"$NAUTILUS_ENV/bin/python\" --pre nautilus_trader==2.0.0rc5", + "\"$NAUTILUS_ENV/bin/python\" \"$UPSTREAM_QUICKSTART\"" + ], + "scope": "Use the selected native recipe only when its task applies.", + "recipe_document": "blueprints/us-equities/engine-nautilus/README.md", + "lifecycle_guide": "adoption/lifecycle.md" + }, + "functional_evidence": { + "public_receipts": [ + { + "id": "native-nautilus-v2-20260920", + "path": "evidence/receipts/native-nautilus-v2-20260920.json", + "kind": "native_cli_e2e" + }, + { + "id": "native-nautilus-ci-20260920", + "path": "evidence/receipts/native-nautilus-ci-20260920.json", + "kind": "native_cli_e2e" + } + ], + "retained_operation_ids": [], + "scope": "Pinned NautilusTrader2.0.0rc5 unchanged upstream synthetic EURUSD quickstart passed two isolated offline runs with exact cash reconciliation, repeatable economic reports and original cleanup; two empty-report attempts remain retained. Fresh hosted CI also passed exact wheel/source checks, two offline replays and independent report validation." + }, + "artifact_baselines": [], + "exact_causal_lifetime_provider_tokens_saved": null, + "next_action": "Reuse applicable dated acceptance; rerun only after changed inputs or a concrete failed operation.", + "integration_mode": "Explicit native CLI, MCP or SDK operation for the selected task.", + "lifecycle_evidence": { + "assessment": "bounded_role_evidence", + "scope": "Dated role evidence is separated into install, use, persistence, restart, cleanup and recovery below. An unestablished stage is not inferred from runtime availability.", + "all_optional_features_exercised": false + }, + "remaining_install_gap": null, + "remaining_install_gap_reason": "No additional useful installation gap identified for the selected role in this bounded evidence review; full lifecycle/optional-feature limits remain explicit.", + "lifecycle_stages": { + "install": { + "status": "accepted_within_scope", + "scope": "uv installed exact2.0.0rc5 into an isolated CPython3.12 prefix. Published wheel hash is metadata; archive was not separately retained/rehashed.", + "evidence_refs": [ + "evidence/receipts/native-nautilus-v2-20260920.json" + ] + }, + "use": { + "status": "accepted_within_scope", + "scope": "Two unchanged pinned upstream synthetic FX replays passed:10000bars,902fills,451closedpositions and equal economic results after defined UUID-only normalization.", + "evidence_refs": [ + "evidence/receipts/native-nautilus-v2-20260920.json" + ] + }, + "persistence": { + "status": "partial_acceptance", + "scope": "Native CSV reports were retained with hashes. Engine state restoration was not exercised.", + "evidence_refs": [ + "evidence/receipts/native-nautilus-v2-20260920.json" + ] + }, + "restart": { + "status": "partial_acceptance", + "scope": "Two fresh offline processes replayed seed42; this does not establish interrupted-state recovery.", + "evidence_refs": [ + "evidence/receipts/native-nautilus-v2-20260920.json" + ] + }, + "cleanup": { + "status": "accepted_within_scope", + "scope": "Accepted processes exited zero; original dispose completed and subsequent empty reports confirmed observed cleanup. Prefix retained.", + "evidence_refs": [ + "evidence/receipts/native-nautilus-v2-20260920.json" + ] + }, + "recovery": { + "status": "not_established", + "scope": "Crash-resume and broker-effect reconciliation remain untested.", + "evidence_refs": [] + } + }, + "baseline_applicability": { + "category": "supporting_workflow", + "scope": "This role supports quality, execution, state or observation. A direct token-saving claim needs a separately defined same-task comparison; installation alone has no token baseline.", + "retained_artifact_comparisons": 0, + "matched_lifetime_provider_baseline": "not_established", + "regression_policy": "Keep the cheaper adequate native path when a candidate expands tokens or fails required information/quality checks." + }, + "source_pin": "1b0a49d2792a9432a3aca3fcb617ce7a630d905e" } ], "remaining_boundaries": [ diff --git a/blueprints/us-equities/engine-nautilus/README.md b/blueprints/us-equities/engine-nautilus/README.md new file mode 100644 index 000000000..9d34f1026 --- /dev/null +++ b/blueprints/us-equities/engine-nautilus/README.md @@ -0,0 +1,27 @@ +# NautilusTrader v2 engine acceptance + +The user-selected destination is NautilusTrader **2.0.0rc5** with IBKR plus a separately validated Alpaca boundary. This isolated Linux acceptance uses the unchanged upstream synthetic EUR/USD quickstart. It does not replace the accepted LEAN comparison or qualify equity data, strategy performance, broker connectivity or paper execution. + +Upstream source: commit `1b0a49d2792a9432a3aca3fcb617ce7a630d905e`, `docs/getting_started/quickstart.py`; SHA256 `487e6807dedd1a38062638eb671f6110799451611819542bf0f0c10646cb2c53`. Official [installation](https://nautilustrader.io/docs/latest/getting_started/installation/) supports vanilla CPython 3.12–3.14. The accepted host used Python 3.12.3, uv 0.12.17, Bubblewrap 0.9.0 and glibc 2.39. + +Choose new owned paths outside existing environments: + +```sh +uv venv --python /usr/bin/python3.12 "$NAUTILUS_ENV" +uv pip install --python "$NAUTILUS_ENV/bin/python" --index-url https://pypi.org/simple --pre nautilus_trader==2.0.0rc5 numpy==2.5.3 pandas==3.0.6 +uv pip check --python "$NAUTILUS_ENV/bin/python" +curl -fsSL https://raw.githubusercontent.com/nautechsystems/nautilus_trader/1b0a49d2792a9432a3aca3fcb617ce7a630d905e/docs/getting_started/quickstart.py -o "$UPSTREAM_QUICKSTART" +sha256sum "$UPSTREAM_QUICKSTART" +``` + +The linked [observer](observe_quickstart.py) calls documented native report methods immediately before the original `engine.dispose()`, then allows upstream cleanup. It changes no strategy or generated input. Run it with the exact read-only mounts, cleared environment, isolated network and owned output directory recorded in the [native receipt](../../../evidence/receipts/native-nautilus-v2-20260920.json). Paths are portable placeholders. The upstream source and observer are mounted at `/input/quickstart.py` and `/input/observe_quickstart.py`; outputs go to `/out`. + +Two accepted fresh-process runs each returned 10,000 iterations, 1,804 events, 902 simulated orders/fills, 451 closed positions and 903 account rows. All 902 fills reconcile to ending cash, and aggregate realized PnL from 451 flat positions equals the cash change. Both economic reports match, and account CSV bytes match exactly. Fill/position CSVs contain generated UUIDs; comparison validates and normalizes only the explicitly named UUID fields, with every other field equal. One stable non-snapshot position ID is preserved. This is fixture reproducibility, not investment performance. + +Two initial attempts exited zero but collected empty reports after disposal, so they failed useful-result acceptance and remain retained. The corrected before-dispose observation captures the reports and verifies original cleanup. No credentials, host home or network interface beyond loopback were available in the Bubblewrap runs. No broker or model request was made. + +The next scope is retained equity replay and independent cash/order comparison. Broker-specific risk, ambiguous submissions, partial fills, cancels and restart reconciliation remain separate acceptance work. The [target catalog](../../../catalogs/us-equities/runtime-target.json) records current IBKR and Alpaca boundaries. + +The [native CI workflow](../../../.github/workflows/native-foundation-e2e.yml) performs a fresh Linux install, checks the downloaded engine wheel and source hashes, runs the unchanged example twice in mandatory network namespaces, and retains command outputs and failures. Its [independent verifier](../../../scripts/verify_nautilus_ci.py) checks exact distributions, isolation, cleanup and the report comparisons above. A green artifact qualifies that specific synthetic engine workflow; it does not qualify broker execution or a new PC's private accounts. + +The [fresh hosted run](https://github.com/seathatflowsinourveins/native-agent-stack/actions/runs/35531326386) passed all steps on September20. The coordinator rehashed all46 downloaded artifacts and reproduced the full verifier result. [Returned upstream outputs and hashes](../../../evidence/receipts/native-nautilus-ci-20260920.json) preserve the earlier runner-path failure and its scoped correction. Both CI economic hashes match the original Linux/WSL acceptance. diff --git a/blueprints/us-equities/engine-nautilus/observe_quickstart.py b/blueprints/us-equities/engine-nautilus/observe_quickstart.py new file mode 100644 index 000000000..020992649 --- /dev/null +++ b/blueprints/us-equities/engine-nautilus/observe_quickstart.py @@ -0,0 +1,45 @@ +"""Run unchanged upstream quickstart, then retain its public native reports.""" +import importlib.metadata +import json +from pathlib import Path +import runpy +import socket +import sys + +out = Path('/out') +isolation = {'network_namespace': str(Path('/proc/self/ns/net').readlink()), 'interfaces': socket.if_nameindex(), 'home_exists': Path('/home').exists(), 'environment_names': sorted(__import__('os').environ)} +(out / 'isolation.json').write_text(json.dumps(isolation, indent=2) + '\n') +source_lines = Path('/input/quickstart.py').read_text().splitlines() +dispose_lines = [n for n, line in enumerate(source_lines, 1) if line == 'engine.dispose()'] +assert len(dispose_lines) == 1 +captured = False +def observe(frame, event, arg): + global captured + if frame.f_code.co_filename != '/input/quickstart.py': + return None + if event == 'line' and frame.f_lineno == dispose_lines[0] and not captured: + captured = True + namespace = frame.f_globals + engine = namespace['engine'] + result = engine.get_result() + reports = { + 'account': engine.generate_account_report(venue=namespace['SIM']), + 'positions': engine.generate_positions_report(), + 'fills': engine.generate_order_fills_report(), + } + summary = {'version': importlib.metadata.version('nautilus_trader'), 'generated_bars': len(namespace['bars']), 'seed': 42, 'instrument': str(namespace['EURUSD'].id), 'native_result': {name: getattr(result, name) for name in ('iterations','total_events','total_orders','total_positions','backtest_start','backtest_end','stats_pnls','stats_general')}, 'reports': {}} + for name, report in reports.items(): + report.to_csv(out / (name + '.csv')) + summary['reports'][name] = {'rows': len(report), 'columns': [str(c) for c in report.columns], 'last_row': json.loads(report.tail(1).to_json(orient='records', date_format='iso'))} + (out / 'summary.json').write_text(json.dumps(summary, indent=2) + '\n') + assert result.iterations == 10000, 'Native engine did not process expected bars' + assert all(len(r) > 0 for r in reports.values()), 'Native report unexpectedly empty' + print(json.dumps(summary, sort_keys=True)) + return observe +sys.settrace(observe) +try: + namespace = runpy.run_path('/input/quickstart.py', run_name='__main__') +finally: + sys.settrace(None) +assert captured +(out / 'cleanup.json').write_text(json.dumps({'upstream_script_completed_after_dispose': True, 'account_rows_after_dispose': len(namespace['engine'].generate_account_report(venue=namespace['SIM']))}, indent=2)+'\n') diff --git a/blueprints/us-equities/north-star.md b/blueprints/us-equities/north-star.md index 94e28cdde..4be771d62 100644 --- a/blueprints/us-equities/north-star.md +++ b/blueprints/us-equities/north-star.md @@ -1,9 +1,13 @@ # North star: evidence-led US-equities automation -The target is a system that moves from reproducible research to an observable, -recoverable **Alpaca paper** runtime. The present deliverable is its native -research/backtest foundation and examined [grand catalog](../../catalogs/us-equities/README.md). -It is not a deployed broker service or a validated profitable strategy. +The selected destination is reproducible research and simulation leading to +observable, recoverable **IBKR and Alpaca paper** runtimes. The requested engine +target is **NautilusTrader 2.0.0rc5**. Its IBKR integration and the separate Alpaca +execution boundary need their own acceptance. LEAN remains an accepted historical +comparison engine; its results do not establish Nautilus or broker parity. +The [trading catalog](../../catalogs/us-equities/README.md) is separate from the +general [native harness foundation](../../catalogs/foundation/README.md). +This is not a deployed broker service or a validated profitable strategy. The current [architecture and next-role contract](architecture/README.md) records the latest research wave, official Alpaca limits, native SDK compatibility gap, @@ -19,9 +23,10 @@ simulation realism requirements and platform-specific acceptance. | Retrieval | QMD for scoped Markdown; Serena for symbols; SocratiCode → Nemotron → Qdrant for code | Local automatic code refresh proved; no financial corpus implied | | Optional routing | OmniRoute for deliberately selected, independently verified routes | Healthy; prior Opus/Qwen and new bounded Astra text proof; full native parity unproved | | Optional research orchestration | DeerFlow stable 2.0 reference; pinned development backend/ACP exploration | Embedded native ACP inference proved; full planner/UI hosting pending | -| Market/filing ingestion | Alpaca SDK plus SEC-sourced filings; alternative commercial feeds only with entitlement | SDK installed; financial ingestion and account access pending | +| Market/filing ingestion | Alpaca SDK plus SEC-sourced filings; alternative commercial feeds only with entitlement | Bounded authenticated AAPL SIP bars/actions and FB/META identity observations accepted; current Elite routing/throughput and a point-in-time market-wide corpus remain unverified | | Research data | Immutable raw snapshots, Parquet and DuckDB; exchange calendars | Native sample-event pipeline proved | -| Engine | LEAN native source build, one engine-owned paper adapter later | Bundled backtest proved; patched build and source-integrated adapter evidence recorded; credentialed runtime pending | +| Engine | Requested NautilusTrader 2.0.0rc5; retain LEAN as the historical comparison | Exact prerelease verified; each engine's native execution and data-equivalence results require separate receipts | +| Broker adapters | Native Nautilus IBKR adapter; Alpaca through a separately validated deterministic adapter | Upstream Nautilus integration list has no Alpaca adapter; socket/API availability is not broker execution acceptance | | Strategy research | Simple lagged baselines, then selected Qlib/statistical/portfolio tools | Catalogued; no strategy accepted or performance asserted | | Execution state | Separate deterministic order writer, durable journal and broker reconciliation | Design requirement, not implemented | | Hosting | On-demand native research and Dagu history service now; dedicated identity for paper later | No new cloud account or standing trading service | @@ -41,11 +46,12 @@ flowchart TB memory[Scoped ai-memory + code context] --> research research --> proposal[Source-linked research proposal] proposal --> review[Versioned strategy review + held-out evaluation] - review --> lean[LEAN deterministic replay] - lean --> acceptance[Paper acceptance requirements] + review --> replay[Nautilus deterministic replay / LEAN comparison] + replay --> acceptance[Broker-specific paper acceptance requirements] acceptance -. pending .-> execution[One deterministic order writer] execution <--> journal[Durable intents / orders / fills / reconciliation] - execution <--> alpaca[Alpaca paper] + execution <--> ibkr[IBKR paper / native TWS or Gateway] + execution <--> alpaca[Alpaca paper / separate adapter] risk[Independent numeric risk checks + kill switch] -. required .-> execution observe[Health / lag / fills / recovery / model usage] -. required .-> execution ``` @@ -98,6 +104,20 @@ broker, risk and recovery acceptance. Do not interpret a successful build as dep ## Paper runtime acceptance +The [current broker target and capability record](../../catalogs/us-equities/runtime-target.json) +pins the requested Nautilus release and current official broker documentation. +Nautilus' native IBKR socket adapter requires a signed-in TWS or IB Gateway, +selected market-data permissions and a distinct client ID. Its presence does not +qualify account access, paper orders, reconnect reconciliation or the Alpaca route. + +Alpaca Elite advertises **1,000 API calls per minute**, not a guaranteed trade or +fill rate. Trading requests and historical market-data throughput are different +limits. Current Algo Trader Plus documentation lists 10,000 historical calls per +minute and equity history since 2016; feed coverage, subscriptions and account +entitlement still matter. The existing historical-data GET receipts do not prove +Elite activation or every data entitlement. [Elite terms](https://alpaca.markets/elite), +[market-data plans](https://docs.alpaca.markets/us/docs/about-market-data-api). + The future paper service needs explicit numeric limits, an allowed universe, session/extended-hours policy and data-feed entitlement. Maintain one order writer per account/strategy scope. Persist intent and a stable client order ID before diff --git a/catalogs/README.md b/catalogs/README.md new file mode 100644 index 000000000..b856e6d22 --- /dev/null +++ b/catalogs/README.md @@ -0,0 +1,10 @@ +# Two maintained catalogs + +| Catalog | Purpose | Start here | +| --- | --- | --- | +| Foundation | Native Codex/Claude runtimes, rules, skills, workers, isolation, retrieval, memory, research, efficiency, evaluation, CI, scheduling, hosting, recovery and observation | [Foundation guide](foundation/README.md) · [Layer manifest](foundation/manifest.json) · [Harness defaults](../docs/harness-defaults.md) | +| Trading architecture | Reproducible historical/simulation research and separate IBKR/NautilusTrader and Alpaca paper execution boundaries | [US-equities guide](us-equities/README.md) · [North star](../blueprints/us-equities/north-star.md) | + +Both catalogs reference shared component pins, upstream source reviews and scoped execution receipts. General engineering does not inherit broker prerequisites. Trading work reuses the foundation and adds data, strategy, risk and broker-specific acceptance. + +The broad repository decision union remains at [its existing path](us-equities/decision-index.json) for compatibility; it contains shared research discovery, not just trading adoption. Curated lists and stars are discovery sources. Explicit catalog decisions establish selected capabilities, and execution receipts establish only the workflows they actually measured. diff --git a/catalogs/foundation/README.md b/catalogs/foundation/README.md new file mode 100644 index 000000000..476f0bff7 --- /dev/null +++ b/catalogs/foundation/README.md @@ -0,0 +1,95 @@ +# FOUNDATION capability catalog + +FOUNDATION selects the general native workflow: clients, skills, owned workers, +source retrieval, memory, research, quality, applications, observation and recovery. +Start with the layer needed for the task in [manifest.json](manifest.json), then +read its scoped capability decision in [decisions.json](decisions.json). A default +is a selected way to do a task, not permission to install or activate every tool. + +The catalog references 61 selected components through 41 capability decisions. It cites 67 relevant registered +receipts from the current 88-receipt inventory. These are coverage counts, not a +score of complete installation, execution or lifecycle acceptance. + +| Layer | Purpose | +| --- | --- | +| Native clients | Signed-in native coding/research tasks and actual process activation | +| Instructions and skills | Short project rules and task-specific procedures | +| Workers | Bounded delegation, owned paths and independent acceptance | +| Isolation | Worktree ownership and selected enforced OS restrictions | +| Code navigation | Exact symbols, structural patterns and scoped source retrieval | +| Document retrieval | Named lexical corpora and supported document ingestion | +| Semantic RAG | Project-scoped conceptual code retrieval and local embeddings | +| Durable memory | Approved cross-client decisions, continuity and scoped restore | +| Web research | Selected browser, literature and current-source operations | +| Token efficiency | Adequate context representations and honest usage accounting | +| Quality and evaluation | Behavioral oracles, negative cases and independent review | +| CI and supply chain | Publication checks, security controls and dependency identity | +| Scheduling and supervision | Owned process deadlines and checkpointed job continuation | +| Hosting and services | Typed local applications, databases and selected MCP services | +| Recovery and portability | Exact restore inputs, session continuity and lifecycle limits | +| Observation and inference | Bounded telemetry, usage and optional inference trials | + +Each layer records its purpose, selected approach, activation condition, lifecycle +scope and next actionable gap. Decisions join actual `component_ids` and +`evidence_ids`; they retain an explicit `evidence_scope`, limitations and activation +rule. `accepted_within_scope` describes the named capability only. Partial, +source-review and pending decisions remain distinguishable from acceptance. + +Pins remain in [the stack manifest](../../manifests/stack.json). Original receipt +claims, evidence classes, paths and limitations remain in +[the evidence manifest](../../manifests/evidence.json). Lifecycle `stage_refs` point +to the exact status in [the component matrix](../../blueprints/token-native-focus/saturation-audit.json); +they do not duplicate its commands, stage scope or receipt content. Read those +canonical details before reusing acceptance. Unlisted stages and the explicit +`lifecycle.unknown` field do not become successful by implication. + +The [broad decision index](../us-equities/decision-index.json) remains the shared +research inventory at its existing path. Discovery lists, candidates and older +[foundation/memory](../us-equities/foundation-memory.json) or +[agent/operations](../us-equities/agents-operations.json) source reviews remain +available. Their directory placement and reviewed source pins do not supersede +the currently selected component pin or qualify an entire repository. + +The manifest explicitly leaves NautilusTrader, LEAN, Alpaca, skfolio, EdgarTools and the currently +financial-only DuckDB/pandas claims in the [US-equities domain](../us-equities/README.md). +Some domain-located fixtures demonstrate reusable operations such as process-tree +termination, dependency inventory or state restore. A FOUNDATION decision cites +only that operation; it does not import strategy, market-data, broker or trading +acceptance. Tavily has a [native CLI receipt](../../evidence/receipts/native-tavily-cli-20260920.json) +for upstream installation, Search/Extract and fresh eight-skill discovery. It retains +the initial Desktop probe failure and temporary-state recovery; it does not claim +that every skill ran in a model turn or that the current Desktop registry hot-reloaded. + +The three current priorities are: + +1. Keep general capabilities and financial-domain decisions separate, with + explicit claim scope. This catalog addresses that structure; maintain the + references when evidence changes rather than migrating the broad inventory. +2. Complete crash descendant containment after the recorded same-child cancellation + and crash continuation. The new fixture retained one checkpoint and final effect, + but needed explicit supervisor cleanup for a surviving wait. +3. Qualify independent off-host restore with separately available key recovery, + and scheduled-service acceptance after reboot. Same-host restore and ordinary + stop/start do not close these gaps. + +Use [the convergence guide](../../docs/convergence-architecture.md) for the work +sequence and [the lifecycle guide](../../adoption/lifecycle.md) for selected native +operations. Keep failed attempts, unknown usage and new-host limits intact. +The newer vLLM startup failure, failed gateway inference/compression attempts, +unverified live HUD and TOON expansion remain counterexamples, not successes. + +Validate references without installing tools, calling providers or replaying +native acceptance: + +```sh +python3 scripts/validate_foundation.py --root . --json +python3 -m unittest tests.test_foundation_catalog +``` + +The validator checks the 16 layers, unique identities, component/evidence joins, +source paths, explicit scope/limitations, canonical lifecycle statuses, candidate +separation and scoped supersession. It rejects copied pin/receipt fields. A later +decision may supersede only an earlier decision for the same capability and +component scope, retaining the old record with a reason and scope. Structural +validation cannot certify the truth or adequacy of a prose claim; review the cited +receipt and its limitations before changing an adoption decision. diff --git a/catalogs/foundation/decisions.json b/catalogs/foundation/decisions.json new file mode 100644 index 000000000..d4c66d326 --- /dev/null +++ b/catalogs/foundation/decisions.json @@ -0,0 +1,2241 @@ +{ + "schema_version": 1, + "checked_at": "2026-09-20", + "scope": "Capability-specific general FOUNDATION selection; original pins, full receipt claims and per-component lifecycle stages remain canonical. Shared research and financial examples are not blanket adoption.", + "decisions": [ + { + "id": "native-source-tasks", + "capability": "Use native client tools to retrieve exact project evidence", + "capability_key": "native-source-tasks", + "checked_at": "2026-09-20", + "layer_ids": [ + "native-clients" + ], + "selection": "default", + "review_status": "accepted_within_scope", + "activation": "Use the native client and selected project tools for an actual coding or research task.", + "component_ids": [ + "codex", + "claude-code" + ], + "candidate": null, + "evidence_ids": [ + "foundation-native-20260920", + "native-token-focus-clients-20260920", + "native-token-stack-final-20260920" + ], + "evidence_scope": "Both signed-in native clients completed the bounded source-retrieval tasks; the final receipt also retains scoped continuation and observation results.", + "limitations": [ + "Earlier refused MCP calls, Claude format failures and source-host account limits remain recorded.", + "Successful retrieval does not qualify every installed tool, all prompts, another PC or complete causal token savings." + ], + "source_paths": [ + "docs/foundation-stack.md", + "blueprints/convergence-practice/README.md" + ], + "next_gap": "Verify changed native process/tool activation on the intended host; retain failed attempts.", + "lifecycle": { + "source_path": "blueprints/token-native-focus/saturation-audit.json", + "scope": "Only the listed canonical stages and their original host/operation scopes apply. Both signed-in native clients completed the bounded source-retrieval tasks; the final receipt also retains scoped continuation and observation results.", + "unknown": "Unlisted or unestablished stages are not implied by this capability decision. Verify changed native process/tool activation on the intended host; retain failed attempts.", + "stage_refs": [ + { + "component_id": "codex", + "stage": "use", + "status": "accepted_within_scope" + }, + { + "component_id": "claude-code", + "stage": "use", + "status": "accepted_within_scope" + } + ] + }, + "supersedes": [] + }, + { + "id": "native-process-defaults", + "capability": "Resolve persistent native command and MCP environments", + "capability_key": "native-process-defaults", + "checked_at": "2026-09-20", + "layer_ids": [ + "native-clients", + "instructions-skills" + ], + "selection": "default", + "review_status": "accepted_within_scope", + "activation": "Reuse accepted persistent settings and inspect a fresh native process when environment inputs change.", + "component_ids": [ + "codex", + "claude-code", + "context-mode", + "rtk", + "qmd", + "ai-memory" + ], + "candidate": null, + "evidence_ids": [ + "codex-session-environment-20260920", + "codex-desktop-live-20260920", + "native-session-defaults-20260920", + "native-harness-defaults-20260920" + ], + "evidence_scope": "Fresh native processes resolved selected commands/MCP servers and Claude startup hooks; restarted Desktop source retrieval has its own dated receipt.", + "limitations": [ + "Configuration presence does not prove an already-running task hot-reloaded it.", + "The Linux/WSL and Desktop process/configuration boundaries remain distinct." + ], + "source_paths": [ + "docs/convergence-architecture.md", + "docs/harness-defaults.md" + ], + "next_gap": "Collect the specific new-host or changed-session activation evidence; do not copy account stores.", + "lifecycle": { + "source_path": "blueprints/token-native-focus/saturation-audit.json", + "scope": "Only the listed canonical stages and their original host/operation scopes apply. Fresh native processes resolved selected commands/MCP servers and Claude startup hooks; restarted Desktop source retrieval has its own dated receipt.", + "unknown": "Unlisted or unestablished stages are not implied by this capability decision. Collect the specific new-host or changed-session activation evidence; do not copy account stores.", + "stage_refs": [ + { + "component_id": "codex", + "stage": "use", + "status": "accepted_within_scope" + }, + { + "component_id": "claude-code", + "stage": "use", + "status": "accepted_within_scope" + }, + { + "component_id": "context-mode", + "stage": "use", + "status": "accepted_within_scope" + }, + { + "component_id": "rtk", + "stage": "use", + "status": "accepted_within_scope" + }, + { + "component_id": "qmd", + "stage": "use", + "status": "accepted_within_scope" + }, + { + "component_id": "ai-memory", + "stage": "use", + "status": "accepted_within_scope" + } + ] + }, + "supersedes": [] + }, + { + "id": "on-demand-guidance", + "capability": "Load selected community procedures only for the current operation", + "capability_key": "on-demand-guidance", + "checked_at": "2026-09-20", + "layer_ids": [ + "instructions-skills" + ], + "selection": "optional", + "review_status": "source_review", + "activation": "Load the named skill only when its procedure helps the authorized task.", + "component_ids": [ + "affaan-m/ECC", + "davila7/claude-code-templates", + "shanraisshan/claude-code-best-practice" + ], + "candidate": null, + "evidence_ids": [ + "component-history", + "token-practice-coverage-20260920" + ], + "evidence_scope": "Selected guidance/source records are retained; they have no executable installation or process lifecycle.", + "limitations": [ + "Source selection is not execution acceptance and does not activate a complete skills catalog." + ], + "source_paths": [ + "docs/convergence-architecture.md", + "adoption/lifecycle.md" + ], + "next_gap": "Review a newly selected skill against current project rules before activation.", + "lifecycle": { + "source_path": "blueprints/token-native-focus/saturation-audit.json", + "scope": "Only the listed canonical stages and their original host/operation scopes apply. Selected guidance/source records are retained; they have no executable installation or process lifecycle.", + "unknown": "Unlisted or unestablished stages are not implied by this capability decision. Review a newly selected skill against current project rules before activation.", + "stage_refs": [ + { + "component_id": "affaan-m/ECC", + "stage": "use", + "status": "not_applicable" + }, + { + "component_id": "davila7/claude-code-templates", + "stage": "use", + "status": "not_applicable" + }, + { + "component_id": "shanraisshan/claude-code-best-practice", + "stage": "use", + "status": "not_applicable" + } + ] + }, + "supersedes": [] + }, + { + "id": "portable-skill-reference", + "capability": "Validate and render a selected portable skill", + "capability_key": "portable-skill-reference", + "checked_at": "2026-09-20", + "layer_ids": [ + "instructions-skills", + "quality-evaluation" + ], + "selection": "conditional", + "review_status": "accepted_within_scope", + "activation": "Run the reference validator for a portable-format compatibility question.", + "component_ids": [ + "skills-ref" + ], + "candidate": null, + "evidence_ids": [ + "upstream-native-tools-20260920" + ], + "evidence_scope": "The native reference validator accepted and rendered one selected skill.", + "limitations": [ + "The reference format does not define every Codex or Claude extension." + ], + "source_paths": [ + "docs/convergence-architecture.md", + "adoption/lifecycle.md" + ], + "next_gap": "Check client discovery/extension behavior separately on the target client.", + "lifecycle": { + "source_path": "blueprints/token-native-focus/saturation-audit.json", + "scope": "Only the listed canonical stages and their original host/operation scopes apply. The native reference validator accepted and rendered one selected skill.", + "unknown": "Unlisted or unestablished stages are not implied by this capability decision. Check client discovery/extension behavior separately on the target client.", + "stage_refs": [ + { + "component_id": "skills-ref", + "stage": "use", + "status": "accepted_within_scope" + } + ] + }, + "supersedes": [] + }, + { + "id": "owned-native-child", + "capability": "Implement a bounded repair through an owned native child", + "capability_key": "owned-native-child", + "checked_at": "2026-09-20", + "layer_ids": [ + "workers" + ], + "selection": "default", + "review_status": "accepted_within_scope", + "activation": "Dispatch independent bounded work with base commit, owned paths and acceptance; the coordinator integrates.", + "component_ids": [ + "claude-code" + ], + "candidate": null, + "evidence_ids": [ + "native-claude-child-patch-20260920" + ], + "evidence_scope": "One foreground native Opus child repaired the owned file; twelve frozen tests and independent exhaustive checks passed.", + "limitations": [ + "One successful child task does not establish arbitrary delegation quality, crash recovery or total workflow efficiency." + ], + "source_paths": [ + "blueprints/convergence-practice/native-worker/README.md" + ], + "next_gap": "Exercise abrupt worker failure and effect-aware same-task resume.", + "lifecycle": { + "source_path": "blueprints/token-native-focus/saturation-audit.json", + "scope": "Only the listed canonical stages and their original host/operation scopes apply. One foreground native Opus child repaired the owned file; twelve frozen tests and independent exhaustive checks passed.", + "unknown": "Unlisted or unestablished stages are not implied by this capability decision. Exercise abrupt worker failure and effect-aware same-task resume.", + "stage_refs": [ + { + "component_id": "claude-code", + "stage": "use", + "status": "accepted_within_scope" + } + ] + }, + "supersedes": [] + }, + { + "id": "companion-backend", + "capability": "Use the scoped native companion backend when explicitly selected", + "capability_key": "companion-backend", + "checked_at": "2026-09-20", + "layer_ids": [ + "workers" + ], + "selection": "optional", + "review_status": "partial_acceptance", + "activation": "Use the selected companion only for a concrete cross-client task with native readiness checked.", + "component_ids": [ + "codex-for-claude", + "codex" + ], + "candidate": null, + "evidence_ids": [ + "token-practice-gap-followup-20260920" + ], + "evidence_scope": "One read-only native bridge backend task passed.", + "limitations": [ + "The backend result is narrower than complete plugin integration; native account allowance and interactive activation remain separate." + ], + "source_paths": [ + "docs/convergence-architecture.md", + "adoption/lifecycle.md" + ], + "next_gap": "Qualify the intended outer plugin invocation before calling full integration accepted.", + "lifecycle": { + "source_path": "blueprints/token-native-focus/saturation-audit.json", + "scope": "Only the listed canonical stages and their original host/operation scopes apply. One read-only native bridge backend task passed.", + "unknown": "Unlisted or unestablished stages are not implied by this capability decision. Qualify the intended outer plugin invocation before calling full integration accepted.", + "stage_refs": [ + { + "component_id": "codex-for-claude", + "stage": "use", + "status": "partial_acceptance" + }, + { + "component_id": "codex", + "stage": "use", + "status": "accepted_within_scope" + } + ] + }, + "supersedes": [] + }, + { + "id": "dependency-task-queue", + "capability": "Persist selected project claims and task dependencies", + "capability_key": "dependency-task-queue", + "checked_at": "2026-09-20", + "layer_ids": [ + "workers", + "scheduling-supervision" + ], + "selection": "conditional", + "review_status": "accepted_within_scope", + "activation": "Use one explicitly scoped queue when dependencies improve coordination.", + "component_ids": [ + "beads" + ], + "candidate": null, + "evidence_ids": [ + "upstream-native-tools-20260920" + ], + "evidence_scope": "Native Beads persisted task claims and dependency transitions in the selected fixture.", + "limitations": [ + "A queue is not worker cancellation, distributed lease correctness or restored task-effect acceptance." + ], + "source_paths": [ + "docs/convergence-architecture.md", + "adoption/lifecycle.md" + ], + "next_gap": "Test the selected queue restart/recovery boundary before unattended reliance.", + "lifecycle": { + "source_path": "blueprints/token-native-focus/saturation-audit.json", + "scope": "Only the listed canonical stages and their original host/operation scopes apply. Native Beads persisted task claims and dependency transitions in the selected fixture.", + "unknown": "Unlisted or unestablished stages are not implied by this capability decision. Test the selected queue restart/recovery boundary before unattended reliance.", + "stage_refs": [ + { + "component_id": "beads", + "stage": "use", + "status": "accepted_within_scope" + }, + { + "component_id": "beads", + "stage": "persistence", + "status": "accepted_within_scope" + }, + { + "component_id": "beads", + "stage": "recovery", + "status": "not_established" + } + ] + }, + "supersedes": [] + }, + { + "id": "owned-worktrees", + "capability": "Create and retire bounded native Git worktrees", + "capability_key": "owned-worktrees", + "checked_at": "2026-09-20", + "layer_ids": [ + "workers", + "isolation" + ], + "selection": "default", + "review_status": "accepted_within_scope", + "activation": "Give each writer an owned branch/worktree and exact base; retain dirty work until reconciled.", + "component_ids": [ + "worktrunk" + ], + "candidate": null, + "evidence_ids": [ + "worktrunk-list", + "token-native-retained-functional-20260920", + "velanext-native-quality-tools-20260920" + ], + "evidence_scope": "Native listing and disposable create/list/remove passed; dirty removal was refused without loss.", + "limitations": [ + "Worktrees isolate edits, not permissions, accounts, global settings or shared services." + ], + "source_paths": [ + "docs/convergence-architecture.md", + "adoption/lifecycle.md" + ], + "next_gap": "Prove any required crash cleanup without deleting unrelated or dirty state.", + "lifecycle": { + "source_path": "blueprints/token-native-focus/saturation-audit.json", + "scope": "Only the listed canonical stages and their original host/operation scopes apply. Native listing and disposable create/list/remove passed; dirty removal was refused without loss.", + "unknown": "Unlisted or unestablished stages are not implied by this capability decision. Prove any required crash cleanup without deleting unrelated or dirty state.", + "stage_refs": [ + { + "component_id": "worktrunk", + "stage": "use", + "status": "accepted_within_scope" + } + ] + }, + "supersedes": [] + }, + { + "id": "scoped-os-isolation", + "capability": "Enforce the selected filesystem and HTTP network boundaries", + "capability_key": "scoped-os-isolation", + "checked_at": "2026-09-20", + "layer_ids": [ + "isolation" + ], + "selection": "conditional", + "review_status": "accepted_within_scope", + "activation": "Apply native restrictions only to the owned command and policy required by the task.", + "component_ids": [ + "sandbox-runtime" + ], + "candidate": null, + "evidence_ids": [ + "runtime-tools", + "native-sandbox-network-20260920" + ], + "evidence_scope": "Permitted/protected filesystem checks and loopback allow/deny HTTP fixtures passed.", + "limitations": [ + "This is not a general escape audit or TLS/SOCKS/network-stack qualification." + ], + "source_paths": [ + "docs/convergence-architecture.md", + "adoption/lifecycle.md" + ], + "next_gap": "Qualify a new protocol/platform boundary if the task actually needs it.", + "lifecycle": { + "source_path": "blueprints/token-native-focus/saturation-audit.json", + "scope": "Only the listed canonical stages and their original host/operation scopes apply. Permitted/protected filesystem checks and loopback allow/deny HTTP fixtures passed.", + "unknown": "Unlisted or unestablished stages are not implied by this capability decision. Qualify a new protocol/platform boundary if the task actually needs it.", + "stage_refs": [ + { + "component_id": "sandbox-runtime", + "stage": "use", + "status": "accepted_within_scope" + } + ] + }, + "supersedes": [] + }, + { + "id": "language-symbols", + "capability": "Retrieve exact symbols and references in configured languages", + "capability_key": "language-symbols", + "checked_at": "2026-09-20", + "layer_ids": [ + "code-navigation" + ], + "selection": "default", + "review_status": "accepted_within_scope", + "activation": "Use symbols/references for known identifiers and inspect original code before editing.", + "component_ids": [ + "serena" + ], + "candidate": null, + "evidence_ids": [ + "native-context-memory", + "foundation-native-20260920" + ], + "evidence_scope": "Serena native symbol operations passed; the foundation wave adds eight fresh Python/CJS checks after language coverage repair.", + "limitations": [ + "A configured Bash server or one passing extension cannot establish every language server." + ], + "source_paths": [ + "docs/foundation-stack.md" + ], + "next_gap": "Run the relevant extension/language operation for a newly adopted project.", + "lifecycle": { + "source_path": "blueprints/token-native-focus/saturation-audit.json", + "scope": "Only the listed canonical stages and their original host/operation scopes apply. Serena native symbol operations passed; the foundation wave adds eight fresh Python/CJS checks after language coverage repair.", + "unknown": "Unlisted or unestablished stages are not implied by this capability decision. Run the relevant extension/language operation for a newly adopted project.", + "stage_refs": [ + { + "component_id": "serena", + "stage": "use", + "status": "accepted_within_scope" + } + ] + }, + "supersedes": [] + }, + { + "id": "structural-code-lane", + "capability": "Search syntax and inspect a selected static call graph", + "capability_key": "structural-code-lane", + "checked_at": "2026-09-20", + "layer_ids": [ + "code-navigation" + ], + "selection": "conditional", + "review_status": "accepted_within_scope", + "activation": "Choose exact structural search or the graph lane when it answers the actual code question.", + "component_ids": [ + "ast-grep", + "codebase-memory-mcp" + ], + "candidate": null, + "evidence_ids": [ + "portable-cli-artifacts", + "desktop-cli-workflows", + "native-cli-gaps" + ], + "evidence_scope": "Native structural-source fixtures and selected static graph search/trace passed.", + "limitations": [ + "The earlier Codex attempt in native-cli-gaps was quota-blocked; later Desktop acceptance does not rewrite that attempt.", + "Static graph coverage is language/project-specific and does not establish runtime call behavior." + ], + "source_paths": [ + "docs/convergence-architecture.md", + "adoption/lifecycle.md" + ], + "next_gap": "Check target-language and changed-source coverage rather than assuming a universal graph.", + "lifecycle": { + "source_path": "blueprints/token-native-focus/saturation-audit.json", + "scope": "Only the listed canonical stages and their original host/operation scopes apply. Native structural-source fixtures and selected static graph search/trace passed.", + "unknown": "Unlisted or unestablished stages are not implied by this capability decision. Check target-language and changed-source coverage rather than assuming a universal graph.", + "stage_refs": [ + { + "component_id": "ast-grep", + "stage": "use", + "status": "accepted_within_scope" + }, + { + "component_id": "codebase-memory-mcp", + "stage": "use", + "status": "accepted_within_scope" + } + ] + }, + "supersedes": [] + }, + { + "id": "scoped-symbol-index", + "capability": "Retrieve exact implementation from a scoped symbol index", + "capability_key": "scoped-symbol-index", + "checked_at": "2026-09-20", + "layer_ids": [ + "code-navigation", + "token-efficiency" + ], + "selection": "conditional", + "review_status": "accepted_within_scope", + "activation": "Use indexed discovery when it replaces broad reads; use the cheaper known-source read when adequate.", + "component_ids": [ + "jcodemunch-mcp" + ], + "candidate": null, + "evidence_ids": [ + "native-jcodemunch-20260920", + "native-token-focus-clients-20260920", + "native-token-clean-prefix-20260920" + ], + "evidence_scope": "Exact function retrieval and bounded native client calls passed; isolated install/restart/uninstall has its own receipt.", + "limitations": [ + "The complete search/source sequence was smaller than a whole file and larger than a known focused read.", + "Native estimated tokens avoided are not exact causal provider savings." + ], + "source_paths": [ + "docs/foundation-stack.md", + "adoption/lifecycle.md" + ], + "next_gap": "Verify symbol updates/deletions or recovery only after a relevant index/input change.", + "lifecycle": { + "source_path": "blueprints/token-native-focus/saturation-audit.json", + "scope": "Only the listed canonical stages and their original host/operation scopes apply. Exact function retrieval and bounded native client calls passed; isolated install/restart/uninstall has its own receipt.", + "unknown": "Unlisted or unestablished stages are not implied by this capability decision. Verify symbol updates/deletions or recovery only after a relevant index/input change.", + "stage_refs": [ + { + "component_id": "jcodemunch-mcp", + "stage": "use", + "status": "accepted_within_scope" + }, + { + "component_id": "jcodemunch-mcp", + "stage": "install", + "status": "accepted_within_scope" + }, + { + "component_id": "jcodemunch-mcp", + "stage": "restart", + "status": "accepted_within_scope" + }, + { + "component_id": "jcodemunch-mcp", + "stage": "cleanup", + "status": "accepted_within_scope" + }, + { + "component_id": "jcodemunch-mcp", + "stage": "recovery", + "status": "not_established" + } + ] + }, + "supersedes": [] + }, + { + "id": "scoped-document-bm25", + "capability": "Search and read a named local Markdown corpus", + "capability_key": "scoped-document-bm25", + "checked_at": "2026-09-20", + "layer_ids": [ + "document-retrieval" + ], + "selection": "default", + "review_status": "accepted_within_scope", + "activation": "Name the index/collection, refresh changed files, search then get the selected source.", + "component_ids": [ + "qmd" + ], + "candidate": null, + "evidence_ids": [ + "qmd-bm25-retrieval-20260919", + "desktop-cli-workflows", + "foundation-native-20260920" + ], + "evidence_scope": "Native scoped QMD search/get passed; the fixed twelve-query benchmark returned the intended source in eight top-three results.", + "limitations": [ + "All four benchmark misses remain; exact source retrieval on a fixture does not establish arbitrary corpus recall.", + "The selected BM25 lane needs no downloaded embedding model." + ], + "source_paths": [ + "blueprints/us-equities/retrieval-evaluation/README.md", + "docs/foundation-stack.md" + ], + "next_gap": "Evaluate positive and absent queries for a new corpus.", + "lifecycle": { + "source_path": "blueprints/token-native-focus/saturation-audit.json", + "scope": "Only the listed canonical stages and their original host/operation scopes apply. Native scoped QMD search/get passed; the fixed twelve-query benchmark returned the intended source in eight top-three results.", + "unknown": "Unlisted or unestablished stages are not implied by this capability decision. Evaluate positive and absent queries for a new corpus.", + "stage_refs": [ + { + "component_id": "qmd", + "stage": "use", + "status": "accepted_within_scope" + } + ] + }, + "supersedes": [] + }, + { + "id": "source-document-conversion", + "capability": "Convert supported local documents into bounded source evidence", + "capability_key": "source-document-conversion", + "checked_at": "2026-09-20", + "layer_ids": [ + "document-retrieval" + ], + "selection": "conditional", + "review_status": "accepted_within_scope", + "activation": "Select the supported input format and retain document/page/hash boundaries.", + "component_ids": [ + "markitdown", + "poppler" + ], + "candidate": null, + "evidence_ids": [ + "portable-cli-artifacts", + "mac-native-document-ingestion-20260920", + "wsl-document-ingestion-20260920" + ], + "evidence_scope": "Selected HTML conversion passed; native Poppler preserved three designed PDF pages, twenty-four cells and twelve positive/absent queries on Mac and WSL.", + "limitations": [ + "Base MarkItDown HTML acceptance does not imply optional PDF/Office extras.", + "The designed born-digital PDF fixture does not qualify OCR, arbitrary layouts or semantic retrieval." + ], + "source_paths": [ + "blueprints/convergence-practice/document-ingestion/README.md", + "blueprints/convergence-practice/wsl-document-ingestion/README.md" + ], + "next_gap": "Freeze a representative layout/OCR protocol before extending the claim.", + "lifecycle": { + "source_path": "blueprints/token-native-focus/saturation-audit.json", + "scope": "Only the listed canonical stages and their original host/operation scopes apply. Selected HTML conversion passed; native Poppler preserved three designed PDF pages, twenty-four cells and twelve positive/absent queries on Mac and WSL.", + "unknown": "Unlisted or unestablished stages are not implied by this capability decision. Freeze a representative layout/OCR protocol before extending the claim.", + "stage_refs": [ + { + "component_id": "markitdown", + "stage": "use", + "status": "accepted_within_scope" + }, + { + "component_id": "poppler", + "stage": "use", + "status": "accepted_within_scope" + } + ] + }, + "supersedes": [] + }, + { + "id": "curated-developer-docs", + "capability": "Retrieve selected curated developer documentation", + "capability_key": "curated-developer-docs", + "checked_at": "2026-09-20", + "layer_ids": [ + "document-retrieval" + ], + "selection": "conditional", + "review_status": "accepted_within_scope", + "activation": "Use for a named documentation gap and inspect the returned primary source.", + "component_ids": [ + "context-hub" + ], + "candidate": null, + "evidence_ids": [ + "token-native-retained-functional-20260920" + ], + "evidence_scope": "Retained native Context Hub search/retrieval supports its selected developer-document operation.", + "limitations": [ + "This is not a claim that all external documentation is current or indexed." + ], + "source_paths": [ + "docs/convergence-architecture.md", + "adoption/lifecycle.md" + ], + "next_gap": "Recheck the relevant source revision when its API or requirement changes.", + "lifecycle": { + "source_path": "blueprints/token-native-focus/saturation-audit.json", + "scope": "Only the listed canonical stages and their original host/operation scopes apply. Retained native Context Hub search/retrieval supports its selected developer-document operation.", + "unknown": "Unlisted or unestablished stages are not implied by this capability decision. Recheck the relevant source revision when its API or requirement changes.", + "stage_refs": [ + { + "component_id": "context-hub", + "stage": "use", + "status": "accepted_within_scope" + } + ] + }, + "supersedes": [] + }, + { + "id": "project-semantic-index", + "capability": "Maintain conceptual code retrieval for one project", + "capability_key": "project-semantic-index", + "checked_at": "2026-09-20", + "layer_ids": [ + "semantic-rag", + "code-navigation" + ], + "selection": "conditional", + "review_status": "accepted_within_scope", + "activation": "Adopt one explicit project index when conceptual search helps; keep exact identifiers in focused source tools.", + "component_ids": [ + "socraticode", + "qdrant" + ], + "candidate": null, + "evidence_ids": [ + "native-rag", + "desktop-direct-rag", + "foundation-native-20260920" + ], + "evidence_scope": "Correct project code and automatic add/update/delete persisted in the selected local vector store; direct Desktop retrieval is separately recorded.", + "limitations": [ + "Another project/index and full-service restart/recovery need their own scope." + ], + "source_paths": [ + "docs/foundation-stack.md" + ], + "next_gap": "Verify changed-project freshness before relying on retrieved code.", + "lifecycle": { + "source_path": "blueprints/token-native-focus/saturation-audit.json", + "scope": "Only the listed canonical stages and their original host/operation scopes apply. Correct project code and automatic add/update/delete persisted in the selected local vector store; direct Desktop retrieval is separately recorded.", + "unknown": "Unlisted or unestablished stages are not implied by this capability decision. Verify changed-project freshness before relying on retrieved code.", + "stage_refs": [ + { + "component_id": "socraticode", + "stage": "use", + "status": "accepted_within_scope" + }, + { + "component_id": "socraticode", + "stage": "persistence", + "status": "accepted_within_scope" + }, + { + "component_id": "socraticode", + "stage": "recovery", + "status": "not_established" + }, + { + "component_id": "qdrant", + "stage": "use", + "status": "accepted_within_scope" + }, + { + "component_id": "qdrant", + "stage": "persistence", + "status": "accepted_within_scope" + }, + { + "component_id": "qdrant", + "stage": "recovery", + "status": "accepted_within_scope" + } + ] + }, + "supersedes": [] + }, + { + "id": "local-embedding-runtime", + "capability": "Serve accepted local embeddings with pinned model inputs", + "capability_key": "local-embedding-runtime", + "checked_at": "2026-09-20", + "layer_ids": [ + "semantic-rag", + "observation-inference" + ], + "selection": "conditional", + "review_status": "accepted_within_scope", + "activation": "Retain the compatible runtime/model revision and native GPU evidence.", + "component_ids": [ + "vllm", + "huggingface-hub-native" + ], + "candidate": null, + "evidence_ids": [ + "native-rag", + "vllm-compatibility", + "foundation-native-20260920" + ], + "evidence_scope": "Native local embedding/model retrieval supports the accepted runtime; a later runtime installed but failed GPU startup and the accepted environment was restored.", + "limitations": [ + "The newer WSL startup failure remains failed; release availability is not runtime acceptance.", + "Model downloads and embedding acceptance do not qualify local text-generation quality." + ], + "source_paths": [ + "docs/foundation-stack.md" + ], + "next_gap": "Test a changed GPU/runtime only for an actual compatibility need.", + "lifecycle": { + "source_path": "blueprints/token-native-focus/saturation-audit.json", + "scope": "Only the listed canonical stages and their original host/operation scopes apply. Native local embedding/model retrieval supports the accepted runtime; a later runtime installed but failed GPU startup and the accepted environment was restored.", + "unknown": "Unlisted or unestablished stages are not implied by this capability decision. Test a changed GPU/runtime only for an actual compatibility need.", + "stage_refs": [ + { + "component_id": "vllm", + "stage": "use", + "status": "accepted_within_scope" + }, + { + "component_id": "huggingface-hub-native", + "stage": "use", + "status": "accepted_within_scope" + } + ] + }, + "supersedes": [] + }, + { + "id": "scoped-memory-lifecycle", + "capability": "Persist and retrieve approved cross-client project memory", + "capability_key": "scoped-memory-lifecycle", + "checked_at": "2026-09-20", + "layer_ids": [ + "durable-memory", + "recovery-portability" + ], + "selection": "default", + "review_status": "accepted_within_scope", + "activation": "Use one explicitly scoped memory of record; durable writes require explicit intent.", + "component_ids": [ + "ai-memory" + ], + "candidate": null, + "evidence_ids": [ + "native-memory", + "native-memory-lifecycle-20260919", + "native-ai-memory-maintenance-20260920", + "mac-memory-patch-20260920", + "wsl-memory-maintenance-20260920" + ], + "evidence_scope": "Scoped native retrieval, lifecycle negatives, migration, restart, upstream backup and empty-target restore have distinct accepted receipts.", + "limitations": [ + "Lifecycle capture is bounded sanitized observations, not complete transcripts.", + "Synthetic maintenance and production activation differ; TTL observations are not immediate access revocation." + ], + "source_paths": [ + "adoption/lifecycle.md", + "blueprints/convergence-practice/wsl-memory-maintenance/README.md" + ], + "next_gap": "Establish independent-host/key recovery and the target production activation separately.", + "lifecycle": { + "source_path": "blueprints/token-native-focus/saturation-audit.json", + "scope": "Only the listed canonical stages and their original host/operation scopes apply. Scoped native retrieval, lifecycle negatives, migration, restart, upstream backup and empty-target restore have distinct accepted receipts.", + "unknown": "Unlisted or unestablished stages are not implied by this capability decision. Establish independent-host/key recovery and the target production activation separately.", + "stage_refs": [ + { + "component_id": "ai-memory", + "stage": "use", + "status": "accepted_within_scope" + }, + { + "component_id": "ai-memory", + "stage": "install", + "status": "accepted_within_scope" + }, + { + "component_id": "ai-memory", + "stage": "persistence", + "status": "accepted_within_scope" + }, + { + "component_id": "ai-memory", + "stage": "restart", + "status": "accepted_within_scope" + }, + { + "component_id": "ai-memory", + "stage": "cleanup", + "status": "accepted_within_scope" + }, + { + "component_id": "ai-memory", + "stage": "recovery", + "status": "accepted_within_scope" + } + ] + }, + "supersedes": [] + }, + { + "id": "bounded-browser-operations", + "capability": "Inspect and interact with selected browser pages", + "capability_key": "bounded-browser-operations", + "checked_at": "2026-09-20", + "layer_ids": [ + "web-research" + ], + "selection": "conditional", + "review_status": "accepted_within_scope", + "activation": "Use the selected browser lane for the requested page and retain bounded results.", + "component_ids": [ + "agent-browser", + "playwright-cli" + ], + "candidate": null, + "evidence_ids": [ + "desktop-cli-workflows", + "token-practice-gap-followup-20260920" + ], + "evidence_scope": "Selected local browser snapshot/ref interactions and the pinned Linux browser fixture passed.", + "limitations": [ + "Local fixture acceptance does not authorize unrelated websites, accounts or messages.", + "Browser-session recovery and arbitrary website compatibility remain unestablished." + ], + "source_paths": [ + "docs/convergence-architecture.md", + "adoption/lifecycle.md" + ], + "next_gap": "Check a changed website/browser operation only when the task depends on it.", + "lifecycle": { + "source_path": "blueprints/token-native-focus/saturation-audit.json", + "scope": "Only the listed canonical stages and their original host/operation scopes apply. Selected local browser snapshot/ref interactions and the pinned Linux browser fixture passed.", + "unknown": "Unlisted or unestablished stages are not implied by this capability decision. Check a changed website/browser operation only when the task depends on it.", + "stage_refs": [ + { + "component_id": "agent-browser", + "stage": "use", + "status": "accepted_within_scope" + }, + { + "component_id": "playwright-cli", + "stage": "use", + "status": "accepted_within_scope" + } + ] + }, + "supersedes": [] + }, + { + "id": "public-literature-retrieval", + "capability": "Discover and retrieve selected public research papers", + "capability_key": "public-literature-retrieval", + "checked_at": "2026-09-20", + "layer_ids": [ + "web-research" + ], + "selection": "conditional", + "review_status": "accepted_within_scope", + "activation": "Use for a bounded literature question and verify the selected paper/source.", + "component_ids": [ + "openresearch" + ], + "candidate": null, + "evidence_ids": [ + "artifact-reductions", + "token-practice-gap-followup-20260920" + ], + "evidence_scope": "Retained public-paper retrieval and selected extracted artifacts support the narrow research operation.", + "limitations": [ + "Discovery and extracted text do not establish paper conclusions or exhaustive literature coverage." + ], + "source_paths": [ + "docs/convergence-architecture.md", + "adoption/lifecycle.md" + ], + "next_gap": "Evaluate missing/ambiguous source handling for the next research corpus.", + "lifecycle": { + "source_path": "blueprints/token-native-focus/saturation-audit.json", + "scope": "Only the listed canonical stages and their original host/operation scopes apply. Retained public-paper retrieval and selected extracted artifacts support the narrow research operation.", + "unknown": "Unlisted or unestablished stages are not implied by this capability decision. Evaluate missing/ambiguous source handling for the next research corpus.", + "stage_refs": [ + { + "component_id": "openresearch", + "stage": "use", + "status": "accepted_within_scope" + } + ] + }, + "supersedes": [] + }, + { + "id": "selected-context-processing", + "capability": "Process large tool output while preserving useful source facts", + "capability_key": "selected-context-processing", + "checked_at": "2026-09-20", + "layer_ids": [ + "token-efficiency" + ], + "selection": "conditional", + "review_status": "accepted_within_scope", + "activation": "Use an explicit filter/execution lane when cheaper than a short direct read, retaining raw errors and recovery.", + "component_ids": [ + "context-mode", + "rtk" + ], + "candidate": null, + "evidence_ids": [ + "native-context-memory", + "token-practice-artifacts-20260920", + "token-practice-native-pairs-20260920", + "native-token-focus-clients-20260920", + "foundation-native-20260920" + ], + "evidence_scope": "Selected explicit native calls and exact artifact checks passed; paired trials retain both a Codex reduction and a Claude increase.", + "limitations": [ + "Cache conditions were uncontrolled and enclosing workflow usage was incomplete.", + "The foundation gateway RTK/lite previews failed required semantic checks; general CLI acceptance does not repair those failures." + ], + "source_paths": [ + "docs/token-practice.md", + "docs/foundation-stack.md" + ], + "next_gap": "Measure only a concrete changed workload, with correctness and complete attempt accounting.", + "lifecycle": { + "source_path": "blueprints/token-native-focus/saturation-audit.json", + "scope": "Only the listed canonical stages and their original host/operation scopes apply. Selected explicit native calls and exact artifact checks passed; paired trials retain both a Codex reduction and a Claude increase.", + "unknown": "Unlisted or unestablished stages are not implied by this capability decision. Measure only a concrete changed workload, with correctness and complete attempt accounting.", + "stage_refs": [ + { + "component_id": "context-mode", + "stage": "use", + "status": "accepted_within_scope" + }, + { + "component_id": "rtk", + "stage": "use", + "status": "accepted_within_scope" + } + ] + }, + "supersedes": [] + }, + { + "id": "guarded-recoverable-compression", + "capability": "Compress selected artifacts with exact-source recovery", + "capability_key": "guarded-recoverable-compression", + "checked_at": "2026-09-20", + "layer_ids": [ + "token-efficiency" + ], + "selection": "conditional", + "review_status": "accepted_within_scope", + "activation": "Use upstream direct MCP or the guarded adapter for a matching selected artifact.", + "component_ids": [ + "headroom" + ], + "candidate": null, + "evidence_ids": [ + "native-headroom-mcp-20260920", + "native-token-clean-prefix-20260920", + "token-practice-confirmation-20260920" + ], + "evidence_scope": "Owned synthetic MCP compression/retrieval and isolated install/restart/uninstall passed; retained guard comparisons preserve counterexamples.", + "limitations": [ + "Automatic interception of all agent traffic is not configured.", + "Capped native counters and exact artifact comparisons do not establish lifetime causal provider savings." + ], + "source_paths": [ + "docs/token-practice.md", + "adoption/lifecycle.md" + ], + "next_gap": "Reject a candidate representation that loses required facts or costs more than the adequate baseline.", + "lifecycle": { + "source_path": "blueprints/token-native-focus/saturation-audit.json", + "scope": "Only the listed canonical stages and their original host/operation scopes apply. Owned synthetic MCP compression/retrieval and isolated install/restart/uninstall passed; retained guard comparisons preserve counterexamples.", + "unknown": "Unlisted or unestablished stages are not implied by this capability decision. Reject a candidate representation that loses required facts or costs more than the adequate baseline.", + "stage_refs": [ + { + "component_id": "headroom", + "stage": "use", + "status": "accepted_within_scope" + }, + { + "component_id": "headroom", + "stage": "install", + "status": "accepted_within_scope" + }, + { + "component_id": "headroom", + "stage": "restart", + "status": "accepted_within_scope" + }, + { + "component_id": "headroom", + "stage": "cleanup", + "status": "accepted_within_scope" + }, + { + "component_id": "headroom", + "stage": "recovery", + "status": "accepted_within_scope" + } + ] + }, + "supersedes": [] + }, + { + "id": "selected-file-representations", + "capability": "Pack selected files or encode structured data only when useful", + "capability_key": "selected-file-representations", + "checked_at": "2026-09-20", + "layer_ids": [ + "token-efficiency", + "code-navigation" + ], + "selection": "conditional", + "review_status": "accepted_within_scope", + "activation": "Use explicit file selection and keep the smallest adequate decoded representation.", + "component_ids": [ + "repomix", + "toon" + ], + "candidate": null, + "evidence_ids": [ + "portable-cli-artifacts", + "token-practice-artifacts-20260920", + "token-practice-catalog-toon-20260920" + ], + "evidence_scope": "Selected-file packing and TOON roundtrip passed; exact full-catalog tokens increased under TOON and compact JSON was retained.", + "limitations": [ + "Structural compression omits implementation details; originals remain required for edits and correctness.", + "A smaller heuristic estimate is not an exact token reduction." + ], + "source_paths": [ + "docs/token-practice.md" + ], + "next_gap": "Recount a changed artifact only when representation choice matters.", + "lifecycle": { + "source_path": "blueprints/token-native-focus/saturation-audit.json", + "scope": "Only the listed canonical stages and their original host/operation scopes apply. Selected-file packing and TOON roundtrip passed; exact full-catalog tokens increased under TOON and compact JSON was retained.", + "unknown": "Unlisted or unestablished stages are not implied by this capability decision. Recount a changed artifact only when representation choice matters.", + "stage_refs": [ + { + "component_id": "repomix", + "stage": "use", + "status": "accepted_within_scope" + }, + { + "component_id": "toon", + "stage": "use", + "status": "accepted_within_scope" + } + ] + }, + "supersedes": [] + }, + { + "id": "native-usage-reading", + "capability": "Read native provider usage without mixing counter scopes", + "capability_key": "native-usage-reading", + "checked_at": "2026-09-20", + "layer_ids": [ + "token-efficiency", + "observation-inference" + ], + "selection": "conditional", + "review_status": "accepted_within_scope", + "activation": "Read the selected native ledger and retain its aggregation scope.", + "component_ids": [ + "ccusage" + ], + "candidate": null, + "evidence_ids": [ + "token-practice-gap-followup-20260920", + "current-session-observation-20260920" + ], + "evidence_scope": "Offline native usage parsing and scoped current-session observations have retained outputs.", + "limitations": [ + "Provider consumption, estimated savings, billing and cache subsets are distinct.", + "Repeated cumulative snapshots cannot be summed as additional usage." + ], + "source_paths": [ + "docs/token-practice.md" + ], + "next_gap": "Resolve missing attempt/child coverage before any whole-workflow efficiency claim.", + "lifecycle": { + "source_path": "blueprints/token-native-focus/saturation-audit.json", + "scope": "Only the listed canonical stages and their original host/operation scopes apply. Offline native usage parsing and scoped current-session observations have retained outputs.", + "unknown": "Unlisted or unestablished stages are not implied by this capability decision. Resolve missing attempt/child coverage before any whole-workflow efficiency claim.", + "stage_refs": [ + { + "component_id": "ccusage", + "stage": "use", + "status": "accepted_within_scope" + } + ] + }, + "supersedes": [] + }, + { + "id": "deterministic-quality-tools", + "capability": "Evaluate fixtures and review shell/source changes", + "capability_key": "deterministic-quality-tools", + "checked_at": "2026-09-20", + "layer_ids": [ + "quality-evaluation" + ], + "selection": "conditional", + "review_status": "accepted_within_scope", + "activation": "Use the smallest meaningful project acceptance plus independent review for substantive changes.", + "component_ids": [ + "promptfoo", + "difftastic", + "shellcheck", + "playwright-test" + ], + "candidate": null, + "evidence_ids": [ + "token-native-retained-functional-20260920", + "portable-cli-artifacts", + "wsl-application-20260920" + ], + "evidence_scope": "Deterministic promptfoo, native shell/structural comparison and the locked browser application flow have scoped acceptance.", + "limitations": [ + "Fixture success does not prove universal model quality or production application correctness." + ], + "source_paths": [ + "blueprints/convergence-practice/wsl-application/README.md" + ], + "next_gap": "Add the missing behavioral negative case exposed by the next task.", + "lifecycle": { + "source_path": "blueprints/token-native-focus/saturation-audit.json", + "scope": "Only the listed canonical stages and their original host/operation scopes apply. Deterministic promptfoo, native shell/structural comparison and the locked browser application flow have scoped acceptance.", + "unknown": "Unlisted or unestablished stages are not implied by this capability decision. Add the missing behavioral negative case exposed by the next task.", + "stage_refs": [ + { + "component_id": "promptfoo", + "stage": "use", + "status": "accepted_within_scope" + }, + { + "component_id": "difftastic", + "stage": "use", + "status": "accepted_within_scope" + }, + { + "component_id": "shellcheck", + "stage": "use", + "status": "accepted_within_scope" + }, + { + "component_id": "playwright-test", + "stage": "use", + "status": "accepted_within_scope" + } + ] + }, + "supersedes": [] + }, + { + "id": "offline-security-inventory", + "capability": "Check workflow/secret controls and selected dependency identity", + "capability_key": "offline-security-inventory", + "checked_at": "2026-09-20", + "layer_ids": [ + "ci-supply-chain", + "quality-evaluation" + ], + "selection": "conditional", + "review_status": "accepted_within_scope", + "activation": "Run selected offline checks on changed published files and an explicitly scoped dependency source.", + "component_ids": [ + "gitleaks", + "zizmor", + "syft" + ], + "candidate": null, + "evidence_ids": [ + "velanext-native-quality-tools-20260920", + "native-ci-security-20260920", + "native-linux-zizmor-20260920", + "syft-sdk-inventory-20260919" + ], + "evidence_scope": "Native gitleaks and zizmor accepted clean controls and rejected inert unsafe fixtures; Syft matched thirty-six selected SDK distributions.", + "limitations": [ + "Secret scanning is not proof of no secret anywhere; regular offline workflow analysis is scoped.", + "The financial SDK fixture supports dependency enumeration only, not financial behavior or vulnerability assurance." + ], + "source_paths": [ + "blueprints/convergence-practice/ci-security/README.md", + "blueprints/us-equities/supply-chain/README.md" + ], + "next_gap": "Qualify new distributions or security boundaries independently.", + "lifecycle": { + "source_path": "blueprints/token-native-focus/saturation-audit.json", + "scope": "Only the listed canonical stages and their original host/operation scopes apply. Native gitleaks and zizmor accepted clean controls and rejected inert unsafe fixtures; Syft matched thirty-six selected SDK distributions.", + "unknown": "Unlisted or unestablished stages are not implied by this capability decision. Qualify new distributions or security boundaries independently.", + "stage_refs": [ + { + "component_id": "gitleaks", + "stage": "use", + "status": "accepted_within_scope" + }, + { + "component_id": "zizmor", + "stage": "use", + "status": "accepted_within_scope" + }, + { + "component_id": "syft", + "stage": "use", + "status": "accepted_within_scope" + } + ] + }, + "supersedes": [] + }, + { + "id": "clean-token-tool-ci", + "capability": "Reproduce native context-tool commands in a clean CI environment", + "capability_key": "clean-token-tool-ci", + "checked_at": "2026-09-20", + "layer_ids": [ + "ci-supply-chain", + "token-efficiency" + ], + "selection": "conditional", + "review_status": "accepted_within_scope", + "activation": "Run the existing job when its pinned inputs or acceptance code change.", + "component_ids": [ + "rtk", + "qmd", + "repomix", + "toon" + ], + "candidate": null, + "evidence_ids": [ + "native-token-ci-local-20260920", + "native-token-ci-github-20260920" + ], + "evidence_scope": "Local and GitHub clean installation passed forty-one command expectations and fourteen fidelity/recovery checks; retained artifact/source hashes matched.", + "limitations": [ + "CI acceptance covers these four tool fixtures, not live providers, GPU execution or a full new-PC stack." + ], + "source_paths": [ + "docs/convergence-architecture.md", + "adoption/lifecycle.md" + ], + "next_gap": "Extend a specific missing native-tool CI behavior only with its own useful fixture.", + "lifecycle": { + "source_path": "blueprints/token-native-focus/saturation-audit.json", + "scope": "Only the listed canonical stages and their original host/operation scopes apply. Local and GitHub clean installation passed forty-one command expectations and fourteen fidelity/recovery checks; retained artifact/source hashes matched.", + "unknown": "Unlisted or unestablished stages are not implied by this capability decision. Extend a specific missing native-tool CI behavior only with its own useful fixture.", + "stage_refs": [ + { + "component_id": "rtk", + "stage": "use", + "status": "accepted_within_scope" + }, + { + "component_id": "qmd", + "stage": "use", + "status": "accepted_within_scope" + }, + { + "component_id": "repomix", + "stage": "use", + "status": "accepted_within_scope" + }, + { + "component_id": "toon", + "stage": "use", + "status": "accepted_within_scope" + } + ] + }, + "supersedes": [] + }, + { + "id": "owned-process-deadlines", + "capability": "Terminate an owned local process tree at its deadline", + "capability_key": "owned-process-deadlines", + "checked_at": "2026-09-20", + "layer_ids": [ + "scheduling-supervision", + "workers" + ], + "selection": "conditional", + "review_status": "accepted_within_scope", + "activation": "Use a transient owned unit for a task that needs process-tree supervision.", + "component_ids": [ + "systemd" + ], + "candidate": null, + "evidence_ids": [ + "native-worker-supervision-20260919", + "native-worker-containment-20260920" + ], + "evidence_scope": "The Linux user manager terminated a TERM-ignoring parent and descendants, retained timeout failure, and accepted a separate fresh run. A separate upstream user-service fixture also contained a TERM-ignoring setsid descendant after MainPID crash; the combined native child trial was refused before effects and remains unaccepted.", + "limitations": [ + "Local process termination does not prove remote provider cancellation, spending caps or exactly-once effects." + ], + "source_paths": [ + "blueprints/us-equities/worker-supervision/README.md", + "blueprints/convergence-practice/worker-recovery/README.md" + ], + "next_gap": "Test worker cancellation and reconcile external effects before any relaunch.", + "lifecycle": { + "source_path": "blueprints/token-native-focus/saturation-audit.json", + "scope": "Only the listed canonical stages and their original host/operation scopes apply. The Linux user manager terminated a TERM-ignoring parent and descendants, retained timeout failure, and accepted a separate fresh run.", + "unknown": "Unlisted or unestablished stages are not implied by this capability decision. Test worker cancellation and reconcile external effects before any relaunch.", + "stage_refs": [ + { + "component_id": "systemd", + "stage": "use", + "status": "accepted_within_scope" + } + ] + }, + "supersedes": [] + }, + { + "id": "checkpointed-workflow-resume", + "capability": "Retry unfinished workflow steps while preserving a checkpoint", + "capability_key": "checkpointed-workflow-resume", + "checked_at": "2026-09-20", + "layer_ids": [ + "scheduling-supervision", + "recovery-portability" + ], + "selection": "conditional", + "review_status": "accepted_within_scope", + "activation": "Run an owned workflow with explicit checkpoints and bounded retry conditions.", + "component_ids": [ + "dagu" + ], + "candidate": null, + "evidence_ids": [ + "native-dagu-job-recovery-20260920", + "wsl-transport-recovery-20260920" + ], + "evidence_scope": "Native cancellation/retry retained one checkpoint on Mac and WSL; separate SSH-client termination left the same job running to completion.", + "limitations": [ + "Controlled transport interruption is not a real network outage or host reboot.", + "This does not establish remote model cancellation or distributed exactly-once effects." + ], + "source_paths": [ + "blueprints/convergence-practice/job-recovery/README.md", + "blueprints/convergence-practice/wsl-transport-recovery/README.md" + ], + "next_gap": "Qualify scheduled-service restart/reboot and unfinished worker effect reconciliation.", + "lifecycle": { + "source_path": "blueprints/token-native-focus/saturation-audit.json", + "scope": "Only the listed canonical stages and their original host/operation scopes apply. Native cancellation/retry retained one checkpoint on Mac and WSL; separate SSH-client termination left the same job running to completion.", + "unknown": "Unlisted or unestablished stages are not implied by this capability decision. Qualify scheduled-service restart/reboot and unfinished worker effect reconciliation.", + "stage_refs": [ + { + "component_id": "dagu", + "stage": "use", + "status": "accepted_within_scope" + }, + { + "component_id": "dagu", + "stage": "persistence", + "status": "accepted_within_scope" + }, + { + "component_id": "dagu", + "stage": "restart", + "status": "accepted_within_scope" + }, + { + "component_id": "dagu", + "stage": "recovery", + "status": "accepted_within_scope" + } + ] + }, + "supersedes": [] + }, + { + "id": "local-typed-application", + "capability": "Build a typed local UI/API with persistent database state", + "capability_key": "local-typed-application", + "checked_at": "2026-09-20", + "layer_ids": [ + "hosting-services", + "quality-evaluation" + ], + "selection": "conditional", + "review_status": "accepted_within_scope", + "activation": "Use the selected locked project and owned native database/application processes.", + "component_ids": [ + "nextjs", + "react", + "fastapi", + "postgresql" + ], + "candidate": null, + "evidence_ids": [ + "native-application-delivery-20260920", + "mac-native-application-migration-20260920", + "wsl-application-20260920" + ], + "evidence_scope": "Locked UI/API, twelve API checks, browser create/update, migration reversal and exact rows/history after restart passed on named Mac/WSL fixtures.", + "limitations": [ + "No production authentication, cloud hosting or independent-host database restore is accepted.", + "The failed newer TypeScript generator attempt remains separate from the retained supported runtime." + ], + "source_paths": [ + "blueprints/convergence-practice/application-delivery/README.md", + "blueprints/convergence-practice/wsl-application/README.md" + ], + "next_gap": "Qualify independent restore and the requested deployment-specific access/runtime conditions.", + "lifecycle": { + "source_path": "blueprints/token-native-focus/saturation-audit.json", + "scope": "Only the listed canonical stages and their original host/operation scopes apply. Locked UI/API, twelve API checks, browser create/update, migration reversal and exact rows/history after restart passed on named Mac/WSL fixtures.", + "unknown": "Unlisted or unestablished stages are not implied by this capability decision. Qualify independent restore and the requested deployment-specific access/runtime conditions.", + "stage_refs": [ + { + "component_id": "nextjs", + "stage": "use", + "status": "accepted_within_scope" + }, + { + "component_id": "nextjs", + "stage": "install", + "status": "accepted_within_scope" + }, + { + "component_id": "nextjs", + "stage": "persistence", + "status": "accepted_within_scope" + }, + { + "component_id": "nextjs", + "stage": "restart", + "status": "accepted_within_scope" + }, + { + "component_id": "nextjs", + "stage": "recovery", + "status": "not_established" + }, + { + "component_id": "react", + "stage": "use", + "status": "accepted_within_scope" + }, + { + "component_id": "react", + "stage": "install", + "status": "accepted_within_scope" + }, + { + "component_id": "react", + "stage": "persistence", + "status": "accepted_within_scope" + }, + { + "component_id": "react", + "stage": "restart", + "status": "accepted_within_scope" + }, + { + "component_id": "react", + "stage": "recovery", + "status": "not_established" + }, + { + "component_id": "fastapi", + "stage": "use", + "status": "accepted_within_scope" + }, + { + "component_id": "fastapi", + "stage": "install", + "status": "accepted_within_scope" + }, + { + "component_id": "fastapi", + "stage": "persistence", + "status": "accepted_within_scope" + }, + { + "component_id": "fastapi", + "stage": "restart", + "status": "accepted_within_scope" + }, + { + "component_id": "fastapi", + "stage": "recovery", + "status": "not_established" + }, + { + "component_id": "postgresql", + "stage": "use", + "status": "accepted_within_scope" + }, + { + "component_id": "postgresql", + "stage": "install", + "status": "accepted_within_scope" + }, + { + "component_id": "postgresql", + "stage": "persistence", + "status": "accepted_within_scope" + }, + { + "component_id": "postgresql", + "stage": "restart", + "status": "accepted_within_scope" + }, + { + "component_id": "postgresql", + "stage": "recovery", + "status": "not_established" + } + ] + }, + "supersedes": [] + }, + { + "id": "mac-container-volume", + "capability": "Retain a database row in an owned native Mac container volume", + "capability_key": "mac-container-volume", + "checked_at": "2026-09-20", + "layer_ids": [ + "hosting-services", + "isolation" + ], + "selection": "optional", + "review_status": "accepted_within_scope", + "activation": "Use only the matching Mac container/volume recipe; WSL has a separate direct database recipe.", + "component_ids": [ + "apple-container" + ], + "candidate": null, + "evidence_ids": [ + "mac-native-container-storage-20260920" + ], + "evidence_scope": "Pinned PostgreSQL image on Apple container retained its row after native stop/start; owned fixtures were removed.", + "limitations": [ + "Mac Documents bind mount stalled; accepted ext4 named-volume behavior does not erase that failure.", + "Mac-only fixture; no crash/reboot or production durability claim." + ], + "source_paths": [ + "blueprints/convergence-practice/container-storage/README.md" + ], + "next_gap": "Qualify crash/reboot persistence only when that deployment needs it.", + "lifecycle": { + "source_path": "blueprints/token-native-focus/saturation-audit.json", + "scope": "Only the listed canonical stages and their original host/operation scopes apply. Pinned PostgreSQL image on Apple container retained its row after native stop/start; owned fixtures were removed.", + "unknown": "Unlisted or unestablished stages are not implied by this capability decision. Qualify crash/reboot persistence only when that deployment needs it.", + "stage_refs": [ + { + "component_id": "apple-container", + "stage": "use", + "status": "accepted_within_scope" + }, + { + "component_id": "apple-container", + "stage": "persistence", + "status": "accepted_within_scope" + }, + { + "component_id": "apple-container", + "stage": "restart", + "status": "accepted_within_scope" + }, + { + "component_id": "apple-container", + "stage": "cleanup", + "status": "accepted_within_scope" + }, + { + "component_id": "apple-container", + "stage": "recovery", + "status": "not_established" + } + ] + }, + "supersedes": [] + }, + { + "id": "native-mcp-adapters", + "capability": "Bridge or inspect selected MCP operations through upstream tools", + "capability_key": "native-mcp-adapters", + "checked_at": "2026-09-20", + "layer_ids": [ + "hosting-services", + "code-navigation" + ], + "selection": "conditional", + "review_status": "accepted_within_scope", + "activation": "Use the configured project bridge or Inspector for a concrete operation/protocol check.", + "component_ids": [ + "mcporter", + "mcp-inspector" + ], + "candidate": null, + "evidence_ids": [ + "desktop-restart-acceptance", + "token-native-retained-functional-20260920" + ], + "evidence_scope": "Retained native bridge recovery and Inspector stdio arithmetic support their selected operations.", + "limitations": [ + "A shared daemon is not an owned disposable service; removing one registration is not an uninstall or all-client cleanup." + ], + "source_paths": [ + "docs/convergence-architecture.md", + "adoption/lifecycle.md" + ], + "next_gap": "Qualify changed process roots and scoped registration recovery without disturbing unrelated consumers.", + "lifecycle": { + "source_path": "blueprints/token-native-focus/saturation-audit.json", + "scope": "Only the listed canonical stages and their original host/operation scopes apply. Retained native bridge recovery and Inspector stdio arithmetic support their selected operations.", + "unknown": "Unlisted or unestablished stages are not implied by this capability decision. Qualify changed process roots and scoped registration recovery without disturbing unrelated consumers.", + "stage_refs": [ + { + "component_id": "mcporter", + "stage": "use", + "status": "accepted_within_scope" + }, + { + "component_id": "mcp-inspector", + "stage": "use", + "status": "accepted_within_scope" + } + ] + }, + "supersedes": [] + }, + { + "id": "same-host-restore", + "capability": "Restore selected native state into an isolated empty target", + "capability_key": "same-host-restore", + "checked_at": "2026-09-20", + "layer_ids": [ + "recovery-portability", + "durable-memory", + "semantic-rag" + ], + "selection": "conditional", + "review_status": "accepted_within_scope", + "activation": "Retain the exact snapshot and separately available private key source; restore into an empty owned target.", + "component_ids": [ + "restic", + "ai-memory", + "qdrant" + ], + "candidate": null, + "evidence_ids": [ + "restic-local-public-reference-20260919", + "ai-memory-native-state-recovery-20260919", + "qdrant-native-state-recovery-20260919", + "native-wsl-restic-synthetic-20260920" + ], + "evidence_scope": "Selected public bytes, native memory/FTS state and Qdrant snapshot/query results survived same-host backup/restore; synthetic wrong-key/corrupt-copy refusals were retained.", + "limitations": [ + "Independent physical host, lost-key recovery and the whole stack after disaster remain unestablished.", + "Financial-blueprint location supplies reusable state-recovery evidence only." + ], + "source_paths": [ + "adoption/lifecycle.md", + "blueprints/convergence-practice/wsl-restore/README.md" + ], + "next_gap": "Run independent off-host recovery with a separately accessible key and real post-restore application queries.", + "lifecycle": { + "source_path": "blueprints/token-native-focus/saturation-audit.json", + "scope": "Only the listed canonical stages and their original host/operation scopes apply. Selected public bytes, native memory/FTS state and Qdrant snapshot/query results survived same-host backup/restore; synthetic wrong-key/corrupt-copy refusals were retained.", + "unknown": "Unlisted or unestablished stages are not implied by this capability decision. Run independent off-host recovery with a separately accessible key and real post-restore application queries.", + "stage_refs": [ + { + "component_id": "restic", + "stage": "recovery", + "status": "accepted_within_scope" + }, + { + "component_id": "ai-memory", + "stage": "recovery", + "status": "accepted_within_scope" + }, + { + "component_id": "qdrant", + "stage": "recovery", + "status": "accepted_within_scope" + } + ] + }, + "supersedes": [] + }, + { + "id": "native-session-resume", + "capability": "Resume the same native session after an owned interruption", + "capability_key": "native-session-resume", + "checked_at": "2026-09-20", + "layer_ids": [ + "recovery-portability", + "native-clients", + "workers" + ], + "selection": "conditional", + "review_status": "accepted_within_scope", + "activation": "Reconcile native session identity and saved effects before resubmitting unfinished work.", + "component_ids": [ + "codex", + "claude-code" + ], + "candidate": null, + "evidence_ids": [ + "native-codex-session-recovery-20260920", + "native-claude-session-recovery-20260920", + "native-token-stack-final-20260920" + ], + "evidence_scope": "Codex on Mac and Claude on WSL resumed the same session to finish an unchanged single checkpoint; later bounded source tasks also retained continuations.", + "limitations": [ + "Individual session continuation does not establish arbitrary worker crash, provider cancellation or whole-host recovery.", + "Resumed cumulative usage must not be added again to earlier included totals." + ], + "source_paths": [ + "blueprints/convergence-practice/native-recovery/README.md", + "blueprints/convergence-practice/native-recovery/claude/README.md" + ], + "next_gap": "Qualify abrupt writing-worker failure with task-specific single-effect acceptance.", + "lifecycle": { + "source_path": "blueprints/token-native-focus/saturation-audit.json", + "scope": "Only the listed canonical stages and their original host/operation scopes apply. Codex on Mac and Claude on WSL resumed the same session to finish an unchanged single checkpoint; later bounded source tasks also retained continuations.", + "unknown": "Unlisted or unestablished stages are not implied by this capability decision. Qualify abrupt writing-worker failure with task-specific single-effect acceptance.", + "stage_refs": [ + { + "component_id": "codex", + "stage": "recovery", + "status": "accepted_within_scope" + }, + { + "component_id": "claude-code", + "stage": "recovery", + "status": "accepted_within_scope" + } + ] + }, + "supersedes": [] + }, + { + "id": "loopback-usage-observation", + "capability": "Observe bounded native outcomes and reconcile usage categories", + "capability_key": "loopback-usage-observation", + "checked_at": "2026-09-20", + "layer_ids": [ + "observation-inference" + ], + "selection": "conditional", + "review_status": "accepted_within_scope", + "activation": "Keep local observation access separate from workflow operator authentication and inference accounts.", + "component_ids": [ + "opentelemetry-collector-contrib", + "prometheus", + "loki", + "grafana", + "alertmanager", + "ntfy" + ], + "candidate": null, + "evidence_ids": [ + "native-observability", + "native-observability-followup", + "native-token-stack-final-20260920", + "current-session-observation-20260920" + ], + "evidence_scope": "Native tasks, loopback queries/dashboard and local firing/resolved notifications passed; later writer-scoped results reconcile selected native usage.", + "limitations": [ + "Liveness, checkpoint age, source attribution and consumed tokens are different observations.", + "Extra startup events and unlabelled historical invocations retain attribution limits; no exact causal lifetime savings are inferred." + ], + "source_paths": [ + "observability/README.md", + "adoption/lifecycle.md" + ], + "next_gap": "Qualify scheduled-service/reboot persistence and missing task attribution only in the needed scope.", + "lifecycle": { + "source_path": "blueprints/token-native-focus/saturation-audit.json", + "scope": "Only the listed canonical stages and their original host/operation scopes apply. Native tasks, loopback queries/dashboard and local firing/resolved notifications passed; later writer-scoped results reconcile selected native usage.", + "unknown": "Unlisted or unestablished stages are not implied by this capability decision. Qualify scheduled-service/reboot persistence and missing task attribution only in the needed scope.", + "stage_refs": [ + { + "component_id": "opentelemetry-collector-contrib", + "stage": "use", + "status": "accepted_within_scope" + }, + { + "component_id": "prometheus", + "stage": "use", + "status": "accepted_within_scope" + }, + { + "component_id": "loki", + "stage": "use", + "status": "accepted_within_scope" + }, + { + "component_id": "grafana", + "stage": "use", + "status": "accepted_within_scope" + }, + { + "component_id": "alertmanager", + "stage": "use", + "status": "accepted_within_scope" + }, + { + "component_id": "ntfy", + "stage": "use", + "status": "accepted_within_scope" + } + ] + }, + "supersedes": [] + }, + { + "id": "bounded-history-and-traces", + "capability": "Inspect selected native session history and local traces", + "capability_key": "bounded-history-and-traces", + "checked_at": "2026-09-20", + "layer_ids": [ + "observation-inference" + ], + "selection": "conditional", + "review_status": "accepted_within_scope", + "activation": "Use a selected archive or loopback receiver when a concrete diagnostic needs it.", + "component_ids": [ + "agentsview", + "otel-tui" + ], + "candidate": null, + "evidence_ids": [ + "token-practice-gap-followup-20260920", + "upstream-native-tools-20260920", + "current-session-observation-20260920" + ], + "evidence_scope": "One scoped session archive query and a synthetic loopback terminal trace were accepted; current observations retain their separate bounds.", + "limitations": [ + "Archive retrieval requires explicit scope/refresh and is not every native transcript or durable memory.", + "Synthetic trace acceptance is not production tracing completeness." + ], + "source_paths": [ + "docs/convergence-architecture.md", + "adoption/lifecycle.md" + ], + "next_gap": "Test changed archive/session scope and missing attribution before drawing broader conclusions.", + "lifecycle": { + "source_path": "blueprints/token-native-focus/saturation-audit.json", + "scope": "Only the listed canonical stages and their original host/operation scopes apply. One scoped session archive query and a synthetic loopback terminal trace were accepted; current observations retain their separate bounds.", + "unknown": "Unlisted or unestablished stages are not implied by this capability decision. Test changed archive/session scope and missing attribution before drawing broader conclusions.", + "stage_refs": [ + { + "component_id": "agentsview", + "stage": "use", + "status": "accepted_within_scope" + }, + { + "component_id": "otel-tui", + "stage": "use", + "status": "accepted_within_scope" + } + ] + }, + "supersedes": [] + }, + { + "id": "interactive-hud-boundary", + "capability": "Retain synthetic HUD rendering separately from live activation", + "capability_key": "interactive-hud-boundary", + "checked_at": "2026-09-20", + "layer_ids": [ + "observation-inference" + ], + "selection": "optional", + "review_status": "partial_acceptance", + "activation": "Keep the configured optional statusline scoped and use native usage for authoritative accounting.", + "component_ids": [ + "claude-hud" + ], + "candidate": null, + "evidence_ids": [ + "token-practice-gap-followup-20260920", + "native-claude-hud-interactive-20260920" + ], + "evidence_scope": "Synthetic renderer passed; the real terminal launch reached onboarding before the conversation HUD appeared.", + "limitations": [ + "Live interactive HUD rendering remains unverified despite existing authentication; a synthetic rendering pass does not replace it." + ], + "source_paths": [ + "docs/convergence-architecture.md", + "adoption/lifecycle.md" + ], + "next_gap": "Observe the real statusline only after the native onboarding condition is resolved.", + "lifecycle": { + "source_path": "blueprints/token-native-focus/saturation-audit.json", + "scope": "Only the listed canonical stages and their original host/operation scopes apply. Synthetic renderer passed; the real terminal launch reached onboarding before the conversation HUD appeared.", + "unknown": "Unlisted or unestablished stages are not implied by this capability decision. Observe the real statusline only after the native onboarding condition is resolved.", + "stage_refs": [ + { + "component_id": "claude-hud", + "stage": "use", + "status": "partial_acceptance" + } + ] + }, + "supersedes": [] + }, + { + "id": "local-generation-trial", + "capability": "Trial local text generation against a frozen repair oracle", + "capability_key": "local-generation-trial", + "checked_at": "2026-09-20", + "layer_ids": [ + "observation-inference" + ], + "selection": "trial", + "review_status": "accepted_within_scope", + "activation": "Use an isolated local trial only when a concrete inference gap warrants it; native workers remain default.", + "component_ids": [ + "llama-cpp" + ], + "candidate": null, + "evidence_ids": [ + "native-gpu-patch-20260920" + ], + "evidence_scope": "One pinned partial-offload local CUDA repair passed independent source review and twelve original tests on WSL RTX4090.", + "limitations": [ + "Single-task trial, not general frontier parity, host portability or causal token savings.", + "Memory reserve, model/hash provenance and missing exact layer telemetry remain in the receipt." + ], + "source_paths": [ + "blueprints/convergence-practice/gpu-inference/README.md" + ], + "next_gap": "Freeze a representative next workload and resource acceptance before expanding use.", + "lifecycle": { + "source_path": "blueprints/token-native-focus/saturation-audit.json", + "scope": "Only the listed canonical stages and their original host/operation scopes apply. One pinned partial-offload local CUDA repair passed independent source review and twelve original tests on WSL RTX4090.", + "unknown": "Unlisted or unestablished stages are not implied by this capability decision. Freeze a representative next workload and resource acceptance before expanding use.", + "stage_refs": [ + { + "component_id": "llama-cpp", + "stage": "use", + "status": "accepted_within_scope" + } + ] + }, + "supersedes": [] + }, + { + "id": "optional-gateway-lifecycle", + "capability": "Keep optional gateway lifecycle separate from inference acceptance", + "capability_key": "optional-gateway-lifecycle", + "checked_at": "2026-09-20", + "layer_ids": [ + "observation-inference", + "hosting-services" + ], + "selection": "trial", + "review_status": "partial_acceptance", + "activation": "Retain native account/model routes; use the optional gateway only for an explicit qualified routing need.", + "component_ids": [ + "omniroute" + ], + "candidate": null, + "evidence_ids": [ + "foundation-native-20260920" + ], + "evidence_scope": "Clean native Linux installation, service restart, persistence, plaintext restore and stop passed; inference and compression are separately scoped attempts.", + "limitations": [ + "Native Codex model400, direct quota429 and malformed Claude launch/plaintext429 remain unsuccessful gateway tasks.", + "RTK/lite semantic previews failed; exact dedup retained its matching-scope result; cache/compression counters are not provider savings." + ], + "source_paths": [ + "docs/foundation-stack.md" + ], + "next_gap": "Retry an exact-model task only after model mapping/provider capacity changes; do not repeat unchanged refusals.", + "lifecycle": { + "source_path": "blueprints/token-native-focus/saturation-audit.json", + "scope": "Only the listed canonical stages and their original host/operation scopes apply. Clean native Linux installation, service restart, persistence, plaintext restore and stop passed; inference and compression are separately scoped attempts.", + "unknown": "Unlisted or unestablished stages are not implied by this capability decision. Retry an exact-model task only after model mapping/provider capacity changes; do not repeat unchanged refusals.", + "stage_refs": [ + { + "component_id": "omniroute", + "stage": "use", + "status": "partial_acceptance" + }, + { + "component_id": "omniroute", + "stage": "install", + "status": "accepted_within_scope" + }, + { + "component_id": "omniroute", + "stage": "restart", + "status": "accepted_within_scope" + }, + { + "component_id": "omniroute", + "stage": "recovery", + "status": "partial_acceptance" + } + ] + }, + "supersedes": [] + }, + { + "id": "tavily-native-search-extract", + "capability": "Search and extract primary web sources through the upstream Tavily CLI", + "capability_key": "tavily-native-integration", + "checked_at": "2026-09-20", + "layer_ids": [ + "web-research", + "instructions-skills" + ], + "selection": "conditional", + "review_status": "accepted_within_scope", + "activation": "Use tvly Search or Extract on demand with native private authentication; eight official skills provide task-specific guidance.", + "component_ids": [ + "tavily-cli" + ], + "candidate": null, + "evidence_ids": [ + "native-tavily-cli-20260920" + ], + "evidence_scope": "Upstream CLI0.1.8 installed and authenticated; live search returned four official sources and extraction returned one result with zero failures. Eight official skills were listed for both clients and discovered by fresh Codex probes for native and Desktop homes.", + "limitations": [ + "Desktop-home discovery initially failed SQLite initialization and passed only with a temporary session-specific sqlite_home; the active Desktop registry was not hot-reloaded.", + "Claude global skill listing and fresh Codex discovery do not prove actual model invocation of every skill. Map, Crawl and Research remain unqualified.", + "No causal lifetime token savings or full lifecycle recovery is measured." + ], + "source_paths": [ + "recipes/tavily.md", + "evidence/receipts/native-tavily-cli-20260920.json" + ], + "next_gap": "Use the accepted CLI now; check the intended fresh client for skill activation when needed, and qualify broader operations only for a concrete task.", + "lifecycle": { + "source_path": "blueprints/token-native-focus/saturation-audit.json", + "scope": "Native install, Search/Extract and owned-probe cleanup are recorded; each stage retains its exact operation boundary.", + "unknown": "Independent key recovery, uninstall/reinstall and the active Desktop skill registry remain unverified.", + "stage_refs": [ + { + "component_id": "tavily-cli", + "stage": "use", + "status": "accepted_within_scope" + } + ] + }, + "supersedes": [] + }, + { + "id": "native-child-interruption-recovery", + "capability": "Resume the same native child and reconcile a local effect after interruption", + "capability_key": "native-child-interruption-recovery", + "checked_at": "2026-09-20", + "layer_ids": [ + "workers", + "scheduling-supervision", + "recovery-portability" + ], + "selection": "conditional", + "review_status": "partial_acceptance", + "activation": "Use bounded native TaskStop/SendMessage and same-parent continuation; explicitly own and reconcile descendant processes and local effects.", + "component_ids": [ + "claude-code" + ], + "candidate": null, + "evidence_ids": [ + "native-worker-recovery-20260920", + "native-worker-containment-20260920" + ], + "evidence_scope": "One native background child retained its identity through TaskStop/SendMessage cancellation and same-parent continuation after abrupt runtime failure, producing one final local effect from an unchanged checkpoint after explicit supervisor cleanup.", + "limitations": [ + "One synthetic local fixture and one physical WSL host, not arbitrary application state.", + "Actual native child identities and paths remain private; hashes bind retained streams.", + "Native original runtime SIGKILL is a shared-process failure; task identity and effect continuation are distinct from process containment.", + "The updated runner parser is regression-tested offline; the one native attempt executed the separately retained source.", + "Automatic native crash descendant containment: the crash wait survived and needed supervisor SIGKILL.", + "Exact requested tool-only behavior: the child attempted an extra read-only ls/git-status command, which was refused.", + "Remote provider cancellation, billing cessation, independent child-process isolation, off-host recovery, power-loss durability and distributed exactly-once effects.", + "The cgroup follow-up contained its deterministic detached fixture, but its native child prepended a refused command before checkpoint. No combined native result is accepted." + ], + "source_paths": [ + "blueprints/convergence-practice/worker-recovery/README.md" + ], + "next_gap": "Resolve the frozen child command-contract mismatch before another changed native cgroup qualification; retain existing permissions, failed attempt and effect oracle.", + "lifecycle": { + "source_path": "blueprints/token-native-focus/saturation-audit.json", + "scope": "Existing native-use stage is retained; this new child-continuation receipt explicitly needs supervisor cleanup.", + "unknown": "Native automatic crash containment failed in this attempt; provider cancellation and complete usage unknown.", + "stage_refs": [ + { + "component_id": "claude-code", + "stage": "use", + "status": "accepted_within_scope" + } + ] + }, + "supersedes": [] + } + ] +} diff --git a/catalogs/foundation/manifest.json b/catalogs/foundation/manifest.json new file mode 100644 index 000000000..20cebb369 --- /dev/null +++ b/catalogs/foundation/manifest.json @@ -0,0 +1,251 @@ +{ + "schema_version": 1, + "catalog_id": "foundation", + "checked_at": "2026-09-20", + "scope": "General native engineering, research, documentation, applications, workers, observation and recovery. FOUNDATION is a capability selection over canonical evidence, separate from the US-equities domain catalog.", + "limitations": [ + "Historical receipts qualify their named host, input and operation only; this catalog does not run or certify a new host.", + "Component pins and original evidence claims remain canonical; discoveries, source review, deployment and successful execution are distinct.", + "The broad repository union remains shared research inventory at catalogs/us-equities/decision-index.json; it is not an installation or adoption list." + ], + "canonical_sources": { + "components": "manifests/stack.json", + "evidence": "manifests/evidence.json", + "lifecycle": "blueprints/token-native-focus/saturation-audit.json", + "shared_research_inventory": "catalogs/us-equities/decision-index.json" + }, + "decisions_file": "catalogs/foundation/decisions.json", + "layers": [ + { + "id": "native-clients", + "title": "Native clients", + "purpose": "Run ordinary coding, research and review through locally signed-in native clients.", + "selection": "Codex and Claude keep native accounts, model selection, caching and compaction.", + "activation": "Use the intended native client and inspect its loaded project tools; new process defaults require a fresh session.", + "lifecycle_scope": "Dated native source retrieval, process environment and scoped session continuation passed; host-wide restart recovery is separate.", + "next_gap": "Bind fresh-session activation and resumed effects to the next target host without repeating accepted model trials." + }, + { + "id": "instructions-skills", + "title": "Instructions and skills", + "purpose": "Keep project rules short and load detailed task procedures on demand.", + "selection": "Canonical project instructions plus selected upstream skills; reference validation is optional.", + "activation": "Load only the skill needed for the requested operation; repository discovery never activates every skill.", + "lifecycle_scope": "Selected skill format and renderer checks exist; source guidance has no executable lifecycle.", + "next_gap": "Check the target client actually discovers a newly selected skill before claiming integration." + }, + { + "id": "workers", + "title": "Workers and task ownership", + "purpose": "Delegate bounded independent work with an actual base, owned paths and independent acceptance.", + "selection": "Native workers first; Beads only when a dependency-aware queue helps.", + "activation": "One coordinator integrates; each writing worker uses its own worktree and concise task contract.", + "lifecycle_scope": "Native child repair and same-child interruption/crash continuation passed within their fixtures; crash descendant containment required explicit supervisor cleanup.", + "next_gap": "Qualify supported process containment for the observed survivor; independent-host and provider effects remain separate." + }, + { + "id": "isolation", + "title": "Isolation", + "purpose": "Bound filesystem, network, checkout and shared-resource ownership.", + "selection": "Git worktrees for edits; optional native sandbox for a task requiring enforced restrictions.", + "activation": "Assign ownership before writes and use supported OS permissions for enforcement; prose is not a sandbox.", + "lifecycle_scope": "Disposable worktree operations and filesystem/HTTP allow-deny fixtures passed; worktrees do not isolate accounts or services.", + "next_gap": "Qualify only the required platform/network boundary; broader sandbox escape and crash isolation are unknown." + }, + { + "id": "code-navigation", + "title": "Code navigation", + "purpose": "Find exact implementations, symbols, references and structural relationships.", + "selection": "Known source or exact search first; Serena, ast-grep, static graph or scoped jCodeMunch when useful.", + "activation": "Choose one fitting retrieval lane and read original implementation before edits or correctness decisions.", + "lifecycle_scope": "Recorded exact source/symbol checks passed; language coverage and index freshness stay project-specific.", + "next_gap": "Test the actual target language and a changed/deleted symbol after moving to a new project." + }, + { + "id": "document-retrieval", + "title": "Documents and ingestion", + "purpose": "Retrieve bounded, source-attributed documentation and supported document text.", + "selection": "Scoped QMD BM25, selected Context Hub documentation, MarkItDown HTML and Poppler PDF fixtures.", + "activation": "Name the collection/corpus, refresh changed files, search then read the selected source.", + "lifecycle_scope": "Lexical retrieval and designed PDF/text fixtures passed with retained misses; arbitrary OCR/layout is unknown.", + "next_gap": "Freeze a representative new corpus and negative queries before claiming wider retrieval quality." + }, + { + "id": "semantic-rag", + "title": "Semantic code retrieval", + "purpose": "Retrieve conceptual code using the selected project index and local embeddings.", + "selection": "SocratiCode with Qdrant and the accepted local vLLM embedding runtime.", + "activation": "Activate only the selected project and models; do not index unrelated folders or change the accepted runtime for release novelty.", + "lifecycle_scope": "Native source retrieval and add/change/delete persistence passed; a newer GPU runtime startup failed and remains failed.", + "next_gap": "Retain the accepted environment and collect changed-runtime/GPU acceptance only when a concrete need warrants it." + }, + { + "id": "durable-memory", + "title": "Durable memory", + "purpose": "Preserve scoped decisions, approved durable knowledge and recoverable handoffs across clients.", + "selection": "One ai-memory store as cross-harness memory of record.", + "activation": "Retrieve relevant history when needed; durable writes require explicit intent and recalled text never authorizes actions.", + "lifecycle_scope": "Synthetic migration, scope, restart, backup and empty-target restore passed; capture is bounded, not a full transcript.", + "next_gap": "Establish independent-host/key recovery and the target host production activation separately." + }, + { + "id": "web-research", + "title": "Web research", + "purpose": "Find current primary sources and inspect selected web content.", + "selection": "Native browser, bounded literature retrieval and the upstream Tavily CLI/skills for selected web research.", + "activation": "Use an existing authenticated route on demand; load only the research operation needed.", + "lifecycle_scope": "Dated browser/paper retrieval and Tavily Search/Extract passed. Eight official skills were discovered in fresh Codex probes; broader operations and the active Desktop registry remain separate.", + "next_gap": "Qualify Map, Crawl or Research only for a concrete task; retain current Desktop discovery and account limits." + }, + { + "id": "token-efficiency", + "title": "Context and usage efficiency", + "purpose": "Reduce task context only while preserving required facts, source recovery and answer quality.", + "selection": "Known focused reads, RTK, Context Mode, scoped jCodeMunch, guarded Headroom and selected representations.", + "activation": "Choose the cheapest sufficient lane for each artifact; preserve raw failure output and native caching.", + "lifecycle_scope": "Exact artifact comparisons and mixed native trial results are retained; heuristic counters and consumed usage are separate.", + "next_gap": "Measure complete matched attempts only for a decision-changing optimization; do not infer causal lifetime savings." + }, + { + "id": "quality-evaluation", + "title": "Quality and evaluation", + "purpose": "Use deterministic oracles and independent review to accept the actual requested behavior.", + "selection": "Project tests, browser acceptance, promptfoo fixtures, shell review and structural diffs as applicable.", + "activation": "Freeze useful acceptance and negative cases before a substantive change; reuse matching passing evidence.", + "lifecycle_scope": "Selected deterministic fixtures and browser flows passed; no universal model-quality or production guarantee follows.", + "next_gap": "Add a representative failure oracle when the next task exposes an untested behavior." + }, + { + "id": "ci-supply-chain", + "title": "CI and supply chain", + "purpose": "Check published artifacts, workflow permissions, secret controls and scoped dependency identity.", + "selection": "Native publication checks, zizmor, gitleaks and scoped Syft inventory.", + "activation": "Run the relevant offline checks and current CI for changed inputs; keep private state out of artifacts.", + "lifecycle_scope": "Workflow/secret negative fixtures and clean native token-tool CI passed; inventory is not a vulnerability or provenance verdict.", + "next_gap": "Qualify changed distribution inputs and applicable hosted jobs; no broad vulnerability assurance is accepted." + }, + { + "id": "scheduling-supervision", + "title": "Scheduling and supervision", + "purpose": "Schedule owned work, bound process lifetime and resume unfinished steps deliberately.", + "selection": "Dagu for selected workflows and Linux user-manager supervision for owned process trees.", + "activation": "Use explicit task/service ownership, bounded retries and independent state/effect checks.", + "lifecycle_scope": "Local descendant termination and Dagu cancel/retry/SSH continuation passed; full service reboot and provider cancellation remain unknown.", + "next_gap": "Test an owned scheduled service across reboot and reconcile pending native worker effects before resubmission." + }, + { + "id": "hosting-services", + "title": "Application and service hosting", + "purpose": "Build, run and inspect recoverable local application and MCP services.", + "selection": "Locked Next/React/FastAPI/PostgreSQL fixture; platform-specific container and MCP tools only as needed.", + "activation": "Select the target host recipe, explicit service owner and isolated prefix; external hosting is a separate action.", + "lifecycle_scope": "Typed API/browser flows, migration reversal and rows after restart passed on named hosts; production auth and cloud deployment are unqualified.", + "next_gap": "Qualify independent database restore and production-specific access requirements before broader hosting claims." + }, + { + "id": "recovery-portability", + "title": "Recovery and portability", + "purpose": "Retain pinned inputs and prove usable restore, continuity and cleanup at the intended boundary.", + "selection": "Owned lifecycle recipes, Restic, native application backups and native session resume.", + "activation": "Use exact snapshots and empty restore targets; keep keys/account sign-ins private and separate from the checkout.", + "lifecycle_scope": "Same-host restores and individual session/job continuations passed; a whole-stack independent-host disaster recovery has not.", + "next_gap": "Run independent off-host restore with separately available key recovery and affected service acceptance." + }, + { + "id": "observation-inference", + "title": "Observation and optional inference", + "purpose": "Observe bounded native outcomes and usage; trial local inference or routing only against a concrete gap.", + "selection": "Loopback native telemetry and scoped history; local model and gateway remain optional trials.", + "activation": "Preserve writer/task attribution, account boundaries and native default routes; dashboards do not grant operator authority.", + "lifecycle_scope": "Recorded telemetry reconciles scoped usage; HUD live rendering and exact-model gateway inference remain incomplete.", + "next_gap": "Resolve only the selected unknown attribution, interactive rendering or provider compatibility condition before retrying." + } + ], + "domain_boundary": [ + { + "component_id": "lean", + "catalog": "catalogs/us-equities/README.md", + "scope": "Historical execution engine and market-data assumptions belong to TRADING." + }, + { + "component_id": "alpaca-py", + "catalog": "catalogs/us-equities/README.md", + "scope": "Broker/data SDK contract and observation acceptance belong to TRADING; no order authority is conveyed." + }, + { + "component_id": "skfolio", + "catalog": "catalogs/us-equities/README.md", + "scope": "Only chronological financial splitter/control evidence is accepted; portfolio optimization is not a general foundation capability." + }, + { + "component_id": "edgartools", + "catalog": "catalogs/us-equities/README.md", + "scope": "SEC acquisition and filing provenance belong to the financial data domain." + }, + { + "component_id": "duckdb", + "catalog": "catalogs/us-equities/README.md", + "scope": "Current accepted use is financial/synthetic temporal materialization; a general SQL product claim requires its own workload acceptance." + }, + { + "component_id": "pandas", + "catalog": "catalogs/us-equities/README.md", + "scope": "Current accepted use is exact timestamp parsing and chronological financial controls, not blanket dataframe acceptance." + }, + { + "component_id": "nautilus-trader", + "catalog": "catalogs/us-equities/runtime-target.json", + "scope": "Pinned synthetic trading-engine replay belongs to TRADING; it does not establish historical equities or broker execution." + } + ], + "top_gaps": [ + { + "id": "catalog-capability-separation", + "priority": 1, + "status": "addressed_in_catalog", + "scope": "General foundation capabilities now have an explicit home and scoped claims; the broad research union keeps its existing path.", + "next_action": "Maintain these capability joins when a decision changes; do not migrate or adopt every discovery by directory placement.", + "source_paths": [ + "catalogs/foundation/manifest.json", + "catalogs/foundation/decisions.json", + "catalogs/us-equities/decision-index.json" + ] + }, + { + "id": "worker-cancellation-crash-resume", + "priority": 2, + "status": "partial", + "scope": "One same-child cancellation/crash/resume with an unchanged checkpoint and one local effect passed after explicit supervisor cleanup. The pending wait survived the native runtime crash; automatic descendant containment remains open. A supported user-service cgroup contained the deterministic survivor fixture. The combined native follow-up stopped at a refused prefixed command before checkpoint.", + "next_action": "Use compatible native inherited-tool roles; qualify a deliberately restricted role only after resolving its instruction/tool contract. Context Mode1.0.169 has no supported Agent-routing opt-out; retain the failed trial and existing global permissions.", + "source_paths": [ + "blueprints/convergence-practice/native-worker/README.md", + "blueprints/convergence-practice/native-recovery/README.md", + "blueprints/us-equities/worker-supervision/README.md", + "blueprints/convergence-practice/worker-recovery/README.md", + "docs/restricted-worker-compatibility.md" + ] + }, + { + "id": "offhost-keys-and-service-reboot", + "priority": 3, + "status": "open", + "scope": "Same-host backup/restore and service stop/start do not establish independent off-host key recovery or scheduled-service continuity after reboot.", + "next_action": "Exercise a separately accessible key and exact snapshot on an independent host, then qualify the selected owned scheduled service after reboot.", + "source_paths": [ + "adoption/lifecycle.md", + "blueprints/convergence-practice/wsl-restore/README.md", + "blueprints/convergence-practice/wsl-transport-recovery/README.md" + ] + } + ], + "open_gates": [ + { + "id": "worker-cancellation-crash-resume", + "gap_id": "worker-cancellation-crash-resume" + }, + { + "id": "offhost-keys-and-service-reboot", + "gap_id": "offhost-keys-and-service-reboot" + } + ] +} diff --git a/catalogs/us-equities/README.md b/catalogs/us-equities/README.md index e65ce42df..ee9ac8cf7 100644 --- a/catalogs/us-equities/README.md +++ b/catalogs/us-equities/README.md @@ -1,13 +1,24 @@ # US-equities grand catalog +This is the **trading architecture catalog**. General Codex/Claude runtimes, +workers, skills, memory, retrieval, efficiency and operations are maintained in +the separate [foundation catalog](../foundation/README.md). Trading work reuses +that foundation and adds data, strategy, risk and broker-specific requirements. + +The current selected destination is **NautilusTrader 2.0.0rc5 with IBKR**, plus a +separately validated **Alpaca** data/paper-execution boundary. LEAN remains the +accepted historical comparison engine. See the [current target and official +capability record](runtime-target.json) and updated [north star](../../blueprints/us-equities/north-star.md). +Earlier research waves below retain their original decisions and evidence. + The [current token-practice audit](../../docs/token-practice.md) maps the selected -52 components to their evidence levels and records ten exact artifact comparisons +the then-selected 52 components to their evidence levels and records ten exact artifact comparisons plus four accepted native coding trials. Catalog inclusion does not supply a per-repository token-saving value. -**Dated decision catalog: September 20, 2026.** The north star is native, token-efficient research → reproducible backtesting → Alpaca paper automation. This is an examined selection across layers, not a universal final SOTA ranking or a claim that every listed framework runs together. +**Dated decision catalog: September 20, 2026.** The north star is native research → reproducible backtesting → independently accepted IBKR and Alpaca paper workflows. This is an examined selection across layers, not a universal final SOTA ranking or a claim that every listed framework runs together. -The catalog has **152 baseline repository decision cards covering 147 unique GitHub repositories**, and **20 model entries**. The [combined repository index](repository-index.md) now contains **505 repository identities**, including all 342 public stars and 163 beyond that snapshot. Its [typed decision union](decision-index.json) validates baseline cards, component/candidate records and explicitly registered research supplements together; 1,057 source pointers preserve their different evidence depths. The historical 453-row index remains dated reference material. +The catalog has **152 baseline repository decision cards covering 147 unique GitHub repositories**, and **20 model entries**. The [combined repository index](repository-index.md) now contains **513 repository identities**, including all 342 public stars and 171 beyond that snapshot. Its [typed decision union](decision-index.json) validates baseline cards, component/candidate records and explicitly registered research supplements together; 1,067 source pointers preserve their different evidence depths. The historical 453-row index remains dated reference material. The newest [security-identity review](security-identity-review.md) examines Alpaca, Zipline, Qlib, NautilusTrader, LEAN and WRDS. It separates engine identity/lifetime @@ -72,7 +83,7 @@ summary](convergence-review.json) preserves every remaining gate. ## Recommended convergence -Use native **Codex SDK/Astra + Claude Opus**, **Context Mode/RTK**, **ai-memory**, scoped **QMD/Serena/SocratiCode**, and existing **Nemotron/vLLM/Qdrant**. Keep **DuckDB/Parquet + exchange calendars** for deterministic data work and **LEAN** as the accepted source-built backtest engine. The official **Alpaca adapter** is the paper target, with the SDK as a read-only observer and one future order writer. QuantStats is a proposed reporting layer; selected statistical/ML tools follow only after point-in-time data exists. +Use the selected native capabilities from the foundation catalog. Keep **DuckDB/Parquet + exchange calendars** for deterministic data work and **LEAN** as the accepted source-built comparison engine. Advance the requested **NautilusTrader 2.0.0rc5 / IBKR** destination with its own scoped evidence; **Alpaca** requires a separate adapter because the official Nautilus integration list has none. The Alpaca SDK's authenticated data receipts remain read-only evidence. QuantStats is a proposed reporting layer; selected statistical/ML tools follow only after point-in-time data exists. **OmniRoute** remains an optional route with explicit model fidelity and usage checks; **DeerFlow** remains a research orchestration candidate whose backend, ACP discovery and later bounded native task have separate [receipts](../../blueprints/us-equities/deerflow/research-receipt.json). Add document RAG, a temporal graph, durable scheduling, remote sandboxes or managed hosting only for a concrete requirement. A healthy endpoint, installed SDK or paper simulator is not a complete automated trading runtime. diff --git a/catalogs/us-equities/decision-index.json b/catalogs/us-equities/decision-index.json index 91a9e2ae3..fce40dc33 100644 --- a/catalogs/us-equities/decision-index.json +++ b/catalogs/us-equities/decision-index.json @@ -161,13 +161,13 @@ "zep-ai/graphiti": "getzep/graphiti" }, "counts": { - "repositories": 512, + "repositories": 513, "public_star_repositories": 342, - "beyond_public_stars": 170, - "references": 1065, + "beyond_public_stars": 171, + "references": 1067, "repositories_by_record_type": { "catalog_card": 147, - "component_record": 66, + "component_record": 68, "legacy_candidate": 20, "public_star": 342, "research_supplement": 103, @@ -7623,6 +7623,7 @@ "public_star": true, "record_types": [ "catalog_card", + "component_record", "public_star", "research_supplement", "star_review" @@ -7663,6 +7664,12 @@ "decision": "already_covered", "review_level": "prior_catalog", "review_depth": "prior_evidence_link" + }, + { + "kind": "component_record", + "path": "manifests/stack.json", + "pointer": "/components/67", + "id": "nautilus-trader" } ] }, @@ -11074,6 +11081,22 @@ } ] }, + { + "repository": "https://github.com/tavily-ai/tavily-cli", + "aliases": [], + "public_star": false, + "record_types": [ + "component_record" + ], + "references": [ + { + "kind": "component_record", + "path": "manifests/stack.json", + "pointer": "/components/66", + "id": "tavily-cli" + } + ] + }, { "repository": "https://github.com/tech-leads-club/agent-skills", "aliases": [], diff --git a/catalogs/us-equities/manifest.json b/catalogs/us-equities/manifest.json index dfeb92ae3..29e62bd7f 100644 --- a/catalogs/us-equities/manifest.json +++ b/catalogs/us-equities/manifest.json @@ -56,7 +56,7 @@ "harness_contract": "blueprints/us-equities/harness-contract.json", "broader_reference_union": 171, "star_audit_file": "catalogs/us-equities/star-audit.json", - "grand_index_repositories": 512, - "grand_index_beyond_stars": 170, + "grand_index_repositories": 513, + "grand_index_beyond_stars": 171, "decision_index_file": "catalogs/us-equities/decision-index.json" } diff --git a/catalogs/us-equities/runtime-target.json b/catalogs/us-equities/runtime-target.json new file mode 100644 index 000000000..ee7b2e327 --- /dev/null +++ b/catalogs/us-equities/runtime-target.json @@ -0,0 +1,114 @@ +{ + "schema_version": 1, + "id": "ibkr-nautilus-alpaca-20260920", + "reviewed_at": "2026-09-20", + "scope": "User-selected destination and current primary-source capability boundaries. Installation and broker acceptance are recorded separately.", + "foundation_catalog": "catalogs/foundation/manifest.json", + "north_star": "blueprints/us-equities/north-star.md", + "engine": { + "repository": "https://github.com/nautechsystems/nautilus_trader", + "requested_version": "2.0.0rc5", + "tag": "v2.0.0rc5", + "tag_object": "34de0d6f886a9fe8359f9d6590f43f53c86b1d32", + "source_commit": "1b0a49d2792a9432a3aca3fcb617ce7a630d905e", + "release_published_at": "2026-09-15T06:17:23Z", + "prerelease": true, + "decision": "selected_destination", + "install_command": "uv pip install --python \"$NAUTILUS_ENV/bin/python\" --pre \"nautilus_trader==2.0.0rc5\"", + "supported_python": ">=3.12,<3.15; vanilla CPython", + "linux_support": "Official installation guide: Ubuntu22.04+ and glibc>=2.35; wheel platform tags are not a broader tested-host claim.", + "acceptance": "isolated native upstream synthetic EURUSD quickstart accepted; two economic replay runs; no equity/broker acceptance; fresh GitHub Ubuntu24.04 exact wheel/source installation and two offline replays passed", + "retained_comparison_engine": "LEAN native source-build and dated historical simulation receipts", + "sources": [ + "https://github.com/nautechsystems/nautilus_trader/releases/tag/v2.0.0rc5", + "https://pypi.org/pypi/nautilus_trader/2.0.0rc5/json", + "https://nautilustrader.io/docs/latest/getting_started/installation/", + "https://github.com/nautechsystems/nautilus_trader/blob/1b0a49d2792a9432a3aca3fcb617ce7a630d905e/docs/getting_started/quickstart.py" + ], + "native_receipt": "evidence/receipts/native-nautilus-v2-20260920.json" + }, + "broker_boundaries": [ + { + "id": "ibkr", + "selected_path": "Nautilus native IBKR socket adapter with signed-in TWS or IB Gateway", + "upstream_supported": true, + "local_broker_acceptance": "not_established", + "paper_socket_defaults": { + "tws": 7497, + "gateway": 4002 + }, + "required_inputs": [ + "native gateway sign-in", + "paper account", + "market-data permissions", + "unique client ID", + "risk/universe/session contract" + ], + "limitations": [ + "Adapter installation does not establish socket access, paper order behavior, cancellation races or reconnect reconciliation." + ], + "sources": [ + "https://nautilustrader.io/docs/latest/integrations/interactive_brokers/" + ] + }, + { + "id": "alpaca", + "selected_path": "Official Alpaca SDK for accepted read-only ingestion; separately validated deterministic execution adapter", + "upstream_nautilus_adapter_present": false, + "local_data_acceptance": [ + "bounded AAPL SIP/raw daily bars and corporate actions", + "bounded FB/META identity observations and current asset snapshot" + ], + "local_broker_execution_acceptance": "not_established", + "elite_account_activation": "not_established_by_existing_receipts", + "documented_trading_rate": { + "value": 1000, + "unit": "API calls per minute", + "scope": "Elite Smart Router advertised throughput; not executed trades/fills" + }, + "documented_market_data": { + "basic_historical_calls_per_minute": 200, + "algo_trader_plus_historical_calls_per_minute": 10000, + "equity_history_start_year": 2016, + "boundary": "Feed, subscription, asset and account entitlements remain separate. Unlimited streaming symbols is not unlimited history or throughput." + }, + "sources": [ + "https://alpaca.markets/elite", + "https://docs.alpaca.markets/us/docs/about-market-data-api", + "https://docs.alpaca.markets/us/docs/paper-trading", + "https://nautilustrader.io/docs/latest/integrations/" + ] + } + ], + "accepted_reference_paths": [ + "blueprints/us-equities/historical-simulation/receipt.json", + "blueprints/us-equities/authenticated-data/native-receipt.json", + "blueprints/us-equities/identity-readiness/native-receipt.json", + "blueprints/us-equities/acceptance-wave/README.md", + "evidence/receipts/native-nautilus-ci-20260920.json" + ], + "next_acceptance": [ + { + "id": "pinned-engine-fixture", + "scope": "Exact upstream seed42 synthetic EURUSD quickstart in an isolated environment; useful reports and repeatability; no broker credentials or network" + }, + { + "id": "retained-equity-replay", + "scope": "Reviewed converter for existing hashed equity fixture; compare orders, fills and cash with accepted LEAN baseline" + }, + { + "id": "broker-state-failures", + "scope": "Offline ambiguous submission, duplicate intent, partial fill, cancel race, stale input and restart reconciliation" + }, + { + "id": "separate-paper-adapters", + "scope": "Broker-specific operational acceptance after native sign-in and explicit risk/account scope; no inferred live-trading authority" + } + ], + "limitations": [ + "These are source-reviewed public terms, not a query of the user's current Elite or IBKR account.", + "Synthetic EURUSD engine acceptance is not historical US-equity data or strategy acceptance.", + "Paper fills omit market impact, realistic queue position and some costs; they cannot establish deployable profitability or execution capacity.", + "No broker orders, paid hosting, purchases or live trading are authorized by catalog inclusion." + ] +} diff --git a/docs/ecosystem/index.html b/docs/ecosystem/index.html index 503b4d4a3..609322c35 100644 --- a/docs/ecosystem/index.html +++ b/docs/ecosystem/index.html @@ -3,7 +3,7 @@ - + Native stack — ecosystem manifest @@ -26,6 +28,8 @@