From 9efdfc73da39e61acbfd456c1e06f772577e5c26 Mon Sep 17 00:00:00 2001 From: bouillipx Date: Mon, 2 Mar 2026 23:26:05 +0800 Subject: [PATCH 1/3] docs(client): archive slice C and kick off slice D Archive the merged client-external-control-plane-v1 change, sync its landed control-plane deltas into the canonical client-host-orchestration spec, and establish the docs-first kickoff baseline for client-capability-discovery-and-host-tests. Key changes: - archive Slice C OpenSpec artifacts under openspec/changes/archive/2026-03-02-client-external-control-plane-v1 and move its feature aggregation doc to docs/features/archive - sync the landed control-plane requirements into openspec/specs/client-host-orchestration/spec.md so the main spec reflects control-stdin, canonical action ids, and status snapshot semantics - update client/DESIGN.md and client/README.md to choose explicit actions:list discovery over unsolicited startup handshake for the next slice - refresh the host-orchestration master TODO ledger: mark CCLI-005/006 done, record Slice C archive evidence, and claim CCLI-007/008 for Slice D - create the client-capability-discovery-and-host-tests OpenSpec change plus its feature evidence doc, covering explicit capability discovery and host protocol regression testing Rationale: PR #151 is already merged, so Slice C must be archived before more implementation work begins. Slice D needs a docs-first baseline on top of the merged control-plane spec, otherwise the next implementation slice would start from an outdated canonical contract and leave hosts choosing between hardcoded action matrices and undefined handshake behavior. --- client/DESIGN.md | 12 ++-- client/README.md | 5 +- .../client-external-control-plane-v1.md | 11 +-- ...ent-capability-discovery-and-host-tests.md | 71 +++++++++++++++++++ ...ient_cli_host_orchestration_master_todo.md | 19 ++--- .../.openspec.yaml | 0 .../design.md | 0 .../proposal.md | 0 .../specs/client-host-orchestration/spec.md | 0 .../tasks.md | 0 .../.openspec.yaml | 2 + .../design.md | 71 +++++++++++++++++++ .../proposal.md | 39 ++++++++++ .../specs/client-host-orchestration/spec.md | 20 ++++++ .../tasks.md | 15 ++++ .../specs/client-host-orchestration/spec.md | 31 +++++++- 16 files changed, 273 insertions(+), 23 deletions(-) rename docs/features/{ => archive}/client-external-control-plane-v1.md (91%) create mode 100644 docs/features/client-capability-discovery-and-host-tests.md rename openspec/changes/{client-external-control-plane-v1 => archive/2026-03-02-client-external-control-plane-v1}/.openspec.yaml (100%) rename openspec/changes/{client-external-control-plane-v1 => archive/2026-03-02-client-external-control-plane-v1}/design.md (100%) rename openspec/changes/{client-external-control-plane-v1 => archive/2026-03-02-client-external-control-plane-v1}/proposal.md (100%) rename openspec/changes/{client-external-control-plane-v1 => archive/2026-03-02-client-external-control-plane-v1}/specs/client-host-orchestration/spec.md (100%) rename openspec/changes/{client-external-control-plane-v1 => archive/2026-03-02-client-external-control-plane-v1}/tasks.md (100%) create mode 100644 openspec/changes/client-capability-discovery-and-host-tests/.openspec.yaml create mode 100644 openspec/changes/client-capability-discovery-and-host-tests/design.md create mode 100644 openspec/changes/client-capability-discovery-and-host-tests/proposal.md create mode 100644 openspec/changes/client-capability-discovery-and-host-tests/specs/client-host-orchestration/spec.md create mode 100644 openspec/changes/client-capability-discovery-and-host-tests/tasks.md diff --git a/client/DESIGN.md b/client/DESIGN.md index 38bfb646..b7c16bf9 100644 --- a/client/DESIGN.md +++ b/client/DESIGN.md @@ -313,10 +313,11 @@ v1 设计选择:优先支持 `--control-stdin`,即 stdin 一行一个 JSON 3. `skills:list` 4. `status:get` -当前仍未纳入 Slice C 基线: +Slice D 设计基线: -1. `actions:list` -2. capability discovery / startup handshake +1. v1 capability discovery 优先走显式 `actions:list`,继续复用 `client-control-stdin.v1` +2. unsolicited startup handshake 不纳入当前宿主协议基线,避免在 stdout 多路复用流上引入额外隐式帧 +3. 能力发现返回当前 session 可用的 canonical action ids,不要求首版附带额外元数据矩阵 #### 8.3.5 错误处理与安全边界(Slice C landed baseline) @@ -352,7 +353,7 @@ v1 设计选择:优先支持 `--control-stdin`,即 stdin 一行一个 JSON 4. `script` 模式(注释/空行/失败中断)。 5. headless 协议稳定性(事件 envelope、schema version、error path)。 6. `control-stdin` 往返控制(approvals / MCP / skills / status)。 -7. capability discovery(`actions:list` / 启动握手)与宿主降级策略。 +7. capability discovery(显式 `actions:list`)与宿主降级策略。 ## 11. 分阶段落地计划 @@ -381,7 +382,8 @@ v1 设计选择:优先支持 `--control-stdin`,即 stdin 一行一个 JSON 1. `--headless` 明确模式边界 2. versioned event envelope v1 3. `--control-stdin` 最小外部控制面 -4. capability discovery / handshake +4. 显式 capability discovery(`actions:list`) +5. 启动握手若要引入,需作为后续独立 slice 明确多路复用与兼容策略 ## 12. 风险与缓解 diff --git a/client/README.md b/client/README.md index 033d249e..507cd391 100644 --- a/client/README.md +++ b/client/README.md @@ -347,19 +347,20 @@ Issue #135 对应的宿主编排能力目前分成“已落地”和“未落地 仍未落地: -- `actions:list` / 启动握手式能力发现 +- `actions:list` 显式能力发现 当前推荐边界是: 1. 自动化脚本仍使用 `run/script --output json`。 2. 宿主事件流接入使用 `run/script --headless`。 -3. 运行中控制当前优先使用 `--control-stdin` 做 `status:get`、approvals、MCP 与 `skills:list`;`actions:list` / 启动握手仍在后续 Slice 中。 +3. 运行中控制当前优先使用 `--control-stdin` 做 `status:get`、approvals、MCP 与 `skills:list`;`actions:list` 作为下一 Slice 的显式能力发现入口继续推进。 4. 不要把当前 `log/event/result` 三类 JSON 行当作长期稳定的宿主协议。 补充说明: - `script --headless` 与 `run --headless` 一样支持审批超时控制。 - `script` 可显式传入 `--approval-timeout-seconds `;未显式传入时,headless 脚本默认使用 `120s` 超时,避免无头会话无限等待审批。 +- 启动即发送的 capability handshake 当前不属于 v1 计划;宿主应通过显式 discovery action 获取支持矩阵。 退出码约定: diff --git a/docs/features/client-external-control-plane-v1.md b/docs/features/archive/client-external-control-plane-v1.md similarity index 91% rename from docs/features/client-external-control-plane-v1.md rename to docs/features/archive/client-external-control-plane-v1.md index d93bb89b..5897d6b9 100644 --- a/docs/features/client-external-control-plane-v1.md +++ b/docs/features/archive/client-external-control-plane-v1.md @@ -5,7 +5,7 @@ topics: ["client-cli", "host-orchestration", "control-plane", "issue-135"] todo_ids: ["CCLI-005", "CCLI-006"] created: 2026-03-02 updated: 2026-03-02 -status: active +status: archived mode: openspec --- @@ -46,6 +46,7 @@ mode: openspec - `../../.venv/bin/python -m pytest tests/integration/test_client_cli_flow.py -q` - `openspec list` - `openspec validate client-external-control-plane-v1 --type change --strict --json --no-interactive` +- `openspec archive client-external-control-plane-v1 -y` - `./scripts/ci/check_governance_evidence_truth.sh` ### Results @@ -60,10 +61,11 @@ mode: openspec - `../../.venv/bin/python -m pytest tests/integration/test_client_cli_flow.py -q -k 'status_get_reports_pending_approvals'`: failed before the review fix because `run --headless --control-stdin` only updated the approval timeout watch, leaving `status:get` snapshots blind to pending runtime approvals; passed after wiring run-mode approval pending/resolved events into `CLISessionState.pending_runtime_approvals`. - `../../.venv/bin/python -m pytest tests/integration/test_client_cli_flow.py -q -k 'surfaces_action_handler_failure or rejects_unsupported_action or bridges_approvals_list or control_stdin_status_get_emits_structured_result or script_headless_control_stdin_status_get_reports_active_task'`: passed (`5` tests), covering happy path plus unsupported-action and handler-failure branches. - `../../.venv/bin/python -m pytest tests/unit/test_client_cli.py -q -k 'cancellation_does_not_block_default_executor_shutdown'`: failed before the review fix because cancelling the control task still left a blocking `stdin.readline()` worker pinned in the default executor; passed after moving `control-stdin` reads onto a daemon thread + asyncio queue bridge. -- `../../.venv/bin/python -m pytest tests/unit/test_client_cli.py -q`: passed (`44` tests, `0` failures). -- `../../.venv/bin/python -m pytest tests/integration/test_client_cli_flow.py -q`: passed (`20` tests, `0` failures). +- `../../.venv/bin/python -m pytest tests/unit/test_client_cli.py -q`: passed (`45` tests, `0` failures) after the final `pending_approvals` status snapshot regression fix. +- `../../.venv/bin/python -m pytest tests/integration/test_client_cli_flow.py -q`: passed (`21` tests, `0` failures) after the final `status:get` pending-approval coverage landed. - `openspec list`: confirms Slice A / Slice B have been archived out of the active change list, and the active Slice C change now shows `✓ Complete`. - `openspec validate client-external-control-plane-v1 --type change --strict --json --no-interactive`: passed (`1/1` change valid, `0` issues). +- `openspec archive client-external-control-plane-v1 -y`: archived the completed change to `openspec/changes/archive/2026-03-02-client-external-control-plane-v1/` and synced the landed control-plane deltas back into `openspec/specs/client-host-orchestration/spec.md`. - `./scripts/ci/check_governance_evidence_truth.sh`: passed after the Slice C feature evidence block and prior-slice archive moves were synchronized. ### Behavior Verification @@ -83,7 +85,8 @@ mode: openspec - Slice A intent gate (merged): `https://github.com/zts212653/Deterministic-Agent-Runtime-Engine/pull/141` - Slice B implementation gate (merged): `https://github.com/zts212653/Deterministic-Agent-Runtime-Engine/pull/145` - Slice C docs-only intent PR (merged): `https://github.com/zts212653/Deterministic-Agent-Runtime-Engine/pull/148` -- Slice C implementation PR (open): `https://github.com/zts212653/Deterministic-Agent-Runtime-Engine/pull/151` +- Slice C implementation PR (merged): `https://github.com/zts212653/Deterministic-Agent-Runtime-Engine/pull/151` - Slice C spec-fold review thread: `https://github.com/zts212653/Deterministic-Agent-Runtime-Engine/pull/148#discussion_r2872038646` - Slice C implementation review thread: `https://github.com/zts212653/Deterministic-Agent-Runtime-Engine/pull/151#discussion_r2872629793` - Slice C implementation review thread: `https://github.com/zts212653/Deterministic-Agent-Runtime-Engine/pull/151#discussion_r2872876273` +- Archive target: `openspec/changes/archive/2026-03-02-client-external-control-plane-v1/` diff --git a/docs/features/client-capability-discovery-and-host-tests.md b/docs/features/client-capability-discovery-and-host-tests.md new file mode 100644 index 00000000..fe2619fd --- /dev/null +++ b/docs/features/client-capability-discovery-and-host-tests.md @@ -0,0 +1,71 @@ +--- +change_ids: ["client-capability-discovery-and-host-tests"] +doc_kind: feature +topics: ["client-cli", "host-orchestration", "capability-discovery", "issue-135"] +todo_ids: ["CCLI-007", "CCLI-008"] +created: 2026-03-02 +updated: 2026-03-02 +status: active +mode: openspec +--- + +# Feature: client-capability-discovery-and-host-tests + +## Scope + +落实 Issue #135 的 Slice D:为 `client/` 的宿主协议面补上显式 capability discovery(`actions:list`),并建立覆盖 headless event envelope、control plane 与 discovery 的宿主级回归测试。 + +## OpenSpec Artifacts + +- Proposal: `openspec/changes/client-capability-discovery-and-host-tests/proposal.md` +- Design: `openspec/changes/client-capability-discovery-and-host-tests/design.md` +- Specs: + - `openspec/changes/client-capability-discovery-and-host-tests/specs/client-host-orchestration/spec.md` +- Tasks: `openspec/changes/client-capability-discovery-and-host-tests/tasks.md` + +## TODO Coverage + +- `CCLI-007` +- `CCLI-008` + +## Evidence + +### Commands + +- `git fetch origin` +- `git worktree add .worktrees/client-capability-discovery-and-host-tests -b codex/client-capability-discovery-and-host-tests origin/main` +- `openspec archive client-external-control-plane-v1 -y` +- `../../.venv/bin/python -m pytest tests/unit/test_client_cli.py -q` +- `../../.venv/bin/python -m pytest tests/integration/test_client_cli_flow.py -q` +- `openspec list` +- `openspec show client-capability-discovery-and-host-tests --type change --json --no-interactive` +- `openspec validate client-capability-discovery-and-host-tests --type change --strict --json --no-interactive` +- `./scripts/ci/check_governance_evidence_truth.sh` + +### Results + +- `git fetch origin`: confirmed `origin/main` has merged Slice C via PR `#151`. +- `git worktree add .worktrees/client-capability-discovery-and-host-tests -b codex/client-capability-discovery-and-host-tests origin/main`: created an isolated Slice D workspace from merged `main` at commit `cce6e4d`. +- `openspec archive client-external-control-plane-v1 -y`: archived the completed Slice C change to `openspec/changes/archive/2026-03-02-client-external-control-plane-v1/` and synced the landed control-plane deltas back into the main `client-host-orchestration` spec. +- `../../.venv/bin/python -m pytest tests/unit/test_client_cli.py -q`: passed (`45` tests, `0` failures) as the Slice D kickoff baseline in the new worktree. +- `../../.venv/bin/python -m pytest tests/integration/test_client_cli_flow.py -q`: passed (`21` tests, `0` failures) as the Slice D kickoff baseline in the new worktree. +- `openspec list`: shows the new change as `client-capability-discovery-and-host-tests 0/7 tasks`. +- `openspec show client-capability-discovery-and-host-tests --type change --json --no-interactive`: confirms the change exposes `1` `MODIFIED` delta under `client-host-orchestration`. +- `openspec validate client-capability-discovery-and-host-tests --type change --strict --json --no-interactive`: passed (`1/1` change valid, `0` issues). +- `./scripts/ci/check_governance_evidence_truth.sh`: passed after the Slice C archive moves and Slice D kickoff evidence were synchronized. + +### Behavior Verification + +- Happy path: Slice C is now archived on top of merged `main`, and Slice D design chooses explicit `actions:list` discovery on `--control-stdin` rather than adding startup chatter to the host protocol. +- Error branch: unsolicited startup capability handshake remains out of scope for v1, preventing hosts from depending on implicit frames before explicit discovery semantics are finalized. + +### Risks and Rollback + +- Risk: until Slice D implementation lands, hosts still need a hardcoded discovery matrix even though the design baseline now prefers explicit `actions:list`. +- Rollback: drop the Slice D kickoff change and keep the repository at the archived Slice C baseline where control is available but capability discovery remains planned-only. + +### Review and Merge Gate Links + +- Slice C implementation gate (merged): `https://github.com/zts212653/Deterministic-Agent-Runtime-Engine/pull/151` +- Slice C archive target: `openspec/changes/archive/2026-03-02-client-external-control-plane-v1/` +- Slice D intent PR: pending diff --git a/docs/todos/2026-03-02_client_cli_host_orchestration_master_todo.md b/docs/todos/2026-03-02_client_cli_host_orchestration_master_todo.md index f740efa3..c00e5e43 100644 --- a/docs/todos/2026-03-02_client_cli_host_orchestration_master_todo.md +++ b/docs/todos/2026-03-02_client_cli_host_orchestration_master_todo.md @@ -16,14 +16,15 @@ mode: openspec ## 认领声明(Claim Ledger) -> 当前状态:Slice A / Slice B 已于 2026-03-02 完成并合入 `main`;Slice C 的 docs-only intent PR `#148` 已合入,当前实现已覆盖 approvals / MCP / skills / status 的 `control-stdin` 基线,待进入实现 PR / review gate。 -> Slice C 负责外部 control plane v1;Slice D 继续承担 capability discovery 与宿主级回归测试。 +> 当前状态:Slice A / Slice B / Slice C 已于 2026-03-02 完成并合入 `main`;Slice C 已归档到 `openspec/changes/archive/2026-03-02-client-external-control-plane-v1/`。 +> Slice D 当前进入 docs-first kickoff:先建立 capability discovery 与宿主协议回归测试的设计基线、OpenSpec change 和 intent PR payload,再进入实现。 | Claim ID | TODO Scope | Owner | Status | Declared At | Expires At | OpenSpec Change | Notes | |---|---|---|---|---|---|---|---| -| CLM-20260302-CCLI-A | CCLI-001~CCLI-002 | bouillipx | done | 2026-03-02 | 2026-03-09 | `client-host-orchestration-doc-baseline` | Slice A: docs baseline 已随 PR `#141` 合入 `main`,待归档到 `openspec/changes/archive/2026-03-02-client-host-orchestration-doc-baseline/`。 | -| CLM-20260302-CCLI-B | CCLI-003~CCLI-004 | bouillipx | done | 2026-03-02 | 2026-03-09 | `client-headless-event-envelope-v1` | Slice B: headless event envelope v1 已随 PR `#145` 合入 `main`,待归档到 `openspec/changes/archive/2026-03-02-client-headless-event-envelope-v1/`。 | -| CLM-20260302-CCLI-C | CCLI-005~CCLI-006 | bouillipx | active | 2026-03-02 | 2026-03-09 | `client-external-control-plane-v1` | Slice C: docs-only intent PR `#148` 已合入;当前已落地 `--control-stdin` 最小基线,以及 `status:get`、approvals、`mcp:list/reload/show-tool`、`skills:list` host bridge;`actions:list` 仍留给 Slice D。 | +| CLM-20260302-CCLI-A | CCLI-001~CCLI-002 | bouillipx | done | 2026-03-02 | 2026-03-09 | `client-host-orchestration-doc-baseline` | Slice A: docs baseline 已随 PR `#141` 合入 `main`,并已归档到 `openspec/changes/archive/2026-03-02-client-host-orchestration-doc-baseline/`。 | +| CLM-20260302-CCLI-B | CCLI-003~CCLI-004 | bouillipx | done | 2026-03-02 | 2026-03-09 | `client-headless-event-envelope-v1` | Slice B: headless event envelope v1 已随 PR `#145` 合入 `main`,并已归档到 `openspec/changes/archive/2026-03-02-client-headless-event-envelope-v1/`。 | +| CLM-20260302-CCLI-C | CCLI-005~CCLI-006 | bouillipx | done | 2026-03-02 | 2026-03-09 | `client-external-control-plane-v1` | Slice C: docs-only intent PR `#148` 与实现 PR `#151` 已合入;change 已归档到 `openspec/changes/archive/2026-03-02-client-external-control-plane-v1/`,feature evidence 已迁移到 `docs/features/archive/client-external-control-plane-v1.md`。 | +| CLM-20260302-CCLI-D | CCLI-007~CCLI-008 | bouillipx | active | 2026-03-02 | 2026-03-09 | `client-capability-discovery-and-host-tests` | Slice D: 建立显式 `actions:list` 能力发现与宿主协议回归测试的 docs baseline、OpenSpec artifacts 与 intent PR payload。 | ## 切片规划 @@ -42,10 +43,10 @@ mode: openspec | CCLI-002 | P0 | done | CCLI-GAP-006 | `client-host-orchestration-doc-baseline` | 更新 `client/README.md`,明确当前 `--output json` 是 legacy automation schema,补充后续宿主协议模式的兼容说明。 | bouillipx | `client/README.md`;`docs/features/archive/client-host-orchestration-doc-baseline.md` | 2026-03-02 | | CCLI-003 | P1 | done | CCLI-GAP-001 | `client-headless-event-envelope-v1` | 为 `client` 设计并实现显式 headless 模式,定义禁止 prompt / 禁止内联审批 / 只输出协议帧的行为边界。 | bouillipx | `client/main.py`;`client/session.py`;`tests/integration/test_client_cli_flow.py`;`docs/features/archive/client-headless-event-envelope-v1.md` | 2026-03-02 | | CCLI-004 | P1 | done | CCLI-GAP-002 | `client-headless-event-envelope-v1` | 设计并实现 versioned event envelope(至少含 `schema_version`、`run_id`、`seq`、`event`、`data`),并定义与现有 JSON 输出的兼容策略。 | bouillipx | `client/render/headless.py`;`tests/unit/test_client_cli.py`;`tests/integration/test_client_cli_flow.py`;`docs/features/archive/client-headless-event-envelope-v1.md` | 2026-03-02 | -| CCLI-005 | P1 | doing | CCLI-GAP-003 | `client-external-control-plane-v1` | 设计外部控制协议入口(如 `control-stdin` 或 loopback RPC),覆盖 approvals / MCP / skills / status 的结构化控制。 | bouillipx | `client/main.py`;`client/render/control.py`;`tests/unit/test_client_cli.py`;`tests/integration/test_client_cli_flow.py`;相关 OpenSpec design/specs/tasks | 2026-03-02 | -| CCLI-006 | P2 | doing | CCLI-GAP-005 | `client-external-control-plane-v1` | 将当前 canonical MCP actions(首批为 `mcp:list/reload/show-tool`)接入外部 control plane,并明确运行中生效与错误处理语义。CLI 层 `unload` 待后续补 canonical action 后再纳入宿主协议面。 | bouillipx | `client/main.py`;`tests/integration/test_client_cli_flow.py`;`docs/features/client-external-control-plane-v1.md` | 2026-03-02 | -| CCLI-007 | P2 | todo | CCLI-GAP-004 | `client-capability-discovery-and-host-tests` | 将 `actions:list` 提升到 CLI 宿主协议面,并定义启动握手或显式查询命令。 | TBD | `dare_framework/transport/interaction/resource_action.py`;`client/main.py`;相关文档 | 2026-03-02 | -| CCLI-008 | P1 | todo | CCLI-GAP-006 | `client-capability-discovery-and-host-tests` | 新增 headless 协议稳定性、外部控制、能力发现三组集成测试,并回写 README / 设计文档中的验证锚点。 | TBD | `tests/integration/test_client_cli_flow.py`;新增协议测试文件 | 2026-03-02 | +| CCLI-005 | P1 | done | CCLI-GAP-003 | `client-external-control-plane-v1` | 设计外部控制协议入口(如 `control-stdin` 或 loopback RPC),覆盖 approvals / MCP / skills / status 的结构化控制。 | bouillipx | `client/main.py`;`client/render/control.py`;`tests/unit/test_client_cli.py`;`tests/integration/test_client_cli_flow.py`;`docs/features/archive/client-external-control-plane-v1.md`;`openspec/changes/archive/2026-03-02-client-external-control-plane-v1/` | 2026-03-02 | +| CCLI-006 | P2 | done | CCLI-GAP-005 | `client-external-control-plane-v1` | 将当前 canonical MCP actions(首批为 `mcp:list/reload/show-tool`)接入外部 control plane,并明确运行中生效与错误处理语义。CLI 层 `unload` 待后续补 canonical action 后再纳入宿主协议面。 | bouillipx | `client/main.py`;`tests/integration/test_client_cli_flow.py`;`docs/features/archive/client-external-control-plane-v1.md`;`openspec/changes/archive/2026-03-02-client-external-control-plane-v1/` | 2026-03-02 | +| CCLI-007 | P2 | doing | CCLI-GAP-004 | `client-capability-discovery-and-host-tests` | 将 `actions:list` 提升到 CLI 宿主协议面,并收敛为显式 discovery action;启动握手不纳入当前 v1 scope。 | bouillipx | `client/DESIGN.md`;`client/README.md`;`docs/features/client-capability-discovery-and-host-tests.md`;相关 OpenSpec design/specs/tasks | 2026-03-02 | +| CCLI-008 | P1 | doing | CCLI-GAP-006 | `client-capability-discovery-and-host-tests` | 新增 headless 协议稳定性、外部控制、能力发现三组集成测试,并回写 README / 设计文档中的验证锚点。 | bouillipx | `tests/integration/test_client_cli_flow.py`;`docs/features/client-capability-discovery-and-host-tests.md`;相关 OpenSpec design/specs/tasks | 2026-03-02 | --- diff --git a/openspec/changes/client-external-control-plane-v1/.openspec.yaml b/openspec/changes/archive/2026-03-02-client-external-control-plane-v1/.openspec.yaml similarity index 100% rename from openspec/changes/client-external-control-plane-v1/.openspec.yaml rename to openspec/changes/archive/2026-03-02-client-external-control-plane-v1/.openspec.yaml diff --git a/openspec/changes/client-external-control-plane-v1/design.md b/openspec/changes/archive/2026-03-02-client-external-control-plane-v1/design.md similarity index 100% rename from openspec/changes/client-external-control-plane-v1/design.md rename to openspec/changes/archive/2026-03-02-client-external-control-plane-v1/design.md diff --git a/openspec/changes/client-external-control-plane-v1/proposal.md b/openspec/changes/archive/2026-03-02-client-external-control-plane-v1/proposal.md similarity index 100% rename from openspec/changes/client-external-control-plane-v1/proposal.md rename to openspec/changes/archive/2026-03-02-client-external-control-plane-v1/proposal.md diff --git a/openspec/changes/client-external-control-plane-v1/specs/client-host-orchestration/spec.md b/openspec/changes/archive/2026-03-02-client-external-control-plane-v1/specs/client-host-orchestration/spec.md similarity index 100% rename from openspec/changes/client-external-control-plane-v1/specs/client-host-orchestration/spec.md rename to openspec/changes/archive/2026-03-02-client-external-control-plane-v1/specs/client-host-orchestration/spec.md diff --git a/openspec/changes/client-external-control-plane-v1/tasks.md b/openspec/changes/archive/2026-03-02-client-external-control-plane-v1/tasks.md similarity index 100% rename from openspec/changes/client-external-control-plane-v1/tasks.md rename to openspec/changes/archive/2026-03-02-client-external-control-plane-v1/tasks.md diff --git a/openspec/changes/client-capability-discovery-and-host-tests/.openspec.yaml b/openspec/changes/client-capability-discovery-and-host-tests/.openspec.yaml new file mode 100644 index 00000000..fd79bfc5 --- /dev/null +++ b/openspec/changes/client-capability-discovery-and-host-tests/.openspec.yaml @@ -0,0 +1,2 @@ +schema: spec-driven +created: 2026-03-02 diff --git a/openspec/changes/client-capability-discovery-and-host-tests/design.md b/openspec/changes/client-capability-discovery-and-host-tests/design.md new file mode 100644 index 00000000..c7343673 --- /dev/null +++ b/openspec/changes/client-capability-discovery-and-host-tests/design.md @@ -0,0 +1,71 @@ +## Context + +`client/` 在 Slice C 之后已经具备了可写的本地 control plane,但 capability discovery 仍然缺位: + +- transport runtime 内部已经支持 `actions:list`,并返回当前注册的 canonical `resource:action` ids; +- CLI 宿主协议桥接目前只暴露 approvals / MCP / skills / status,未把 `actions:list` 暴露给外部宿主; +- 现有集成测试主要按功能面分段验证,还没有把 headless event envelope、control plane 和 capability discovery 作为统一协议面冻结。 + +Issue #135 的最后一片因此不需要再扩 transport 语义,而是要把已有 discovery surface 提升到 CLI 宿主协议面,并为协议稳定性建立联合回归。 + +## Goals / Non-Goals + +**Goals:** + +- 通过现有 `client-control-stdin.v1` 暴露显式 `actions:list` 能力发现。 +- 明确 v1 discovery baseline:显式请求、结构化响应、无 startup handshake。 +- 为宿主协议补齐 capability discovery happy path 与回归测试。 +- 把 Slice D 的设计选择回写到 canonical docs 与 feature evidence。 + +**Non-Goals:** + +- 本次不引入启动即发送的 capability handshake。 +- 本次不为 action discovery 设计 richer metadata schema。 +- 本次不引入新的控制通道(例如 loopback RPC / websocket)。 +- 本次不改变 Slice B / Slice C 已落地的 envelope schema。 + +## Decisions + +### Decision 1: v1 capability discovery 采用显式 `actions:list` + +- 宿主通过已存在的 `--control-stdin` 通道显式发送 `actions:list`。 +- CLI 不会在 session 启动时自动发送 discovery frame。 +- 这一选择避免了在 headless event envelope 与 control result 多路复用流上再引入第三类“隐式 handshake”启动帧。 + +### Decision 2: discovery payload 继续复用 transport canonical shape + +- `actions:list` 的返回结果继续使用现有 transport payload 形状:`{"actions": ["resource:action", ...]}`。 +- 首版只承诺 canonical action id 列表,不额外附带 capability metadata。 +- 返回动作必须与当前 session 真实可调用的 CLI host bridge surface 一致,而不是静态文档枚举。 + +### Decision 3: Slice D 把宿主协议作为联合回归面冻结 + +- 集成测试至少覆盖: + - headless event envelope 基线仍可稳定输出; + - `control-stdin` 在 `actions:list` 加入后不破坏现有 approvals / MCP / skills / status; + - capability discovery 结果可被宿主直接消费,无需解析 help 文本或启动 chatter。 +- 错误路径至少覆盖: + - 不支持的 action 仍返回结构化错误; + - 未请求 discovery 时不会出现 unsolicited startup handshake frame。 + +## Risks / Trade-offs + +- [Risk] `actions:list` 可能暴露 runtime 内部尚未桥接的 action id。 + → Mitigation: Slice D 需要明确 discovery 返回的是 CLI host bridge 当前 surface,而不是底层 transport 的全部潜在动作。 + +- [Risk] 把 startup handshake 推迟可能要求宿主多发一次 discovery 请求。 + → Mitigation: 显式请求比隐式帧更容易做多路复用和兼容控制,首版优先稳定性而不是减少一个往返。 + +- [Risk] 回归测试过度绑定当前 action 列表,降低未来扩展空间。 + → Mitigation: 测试以“至少包含 / error contract 稳定”为主,避免把列表顺序或未来扩展动作硬编码成脆弱断言。 + +## Migration Plan + +1. 在 canonical docs 中把 Slice D 设计基线收敛到显式 `actions:list`,并明确 startup handshake 延后。 +2. 在 CLI host bridge 中暴露 `actions:list`。 +3. 增加 capability discovery 与宿主协议联合回归测试。 +4. 回写 feature evidence、master TODO、review links 和最终归档记录。 + +## Open Questions + +- `actions:list` 是否应只返回 action id 列表,还是需要在后续 slice 中增加 category / mutability / docs link 等 metadata? diff --git a/openspec/changes/client-capability-discovery-and-host-tests/proposal.md b/openspec/changes/client-capability-discovery-and-host-tests/proposal.md new file mode 100644 index 00000000..bd1fd81c --- /dev/null +++ b/openspec/changes/client-capability-discovery-and-host-tests/proposal.md @@ -0,0 +1,39 @@ +## Why + +Slice C 已经让宿主可以通过 `--control-stdin` 对活跃 headless run 发送 approvals / MCP / skills / status 控制,但宿主仍然必须硬编码“当前 CLI 支持哪些动作”。Issue #135 剩余的协议缺口因此不再是控制写路径,而是显式能力发现与宿主级回归冻结。 + +当前 `main` 的剩余问题有两类: + +1. CLI 宿主协议面还没有暴露 `actions:list`,宿主无法在运行时查询当前 session 的 canonical action surface。 +2. headless event envelope、control-stdin 和 capability discovery 还没有被同一组宿主协议回归测试一起冻结,后续演进容易在一个面上修复时回退另一个面。 + +Slice D 收敛到两件事:把 `actions:list` 提升为宿主协议动作,并补齐宿主级协议回归测试。启动即发送的 capability handshake 不纳入这一版基线,避免在 stdout 多路复用流里额外引入隐式协议帧。 + +## What Changes + +- 为 `run/script --headless --control-stdin` 暴露显式 `actions:list` capability discovery。 +- 定义 Slice D 的 v1 discovery baseline:显式请求、结构化返回、无 unsolicited startup handshake。 +- 增加宿主协议集成测试,覆盖 headless event envelope、control plane 和 capability discovery 的联合回归面。 +- 回写 `client/DESIGN.md`、`client/README.md`、master TODO 和 feature evidence,作为实现前的 docs-first 基线。 + +## Capabilities + +### Modified Capabilities + +- `client-host-orchestration`: 把“planned capability discovery”推进为显式 `actions:list` 宿主协议动作,并补齐协议回归锚点。 + +## Impact + +- 影响文件: + - `client/main.py` + - `client/DESIGN.md` + - `client/README.md` + - `tests/unit/test_client_cli.py` + - `tests/integration/test_client_cli_flow.py` + - `docs/todos/2026-03-02_client_cli_host_orchestration_master_todo.md` + - `docs/features/client-capability-discovery-and-host-tests.md` + - `openspec/changes/client-capability-discovery-and-host-tests/**` +- 不包含: + - 启动即发送的 capability handshake + - 更丰富的 capability metadata schema(标签、权限、分类矩阵) + - 新的网络控制入口或 `--control-port` diff --git a/openspec/changes/client-capability-discovery-and-host-tests/specs/client-host-orchestration/spec.md b/openspec/changes/client-capability-discovery-and-host-tests/specs/client-host-orchestration/spec.md new file mode 100644 index 00000000..31a119b1 --- /dev/null +++ b/openspec/changes/client-capability-discovery-and-host-tests/specs/client-host-orchestration/spec.md @@ -0,0 +1,20 @@ +## MODIFIED Requirements + +### Requirement: Host capabilities are discoverable without hardcoded matrices +The system SHALL provide a deterministic capability discovery surface for host orchestration. + +- v1 capability discovery MUST be exposed as an explicit `actions:list` request over the structured local control plane. +- The discovery response MUST return the currently supported canonical action ids as structured data. +- v1 MUST NOT require an unsolicited startup handshake before a host can interact with the session. + +#### Scenario: Host queries supported actions over control plane +- **GIVEN** a host is attached to a running headless session through `--control-stdin` +- **WHEN** it sends action `actions:list` +- **THEN** the client returns a structured list of currently supported canonical action ids +- **AND** the host does not need to infer support by parsing help text or natural-language output + +#### Scenario: Startup does not emit unsolicited capability handshake +- **GIVEN** a host starts a headless session and has not sent a discovery request +- **WHEN** the session begins running +- **THEN** the client does not emit an unsolicited capability handshake frame +- **AND** capability discovery remains available through an explicit structured request diff --git a/openspec/changes/client-capability-discovery-and-host-tests/tasks.md b/openspec/changes/client-capability-discovery-and-host-tests/tasks.md new file mode 100644 index 00000000..65dddfc1 --- /dev/null +++ b/openspec/changes/client-capability-discovery-and-host-tests/tasks.md @@ -0,0 +1,15 @@ +## 1. Capability Discovery Bridge + +- [ ] 1.1 将 `actions:list` 暴露到 `run/script --headless --control-stdin` 的 host bridge。 +- [ ] 1.2 明确并验证 discovery 返回的是当前 CLI host protocol surface,而不是 unsolicited startup handshake。 + +## 2. Host Protocol Regression Coverage + +- [ ] 2.1 增加 `actions:list` 的宿主协议 happy path 集成测试。 +- [ ] 2.2 增加 capability discovery 与现有 approvals / MCP / skills / status 共存的回归测试。 +- [ ] 2.3 覆盖 discovery 相关 error branch 和“无 startup handshake”约束。 + +## 3. Docs And Evidence + +- [ ] 3.1 更新 `client/DESIGN.md` 与 `client/README.md`,锁定显式 discovery baseline 和 handshake 延后策略。 +- [ ] 3.2 回写 `docs/features/client-capability-discovery-and-host-tests.md`、master TODO 与 review/merge-gate evidence。 diff --git a/openspec/specs/client-host-orchestration/spec.md b/openspec/specs/client-host-orchestration/spec.md index 6fa7f695..168dd1b0 100644 --- a/openspec/specs/client-host-orchestration/spec.md +++ b/openspec/specs/client-host-orchestration/spec.md @@ -2,9 +2,7 @@ ## Purpose Define the stable host-orchestration contract for `client/`, including explicit mode separation, headless event semantics, the planned structured local control plane, and capability discovery boundaries. - ## Requirements - ### Requirement: Client host orchestration modes are explicitly separated The system SHALL distinguish between interactive CLI behavior, legacy automation JSON output, and host-orchestrated headless execution. @@ -55,8 +53,9 @@ The system SHALL emit a versioned event envelope for headless mode that is disti ### Requirement: Host control is provided through a structured local control plane The system SHALL provide a structured local control plane for host-orchestrated sessions. +- v1 MUST support a local `--control-stdin` entry for headless `run/script`. - The control plane MUST accept deterministic actions for approvals, MCP management, skills discovery, and session status. -- Control responses MUST use structured success/error payloads. +- Control responses MUST use structured success/error payloads with request correlation. - The control plane MUST preserve existing approval and action semantics rather than bypassing them. #### Scenario: Host grants approval through structured control @@ -65,6 +64,12 @@ The system SHALL provide a structured local control plane for host-orchestrated - **THEN** the client resolves the approval through the deterministic approval action path - **AND** the result is returned as a structured control response +#### Scenario: Unknown control action fails structurally +- **GIVEN** a host sends a control command with an unsupported action id +- **WHEN** the client validates the command frame +- **THEN** the client returns a structured error response +- **AND** it does not fall back to prompt-oriented or natural-language command parsing + ### Requirement: Host capabilities are discoverable without hardcoded matrices The system SHALL provide a deterministic capability discovery surface for host orchestration. @@ -76,3 +81,23 @@ The system SHALL provide a deterministic capability discovery surface for host o - **WHEN** it requests capability discovery - **THEN** the client returns a structured list of supported actions - **AND** the host does not need to infer support by parsing help text or natural-language output + +### Requirement: Control plane v1 reuses canonical action identifiers +The system SHALL expose control-plane actions using canonical stable identifiers. + +- MCP control in v1 MUST be limited to `mcp:list`, `mcp:reload`, and `mcp:show-tool`. +- CLI-only verbs without canonical actions, including `mcp:unload`, MUST NOT be advertised as v1 host protocol actions. +- Approvals and skills actions MUST reuse their existing `resource:action` identifiers. + +#### Scenario: Host reloads MCP providers through canonical action id +- **GIVEN** the host needs to refresh MCP provider paths for a running headless session +- **WHEN** it sends action `mcp:reload` through the control plane +- **THEN** the client reuses the current MCP reload runtime path +- **AND** the response is returned as a structured control result + +#### Scenario: Host requests CLI session status +- **GIVEN** a headless session is running under the CLI host protocol +- **WHEN** the host sends action `status:get` +- **THEN** the client returns a structured snapshot of current session state +- **AND** the response is correlated to the request id + From cee7a50030fbb4e242d5b890517bbbe43d5b7b5d Mon Sep 17 00:00:00 2001 From: bouillipx Date: Mon, 2 Mar 2026 23:27:57 +0800 Subject: [PATCH 2/3] docs(feature): record Slice D intent PR evidence Record the docs-only intent PR link for client-capability-discovery-and-host-tests in the active feature evidence doc. Key changes: - replace the pending Slice D intent PR placeholder with the live PR #156 link - rerun governance evidence truth after the evidence update Rationale: The feature aggregation doc is the source of truth for review and merge-gate evidence. Once the intent PR exists, its link should live in the feature evidence immediately so the next implementation slice can trace the merged docs gate without reconstructing it from GitHub history. --- docs/features/client-capability-discovery-and-host-tests.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/features/client-capability-discovery-and-host-tests.md b/docs/features/client-capability-discovery-and-host-tests.md index fe2619fd..82cb2236 100644 --- a/docs/features/client-capability-discovery-and-host-tests.md +++ b/docs/features/client-capability-discovery-and-host-tests.md @@ -68,4 +68,4 @@ mode: openspec - Slice C implementation gate (merged): `https://github.com/zts212653/Deterministic-Agent-Runtime-Engine/pull/151` - Slice C archive target: `openspec/changes/archive/2026-03-02-client-external-control-plane-v1/` -- Slice D intent PR: pending +- Slice D intent PR: `https://github.com/zts212653/Deterministic-Agent-Runtime-Engine/pull/156` From e97f2e6b51fce8ba1037ee343b3746e955a69e43 Mon Sep 17 00:00:00 2001 From: bouillipx Date: Mon, 2 Mar 2026 23:35:35 +0800 Subject: [PATCH 3/3] docs(feature): fix archived Slice C artifact links Point the archived client-external-control-plane-v1 feature doc at the archived OpenSpec artifact paths instead of the pre-archive active change location. Key changes: - update proposal/design/spec/tasks links in docs/features/archive/client-external-control-plane-v1.md to openspec/changes/archive/2026-03-02-client-external-control-plane-v1 - rerun governance evidence truth after the archived-link fix Rationale: Once Slice C was archived, the feature aggregation doc became the retained audit record for that slice. Leaving its artifact links pointed at the deleted active-change path broke the docs-first traceability chain and forced readers to reconstruct archive locations manually. --- docs/features/archive/client-external-control-plane-v1.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/features/archive/client-external-control-plane-v1.md b/docs/features/archive/client-external-control-plane-v1.md index 5897d6b9..d6b95f39 100644 --- a/docs/features/archive/client-external-control-plane-v1.md +++ b/docs/features/archive/client-external-control-plane-v1.md @@ -17,11 +17,11 @@ mode: openspec ## OpenSpec Artifacts -- Proposal: `openspec/changes/client-external-control-plane-v1/proposal.md` -- Design: `openspec/changes/client-external-control-plane-v1/design.md` +- Proposal: `openspec/changes/archive/2026-03-02-client-external-control-plane-v1/proposal.md` +- Design: `openspec/changes/archive/2026-03-02-client-external-control-plane-v1/design.md` - Specs: - - `openspec/changes/client-external-control-plane-v1/specs/client-host-orchestration/spec.md` -- Tasks: `openspec/changes/client-external-control-plane-v1/tasks.md` + - `openspec/changes/archive/2026-03-02-client-external-control-plane-v1/specs/client-host-orchestration/spec.md` +- Tasks: `openspec/changes/archive/2026-03-02-client-external-control-plane-v1/tasks.md` ## TODO Coverage