diff --git a/docs/reference/spec-v01-agentrun-mgr.md b/docs/reference/spec-v01-agentrun-mgr.md index 731660f..6d68e08 100644 --- a/docs/reference/spec-v01-agentrun-mgr.md +++ b/docs/reference/spec-v01-agentrun-mgr.md @@ -167,13 +167,15 @@ Manager 只承接 HWLAB v0.2 Code Agent 的通用执行事实,不承接 HWLAB | `runId` / `commandId` / `attemptId` | 支持调用方持久关联和问题定位。 | | `artifactSummary` | 第一阶段只放有界摘要、字节数、截断标记和必要引用;不内嵌大 stdout/stderr。 | | `toolCallSummary` | 输出有界、脱敏的 tool call 状态摘要,至少包含 `count`、`statusCounts`、`exitCodeCounts` 和最近若干条 `items` 的 `method/toolName/type/status/exitCode/command`。消费侧必须用它区分 AgentRun command terminal、agent 内部工具执行和后置诊断,不得用单一 `hwpodExitCode` 覆盖 AgentRun 成功终态。 | -| `liveness` | 查询时派生的 supervisor 活性快照,不写入 durable event。必须暴露 `phase`、`active`、`lastSeq`、`lastEventAgeMs`、`lastActivity`/`lastCommandActivity`、`timeoutBudget`、lease/heartbeat 摘要和可执行恢复动作。`lastActivity` 必须包含 `sourceSeq`、`eventId`、`activityKind` 和 `ageMs`,用于按 id/seq drill-down;默认只给有界摘要,不展开 stdout、runnerTrace、完整 tool command 或 raw event。`timeoutBudget` 必须基于 `executionPolicy.timeoutMs` 暴露 `elapsedMs`、`remainingMs` 和 `state`(如 `within-budget`、`approaching-hard-timeout`、`timed-out`)。`phase` 至少区分 `waiting-runner`、`waiting-model`、`waiting-model-output`、`waiting-tool`、`waiting-tool-output`、`idle-after-tool`、`runner-stdio-inactive`、`transport-disconnected`、`runner-heartbeat-stale` 和 `terminal`,避免调用方只能用外层超时猜测 backend 状态。终态失败/阻塞时仍必须保留恢复动作,例如 inspect result、resume session、split task,而不是返回空数组。 | +| `liveness` | 查询时派生的 supervisor 活性快照,不写入 durable event。必须暴露 `phase`、`active`、`lastSeq`、`lastEventAgeMs`、`lastActivity`/`lastCommandActivity`、`timeoutBudget`、lease/heartbeat 摘要和可执行恢复动作。`lastActivity` 必须包含 `sourceSeq`、`eventId`、`activityKind`、`observedAt` 和 `ageMs`,用于按 id/seq drill-down;默认只给有界摘要,不展开 stdout、runnerTrace、完整 tool command 或 raw event。`timeoutBudget` 必须按无响应空闲时间计算,`executionPolicy.timeoutMs` 是 idle budget,不是 turn wall-clock hard timeout;只要 backend notification、assistant/tool/event、command output 或等价 activity 持续刷新,就必须重置 idle 起点并继续等待。该对象必须暴露 `timeoutKind="idle"`、`hardTimeout=false`、`idleStartedAt`、`idleElapsedMs`、`lastActivityAt`、`lastActivitySeq`、`elapsedMs`、`remainingMs` 和 `state`(如 `within-budget`、`approaching-idle-timeout`、`idle-timed-out`、`terminal`)。`phase` 至少区分 `waiting-runner`、`waiting-model`、`waiting-model-output`、`waiting-tool`、`waiting-tool-output`、`idle-after-tool`、`runner-stdio-inactive`、`transport-disconnected`、`runner-heartbeat-stale` 和 `terminal`,避免调用方只能用外层超时猜测 backend 状态。终态失败/阻塞时仍必须保留恢复动作,例如 inspect result、read events/trace、continue same session、split task,而不是返回空数组。 | | `steerDelivery` | 仅在查询 `type=steer` command result 时出现。必须说明 steer 是否已被 runner ack、是否已转发并被 backend `turn/steer` RPC 接受、目标 `targetCommandId`、是否观察到 target command 后续事件,以及“steer command completed 不等于 target turn 已产生后续 assistant/tool 输出”的语义。 | `assistant_message` partial、`command_output` 存在、stdout 非空、backend transport close 或 idle timeout 都不能单独让 result 进入 `completed`。 `GET /api/v1/sessions/:sessionId` 作为 session status 入口,必须在存在 active/last run 时透出同一套 `liveness` 和 `supervisor` 摘要;该摘要是观测辅助,不能替代 command terminal、run terminal 或 raw events 的事实来源。 +当 command 因 idle timeout、provider stream disconnect、runner stdio inactive 或其他非业务终态失败时,manager 的恢复建议必须面向指挥官而不是要求 worker 自行读 trace。指挥官应先读取 `result`、`events` 或 `sessions/:id/trace` 确认最后有效 activity、已完成修改和卡点;若 run/task 有可继续的 `sessionRef`,后续 prompt 必须用同一个 AgentRun session 通过 `send session/` 或 `steer session/` 续跑,并在 prompt 中写入管理者从 trace 得出的下一步。只有旧任务没有 `sessionRef`、session 已 evicted、或同 session 已证明不可恢复时,才创建带管理者摘要的新任务。 + 当 `commandId` 已指定,result envelope 必须只聚合该 command 的 assistant/output/error/terminal 事件;同一 run 的其他 command reply 不能串入当前 command result。未指定 `commandId` 时可默认选择最新 command。 长 trace / steer 场景的验收标准是:raw events 已有 terminal seq 时,`commands result` 的 `lastSeq` 与 `eventCount` 必须覆盖同一终态事件范围,`finalAssistantSeq` 必须指向 terminal 前最后一条可用 assistant 或 authoritative final,且 silent first-page truncation 一律视为 result 合同失败。 diff --git a/docs/reference/spec-v01-aipod-spec.md b/docs/reference/spec-v01-aipod-spec.md index 02a78c9..393b654 100644 --- a/docs/reference/spec-v01-aipod-spec.md +++ b/docs/reference/spec-v01-aipod-spec.md @@ -95,6 +95,7 @@ imageRef: - 通过 `toolCredentials` 获取 GitHub SSH 凭据:`agentrun-v01-tool-github-ssh` -> volume `/home/agentrun/.ssh`。 - 通过 GitHub SSH 直接 checkout 多仓库 gitbundle,装配 UniDesk repo 中的 `unidesk-*` skills、AgentRun repo 中的 `tools/trans`、`tools/tran`、`tools/apply_patch`,以及 `agent_skills` repo 中的 `dad-dev`、`cli-spec`、`docs-spec`、`git-spec`;Artificer 默认不依赖 G14 git mirror 的覆盖范围。 - 通过 `requiredSkills[]` 在 runner 启动 backend 前校验 `dad-dev` 与 UniDesk 关键 skills 已被 materialize;缺失时必须 `required-skill-unavailable`,不得使用模型默认 skill 猜测。 +- Artificer 默认是 session-capable agent。`render`/`queue submit --aipod Artificer` 在调用方没有显式传入 `sessionRef` 时,必须生成稳定的默认 `SessionRef`,`sessionId` 使用 `sess_artificer_<24 hex>` 形态,`conversationId` 默认等于 `sessionId`,并把该引用写入 Queue task/run 装配输入;后续 follow-up、补测、reviewer feedback 和 manager recovery 优先继续同一个 session,而不是每次新开 session。 ## Git mirror @@ -155,6 +156,7 @@ CLI: - A1:`config/aipods/artificer.yaml` 能被 manager list/show/render,render 结果包含 `imageRef.kind=env-image-dockerfile`、`repoUrl`、`commitId`、`dockerfilePath`、`backendProfile=sub2api`、`model=gpt-5.5`、`reasoningEffort=xhigh`、provider SecretRef、GitHub PR token env projection、UniDesk SSH env projection、GitHub SSH volume projection、Artificer `gitMirror.enabled=false`、AgentRun runner tools gitbundle 和 gitbundle requiredSkills。 - A2:`queue submit --aipod Artificer --dry-run` 输出标准 `queue-submit-plan`,且 `idempotencyKey`、prompt 与 metadata 被保留。 +- A2b:`queue submit --aipod Artificer --dry-run` 或 `render Artificer` 在没有显式 `sessionRef` 时必须输出默认 `sessionRef.sessionId` / `conversationId`;显式传入 `sessionRef` 时不得覆盖。 - A3:Artificer 默认 `gitMirror.enabled=false` 时 GitHub URL 保持 SSH fetch;显式启用 `gitMirror` 后 GitHub URL 改写到 mirror base URL;非 GitHub URL 不改写。 - A4:Aipod 启动/dispatch 能基于 `imageRef` 命中 artifact catalog / registry 并复用 digest-pinned env image;未命中时返回明确 build-required 或进入受控 CI/CD,不在 runner 任务内补装依赖。 - A5:runner Job dry-run 支持 tool credential volume mount,并且 response/manifest/event 不泄漏 Secret 明文。 diff --git a/docs/reference/spec-v01-backend-codex.md b/docs/reference/spec-v01-backend-codex.md index d4dea63..05d9bd2 100644 --- a/docs/reference/spec-v01-backend-codex.md +++ b/docs/reference/spec-v01-backend-codex.md @@ -89,6 +89,7 @@ Kubernetes Secret 的创建、轮换和权限控制属于集群密钥管理流 - Adapter 必须在调用 Codex 前验证 `auth.json` 和 `config.toml` 均存在且可读;`config.toml` 声明 `model_catalog_json` 时还必须验证目标文件可读;`dsflash-go` 缺少 `model_catalog_json` 时也必须在 provider 调用前返回 `secret-unavailable`。 - Codex 运行时必须使用被投影的 `.codex` 目录;不得 fallback 到镜像内默认凭据或节点宿主机 `~/.codex`。 - Codex stdio backend 不得设置 turn/session/conversation 的总时长 timeout;`executionPolicy.timeoutMs` 只能作为无 app-server 响应、无 notification、无 assistant/tool/event activity 的 idle timeout。长程任务只要持续产生可见 activity,就必须继续等待 `turn/completed`、取消或真实 transport failure。 +- idle timeout 的活动源至少包括 Codex app-server notification、assistant/message delta、tool call 状态、command output、stderr/diagnostic event 和 backend status event;这些活动必须刷新 `lastActivityAt/lastActivitySeq`。只有超过 idle budget 没有任何活动时,才允许把当前 command 归为 idle timeout;result/session 仍必须标记 `timeoutKind="idle"`、`hardTimeout=false`,避免调用方把它误判成固定 wall-clock backend-timeout。 - 普通 turn command 失败只终结当前 command,不得把 reusable run/session 置为 terminal;后续 command 必须仍可进入同一个 run/runner。只有显式 cancel、runner lease/claim 失效、资源装配不可恢复或运行面退出才允许终结 run。 - 若 `config.toml` 指向 hyueapi 或其他 OpenAI-compatible upstream,runner/backend Pod 的 proxy 与 `NO_PROXY` 必须保持该配置可用;不得在日志中打印完整 auth/config 内容。 - 模型名、provider profile、upstream host 可以作为 redacted metadata 输出;provider credential、token、Authorization header 和文件内容不得输出。 diff --git a/docs/reference/spec-v01-runtime-assembly.md b/docs/reference/spec-v01-runtime-assembly.md index 0c24a6c..e6b02a3 100644 --- a/docs/reference/spec-v01-runtime-assembly.md +++ b/docs/reference/spec-v01-runtime-assembly.md @@ -169,6 +169,7 @@ HWLAB Workbench 的 project/workspace 不属于 RuntimeAssembly 四要素,也 - runner Job 必须在 `${CODEX_HOME}/` 位置把 PVC **直接挂载**到 runner pod;`auth.json`、`config.toml`、`state_*.sqlite`、`memories/`、`tmp/`、`skills/` 仍由 `emptyDir` 父目录提供,不持久化。 - 完整 CODEX_HOME 不进入 PVC,profile Secret 投影仍走 `agentrun-v01-runner-secret-reader`,与 session 持久化路径分离。 - runner 启动时把 PVC 名、namespace、mount path、codex rollout subdir 写入 env(`AGENTRUN_SESSION_PVC_NAME`、`AGENTRUN_SESSION_PVC_NAMESPACE`、`AGENTRUN_SESSION_PVC_MOUNT_PATH`、`AGENTRUN_CODEX_ROLLOUT_SUBDIR`),backend adapter 不需要直接读 k8s API。 +- Queue、AipodSpec 或手动调度只要携带非空 `sessionRef`,runner Job render 必须在创建 Job 前解析或创建对应 session PVC,并把 PVC 直接 mount 到 `${CODEX_HOME}/`;runner Job response、dry-run manifest 和 event 必须暴露 `sessionPvc` 摘要与 `valuesPrinted=false`。不得因为任务来自 Queue/Aipod 而跳过 `AGENTRUN_SESSION_PVC_NAME` 或只保存 metadata-only session。 - `codex_rollout_subdir` 走 env,默认 `sessions`,codex CLI 升级改子目录时只改该 env,不改 runner/backend 装配。 - `POST /api/v1/sessions` 创建 session 时同步创建 PVC;`POST /api/v1/runs/:runId/commands` 命中已有 session 且 `storage_kind='evicted'` 时短路返回 `session-store-evicted`,不创建 runner Job。 - runner pod 删除或旧 lease 过期后的 replacement runner 只改变执行尝试 identity,不改变 RuntimeAssembly 的 `SessionRef`、`ProfileRef` 或 `ResourceBundleRef`。验收时应证明 replacement run/job 仍使用同一 `SessionRef.sessionId`、`threadId`、`ProfileRef.profile` 和 PVC;不能通过新 session、新 profile 或历史 prompt 拼接来制造 resume 表象。 @@ -180,6 +181,7 @@ HWLAB Workbench 的 project/workspace 不属于 RuntimeAssembly 四要素,也 - 不引入「runner 启动后 copy/restore」path,撤掉的 copy 方案不允许复活(PR #78 已回退 replacement 逻辑,本节同样禁止任何「持久化卷 + 热修脚手架」变体)。 - 不允许 fake `thread/resume:completed`,PVC 真的存在且 codex 真的能 resume 才算通过。 - 不写 fallback、不写 replacement、不拼接历史。`thread/resume` 失败时按 [spec-v01-backend-codex.md](spec-v01-backend-codex.md) T7 直接失败;只有 `AGENTRUN_SESSION_PVC_NAME` 已设 + codex 报 `no rollout found for thread id` 时升级为 `session-store-evicted`,用于上层区分「PVC 被删」与「真协议错误」。 +- 不得把 `sessionRef=null` 的历史任务伪装成可同 session 续跑。旧任务没有 session 时,manager 可以基于 trace 总结重开一个带 sessionRef 的新任务,但该动作必须被记录为新 session bootstrap,而不是 resume。 ### ResourceBundleRef