Skip to content

perf(cli): reuse selected dispatch for manager Inbox commands - #6989

Open
hhyykk wants to merge 1 commit into
loopx-project:mainfrom
hhyykk:codex/inbox-cli-caller-adoption-20261021
Open

hhyykk wants to merge 1 commit into
loopx-project:mainfrom
hhyykk:codex/inbox-cli-caller-adoption-20261021

Conversation

@hhyykk

@hhyykk hhyykk commented Oct 21, 2026

Copy link
Copy Markdown
Collaborator

Goal And Delivered Outcome

Normal manager-inbox commands load the full compatibility CLI, although the selected-command dispatcher already provides the same parser and native runtime request scope. This adopts that existing path and deletes the duplicate compatibility dispatch branch. Inbox command inputs, outputs, guards and durable effects stay the same; unrelated CLI imports disappear.

  • Basis: TypeScript control-plane migration RFC, Stage 3 caller adoption, at 68e99ad93ef1954a0bf90ad7158ffb85cf365f2d.
  • Before → after: the same result publication/replay test fails on the old entrypoint with unexpected module import: loopx.cli and passes with identical response/receipt bytes on the new entrypoint.
  • Base: main; complete within this CLI scope.

Author Declaration

  • Written by: model_agent, OpenAI GPT-6 Codex, for the requesting operator.

Implemented against

Specification: docs/architecture/rfcs/typescript-control-plane-migration-v0.md, revision 68e99ad93ef1954a0bf90ad7158ffb85cf365f2d.

Criterion Disposition Path / evidence
Stage 3: actual caller consumes the existing migrated control path implemented loopx/cli_runtime.py, normal installed CLI
Retire replaced orchestration in the same change implemented old Inbox branch removed from loopx/cli.py; compatibility CLI uses the shared dispatcher
Preserve authority, live source reads and receipts implemented unchanged existing handler/native owners; refusal, publication, replay, conflict and controlled revision checks
Complete R1–R3 / asynchronous delivery migration out_of_scope no completion claim; existing #6855 remains separate

Self-check: production, test and docs guard review; related tests, real disposable File/SQLite records, installed artifacts and fresh main integration. No real model or external delivery qualification claimed.

Scope And Continuation

  • Reuse existing registration, handler, registry/runtime-root resolution and native-controller guard.
  • The existing common dispatcher resolves executable revision once per command. This reuses that scope; source records remain live reads under their existing locks. There is no cross-command data cache.
  • Production economics: 14 added / 14 removed, net 0 lines; no new bridge, dependency, native operation, schema or store. Python provider IO and existing TypeScript semantic owners remain unchanged. RPC counts remain one per File/SQLite result publication, two for the controlled source-session path.
  • Reviewed the 48-PR discovery inventory and refreshed against all 47 currently open PRs, including changed planning/turn heads. No other reviewed PR touches cli_runtime.py or changes Inbox dispatch hunks. refactor(todos): compose full readback in one TypeScript transaction #6874/perf(control-plane): reuse acceptance reads within one Todo snapshot #6984 concern Todo reads; refactor(collaboration): converge return delivery and restart recovery in TypeScript #6855 concerns return delivery/recovery. Shared RFC/README edits and unrelated cli.py hunks are acknowledged; there is no duplicate implementation.
  • An additional native result-store prototype was tested then excluded: caller adoption produced most of the measured benefit with a smaller compatibility surface. No prototype scaffolding is in this diff.

Validation

  • Tested revision: d941ee98c599e6edf5a006d14e6cbe8e07010b86 on 68e99ad93ef1954a0bf90ad7158ffb85cf365f2d.
  • Run state: finished. Input classes: synthetic, public_fixture.
Check kind Result Evidence / limitation
integration passed 325 Python tests covering CLI, manager-context roundtrip, Goal identity, peer store, request amendment/recovery, Inbox recovery and executable request scope; run before rebase, unchanged relevant production/test files
integration passed 63 CLI entrypoint + task-planning tests rerun on final rebased HEAD
unit passed 37 related TS Inbox read/receipt/result-publication/request-control contracts; no TS product diff
static passed control-plane typecheck, scoped Ruff and paired RFC check
regression_parity passed 22 semantic rows across File, SQLite and controlled exact source sessions, plus reverse SQLite run; persisted records equal; rejected operations produce no writes; recording remains delivered:false
regression_parity passed same final regression test loaded against baseline fails on full CLI import and passes on candidate, with independently verified module roots
real_entrypoint passed 240 source-verified fresh Python CLI processes on pinned baseline/candidate series; another 60 fresh processes and seven semantic rows on final main/HEAD
real_backend passed disposable real File and SQLite records; no production state or external provider sends
integration passed normal wheel + sdist builds at final HEAD; independent installed environments, empty-project cwd, no source PYTHONPATH; legacy/exact request, acknowledge, report, separate-process replay, conflict refusal and readback

Complete-command performance

Linux; Python 3.11; Node 24.21.0 / SQLite 3.53.4; disposable synthetic Goal. Each sample starts a fresh Python CLI process, uses a warm managed native runtime and records a new result update. Includes parsing, imports, registry lookup, source reads, RPC and durable result recording. The harness asserts loaded Python and TS roots; each child emits a source-origin proof. No timestamp normalization beyond a fixed semantic-fixture clock and disposable-root substitution.

Fresh final comparison: main 68e99ad93ef1954a0bf90ad7158ffb85cf365f2d versus this HEAD, 15 samples per arm per history; all seven SQLite semantic/persisted-state observations match.

SQLite history p50 ms, base → head p95 ms, base → head p95 change
Small 1034.7 → 371.7 1072.4 → 522.8 -51.3%
Expanded (+32 appended updates) 1035.7 → 351.0 1147.4 → 395.0 -65.6%

Supporting pinned-base repeated/reversed SQLite series (30 samples/arm/history) measured p95 1,096.8 → 386.7 ms and 1,135.5 → 363.6 ms. File/controlled profiles (15/arm) also improved. That earlier baseline was 98709770d80e9c332f3c07d2b545226a6dd17521; the five measured runtime files have unchanged hashes after rebase. Earlier cwd-contaminated and CPU-contended study runs were excluded, not pooled into these figures.

These results qualify this CLI overhead change only. They do not measure task success, model quality, token savings, cold native-runtime startup or the entire LoopX application. Full repository tests, Windows, PostgreSQL, browser flows and real model/provider delivery were not run for this scoped change; hosted CI is separate.

Portable qualification harness and reproduction

Save the script below as qualify.py outside both checkouts. Install repository Python dependencies and run npm ci in both checkouts. Use a qualified Node runtime (the run above used 24.21.0 / SQLite 3.53.4), the same Python interpreter, and idle the machine. Outputs must be separate empty directories. Run sequentially:

python3 qualify.py BASE_CHECKOUT BASE_EVIDENCE --providers file,sqlite,controlled --samples 15
python3 qualify.py HEAD_CHECKOUT HEAD_EVIDENCE --providers file,sqlite,controlled --samples 15

Compare receipt.json rows for exact equality; performance contains every sample and method count, and subprocess_import_receipts proves actual module origins. Synthetic fixtures only; the script disables usage pings and stops its managed native runtime.

Harness SHA256: 703773c33713122c8bbcbfccd7e2201e49573f18f102998d464f55beb8833742.

import argparse,contextlib,hashlib,io,json,os,statistics,subprocess,sys,tempfile,time
from pathlib import Path
p=argparse.ArgumentParser();p.add_argument('repo');p.add_argument('out');p.add_argument('--samples',type=int,default=15);p.add_argument('--providers',default='file,sqlite,controlled');p.add_argument('--history',type=int,default=32);args=p.parse_args()
repo=Path(args.repo).resolve();out=Path(args.out).resolve();out.mkdir(parents=True,exist_ok=True)
os.environ.update(LOOPX_USAGE_PING='0',PYTHONDONTWRITEBYTECODE='1',TMPDIR=str(out/'tmp'),TEMP=str(out/'tmp'),TMP=str(out/'tmp'))
Path(os.environ['TMPDIR']).mkdir(exist_ok=True);tempfile.tempdir=os.environ['TMPDIR']
sys.path[:0]=[str(repo),str(repo/'tests'),str(repo/'tests/control_plane')]
import loopx
from loopx.entrypoint import main
from loopx.control_plane import effect_runtime
from loopx.control_plane.collaboration import inbox,peers,request_control_source
from test_collaboration_goal_instance import _create_source_registry,_brief
from canonical_authority_fixture import promoted_create_fixture
for owner in [inbox,peers,request_control_source]:owner._now=lambda:'2026-10-21T00:00:00+00:00'
assert Path(loopx.__file__).resolve()==repo/'loopx/__init__.py'
assert effect_runtime._control_plane_root().resolve()==repo/'loopx/control_plane'
import_receipts=[]
calls=[];transport=[];original=effect_runtime._request_with_info

def capture(*a,**kw):
 calls.append(kw['method']);began=time.perf_counter();reply=original(*a,**kw)
 transport.append({'method':kw['method'],'params_utf8_bytes':len(json.dumps(kw['params'],ensure_ascii=False,separators=(',',':')).encode()),'ms':(time.perf_counter()-began)*1000});return reply
effect_runtime._request_with_info=capture

def command(root,registry,goal,agent,rid,action,*extra):
 return ['--registry',str(registry),'--runtime-root',str(root),'--format','json','manager-inbox',action,'--goal-id',goal,'--agent-id',agent,'--request-id',rid,*extra]

def invoke(argv):
 stream=io.StringIO();calls.clear();transport.clear();began=time.perf_counter()
 with contextlib.redirect_stdout(stream):code=main(argv)
 return {'exit_code':code,'value':json.loads(stream.getvalue()),'methods':list(calls),'transport':list(transport),'ms':(time.perf_counter()-began)*1000}

def normal(value):
 if isinstance(value,dict):return {k:normal(v) for k,v in value.items()}
 if isinstance(value,list):return [normal(v) for v in value]
 if isinstance(value,str):return value.replace(str(out),'<fixture>')
 return value

def observations(root):
 base=root/'.local/manager-context'
 return {str(f.relative_to(base)):normal(json.loads(f.read_text())) for f in sorted(base.rglob('*.json')) if any(x in f.parts for x in ('entries','decisions','replies'))}

def percentile(values,q):return sorted(values)[min(len(values)-1,int((len(values)-1)*q+.5))]

all_rows=[];perf=[];clock_contract='fixed Inbox/peer/source-control clock for semantic rows; real clock in subprocess performance runs'
try:
 for provider in args.providers.split(','):
  folder=out/provider;folder.mkdir(exist_ok=True)
  if provider=='controlled':
   registry=_create_source_registry(folder);root=folder;goal='delivery';sender='builder';agent='reviewer';ref={'goal_id':goal,'goal_instance_id':'ginst_'+'a'*32}
   from loopx.control_plane.projects.registry_codec import source_session_registry_transaction
   with source_session_registry_transaction(registry,operation='fixture_runtime') as tx:
    configured=tx.payload_copy();configured['common_runtime_root']=str(root);tx.commit(configured)
  else:
   registry,root,_=promoted_create_fixture(folder,provider=provider,registered_agents=['builder','reviewer']);goal='goal-a';sender='builder';agent='reviewer';ref=None
  receipt=peers.request(root,registry,goal,sender,agent,'qualified-review',_brief('Review exact fixture'),caller_goal_ref=ref)
  rid=receipt['request_id'];revision=[]
  if provider=='controlled':
   kw=dict(registry_path=registry,runtime_root=root,goal_ref=ref,receiver_agent_id=agent,request_id=rid,actor_agent_id=sender)
   view=request_control_source.execute_request_control(**kw,operation='inspect')['view']
   revised=request_control_source.execute_request_control(**kw,operation='revise',parameters={'operation_id':'correction','expected_revision':view['revision'],'expected_digest':view['revision_digest'],'brief':_brief('Review corrected evidence'),'reason':'Use current source'},execute=True)
   revision=['--request-revision','2','--request-digest',revised['view']['revision_digest']]
  ack=command(root,registry,goal,agent,rid,'acknowledge','--decision','adopt','--reason','Reviewed exact evidence',*revision)
  report=command(root,registry,goal,agent,rid,'report','--phase','conclusion','--reply-text','The independent fixture review passed.',*(['--request-revision','2'] if provider=='controlled' else []))
  rows=[('unassessed-report',report,1),('ack',ack,0),('ack-replay',ack,0),('conflicting-decision',command(root,registry,goal,agent,rid,'acknowledge','--decision','reject','--reason','Different assessment',*revision),1)]
  if provider=='controlled':rows.append(('stale-revision',command(root,registry,goal,agent,rid,'acknowledge','--decision','adopt','--reason','Reviewed exact evidence','--request-revision','1'),1))
  rows += [('report',report,0),('report-replay',report,0),('conflicting-result',command(root,registry,goal,agent,rid,'report','--phase','conclusion','--reply-text','A conflicting result.',*(['--request-revision','2'] if provider=='controlled' else [])),1)]
  for name,argv,expected in rows:
   before=observations(root);result=invoke(argv);after=observations(root)
   assert result['exit_code']==expected and result['value']['ok']==(expected==0),(provider,name,result)
   if expected:assert before==after,(provider,name,'rejected operation wrote state')
   if name.startswith('report'):assert result['value'].get('delivered') is False,(provider,name,'recording is not delivery')
   all_rows.append({'provider':provider,'case':name,'exit_code':result['exit_code'],'observation':normal(result['value']),'methods':result['methods'],'persisted':after})
  env={**os.environ,'PYTHONPATH':os.pathsep.join([str(repo),str(repo/'tests'),str(repo/'tests/control_plane')])}
  for history in ([0,args.history] if args.samples else []):
   for n in range(history):
    seeded=invoke([*report,'--update-id',f'history-{n}']);assert seeded['exit_code']==0,seeded
   warm=[];full=[]
   for n in range(args.samples):
    sample=invoke([*report,'--update-id',f'warm-{history}-{n}']);assert sample['exit_code']==0,sample;warm.append(sample)
   for n in range(args.samples):
    began=time.perf_counter();pr=subprocess.run([sys.executable,'-c','import pathlib,sys,loopx; actual=pathlib.Path(loopx.__file__).resolve(); assert actual==pathlib.Path('+repr(str(repo/'loopx/__init__.py'))+'); sys.stderr.write("QUALIFIED_SOURCE="+str(actual)+"\\n"); from loopx.entrypoint import main; raise SystemExit(main())',*report,'--update-id',f'cli-{history}-{n}'],cwd=repo,env=env,capture_output=True,text=True,timeout=60)
    assert pr.returncode==0,(pr.stdout,pr.stderr);assert json.loads(pr.stdout).get('delivered') is False
    actual=next(line.removeprefix('QUALIFIED_SOURCE=') for line in pr.stderr.splitlines() if line.startswith('QUALIFIED_SOURCE='));assert Path(actual)==repo/'loopx/__init__.py';import_receipts.append({'provider':provider,'history_seed':history,'sample':n,'module':actual,'verified':True})
    full.append((time.perf_counter()-began)*1000)
   rpc=[v['ms'] for sample in warm for v in sample['transport']]
   perf.append({'provider':provider,'history_seed':history,'warm_p50_ms':statistics.median(v['ms'] for v in warm),'warm_p95_ms':percentile([v['ms'] for v in warm],.95),'full_cli_p50_ms':statistics.median(full),'full_cli_p95_ms':percentile(full,.95),'warm_samples':[v['ms'] for v in warm],'full_cli_samples':full,'methods':warm[-1]['methods'],'params_utf8_bytes':sum(v['params_utf8_bytes'] for v in warm[-1]['transport']),'rpc_p50_ms':statistics.median(rpc),'rpc_p95_ms':percentile(rpc,.95)})
   print(json.dumps({'provider':provider,'history_seed':history,'full_cli_p95_ms':perf[-1]['full_cli_p95_ms'],'methods':perf[-1]['methods']}),flush=True)
 document={'revision':subprocess.check_output(['git','-C',str(repo),'rev-parse','HEAD'],text=True).strip(),'harness_sha256':hashlib.sha256(Path(__file__).read_bytes()).hexdigest(),'clock_contract':clock_contract,'python_module':str(Path(loopx.__file__).resolve()),'native_module_root':str(effect_runtime._control_plane_root().resolve()),'subprocess_import_receipts':import_receipts,'rows':all_rows,'performance':perf,'candidate_files_sha256':{str(f.relative_to(repo)):hashlib.sha256(f.read_bytes()).hexdigest() for f in [repo/'loopx/control_plane/collaboration/inbox.py',repo/'loopx/control_plane/collaboration/inbox_read.ts',repo/'loopx/control_plane/effect_runtime_handlers.ts',repo/'loopx/cli.py',repo/'loopx/cli_runtime.py']}}
 (out/'receipt.json').write_text(json.dumps(document,indent=2)+'\n');print(json.dumps({'rows':len(all_rows),'status':'complete'}),flush=True)
finally:effect_runtime.restart_effect_runtime()

Frontend / Visual Evidence

UI impact: none. No dashboard, browser behavior or presentation surface changes; the paired RFC text documents caller ownership only.

Change Area

  • Control plane (CLI caller adoption)

Technical Direction

Existing TypeScript control-plane migration, Stage 3 caller adoption. Semantic ownership is unchanged.

Shared-authority RFC fixture impact

  • Fixture schema: disposable Goal, registered sender/receiver, collaboration brief, request/decision/result records; File, default SQLite and exact controlled source-session arms.
  • Reviewed no-impact rationale: no authority/schema/provider routing/compatibility projection changes; request validity, revision, refusal, replay and conflict observations remain equal. Existing locks and receiver identity handling remain in the original handler.
  • Provider conformance: File, SQLite, controlled source-session; installed legacy/exact profiles.
  • Read-only legacy/file/PostgreSQL three-arm promotion rehearsal: not run. This PR does not promote a provider or change authority/runtime backend routing; full PostgreSQL/R1–R3 qualification remains outside this CLI dispatch scope.

Boundary Checklist

  • Public-safe diff and description; no private data, raw traces, credentials, internal URLs or machine paths.
  • Existing work reviewed; no duplicate maintainer benchmark project.
  • Scoped to the requested caller improvement.
  • Both RFC languages changed; python3 scripts/check_rfc_bilingual.py --base origin/main --head HEAD passes.
  • UI impact none.
  • DCO sign-off included.

Signed-off-by: aihop <4408344+hhyykk@users.noreply.github.com>

@loopx-agent loopx-agent left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewer: model_agent; gpt-6.1-sol; OpenAI; runtime_reported; reasoning_effort=max.

动机

通过 CLI 读取、确认或上报 Inbox 请求的 Agent 和维护者。原来每次 Inbox 命令都会加载整套兼容 CLI,带修订的上报还会重复识别运行代码;即使只提交一条结论,也要支付这些额外启动成本。当前提交让正常 Inbox 命令复用已有精简分发入口;本次实测整条 CLI 明显加快,确认、拒绝、重放和持久化结果保持一致。此改动不增加请求权限,不缓存请求内容,也不把“记录结论”升级为“已向对方发送”。

完整迁移的常驻内存、冷原生启动、安装态 App、跨平台与真实 Agent 长程任务收益仍须按原迁移方案分别验收。

完整评审 d941ee98c599e6edf5a006d14e6cbe8e07010b86,基线 68e99ad93ef1954a0bf90ad7158ffb85cf365f2d,覆盖全部 6 个文件。作者提供的测量作为上下文,下面的结果均由本次评审重新执行。

改动思路

A second dispatcher or process-global cache would add invalidation/authority risk. The existing shared synchronous dispatch is the correct owner and already supplies the scope, so the change eliminates duplication and leaves source IO live.One existing synchronous CLI family is adopted; native protocol/recording/actual asynchronous delivery, other CLI families and parent migration acceptance are outside this slice.

路径 基线 当前提交
正常 Inbox 命令 加载完整兼容 CLI,独立 Inbox 分支 既有按命令 parser → 共享 dispatcher
完整兼容 CLI 自己的 Inbox 分支 同一个共享 dispatcher
状态、权限与结论 原 handler、实时来源和记录语义 保留原 owner;记录仍不等于发送

表格说明本次源码的调用关系,不代替执行证据。用户继续使用原命令或原管理入口,无需新增设置、重填已知信息或增加确认轮次;也没有以优化为理由删除原有权限检查。

具体改动

关键代码讲解

  1. _SELECTED_COMMANDS 与 parser 只增加已有 manager-inbox 注册入口,没有复制动作、选项或默认值。非法输入仍回到完整 parser 生成原诊断。
  2. _dispatch_common_command 复用同一个 handle_manager_inbox 及 registry/runtime 解析。外层 native-controller guard 仍先执行;实际既有策略对 Inbox 的允许与拒绝范围均未改变。
  3. dispatch_common_command 已提供单次代码身份作用域,因此删除 cli.py 的重复分支即可覆盖完整兼容入口,无需新缓存。源码断言及真实命令确认新路径不加载 loopx.cli。

规范依据是 docs/architecture/rfcs/typescript-control-plane-migration-v0.md,固定版本 68e99ad93ef1954a0bf90ad7158ffb85cf365f2d,在读取实现差异前已经核对。§2.4 约束复用既有 owner;§2.5 保留原输入、诊断与验证顺序;§5 要求实际调用者与成本证据;§6 的 File/SQLite、正常安装包和本次完整 CLI 验证已有当前结果,冷原生启动、RSS、App、跨平台与真实任务收益仍为分开的资格项;§7 仍由既有请求作用域维护代码身份、退出与下次读取。中英文 RFC 同时修改,内容未降低这些条件。

对主干的风险

最危险的回退是新分发入口丢失接收者、修订或 controller 检查,或者把持久化结论误报为已发送。File、SQLite 和精确 Goal 修订来源三种边界的 22 组完整 payload、native method 与持久化 entry/decision/conclusion 对照一致,包含未评估上报、确认、重复确认、冲突、修订过期、上报及重放。拒绝时存储不变,成功仍为 delivered:false。独立旧实现和强制回退 mutant 均触发“不应加载完整 CLI”断言,当前 head 通过;外层 guard 被实际调用,策略未被悄悄加强或跳过。

本次 265 项 Python、24 项 native 测试通过。wheel 与 sdist 重新构建后正常安装到两个独立环境,从空 cwd 调用真实 console,File/SQLite 共 36 个正向、拒绝、重放、独立读取案例通过,声明状态字节不变。性能为 macOS/Python3.12/Node24.21、已预热 native、每种来源与 0/32 条历史各 15 个全新 Python CLI 进程;六组 p95 从 421–460ms 降到 158–218ms,SQLite 为 459.60→162.40ms、451.21→174.24ms。全部样本与模块来源保留,计入完整 Python 进程和真实 provider IO,未将 RPC 次数代作耗时。

语义与 CI 对齐

标准风险 premerge 的 6 项 direct 检查通过,19 项选中检查中 18 项通过、输出差分一项失败。对此没有更改预算:固定最新 main 5bf58c1ca3d21919b15c662bc705c3e069bfb496,原始基线与当前 head 都得到逐项相同的 15 个失败,含规划/action schema 与 3 个 status Markdown 增长 38 字符、上限 32 的失败。相关 quota/status owner 与该检查的因果路径未被此 PR 改动。单独以真正 PR 基线比较 head 的完整 CLI 输出预算通过。这是已独立归因的既有集成红灯,原 premerge 仍记失败,合并前仍要在集成后的精确 head 解决或通过该检查,不能用本次 approval 绕过。

未查询或等待 CI。首次分发构建被本地过期的忽略态 Chat 资源拦住;从当前源码重建资源后,两种正常安装都通过,未修改版本库源码或共享默认 CLI。没有复跑 Windows、真实 PostgreSQL、冷 native 启动、RSS/长时压力、安装态 App 或模型任务;这些仍是原迁移方案的独立资格。

我的整体评价

APPROVE — justified_increment。 既有 dispatcher 的实际接入减少完整 CLI 成本,全部拒绝与记录语义保留;原 main 相对检查红灯继续作为集成门。 这认可当前有实测收益、可独立回退的调用者接入增量,不关闭父级迁移或真实长程任务收益验收,也不授予合并权限。

English verdict: APPROVE for exact head d941ee98c599e6edf5a006d14e6cbe8e07010b86. The selected Inbox dispatcher lowers complete CLI cost while retaining full state, diagnostics, replay and recording-versus-delivery semantics across real local boundaries and normal installed distributions. The identical 15-row base/head main-relative validation failure remains an integration hold; no hard budget or merge gate is waived.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants