2026-10-03 15:25:04 +02:00
#!/usr/bin/env python3
""" Read-only Claude probe from an actual pilot checkout; no production effects. """
from pathlib import Path
import argparse
from datetime import datetime , timezone
import json
import os
import subprocess
import sys
import tempfile
ROOT = Path ( __file__ ) . resolve ( ) . parents [ 1 ]
sys . path . insert ( 0 , str ( ROOT / " src " ) )
from emergent_security . knowledge import Knowledge
2026-10-04 11:32:30 +02:00
from probe_provider import extract_json , unwrap_response , source_preflight , write_report
2026-10-03 15:25:04 +02:00
SCENARIOS = {
" net-kingdom " : ( " compatibility " , " The old generic canon calls Gate House a broker. Explain the current owner mapping and how the reference evaluator relates to live authorization. " ) ,
" ops-warden " : ( " access " , " A coding agent needs a scoped credential. Explain discovery, when warden plan is required before founder steps, and why a readable broader token is insufficient. " ) ,
" tenant-engine " : ( " tenant " , " A tenant admin wants to approve beyond the platform envelope. Explain the next recipient and what this engine can decide. " ) ,
" railiance-master " : ( " deployment " , " A local test passed in build mode. Explain whether a live production change can proceed and who must decide. " ) ,
}
def main ( ) :
parser = argparse . ArgumentParser ( description = __doc__ )
parser . add_argument ( " repo " , choices = SCENARIOS )
parser . add_argument ( " --root " , type = Path , required = True )
parser . add_argument ( " --output " , type = Path , required = True )
args = parser . parse_args ( )
package = Knowledge ( ROOT / " knowledge " )
card , question = SCENARIOS [ args . repo ]
2026-10-04 11:32:30 +02:00
preflight = source_preflight ( package , args . root , " claude " , ( " start " , card ) )
report = { " schema " : " emergent.repository-pilot.v1 " , " repository " : args . repo ,
" provider " : " claude " , " timestamp " : datetime . now ( timezone . utc ) . isoformat ( ) ,
" package_version " : package . catalog [ " version " ] , " package_digest " : package . package_digest ,
" source_status " : preflight [ " cards " ] [ card ] , " source_preflight " : preflight ,
" scope " : " read-only scenario in actual repository " , " status " : " unverified " }
if not preflight [ " ok " ] :
report [ " status " ] = " source-withheld "
write_report ( args . output , report )
return 2
2026-10-03 15:25:04 +02:00
repo = args . root / args . repo
schema = { " type " : " object " , " additionalProperties " : False ,
" properties " : { " package_version " : { " type " : " string " } ,
" answers " : { " type " : " array " , " items " : { " type " : " object " , " additionalProperties " : False ,
" properties " : { key : { " type " : " string " } for key in ( " card " , " source_path " , " route " , " reason " ) } ,
" required " : [ " card " , " source_path " , " route " , " reason " ] } } } ,
" required " : [ " package_version " , " answers " ] }
prompt = (
" This is a read-only situational knowledge pilot. Do not perform operational work, "
" write records, contact services or read credentials. Follow the new orientation "
" pilot pointer in the repository instructions; read the shared start and relevant "
" task card and knowledge/catalog.yaml and knowledge/release.yaml from the sibling "
" emergent-security checkout (sources are indexed in knowledge/sources.yaml). "
" The supervising runner verified the relevant source digests. Answer this scenario: "
+ question + " Return only JSON with package_version and answers containing one "
" object with card, source_path (shared card path actually read), route (actual "
" next recipient, including a human role where appropriate), and reason. "
)
command = [ " claude " , " -p " , " --tools " , " Read " , " --add-dir " , str ( ROOT ) ,
" --permission-mode " , " default " , " --no-session-persistence " , " --max-budget-usd " , " 2 " ,
" --output-format " , " json " , " --json-schema " , json . dumps ( schema ) , prompt ]
try :
run = subprocess . run ( command , cwd = repo , capture_output = True , text = True , timeout = 180 )
raw_dir = Path ( tempfile . mkdtemp ( prefix = " emergent-pilot- " ) )
for name , content in [ ( " stdout " , run . stdout ) , ( " stderr " , run . stderr ) ] :
path = raw_dir / name
path . write_text ( content )
os . chmod ( path , 0o600 )
report [ " exit_code " ] = run . returncode
if run . returncode :
report [ " status " ] = " client-failed "
else :
answer , metadata = unwrap_response ( extract_json ( run . stdout ) )
report . update ( metadata )
report [ " answers " ] = answer [ " answers " ]
report [ " version_correct " ] = answer . get ( " package_version " ) == package . catalog [ " version " ]
report [ " status " ] = " awaiting-semantic-review "
except subprocess . TimeoutExpired :
report [ " status " ] = " timeout "
except ( OSError , ValueError , TypeError ) :
report [ " status " ] = " client-output-unusable "
2026-10-04 11:32:30 +02:00
write_report ( args . output , report )
2026-10-03 15:25:04 +02:00
return 0 if report [ " status " ] == " awaiting-semantic-review " else 2
if __name__ == " __main__ " :
raise SystemExit ( main ( ) )