Why: the 8788 project-member runtime delivery finished (code merged via #526/#530) but its card and operation records lived only on an unpushed task branch, leaving the worktree impossible to recycle and the record invisible on main. Evidence: card status "已完成(运行目标)" on feature/project-member-runtime 835d807; branch diff against merge-base touches only .task (card + 29 operation records); credential scan finds only variable-based Authorization headers and sha256 digests. Impact: adds .task/archive/feature-project-member-runtime.md and .task/artifacts/project-member-runtime/**; no code, gitlink or policy change. Refs: worktree cleanup 2026-10-18 Co-authored-by: Cursor <cursoragent@cursor.com>
32 lines
2.5 KiB
Python
32 lines
2.5 KiB
Python
import hashlib,json,os,subprocess,urllib.request
|
|
from pathlib import Path
|
|
import client,prepare
|
|
W=client.W;R=prepare.R;DATA=prepare.DATA
|
|
assert (W/'acceptance-http.json').is_file() and (W/'acceptance-browser.json').is_file()
|
|
assert Path('/tmp/project-member-runtime-independent-review.md').is_file()
|
|
ADMIN=Path('/home/weichen/projects/Agent-System-RDM-wt-feature-project-member-access/bin/agent-system-admin')
|
|
NAME='project-member-runtime-20261013'
|
|
env=dict(os.environ);env.pop('AGENT_SYSTEM_DSN',None)
|
|
results={}
|
|
for owner in ['weichen','test']:
|
|
with prepare.db(DATA/'agent-system.db') as c:
|
|
row=c.execute('select revoked from api_keys where owner=? and name=?',(owner,NAME)).fetchone();assert row is not None
|
|
if not row['revoked']:
|
|
r=subprocess.run([str(ADMIN),'apikey','revoke','--owner',owner,'--name',NAME,'--data',str(DATA)],capture_output=True,text=True,env=env)
|
|
assert r.returncode==0,'credential revocation failed; reconcile before retry'
|
|
code,_=client.request(owner,'/api/me');assert code==401,'revoked credential still admitted'
|
|
results[owner]=code
|
|
with prepare.db(DATA/'agent-system.db') as c:
|
|
assert c.execute('select count(*) from api_keys where name=? and revoked=0',(NAME,)).fetchone()[0]==0
|
|
with urllib.request.urlopen(client.BASE+'/',timeout=15) as res:assert res.status==200
|
|
before=json.loads((W/'baseline-private.json').read_text());now=prepare.logical(DATA)
|
|
assert now['agent-system.db:users']==before['logical']['agent-system.db:users'],'existing account/password state changed'
|
|
for a in before['artifacts']:assert prepare.sha(Path(a['content_path']))==a['sha256']
|
|
assert json.loads((R/'manifest.json').read_text())['instance_id']==prepare.INSTANCE
|
|
pid=int((R/'svc.pid').read_text());exe=Path(f'/proc/{pid}/exe').resolve()
|
|
assert exe==(R/'current/bin/agent-system').resolve()
|
|
assert prepare.sha(exe)=='d5db3d0ac292d99582ec91938317af356c050ad61e61f42c097e7faf7a731765'
|
|
(W/'credentials.json').unlink()
|
|
result={'source':'SELF','operation':'succeeded','pid':pid,'release':os.readlink(R/'current'),'binary_sha256':prepare.sha(exe),'instance':prepare.INSTANCE,'root_http':200,'temporary_keys_revoked':results,'plaintext_credential_file_removed':True,'existing_accounts_and_passwords_unchanged':True,'original_artifact_bytes_preserved':len(before['artifacts']),'auth_route':'temporary API credentials; password login NOT_RUN','verification_data_retained':{'empty_conversations':5,'synthetic_private_files':2},'worktrees_retained':True}
|
|
client.save('final-state.json',result);print(json.dumps(result,ensure_ascii=False))
|