Problem:
Stale worker detection was reporting incorrect durations when sessions
were reused. Workers showed total session lifetime rather than time
since current task assignment.
Example:
- Session created 13 hours ago for issue #71
- Session reused 4 minutes ago for issue #106
- Status incorrectly showed: "DEV active on #106 (3.3h)"
- Should show: "DEV active on #106 (4m)"
Root Cause:
In recordWorkerState(), startTime was only set when spawning a new
session (sessionAction === 'spawn'). When reusing an existing session
(sessionAction === 'send'), the old startTime persisted, causing
stale worker detection to use total session age instead of task age.
Solution:
Always set startTime to current time when activating a worker,
regardless of whether we're spawning a new session or reusing one.
The startTime field now consistently represents "when did this worker
start THIS specific task" rather than "when was the session created".
Changes:
- lib/dispatch.ts: Move startTime assignment outside spawn-only block
- startTime now set unconditionally for both spawn and send actions
- Maintains backward compatibility with existing health checks
Impact:
- Stale worker detection now accurately reflects task duration
- Session reuse no longer causes false positive stale alerts
- Duration shown in status matches actual time on current task
Addresses issue #108
- Moved setup logic into dedicated files: agent.ts, config.ts, index.ts, workspace.ts.
- Introduced tool-helpers.ts for shared functions across tools, reducing boilerplate.
- Updated tools (status, task-comment, task-create, task-update, work-finish, work-start) to utilize new helper functions for workspace resolution and provider creation.
- Enhanced error handling and context detection in tools.
- Improved project resolution logic to streamline tool execution.
- Added new functionality for agent creation and configuration management in setup.
Remove hard-coded auto-chain dispatch (DEV done→QA, QA fail→DEV) and
replace with a general-purpose projectTick service that scans the queue
and fills free worker slots after every state transition.
- Create lib/services/tick.ts: consolidates shared helpers and core
projectTick() function from duplicated code in work-start/auto-pickup
- work_finish: replaces auto-chain block with projectTick call
- work_start: adds projectTick after dispatch to fill parallel slots
- auto_pickup: delegates per-project loop to projectTick
- Remove autoChain from Project type, migration code, and project-register
- Remove scheduling config dependency from work_finish
- Net -112 lines: simpler, self-healing pipeline
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Updated import paths for task management providers in task-comment, task-create, and task-update tools.
- Removed deprecated task-complete and task-pickup tools, replacing them with work-finish and work-start tools for improved task handling.
- Enhanced work-finish and work-start tools to streamline task completion and pickup processes, including context-aware detection and auto-scheduling features.
- Updated package.json to include build scripts and main entry point.
- Modified tsconfig.json to enable output directory, declaration files, and source maps for better TypeScript support.
Automatically includes the issue URL in the announcement when
task_create is called, eliminating the need for users to ask
'What's the URL?' after creating a task.
Changes:
- Enhanced announcement formatting with line breaks
- Always includes issue URL with 🔗 prefix
- Improved readability with structured format
Example output:
📋 Created #109: "Fix bug" (To Do)
🔗https://github.com/user/repo/issues/109
Ready for pickup when needed.
Example with description:
📋 Created #110: "Add feature" (Planning)
With detailed description.
🔗https://github.com/user/repo/issues/110
Picking up for DEV...
Addresses issue #109
Improvements to notification system for better traceability:
1. DEV Completion Notifications:
- Always include issue URL (📋 Issue: ...)
- Include PR/MR URL when available (🔗 PR: ...)
- Issue URL serves as fallback when PR/MR not found
- Both URLs shown when PR/MR exists for maximum traceability
2. QA Pass Notifications:
- Now include issue URL (📋 Issue: ...)
- Provides direct link to resolved issue
3. Tool Aliases:
- Added 'work_finish' as alias for 'task_complete'
- Added 'work_start' as alias for 'task_pickup'
- Added 'status' as alias for 'queue_status'
- Matches naming used in AGENTS.md documentation
Example DEV notification:
✅ DEV done #106 — Enhanced notification URLs
📋 Issue: https://github.com/user/repo/issues/106🔗 PR: https://github.com/user/repo/pull/107
Moved to QA queue.
Example QA notification:
🎉 QA PASS #106 — All tests passed
📋 Issue: https://github.com/user/repo/issues/106
Issue closed.
Addresses issue #106
Added comprehensive QA workflow documentation explaining:
- Required steps for QA reviews
- Mandatory task_comment before task_complete
- Comment templates for pass/fail scenarios
- Rationale for enforcement (audit trail, knowledge sharing, etc.)
- Best practices for QA documentation
This documentation supports the QA comment enforcement
introduced in role templates.
Related to issue #103
Adds automatic PR/MR URL detection and inclusion in DEV completion
announcements to provide better visibility into completed work.
Changes:
1. TaskManager interface:
- Added getMergedMRUrl() method to fetch PR/MR URL for an issue
2. GitHub/GitLab providers:
- Implemented getMergedMRUrl() to find most recent merged PR/MR
- Returns URL of PR/MR that references the issue number
3. task_complete tool:
- Added optional prUrl parameter
- Auto-detects PR/MR URL if not provided
- Includes PR URL in announcement with 🔗 prefix
- Format: 'PR: https://github.com/...'
4. Role templates (dev.md):
- Updated to instruct workers to include prUrl in task_complete
- Documents that prUrl is optional (auto-detected as fallback)
Example announcement:
✅ DEV done #101 — Added PR/MR URL to notifications
🔗 PR: https://github.com/user/repo/pull/102
. Moved to QA queue.
Addresses issue #101
Problem:
GitHub was showing confusing label transitions like:
- 'added To Do Doing and removed To Do'
- 'added To Test Testing Done and removed Doing To Test Testing'
This occurred when issues had multiple state labels simultaneously
(due to bugs, manual edits, or failed transitions).
Root Cause:
The old transitionLabel() only removed the 'from' label and added
the 'to' label. If other state labels existed on the issue, they
would remain, causing messy multi-label states.
Solution:
1. Fetch the current issue to inspect all labels
2. Find ALL state labels on the issue (not just 'from')
3. Remove ALL state labels in a single operation
4. Add only the new 'to' label
This ensures atomic, clean transitions that display on GitHub as
a single 'removed X, added Y' operation, even if the issue
previously had multiple state labels.
Changes:
- GitHubProvider.transitionLabel(): Remove all state labels before adding new one
- GitLabProvider.transitionLabel(): Same fix for GitLab consistency
Addresses issue #97
Adds test file with validation scenarios:
- Schema validation for required/optional params
- All 8 state labels are supported
- Same-state transitions handled gracefully
- Audit logging verification
Includes manual test scenarios for integration verification.
Addresses issue #71 acceptance criteria:
✅ Can transition any issue to any valid state
✅ Logs reason to audit trail
✅ Updates GitHub label (projects.json managed by session_health)
✅ Documented as orchestrator-only in AGENTS.md
- Deleted `helpers.ts`, `projects.test.ts`, and `scenarios.test.ts` as they are no longer needed.
- Updated `package.json` to remove the test script that referenced the deleted files.
- Add defensive verification in deactivateWorker to catch any accidental
session clearing bugs
- Enhance documentation in activateWorker, deactivateWorker, and
updateWorker to clearly explain session preservation behavior
- Add comprehensive example flow in activateWorker docs showing session
reuse across multiple tasks and tiers
- Add test suite for session persistence (projects.test.ts) to prevent
regression
- Add npm test script to run test suite
This ensures sessions persist per tier after task completion, enabling
session reuse across multiple tasks of the same tier for massive token
savings (~50K per reuse) and context preservation.
Fixes: Bug where sessions could theoretically be accidentally cleared
during worker state updates, though current code was already correct.
This adds defense-in-depth to make the invariant bulletproof.
- Expanded DEFAULT_DEV_INSTRUCTIONS with more detailed context and explicit
warning about not using 'Closes #X', 'Fixes #X', 'Resolves #X'
- Added 'Fixes issue #X' to the list of prohibited closing keywords
- Added new 'Worker Task Templates' section to AGENTS_MD_TEMPLATE with
explicit CRITICAL warning about closing keywords in PR/MR descriptions
- Updated workflow steps to reinforce proper issue referencing:
Use 'As described in issue #X' or 'Addresses issue #X' instead
This prevents GitHub from auto-closing issues when PRs merge, ensuring
DevClaw's task_complete validation and QA workflow are not bypassed.
As described in issue: #24
Closes#26
This PR adds two new DevClaw tools for better task lifecycle management:
- task_update: Change issue state programmatically without full pickup/complete flow
- task_comment: Add review comments or notes to issues with optional role attribution
- Added explicit warning to DEFAULT_DEV_INSTRUCTIONS
- Added warning to AGENTS_MD_TEMPLATE conventions section
- Workers instructed to use 'As described in issue #X' instead of 'Closes #X'
- Prevents GitHub/GitLab from auto-closing issues before QA validation
Adds defense-in-depth by explicitly calling activateWorker() in task_pickup.ts
after dispatchTask() returns. This ensures the worker state (active, issueId,
model, sessionKey, startTime) is properly set in projects.json even if
dispatchTask's internal state update encounters issues.
The redundant update:
- Sets active=true, issueId, and model for both spawn and reuse cases
- Sets sessionKey and startTime only on new spawns (not on session reuse)
- Provides fallback if race conditions or I/O errors affect dispatch.ts
Fixes#23
Adds defense-in-depth by explicitly calling activateWorker() in task_pickup.ts
after dispatchTask() returns. This ensures the worker state (active, issueId,
model, sessionKey, startTime) is properly set in projects.json even if
dispatchTask's internal state update encounters issues.
The redundant update:
- Sets active=true, issueId, and model for both spawn and reuse cases
- Sets sessionKey and startTime only on new spawns (not on session reuse)
- Provides fallback if race conditions or I/O errors affect dispatch.ts
Fixes#23
- Show plugin-level projectExecution setting in output
- Show project-level roleExecution for each project
- Sequential mode: single global task sequence across projects
- Parallel mode: per-project task tracks
- Proper handling of roleExecution within each project
- Priority ordering (To Improve > To Test > To Do)
- Visual distinction between active and upcoming tasks
Closes#21
When a worker session is successfully dispatched but activateWorker
fails to update projects.json, the error was being logged but not
re-thrown. This caused task_pickup to return success even though
the state wasn't updated, leading to task_complete failures later.
Now we re-throw the error after logging the warning, so the caller
knows the state update failed even though the session is running.
Fixes: #23