You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The dotbot MCP server (core/mcp/dotbot-mcp.ps1) resolves $global:DotbotProjectRoot by walking up from $PSScriptRoot until it finds something at .git. The Test-Path check matches both a .git directory and the .git gitfile that lives at the root of every git worktree. So when the MCP server is launched from a per-task worktree (the standard dotbot convention) it sets DotbotProjectRoot to the worktree root rather than the main repo. Every MCP tool reads that variable to locate .bot/workspace/tasks/, so every agent-driven task-state transition (task_mark_needs_input, task_mark_done, task_mark_skipped, task_mark_analysed, task_answer_question, etc.) writes to the worktree. Complete-TaskWorktree then runs git checkout -- .bot/workspace/tasks/ on the worktree before the squash-merge, silently discarding every one of those writes.
Net effect: any change the agent makes to task state from within a worktree is invisible to the parent. PR #352's loop-escalation fix (move failed execution to needs-input) is no-op'd in worktree runs. So is mark_done, so is everything else.
Repro
A live SlashOps dogfood run on 2026-04-27 (process proc-8a41a3, started 13:07Z, runner stopped by the operator around 14:01Z when the task hit a privacy-scan blocker). All paths and timestamps below come from .bot/.control/activity.jsonl and .bot/.control/processes/proc-8a41a3.activity.jsonl of that run.
Activity log timeline for task Product Documents (id 37dcd1a5-9c6f-4d42-b01c-cee834589f12):
13:30:31 mcp__dotbot__task_mark_needs_input (called from worktree's Claude session)
13:31:03 Squash-merged to main: Product Documents
13:31:03 Task completed (analyse+execute): Product Documents
State on disk after the merge:
.bot/workspace/tasks/in-progress/product-documents-37dcd1a5.json
status: in-progress
updated_at: 2026-04-27T13:11:27Z ← original execute-phase timestamp, never updated
pending_question: null
completed_at: null
The merge commit (004ec1257e712a0562eb80fbe56f367cf61370cb, "feat: Product Documents [task:37dcd1a5]") only touches .gemini/settings.json. The task file is bit-identical to the prior 9ba6fff chore: save autonomous task state commit. The mark_needs_input call at 13:30:31 left no trace in the parent.
Root cause (verified by source read)
Three steps, all in framework code:
1. core/mcp/dotbot-mcp.ps1:30-39
# Auto-detect project root by walking up from script location to find .git folder$script:ProjectRoot=$null$currentPath=$PSScriptRootwhile ($currentPath) {
if (Test-Path (Join-Path$currentPath".git")) {
$script:ProjectRoot=$currentPathbreak
}
$parent=Split-Path$currentPath-Parent
if ($parent-eq$currentPath) { break }
$currentPath=$parent
}
Walks up looking for .git. Test-Path (no -PathType Container) succeeds on both directories and files. A worktree's root contains a .gitfile of the form gitdir: /path/to/main/.git/worktrees/<id>. So the walk stops at the worktree root and $script:ProjectRoot resolves to the worktree, not the main repo. $global:DotbotProjectRoot = $script:ProjectRoot (line 47) makes that visible to every dot-sourced tool.
The tool resolves modules — and ultimately the task tree — relative to that variable. Set-TaskState writes the new file under Join-Path $global:DotbotProjectRoot ".bot/workspace/tasks/needs-input/..." and removes the old one from tasks/in-progress/. Both operations happen in the worktree's tasks tree.
Same pattern in every other MCP tool that touches task state — task-mark-done, task-mark-skipped, task-mark-analysed, task-mark-in-progress, task-mark-todo, task-answer-question, task-approve-split, etc. They all dot-source TaskStore.psm1 from $global:DotbotProjectRoot. (Suggest a sweep: grep -l 'global:DotbotProjectRoot' core/mcp/tools/.)
(line 717-718 — wipes whatever the parent had). The parent then merges, and a backup-restore at line 768-775 puts back the snapshot of the parent's task tree taken at line 705-714 (just before the git checkout).
The design clearly assumes the parent repo holds the canonical task state and the worktree's task changes are noise — hence the unconditional reset of .bot/workspace/tasks/ in the worktree before merge. The MCP path (steps 1 and 2 above) violates that assumption by writing the canonical state into the worktree.
Blast radius
PR Fix init prompt paths, unapproved verbs, and analysis loop #352's loop-escalation fix (move failed execution to needs-input so the runner stops looping) is silently no-op'd in worktree runs. The repro above is exactly that mechanism failing — the wedged file in in-progress/ has no pending_question, no updated updated_at.
Every other agent-driven task transition is affected the same way: mark_done, mark_skipped, answer_question, approve_split, etc. The fact that things sometimes appear to work is likely because a separate runtime path in the parent (e.g. Invoke-WorkflowProcess.ps1 calling Move-Task or similar in-process) re-derives state from worktree commits or invokes the same MCP tools again later — that path needs investigation.
Affects every dotbot install that uses worktree isolation, not just SlashOps. Any project running start-from-prompt (or any other workflow that uses worktrees) would see the same wedge.
Suggested fix
Resolve DotbotProjectRoot to the main repo root regardless of whether the launcher's cwd is a worktree. The cleanest signal git already provides:
# In dotbot-mcp.ps1, replacing lines 28-44 (approximate)$gitCommonDir= git -C $PSScriptRoot rev-parse --git-common-dir 2>$nullif ($LASTEXITCODE-eq0-and$gitCommonDir) {
# rev-parse returns '.git' relative to cwd in non-worktree, or an absolute# path to the main .git/ in a worktree. Resolve and walk up to its parent.$resolved= (Resolve-Path-LiteralPath (Join-Path$PSScriptRoot$gitCommonDir) -ErrorAction SilentlyContinue)
if ($resolved) {
$script:ProjectRoot=Split-Path$resolved.Path-Parent
}
}
# Fallback: keep the existing walk-up for the no-git case (e.g. tests)if (-not$script:ProjectRoot) {
$currentPath=$PSScriptRootwhile ($currentPath) {
if (Test-Path (Join-Path$currentPath".git")) {
$script:ProjectRoot=$currentPathbreak
}
$parent=Split-Path$currentPath-Parent
if ($parent-eq$currentPath) { break }
$currentPath=$parent
}
}
git rev-parse --git-common-dir:
In the main repo: returns .git (relative).
In a worktree: returns the absolute path to the main .git/ directory.
Either way, Split-Path -Parent of the resolved path gives the main repo's toplevel.
Regression test
Dotbot tests are imperative scripts under tests/ using Test-Helpers.psm1 (the project does not use Pester and is not opting in yet). Add a test fixture that:
Creates a temp project with New-TestProject, lays down core/ via the existing test helper that mirrors dotbot init.
Seeds a task in .bot/workspace/tasks/in-progress/.
Creates a worktree for the task (use git worktree add directly; no need for the runtime layer).
From the worktree directory, dot-sources or invokes task-mark-needs-input's Invoke-TaskMarkNeedsInput.
Asserts the parent's.bot/workspace/tasks/needs-input/<task>.json exists with the right status and pending_question, and that the parent's.bot/workspace/tasks/in-progress/<task>.json no longer exists.
Best home is probably tests/Test-TaskActions.ps1 (already exercises Set-TaskState and friends) with a new --- MCP project root resolves to main repo from worktree --- section. A standalone Test-MCPProjectRoot.ps1 is also fine if the section gets long.
Audit
Sweep all MCP tools to confirm none of them legitimately need worktree-local state:
For any that do (e.g. dev-only tools tied to the worktree's checkout), give them an explicit $WorktreeRoot parameter rather than reading the global.
Secondary findings
These five came out of the same log mining session. Sized for triage; the PR author can decide whether to bundle into the same PR or split. None block the primary fix.
Stale runner lock from operator-killed runner — low / hardening
.bot/.control/launch-task-runner.lock contains the dead PID 45620 after the operator stopped the runner during the privacy-scan blocker. dotbot init -Force later in the same session also kills any active runner. Both are operator-induced rather than graceful exits, so this isn't a production-path bug — but it makes "ctrl-c then start again" require manual lock cleanup.
Suggested hardening: when Set-ProcessLock (or whatever holds the lock during launch) sees an existing lock, check liveness of the recorded PID via Get-Process -Id and reclaim if dead.
Privacy scan blocks task_mark_done on framework-owned files — medium
Activity log at 2026-04-27T13:25:14Z shows task_mark_done blocked with 47 violations: ~32 in agent-editable files (docs/*.md, .bot/workspace/product/briefing/*.md, CLAUDE.md), 8 in .bot/core/mcp/modules/PathSanitizer.psm1 (framework — off-limits per the project CLAUDE.md convention), and 7 elsewhere in the project. The agent fixed the 32 it could touch, then the second task_mark_done blocked at 13:29:06Z listed only the 8 PathSanitizer entries — exactly the files the agent isn't allowed to edit. PR #352 fixes the specific PathSanitizer comments, but the verification step still gives a single pass/fail with no signal that the remaining violations are framework state outside the project's ability to resolve.
Suggested refinement: when 00-privacy-scan.ps1 runs from task_mark_done, partition the result into project_violations (block) and framework_violations (warn + suggest filing a separate dotbot issue) so the project-level task can proceed.
Privacy scan double-counts overlapping pattern matches on the same line — cosmetic
Same 13:25:14Z report shows context-memory.md:287 flagged for both Connection string with password and Secret/password value, and context-memory.md:288 flagged for Private key. Each matching pattern appends a separate violation in core/hooks/verify/00-privacy-scan.ps1 around line 118-133. So one suspicious line counts as two or three.
Suggested: dedupe by (file, line), surface multiple pattern names as a list in the single violation entry. Inflated counts are confusing without changing actual security behaviour.
dotbot init -Force post-install auto-commit fails silently — medium
Reproduced in this session at 2026-04-27T16:00 local:
init -Force leaves the user with a dirty .bot/ tree they have to commit by hand. The actual git error is not surfaced — could be the in-flight pre-commit hook tripping on something, could be no-op, could be a pre-existing dirty tree.
Suggested investigation: read scripts/init-project.ps1 around the post-install commit, capture and surface the actual git stderr. If the cause is "nothing to commit", downgrade to a debug message instead of a warning.
Three todo/ tasks didn't run — unconfirmed / watch-list
None have depends_on. The debug log shows [task-get-next] No eligible tasks found polling every ~5s from 13:31 → 14:01. The user manually stopped the runner around the privacy-scan blocker, so the polling window may simply be "human-input gating" rather than a picker bug. Re-reading core/mcp/tools/task-get-next/script.ps1 and TaskIndexCache.psm1's Get-NextTask showed no obvious filter that would exclude these tasks.
Status: keep this as a watch-list item. After the primary fix lands, re-run the dogfood end-to-end without operator interruption; if the three todo/ tasks still don't pick up, file as a separate bug. Do not claim this is fixed by the primary patch unless the post-fix dogfood confirms it.
Out of scope
These showed up in the logs but are not dotbot framework bugs:
Glob head_limit validation error during the analysis phase (Claude tool layer rejecting an unsupported parameter).
PowerShell ParserError from a Bash -Command containing backtick-escaped regex examples (agent constructed a syntactically invalid one-liner).
Edit: File has not been read yet errors (Claude agent retrying without parsing the prior failure).
Long thinking pauses (30s, 83s) in the per-process activity log are model latency, not framework.
Context saturation at 100.2% on turn 87 is a Claude window limit; chunking briefing inputs is a bigger architectural change than this issue.
Notes for the PR author
One bundled umbrella per PR is the convention; this issue is intentionally self-contained so the PR can Closes #<this> and not need cross-references.
Finding 2 is unconfirmed — the post-fix dogfood is the only way to tell. Don't claim it's fixed without that signal.
The user prefers no Pester. Stick to imperative Test-*.ps1 scripts via Test-Helpers.psm1 for any new test coverage.
The fix proposal in this issue is correct. Pinning the line numbers and inlining the audit list so the PR session opens the right files at the right line.
core/mcp/dotbot-mcp.ps1
Walk-up loop at lines 31-39.
$script:ProjectRoot = $currentPath at line 33.
Fatal-exit guard if the walk fails at lines 41-44.
$global:DotbotProjectRoot = $script:ProjectRoot at line 47.
Worktree-side restore: git -C $worktreePath checkout -- .bot/workspace/tasks at line 674.
Parent-side wipe: git -C $ProjectRoot checkout -- .bot/workspace/tasks/ at line 717.
Audit: scripts under core/mcp/tools/ that read $global:DotbotProjectRoot
37 files match Grep -r 'global:DotbotProjectRoot' core/mcp/tools/. Of these, 33 are production script.ps1 files and 4 are test.ps1 files. None look like they legitimately need a worktree-local view, so the fix applies cleanly across the whole set without per-tool overrides.
TL;DR
The dotbot MCP server (
core/mcp/dotbot-mcp.ps1) resolves$global:DotbotProjectRootby walking up from$PSScriptRootuntil it finds something at.git. TheTest-Pathcheck matches both a.gitdirectory and the.gitgitfile that lives at the root of every git worktree. So when the MCP server is launched from a per-task worktree (the standard dotbot convention) it setsDotbotProjectRootto the worktree root rather than the main repo. Every MCP tool reads that variable to locate.bot/workspace/tasks/, so every agent-driven task-state transition (task_mark_needs_input,task_mark_done,task_mark_skipped,task_mark_analysed,task_answer_question, etc.) writes to the worktree.Complete-TaskWorktreethen runsgit checkout -- .bot/workspace/tasks/on the worktree before the squash-merge, silently discarding every one of those writes.Net effect: any change the agent makes to task state from within a worktree is invisible to the parent. PR #352's loop-escalation fix (move failed execution to
needs-input) is no-op'd in worktree runs. So ismark_done, so is everything else.Repro
A live SlashOps dogfood run on
2026-04-27(processproc-8a41a3, started 13:07Z, runner stopped by the operator around 14:01Z when the task hit a privacy-scan blocker). All paths and timestamps below come from.bot/.control/activity.jsonland.bot/.control/processes/proc-8a41a3.activity.jsonlof that run.Activity log timeline for task
Product Documents(id37dcd1a5-9c6f-4d42-b01c-cee834589f12):State on disk after the merge:
The merge commit (
004ec1257e712a0562eb80fbe56f367cf61370cb, "feat: Product Documents [task:37dcd1a5]") only touches.gemini/settings.json. The task file is bit-identical to the prior9ba6fff chore: save autonomous task statecommit. Themark_needs_inputcall at 13:30:31 left no trace in the parent.Root cause (verified by source read)
Three steps, all in framework code:
1.
core/mcp/dotbot-mcp.ps1:30-39Walks up looking for
.git.Test-Path(no-PathType Container) succeeds on both directories and files. A worktree's root contains a.gitfile of the formgitdir: /path/to/main/.git/worktrees/<id>. So the walk stops at the worktree root and$script:ProjectRootresolves to the worktree, not the main repo.$global:DotbotProjectRoot = $script:ProjectRoot(line 47) makes that visible to every dot-sourced tool.2.
core/mcp/tools/task-mark-needs-input/script.ps1:2-3The tool resolves modules — and ultimately the task tree — relative to that variable.
Set-TaskStatewrites the new file underJoin-Path $global:DotbotProjectRoot ".bot/workspace/tasks/needs-input/..."and removes the old one fromtasks/in-progress/. Both operations happen in the worktree's tasks tree.Same pattern in every other MCP tool that touches task state —
task-mark-done,task-mark-skipped,task-mark-analysed,task-mark-in-progress,task-mark-todo,task-answer-question,task-approve-split, etc. They all dot-sourceTaskStore.psm1from$global:DotbotProjectRoot. (Suggest a sweep:grep -l 'global:DotbotProjectRoot' core/mcp/tools/.)3.
core/runtime/modules/WorktreeManager.psm1:670-718Complete-TaskWorktreeruns in the parent repo at the end of a task. Before any merge it does:(line 674-675 — restores from worktree's HEAD), and later, against the parent:
(line 717-718 — wipes whatever the parent had). The parent then merges, and a backup-restore at line 768-775 puts back the snapshot of the parent's task tree taken at line 705-714 (just before the
git checkout).The design clearly assumes the parent repo holds the canonical task state and the worktree's task changes are noise — hence the unconditional reset of
.bot/workspace/tasks/in the worktree before merge. The MCP path (steps 1 and 2 above) violates that assumption by writing the canonical state into the worktree.Blast radius
needs-inputso the runner stops looping) is silently no-op'd in worktree runs. The repro above is exactly that mechanism failing — the wedged file inin-progress/has nopending_question, no updatedupdated_at.mark_done,mark_skipped,answer_question,approve_split, etc. The fact that things sometimes appear to work is likely because a separate runtime path in the parent (e.g.Invoke-WorkflowProcess.ps1calling Move-Task or similar in-process) re-derives state from worktree commits or invokes the same MCP tools again later — that path needs investigation.start-from-prompt(or any other workflow that uses worktrees) would see the same wedge.Suggested fix
Resolve
DotbotProjectRootto the main repo root regardless of whether the launcher's cwd is a worktree. The cleanest signal git already provides:git rev-parse --git-common-dir:.git(relative)..git/directory.Either way,
Split-Path -Parentof the resolved path gives the main repo's toplevel.Regression test
Dotbot tests are imperative scripts under
tests/usingTest-Helpers.psm1(the project does not use Pester and is not opting in yet). Add a test fixture that:New-TestProject, lays downcore/via the existing test helper that mirrorsdotbot init..bot/workspace/tasks/in-progress/.git worktree adddirectly; no need for the runtime layer).task-mark-needs-input'sInvoke-TaskMarkNeedsInput..bot/workspace/tasks/needs-input/<task>.jsonexists with the rightstatusandpending_question, and that the parent's.bot/workspace/tasks/in-progress/<task>.jsonno longer exists.Best home is probably
tests/Test-TaskActions.ps1(already exercisesSet-TaskStateand friends) with a new--- MCP project root resolves to main repo from worktree ---section. A standaloneTest-MCPProjectRoot.ps1is also fine if the section gets long.Audit
Sweep all MCP tools to confirm none of them legitimately need worktree-local state:
For any that do (e.g. dev-only tools tied to the worktree's checkout), give them an explicit
$WorktreeRootparameter rather than reading the global.Secondary findings
These five came out of the same log mining session. Sized for triage; the PR author can decide whether to bundle into the same PR or split. None block the primary fix.
Stale runner lock from operator-killed runner —
low / hardening.bot/.control/launch-task-runner.lockcontains the dead PID45620after the operator stopped the runner during the privacy-scan blocker.dotbot init -Forcelater in the same session also kills any active runner. Both are operator-induced rather than graceful exits, so this isn't a production-path bug — but it makes "ctrl-c then start again" require manual lock cleanup.Suggested hardening: when
Set-ProcessLock(or whatever holds the lock during launch) sees an existing lock, check liveness of the recorded PID viaGet-Process -Idand reclaim if dead.Privacy scan blocks
task_mark_doneon framework-owned files —mediumActivity log at
2026-04-27T13:25:14Zshowstask_mark_done blockedwith 47 violations: ~32 in agent-editable files (docs/*.md,.bot/workspace/product/briefing/*.md,CLAUDE.md), 8 in.bot/core/mcp/modules/PathSanitizer.psm1(framework — off-limits per the projectCLAUDE.mdconvention), and 7 elsewhere in the project. The agent fixed the 32 it could touch, then the secondtask_mark_done blockedat13:29:06Zlisted only the 8 PathSanitizer entries — exactly the files the agent isn't allowed to edit. PR #352 fixes the specific PathSanitizer comments, but the verification step still gives a single pass/fail with no signal that the remaining violations are framework state outside the project's ability to resolve.Suggested refinement: when
00-privacy-scan.ps1runs fromtask_mark_done, partition the result intoproject_violations(block) andframework_violations(warn + suggest filing a separate dotbot issue) so the project-level task can proceed.Privacy scan double-counts overlapping pattern matches on the same line —
cosmeticSame
13:25:14Zreport showscontext-memory.md:287flagged for bothConnection string with passwordandSecret/password value, andcontext-memory.md:288flagged forPrivate key. Each matching pattern appends a separate violation incore/hooks/verify/00-privacy-scan.ps1around line 118-133. So one suspicious line counts as two or three.Suggested: dedupe by
(file, line), surface multiple pattern names as a list in the single violation entry. Inflated counts are confusing without changing actual security behaviour.dotbot init -Forcepost-install auto-commit fails silently —mediumReproduced in this session at
2026-04-27T16:00local:init -Forceleaves the user with a dirty.bot/tree they have to commit by hand. The actual git error is not surfaced — could be the in-flight pre-commit hook tripping on something, could be no-op, could be a pre-existing dirty tree.Suggested investigation: read
scripts/init-project.ps1around the post-install commit, capture and surface the actual git stderr. If the cause is "nothing to commit", downgrade to a debug message instead of a warning.Three
todo/tasks didn't run —unconfirmed / watch-listNone have
depends_on. The debug log shows[task-get-next] No eligible tasks foundpolling every ~5s from 13:31 → 14:01. The user manually stopped the runner around the privacy-scan blocker, so the polling window may simply be "human-input gating" rather than a picker bug. Re-readingcore/mcp/tools/task-get-next/script.ps1andTaskIndexCache.psm1'sGet-NextTaskshowed no obvious filter that would exclude these tasks.Status: keep this as a watch-list item. After the primary fix lands, re-run the dogfood end-to-end without operator interruption; if the three
todo/tasks still don't pick up, file as a separate bug. Do not claim this is fixed by the primary patch unless the post-fix dogfood confirms it.Out of scope
These showed up in the logs but are not dotbot framework bugs:
head_limitvalidation error during the analysis phase (Claude tool layer rejecting an unsupported parameter).ParserErrorfrom a Bash-Commandcontaining backtick-escaped regex examples (agent constructed a syntactically invalid one-liner).Edit: File has not been read yeterrors (Claude agent retrying without parsing the prior failure).Notes for the PR author
Closes #<this>and not need cross-references.Test-*.ps1scripts viaTest-Helpers.psm1for any new test coverage.fix/init-prompt-paths-verbs-and-loop) is in CI as of issue creation. The primary fix here is independent of Fix init prompt paths, unapproved verbs, and analysis loop #352 — both branches can land in either order.Verified against current source (2026-04-28)
The fix proposal in this issue is correct. Pinning the line numbers and inlining the audit list so the PR session opens the right files at the right line.
core/mcp/dotbot-mcp.ps1$script:ProjectRoot = $currentPathat line 33.$global:DotbotProjectRoot = $script:ProjectRootat line 47.Invoke-ListTools(the function that returns the tool list to the MCP client) at lines 164-204 (referenced from Pre-load MCP tool schemas at server startup so prompts do not need ToolSearch #366 — orthogonal but worth knowing).core/runtime/modules/WorktreeManager.psm1git -C $worktreePath checkout -- .bot/workspace/tasksat line 674.git -C $ProjectRoot checkout -- .bot/workspace/tasks/at line 717.Audit: scripts under
core/mcp/tools/that read$global:DotbotProjectRoot37 files match
Grep -r 'global:DotbotProjectRoot' core/mcp/tools/. Of these, 33 are productionscript.ps1files and 4 aretest.ps1files. None look like they legitimately need a worktree-local view, so the fix applies cleanly across the whole set without per-tool overrides.Production scripts (33)
core/mcp/tools/decision-create/script.ps1core/mcp/tools/decision-get/script.ps1core/mcp/tools/decision-list/script.ps1core/mcp/tools/decision-mark-accepted/script.ps1core/mcp/tools/decision-mark-deprecated/script.ps1core/mcp/tools/decision-mark-superseded/script.ps1core/mcp/tools/decision-update/script.ps1core/mcp/tools/dev-start/script.ps1core/mcp/tools/dev-stop/script.ps1core/mcp/tools/plan-create/script.ps1core/mcp/tools/plan-get/script.ps1core/mcp/tools/plan-update/script.ps1core/mcp/tools/session-get-state/script.ps1core/mcp/tools/session-get-stats/script.ps1core/mcp/tools/session-increment-completed/script.ps1core/mcp/tools/session-initialize/script.ps1core/mcp/tools/session-update/script.ps1core/mcp/tools/steering-heartbeat/script.ps1core/mcp/tools/task-answer-question/script.ps1core/mcp/tools/task-approve-split/script.ps1core/mcp/tools/task-create-bulk/script.ps1core/mcp/tools/task-create/script.ps1core/mcp/tools/task-get-context/script.ps1core/mcp/tools/task-get-next/script.ps1core/mcp/tools/task-get-stats/script.ps1core/mcp/tools/task-list/script.ps1core/mcp/tools/task-mark-analysed/script.ps1core/mcp/tools/task-mark-analysing/script.ps1core/mcp/tools/task-mark-done/script.ps1core/mcp/tools/task-mark-in-progress/script.ps1core/mcp/tools/task-mark-needs-input/script.ps1core/mcp/tools/task-mark-skipped/script.ps1core/mcp/tools/task-mark-todo/script.ps1Test scripts (4)
core/mcp/tools/steering-heartbeat/test.ps1core/mcp/tools/task-answer-question/test.ps1core/mcp/tools/task-mark-done/test.ps1core/mcp/tools/task-mark-skipped/test.ps1