P08-02: 旧配置の安全な変更

This commit is contained in:
Agent Control Runner
2026-10-13 21:39:16 +09:00
parent e59206b9b2
commit bb34f443c4
8 changed files with 166 additions and 17806 deletions
+10 -1
View File
@@ -76,8 +76,17 @@ def semantics(snapshot, identity, initial=False):
raise ValueError('operational/construction ownership mismatch')
for jid in identity['jobs']:
if jid not in jobs: raise ValueError('lost paid job')
if initial and (jobs[jid]['progress'] <= 0 or jobs[jid]['state'] != 'BUILDING' or len(jobs[jid]['reserved_cells']) != 6):
starting = jid == identity['starting_job']
stage_ok = (jobs[jid]['progress'] == 0 and jobs[jid]['state'] == 'PLANNED') if starting else (jobs[jid]['progress'] > 0 and jobs[jid]['state'] == 'BUILDING')
if initial and (not stage_ok or not jobs[jid]['construction_cost'] or len(jobs[jid]['reserved_cells']) != 6):
raise ValueError('missing paid old-size progress/reservation')
if identity['starting_job'] not in identity['jobs']: raise ValueError('missing starting stage')
budget = identity['diagnostic_budget']
total = {key:sum(row['cost'].get(key,0) for row in budget['costs']) for key in ('gold','materials')}
total['gold'] += budget['signing'] + budget['food_cost']
deficit = {key:max(0,value-budget['initial'][key]) for key,value in total.items() if value > budget['initial'][key]}
if budget['seed'] != 42588 or budget['food_quantity'] != 8 or total != budget['needed'] or deficit != budget['deltas']:
raise ValueError('diagnostic resource derivation mismatch')
if len(identity['jobs']) < 2 or identity['dorm'] not in facilities: raise ValueError('mixed jobs/completed facility missing')
tasks = indexed(r['staff']['tasks'],'task_id')
if 'patient' not in staff or 'carrier' not in staff: raise ValueError('lost patient/carrier')
+9 -2
View File
@@ -46,7 +46,7 @@ class Proof:
self.put(prefix+name+'.var',json.dumps(node).encode())
def save(self): (self.path/'index.json').write_text(json.dumps(self.index))
def state(self,operations):
jobs = [{'job_id':j,'state':'BUILDING','progress':466,'reserved_cells':[[x,2,0] for x in range(offset,offset+6)],'construction_cost':{'gold':1}}
jobs = [{'job_id':j,'state':'PLANNED' if j=='j2' else 'BUILDING','progress':0 if j=='j2' else 466,'reserved_cells':[[x,2,0] for x in range(offset,offset+6)],'construction_cost':{'gold':1}}
for j,offset in [('j1',0),('j2',10)]]
facilities = [{'instance_id':'dorm','occupied_cells':[[30,0,1]]},{'instance_id':'clinic','occupied_cells':[[31,0,1]]}]
guests = [{'guest_id':g} for g in ['p08.walker']+['g'+str(n) for n in range(5)]]
@@ -81,7 +81,7 @@ class Proof:
phases = [self.phase(name+'-'+role,role,100+2*number+i) for i,role in enumerate(('writer','reader'))]
self.index['cases'].append({'id':name,'operations':'on' if operations else 'off','kind':'refusal' if refusal else 'positive','directory':prefix[:-1],'phases':phases})
self.index['phases'] += phases
identity = {'jobs':['j1','j2'],'dorm':'dorm','rescue_task':'rescue','logistics_requests':['food'],'ev_requests':['ev'+str(n) for n in range(5)]}
identity = {'starting_job':'j2','diagnostic_budget':{'seed':42588,'food_quantity':8,'food_cost':24,'signing':1,'costs':[{'cost':{'gold':2,'materials':1}}],'initial':{'gold':0,'materials':0},'needed':{'gold':27,'materials':1},'deltas':{'gold':27,'materials':1}},'jobs':['j1','j2'],'dorm':'dorm','rescue_task':'rescue','logistics_requests':['food'],'ev_requests':['ev'+str(n) for n in range(5)]}
original = self.state(operations)
self.variant(prefix,'identity',identity); self.variant(prefix,'original',original); self.variant(prefix,'after-live',original)
before = {}; after = {}
@@ -151,6 +151,7 @@ class EvidenceTests(unittest.TestCase):
'lost_patient':lambda r:r['staff']['staff'].pop(0),
'lost_cargo':lambda r:r['inventory']['inventories'].pop(),
'lost_ev':lambda r:r['elevators']['trips'].pop(),
'missing_start_stage':lambda r:r['construction']['jobs'][1].update(state='BUILDING',progress=1),
}
path = 'pairs/off-positive/original.json'
original = (p.path/path).read_bytes()
@@ -160,6 +161,12 @@ class EvidenceTests(unittest.TestCase):
p.put(path,typed(node)); p.save()
self.assertTrue(c.check(ROOT,p.path),label)
p.put(path,original); p.index = copy.deepcopy(self.baseline); p.save()
path = 'pairs/off-positive/identity.json'
original = (p.path/path).read_bytes()
node = c.decode(json.loads(original)); node['diagnostic_budget']['deltas']['gold'] += 1
p.put(path,typed(node)); p.save()
self.assertTrue(c.check(ROOT,p.path),'resource_delta_mismatch')
p.put(path,original); p.index = copy.deepcopy(self.baseline); p.save()
paths = [('partial_batch','pairs/off-refusal/after-live.json'),('unequal_cross_pid','pairs/on-positive/reader-checkpoint.json'),
('overwritten_original','pairs/off-refusal/original/formal/world.bin'),('overwritten_backup','pairs/off-refusal/backup/formal/world.bin')]
for label,path in paths: