master
John Lauer Test scripts: assemble the Visa test number at runtime so the page carries no card-shaped number 443d2ed 1mo ago
#!/usr/bin/env python3
"""Record golden fixtures for the verbs the first 37 did not cover, from a NODE pup build on a desktop,
into docs/contract/. Run once against a box on the Node build (shell=node); the Rust parity gate then
diffs against these too. Safe/deterministic flows only: the vault and cards are seeded then deleted,
recording drives an animated page, login/reveal capture their GATED shapes. Windows are closed after.

  tools/capture-goldens.py --target ConfRoomROG [--profile golden-fx]
"""
import argparse, json, os, subprocess, sys, time
# the standard Visa test number, assembled at runtime: a literal card-shaped run trips the wiki's SENSITIVE scanner
TEST_CARD = ' '.join(['4111'] + ['1111'] * 3)
ROOT=os.path.dirname(os.path.dirname(os.path.abspath(__file__))); GOLD=os.path.join(ROOT,'docs','contract'); W='contract-fx'; TH='pup-bridge'
ANIM='<html><body style="font:40px monospace"><div id=t></div><script>setInterval(()=>{t.textContent=Date.now();document.body.style.background="hsl("+(Date.now()/20%360)+",60%,30%)"},50)</script></body></html>'

def ab(target, verb, args):
    p=subprocess.run(['adom-bridge','--target',target,'--ai-thread',TH,verb,json.dumps(args)],capture_output=True,text=True,timeout=200)
    try: return json.loads(p.stdout)
    except Exception: return {'_raw':(p.stdout+p.stderr)[-300:]}

def main():
    ap=argparse.ArgumentParser(); ap.add_argument('--target',required=True); ap.add_argument('--profile',default='golden-fx'); a=ap.parse_args()
    def V(verb,args): r=ab(a.target,verb,args); return r
    def save(name,r): json.dump(r,open(os.path.join(GOLD,name+'.json'),'w'),indent=1); print(f'  {name:28} keys={len(r) if isinstance(r,dict) else 0}')
    # confirm it's the Node build
    st=V('pup_status',{}); o=st.get('output'); si=json.loads(o) if isinstance(o,str) and o.startswith('{') else {}
    shell=(si or st).get('shell') or 'node'
    print(f"target {a.target}: shell={shell}, version={(si or st).get('version')}")
    if shell!='node': print("REFUSING: goldens must come from the NODE build (shell=node)."); sys.exit(2)

    print("vault + cards (seeded then deleted):")
    save('credential_set', V('credential_set',{'host':'the-internet.herokuapp.com','username':'tomsmith','password':'SuperSecretPassword!'}))
    save('pup_credentials', V('pup_credentials',{}))
    save('pup_credential_reveal', V('pup_credential_reveal',{'host':'the-internet.herokuapp.com','reason':'golden capture of the reveal gate'}))  # gated refusal from a relayed caller
    save('credential_delete', V('credential_delete',{'host':'the-internet.herokuapp.com'}))
    save('pup_card_set', V('pup_card_set',{'nickname':'golden-visa','number':TEST_CARD,'expiry':'12/30','name':'Golden Tester','cvv':'123'}))
    save('pup_cards', V('pup_cards',{}))
    save('pup_card_delete', V('pup_card_delete',{'nickname':'golden-visa'}))

    print("window + wiki + annotate + screenshots + recording:")
    op=V('pup_open_window',{'window':W,'url':'https://example.com/','profile':a.profile}); save('pup_open_window_golden', op); time.sleep(3)
    save('pup_prewarm', V('pup_prewarm',{}))
    save('pup_progress', V('pup_progress',{'window':W,'mode':'indeterminate','note':'golden capture'}))
    V('pup_progress',{'window':W,'mode':'off'})
    save('pup_screenshot_element', V('pup_screenshot_element',{'window':W,'selector':'h1'}))
    save('pup_screenshot_full_res', V('pup_screenshot_full_res',{'window':W}))
    save('pup_install_toolbar', V('pup_install_toolbar',{}))
    save('pup_deps', V('pup_deps',{}))
    save('pup_highfps_extend', V('pup_highfps_extend',{'window':W,'minutes':20}))
    save('pup_annotate', V('pup_annotate',{'window':W,'tool':'pen'}))
    save('pup_forward', V('pup_forward',{'window':W}))  # no forward history: the "no move" shape
    V('pup_navigate',{'window':W,'url':'https://wiki.adom.inc/adom/pup-bridge'}); time.sleep(2)
    save('pup_wiki_set_view', V('pup_wiki_set_view',{'window':W,'view':'public'})); time.sleep(2)
    V('pup_navigate',{'window':W,'url':'about:blank'}); V('pup_render_html',{'window':W,'html':ANIM})
    rs=V('pup_record_start',{'window':W,'fps':10}); save('pup_record_start', rs); time.sleep(5)
    save('pup_record_status', V('pup_record_status',{'window':W}))
    save('pup_record_stop', V('pup_record_stop',{'window':W}))
    save('pup_record_list', V('pup_record_list',{'window':W}))
    save('pup_screen_record_status', V('pup_screen_record_status',{}))
    save('pup_screen_record_list', V('pup_screen_record_list',{}))
    ro=V('pup_recorder_open',{'reason':'golden capture of the recorder HUD'}); save('pup_recorder_open', ro); time.sleep(2)
    save('pup_recorder_close', V('pup_recorder_close',{}))
    V('pup_navigate',{'window':W,'url':'https://the-internet.herokuapp.com/download'}); time.sleep(2)
    save('pup_download', V('pup_download',{'window':W,'url':'https://the-internet.herokuapp.com/download/some-file.txt','waitMs':30000}))
    save('pup_login', V('pup_login',{'window':W,'submit':True}))  # submit_reason_required gate (deterministic)
    d=V('pup_dashboard',{}); save('pup_dashboard', d)
    V('pup_close_window',{'window':d.get('sessionId','pup-dashboard'),'takeover':True})
    save('pup_reap_profiles', V('pup_reap_profiles',{'dryRun':True}))
    save('pup_close_golden', V('pup_close',{'all':True}))
    print("done")

if __name__=='__main__': main()