@staix/agent-hub 0.17.0 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +35 -0
- package/README.md +4 -4
- package/docs/agent-notes/README.md +11 -0
- package/docs/agent-notes/adapters.md +10 -6
- package/docs/agent-notes/benchmarks.md +1 -0
- package/docs/agent-notes/daemon.md +6 -2
- package/docs/agent-notes/local-worker.md +3 -1
- package/docs/agent-notes/tasks.md +11 -2
- package/docs/agent-notes/tests.md +7 -3
- package/docs/dogfood.md +22 -2
- package/docs/memory.md +1 -1
- package/docs/operations.md +162 -35
- package/docs/profiles.md +36 -0
- package/docs/quickstart.md +15 -5
- package/docs/sdlc.md +29 -3
- package/docs/security.md +44 -13
- package/docs/smoke.md +3 -3
- package/docs/specs/2026-09-19-agent-hub-design.md +31 -10
- package/docs/verification/2026-10-25-0.18.0.md +76 -0
- package/docs/verification/2026-10-25-codex-review-live-verdict.md +35 -0
- package/docs/verification/2026-10-25-remote-docker-transport.md +56 -0
- package/docs/verification/2026-10-26-agy-1.4.7.md +69 -0
- package/docs/verification/2026-10-26-claude-implementer-2.1.310.md +69 -0
- package/docs/verification/2026-10-26-headless-claude-shell-context.md +62 -0
- package/docs/verification/2026-10-26-jcode-0.99.1.md +49 -0
- package/docs/verification/2026-10-26-kimi-232-reviewer-compat.md +53 -0
- package/docs/verification/2026-10-26-pi-140-compat.md +41 -0
- package/docs/verification/2026-10-26-qwen-0261-acp.md +60 -0
- package/docs/verification/2026-10-27-0.19.0.md +86 -0
- package/docs/verification/claude-permission-transport-native.py +187 -0
- package/docs/verification/claude-shell-wrapper-host.ts +20 -0
- package/docs/verification/claude-shell-wrapper-native.py +145 -0
- package/docs/verification/pi-140-model-free.ts +57 -0
- package/docs/verification/pi-140-native.mjs +21 -0
- package/docs/verification/profiles/YYYY-MM-DD-general.md +46 -0
- package/docs/verification/profiles/YYYY-MM-DD-research.md +61 -0
- package/docs/verification/profiles/YYYY-MM-DD-writing.md +46 -0
- package/docs/verified.json +24 -18
- package/package.json +2 -2
- package/plugins/agent-hub/.claude-plugin/plugin.json +1 -1
- package/plugins/agent-hub/server.js +364 -98
- package/src/adapters/agy/entry.ts +1 -1
- package/src/adapters/claude-channel.ts +7 -3
- package/src/adapters/claude-implementer.ts +5 -3
- package/src/adapters/compat.ts +32 -18
- package/src/adapters/conformance/fakes/pi-rpc.ts +1 -0
- package/src/adapters/definitions/builtin-metadata.ts +3 -3
- package/src/adapters/definitions/native-factories.ts +7 -2
- package/src/adapters/definitions/reviewer-variants.ts +2 -2
- package/src/adapters/local-worker.ts +5 -3
- package/src/adapters/pi.ts +39 -3
- package/src/adapters/qwen-dual.ts +25 -0
- package/src/adapters/registry-types.ts +6 -2
- package/src/adapters/registry.ts +1 -0
- package/src/cli/agents.ts +69 -7
- package/src/cli/claude-shell-wrapper.ts +54 -0
- package/src/cli/console-state.ts +9 -2
- package/src/cli/help.ts +29 -28
- package/src/cli/identity.ts +87 -6
- package/src/cli/main.ts +198 -71
- package/src/cli/output.ts +11 -2
- package/src/cli/sdlc-output.ts +242 -0
- package/src/cli/task-output.ts +212 -0
- package/src/cli/upgrade-output.ts +57 -0
- package/src/hub/agent-drift.ts +61 -0
- package/src/hub/board.ts +31 -2
- package/src/hub/check-runner.ts +385 -25
- package/src/hub/claude-shell-wrapper.ts +349 -0
- package/src/hub/conductor.ts +5 -0
- package/src/hub/config-apply.ts +16 -7
- package/src/hub/config-edit-host.ts +1 -1
- package/src/hub/config-edit.ts +2 -2
- package/src/hub/config-tier.ts +3 -3
- package/src/hub/daemon.ts +530 -87
- package/src/hub/dogfood-profile.ts +248 -0
- package/src/hub/dogfood-read.ts +77 -14
- package/src/hub/dogfood.ts +5 -1
- package/src/hub/events.ts +1 -1
- package/src/hub/host-executable.ts +21 -1
- package/src/hub/hub-tools.ts +2 -2
- package/src/hub/instances.ts +18 -2
- package/src/hub/lifecycle.ts +1 -1
- package/src/hub/operational-authority.ts +67 -0
- package/src/hub/operational-view.ts +137 -0
- package/src/hub/orphan-process.ts +69 -0
- package/src/hub/permission-mode.ts +1 -1
- package/src/hub/read-only-shell-proof.ts +81 -0
- package/src/hub/read-only-shell.ts +162 -0
- package/src/hub/review-scope.ts +13 -0
- package/src/hub/reviewer-pool-config.ts +3 -2
- package/src/hub/reviewer-pool.ts +3 -0
- package/src/hub/routing.ts +23 -6
- package/src/hub/sdlc-merge.ts +299 -0
- package/src/hub/sdlc-metrics.ts +6 -4
- package/src/hub/sdlc-mirror.ts +129 -0
- package/src/hub/sdlc.ts +58 -12
- package/src/hub/settings.ts +11 -5
- package/src/hub/snapshots.ts +60 -0
- package/src/hub/task-repository.ts +31 -5
- package/src/hub/task-shell-command.ts +85 -0
- package/src/hub/task-shell-default.ts +78 -0
- package/src/hub/task-shell-proof.ts +171 -0
- package/src/hub/task-shell-sandbox.ts +61 -0
- package/src/hub/tasks.ts +378 -27
- package/src/local/deny.ts +91 -11
- package/src/local/sandbox.ts +67 -28
- package/src/local/shell-environment.ts +10 -0
- package/src/local/tools.ts +17 -4
- package/src/ui/index.html +3 -1
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# Model-free native receipt. Usage: python3 this.py OUTPUT --bun /absolute/bun --claude /absolute/claude [--claude ...]
|
|
2
|
+
import argparse, hashlib, http.server, json, os, pathlib, select, shlex, signal, subprocess, sys, threading
|
|
3
|
+
parser=argparse.ArgumentParser(); parser.add_argument('output'); parser.add_argument('--bun',required=True); parser.add_argument('--claude',action='append',required=True)
|
|
4
|
+
args=parser.parse_args(); ROOT=pathlib.Path(args.output).resolve(); ROOT.mkdir(mode=0o700,parents=False,exist_ok=False)
|
|
5
|
+
HOST=pathlib.Path(__file__).with_name('claude-shell-wrapper-host.ts').resolve()
|
|
6
|
+
MCP="import sys,json,os,time\nfor line in sys.stdin:\n try: q=json.loads(line)\n except: continue\n method=q.get('method'); rid=q.get('id')\n if rid is None: continue\n if method=='initialize': r={'protocolVersion':'2024-11-05','capabilities':{'tools':{}},'serverInfo':{'name':'fixture','version':'1'}}\n elif method=='tools/list': r={'tools':[{'name':'approve','description':'Person approval fixture','inputSchema':{'type':'object','properties':{'tool_name':{'type':'string'},'input':{'type':'object'},'tool_use_id':{'type':'string'}},'required':['tool_name','input','tool_use_id'],'additionalProperties':False}}]}\n elif method=='tools/call':\n mode=os.environ['CASE']; args=q.get('params',{}).get('arguments',{})\n if mode=='timeout': time.sleep(60)\n if mode=='approval-timeout': time.sleep(.1)\n if mode=='disconnect': sys.exit(1)\n if mode=='tool-error':\n print(json.dumps({'jsonrpc':'2.0','id':rid,'error':{'code':-32000,'message':'fixture hub unavailable'}}),flush=True); continue\n if mode in ('deny','hook-failure','approval-timeout'): value={'behavior':'deny','message':'no person answered' if mode=='approval-timeout' else 'fixture denied'}\n else:\n updated=args.get('input',{})\n if mode=='normalized' and updated.get('description') in ('probe1','probe2'): updated={'command':os.environ['NORMALIZED'],'description':'host-bound fixture'}\n value={'behavior':'allow','updatedInput':updated}\n with open(os.environ['RECEIPT'],'a') as f: print(json.dumps({'arguments':args,'response':value}),file=f)\n r={'content':[{'type':'text','text':json.dumps(value)}]}\n else: r={}\n print(json.dumps({'jsonrpc':'2.0','id':rid,'result':r}),flush=True)\n"
|
|
7
|
+
(ROOT/'mcp.py').write_text(MCP)
|
|
8
|
+
class Handler(http.server.BaseHTTPRequestHandler):
|
|
9
|
+
def log_message(self,*a): pass
|
|
10
|
+
def do_POST(self):
|
|
11
|
+
q=json.loads(self.rfile.read(int(self.headers['Content-Length'])))
|
|
12
|
+
state=self.server.state
|
|
13
|
+
state['requests']+=1
|
|
14
|
+
if 'count_tokens' in self.path:
|
|
15
|
+
b=json.dumps({'input_tokens':100}).encode(); self.send_response(200);self.end_headers();self.wfile.write(b);return
|
|
16
|
+
msgs=q.get('messages',[])
|
|
17
|
+
with open(state['record'],'a') as f:f.write(json.dumps({'path':self.path,'keys':list(q),'tools':[x.get('name') for x in q.get('tools',[])],'messages':msgs})+'\n')
|
|
18
|
+
count=sum(1 for m in msgs if isinstance(m.get('content'),list) for x in m['content'] if isinstance(x,dict) and x.get('type')=='tool_result'); seen=count>=len(state['commands'])
|
|
19
|
+
content=[{'type':'text','text':'Fixture finished.'}] if seen else [{'type':'tool_use','id':'toolu_probe_'+str(count),'name':'Bash','input':{'command':state['commands'][count],'description':'probe'+str(count)}}]
|
|
20
|
+
result={'id':'msg_probe_'+str(count),'type':'message','role':'assistant','model':'claude-sonnet-4-5','content':content,'stop_reason':'end_turn' if seen else 'tool_use','stop_sequence':None,'usage':{'input_tokens':100,'output_tokens':10}}
|
|
21
|
+
if not q.get('stream'):
|
|
22
|
+
self.send_response(200);self.send_header('Content-Type','application/json');self.end_headers();self.wfile.write(json.dumps(result).encode());return
|
|
23
|
+
self.send_response(200);self.send_header('Content-Type','text/event-stream');self.end_headers()
|
|
24
|
+
start=dict(result);start.update(content=[],stop_reason=None,usage={'input_tokens':100,'output_tokens':0})
|
|
25
|
+
events=[('message_start',{'type':'message_start','message':start})]
|
|
26
|
+
for i,c in enumerate(content):
|
|
27
|
+
block=dict(c)
|
|
28
|
+
if c['type']=='tool_use': block['input']={}
|
|
29
|
+
else: block['text']=''
|
|
30
|
+
events.append(('content_block_start',{'type':'content_block_start','index':i,'content_block':block}))
|
|
31
|
+
delta={'type':'input_json_delta','partial_json':json.dumps(c['input'])} if c['type']=='tool_use' else {'type':'text_delta','text':c['text']}
|
|
32
|
+
events.extend([('content_block_delta',{'type':'content_block_delta','index':i,'delta':delta}),('content_block_stop',{'type':'content_block_stop','index':i})])
|
|
33
|
+
events.extend([('message_delta',{'type':'message_delta','delta':{'stop_reason':result['stop_reason'],'stop_sequence':None},'usage':{'output_tokens':10}}),('message_stop',{'type':'message_stop'})])
|
|
34
|
+
try:
|
|
35
|
+
for e,v in events:self.wfile.write(('event: '+e+'\ndata: '+json.dumps(v)+'\n\n').encode());self.wfile.flush()
|
|
36
|
+
except BrokenPipeError:pass
|
|
37
|
+
|
|
38
|
+
def stop(process):
|
|
39
|
+
if process is None: return True
|
|
40
|
+
try:
|
|
41
|
+
if process.stdin: process.stdin.close()
|
|
42
|
+
try: process.wait(timeout=25)
|
|
43
|
+
except subprocess.TimeoutExpired:
|
|
44
|
+
if process.poll() is None:
|
|
45
|
+
try: os.killpg(process.pid,signal.SIGKILL)
|
|
46
|
+
except ProcessLookupError: pass
|
|
47
|
+
process.wait(timeout=5)
|
|
48
|
+
return process.returncode==0
|
|
49
|
+
except (OSError,subprocess.TimeoutExpired):return False
|
|
50
|
+
|
|
51
|
+
def empty_group(pid):
|
|
52
|
+
try:table=subprocess.run(['/bin/ps','-axo','pgid=,stat='],env={'PATH':'/usr/bin:/bin','LC_ALL':'C','TZ':'UTC'},capture_output=True,text=True,timeout=3)
|
|
53
|
+
except (OSError,subprocess.TimeoutExpired):return False
|
|
54
|
+
if table.returncode or len(table.stdout)>1024*1024:return False
|
|
55
|
+
parsed=[line.split() for line in table.stdout.splitlines() if line.strip()]
|
|
56
|
+
return bool(parsed) and all(len(row)==2 for row in parsed) and not any(row[0]==str(pid) and not row[1].startswith('Z') for row in parsed)
|
|
57
|
+
|
|
58
|
+
def rows(file):
|
|
59
|
+
return [json.loads(line) for line in file.read_text().splitlines() if line]
|
|
60
|
+
|
|
61
|
+
def sha(file):
|
|
62
|
+
digest=hashlib.sha256()
|
|
63
|
+
with file.open('rb') as stream:
|
|
64
|
+
for block in iter(lambda:stream.read(1024*1024),b''):digest.update(block)
|
|
65
|
+
return digest.hexdigest()
|
|
66
|
+
|
|
67
|
+
results=[]
|
|
68
|
+
for raw_binary in args.claude:
|
|
69
|
+
binary=pathlib.Path(raw_binary).resolve(); identity=ROOT/('identity-'+binary.name); identity.mkdir()
|
|
70
|
+
version=subprocess.run([str(binary),'--version'],env={'HOME':str(identity),'CLAUDE_CONFIG_DIR':str(identity/'config'),'PATH':'/usr/bin:/bin'},capture_output=True,text=True,timeout=10)
|
|
71
|
+
assert version.returncode==0 and version.stdout.strip().split()[0] in ('2.1.309','2.1.310'),(version.returncode,version.stdout)
|
|
72
|
+
label=version.stdout.strip().split()[0]; digest=sha(binary)
|
|
73
|
+
for mode in ('context','normalized'):
|
|
74
|
+
d=ROOT/(label+'-'+mode); d.mkdir(); home=d/'home';home.mkdir(); work=d/"work 'quoted'";work.mkdir();(work/'sub').mkdir()
|
|
75
|
+
work=work.resolve(); host_bin=d/"host bin's";host_bin.mkdir(); executable=host_bin/'fixture';counter=d/'effects'
|
|
76
|
+
program='#!/usr/bin/python3\nimport json,os,pathlib,sys\np=pathlib.Path('+repr(str(counter))+');p.write_text(str(int(p.read_text())+1) if p.exists() else "1")\nprint(json.dumps({"marker":"HOST_EXECUTABLE","cwd":os.getcwd(),"executable":os.path.realpath(sys.argv[0]),"nativeVars":{k:os.environ.get(k) for k in ["GIT_DIR","RIPGREP_CONFIG_PATH"]},"peer":os.environ.get("AGENTHUB_PEER_ID"),"term":os.environ.get("TERM"),"home":os.environ.get("HOME"),"path":os.environ.get("PATH"),"tmpdir":os.environ.get("TMPDIR")}))\n'
|
|
77
|
+
executable.write_text(program);executable.chmod(0o700)
|
|
78
|
+
helper=None;srv=None;native=None
|
|
79
|
+
result={'version':version.stdout.strip(),'binarySha256':digest,'case':mode}
|
|
80
|
+
try:
|
|
81
|
+
rewritten=''
|
|
82
|
+
if mode=='normalized':
|
|
83
|
+
fixture=d/'host.json';fixture.write_text(json.dumps({'root':str(work),'executable':str(executable)}))
|
|
84
|
+
helper=subprocess.Popen([str(pathlib.Path(args.bun).resolve()),str(HOST),str(fixture)],env={'HOME':str(home),'PATH':'/opt/homebrew/bin:/usr/bin:/bin','LANG':'C','TERM':'dumb'},stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=open(d/'host.stderr','w'),text=True,start_new_session=True)
|
|
85
|
+
assert select.select([helper.stdout],[],[],10)[0],'host fixture handshake timeout'
|
|
86
|
+
reply=json.loads(helper.stdout.readline());rewritten=reply['command'];assert isinstance(rewritten,str) and rewritten
|
|
87
|
+
commands=['cd sub && pwd','pwd']+(['pwd'] if mode=='normalized' else [])
|
|
88
|
+
srv=http.server.ThreadingHTTPServer(('127.0.0.1',0),Handler);srv.state={'requests':0,'record':str(d/'api.jsonl'),'commands':commands}
|
|
89
|
+
threading.Thread(target=srv.serve_forever,daemon=True).start()
|
|
90
|
+
config={'mcpServers':{'fixture':{'command':'/usr/bin/python3','args':[str(ROOT/'mcp.py')],'env':{'CASE':mode,'RECEIPT':str(d/'mcp.jsonl'),'NORMALIZED':rewritten}}}}
|
|
91
|
+
(d/'mcp.json').write_text(json.dumps(config));(d/'settings.json').write_text(json.dumps({'permissions':{'ask':['Bash']}}))
|
|
92
|
+
native_env={'HOME':str(home),'CLAUDE_CONFIG_DIR':str(home/'config'),'PATH':'/usr/bin:/bin','ANTHROPIC_BASE_URL':'http://127.0.0.1:'+str(srv.server_port),'ANTHROPIC_API_KEY':'synthetic-probe-not-a-credential','CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC':'1','DISABLE_AUTOUPDATER':'1','GIT_DIR':str(d/'poison-git'),'RIPGREP_CONFIG_PATH':str(d/'poison-rg')}
|
|
93
|
+
argv=[str(binary),'-p','--output-format','stream-json','--verbose','--strict-mcp-config','--mcp-config',str(d/'mcp.json'),'--setting-sources','','--settings',str(d/'settings.json'),'--permission-mode','default','--permission-prompts','host','--permission-prompt-tool','mcp__fixture__approve','--model','claude-sonnet-4-5','Run the fixture commands.']
|
|
94
|
+
native=subprocess.Popen(argv,cwd=work,env=native_env,stdout=open(d/'stdout','w'),stderr=open(d/'stderr','w'),start_new_session=True)
|
|
95
|
+
native.wait(timeout=25);assert native.returncode==0,(native.returncode,(d/'stderr').read_text())
|
|
96
|
+
assert (d/'stderr').read_text()==''
|
|
97
|
+
calls=rows(d/'mcp.jsonl');assert len(calls)==len(commands),calls
|
|
98
|
+
frames={}
|
|
99
|
+
for frame in rows(d/'stdout'):
|
|
100
|
+
if frame.get('type')!='user':continue
|
|
101
|
+
for block in frame.get('message',{}).get('content',[]):
|
|
102
|
+
if block.get('type')=='tool_result':
|
|
103
|
+
ident=block['tool_use_id'];assert ident not in frames;frames[ident]=(frame.get('tool_use_result'),block)
|
|
104
|
+
assert set(frames)=={'toolu_probe_'+str(i) for i in range(len(commands))},frames
|
|
105
|
+
for i,call in enumerate(calls):
|
|
106
|
+
assert call['arguments']=={'tool_name':'Bash','input':{'command':commands[i],'description':'probe'+str(i)},'tool_use_id':'toolu_probe_'+str(i)},call
|
|
107
|
+
expected=call['arguments']['input'] if i==0 or mode=='context' else {'command':rewritten,'description':'host-bound fixture'}
|
|
108
|
+
assert call['response']=={'behavior':'allow','updatedInput':expected},call
|
|
109
|
+
def output(i):
|
|
110
|
+
tool,block=frames['toolu_probe_'+str(i)];assert isinstance(tool,dict) and block.get('is_error') is False and tool.get('stderr')=='' and tool.get('interrupted') is False,(tool,block)
|
|
111
|
+
assert block.get('content')==tool['stdout'];return tool['stdout']
|
|
112
|
+
assert output(0).strip()==str(work/'sub')
|
|
113
|
+
if mode=='context':
|
|
114
|
+
assert output(1).strip()==str(work/'sub');result['persistentCwd']=True
|
|
115
|
+
else:
|
|
116
|
+
observed=json.loads(output(1));assert observed['marker']=='HOST_EXECUTABLE' and observed['cwd']==str(work) and observed['executable']==str(executable.resolve()),observed
|
|
117
|
+
assert observed['nativeVars']=={'GIT_DIR':None,'RIPGREP_CONFIG_PATH':None},observed
|
|
118
|
+
assert observed['peer']=='claude-fixture' and observed['term']=='dumb' and observed['home']==str(home) and observed['path']=='/opt/homebrew/bin:/usr/bin:/bin',observed
|
|
119
|
+
assert observed['tmpdir'] and 'ahub-shell-' in observed['tmpdir'] and str(d) not in observed['tmpdir'],observed
|
|
120
|
+
replay_tool,replay=frames['toolu_probe_2'];assert replay.get('is_error') is True and 'host shell execution refused' in json.dumps(replay_tool),frames['toolu_probe_2']
|
|
121
|
+
assert counter.read_text()=='1',counter.read_text()
|
|
122
|
+
result.update(rewrite=True,priorCd=True,environmentIsolation=True,replayRefused=True,effects=1,quotedPaths=True)
|
|
123
|
+
result.update(passed=True,nativeExit=0,requests=srv.state['requests'],permissionCalls=len(calls))
|
|
124
|
+
except Exception as error:result.update(passed=False,error=repr(error))
|
|
125
|
+
finally:
|
|
126
|
+
if native is not None:
|
|
127
|
+
# Signal only while this unreaped direct child still owns its pid, never a group id after successful wait.
|
|
128
|
+
if native.poll() is None:
|
|
129
|
+
try:os.killpg(native.pid,signal.SIGKILL)
|
|
130
|
+
except ProcessLookupError:pass
|
|
131
|
+
native.wait(timeout=5)
|
|
132
|
+
import time
|
|
133
|
+
deadline=time.monotonic()+1
|
|
134
|
+
while not empty_group(native.pid) and time.monotonic()<deadline:time.sleep(.02)
|
|
135
|
+
result['nativeGroupEmpty']=empty_group(native.pid)
|
|
136
|
+
if not result['nativeGroupEmpty']:result.update(passed=False,cleanup='native group not established empty; no unrelated process signalled')
|
|
137
|
+
result['hostStopped']=stop(helper)
|
|
138
|
+
if not result['hostStopped']:result.update(passed=False,cleanup='host wrapper cleanup failed')
|
|
139
|
+
if srv:srv.shutdown()
|
|
140
|
+
result['binaryUnchanged']=sha(binary)==digest
|
|
141
|
+
if not result['binaryUnchanged']:result.update(passed=False,error='native binary changed during probe')
|
|
142
|
+
results.append(result);print(json.dumps(result),flush=True)
|
|
143
|
+
receipt={'cases':results,'certified':all(row['passed'] for row in results),'account':False,'inference':False}
|
|
144
|
+
(ROOT/'receipt.json').write_text(json.dumps(receipt,indent=2));print(json.dumps({'receipt':str(ROOT/'receipt.json'),'certified':receipt['certified']}),flush=True)
|
|
145
|
+
raise SystemExit(0 if receipt['certified'] else 1)
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import {mkdtempSync, mkdirSync, readFileSync} from 'node:fs';
|
|
2
|
+
import {join, resolve} from 'node:path';
|
|
3
|
+
import {homedir} from 'node:os';
|
|
4
|
+
import {fileURLToPath} from 'node:url';
|
|
5
|
+
import assert from 'node:assert/strict';
|
|
6
|
+
const launcher=resolve(process.argv[2] ?? join(homedir(),'.pi/agent/bin/pi'));
|
|
7
|
+
const packageRoot=resolve(process.argv[3] ?? join(homedir(),'.pi/agent/install/releases/1.4.0/node_modules/@earendil-works/pi-coding-agent'));
|
|
8
|
+
const extension=fileURLToPath(new URL('../../src/pi/extension.ts',import.meta.url));
|
|
9
|
+
const driver=fileURLToPath(new URL('./pi-140-native.mjs',import.meta.url));
|
|
10
|
+
import {PiToolReceipts} from '../../src/pi/tool-receipts.ts';
|
|
11
|
+
const home=mkdtempSync('/tmp/ahub-505-native-home.'); mkdirSync(join(home,'agent'));
|
|
12
|
+
const pkg=JSON.parse(readFileSync(join(packageRoot,'package.json'),'utf8'));
|
|
13
|
+
assert.equal(pkg.name,'@earendil-works/pi-coding-agent');assert.equal(pkg.version,'1.4.0');
|
|
14
|
+
const version=Bun.spawn([launcher,'--version'],{cwd:home,env:{HOME:home,PATH:process.env.PATH!,PI_CODING_AGENT_DIR:join(home,'agent')},stdin:'ignore',stdout:'pipe',stderr:'pipe'});
|
|
15
|
+
const versionTimer=setTimeout(()=>version.kill(),10000);
|
|
16
|
+
const [versionCode,versionOut,versionErr]=await Promise.all([version.exited,new Response(version.stdout).text(),new Response(version.stderr).text()]);clearTimeout(versionTimer);
|
|
17
|
+
assert.equal(versionCode,0);assert.equal(versionOut.trim(),'1.4.0');assert.equal(versionErr,'');
|
|
18
|
+
const ledger=new PiToolReceipts(join(home,'hub.db'));
|
|
19
|
+
let effects=0, providers=0; const events:any[]=[];
|
|
20
|
+
const bridge=Bun.serve({hostname:'127.0.0.1',port:0,async fetch(req){
|
|
21
|
+
const url=new URL(req.url); if(req.headers.get('authorization')!=='Bearer fixture')return new Response('forbidden',{status:403});
|
|
22
|
+
if(url.pathname==='/commands') {await Bun.sleep(25);return Response.json({command:null});}
|
|
23
|
+
const body=await req.json() as any;
|
|
24
|
+
if(url.pathname==='/event'){events.push(body.type);return Response.json({ok:true});}
|
|
25
|
+
if(url.pathname==='/budget')return Response.json({decisions:[]});
|
|
26
|
+
if(url.pathname==='/tool') {
|
|
27
|
+
const text=await ledger.execute(body.sessionId,body.toolCallId,body.name,body.args,async()=>{
|
|
28
|
+
if(body.args.value==='deny')return 'error: fixture permission denied';
|
|
29
|
+
effects++;return 'fixture success';
|
|
30
|
+
});
|
|
31
|
+
return Response.json({text,failed:text.startsWith('error:')});
|
|
32
|
+
}
|
|
33
|
+
providers++;return new Response('provider forbidden',{status:500});
|
|
34
|
+
}});
|
|
35
|
+
const env={HOME:home,PATH:process.env.PATH!,PI_CODING_AGENT_DIR:join(home,'agent'),HUB_EXTENSION:extension,PI_COMPAT_PACKAGE:packageRoot,
|
|
36
|
+
AGENTHUB_PI_BRIDGE_URL:`http://127.0.0.1:${bridge.port}`,AGENTHUB_PI_BRIDGE_TOKEN:'fixture',AGENTHUB_PI_OWNER_TOKEN:'fixture',
|
|
37
|
+
AGENTHUB_PI_TOOLS:JSON.stringify([{name:'compat_probe',description:'model-free fixture',parameters:{type:'object',properties:{value:{type:'string'}},required:['value']}}])};
|
|
38
|
+
const child=Bun.spawn(['node',driver],{cwd:home,env,stdin:'ignore',stdout:'pipe',stderr:'pipe'});
|
|
39
|
+
const timer=setTimeout(()=>child.kill(),10000);
|
|
40
|
+
const [code,stdout,stderr]=await Promise.all([child.exited,new Response(child.stdout).text(),new Response(child.stderr).text()]);clearTimeout(timer);
|
|
41
|
+
console.log(JSON.stringify({code,stdout,stderr,effects,providers,events,isolatedHome:home}));
|
|
42
|
+
const native=Bun.spawn([launcher,'--mode','rpc','--provider','agent-hub-local','--model','fixture','--no-builtin-tools','--no-skills','--no-prompt-templates','--no-extensions','--extension',env.HUB_EXTENSION,'--session-dir',join(home,'native-sessions')],{
|
|
43
|
+
cwd:home,env:{...env,AGENTHUB_PI_RELAY_URL:`http://127.0.0.1:${bridge.port}/v1`,AGENTHUB_PI_RELAY_TOKEN:'fixture',AGENTHUB_PI_MODELS:JSON.stringify([{id:'fixture',name:'fixture'}])},stdin:'pipe',stdout:'pipe',stderr:'pipe'});
|
|
44
|
+
native.stdin.write(JSON.stringify({id:'probe',type:'get_state'})+'\n');
|
|
45
|
+
const nativeTimer=setTimeout(()=>native.kill(),10000);
|
|
46
|
+
let wire='';for await(const chunk of native.stdout){wire+=new TextDecoder().decode(chunk);if(wire.includes('"command":"get_state"')){native.kill();break;}}
|
|
47
|
+
await native.exited;clearTimeout(nativeTimer);const nativeErr=await new Response(native.stderr).text();
|
|
48
|
+
console.log(JSON.stringify({nativeRpc:wire,nativeStderr:nativeErr,providers,events}));
|
|
49
|
+
bridge.stop(true);await ledger.close();
|
|
50
|
+
assert.equal(code,0);assert.equal(stderr,'');
|
|
51
|
+
const result=JSON.parse(stdout);
|
|
52
|
+
assert.equal(result.extension,'loaded');assert.equal(result.first.isError,false);assert.deepEqual(result.first,result.replay);assert.equal(result.denied.isError,true);
|
|
53
|
+
assert.equal(effects,1);assert.equal(providers,0);assert.equal(nativeErr,'');
|
|
54
|
+
const state=wire.trim().split('\n').map(line=>JSON.parse(line)).find(item=>item.command==='get_state');
|
|
55
|
+
assert.equal(state?.success,true);assert.equal(state.data.messageCount,0);assert.ok(state.data.sessionId);assert.ok(state.data.sessionFile);
|
|
56
|
+
assert.ok(events.includes('session_start'));assert.ok(events.includes('session_shutdown'));
|
|
57
|
+
console.log('pi 1.4.0 model-free receipt: PASS');
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { pathToFileURL } from 'node:url';
|
|
2
|
+
const { createAgentSession, DefaultResourceLoader, SessionManager, SettingsManager } = await import(pathToFileURL(`${process.env.PI_COMPAT_PACKAGE}/dist/index.js`).href);
|
|
3
|
+
const cwd = process.env.HOME;
|
|
4
|
+
const settingsManager = SettingsManager.create(cwd, process.env.PI_CODING_AGENT_DIR);
|
|
5
|
+
const loader = new DefaultResourceLoader({cwd, agentDir:process.env.PI_CODING_AGENT_DIR, settingsManager,
|
|
6
|
+
noExtensions:true, additionalExtensionPaths:[process.env.HUB_EXTENSION], noSkills:true, noPromptTemplates:true, noThemes:true});
|
|
7
|
+
await loader.reload();
|
|
8
|
+
const {session, extensionsResult} = await createAgentSession({cwd, agentDir:process.env.PI_CODING_AGENT_DIR,
|
|
9
|
+
resourceLoader:loader, settingsManager, sessionManager:SessionManager.create(cwd, `${cwd}/sessions`), noTools:'builtin'});
|
|
10
|
+
if (extensionsResult.errors.length) throw new Error(JSON.stringify(extensionsResult.errors));
|
|
11
|
+
await session.bindExtensions({mode:'rpc'});
|
|
12
|
+
const tool = session.extensionRunner.getAllRegisteredTools().find(t=>t.definition.name==='compat_probe');
|
|
13
|
+
if (!tool) throw new Error('hub extension tool not registered');
|
|
14
|
+
const invoke = async (id, args) => tool.definition.execute(id, args, new AbortController().signal);
|
|
15
|
+
const first = await invoke('same-call', {value:'fixture'});
|
|
16
|
+
const replay = await invoke('same-call', {value:'fixture'});
|
|
17
|
+
const denied = await invoke('denied-call', {value:'deny'});
|
|
18
|
+
console.log(JSON.stringify({extension:'loaded',first,replay,denied,tools:session.getActiveToolNames()}));
|
|
19
|
+
await session.extensionRunner.emit({type:'session_shutdown'});
|
|
20
|
+
session.dispose();
|
|
21
|
+
process.exit(0);
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# General profile weekly verification receipt
|
|
2
|
+
|
|
3
|
+
Template only. No pilot result or verdict has been recorded.
|
|
4
|
+
|
|
5
|
+
- Week ending: YYYY-MM-DD
|
|
6
|
+
- Profile id: general
|
|
7
|
+
- Window bounds: unknown
|
|
8
|
+
|
|
9
|
+
## Recorded profile JSON
|
|
10
|
+
|
|
11
|
+
Run ahub report --dogfood --since 7d --json once at the review boundary. Replace the null below with only the emitted profile subsection. Preserve numbers and null values. Include no project/person name, task title, path, raw log or model text; use anonymous identifiers where necessary.
|
|
12
|
+
|
|
13
|
+
null
|
|
14
|
+
|
|
15
|
+
## Verification verdicts
|
|
16
|
+
|
|
17
|
+
Choose exactly one listed verdict for each claim after inspecting recorded evidence. Unknown data alone cannot establish support. These placeholders are not verdicts.
|
|
18
|
+
|
|
19
|
+
- writing-live-example
|
|
20
|
+
- Verdict: [supported | partly supported | not supported]
|
|
21
|
+
- Evidence task/event/receipt ids: []
|
|
22
|
+
- Remaining unknowns: unknown
|
|
23
|
+
- general-live-example
|
|
24
|
+
- Verdict: [supported | partly supported | not supported]
|
|
25
|
+
- Evidence task/event/receipt ids: []
|
|
26
|
+
- Remaining unknowns: unknown
|
|
27
|
+
- research-live-example
|
|
28
|
+
- Verdict: [supported | partly supported | not supported]
|
|
29
|
+
- Evidence task/event/receipt ids: []
|
|
30
|
+
- Remaining unknowns: unknown
|
|
31
|
+
- native-model-ingestion
|
|
32
|
+
- Verdict: [supported | partly supported | not supported]
|
|
33
|
+
- Evidence task/event/receipt ids: []
|
|
34
|
+
- Remaining unknowns: unknown
|
|
35
|
+
- context-retention
|
|
36
|
+
- Verdict: [supported | partly supported | not supported]
|
|
37
|
+
- Evidence task/event/receipt ids: []
|
|
38
|
+
- Remaining unknowns: unknown
|
|
39
|
+
- native-account-research
|
|
40
|
+
- Verdict: [supported | partly supported | not supported]
|
|
41
|
+
- Evidence task/event/receipt ids: []
|
|
42
|
+
- Remaining unknowns: unknown
|
|
43
|
+
- research-measurement
|
|
44
|
+
- Verdict: [supported | partly supported | not supported]
|
|
45
|
+
- Evidence task/event/receipt ids: []
|
|
46
|
+
- Remaining unknowns: unknown
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Research profile weekly verification receipt
|
|
2
|
+
|
|
3
|
+
Template only. No pilot result or verdict has been recorded.
|
|
4
|
+
|
|
5
|
+
- Week ending: YYYY-MM-DD
|
|
6
|
+
- Profile id: research
|
|
7
|
+
- Window bounds: unknown
|
|
8
|
+
|
|
9
|
+
## Recorded profile JSON
|
|
10
|
+
|
|
11
|
+
Run ahub report --dogfood --since 7d --json once at the review boundary. Replace the null below with only the emitted profile subsection. Preserve numbers and null values. Include no project/person name, task title, path, raw log or model text; use anonymous identifiers where necessary.
|
|
12
|
+
|
|
13
|
+
null
|
|
14
|
+
|
|
15
|
+
## Research measurements
|
|
16
|
+
|
|
17
|
+
Copy only emitted counts and anonymous task/claim slots. These placeholders remain unknown until recorded evidence supports a value.
|
|
18
|
+
|
|
19
|
+
- Current-plan declared sources and claims per task: unknown
|
|
20
|
+
- Claims reaching a person verdict: unknown
|
|
21
|
+
- Claim slots with model label, person verdict and agreement: unknown
|
|
22
|
+
- Agreement counts by supported/unsupported/unclear label: unknown
|
|
23
|
+
- Recorded task-check outcomes by class alias: unknown
|
|
24
|
+
- Proven checks.fact_check selection and pass/fail by alias: unknown
|
|
25
|
+
- Missing check keys per run: unknown
|
|
26
|
+
- Section-overlap notices and confirmed section edits: unknown
|
|
27
|
+
|
|
28
|
+
Task-check history alone does not prove checks.fact_check ran. A model label or task approval alone does not prove a person verdict or agreement. Preserve every emitted null.
|
|
29
|
+
|
|
30
|
+
## Verification verdicts
|
|
31
|
+
|
|
32
|
+
Choose exactly one listed verdict for each claim after inspecting recorded evidence. Unknown data alone cannot establish support. These placeholders are not verdicts.
|
|
33
|
+
|
|
34
|
+
- writing-live-example
|
|
35
|
+
- Verdict: [supported | partly supported | not supported]
|
|
36
|
+
- Evidence task/event/receipt ids: []
|
|
37
|
+
- Remaining unknowns: unknown
|
|
38
|
+
- general-live-example
|
|
39
|
+
- Verdict: [supported | partly supported | not supported]
|
|
40
|
+
- Evidence task/event/receipt ids: []
|
|
41
|
+
- Remaining unknowns: unknown
|
|
42
|
+
- research-live-example
|
|
43
|
+
- Verdict: [supported | partly supported | not supported]
|
|
44
|
+
- Evidence task/event/receipt ids: []
|
|
45
|
+
- Remaining unknowns: unknown
|
|
46
|
+
- native-model-ingestion
|
|
47
|
+
- Verdict: [supported | partly supported | not supported]
|
|
48
|
+
- Evidence task/event/receipt ids: []
|
|
49
|
+
- Remaining unknowns: unknown
|
|
50
|
+
- context-retention
|
|
51
|
+
- Verdict: [supported | partly supported | not supported]
|
|
52
|
+
- Evidence task/event/receipt ids: []
|
|
53
|
+
- Remaining unknowns: unknown
|
|
54
|
+
- native-account-research
|
|
55
|
+
- Verdict: [supported | partly supported | not supported]
|
|
56
|
+
- Evidence task/event/receipt ids: []
|
|
57
|
+
- Remaining unknowns: unknown
|
|
58
|
+
- research-measurement
|
|
59
|
+
- Verdict: [supported | partly supported | not supported]
|
|
60
|
+
- Evidence task/event/receipt ids: []
|
|
61
|
+
- Remaining unknowns: unknown
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Writing profile weekly verification receipt
|
|
2
|
+
|
|
3
|
+
Template only. No pilot result or verdict has been recorded.
|
|
4
|
+
|
|
5
|
+
- Week ending: YYYY-MM-DD
|
|
6
|
+
- Profile id: writing
|
|
7
|
+
- Window bounds: unknown
|
|
8
|
+
|
|
9
|
+
## Recorded profile JSON
|
|
10
|
+
|
|
11
|
+
Run ahub report --dogfood --since 7d --json once at the review boundary. Replace the null below with only the emitted profile subsection. Preserve numbers and null values. Include no project/person name, task title, path, raw log or model text; use anonymous identifiers where necessary.
|
|
12
|
+
|
|
13
|
+
null
|
|
14
|
+
|
|
15
|
+
## Verification verdicts
|
|
16
|
+
|
|
17
|
+
Choose exactly one listed verdict for each claim after inspecting recorded evidence. Unknown data alone cannot establish support. These placeholders are not verdicts.
|
|
18
|
+
|
|
19
|
+
- writing-live-example
|
|
20
|
+
- Verdict: [supported | partly supported | not supported]
|
|
21
|
+
- Evidence task/event/receipt ids: []
|
|
22
|
+
- Remaining unknowns: unknown
|
|
23
|
+
- general-live-example
|
|
24
|
+
- Verdict: [supported | partly supported | not supported]
|
|
25
|
+
- Evidence task/event/receipt ids: []
|
|
26
|
+
- Remaining unknowns: unknown
|
|
27
|
+
- research-live-example
|
|
28
|
+
- Verdict: [supported | partly supported | not supported]
|
|
29
|
+
- Evidence task/event/receipt ids: []
|
|
30
|
+
- Remaining unknowns: unknown
|
|
31
|
+
- native-model-ingestion
|
|
32
|
+
- Verdict: [supported | partly supported | not supported]
|
|
33
|
+
- Evidence task/event/receipt ids: []
|
|
34
|
+
- Remaining unknowns: unknown
|
|
35
|
+
- context-retention
|
|
36
|
+
- Verdict: [supported | partly supported | not supported]
|
|
37
|
+
- Evidence task/event/receipt ids: []
|
|
38
|
+
- Remaining unknowns: unknown
|
|
39
|
+
- native-account-research
|
|
40
|
+
- Verdict: [supported | partly supported | not supported]
|
|
41
|
+
- Evidence task/event/receipt ids: []
|
|
42
|
+
- Remaining unknowns: unknown
|
|
43
|
+
- research-measurement
|
|
44
|
+
- Verdict: [supported | partly supported | not supported]
|
|
45
|
+
- Evidence task/event/receipt ids: []
|
|
46
|
+
- Remaining unknowns: unknown
|
package/docs/verified.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"documents": {
|
|
4
4
|
"README.md": {
|
|
5
|
-
"verifiedAgainst": "
|
|
5
|
+
"verifiedAgainst": "bc8a7f25f5ca93563bf1d43aca374b0c85560356",
|
|
6
6
|
"paths": [
|
|
7
7
|
"package.json",
|
|
8
8
|
"src/",
|
|
@@ -11,14 +11,14 @@
|
|
|
11
11
|
]
|
|
12
12
|
},
|
|
13
13
|
"docs/security.md": {
|
|
14
|
-
"verifiedAgainst": "
|
|
14
|
+
"verifiedAgainst": "bc8a7f25f5ca93563bf1d43aca374b0c85560356",
|
|
15
15
|
"paths": [
|
|
16
16
|
"src/",
|
|
17
17
|
"templates/"
|
|
18
18
|
]
|
|
19
19
|
},
|
|
20
20
|
"docs/operations.md": {
|
|
21
|
-
"verifiedAgainst": "
|
|
21
|
+
"verifiedAgainst": "bc8a7f25f5ca93563bf1d43aca374b0c85560356",
|
|
22
22
|
"paths": [
|
|
23
23
|
"package.json",
|
|
24
24
|
"src/",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
]
|
|
36
36
|
},
|
|
37
37
|
"docs/quickstart.md": {
|
|
38
|
-
"verifiedAgainst": "
|
|
38
|
+
"verifiedAgainst": "bc8a7f25f5ca93563bf1d43aca374b0c85560356",
|
|
39
39
|
"paths": [
|
|
40
40
|
"package.json",
|
|
41
41
|
"src/",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
]
|
|
44
44
|
},
|
|
45
45
|
"docs/agent-notes/adapters.md": {
|
|
46
|
-
"verifiedAgainst": "
|
|
46
|
+
"verifiedAgainst": "bc8a7f25f5ca93563bf1d43aca374b0c85560356",
|
|
47
47
|
"paths": [
|
|
48
48
|
"src/adapters/",
|
|
49
49
|
"src/pi/",
|
|
@@ -71,11 +71,14 @@
|
|
|
71
71
|
"src/hub/roster.ts",
|
|
72
72
|
"src/hub/instances.ts",
|
|
73
73
|
"src/hub/action-enforce.ts",
|
|
74
|
-
"src/hub/permission-payload.ts"
|
|
74
|
+
"src/hub/permission-payload.ts",
|
|
75
|
+
"src/hub/read-only-shell.ts",
|
|
76
|
+
"src/hub/read-only-shell-proof.ts",
|
|
77
|
+
"src/hub/operational-authority.ts"
|
|
75
78
|
]
|
|
76
79
|
},
|
|
77
80
|
"docs/agent-notes/benchmarks.md": {
|
|
78
|
-
"verifiedAgainst": "
|
|
81
|
+
"verifiedAgainst": "bc8a7f25f5ca93563bf1d43aca374b0c85560356",
|
|
79
82
|
"paths": [
|
|
80
83
|
"scripts/benchmarks/",
|
|
81
84
|
"test/benchmarks/",
|
|
@@ -87,7 +90,7 @@
|
|
|
87
90
|
]
|
|
88
91
|
},
|
|
89
92
|
"docs/agent-notes/budget.md": {
|
|
90
|
-
"verifiedAgainst": "
|
|
93
|
+
"verifiedAgainst": "bc8a7f25f5ca93563bf1d43aca374b0c85560356",
|
|
91
94
|
"paths": [
|
|
92
95
|
"src/hub/budget.ts",
|
|
93
96
|
"src/cli/statusline-tee.ts",
|
|
@@ -111,7 +114,7 @@
|
|
|
111
114
|
]
|
|
112
115
|
},
|
|
113
116
|
"docs/agent-notes/bus.md": {
|
|
114
|
-
"verifiedAgainst": "
|
|
117
|
+
"verifiedAgainst": "bc8a7f25f5ca93563bf1d43aca374b0c85560356",
|
|
115
118
|
"paths": [
|
|
116
119
|
"src/hub/bus.ts",
|
|
117
120
|
"src/hub/envelope.ts",
|
|
@@ -126,7 +129,7 @@
|
|
|
126
129
|
]
|
|
127
130
|
},
|
|
128
131
|
"docs/agent-notes/daemon.md": {
|
|
129
|
-
"verifiedAgainst": "
|
|
132
|
+
"verifiedAgainst": "bc8a7f25f5ca93563bf1d43aca374b0c85560356",
|
|
130
133
|
"paths": [
|
|
131
134
|
"src/hub/daemon.ts",
|
|
132
135
|
"src/hub/control-client.ts",
|
|
@@ -199,7 +202,7 @@
|
|
|
199
202
|
]
|
|
200
203
|
},
|
|
201
204
|
"docs/agent-notes/local-worker.md": {
|
|
202
|
-
"verifiedAgainst": "
|
|
205
|
+
"verifiedAgainst": "bc8a7f25f5ca93563bf1d43aca374b0c85560356",
|
|
203
206
|
"paths": [
|
|
204
207
|
"src/adapters/local-worker.ts",
|
|
205
208
|
"src/local/",
|
|
@@ -211,7 +214,7 @@
|
|
|
211
214
|
]
|
|
212
215
|
},
|
|
213
216
|
"docs/agent-notes/models.md": {
|
|
214
|
-
"verifiedAgainst": "
|
|
217
|
+
"verifiedAgainst": "af22ee0dd9c6a1f4a5c5fc3f10fbfe4875350c1e",
|
|
215
218
|
"paths": [
|
|
216
219
|
"src/models/",
|
|
217
220
|
"src/hub/inference.ts",
|
|
@@ -219,7 +222,7 @@
|
|
|
219
222
|
]
|
|
220
223
|
},
|
|
221
224
|
"docs/agent-notes/tasks.md": {
|
|
222
|
-
"verifiedAgainst": "
|
|
225
|
+
"verifiedAgainst": "bc8a7f25f5ca93563bf1d43aca374b0c85560356",
|
|
223
226
|
"paths": [
|
|
224
227
|
"src/hub/tasks.ts",
|
|
225
228
|
"src/hub/board.ts",
|
|
@@ -251,11 +254,13 @@
|
|
|
251
254
|
"src/hub/spec-read.ts",
|
|
252
255
|
"src/hub/workflow.ts",
|
|
253
256
|
"src/hub/deliverables.ts",
|
|
254
|
-
"src/hub/deliverable-files.ts"
|
|
257
|
+
"src/hub/deliverable-files.ts",
|
|
258
|
+
"src/hub/sdlc-merge.ts",
|
|
259
|
+
"src/hub/sdlc-mirror.ts"
|
|
255
260
|
]
|
|
256
261
|
},
|
|
257
262
|
"docs/agent-notes/tests.md": {
|
|
258
|
-
"verifiedAgainst": "
|
|
263
|
+
"verifiedAgainst": "bc8a7f25f5ca93563bf1d43aca374b0c85560356",
|
|
259
264
|
"paths": [
|
|
260
265
|
"test/",
|
|
261
266
|
"scripts/check.sh",
|
|
@@ -274,11 +279,12 @@
|
|
|
274
279
|
"scripts/changed-tests.mjs",
|
|
275
280
|
"scripts/check-closing-refs.mjs",
|
|
276
281
|
".github/workflows/closing-refs.yml",
|
|
277
|
-
"scripts/lib/ts-ast.ts"
|
|
282
|
+
"scripts/lib/ts-ast.ts",
|
|
283
|
+
"test/cli-json-guard.test.ts"
|
|
278
284
|
]
|
|
279
285
|
},
|
|
280
286
|
"docs/agent-notes/README.md": {
|
|
281
|
-
"verifiedAgainst": "
|
|
287
|
+
"verifiedAgainst": "bc8a7f25f5ca93563bf1d43aca374b0c85560356",
|
|
282
288
|
"paths": [
|
|
283
289
|
"src/cli/console-state.ts",
|
|
284
290
|
"src/cli/attention.ts",
|
|
@@ -287,7 +293,7 @@
|
|
|
287
293
|
]
|
|
288
294
|
},
|
|
289
295
|
"src/cli/help.ts": {
|
|
290
|
-
"verifiedAgainst": "
|
|
296
|
+
"verifiedAgainst": "bc8a7f25f5ca93563bf1d43aca374b0c85560356",
|
|
291
297
|
"paths": [
|
|
292
298
|
"src/cli/main.ts",
|
|
293
299
|
"src/cli/launch.ts",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@staix/agent-hub",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.0",
|
|
4
4
|
"description": "Native multi-agent hub: Claude Code, Codex, Kimi Code, Pi and local inference as peers in one project",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"bun": ">=1.4.2"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@staix/agent-mem": "0.
|
|
20
|
+
"@staix/agent-mem": "0.10.0"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
23
|
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-hub",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.0",
|
|
4
4
|
"description": "Channel between Claude Code and the agent-hub daemon: peer messages from Codex, Kimi and the local worker arrive as channel events; hub_send replies.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Young Joon Lee",
|