Skip to content

feat: v0.1 scaffold with task engine and agent loop#1

Open
mcj-coder wants to merge 44 commits into
mainfrom
feat/v0.1-scaffold
Open

feat: v0.1 scaffold with task engine and agent loop#1
mcj-coder wants to merge 44 commits into
mainfrom
feat/v0.1-scaffold

Conversation

@mcj-coder
Copy link
Copy Markdown
Contributor

Summary

  • Scaffold project with dev tooling (husky, lint-staged, prettier, shellcheck, shfmt, markdownlint)
  • Task engine (lib/tasks.js): list, filter by capabilities/deps/priority, claim, update status
  • Prompt builder (lib/prompt-builder.js): assemble agent prompts from task JSON + CLAUDE.md
  • Minimal TOML parser (lib/toml.js): parse config files without external deps
  • CLI entrypoint (bin/coordinator.sh): init, start, stop, status subcommands
  • Agent loop (bin/agent-loop.sh): per-agent competing consumer loop
  • Template files for .coordination/ scaffolding (config.toml, claude-md/*.md)

Architecture

  • Bash core + Node.js for task logic — zero production dependencies
  • Git worktrees for agent isolation (one per agent)
  • Coordination branch holds task JSON — never merged to main
  • Competing consumer via git push conflict (first push wins)
  • Dynamic role assignment — agents claim by capability + priority
  • Fresh context per task — one-shot claude -p invocations

Test plan

  • 21 tests passing (node --test) — tasks, prompt-builder, TOML parser
  • shellcheck clean on all bash scripts
  • Pre-commit hooks (lint-staged auto-fix) working
  • Pre-push hooks (full test suite + shellcheck) working
  • Manual test: coordinator init in a test project
  • Manual test: coordinator start with agents.toml configured
  • Manual test: coordinator stop --clean

🤖 Generated with Claude Code

mcj-coder and others added 30 commits February 9, 2026 12:17
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
… branch

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add .gitkeep to tasks/ on coordination branch (git doesn't track empty dirs)
- Check for TTY before prompting for Spec-Kit install (non-interactive fix)
- Handle missing coordination worktree in status command gracefully

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
markdownlint-cli2 uses .markdownlint-cli2.jsonc (not .markdownlintignore)
for file exclusions. Also fixes prettier trailing comma in .markdownlint.jsonc.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Runs unit tests, shellcheck, prettier, and markdownlint in one command.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- tests/e2e.sh: 36 automated tests covering init, start, status, stop
  with mocked wt.exe for CI-safe execution
- tests/smoke.sh: interactive test that opens real WT tabs for manual
  verification of agent launch and lifecycle
- npm run test:e2e / test:smoke / check

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Replaces basic lifecycle smoke test with full journey demo:
- Sets up bare repo as origin, clone as project
- Initializes coordinator, creates 4 tasks (test → implement → review → fix)
- Starts agents with mock AI script that produces real files
- Polls task progress with live status display
- Verifies hello.js and hello.test.js artifacts
- Demonstrates capability-based + priority-based task claiming
- Clean shutdown with verification

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1. wt.exe launches non-interactive bash — .bashrc not sourced, nvm/node
   unavailable. Fixed by using `bash --login` for agent tabs.
   Added node availability check in agent-loop.sh with clear error.

2. DONE_STATUSES missing 'complete' — agent-loop.sh sets tasks to
   'complete' but isBlocked() only recognized 'done'/'approved',
   so blocked tasks could never unblock. Added 'complete' to the set.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
bash --login doesn't help because .bashrc exits early for
non-interactive shells. Instead, agent-loop.sh now sources
~/.nvm/nvm.sh directly when node isn't in PATH.

Reverts the --login flag (ineffective) and replaces with
targeted nvm sourcing with clear error if node still missing.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implements parseTasksMarkdown() to convert Spec-Kit markdown format
to JSON task objects. Extracts task IDs, parallel markers [P], user
story labels [US#], and file paths from task descriptions.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Update file path regex to match both nested paths (src/file.py)
  and root-level files (README.md, package.json)
- Add comprehensive JSDoc with detailed type definitions and examples
- Add edge case tests: root-level files, undefined input, duplicate IDs
- Document that duplicate ID validation is caller's responsibility

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implements buildDependencyGraph() to automatically set blockedBy based
on file ownership. Tasks that touch files owned/touched by earlier
tasks are blocked until those earlier tasks complete.

Key features:
- Builds file ownership map from owns/touches arrays
- Only blocks on earlier tasks (lower task IDs)
- Handles multiple dependencies and complex chains
- Returns sorted blockedBy arrays for deterministic output

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Prevents TypeError crashes when tasks have missing owns or touches
fields by using defensive || [] checks when spreading arrays.

Added test case to verify graceful handling of:
- Missing touches field
- Missing owns field
- Missing both fields

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add cmd_plan function to coordinator.sh that:
- Checks for .coordination/ directory
- Accepts optional tasks.md path argument
- Auto-discovers specs/*/tasks.md if no arg given
- Switches to coordination branch
- Runs node lib/plan.js to convert tasks.md to JSON
- Commits generated task files
- Returns to original branch

Add E2E test for plan command that verifies:
- tasks.md is converted to JSON files
- Files are committed to coordination branch
- Task JSON has correct status field

Also fix specify init hanging in tests by adding --force flag.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add comprehensive implementation plan document
- Fix Spec-Kit init error handling (graceful failure)
- Improve shellcheck compliance (direct exit code checks)
- Update markdownlint ignores for generated/plan directories

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
mcj-coder and others added 14 commits February 9, 2026 16:24
Agent worktrees are on agent/* branches and don't have .coordination/
directory. The .coordination/claude-md/ files exist in the main repo
after 'coordinator init', so read from there instead.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
When coordinator is run from a feature branch, agents should base
their work on that branch, not main. Detect the current branch from
the main repo and use it as the base for agent worktrees.

Changes:
- Detect BASE_BRANCH from main repo on startup
- Use BASE_BRANCH instead of hardcoded 'main' in agent sync
- Pull from origin/$BASE_BRANCH instead of origin/main

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
The coordination worktree's parent directory is not a git repo.
Git worktrees have a .git file that points back to the main repo,
so run git rev-parse from within the worktree itself.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
When agents crash or are stopped mid-task, tasks remain in "claimed"
status and are never picked up again. This adds a reclaim mechanism
that runs on agent startup:

1. Finds all tasks with status="claimed" and claimedBy=this-agent
2. Resets them to status="pending" and claimedBy=null
3. Records the reclaim in task history
4. Cleans the agent worktree (git reset --hard + git clean -fd)

This ensures agents always start with a clean slate and no orphaned
tasks are left behind.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Previously used git rev-parse --show-toplevel which returns the
worktree directory itself, not the main repository. This caused
ENOENT errors when trying to read .coordination/claude-md files.

Now uses git rev-parse --git-common-dir to get the main repo's
.git directory, then navigates up one level to get the main repo path.

Tested: git rev-parse --git-common-dir returns main repo's .git even
from within a worktree, allowing us to reliably find the main repo.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Agent command aliases (like claude-zai) defined in user profile are
not available in WT tabs since they don't source .bashrc/.bash_profile.

This fix:
- Enables alias expansion with 'shopt -s expand_aliases'
- Sources .bash_profile, .bashrc, and .profile if they exist
- Makes user-defined aliases available to agent command execution

Without this, agents fail with "command not found" when using aliases.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
User's shell profile may be in .zshrc/.zprofile instead of bash files.
Now sources both bash and zsh profile files to support both shells.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
When sourcing .zshrc in bash, oh-my-zsh references ZSH_VERSION
which causes "unbound variable" errors with set -u.

Solution:
- Temporarily disable unbound variable check (set +u)
- Suppress errors with 2>/dev/null and || true
- Re-enable check after sourcing (set -u)

This allows sourcing zsh configs in bash without breaking the script.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Failed tasks are now automatically retried up to MAX_RETRIES (default 3).
When a task fails, it increments the retry counter and resets to "pending"
if retries < MAX_RETRIES. Once the limit is reached, the task stays "failed".

Also adds reset-failed command to manually reset all failed tasks to pending
and clear their retry counters.

Configuration:
- Set max-retries in .coordination/config.toml [settings] section
- Defaults to 3 if not specified

CLI commands:
- node lib/tasks.js update <file> failed <agent> <maxRetries>
- node lib/tasks.js reset-failed <tasksDir>

This prevents tasks from being permanently stuck in failed state due to
transient errors like network issues or command not found errors.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Adds reset-failed as a first-class coordinator command:
- coordinator reset-failed
- Documented in help output
- Automatically handles coordination branch operations
- Much simpler than the manual node script approach

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Adds safety check to coordinator reset-failed:
- Counts tasks with status='claimed' (agents running)
- Exits with error if any claimed tasks exist
- Instructs user to run 'coordinator stop' first
- Prevents task confusion when resetting while agents run

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Previously required 'coordinator start' to have been run (confusing).
Now works like 'coordinator plan' - temporarily checks out coordination
branch, resets tasks, and returns to original branch.

Can be run before or after 'coordinator start'.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Two critical fixes for agent startup races:

1. Git index.lock conflicts when multiple agents start simultaneously
   - Add random 0-3 second delay before reclaim
   - Retry push with exponential backoff (3 attempts)
   - Pull between retries to resolve conflicts

2. Agent worktree disappearing mid-execution
   - Check worktree exists before cd
   - Exit with clear error message
   - Happens when 'coordinator stop' runs during agent work

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant