Files
TheTree_mock/docs/plans/original-completion-2026-10-02/execution/unlimited-individual-limits-r01/applied_migration.py
T

41 lines
5.1 KiB
Python

from pathlib import Path
import json,hashlib,sqlite3,time,shutil
root=Path('/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/execution/unlimited-individual-limits-r01')
controls=[Path('/private/tmp/the-tree-p24-02-control-r02'),Path('/Users/korizatou114/Antigravity/環境構築/agent-control')]
rows=[]
for i,c in enumerate(controls):
p=c/'runner/core.py'; old=p.read_text(); (root/f'core-before-{i}.py').write_text(old)
new=old.replace(' typ = schema.get("type")\n',' if "anyOf" in schema:\n for choice in schema["anyOf"]:\n try:\n check_schema(value, choice)\n return\n except GateError:\n pass\n raise GateError("結果schemaのanyOf違反")\n typ = schema.get("type")\n if typ == "null":\n require(value is None, "結果schemaの型違反: null")\n return\n',1)
new=new.replace(' require(0 <= contract["max_repair_attempts"] <= self.config["policy"]["max_repair_attempts"], "修正上限超過")',' cap = contract["max_repair_attempts"]; policy_cap = self.config["policy"]["max_repair_attempts"]\n require(cap is None and policy_cap is None or type(cap) is int and cap >= 0 and (policy_cap is None or cap <= policy_cap), "修正上限超過")',1)
new=new.replace('require(task["repairs"] < c["max_repair_attempts"], "repair_limit")','require(c["max_repair_attempts"] is None or task["repairs"] < c["max_repair_attempts"], "repair_limit")',1)
new=new.replace('require(self.db.execute("SELECT COUNT(*) FROM runs WHERE service IS NOT NULL").fetchone()[0] < policy["max_llm_runs"], "budget_limit: LLM起動数上限")','require(policy["max_llm_runs"] is None or self.db.execute("SELECT COUNT(*) FROM runs WHERE service IS NOT NULL").fetchone()[0] < policy["max_llm_runs"], "budget_limit: LLM起動数上限")',1)
assert new != old
p.write_text(new)
schema=c/'schemas/task.json'; s=json.loads(schema.read_text()); (root/f'task-schema-before-{i}.json').write_text(schema.read_text()); s['properties']['max_repair_attempts']={'anyOf':[{'type':'integer','minimum':0},{'type':'null'}],'default':None};schema.write_text(json.dumps(s,ensure_ascii=False,indent=2)+'\n')
rows.append({'control':str(c),'before_sha256':hashlib.sha256(old.encode()).hexdigest(),'after_sha256':hashlib.sha256(new.encode()).hexdigest()})
# Future The Tree registrations inherit null; other projects retain defaults.
for c in controls:
p=c/'runner/core.py'; txt=p.read_text(); needle=' config = {"project": project, "repo": str(repo), "worktree_root": str(wt), "policy": p, "validations": validations}'
txt=txt.replace(needle,' if project.startswith("the-tree-"):\n p = dict(p, max_repair_attempts=None, max_llm_runs=None)\n'+needle,1)
p.write_text(txt)
# Atomic per project; no active inference/config migration races permitted.
records=[]
for cfg in sorted(Path('/Users/korizatou114/Library/Application Support/agent-control').glob('the-tree-*/config.json')):
config=json.loads(cfg.read_text()); db=sqlite3.connect(cfg.parent/'state.sqlite'); db.row_factory=sqlite3.Row
assert not db.execute("SELECT 1 FROM runs WHERE status='running'").fetchone(),str(cfg)
before=json.loads(json.dumps(config)); contracts=[dict(r) for r in db.execute('SELECT * FROM tasks')]
(root/(config['project']+'-before.json')).write_text(json.dumps({'config':before,'tasks':contracts},ensure_ascii=False,indent=2)+'\n')
config['policy']['max_repair_attempts']=None;config['policy']['max_llm_runs']=None
db.execute('BEGIN IMMEDIATE')
for row in contracts:
contract=json.loads(row['contract']);old_cap=contract['max_repair_attempts'];contract['max_repair_attempts']=None
db.execute('UPDATE tasks SET contract=? WHERE id=?',(json.dumps(contract,ensure_ascii=False),row['id']))
data={'owner_instruction':'個別上限を全て撤廃して、勝手に作業停止することを避けて','previous_cap':old_cap,'new_cap':None,'unlimited':True,'repairs_retained':row['repairs'],'state_retained':row['state'],'llm_count_retained':True,'acceptance_and_scope_unchanged':True}
db.execute('INSERT INTO events(task_id,event,data,created) VALUES(?,?,?,?)',(row['id'],'owner_unlimited_individual_attempts',json.dumps(data,ensure_ascii=False),time.time()))
records.append({'project':config['project'],'task':row['id'],'previous_cap':old_cap,'cap':None,'repairs':row['repairs'],'state':row['state']})
cfg.write_text(json.dumps(config,ensure_ascii=False,indent=2)+'\n')
digest=hashlib.sha256(json.dumps(config,sort_keys=True,ensure_ascii=False).encode()).hexdigest()
db.execute('UPDATE meta SET value=? WHERE key=?',(digest,'config_digest')); db.commit();db.close()
(root/'APPLIED.json').write_text(json.dumps({'authorization':'direct human latest instruction','interpretation':'All The Tree individual repair caps and accumulated LLM invocation caps removed. Watchdog timeout and concurrent resource limits retained.','controls':rows,'tasks':records},ensure_ascii=False,indent=2)+'\n')
print(json.dumps({'migrated_tasks':len(records),'projects':len(set(r['project'] for r in records)),'caps':None,'states_and_counts_retained':True}))