Commit Graph
29 Commits
Author SHA1 Message Date
host ce7fb3afd6 feat: project directory tree + first-round snapshot
- cloud/tree.py: structured worktree tree (dirs first, ignore
  .git/node_modules, symlinks not followed, entry/depth
  truncation flags, text render for injection)
- GET /tasks/{id}/tree with /files auth + worktree resolution,
  max_depth 1..5, max_entries 1..500, escape 400, missing 404,
  cloud/cross-host 409
- MCP get_task_tree translating to the new endpoint
- worker first-round injection of a repo-checkout top-level
  snapshot (2 layers, 120 entries) after repo resolution,
  labelled as checkout snapshot not worktree; skipped for
  coordinator/resume/fork, silent when no host source
- docs/project-tree.md; tests for tree, endpoint, injection,
  MCP translation
2026-10-30 14:46:11 +08:00
host e81ba8d2bf feat: 会话内 LLM 自判 goal / 自动化标记工具,不靠关键词
agent 在回合输出里写 goal-convert 块,worker 在轮次边界
排成 /goal 自后续消息、走已有 followup 转换路径把本会话
转成 goal;写 automation-create 块,worker 在轮次边界
创建自动化定义(权限 create_task、配额整轮门、创建人跟
父任务走、name 缺失自动生成、首次时刻已过去单块拒绝、
bind heartbeat 可绑回本会话)。

automations 新增 first_run_at / run_once:首次时刻只管
首次、之后按间隔算;只跑一次跑过后 is_due / due / claim
三处都不再到期(SQL 到期条件与 Python 口径共用同一
_DUE_SQL);API 创建与更新同步接受这两个字段。

刻意不向 LLM 自动注入工具指南:避免 prompt 臃肿,格式
只写进 docs/marker-tools.md 与 README,需要时由用户在
会话里手动告诉 agent;服务端不按关键词再猜意图。

单测 cloud/tests/test_session_goal_automation.py 12 项,
相关回归 218 项全过。
2026-10-30 07:15:05 +08:00
host 9d6430a4d0 成本配额与文件只读标记:task-cost/quota-status/task-files 2026-10-30 05:11:06 +08:00
host 2fd73c1121 任务列表 task-list 标记 + 首轮项目上下文注入 2026-10-30 05:11:06 +08:00
host 73288f08db 待办:todo-list/create/update 标记工具 + 首轮未完成待办注入 2026-10-30 05:11:06 +08:00
host 972203c38f feat(cloud): MCP 云端任务入口 + 上游 0.164 对齐配置
- cloud/mcp_server.py:stdio MCP 服务,把云端任务 REST 翻成
  tools/list / tools/call(health、list_projects、list_tasks、
  get_task、create_task、cancel_task、get_task_cost、
  get_task_trace),底层只走已有 REST,不另开任务逻辑;
  鉴权只认调用方自己的 CODEX_CLOUD_API_KEY(缺了启动失败,
  绝不打印),服务端权限 403 原样透传;create_task 只传已知
  字段,未知字段丢弃;REST 报错时 isError=true。
  单测 test_mcp_server 9 项(假 transport,不联网、不碰真 key)。
- 上游对齐 #80 的可合部分:config.example.toml 加
  [features] daemon_auto_start = false(防 managed daemon 绕过
  版本 pin)+ docs/upstream-164-alignment.md 对齐表;换稳定版
  二进制是另一次主机侧部署动作,本批不做、不谎称已升级。
2026-10-30 01:41:34 +08:00
host 6aa4b45f2c align: 记白名单后端到端全绿结论
- 白名单 6 域名已同步主机并 reload,curl 验 3 个 200、
  time.is 仍 403、worldtimeapi 站侧 TLS 失败(timeapi 兜底)。
- 全新项目任务 6a267baf:web_search 6/6、web_fetch 1/4
  成功(weather.com.cn),答案报出上海时间与北京晴
  5°C、风力 3 级以下,带来源与快照时间,未编造高低温。
- 诚实边界:时间来自系统时钟 + UTC+8 换算,非 timeapi
  fetch;天气来自 fetch 成功的一级来源页。
清理已核,用户剩余 0,生产 health fd9fe5f。
2026-10-30 01:16:49 +08:00
host 84c79302d7 align: 记 MCP env 根因与端到端再测结论
- MCP 子进程不继承 Codex env,docker -e 无用,env 须
  写 config;手动加 env 后 web_search 立刻成功,代码
  修法 dc9b29e 已落地并经全新项目验证(config 自动
  写进 MCP env,web_search 5/6 成功)。
- 端到端仍未报出数字:web_fetch 4 次全败于 Tinyproxy
  403 Filtered,一级来源域名不在 egress 白名单里;
  下一层是主机白名单变更,另等用户定,非代码。
清理已核,用户剩余 0,生产 health fd9fe5f。
2026-10-30 01:16:49 +08:00
host 08d56b15ce websearch: SearXNG 默认只查 bing,360search
默认 general 类别在 Docker 任务容器里要 20.0 秒才回
(wikipedia/wikidata/brave/duckduckgo/google 引擎全超时,
只有 bing+360search 回),撞 MCP 默认 20 秒超时;随后
DuckDuckGo 经代理也超时,整条链失败。代理本身无问题
(Tinyproxy 白名单早已放行 searx 与 duckduckgo)。
修法:_provider_searxng 默认 engines=bing,360search,
SEARXNG_ENGINES 可覆盖、空值恢复旧行为;worker 搜索
env 透传补 SEARXNG_ENGINES。容器实测:钉住后 0.26 秒
回 3 条(首条北京天气),auto 链 0.15 秒成功;旧 20.0 秒。
测试:新增 test_websearch_searxng 3 项,MCP/worker 共
21 项全过。生产未部署。
2026-10-30 01:16:49 +08:00
host 79cc59e72e align: 记真实任务实测:技能在 Docker 任务里被发现并读取
2026-10-30 临时 worker 实测(生产未部署):
- 隔离:depends_on 假依赖门 + run_one 单任务,生产
  worker 永不认领,临时 worker 只跑指定任务。
- 第一次失败:GitHub clone 卡 684K 6 分钟 + run_one
  无心跳线程,300 秒被 sweep 标 interrupted,播种未跑到。
- 第二次成功(test-repo 项目 + 心跳线程):任务
  7235de8f completed,租户 skills/ 含 3 个 SKILL.md,
  trace 里 agent 真读了容器内 live-info/SKILL.md,
  答案按技能规则明说 web_search 不可用、不编造数字。
- 独立未解:Docker 里 web_search 本身 DNS/联网失败,
  与 2026-10-28 探针同类,另批再修,不在本批宣称内。
清理已核:临时用户/项目/任务/租户目录/临时代码全删,
生产 health 仍 3696dad、worker_ok。
2026-10-30 01:16:49 +08:00
host 378cddfb1e align: 修正技能播种路径:codex-home/skills/ 才是用户技能目录
2026-10-30 主机实测(临时 codex-home,生产未动)纠正:
先播 .agents/skills/ 时 skills/list 只返回 5 个系统技能,
3 个自有技能一个没出现;改播 skills/ 后返回 8 个,
3 个自有技能以 scope=user 出现。系统技能本身就在
skills/.system/ 下。
- skill_seed DEST_SUBDIR 由 .agents/skills 改为 skills,
  模块文档与 worker 注释同步修正。
- 测试期望路径同步改为 skills/。
- 对照表补实测结论与附带发现:Codex 自带系统技能
  imagegen,图片生成在 Codex 本体里不是无技能。

验证:skill_seed + chatgpt skills + websearch worker
共 14 项全过。主机探针文件已全部清理,生产未动。
2026-10-30 01:16:49 +08:00
host cf9d17f035 align: 第二批:把技能包播种进租户 codex-home
仿 websearch MCP 播种,默认关:
- cloud/skill_seed.py:cloud/skills/ 的 SKILL.md 拷进租户
  codex-home/.agents/skills/(个人级技能路径,见模块
  文档的路径依据与诚实边界);幂等,租户改过的文件
  绝不覆盖(上报 differs),缺包不阻塞任务。
- cloud/worker.py:新增 --seed-skills,_tenant_dirs 里
  调用播种;老租户下一次任务自动合并;播种失败只记
  日志、不阻塞任务(技能是可选流程说明)。
- cloud/tests/test_skill_seed_worker.py:播种助手 + worker
  开关,仿 test_websearch_worker.py 的结构。
- docs/chatgpt-codex-alignment.md:补第二批说明与实测
  待办(真实 Docker 任务 skills/list + $live-info 调用,
  通过前不宣称生产任务已能用这些技能)。

验证:skill_seed + chatgpt skills + websearch worker
共 14 项全过。本批不改生产配置、不部署,autoscaler
加 --seed-skills 是部署时另行的主机步骤。
2026-10-30 01:16:49 +08:00
host 8a26d1973c align: ChatGPT Codex 对齐第一批:技能包 + 对照表
对照用户提供的 ChatGPT Codex 工具目录,区分可对齐与
不照搬:核心编程工作流已对齐,ChatGPT 托管专属
(CUA、宠物、Docs/Sites 连接器、图片生成模型)不在
开源宿主编排层范围,不凭空宣称对齐。

第一批只补技能层,不改 worker、不改生产行为:
- cloud/skills/live-info:天气/时区/股票/体育,查一级
  来源、带来源和快照时间,绝不编数字。
- cloud/skills/document-tools:LaTeX/Word/PDF/表格/
  演示文稿,先核查工具、缺了明说、产出后重读验证。
- cloud/skills/image-workflow:已有图片处理 + 生成工具
  已配置时才生成,未配置时明说、绝不顶替。
- docs/chatgpt-codex-alignment.md:逐项对照表与不照搬
  的诚实边界,方向为自动化编程任务平台。
- cloud/tests/test_chatgpt_codex_skills.py:校验技能
  frontmatter、名字与目录一致、正文非空、无密钥占位。

验证:新测试 2 项全过。播种进租户 codex-home、 worker
改动、CUA/连接器/图片模型均不在本批,另行评审。
2026-10-30 01:16:49 +08:00
host 4cbdc41e20 fix: task files endpoint resolves tenant docker worktrees
GET /tasks/{id}/files previously returned 409 for all docker tasks
on the grounds that tenant docker shares /app/work per project.
Production inspection shows the worker creates a per-task
host-worktrees/<task-id> subdirectory under the tenant work dir
(62 such dirs under the wwww tenant), so per-task reads are
attributable after all: the endpoint now resolves tenant docker
tasks via tenants/<project>/work/host-worktrees/<task-id> (local
worktree as fallback), never serves the shared /app/work mount
itself, and still 409s cloud/cross-host tasks. Docs and the
harness2_tasks boundary notes are updated to match.
2026-10-29 23:16:01 +08:00
host c20192bce8 harness2: per-role models, sweep batch, task file assets endpoint
- Role models: run_improvement_via_tasks gains role_models
  (probe/editor/selector/reflector) plus --model-<role> CLI flags;
  missing/empty falls back to shared --model, both empty means
  server default, so default behavior is unchanged.
- Sweep: run_sweep + examples/harness2_sweep.py manifest CLI with
  shared library_root (library restore), per-run failure isolation
  and sweep-report.json summary; preflight gates task creation.
- Deliverable assets: GET /tasks/{id}/files for local-executor
  tasks (safe path resolution, UTF-8 text <=256KB, listing <=200;
  docker/cloud/cross-host 409 with explicit reason, since tenant
  Docker shares one /app/work per project and per-task attribution
  would misattribute); probe rollout deliverable_files from the
  endpoint plus DELIVERABLE FILE reply blocks (endpoint wins on
  collision, bad blocks dropped), surfaced in
  deliverables/<label>/files/ context and full_result summary.
- Docs: harness2.md comparison table updated for all three items.
2026-10-29 16:32:58 +08:00
host 4ed1479d7a harness2: upstream gap fill — trivial selection fix, session budget, run_tag validation, preflight check
- select_final trivial condition now k==1 and single-candidate pool,
  regardless of whether a selector is provided (previously gated on
  selector is None, so wired runs always paid for a useless selector
  task at k=1)
- Budget gains max_sessions gate (probe + stage-attempt sessions;
  fmt2 corrections and selector/reflector sessions exempt), the
  backstop for unpriced models where the USD gate never binds
- validate_run_tag (charset, no leading '-', no s<N> seed prefix)
  enforced at run_improvement_via_tasks and the CLI
- CLI --check preflight (base harness, source dir, prompt, tag,
  control-plane /health probe) without creating tasks
- ModeResult.to_dict now includes rollout summaries so a lost probe
  is visible in full_result instead of only on the server
- CLI plan counts the selector only when k>1
2026-10-29 15:31:58 +08:00
host 42abe3cc5b harness2: recursive harness optimization wired to real codex tasks
Port Google Research's Harness^2 method layer (model weights frozen,
only the surrounding harness is optimized): Propose-Probe-Compose with
INV/DOM/AGG editors, parallel/sequential modes, per-domain experience
library, anonymous-product selection, k<=3 hard cap and budget gate.
Execution goes only through the existing control-plane API (upload ->
task with idempotency key -> poll -> trace/cost -> cancel on timeout);
no new server endpoints, no codex flags composed, tasks inherit the
normal executor/sandbox/quota/audit path.

Wiring lessons from four real rounds against production (project
wwww, ledger task): HttpTaskClient retries transient disconnects and
502/503/429 (3 attempts); editors get a worked file-block example, an
explicit <no-change> marker and one feedback retry (.fmt2) instead of
silently accepting notes-only replies; run_task unwraps the server's
result_text JSON envelope (text field holds the real reply) — without
this, line-anchored file-block parsing could never see blocks the
agents were actually emitting. Final round (real4) fully green:
all stages landed, selection non-fallback, experience入库, probe
delivers the correct signed total 85.15.

Tests: 35 harness tests (17 method + 18 wiring incl. fake-control-plane
full round, idempotent replay, retry, format retry, envelope round).
Deliberate deviations from upstream are documented in docs/harness2.md
(no network-unrestricted/sandbox-disabled defaults, auto_apply off,
no benchmark/scorer, probe deliverable = final reply text).
2026-10-29 14:21:18 +08:00
host 3b2fef95fa 任务内标记工具:task-create/task-poll/task-read 移植、wait-threads 接通、新增 task-cancel/task-retry
- 新模块 cloud/marker_tools.py:纯逻辑解析、校验、快照格式化、
  控制门禁、派生代数与直接上限计数
- sandbox 两处解析提取五种标记块;worker 在 5 处投递点与
  _deliver_peer_messages 同款位置执行,报告排成后续消息下一轮回父任务
- wait 每块 cap 到 8 个目标(与服务端 /wait 对齐,spawn 原先的 10 个收紧),
  每轮最多 2 块;取消/重试门禁:同项目、非自己、非 goal、
  派生链或同创建人,另查 create_task / approve_merge 权限,
  查不到时收紧到仅派生链内
- goal 与协调员任务不解析;单测 30 个,cloud 全量 1043 个、4 跳过、0 失败
2026-10-28 10:13:40 +00:00
host b72a2abae4 feat: websearch MCP worker wiring + egress (public SearXNG route)
Worker --websearch-mcp (default off) seeds tenant codex-home with
websearch MCP on _tenant_dirs (container path); old tenants merge
on next task. Autoscaler unit gains the flag. Tinyproxy filter
adds Perplexity/Exa/Tavily/Brave/DuckDuckGo + exact
searx.diante.me (no diante.me wildcard, control plane stays out).
Tests: test_websearch_worker 4 + websearch_mcp 12 + tenant 7 = 23 OK.
Not pushed, not merged, not deployed; SearXNG host/DNS/nginx and
tinyproxy reload are host steps.
2026-10-28 17:26:31 +08:00
host f8acdffb4a feat: web search MCP v1 (oh-my-pi pattern, Python stdlib)
web_search auto chain Perplexity/Exa/Tavily/Brave/SearXNG/DuckDuckGo
with pinned-provider no-fallback, web_fetch with head+tail truncation,
codex-home seeding helper (idempotent, never writes keys).
Tests: cloud/tests/test_websearch_mcp.py 12/12 (mocked HTTP).
Not wired into worker, not deployed, paid backends not live-tested.
2026-10-28 17:14:22 +08:00
host cbc90f9d30 自动记忆:官方 memories 对齐的提取+注入闭环(确定性 v1)
开关默认关(generate/use),设置接口 GET/PUT /users/me/auto-memory-settings,任务级覆盖 POST /tasks/{id}/auto-memory-flags,手动触发 POST /users/me/auto-memory/run,日志 GET /users/me/auto-memory-log。

提取:worker run_loop 轮次边界扫 completed 任务,闲置/时长/长度/外部上下文/配额剩余百分比五道门,脱敏后写 project 级 identity_memories,同一任务去重、同一目标 supersede 合并;只写 project 级,不跨项目泄漏。

注入:worker run_one 首轮把最新各 5 条用户/项目记忆拼进内存 prompt 副本(goal 任务同步改内存 goal),库原 prompt 不动;续跑/断点/协调员不注入,注入失败 fail-open。

v1 诚实边界:extract/consolidation 模型只存设置不调模型;MCP/web 线程内调用暂无 tasks 表标记,外部上下文门只认任务间消息与协调员子任务;无控制台 UI。
2026-10-28 12:12:10 +08:00
host b93666fbe8 合并云端身份与记忆 PR#102(6e9d6dc)到最新 main ea5ab62 2026-10-28 11:58:49 +08:00
host 5fd4e23b68 fix: thread/unarchive 走已归档解析(--archived 列表)
probe9 实测:thread/archive 200 后 thread/unarchive 稳定 404。
根因是 #103 时代的逻辑 bug:unarchive 走普通解析,普通
thread-list 不传 --archived 时只回非归档 thread,刚归档的
thread 永远解析不到。修法只改服务端:_list_task_threads 加
archived 模式(传 --archived,home×provider 穷尽不变),
_resolve 与 _pick_latest_thread 加归档开关,_task_thread_mutate
加 resolve_archived 参数只供 unarchive;rename/archive/compact
仍走非归档解析。生产只读验证:同一 worktree 普通列表 0 条、
archived 列表恰好 1 条(probe9 归档的 thread),其 archived
字段为 None。
2026-10-28 06:10:02 +08:00
host 613ff4e7c4 fix: 线程解析按 home×provider 穷尽回退(共享 home + sub2api)
生产实测:app-server 按进程 provider 过滤 thread/list,
不带 sub2api 注入看不到 sub2api 下建的 thread;本地
worker 又用共享 home 而非租户 home。旧解析只查租户
home + 缺省 provider,本地任务一律 404。

修法(只改服务端,不动派发):_run_host_cli 支持顶层
--model-provider;_list_task_threads 按 home(租户→共享,
共享取 host-config-host.json 的 codex_home)× provider
(缺省→sub2api,仅配了 SUB2API_BASE_URL 时)穷尽,首个
非空即停;_resolve_task_thread 把 provider 带给后续的
thread-read/rename/archive CLI;_task_thread_read 改用
解析出的 home + provider(此前误用租户 home)。

三套件:cloud 957 OK(4 跳过)、host 91 OK、deploy 29 OK。
新测试 9 个。未动派发:本地改租户 home 会丢共享 home
里的 skills,另案处理。
2026-10-28 05:36:18 +08:00
host cf08c4cf37 feat: 线程生命周期对齐 15 项(bindings/refs/快照/心跳绑定/移交落点)
对照 Codex app 第二批:GET /tasks/{id}/bindings(项目/
环境/主机/worktree/PR/附件/血缘总表)、/refs 外部引用
增删查、/worktree/archive 快照(branch/head/status/diff/
untracked 路径)与 restore(目录在才解归档、目录删了
409 附快照)、自动化 bind + heartbeat(走 thread/message
同款投递路,cron 绑定不唤醒)、移交 completed 后任务
worktree_host 跟随切换、pr/checks 响应补 head_sha、
thread/read 的 tool 条目补 server/status。

诚实边界见 docs/thread-lifecycle-align.md:已有 worktree
附加、自动化变化静默、建议器、服务端定时触发器未实现;
Memory 对位是待合的 PR #102,本批不重复实现。

三套件:cloud 948 OK(4 跳过)、host 91 OK、deploy 29 OK
2026-10-28 04:56:22 +08:00
host 755029f220 feat: 线程等待与状态读取 8 项(wait/read/message/handoff/worktree/pr-checks/automation/sleep)
对照 Codex app:wait_threads 首变+afterCursor+8上限、
read_thread 详情摘要、send_message_to_thread 复活失败任务、
handoff 登记与上报轮询、worktree 派生状态、PR checks JSON+
check-runs 日志与注释、automation GET/PATCH、clock.sleep
(API+host)。诚实边界见 docs/thread-wait-ops.md:无
worktree 阶段流、无 automation 变化静默、无独立测试结果
记录、handoff 服务端不执行迁移、wait 仅数据库级变化检测。

三套件:cloud 940 OK(4 跳过)、host 91 OK、deploy 29 OK
2026-10-28 04:33:20 +08:00
host 6e9d6dc5e8 云端身份与记忆:用户画像+分级记忆,不动 thread
- 新增 cloud/identity.py:user_profiles(显示名/时区/偏好,偏好禁密钥键)
  与 identity_memories(user 级仅本人可见、project 级项目成员可见,
  kind fact/preference/decision/convention,supersede 链+物理删除)。
- server 新增 /users/me/profile、/users/me/memories、/projects/{id}/
  identity-memories、/users/me/identity-context,项目记忆先过项目
  read/create_task 门;上下文只显式取用,不自动注入任务/thread。
- PG schema 与迁移清单同步新增两张 TEXT 主键表,序列清单不动;
  server 补 do_PUT 入口(/users/me/profile 首个 PUT 路由)。
- 新测试 11 个;三套件 cloud 937 OK(4 跳过)、host 89 OK、deploy 29 OK。
- 未动:host.py、worker、CODEX_HOME、旧 summaries 表、控制台 UI;
  未推、未建 PR、未部署。
2026-10-28 03:43:02 +08:00
host 076ba01c74 cloud: fill gaps (memory/KB/cost/models endpoints, WAL concurrency, OAuth scaffold, push subscriptions) 2026-10-26 01:32:57 +08:00
host 2f326f33f8 docs: cloud architecture design (remote sandbox, dispatch, GitHub/Slack/push, multi-user, memory/KB, fallback/cost) 2026-10-26 01:07:49 +08:00