feat(task-system): add experimental task system with Claude Code spec alignment (#1415)
* feat(hooks): add tasks-todowrite-disabler hook to block TodoRead/TodoWrite Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * feat(task-tools): add parallel execution guidance to descriptions Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * refactor(index): migrate task system to experimental.task_system flag Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * docs: update AGENTS.md for experimental task system Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * fix(task-tests): align test field names with Claude Code spec (subject, blockedBy, addBlockedBy) * fix: address Cubic review feedback Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * fix: add optional chaining for tasksTodowriteDisabler null check --------- Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -0,0 +1,137 @@
|
||||
import { describe, expect, test } from "bun:test"
|
||||
|
||||
const { createTasksTodowriteDisablerHook } = await import("./index")
|
||||
|
||||
describe("tasks-todowrite-disabler", () => {
|
||||
describe("when experimental.task_system is enabled", () => {
|
||||
test("should block TodoWrite tool", async () => {
|
||||
// given
|
||||
const hook = createTasksTodowriteDisablerHook({ experimental: { task_system: true } })
|
||||
const input = {
|
||||
tool: "TodoWrite",
|
||||
sessionID: "test-session",
|
||||
callID: "call-1",
|
||||
}
|
||||
const output = {
|
||||
args: {},
|
||||
}
|
||||
|
||||
// when / then
|
||||
await expect(
|
||||
hook["tool.execute.before"](input, output)
|
||||
).rejects.toThrow("TodoRead/TodoWrite are disabled")
|
||||
})
|
||||
|
||||
test("should block TodoRead tool", async () => {
|
||||
// given
|
||||
const hook = createTasksTodowriteDisablerHook({ experimental: { task_system: true } })
|
||||
const input = {
|
||||
tool: "TodoRead",
|
||||
sessionID: "test-session",
|
||||
callID: "call-1",
|
||||
}
|
||||
const output = {
|
||||
args: {},
|
||||
}
|
||||
|
||||
// when / then
|
||||
await expect(
|
||||
hook["tool.execute.before"](input, output)
|
||||
).rejects.toThrow("TodoRead/TodoWrite are disabled")
|
||||
})
|
||||
|
||||
test("should not block other tools", async () => {
|
||||
// given
|
||||
const hook = createTasksTodowriteDisablerHook({ experimental: { task_system: true } })
|
||||
const input = {
|
||||
tool: "Read",
|
||||
sessionID: "test-session",
|
||||
callID: "call-1",
|
||||
}
|
||||
const output = {
|
||||
args: {},
|
||||
}
|
||||
|
||||
// when / then
|
||||
await expect(
|
||||
hook["tool.execute.before"](input, output)
|
||||
).resolves.toBeUndefined()
|
||||
})
|
||||
})
|
||||
|
||||
describe("when experimental.task_system is disabled or undefined", () => {
|
||||
test("should not block TodoWrite when flag is false", async () => {
|
||||
// given
|
||||
const hook = createTasksTodowriteDisablerHook({ experimental: { task_system: false } })
|
||||
const input = {
|
||||
tool: "TodoWrite",
|
||||
sessionID: "test-session",
|
||||
callID: "call-1",
|
||||
}
|
||||
const output = {
|
||||
args: {},
|
||||
}
|
||||
|
||||
// when / then
|
||||
await expect(
|
||||
hook["tool.execute.before"](input, output)
|
||||
).resolves.toBeUndefined()
|
||||
})
|
||||
|
||||
test("should not block TodoWrite when experimental is undefined", async () => {
|
||||
// given
|
||||
const hook = createTasksTodowriteDisablerHook({})
|
||||
const input = {
|
||||
tool: "TodoWrite",
|
||||
sessionID: "test-session",
|
||||
callID: "call-1",
|
||||
}
|
||||
const output = {
|
||||
args: {},
|
||||
}
|
||||
|
||||
// when / then
|
||||
await expect(
|
||||
hook["tool.execute.before"](input, output)
|
||||
).resolves.toBeUndefined()
|
||||
})
|
||||
|
||||
test("should not block TodoRead when flag is false", async () => {
|
||||
// given
|
||||
const hook = createTasksTodowriteDisablerHook({ experimental: { task_system: false } })
|
||||
const input = {
|
||||
tool: "TodoRead",
|
||||
sessionID: "test-session",
|
||||
callID: "call-1",
|
||||
}
|
||||
const output = {
|
||||
args: {},
|
||||
}
|
||||
|
||||
// when / then
|
||||
await expect(
|
||||
hook["tool.execute.before"](input, output)
|
||||
).resolves.toBeUndefined()
|
||||
})
|
||||
})
|
||||
|
||||
describe("error message content", () => {
|
||||
test("should include replacement message with task tools info", async () => {
|
||||
// given
|
||||
const hook = createTasksTodowriteDisablerHook({ experimental: { task_system: true } })
|
||||
const input = {
|
||||
tool: "TodoWrite",
|
||||
sessionID: "test-session",
|
||||
callID: "call-1",
|
||||
}
|
||||
const output = {
|
||||
args: {},
|
||||
}
|
||||
|
||||
// when / then
|
||||
await expect(
|
||||
hook["tool.execute.before"](input, output)
|
||||
).rejects.toThrow(/TaskCreate|TaskUpdate|TaskList|TaskGet/)
|
||||
})
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user