Skip to content

Commit 433e20a

Browse files
author
SqlRush
committed
Accept wrapped runtime action booleans
1 parent 9880934 commit 433e20a

5 files changed

Lines changed: 71 additions & 11 deletions

File tree

docs/cc-100-roadmap.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -598,6 +598,8 @@ M7 补充:prompt history `LogEntry` 读取现在接受 `sessionID`/`session`/`
598598

599599
本轮补充:interaction script 的 direct runtime mutation alias 字段现在接受 object payload;`removeTask: {resource:{id}}``cancelPermission: {edge:{node:{id}}}``cancelTasks: {resource:{attributes:{reasonText}}}` 会走同一递归解析路径,不再被 string/bool alias 字段提前拒绝。
600600

601+
本轮补充:interaction script action 的 boolean payload 现在也递归解包 JSON:API/GraphQL wrapper;`cancelTasks`/`openTasks` 等动作会尊重 `payload.resource.attributes.enabled:false``edge.node.attrs.open:false` 这类 wrapped false,而不是因为 object payload fallback 成 true。
602+
601603
本轮补充:interaction script step 接受 `resize`/`terminalSize`/`screenSize` 对象或 `[width,height]` 数组、顶层 `columns`/`rows` resize 别名、`focus`/`focused`/`blur`/`focusIn`/`focusOut` focus event 别名、`snapshot`/`snapshotId`/`snapshotLabel` capture 名称别名,以及 runtime-aware mutation 别名如 `permission`/`permissionRequest``task`/`taskStatus``removeTask`/`deleteTask``cancelPermission``cancelTasks`/`cancelReason``openTasks`/`showTasks`
602604

603605
本轮补充:interaction script step 可通过 `status`/`setStatus`/`statusLine`/`baseStatus` 设置状态行;runtime-aware scripts 会把它作为 base status,并继续叠加 permission/task 计数,便于复用带状态栏的 ANSI/interaction fixture。

docs/claude-code-go-rewrite-plan.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,7 @@ test/parity/ # golden tests against TS/official behavior
285285
- 本轮补充:scripted runtime 的 permission/task payload 现在会递归解包 `value`/`payload`/`data`/`resource`/`attributes`/`properties`/`attrs`/`edge`/`node` 等 JSON:API/GraphQL wrapper;resource/node 顶层 ID 会回填到内层 permission/task,并避免仅因 wrapper 顶层 ID 生成半空 runtime 对象。
286286
- 本轮补充:scripted runtime mutation 的 `removeTask`/`cancelPermission`/`cancelTasks` 现在也会从 wrapped `value`/`payload`/`data`/`resource`/`edge.node` 中递归读取 task/permission ID 和 cancellation detail,兼容 resource/action fixture 直接驱动 runtime mutation。
287287
- 本轮补充:scripted runtime mutation 的直接 alias 字段现在也接受 object payload,例如 `removeTask: {resource:{id}}``cancelPermission: {edge:{node:{id}}}``cancelTasks: {resource:{attributes:{reasonText}}}` 不再因 string/bool 强类型字段提前解析失败。
288+
- 本轮补充:scripted runtime action 的 boolean payload 现在同样递归解包 `resource`/`attributes`/`edge.node`/`attrs``cancelTasks`/`openTasks` 等动作可用 wrapped `enabled:false`/`open:false` 明确禁用,避免 wrapper object 默认 fallback 成 true。
288289
- 本轮补充:scripted interaction 的布尔字段现在接受非严格 bool payload,包括 `"true"`/`"false"``yes`/`no``on`/`off` 和数字 `1`/`0`;覆盖 mouse release、dialog visible/result、prompt empty、vim state、reverse-search,以及 focus/cancel/openTasks/expectNoEvent/expectFocused 等顶层 step 控制字段。
289290
- 本轮补充:scripted interaction step 现在接受 `expect`/`expected`/`assertions`/`checks`/`verify`/`then`/`after` 等 expectation wrapper object,可把嵌套的 prompt/event/dialog/snapshot/screen/task/vim/viewport 断言映射到已有 `expect*` 字段。
290291
- 本轮补充:scripted interaction expectation wrapper 现在也接受 assertion/check 数组;数组元素可用 `type`/`kind`/`name`/`target` 等 discriminator 加 `value`/`payload` 载荷声明 prompt/event/dialog/snapshot/screen/task/vim/viewport 断言,覆盖官方 fixture 常见的分列 checks 形态。

docs/first-second-parity-audit.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ M7 progress now includes:
222222
- `internal/tui`: scripted runtime permission/task payloads now recursively unwrap JSON:API/GraphQL-style envelopes such as `value`, `payload`, `data`, `resource`, `attributes`, `properties`, `attrs`, `edge`, and `node`, while carrying resource/node IDs into nested permission/task objects and avoiding empty objects created from wrapper-only payloads.
223223
- `internal/tui`: scripted runtime mutations now recursively unwrap wrapped IDs/details for `removeTask`, `cancelPermission`, and `cancelTasks`, so action fixtures can carry task IDs, permission IDs, and cancellation reasons inside `payload.resource.attributes`, `edge.node`, or adjacent API envelopes.
224224
- `internal/tui`: scripted runtime mutation alias fields now accept object payloads directly, so `removeTask`, `cancelPermission`, and `cancelTasks` can carry wrapped resource/edge payloads without failing early on string/bool-only unmarshalling.
225+
- `internal/tui`: scripted runtime action booleans now recurse through wrapped payloads, letting `cancelTasks`, `openTasks`, and related action-discriminator steps honor JSON:API/GraphQL `enabled:false` or `open:false` flags instead of falling back to true for object payloads.
225226
- `internal/tui`: scripted interaction boolean aliases now accept non-strict bool payloads (`"true"`/`"false"`, `yes`/`no`, `on`/`off`, and numeric `1`/`0`) for mouse release, dialog visibility/result checks, prompt empty checks, vim state checks, reverse-search checks, and top-level step controls such as focus, cancellation, task dialog open, and negative event assertions.
226227
- `internal/tui`: scripted interaction steps now accept expectation wrapper objects such as `expect`, `expected`, `assertions`, `checks`, `verify`, `then`, and `after`, mapping nested prompt/event/dialog/snapshot/screen/task/vim/viewport assertions onto the existing `expect*` fields.
227228
- `internal/tui`: scripted interaction expectation wrappers now also accept assertion/check arrays with `type`/`kind`/`name`/`target` discriminators and `value`/`payload` assertion bodies, covering official fixture styles that list checks separately.

internal/tui/script_aliases.go

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1802,20 +1802,18 @@ func scriptStringFromJSON(raw json.RawMessage) string {
18021802
}
18031803

18041804
func scriptActionBoolField(fields map[string]json.RawMessage, fallback bool) bool {
1805-
if value := boolPtrJSONField(fields, "value", "payload", "data", "enabled", "active", "open"); value != nil {
1806-
return *value
1807-
}
1808-
for _, raw := range scriptActionRawFields(fields) {
1809-
raw = bytes.TrimSpace(raw)
1810-
if len(raw) == 0 || raw[0] != '{' {
1805+
for _, name := range []string{"value", "payload", "data", "body", "enabled", "active", "open"} {
1806+
raw, ok := fields[name]
1807+
if !ok {
18111808
continue
18121809
}
1813-
nested := map[string]json.RawMessage{}
1814-
if err := json.Unmarshal(raw, &nested); err != nil {
1815-
continue
1810+
if value, ok := scriptActionBoolFromJSON(raw, 0); ok {
1811+
return value
18161812
}
1817-
if value := boolPtrJSONField(nested, "enabled", "active", "open", "value"); value != nil {
1818-
return *value
1813+
}
1814+
for _, raw := range scriptActionRawFields(fields) {
1815+
if value, ok := scriptActionBoolFromJSON(raw, 0); ok {
1816+
return value
18191817
}
18201818
}
18211819
return fallback

internal/tui/tui_test.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6357,6 +6357,64 @@ func TestRunDialogRuntimeScriptAcceptsWrappedRuntimeMutationAliasFields(t *testi
63576357
}
63586358
}
63596359

6360+
func TestRunDialogRuntimeScriptAcceptsWrappedRuntimeActionBooleans(t *testing.T) {
6361+
steps, err := ParseInteractionScript([]byte(`[
6362+
{
6363+
"task": {"id": "task_bool", "title": "Wrapped bool", "state": "running", "detail": "working", "progress": 12},
6364+
"expectTasks": {"count": 1, "stateCounts": {"running": 1}}
6365+
},
6366+
{
6367+
"action": "cancelTasks",
6368+
"payload": {
6369+
"resource": {
6370+
"attributes": {
6371+
"enabled": false,
6372+
"reasonText": "should not cancel"
6373+
}
6374+
}
6375+
},
6376+
"expectTasks": {
6377+
"count": 1,
6378+
"stateCounts": {"running": 1},
6379+
"contains": {"id": "task_bool", "state": "running", "detail": "working"}
6380+
},
6381+
"expectStatusContains": ["running: 1"]
6382+
},
6383+
{
6384+
"action": "openTasks",
6385+
"payload": {
6386+
"resource": {
6387+
"attributes": {
6388+
"open": false
6389+
}
6390+
}
6391+
},
6392+
"expectDialog": {"active": false}
6393+
},
6394+
{
6395+
"action": "openTasks",
6396+
"payload": {
6397+
"edge": {
6398+
"node": {
6399+
"attrs": {
6400+
"open": true
6401+
}
6402+
}
6403+
}
6404+
},
6405+
"expectDialog": {"active": true, "dialogID": "tasks", "dialogKind": "task"}
6406+
}
6407+
]`))
6408+
if err != nil {
6409+
t.Fatal(err)
6410+
}
6411+
screen := NewREPLScreen(64, 10, nil)
6412+
runtime := NewDialogRuntime()
6413+
if _, err := RunDialogRuntimeScriptChecked(&screen, runtime, "ready", steps); err != nil {
6414+
t.Fatal(err)
6415+
}
6416+
}
6417+
63606418
func TestRunInteractionScriptAcceptsEventFieldAliases(t *testing.T) {
63616419
steps, err := ParseInteractionScript([]byte(`[
63626420
{"input": "go", "expectPrompt": {"text": "go"}},

0 commit comments

Comments
 (0)