Question
怎样让 owner 在聊天中授权 Agent 修改框架,并在修改完成后自动构建、停止旧实例、替换 App、重启、触发验收 Agent 和处理失败?
运行时架构 · 所有者发起 · macOS v1
用户在 OpenProgram 中要求 Agent 修改 OpenProgram。Agent 在隔离 worktree 中完成修改、测试和提交;独立于 worker 的控制进程构建并安装完整 App;新 worker 启动后自动创建一次验收任务,依据原始目标检查结果。系统检查或目标验收失败时恢复旧 App。
怎样让 owner 在聊天中授权 Agent 修改框架,并在修改完成后自动构建、停止旧实例、替换 App、重启、触发验收 Agent 和处理失败?
Runtime、Desktop、Job/DAG、权限和本地发布维护者。
Windows/Linux、远端 stable Release、后台无授权改码、多机部署、无限自动修复循环。
自更新控制协议、重启后验收、受控修正及状态界面已进入组合候选。完整组合检查与默认 App 的成功、激活前失败、激活后回退验收仍是发布条件;代码存在不等于已安装可用。
self_update_prepare,只接受已提交 candidate,不允许通用 shell 隐式获得部署授权。package-and-install-app.sh 已构建 runtime、Electron App 并运行 packaged smoke。install-app.sh 已验证候选、保留 previous.app、失败恢复旧 App,并恢复原来的 App/worker/launchd 状态。openprogram upgrade 已有 cold start、doctor、restart 和 expected revision 校验。origin/main。openprogram/updater/ 识别 managed release、source checkout 和 unsupported 安装方式,并禁止 worker startup 直接应用更新。self_update/ 保存独立请求、状态、控制程序和验收证据,不复用 upgrade-state。用户通过普通对话提出工作请求,消息和工具结果描述该工作。安装状态由更新子系统维护,不由独立的对话组件维护。重新打开 App 会恢复对话,不显示更新历史面板、更新恢复提示或临时验证对话框。
控制进程与 candidate runtime 分离。当前 worker 只负责准备和交接;supervisor 决定激活与恢复;新 worker 只负责运行固定系统检查和新的验收 Agent。
候选构建允许执行 candidate code,但必须在 sandbox 中拒绝写入默认状态目录、安装目录和 update record。激活与恢复只由当前已安装版本生成的 supervisor 执行。
准备阶段复用普通聊天 Agent 的计划、实现和评审过程;提交后由 self_update/ 的持久化控制逻辑转换状态,不新增通用 Workflow 引擎。验收、诊断、修正使用冻结的阶段 prompt 与结构化结果;模型输出不能直接停止进程、安装、回退或改变事务状态。
request.json 的 goal/assertionsrequest.jsonverifier-result-{attempt}.jsondiagnosis-result-{attempt}.jsonScheduler 的时间触发和用户任务 authority 不适合作为更新控制协议。新 worker 在 JobRunner、session store 和 owner-auth 可用后执行 recover_pending_updates()。
Job ID 使用 self-update:{update_id}:verify:{attempt}。claim 保存 owner、lease、attempt 和 job_id;重复启动发现已有 Job 或终态时不再提交。
实现 Agent 不能绕过安装审批;验收 Agent 没有源码写工具;诊断与修正 Agent 只读并提出结构化结果。verifier_config.py、diagnosis.py、source_repair.py 保存各阶段配置。新计划共享 goal、assertions、verification plan、迭代策略和期限,继承上下文不扩大工具权限。
普通 Scheduler 启动失败不阻止自主更新验收;JobRunner 或系统 gate 失败则请求 supervisor 回退。
approve_each_activation:失败后回退并诊断;新 candidate 激活前重新授权。bounded_auto:owner 明确授权最多 3 次、总时限、允许路径和测试集合。恢复服务、诊断原因、修改源码和批准激活是不同阶段。诊断结果不直接授权安装。
self-update:{update_id}:diagnose:{attempt} 创建新任务。未包含冻结诊断配置的旧更新保持原有恢复行为,不从当前可变 profile 补造配置。诊断请求、claim 和结果位于原更新目录,唯一待处理指针位于 self-updates 根目录;新更新在同一存储锁下撤销旧待处理指针。执行入口再次核对持久化 Job、当前 worker claim、冻结输入与未过期期限,拒绝伪造 source 或恢复旧队列时的输入漂移。owner 通过现有 Job 取消入口停止诊断,不使用只对激活前更新有效的 self_update_cancel。诊断记录不得覆盖原 verifier verdict、签名验收结果或回退结论。
修正阶段同样要求原请求中的独立冻结配置;旧请求不自动获得源码写入能力。默认首次授权说明包括“回退后在隔离 worktree 修正和执行所列测试”,不包括再次安装;只有显式选择 bounded_auto 且批准下述完整迭代授权的新请求,才允许范围内再次安装。修正输出最多 32 处文本编辑、总计 1 MiB;每处 old_text 必须在目标普通 UTF-8 文件中唯一匹配,null old_text 仅用于创建不存在的文件。new_text 为 null 时要求 old_text 等于整个文件才允许删除。修正 Job 使用 wait=true、不产生普通后续 Agent、不移动原会话 head。模型 Job 完成后,owner 在原会话调用 self_update_repair_cancel(update_id),取消仍在执行的候选测试。新 SHA、完整 diff、全部已配置测试和测试后检查通过才记录 candidate_ready;未配置 required_tests 时记录 awaiting_tests。任何已配置测试缺失、失败或测试后检查失败均记录 failed;主动取消与期限届满分别记录 cancelled、expired。这些状态均不代表已安装。
每次更新保留独立请求和证据;同一迭代序列共用原始目标、授权范围、次数和总期限。
self_update_retry(update_id, candidate_sha) 对这一精确 SHA 强制单次审批,显示完整变化、测试和剩余预算;不能保存为长期 allow 规则。bounded_auto 由控制器按原授权和真实证据自动提交,无需模型再次调用工具。self_update_iteration_cancel(update_id) 在原 owner 会话持久化停止标记,停止整个序列尚未提交的审批或自动提交,并取消该序列仍运行的诊断、修正 Job 和候选测试。已创建但尚未激活的 child 使用现有取消路径;不影响其他序列或普通任务。状态显示 root、parent、当前 child、attempt/max_attempts、总期限及停止原因。该阶段复用 SelfUpdateStore 的进程锁、JobRunner、现有强制审批、可信 supervisor 和事务安装器,不创建第二套 Scheduler 或通用 workflow 执行器。self_update/iteration.py 保持无副作用策略判断;新的提交协调模块负责证据核验、预算预留、状态持久化和恢复。源码中的职责划分不能代替实际的重启、失败回退及多次尝试验收。
首版只增加完成目标所必需的边界,不引入第二套 Job 系统、插件系统或更新依赖。
使用 macOS launchctl submit 启动 one-shot supervisor。它不属于 worker 进程树,worker/App 停止后仍可完成激活、验证超时和恢复。
candidate 必须来自专用 worktree、状态干净、base 明确。构建期间再次读取 HEAD;变化则废弃 artifact,不尝试部署工作目录快照。
复用完整 runtime、Electron builder 和 packaged smoke。暂不根据 changed paths 选择 wheel、asar 或完整 App,以免维护多套完成语义。
self_update_prepare 只持久化请求并启动 supervisor。dispatcher 在当前 assistant final、session commit 和变更归因完成后写入 turn_released。
新 worker 原子认领 update,再复用 JobRunner 创建 source=self_update_verify 的后台任务。普通 Scheduler 不创建、不轮询也不重试这个 Job。
previous.app 保留到系统检查和目标验收均通过。系统错误、Agent verdict=fail/inconclusive 或超时都会恢复旧 App;candidate worktree 和证据保留。
一个 update id 对应一个目录。每次状态变更使用临时文件、fsync 和 replace;active.json 只保存当前 update id。
授权拒绝、构建失败、candidate 漂移、取消或等待空闲超时;旧 App 从未被替换。
候选激活后系统或目标验收失败,旧 App 已恢复且旧 revision 已重新验证。
新旧 App 状态无法自动确定或 rollback 失败;停止自动动作并保留全部 transaction。
~/.openprogram/self-updates/ active.json # schema + update_id maintenance.json # admission ownership <update_id>/ request.json # immutable intent state.json # current phase + owner events.jsonl # append-only evidence verifier-config.json # frozen model / tools / optional plan diagnosis-config.json source-repair-config.json iteration-root.json # frozen root authority iteration-next.json # bound proposal + unique child reservation iteration-status.json # submission / stop evidence supervisor.sh # trusted copied controller supervisor.log artifact.json # path + hashes verifier-result-{attempt}.json diagnosis-result-{attempt}.json source-repair-result-{attempt}.json controller/ # trusted runtime and installer bootstrap.json recover.sh /Applications/.openprogram-app-install.*/ previous.app # transaction path bound in state.detail
request.json 的稳定字段schema、update_id、created_atsession_id、origin_turn_id、origin_assistant_id、agent_idrepo、worktree_id、base_sha、candidate_shachanged_paths、pre_update_evidencegoal、assertions、timeout_seconds;验收目标直接保存在 request,不另建 acceptance.jsoniteration_policy:mode、max_attempts、deadline、allowed_paths、required_testspre_update_evidence 绑定迭代记录摘要;记录含 root/parent update、原授权摘要、全序列 attempt 和唯一 child ID。每个后继有独立目录,原请求和历史终态不改写。app_path 固定为规范化的 /Applications/OpenProgram.appstate.json 的可变字段phase、revision、updated_at、detailattempt、dispatch.job_id、dispatch.claimed_by、dispatch.lease_untillast_event:状态先落盘而事件 append 中断时,用于确定性补齐最后一条事件不接受 URL、任意 installer 路径、任意 shell 命令、state dir 或端口覆盖。candidate 不能选择控制进程。
构建占用主要时间,但不影响旧实例;只在激活和重启阶段进入短暂不可用状态。
self_update_prepare 从 Git 重新计算 base/candidate/changed paths,保存 acceptance,并显示精确授权卡。拒绝当前主 checkout、dirty candidate、版本不一致和第二个 active update。owner workerlaunchctl submit 启动 one-shot job。只传 update id 和状态目录。launchd/chat 和 expected revision。candidate build 被 sandbox 限制。supervisorturn_released=true。dispatcherself_update_verify 的受限 Job。普通 Scheduler 不参与。new worker确定性系统检查先证明新实例可识别、可启动、可服务;Agent 再判断用户要求的行为是否成立。任何一层都不能替代另一层。
工具白名单为 read/glob/grep/list 与 self_update_observe。检查 ID 只能执行冻结的本地 API、CLI/test 或 UI 动作;不提供通用 Browser/Computer Use、shell、源码写入、提交、部署、外部消息或第二次更新权限。
candidate runtime 无法独立证明自身可信。系统 gate 由 supervisor 判断;Agent 只对用户目标给出结构化 pass/fail/inconclusive 与可检查证据。
系统启动 90 秒、Agent 验收默认 10 分钟、整体更新默认 30 分钟。超时不会被解释为通过。
验收 Agent 使用同一个 JobRunner 和冻结配置。新增的是有限的验收能力,不是第二个 Agent、Scheduler 或通用浏览器控制服务。
/Applications/OpenProgram.app 的实际主窗口。绑定 App 进程、window、owner、update_id、attempt 和本次 worker identity;操作前后复核身份。模型不能指定 CDP 地址、任意 target、JS 或文件路径。/chat HTML、DOM 文本或内置 Web tab 的截图,不能证明 App 主界面的视觉和交互要求。每条 assertion 绑定 evidence kind、检查 ID、允许目标/动作和预算。计划摘要进入 request evidence 和 verifier config 的摘要绑定。prepare 必须检查依赖与权限是否可用;旧配置不自动获得新增 UI 或 test 权限。
沿用 controller 的受限观察与签名 receipt 协议,增加证据类型而不接受模型自签结果。每份证据绑定 update、attempt、SHA、worker、检查 ID、时间和内容摘要。截图及输出限量保存,认证信息不进入日志、截图导出或模型上下文。
窗口关闭、身份变化、权限拒绝、对象消失、输出截断影响判断、provider 失败或超时均记录具体原因。适配层释放自有连接和测试资源,不关闭用户窗口;清理失败须记录并阻止 pass。总时限不因重连或重启重置。
页面内容、测试输出和候选代码均是不可信数据,不能扩大工具权限。对允许动作的约束必须同时覆盖 UI、IPC 和后端写入口;仅凭 DOM selector、按钮文字或“只读”提示词不足以阻止副作用。自动验收不接触其他会话和个人浏览器资料;用户正在操作目标窗口时停止自动交互并保留已有证据,等待不得超过原验收时限。
失败状态必须说明候选是否被激活、当前运行哪个 revision、旧 App 是否保留,以及验收任务是否执行。
quiescence-timeout 和仍运行的任务列表。激活候选前,可信当前版本除保存 controller/runtime/installer,还生成本次更新专用的 ~/.openprogram/self-updates/<update_id>/recover.sh,并在本机用户的 ~/Library/LaunchAgents/ 写入对应的一次性登录任务。脚本、状态目录和 runtime 都位于 App 外;不依赖 PATH 中的 OpenProgram、待修复 App、普通 worker 或 Scheduler。没有完整可验证的保存副本时,不生成新的控制代码,也不尝试猜测恢复。
recover.sh statusrecover.sh repairrecover.sh resume登录文件名为 ai.openprogram.self-update.recovery.<update_id>.plist,在本用户每次登录时最多执行一次,完成后清除:RunAtLoad=true,不设置 KeepAlive、周期或常驻 daemon。写入 plist 不立即加载另一份控制进程;正常更新仍使用原 one-shot supervisor 和同一 controller lock。当前登录会话中,若 App 与控制进程都已不可用,终端恢复脚本是显式入口;机器重启后需本用户登录才触发自动恢复,不声称能在未登录或磁盘未解锁时执行。
发布恢复入口、固定参数和 plist 的绑定记录必须发生在原 supervisor 被提交、候选被激活之前。只操作本用户拥有的规范目录和本次更新的确切文件;已有同名但内容不匹配、符号链接、非普通文件或不安全权限均拒绝,不覆盖。重复准备校验原副本,不从已替换 App 重新复制。启动错误留下独立诊断,绝不解除维护或延长授权。
原更新已终止且不再拥有维护状态后,只清除内容仍与绑定记录一致的本次登录 plist;保存的 runtime、脚本、原更新证据和恢复结果继续保留,便于查询。清理失败保留诊断,不改变已验证的原结果;残留一次性任务再次运行也不得恢复已完成更新。该入口本身损坏、权限变化或原证据不足时仍需人工处理,不提供任意文件修复或强制清除维护的能力。
更新进入维护后,worker 使用现有 canonical pause 命令让正在执行的任务到达持久化检查点。每个更新保存明确的 execution id、pause command id 和观察版本;只恢复由本次更新暂停的任务。原本暂停、等待用户输入、取消和已经完成的任务不自动继续。排队且尚未执行的 Job 保持原有队列身份,不参与活动执行等待。
supervisor 只在 canonical 活动 attempt 和旧版运行任务均结束后替换 App。新 worker 在更新提交或验证回退且解除维护后,通过原来的 continue 命令和 Job 资源队列继续任务。命令使用固定 id,重复恢复不创建重复执行。暂停失败或不可暂停任务在期限内没有完成时中止更新,恢复已暂停任务。
检查点恢复保留运行合同校验;工具实现或权限改变时禁止重放旧操作,保留旧检查点。只有本次更新发起的 continue 因合同变化被拒绝时,才从原任务和历史创建固定身份的新规划 Job,保留原工具选择和权限规则,并在执行前重新校验原执行及更新归属。未解决的副作用、用户取消或其他会话活动阻止自动重新规划。任务恢复失败不更改安装验收结论。发起更新的会话在终态产生一个持久化后续任务,读取原目标、历史和更新结果继续检查;它不替代固定 verifier,也不获得再次激活更新的交互授权。旧记录不追溯创建后续任务。
验收入口是 supervisor 等待、worker reconciliation 和真实 canonical pause/continue。必须覆盖排队任务、检查点恢复、重复 worker 恢复、用户暂停/取消、维护未解除、更新失败,以及原会话后续任务只创建一次。实现状态:实现与针对性测试已完成,独立评审、完整测试和实际 App 验收待完成。
openprogram self-update status [update_id] --json 在不执行模型、不创建更新、不修改 App 的情况下读取维护归属、原终态与恢复结果。openprogram self-update repair <update_id> 是本机 owner 的独立控制入口,不依赖普通聊天或 Scheduler;必须在交互式终端确认显示的 update id、目标 revision、恢复动作与计划摘要,不提供跳过确认参数。确认时重新比较原状态、维护归属、安装 journal 和可信 controller;发生变化则拒绝旧确认。
每次确认生成独立、持久化的恢复请求,绑定原更新与事务身份,限时十分钟;重试和进程重启不延长这次期限。只复用已保存的 controller/runtime/installer,通过包含恢复请求 id 的 one-shot launchd label 启动;不从待修复 App 重新复制控制代码。恢复进程使用原安装事务校验规范 App 后重启默认 worker,再验证新进程,使启动检查和普通 Scheduler 按正常启动顺序恢复。中断时允许在同一期限内重复幂等恢复及 worker 重启,但不能创建 verifier Job 或第二次更新。
原终态、原验收结论与旧期限保持不变;人工恢复写入独立 resolution receipt,区分“旧版本恢复”“已接受版本恢复”和“未激活更新恢复”。只有该 receipt 与新系统证据匹配,才原子解除本次维护归属。失败、过期或未确认时继续禁止普通任务;后续再次尝试必须重新确认。此入口不是任意 shell、文件修复或强制清除 maintenance 的接口。
“允许改代码”和“允许替换当前运行产品”是两个授权。第二个授权只授予一个 candidate SHA,或一个显式有界的多轮 envelope。
控制器从已保存的可信完整 runtime 取得固定版本的 uv、managed Python 和依赖。复用前逐字节核对 candidate 的 uv.lock 与 product-runtime.json;不匹配或输入缺失时在激活前失败,不能悄悄沿用不匹配依赖或允许候选联网。依赖变化需要先提供匹配的完整 runtime 输入,不由候选自选下载源或继承 owner 凭据。
runtime 和既有 npm/uv/Electron-builder/node-gyp 构建缓存复制到本次私有 build-home;macOS 使用独立的 copy-on-write 副本,不共享可写缓存。Electron 平台 zip 由可信控制器按固定版本、架构和发布 SHA-256 选择,复制到 candidate 不可写的 update 输入目录并通过 electronDist 使用,不因缓存命中而跳过完整性校验。候选仍重新构建 Web、文档、wheel 和 Desktop archive,仅把新 wheel 安装到私有 runtime;正式 Release 的常规构建入口保持原有行为。复制、构建及检查共用原期限,缓存命中不是验收证据。
构建进程不访问外部网络、默认 App 或用户状态。packaged worker smoke 只获准绑定并访问控制器选择的单个私有 loopback 端口,明确排除默认端口 18100;其余网络访问继续被 sandbox 拒绝。需要宿主图形服务的固定检查不向 candidate sandbox 扩权:控制器使用固定参数调用系统 sips 检查四个固定图标源,并由固定的可信 runtime Python 执行 Playwright Chromium probe;执行前后都要求 candidate 浏览器资源与已保存可信 runtime 的资源树 hash 一致。worker、图标和浏览器检查都完成并写入 manifest/receipt 后才允许进入激活阶段,不能通过开放默认 worker 或跳过检查取得通过结果。实际打包及已安装 App 验收状态见文末。
supervisor 和安装器在 candidate 激活前从当前 runtime 复制并 hash 固定。candidate 不提供 supervisor、App path、state path、命令或恢复策略。
candidate 的构建和 smoke 会执行源码,因此在 sandbox 内运行,并使用最小环境。拒绝访问 provider 凭据、默认 session state、安装目录和 update record。
self_update_prepare 加入不可由 bypass 跳过的强制审批集合。默认绑定 candidate;有界自动迭代绑定 goal、允许路径、最大次数、时限和禁止变化项。
自动验收不能修改源码或再次更新。它只能读取证据、运行受限检查和操作本地 UI;需要额外副作用时返回 inconclusive。
用户仍然只需要聊天。工具参数保持结构化,不向模型开放安装命令。
{worktree_id, candidate_sha, goal, assertions[], iteration_policy?, verification_plan?}。强制审批后验证 candidate、冻结配置、写 request、启动 supervisor。返回 update_id、phase、candidate_sha、base_sha 和 changed_paths,不返回安装成功。
{update_id?}。返回 phase、steps、current/candidate revision、active App、rollback availability 和 verifier verdict。
只在 PREPARING/STAGING/READY 生效。ACTIVATING 之后拒绝 cancel,由 supervisor 完成 commit 或 rollback。
{update_id}。原 owner 会话取消该次回退后的源码修正或候选测试,不改写原验收和回退结论。
{update_id, candidate_sha}。在原会话批准通过真实证据核验的修正 SHA;审批前后均复核身份、候选和预算。返回固定 child ID 与提交状态,不返回虚假的安装成功。
{update_id}。停止整个迭代序列及其待执行/正在修正的任务。已激活事务继续必要验证或恢复,但不能创建后续 attempt。
# Job result; controller wraps it in a signed receipt
{
"schema": 1,
"update_id": "su_...",
"candidate_sha": "...",
"attempt": 1,
"verdict": "pass | fail | inconclusive",
"assertions": [
{
"id": "acceptance-1",
"status": "pass",
"entry": "default App",
"observation": "...",
"evidence_refs": ["observation-id"],
"observed_at": 1.0
}
]
}
发起更新的 assistant node 记录 self_update_id。重启后的验证 branch 使用:
source=self_update_verifycaller=origin_assistant_idpredecessor=null,不改变用户主分支 HEADUI 将其渲染为“更新后自动验收”,不渲染成用户消息。
安装、验证和回滚保留各自的持久更新记录。对话仅显示普通消息和工具结果。消息列表不挂载软件更新历史组件、不发起更新历史轮询请求,也不提供更新管理表单。Desktop 恢复保留其路由和确认协议,不向对话添加更新恢复提示。
update_id、root/parent、origin session、attemptphase、state_revision、updated_atrevision 和时间。state_revision 是状态版本号,不是 Git SHA。candidate_revision、changed pathslast_verified_runtimesystem_gate、committed_system_gate、restored_system_gate;激活前旧版本来自 previous_system_gate。人工恢复使用对应已校验恢复 receipt。target_app、rollback 状态openprogram/self_update/control/projection.py 提供专用工具、Web 与 Running 的共享只读投影。owner-auth 路由为 GET /api/self-updates?session_id=… 与 GET /api/self-updates/{update_id}?session_id=…,并校验 origin session;历史列表使用有上限的稳定游标分页,不依赖 active 指针。证据经同一更新的 /evidence?session_id=…&evidence_id=… 路由再次验证,只返回签名结果引用的观察记录。
投影只包含明确允许的字段、有限摘要和不透明 evidence ID,不返回配置、token、签名密钥、环境变量或任意日志路径。证据读取必须再次核验 owner、session、update 和 receipt 绑定;不支持任意文件读取。状态及关联结果在同一一致性边界内读取,无法形成一致快照时返回可重试错误。读操作不触发 claim、repair、Job 或 Scheduler。
更新投影 API 保持只读并限定于会话作用域,用于显式工具读取。聊天不轮询这些 API。已存储的更新状态不依据窗口断连推断成功或失败。
工具结果和持久结果交付使用现有对话消息流程。聊天中不挂载独立更新历史、分页、证据查看器或更新请求表单。
controller 先持久化终态,worker 通过已有 Job completion/follow-up 投递机制把有限结果写回原会话。以 update、attempt 和结果类型形成稳定投递键;重复启动或 ACK 丢失不产生重复消息。终态早于 verifier 创建、原会话未打开时也必须投递;会话删除则保留未投递状态,不改投其他会话或创建新的用户任务。
自动验收任务完成、目标通过、安装提交、回退完成和后续修正分别显示。通知由确定性代码生成,不另起 LLM 来编写状态,也不因此触发再次安装。DAG 保留 origin caller 与验证 Job 的关系,不改写用户主分支 HEAD。
复用 apps/desktop/worker-start-url.js 的 owner-auth 启动机制与现有 /s/{session_id} 路由。supervisor 在停止 App 前保存本次更新的受信任 reopen 意图,绑定 update、attempt、origin session、owner、期限和启动动作。Desktop 只接收不透明 update ID;由已认证服务解析经过核验的会话,再构造同源路由。候选、模型、CLI 参数和 renderer 不能指定任意 URL、文件路径或认证 fragment。
只在这次更新触发的重新打开中消费该意图,不改变普通启动、用户当前窗口、中心标签和稳定 Release updater。完成认证并确认原会话加载后才 ACK;ACK 前崩溃可重试定位,不能重新激活更新或重建 verifier Job。多窗口只由指定主窗口消费;重复消费是幂等定位,不重复建标签。用户主动离开原会话后不再强制跳回,也不插入专用恢复提示。
owner 改变、session 不存在、意图过期、身份不匹配或恢复接口不可用时,保持普通启动,在内部状态中保留原因;不跳到其他会话,不自动创建会话,也不把定位失败判为安装成功。App 原本未打开时遵守保存的启动状态;若验收必须操作可见 App,应在 prepare 时显示并获得打开窗口的授权。更新与回退双方均须支持所需的最小读取/恢复协议,协议不兼容在激活前拒绝。
参考只用于确定进程、更新和 worktree 边界;OpenProgram 的候选来源、权限和验收仍由本设计定义。
使用 linked worktree 隔离 candidate 的 HEAD/index/工作目录;serving checkout 和用户现有 dirty checkout 不作为构建输入。
采用用户会话内独立进程边界。首版使用 one-shot launchctl submit,不安装常驻 updater daemon。
采用 staged artifact、restart 和明确状态;候选来自本地 commit,不使用远端 update feed。
macOS 自动更新要求签名并围绕发布 feed 工作;不能覆盖本地未发布 candidate、Agent 验收和当前 unsigned 开发 App 合同。
复用完整 artifact、manifest、runtime probe 和平台安装边界;不改变 stable Release 的发现、下载和用户安装行为。
复用 worktree 归属、commit、merge/discard 和 approval 语义。自主更新只读取 candidate,不自动合并用户主分支。
每个任务独立 review;前一任务通过 specification 与 quality review 后才开始下一任务。所有生产文件名是目标位置,实施时先核对现有共享 primitive。
新增 openprogram/self_update/,只使用 stdlib JSON、fcntl 和 atomic replace。
types.py:phase、request/result schemastore.py:create/load/transition/claim/event journal复用现有 Desktop 构建/安装脚本,不新增 updater dependency。
package-and-install-app.sh:分离 build-only 输出install-app.sh:prepare/commit/rollback 或等价 defer-commit 接口upgrade.py:抽取公共 identity/doctor probe工具不执行停止动作,只提交持久化意图。
programs/tools/system/self_update/:prepare/status/cancelagent/permissions/approval.py:forced owner approvalagent/dispatcher/:final durable 后 release当前可信版本生成固定 controller,candidate 只能提供 commit 内容。
self_update/supervisor.py 与固定 shell handoff不恢复被中断的执行栈;重启后创建新 Job,普通 Scheduler 不参与控制。
self_update/recovery.py:system gate、lease、稳定 Job ID 和 exactly-once dispatchworker/runner.py:JobRunner ready 后、普通 Scheduler 前的启动 hookagent/job/runner.py:source/authority/tool/model snapshotself_update/iteration.py:attempt budget、scope diff 和停止条件验证和恢复使用应用服务;对话保留普通消息和工具结果。
self_update/projection.py、Web self-updates 路由、现有 status 工具和 Running 路由apps/desktop/main.js、worker-start-url.js 与 startup handoffself_update/verifier_config.py、现有受限观察/签名协议与 App/测试适配层scripts/refresh-local-app.sh 更新默认 App,实际验证成功、激活前失败、激活后回退;分别记录 local commit、main、remote 和 installed identity。每个子任务开始前从已评审的不可变 commit 创建隔离 worktree,写明 exact 文件、RED 和完整测试命令。通过相关检查的独立改动及时提交;评审通过不等于发布通过。已证实的基线失败保留为未通过状态,不能用较小测试集合替代完整 gate。文档机器检查、浏览器交互与桌面/窄屏视觉检查分别记录,不新增另一份设计文档。
以下条件全部成立后,才能把“对话内自主更新”标记为 implemented。
owner 在默认 App 中提出修改;Agent 完成 worktree 修改、测试、提交并调用专用工具,不依赖开发者手工执行脚本。
request、artifact 和 live revision 绑定同一 SHA;dirty worktree、HEAD drift、version drift 均在停止旧实例前失败。
旧 worker/App 停止后 supervisor 仍运行;当前 turn 已完成持久化,不产生永久 running node。
存在其他运行任务时只等待或中止更新,不隐式取消;maintenance gate 不丢失已提交用户输入。
App bundle、embedded Python、Web/docs、Programs、Browser assets 和 capability manifest 都来自 candidate,并通过 packaged smoke。
重启后默认 18100 的 owner-auth challenge 证明 candidate revision;单独的匿名 health 结果不能满足该条件。
新 worker 正好创建一个 self_update_verify Job;每条 required assertion 均有结果和证据,缺失即 inconclusive。
普通 Scheduler 停止、延迟或重复 tick 不影响验收触发;worker 重启、lease 接管和 orphan reconciliation 后,每个 attempt 仍至多一个验证 Job。
默认每次重新授权;bounded_auto 严格执行最大次数、总时限、路径和禁止变化项,任何越界都暂停。
系统 gate、目标验收和超时失败均恢复 previous.app,恢复后的 worker revision 可验证,并在原会话显示结果。
在 READY、ACTIVATING、VERIFYING 各阶段模拟进程/机器重启后,recovery 得到确定终态,不重复激活或重复发 Agent turn。
设计、测试、review、candidate commit、App source marker、运行 worker identity 和 UI verdict 指向同一实现状态。
本节描述主线及已安装产品的集成状态。功能分支实现与评审证据单独记录,不等于产品已经可用;目标合同不因当前缺口而降低。
文件/shell/worktree 工具、approval、sandbox、read-before-edit、变更归因和 session DAG 已存在。
Desktop runtime preparation、Electron builder、runtime manifest 和隔离 smoke 已存在。
现有 install-app transaction 已保存 previous App,并在激活或启动失败时恢复原状态。
复用安装方式识别、source probe、Job 持久化及 orphan reconciliation;自更新启动认领使用 JobRunner,普通 Scheduler 不参与控制或兜底验收。
组合候选包含状态机、单活动锁、durable release、maintenance、外部 supervisor、延迟提交与回退,以及 owner repair 和 App 外登录恢复入口。离线私有构建输入、固定 SHA 的 Electron 分发、单端口 packaged worker smoke、固定图标渲染和可信 runtime browser probe 已通过修复后的完整实际打包;browser probe 只执行候选无权写入且已重新校验的保存 controller runtime,构建用可写 runtime 不会由控制器执行。独立评审、最终组合门禁、主线发布和实际安装/恢复验收尚未完成。
startup claim、稳定 self_update_verify Job、签名结果、目标失败 rollback、持久化结果投递和 Desktop reopen 均已集成。旧 App 缺少打包协议时必须先显式完整刷新;不能以源码测试证明已安装 App 的重启、原会话 ACK 或自动验收。
回退后诊断、受限编辑提案、隔离 worktree/commit、冻结测试、再次审批与 bounded_auto 已集成。重启不重置次数和期限;完整组合检查与真实更新序列仍待验收,不覆盖原失败结论。
普通结果投递、原会话定位,以及有签名的 HTTP、CLI/test、截图、滚动和视图检查已集成。聊天不挂载更新管理界面;不支持临时测试对象操作。能力严格限于冻结检查;任意 UI 交互和真实数据修改不在授权内。默认 App 三场景及实际目标证据完成前,整体保持未完成。
打开、切换或重新连接对话不查询软件更新历史。普通工具输出和现有结果交付仍可用。聊天 UI 不显示软件更新加载状态、状态信息、重试表单或恢复提示。生产 App 不挂载临时验证用重命名对话框。验证在任何 UI 请求之前拒绝 test_object 交互;仍支持截图、有界滚动和视角检查。
验收:普通聊天和 App 外层界面挂载时不包含软件更新 UI 或历史请求;桌面会话确认仍正常工作;安装与回滚行为保持不变。