fix(tool-todo): drop the unreachable status re-check that broke the coverage gate
The registry's validateArgs rejects a bad `status` enum before execute runs, so the in-body re-check (`status !== 'pending' && …` → throw) was unreachable dead code — line 70 was uncovered, failing the per-file 100% coverage gate. Narrow the registry-guaranteed value with `status as TodoItem['status']` instead of re-validating it, mirroring tool-bash (which only checks what the DSL can't express). The malformed-status test still passes — it exercises the registry's rejection, the actual path. Coverage back to 100%.
This commit is contained in:
@@ -40,17 +40,20 @@ const DESCRIPTION =
|
|||||||
+ '(not started), `in_progress` (being worked on now), `completed` (finished).'
|
+ '(not started), `in_progress` (being worked on now), `completed` (finished).'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate the constraints the SchemaSpec can't express AND narrow the loosely
|
* Validate the value constraints the SchemaSpec can't express and build the
|
||||||
* typed args into a real {@link TodoItem}[].
|
* canonical {@link TodoItem}[].
|
||||||
*
|
*
|
||||||
* `defineTool` already validates type/required/enum before `execute` runs, but
|
* `defineTool` already validates type/required/enum before `execute` runs (a
|
||||||
* `InferArgs` maps an `enum` string prop to plain `string` (not the literal
|
* bad `status` is rejected by the registry's `validateArgs`, never reaching
|
||||||
* union), so `args.todos` arrives as `{ content: string; status: string }[]` —
|
* here), so `status` is guaranteed to be one of the three enum literals. But
|
||||||
* not assignable to `TodoItem[]`. This pass is therefore the type boundary: it
|
* `InferArgs` maps an `enum` string prop to plain `string`, so the compiler sees
|
||||||
* re-checks each `status` against the literal set (belt-and-suspenders for the
|
* `args.todos` as `{ content: string; status: string }[]`; the
|
||||||
* compiler, which can't see the registry's prior validation) and builds a fresh
|
* `status as TodoItem['status']` narrowing records that registry guarantee
|
||||||
* `TodoItem[]`. It also enforces the value rules the DSL has no vocabulary for:
|
* rather than re-checking it (an unreachable re-check would be dead code — see
|
||||||
* non-empty unique content, and at most one `in_progress` task.
|
* AGENTS.md "don't validate scenarios that can't happen"). What remains is the
|
||||||
|
* value rules the DSL has no vocabulary for: non-empty unique content (stored
|
||||||
|
* trimmed, so the persisted value matches the dedupe/length key), and at most
|
||||||
|
* one `in_progress` task.
|
||||||
*/
|
*/
|
||||||
function toTodoList(raw: { content: string; status: string }[]): TodoItem[] {
|
function toTodoList(raw: { content: string; status: string }[]): TodoItem[] {
|
||||||
const todos: TodoItem[] = []
|
const todos: TodoItem[] = []
|
||||||
@@ -65,10 +68,7 @@ function toTodoList(raw: { content: string; status: string }[]): TodoItem[] {
|
|||||||
throw new Error(`invalid todos: duplicate content ${JSON.stringify(content)}`)
|
throw new Error(`invalid todos: duplicate content ${JSON.stringify(content)}`)
|
||||||
}
|
}
|
||||||
seen.add(content)
|
seen.add(content)
|
||||||
const status = item.status
|
const status = item.status as TodoItem['status']
|
||||||
if (status !== 'pending' && status !== 'in_progress' && status !== 'completed') {
|
|
||||||
throw new Error(`invalid todo status ${JSON.stringify(status)}: expected one of ${STATUSES.join(', ')}`)
|
|
||||||
}
|
|
||||||
if (status === 'in_progress') inProgress++
|
if (status === 'in_progress') inProgress++
|
||||||
todos.push({ content, status })
|
todos.push({ content, status })
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user