agentsys 5.8.3 → 5.8.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "agentsys",
3
3
  "description": "19 specialized plugins for AI workflow automation - task orchestration, PR workflow, slop detection, code review, drift detection, enhancement analysis, documentation sync, unified static analysis, perf investigations, topic research, agent config linting, cross-tool AI consultation, structured AI debate, workflow pattern learning, codebase onboarding, and contributor guidance",
4
- "version": "5.8.3",
4
+ "version": "5.8.4",
5
5
  "owner": {
6
6
  "name": "Avi Fenesh",
7
7
  "url": "https://github.com/avifenesh"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentsys",
3
- "version": "5.8.3",
3
+ "version": "5.8.4",
4
4
  "description": "Professional-grade slash commands for Claude Code with cross-platform support",
5
5
  "keywords": [
6
6
  "workflow",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "worktree-manager",
3
3
  "description": "Create and manage git worktrees for isolated task development. Use this agent after task selection to create a clean working environment.",
4
- "prompt": "# Worktree Manager Agent\n\nYou manage git worktrees to provide isolated development environments for each task.\nThis prevents work-in-progress from polluting the main working directory.\n\n## Phase 1: Pre-flight Checks\n\nVerify git is available and check current status:\n\n```bash\n# Verify git\ngit --version || { echo \"ERROR: git not available\"; exit 1; }\n\n# Check if already in a worktree\nCURRENT_DIR=$(pwd)\nMAIN_WORKTREE=$(git worktree list --porcelain | head -1 | cut -d' ' -f2)\n\nif [ \"$CURRENT_DIR\" != \"$MAIN_WORKTREE\" ]; then\n echo \"WARNING: Already in a worktree at $CURRENT_DIR\"\n echo \"ALREADY_IN_WORKTREE=true\"\nfi\n\n# Get current branch\nORIGINAL_BRANCH=$(git branch --show-current)\necho \"ORIGINAL_BRANCH=$ORIGINAL_BRANCH\"\n\n# Check for uncommitted changes\nif [ -n \"$(git status --porcelain)\" ]; then\n echo \"HAS_UNCOMMITTED_CHANGES=true\"\n git status --short\nfi\n```\n\n## Phase 2: Generate Worktree Path\n\nCreate a slug from the task title and generate paths:\n\n```javascript\nfunction generateWorktreePath(task) {\n // Create slug from task title\n const slug = task.title\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-|-$/g, '')\n .substring(0, 40); // Limit slug length for filesystem compatibility\n\n // Include task ID for uniqueness\n const fullSlug = task.id ? `${slug}-${task.id}` : slug;\n\n return {\n slug: fullSlug,\n branchName: `feature/${fullSlug}`,\n worktreePath: `../worktrees/${fullSlug}`\n };\n}\n```\n\n## Phase 3: Check for Existing Worktree\n\nCheck if worktree already exists (for resume scenarios):\n\n```bash\nWORKTREE_PATH=\"../worktrees/${SLUG}\"\nBRANCH_NAME=\"feature/${SLUG}\"\n\n# Check if worktree exists\nif git worktree list | grep -q \"$WORKTREE_PATH\"; then\n echo \"WORKTREE_EXISTS=true\"\n echo \"Worktree already exists at $WORKTREE_PATH\"\nfi\n\n# Check if branch exists\nif git branch --list \"$BRANCH_NAME\" | grep -q \"$BRANCH_NAME\"; then\n echo \"BRANCH_EXISTS=true\"\nfi\n\n# Check remote branch\nif git ls-remote --heads origin \"$BRANCH_NAME\" | grep -q \"$BRANCH_NAME\"; then\n echo \"REMOTE_BRANCH_EXISTS=true\"\nfi\n```\n\n## Phase 4: Handle Uncommitted Changes\n\nIf there are uncommitted changes, handle them:\n\n```bash\nif [ \"$HAS_UNCOMMITTED_CHANGES\" = \"true\" ]; then\n echo \"Stashing uncommitted changes...\"\n git stash push -m \"Auto-stash before worktree creation for task ${TASK_ID}\"\n STASH_CREATED=\"true\"\nfi\n```\n\n## Phase 5: Create Worktree\n\nCreate the worktree with a new feature branch:\n\n```bash\n# Ensure worktrees directory exists\nmkdir -p ../worktrees\n\n# Create worktree with new branch\nif [ \"$WORKTREE_EXISTS\" = \"true\" ]; then\n echo \"Using existing worktree at $WORKTREE_PATH\"\nelse\n if [ \"$BRANCH_EXISTS\" = \"true\" ]; then\n # Branch exists, create worktree from it\n git worktree add \"$WORKTREE_PATH\" \"$BRANCH_NAME\"\n elif [ \"$REMOTE_BRANCH_EXISTS\" = \"true\" ]; then\n # Remote branch exists, track it\n git worktree add --track -b \"$BRANCH_NAME\" \"$WORKTREE_PATH\" \"origin/$BRANCH_NAME\"\n else\n # Create new branch from main\n git worktree add -b \"$BRANCH_NAME\" \"$WORKTREE_PATH\"\n fi\n\n if [ $? -eq 0 ]; then\n echo \"[OK] Created worktree at $WORKTREE_PATH\"\n echo \"[OK] Created branch $BRANCH_NAME\"\n else\n echo \"ERROR: Failed to create worktree\"\n exit 1\n fi\nfi\n```\n\n## Phase 6: Claim Task in Registry\n\nAdd task to `${STATE_DIR}/tasks.json` to prevent other workflows from claiming it:\n\n```javascript\nconst fs = require('fs');\nconst stateDir = process.env.AI_STATE_DIR || '.claude';\nif (!fs.existsSync(stateDir)) fs.mkdirSync(stateDir, { recursive: true });\n\nlet registry = fs.existsSync(`${stateDir}/tasks.json`)\n ? JSON.parse(fs.readFileSync(`${stateDir}/tasks.json`))\n : { version: '1.0.0', tasks: [] };\n\nconst entry = {\n id: task.id, source: task.source, title: task.title,\n branch, worktreePath: path.resolve(worktreePath),\n claimedAt: new Date().toISOString(), claimedBy: state.workflow.id,\n status: 'claimed', lastActivityAt: new Date().toISOString()\n};\n\nconst idx = registry.tasks.findIndex(t => t.id === task.id);\nif (idx >= 0) registry.tasks[idx] = entry;\nelse registry.tasks.push(entry);\n\nfs.writeFileSync(`${stateDir}/tasks.json`, JSON.stringify(registry, null, 2));\n```\n\n## Phase 7: Anchor PWD to Worktree\n\n**Important**: Change to the worktree directory to anchor all subsequent operations.\n\n**Note**: The `cd` command within a single Bash call does not persist across separate Bash tool invocations. The orchestrator must handle PWD anchoring at the workflow level by passing absolute paths or updating the working directory context between agent invocations.\n\n```bash\ncd \"$WORKTREE_PATH\"\n\n# Verify we're in the right place\nCURRENT_BRANCH=$(git branch --show-current)\nif [ \"$CURRENT_BRANCH\" != \"$BRANCH_NAME\" ]; then\n echo \"ERROR: Not on expected branch. Expected $BRANCH_NAME, got $CURRENT_BRANCH\"\n exit 1\nfi\n\necho \"[OK] Working directory anchored to: $(pwd)\"\necho \"[OK] On branch: $CURRENT_BRANCH\"\n# Note: Orchestrator must use this path for subsequent operations\necho \"WORKTREE_ABSOLUTE_PATH=$(pwd)\"\n```\n\n## Phase 8: Create Worktree Status File\n\nCreate `${STATE_DIR}/workflow-status.json` with task, workflow, git info, and resume state.\n\nKey fields: `task` (id, source, title), `workflow` (id, status, currentPhase), `git` (branch, baseSha, mainRepoPath), `resume` (canResume, resumeFromStep).\n\n## Phase 9: Update Workflow State\n\nCall `workflowState.updateState()` with git info (originalBranch, workingBranch, worktreePath, baseSha, isWorktree: true), then `workflowState.completePhase()`.\n\n## Phase 10: Output Summary\n\nReport: branch name, worktree path, base commit. Confirm PWD anchored to worktree.\n\n## Cleanup Responsibilities\n\n| Component | Creates | Cleans Up |\n|-----------|---------|-----------|\n| worktree-manager | worktrees, tasks.json entries, workflow-status.json | Nothing |\n| ship | - | worktrees (after merge), tasks.json entries |\n| --abort | - | worktrees, tasks.json entries |\n\n**Agents MUST NOT**: clean up worktrees, remove tasks from registry, or delete branches.\n\n## Cleanup Reference (for ship and --abort)\n\n```bash\ncleanup_worktree() {\n cd \"$ORIGINAL_DIR\"\n git worktree remove \"$WORKTREE_PATH\" --force 2>/dev/null\n git worktree prune\n [ -f \"${STATE_DIR}/tasks.json\" ] && node -e \"\n const fs = require('fs');\n const r = JSON.parse(fs.readFileSync('${STATE_DIR}/tasks.json'));\n r.tasks = r.tasks.filter(t => t.id !== '$TASK_ID');\n fs.writeFileSync('${STATE_DIR}/tasks.json', JSON.stringify(r, null, 2));\n \"\n}\n```\n\n## Error Handling\n\nOn failure: remove partial worktree, prune refs, update state with `failPhase()`, exit 1.\n\n## Success Criteria\n\n- **Task claimed in main repo's tasks.json** (prevents collisions)\n- Worktree created at `../worktrees/{task-slug}`\n- Feature branch created: `feature/{task-slug}`\n- **workflow-status.json created in worktree** (for resume capability)\n- PWD anchored to worktree directory\n- Workflow state updated with git info\n- Phase advanced to exploration\n\n## Constraints\n\n- Only create worktrees - never delete them (cleanup is handled by ship or --abort)\n- Do not remove tasks from tasks.json registry\n- Do not delete branches\n- Do not modify files in the main repository after switching to worktree\n- Always claim tasks in registry before creating worktree\n- Always create workflow-status.json in the new worktree\n- Do not proceed if uncommitted changes exist without stashing first\n\n## Model Choice: Haiku\n\nThis agent uses **haiku** because:\n- Executes scripted git commands (deterministic)\n- No complex reasoning about code or architecture\n- Simple string manipulation for slugs/paths\n- Fast execution for setup operations",
4
+ "prompt": "# Worktree Manager Agent\n\nYou manage git worktrees to provide isolated development environments for each task.\nThis prevents work-in-progress from polluting the main working directory.\n\n## Phase 1: Pre-flight Checks\n\nVerify git is available and check current status:\n\n```bash\n# Verify git\ngit --version || { echo \"ERROR: git not available\"; exit 1; }\n\n# Check if already in a worktree\nCURRENT_DIR=$(pwd)\nMAIN_WORKTREE=$(git worktree list --porcelain | head -1 | cut -d' ' -f2)\n\nif [ \"$CURRENT_DIR\" != \"$MAIN_WORKTREE\" ]; then\n echo \"WARNING: Already in a worktree at $CURRENT_DIR\"\n echo \"ALREADY_IN_WORKTREE=true\"\nfi\n\n# Get current branch\nORIGINAL_BRANCH=$(git branch --show-current)\necho \"ORIGINAL_BRANCH=$ORIGINAL_BRANCH\"\n\n# Check for uncommitted changes\nif [ -n \"$(git status --porcelain)\" ]; then\n echo \"HAS_UNCOMMITTED_CHANGES=true\"\n git status --short\nfi\n```\n\n## Phase 2: Generate Worktree Path\n\nCreate a slug from the task title and generate paths:\n\n```javascript\nfunction generateWorktreePath(task) {\n // Create slug from task title\n const slug = task.title\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-|-$/g, '')\n .substring(0, 40); // Limit slug length for filesystem compatibility\n\n // Include task ID for uniqueness\n const fullSlug = task.id ? `${slug}-${task.id}` : slug;\n\n return {\n slug: fullSlug,\n branchName: `feature/${fullSlug}`,\n worktreePath: `../worktrees/${fullSlug}`\n };\n}\n```\n\n## Phase 3: Check for Existing Worktree\n\nCheck if worktree already exists (for resume scenarios):\n\n```bash\nWORKTREE_PATH=\"../worktrees/${SLUG}\"\nBRANCH_NAME=\"feature/${SLUG}\"\n\n# Check if worktree exists\nif git worktree list | grep -q \"$WORKTREE_PATH\"; then\n echo \"WORKTREE_EXISTS=true\"\n echo \"Worktree already exists at $WORKTREE_PATH\"\nfi\n\n# Check if branch exists\nif git branch --list \"$BRANCH_NAME\" | grep -q \"$BRANCH_NAME\"; then\n echo \"BRANCH_EXISTS=true\"\nfi\n\n# Check remote branch\nif git ls-remote --heads origin \"$BRANCH_NAME\" | grep -q \"$BRANCH_NAME\"; then\n echo \"REMOTE_BRANCH_EXISTS=true\"\nfi\n```\n\n## Phase 4: Handle Uncommitted Changes\n\nIf there are uncommitted changes, handle them:\n\n```bash\nif [ \"$HAS_UNCOMMITTED_CHANGES\" = \"true\" ]; then\n echo \"Stashing uncommitted changes...\"\n git stash push -m \"Auto-stash before worktree creation for task ${TASK_ID}\"\n STASH_CREATED=\"true\"\nfi\n```\n\n## Phase 5: Create Worktree\n\nCreate the worktree with a new feature branch:\n\n```bash\n# Ensure worktrees directory exists\nmkdir -p ../worktrees\n\n# Create worktree with new branch\nif [ \"$WORKTREE_EXISTS\" = \"true\" ]; then\n echo \"Using existing worktree at $WORKTREE_PATH\"\nelse\n if [ \"$BRANCH_EXISTS\" = \"true\" ]; then\n # Branch exists, create worktree from it\n git worktree add \"$WORKTREE_PATH\" \"$BRANCH_NAME\"\n elif [ \"$REMOTE_BRANCH_EXISTS\" = \"true\" ]; then\n # Remote branch exists, track it\n git worktree add --track -b \"$BRANCH_NAME\" \"$WORKTREE_PATH\" \"origin/$BRANCH_NAME\"\n else\n # Create new branch from main\n git worktree add -b \"$BRANCH_NAME\" \"$WORKTREE_PATH\"\n fi\n\n if [ $? -eq 0 ]; then\n echo \"[OK] Created worktree at $WORKTREE_PATH\"\n echo \"[OK] Created branch $BRANCH_NAME\"\n else\n echo \"ERROR: Failed to create worktree\"\n exit 1\n fi\nfi\n```\n\n## Phase 6: Claim Task in Registry\n\nAdd task to `${STATE_DIR}/tasks.json` to prevent other workflows from claiming it.\n\nUse the library function — do NOT write raw `fs.writeFileSync` here (it bypasses atomic write-rename and has no optimistic locking):\n\n```javascript\nconst path = require('path');\nconst workflowState = require('../../lib/state/workflow-state');\n\n// PROJECT_PATH is the main repo root (not the worktree); passed in from the orchestrator\n// or resolved from the worktree git config: git -C worktreePath rev-parse --show-toplevel\nconst projectPath = process.env.PROJECT_PATH || process.cwd();\n\nconst ok = workflowState.claimTask({\n id: task.id,\n source: task.source,\n title: task.title,\n branch,\n worktreePath: path.resolve(worktreePath),\n claimedBy: state.workflow.id\n}, projectPath);\n\nif (!ok) {\n // claimTask already logged the reason (concurrent write conflict after max retries).\n // Fail hard so the orchestrator surfaces this to the user instead of continuing\n // with an unclaimed task that could collide with another workflow.\n throw new Error(`[ERROR] claimTask failed for task ${task.id} in ${projectPath} see log above for details.`);\n}\n```\n\n## Phase 7: Anchor PWD to Worktree\n\n**Important**: Change to the worktree directory to anchor all subsequent operations.\n\n**Note**: The `cd` command within a single Bash call does not persist across separate Bash tool invocations. The orchestrator must handle PWD anchoring at the workflow level by passing absolute paths or updating the working directory context between agent invocations.\n\n```bash\ncd \"$WORKTREE_PATH\"\n\n# Verify we're in the right place\nCURRENT_BRANCH=$(git branch --show-current)\nif [ \"$CURRENT_BRANCH\" != \"$BRANCH_NAME\" ]; then\n echo \"ERROR: Not on expected branch. Expected $BRANCH_NAME, got $CURRENT_BRANCH\"\n exit 1\nfi\n\necho \"[OK] Working directory anchored to: $(pwd)\"\necho \"[OK] On branch: $CURRENT_BRANCH\"\n# Note: Orchestrator must use this path for subsequent operations\necho \"WORKTREE_ABSOLUTE_PATH=$(pwd)\"\n```\n\n## Phase 8: Create Worktree Status File\n\nCreate `${STATE_DIR}/workflow-status.json` with task, workflow, git info, and resume state.\n\nKey fields: `task` (id, source, title), `workflow` (id, status, currentPhase), `git` (branch, baseSha, mainRepoPath), `resume` (canResume, resumeFromStep).\n\n## Phase 9: Update Workflow State\n\nCall `workflowState.updateState()` with git info (originalBranch, workingBranch, worktreePath, baseSha, isWorktree: true), then `workflowState.completePhase()`.\n\n## Phase 10: Output Summary\n\nReport: branch name, worktree path, base commit. Confirm PWD anchored to worktree.\n\n## Cleanup Responsibilities\n\n| Component | Creates | Cleans Up |\n|-----------|---------|-----------|\n| worktree-manager | worktrees, tasks.json entries, workflow-status.json | Nothing |\n| ship | - | worktrees (after merge), tasks.json entries |\n| --abort | - | worktrees, tasks.json entries |\n\n**Agents MUST NOT**: clean up worktrees, remove tasks from registry, or delete branches.\n\n## Cleanup Reference (for ship and --abort)\n\nUse the library function — do NOT write raw `fs.writeFileSync` here (it bypasses atomic write-rename and has no optimistic locking):\n\n```bash\ncleanup_worktree() {\n cd \"$ORIGINAL_DIR\"\n git worktree remove \"$WORKTREE_PATH\" --force 2>/dev/null\n git worktree prune\n # Release task claim atomically via library (retry-safe, version-checked).\n # PROJECT_PATH = main repo root (not the worktree). Use $ORIGINAL_DIR if available,\n # or resolve from git: git -C \"$ORIGINAL_DIR\" rev-parse --show-toplevel\n MAIN_REPO_PATH=\"${PROJECT_PATH:-$ORIGINAL_DIR}\"\n node -e \"\n const wf = require('./lib/state/workflow-state');\n const ok = wf.releaseTask('$TASK_ID', process.env.MAIN_REPO_PATH || process.cwd());\n if (!ok) {\n process.stderr.write('[ERROR] releaseTask failed for task $TASK_ID after max retries. Registry entry may still be marked claimed. Retry: node -e \\'require(\\\\\"./lib/state/workflow-state\\\\\").releaseTask(\\\\\"\\'$TASK_ID\\'\\\\\")\\' \\n');\n process.exit(1);\n }\n \" MAIN_REPO_PATH=\"$MAIN_REPO_PATH\"\n}\n```\n\n## Error Handling\n\nOn failure: remove partial worktree, prune refs, update state with `failPhase()`, exit 1.\n\n## Success Criteria\n\n- **Task claimed in main repo's tasks.json** (prevents collisions)\n- Worktree created at `../worktrees/{task-slug}`\n- Feature branch created: `feature/{task-slug}`\n- **workflow-status.json created in worktree** (for resume capability)\n- PWD anchored to worktree directory\n- Workflow state updated with git info\n- Phase advanced to exploration\n\n## Constraints\n\n- Only create worktrees - never delete them (cleanup is handled by ship or --abort)\n- Do not remove tasks from tasks.json registry\n- Do not delete branches\n- Do not modify files in the main repository after switching to worktree\n- Always claim tasks in registry before creating worktree\n- Always create workflow-status.json in the new worktree\n- Do not proceed if uncommitted changes exist without stashing first\n\n## Model Choice: Haiku\n\nThis agent uses **haiku** because:\n- Executes scripted git commands (deterministic)\n- No complex reasoning about code or architecture\n- Simple string manipulation for slugs/paths\n- Fast execution for setup operations",
5
5
  "tools": [
6
6
  "read",
7
7
  "write",
@@ -25,9 +25,9 @@ const workflowState = require('../../lib/state/workflow-state.js');
25
25
  const state = workflowState.readState();
26
26
  const policy = state.policy;
27
27
 
28
- // Load claimed tasks from registry
29
- const claimedTasks = workflowState.readTasks().tasks || [];
30
- const claimedIds = new Set(claimedTasks.map(t => t.id));
28
+ // Load claimed task IDs from registry (tasks[] contains worktree-manager claims)
29
+ const tasksRegistry = workflowState.readTasks();
30
+ const claimedIds = new Set(tasksRegistry.tasks.map(t => t.id));
31
31
  ```
32
32
 
33
33
  ### Phase 2: Fetch Tasks by Source
package/CHANGELOG.md CHANGED
@@ -9,6 +9,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
9
9
 
10
10
  ## [Unreleased]
11
11
 
12
+ ## [5.8.4] - 2026-04-20
13
+
14
+ ### Fixed
15
+ - **tasks.json atomic optimistic locking** (#331) - Concurrent `/next-task` and `/ship` runs could silently lose claims or leave stale registry entries due to unguarded read-modify-write on `tasks.json`. Fix uses `_version` + per-write `_writerId` optimistic locking (mirrors existing `flow.json` pattern): write atomically via rename, re-read and verify both fields match before declaring success, retry up to 5× with jitter on mismatch.
16
+ - **tasks.json schema unification** - `worktree-manager` wrote `{ version, tasks[] }` while `workflow-state.js` read `{ active }`, causing claim exclusion in `discover-tasks` to always return an empty set. Unified schema is `{ active, tasks[], _version, _writerId }` with on-read normalization of both legacy formats — no migration needed.
17
+ - **Silent corruption risk** - `readTasks()` now throws on corrupted JSON instead of returning a safe default, preventing `updateTasks` from silently overwriting potentially recoverable data.
18
+ - **Agent prompt raw file writes** - `worktree-manager` Phase 6 and Cleanup Reference replaced inline `fs.writeFileSync` with `workflowState.claimTask()` / `workflowState.releaseTask()` library calls that are atomic and retry-safe.
19
+
20
+ ### Added
21
+ - `updateTasks(mutatorFn)` - optimistic-lock loop for `tasks.json` mutations (mirrors `updateFlow`)
22
+ - `claimTask(entry, projectPath)` - atomic upsert into `tasks[]` registry for worktree-manager
23
+ - `releaseTask(taskId, projectPath)` - atomic removal from `tasks[]` registry for ship/abort; idempotent
24
+
12
25
  ## [5.8.3] - 2026-04-11
13
26
 
14
27
  ### Fixed
package/README.md CHANGED
@@ -19,8 +19,8 @@
19
19
  </p>
20
20
 
21
21
  <p align="center">
22
- <b>19 plugins · 47 agents · 40 skills (across all repos) · 30k lines of lib code · 3,583 tests · 5 platforms</b><br>
23
- <em>Plugins distributed as standalone repos under <a href="https://github.com/agent-sh">agent-sh</a> org agentsys is the marketplace &amp; installer</em>
22
+ <b>19 plugins · 49 agents · 41 skills (across all repos) · 30k lines of lib code · 3,507 tests · 5 platforms</b><br>
23
+ <em>Plugins distributed as standalone repos under <a href="https://github.com/agent-sh">agent-sh</a> org - agentsys is the marketplace &amp; installer</em>
24
24
  </p>
25
25
 
26
26
  <p align="center">
@@ -38,14 +38,14 @@
38
38
 
39
39
  ---
40
40
 
41
- AI models can write code. That's not the hard part anymore. The hard part is everything around it task selection, branch management, code review, artifact cleanup, CI, PR comments, deployment. **AgentSys is the runtime that orchestrates agents to handle all of it** structured pipelines, gated phases, specialized agents, and persistent state that survives session boundaries.
41
+ AI models can write code. That's not the hard part anymore. The hard part is everything around it - task selection, branch management, code review, artifact cleanup, CI, PR comments, deployment. **AgentSys is the runtime that orchestrates agents to handle all of it** - structured pipelines, gated phases, specialized agents, and persistent state that survives session boundaries.
42
42
 
43
43
  ---
44
- > Building custom skills, agents, hooks, or MCP tools? [agnix](https://github.com/agent-sh/agnix) is the CLI + LSP linter that catches config errors before they fail silently - real-time IDE validation, auto suggestions, auto-fix, and 385 rules for Claude Code, Codex, OpenCode, Cursor, Kiro, Copilot, Gemini CLI, Cline, Windsurf, Roo Code, Amp, and more.
44
+ > Building custom skills, agents, hooks, or MCP tools? [agnix](https://github.com/agent-sh/agnix) is the CLI + LSP linter that catches config errors before they fail silently - real-time IDE validation, auto suggestions, auto-fix, and 399 rules for Claude Code, Codex, OpenCode, Cursor, Kiro, Copilot, Gemini CLI, Cline, Windsurf, Roo Code, Amp, and more.
45
45
 
46
46
  ## What This Is
47
47
 
48
- An agent orchestration system 19 plugins, 47 agents, and 40 skills that compose into structured pipelines for software development. Each plugin lives in its own standalone repo under the [agent-sh](https://github.com/agent-sh) org. agentsys is the marketplace and installer that ties them together.
48
+ An agent orchestration system - 19 plugins, 49 agents (39 file-based + 10 role-based specialists in audit-project), and 41 skills that compose into structured pipelines for software development. Each plugin lives in its own standalone repo under the [agent-sh](https://github.com/agent-sh) org. agentsys is the marketplace and installer that ties them together.
49
49
 
50
50
  Each agent has a single responsibility, a specific model assignment, and defined inputs/outputs. Pipelines enforce phase gates so agents can't skip steps. State persists across sessions so work survives interruptions.
51
51
 
@@ -57,8 +57,8 @@ The system runs on Claude Code, OpenCode, Codex CLI, Cursor, and Kiro. Install v
57
57
 
58
58
  **Code does code work. AI does AI work.**
59
59
 
60
- - **Detection**: regex, AST analysis, static analysisfast, deterministic, no tokens wasted
61
- - **Judgment**: LLM calls for synthesis, planning, reviewwhere reasoning matters
60
+ - **Detection**: regex, AST analysis, static analysis - fast, deterministic, no tokens wasted
61
+ - **Judgment**: LLM calls for synthesis, planning, review - where reasoning matters
62
62
  - **Result**: 77% fewer tokens for [/drift-detect](#drift-detect) vs multi-agent approaches, certainty-graded findings throughout
63
63
 
64
64
  **Certainty levels exist because not all findings are equal:**
@@ -118,7 +118,7 @@ The investment shifts from model spend to pipeline design. Better prompts, riche
118
118
  | [`/next-task`](#next-task) | Task workflow: discovery, implementation, PR, merge |
119
119
  | [`/prepare-delivery`](#prepare-delivery) | Pre-ship quality gates: deslop, review, validation, docs sync |
120
120
  | [`/gate-and-ship`](#gate-and-ship) | Quality gates then ship (/prepare-delivery + /ship) |
121
- | [`/agnix`](#agnix) | Lint agent configurations (385 rules) |
121
+ | [`/agnix`](#agnix) | Lint agent configurations (399 rules) |
122
122
  | [`/ship`](#ship) | PR creation, CI monitoring, merge |
123
123
  | [`/deslop`](#deslop) | Clean AI slop patterns |
124
124
  | [`/perf`](#perf) | Performance investigation with baselines and profiling |
@@ -142,7 +142,7 @@ Each command works standalone. Together, they compose into end-to-end pipelines.
142
142
 
143
143
  ## Skills
144
144
 
145
- 40 skills included across the plugins:
145
+ 41 skills included across the plugins:
146
146
 
147
147
  | Category | Skills |
148
148
  |----------|--------|
@@ -157,6 +157,7 @@ Each command works standalone. Together, they compose into end-to-end pipelines.
157
157
  | **Web** | `web-auth`, `web-browse` |
158
158
  | **Release** | `release` |
159
159
  | **Analysis** | `drift-analysis`, `repo-intel` |
160
+ | **Linting** | `agnix` |
160
161
 
161
162
  **External skill plugins** (standalone repos, installed separately):
162
163
 
@@ -175,7 +176,7 @@ Skills are the reusable implementation units. Agents invoke skills; commands orc
175
176
  | [The Approach](#the-approach) | Why it's built this way |
176
177
  | [Benchmarks](#benchmarks) | Sonnet + agentsys vs raw Opus |
177
178
  | [Commands](#commands) | All 20 commands overview |
178
- | [Skills](#skills) | 40 skills across plugins |
179
+ | [Skills](#skills) | 41 skills across plugins |
179
180
  | [Skill-Only Plugins](#skill-only-plugins) | glide-mq and other non-command plugins |
180
181
  | [Command Details](#command-details) | Deep dive into each command |
181
182
  | [How Commands Work Together](#how-commands-work-together) | Standalone vs integrated |
@@ -328,7 +329,7 @@ agnix catches these issues before they cause problems.
328
329
  | **Best Practices** | Tool restrictions, model selection, trigger phrase quality |
329
330
  | **Cross-Platform** | Compatibility across Claude Code, Codex, OpenCode, Cursor, Kiro, Copilot, Gemini CLI, Cline, Windsurf, Roo Code, Amp, and more |
330
331
 
331
- **385 validation rules** (102 auto-fixable) derived from:
332
+ **399 validation rules** (126 auto-fixable) derived from:
332
333
  - Official tool specifications (Claude Code, Codex CLI, OpenCode, Cursor, Kiro, GitHub Copilot, Gemini CLI, Cline, Windsurf, Roo Code, Amp, and more)
333
334
  - Research papers on agent reliability and prompt injection
334
335
  - Real-world testing across 500+ repositories
@@ -442,7 +443,7 @@ If something can't be fixed, the workflow replies explaining why and resolves th
442
443
 
443
444
  ### /deslop
444
445
 
445
- **Purpose:** Finds AI slopdebug statements, placeholder text, verbose comments, TODOsand removes it.
446
+ **Purpose:** Finds AI slop - debug statements, placeholder text, verbose comments, TODOs - and removes it.
446
447
 
447
448
  **How detection works:**
448
449
 
@@ -613,13 +614,14 @@ Findings are collected and categorized by severity (critical/high/medium/low). A
613
614
 
614
615
  **Purpose:** Analyzes your prompts, plugins, agents, docs, hooks, and skills for improvement opportunities.
615
616
 
616
- **Seven analyzers run in parallel:**
617
+ **Eight analyzers run in parallel:**
617
618
 
618
619
  | Analyzer | What it checks |
619
620
  |----------|----------------|
620
621
  | plugin-enhancer | Plugin structure, MCP tool definitions, security patterns |
621
622
  | agent-enhancer | Agent frontmatter, prompt quality |
622
623
  | claudemd-enhancer | CLAUDE.md/AGENTS.md structure, token efficiency |
624
+ | cross-file-enhancer | Cross-file consistency (tools vs frontmatter, duplicate rules, conflicts) |
623
625
  | docs-enhancer | Documentation readability, RAG optimization |
624
626
  | prompt-enhancer | Prompt engineering patterns, clarity, examples |
625
627
  | hooks-enhancer | Hook frontmatter, structure, safety |
@@ -656,7 +658,7 @@ Findings are collected and categorized by severity (critical/high/medium/low). A
656
658
  - AST symbol mapping: exports, functions, classes, imports
657
659
  - Project metadata and health metrics
658
660
 
659
- Output is cached at `{state-dir}/repo-intel.json` and `{state-dir}/repo-map.json`.
661
+ Output is cached at `{state-dir}/repo-intel.json` (external repo-intel plugin) and `{state-dir}/repo-map.json` (agentsys internal repo-map library). `{state-dir}` is `.claude/`, `.opencode/`, or `.codex/` depending on your platform.
660
662
 
661
663
  **Why it matters:**
662
664
 
@@ -678,7 +680,7 @@ Backed by [agent-analyzer](https://github.com/agent-sh/agent-analyzer) Rust bina
678
680
 
679
681
  ### /sync-docs
680
682
 
681
- **Purpose:** Sync documentation with actual code changesfind outdated refs, update CHANGELOG, flag stale examples.
683
+ **Purpose:** Sync documentation with actual code changes - find outdated refs, update CHANGELOG, flag stale examples.
682
684
 
683
685
  **The problem it solves:**
684
686
 
@@ -958,7 +960,7 @@ No per-turn overhead - it reads transcripts that Claude Code already saves.
958
960
  **What happens when you run it:**
959
961
 
960
962
  1. **Collect** (68ms median) - Pure JavaScript scans manifest, structure, README, CI, git info. Normal depth adds CLAUDE.md/AGENTS.md and repo-intel. No LLM tokens.
961
- 2. **Synthesize** - Opus agent produces a structured overview: tech stack, key files, active areas, conventions
963
+ 2. **Synthesize** - Sonnet agent produces a structured overview: tech stack, key files, active areas, conventions
962
964
  3. **Guide** - Interactive Q&A: ask about specific files, areas, or patterns
963
965
 
964
966
  **74% fewer tokens** than manual onboarding. Validated on 100 repos across JS/TS, Rust, Go, Python, C/C++, Java, and Deno.
@@ -981,7 +983,7 @@ No per-turn overhead - it reads transcripts that Claude Code already saves.
981
983
  /onboard --depth=deep # Include AST data
982
984
  ```
983
985
 
984
- **Agent:** onboard-agent (opus model)
986
+ **Agent:** onboard-agent (sonnet model)
985
987
 
986
988
  [Full documentation →](https://github.com/agent-sh/onboard)
987
989
 
@@ -994,7 +996,7 @@ No per-turn overhead - it reads transcripts that Claude Code already saves.
994
996
  **What happens when you run it:**
995
997
 
996
998
  1. **Collect** - Gathers project data + contributor signals (test gaps, doc drift, bugspots, good-first areas, open issues). Validated on 100 repos.
997
- 2. **Match** - Opus agent asks about developer background and matches skills to project needs
999
+ 2. **Match** - Sonnet agent asks about developer background and matches skills to project needs
998
1000
  3. **Guide** - For each recommendation: reads code, explains what needs doing, gives a concrete first step
999
1001
 
1000
1002
  **Matching:**
@@ -1015,7 +1017,7 @@ No per-turn overhead - it reads transcripts that Claude Code already saves.
1015
1017
  /can-i-help --depth=deep # Include AST data
1016
1018
  ```
1017
1019
 
1018
- **Agent:** can-i-help-agent (opus model)
1020
+ **Agent:** can-i-help-agent (sonnet model)
1019
1021
 
1020
1022
  [Full documentation →](https://github.com/agent-sh/can-i-help)
1021
1023
 
@@ -1092,7 +1094,7 @@ Same principle as good code: single responsibility. The exploration-agent explor
1092
1094
 
1093
1095
  **2. Pipeline with gates, not a monolith**
1094
1096
 
1095
- Same principle as DevOps. Each step must pass before the next begins. Can't push before review. Can't merge before CI passes. Hooks enforce thisagents literally cannot skip phases.
1097
+ Same principle as DevOps. Each step must pass before the next begins. Can't push before review. Can't merge before CI passes. Hooks enforce this - agents literally cannot skip phases.
1096
1098
 
1097
1099
  **3. Tools do tool work, agents do agent work**
1098
1100
 
@@ -1235,7 +1237,7 @@ The system is built on research, not guesswork.
1235
1237
  - Instruction following reliability
1236
1238
 
1237
1239
  **Testing:**
1238
- - 3,583 tests passing
1240
+ - 3,507 tests passing
1239
1241
  - Drift-detect validated on 1,000+ repositories
1240
1242
  - E2E workflow testing across all commands
1241
1243
  - Cross-platform validation (Claude Code, OpenCode, Codex CLI, Cursor, Kiro)
@@ -117,62 +117,248 @@ function getTasksPath(projectPath = process.cwd()) {
117
117
  }
118
118
 
119
119
  /**
120
- * Read tasks.json from main project
121
- * Returns { active: null } if file doesn't exist or is corrupted
122
- * Logs critical error on corruption to prevent silent data loss
120
+ * Read tasks.json from main project.
121
+ *
122
+ * Unified schema (v2):
123
+ * { active: null|Object, tasks: [], _version: number }
124
+ *
125
+ * - active: single active workflow entry (set by createFlow / cleared by completeWorkflow)
126
+ * - tasks: worktree claim registry (set by worktree-manager / cleared by ship or --abort)
127
+ * - _version: monotonic counter for optimistic locking (managed by writeTasks)
128
+ * - _writerId: per-write unique token used by updateTasks to detect concurrent wins
129
+ *
130
+ * Legacy formats are normalized on read — no migration script needed.
131
+ * Throws on corruption so callers can decide whether to abort or recover,
132
+ * rather than silently overwriting potentially recoverable data.
133
+ *
134
+ * @param {string} projectPath
135
+ * @returns {{ active: null|Object, tasks: Array, _version: number, _writerId?: string }}
136
+ * @throws {Error} If tasks.json exists but cannot be parsed
123
137
  */
124
138
  function readTasks(projectPath = process.cwd()) {
125
139
  const tasksPath = getTasksPath(projectPath);
126
140
  if (!fs.existsSync(tasksPath)) {
127
- return { active: null };
141
+ return { active: null, tasks: [], _version: 0 };
128
142
  }
143
+ const raw = fs.readFileSync(tasksPath, 'utf8');
144
+ let data;
129
145
  try {
130
- const data = JSON.parse(fs.readFileSync(tasksPath, 'utf8'));
131
- // Normalize legacy format that may not have 'active' field
132
- if (!Object.prototype.hasOwnProperty.call(data, 'active')) {
133
- return { active: null };
134
- }
135
- return data;
146
+ data = JSON.parse(raw);
136
147
  } catch (e) {
137
- console.error(`[CRITICAL] Corrupted tasks.json at ${tasksPath}: ${e.message}`);
138
- return { active: null };
148
+ throw new Error(`[CRITICAL] Corrupted tasks.json at ${tasksPath}: ${e.message}. File must be repaired or deleted manually before writes are allowed.`);
139
149
  }
150
+ // Normalize: ensure every field exists (handles legacy { active } and legacy { version, tasks[] })
151
+ return {
152
+ active: Object.prototype.hasOwnProperty.call(data, 'active') ? data.active : null,
153
+ tasks: Array.isArray(data.tasks) ? data.tasks : [],
154
+ _version: typeof data._version === 'number' ? data._version : 0,
155
+ _writerId: typeof data._writerId === 'string' ? data._writerId : undefined
156
+ };
140
157
  }
141
158
 
142
159
  /**
143
- * Write tasks.json to main project
160
+ * Write tasks.json atomically.
161
+ * Increments _version and stamps a unique _writerId per write.
162
+ *
163
+ * Both fields are used by updateTasks to verify it was the winning writer:
164
+ * if two processes both read _version N, both write _version N+1 (last
165
+ * renameSync wins), the loser re-reads and finds a _writerId that does not
166
+ * match its own — it knows it lost and retries.
167
+ *
168
+ * @returns {string} The _writerId stamped into this write
144
169
  */
145
170
  function writeTasks(tasks, projectPath = process.cwd()) {
146
171
  ensureStateDir(projectPath);
172
+ const copy = structuredClone(tasks);
173
+ copy._version = (copy._version || 0) + 1;
174
+ copy._writerId = crypto.randomBytes(8).toString('hex');
147
175
  const tasksPath = getTasksPath(projectPath);
148
- writeJsonAtomic(tasksPath, tasks);
149
- return true;
176
+ writeJsonAtomic(tasksPath, copy);
177
+ return copy._writerId;
150
178
  }
151
179
 
152
180
  /**
153
- * Set active task in main project
181
+ * Apply a mutation to tasks.json with optimistic locking.
182
+ *
183
+ * Uses _version + _writerId to detect wins in concurrent-writer races:
184
+ * 1. Read current state, snapshot _version
185
+ * 2. Apply mutatorFn(clone) → new state; skip write if state unchanged
186
+ * 3. Stamp a unique writerId, write atomically (increments _version)
187
+ * 4. Re-read: if _version === initialVersion + 1 AND _writerId matches → we won
188
+ * 5. Otherwise another writer raced us → back off with jitter, retry
189
+ *
190
+ * @param {function(Object): Object} mutatorFn - Pure function that receives a
191
+ * deep clone of current tasks state and returns the desired new state.
192
+ * Must not have side effects; may be called multiple times on retry.
193
+ * @param {string} projectPath
194
+ * @returns {boolean} true on success, false after MAX_RETRIES exhausted or on corruption
195
+ */
196
+ function updateTasks(mutatorFn, projectPath = process.cwd()) {
197
+ const MAX_RETRIES = 5;
198
+
199
+ let current;
200
+ try {
201
+ current = readTasks(projectPath);
202
+ } catch (e) {
203
+ console.error(`[ERROR] updateTasks: cannot read tasks.json — ${e.message}`);
204
+ return false;
205
+ }
206
+
207
+ for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {
208
+ const initialVersion = current._version || 0;
209
+
210
+ let updated;
211
+ try {
212
+ updated = mutatorFn(structuredClone(current));
213
+ } catch (e) {
214
+ console.error(`[ERROR] updateTasks: mutatorFn threw on attempt ${attempt + 1}: ${e.message}`);
215
+ return false;
216
+ }
217
+
218
+ // Skip write if mutatorFn made no changes — avoids spurious version bumps
219
+ if (JSON.stringify(updated) === JSON.stringify(current)) {
220
+ return true;
221
+ }
222
+
223
+ // Carry forward the pre-write version so writeTasks increments it by exactly 1
224
+ updated._version = initialVersion;
225
+
226
+ const writerId = writeTasks(updated, projectPath);
227
+
228
+ // Verify we won: version must be exactly initialVersion + 1 AND writerId must match ours.
229
+ // If another process also wrote _version: initialVersion + 1, only one writerId survives.
230
+ let afterWrite;
231
+ try {
232
+ afterWrite = readTasks(projectPath);
233
+ } catch (e) {
234
+ console.error(`[ERROR] updateTasks: tasks.json corrupted after write on attempt ${attempt + 1}: ${e.message}`);
235
+ return false;
236
+ }
237
+
238
+ if (afterWrite._version === initialVersion + 1 && afterWrite._writerId === writerId) {
239
+ return true;
240
+ }
241
+
242
+ // Lost the race — retry from the current on-disk state
243
+ if (attempt < MAX_RETRIES - 1) {
244
+ const delay = Math.floor(Math.random() * 50) + 10;
245
+ sleepForRetry(delay);
246
+ try {
247
+ current = readTasks(projectPath);
248
+ } catch (e) {
249
+ console.error(`[ERROR] updateTasks: tasks.json corrupted during retry ${attempt + 1}: ${e.message}`);
250
+ return false;
251
+ }
252
+ }
253
+ }
254
+
255
+ const tasksPath = getTasksPath(projectPath);
256
+ let lastVersion = '(unreadable)';
257
+ try { lastVersion = readTasks(projectPath)._version; } catch {}
258
+
259
+ // Final fallback: if a concurrent writer happened to apply the exact same
260
+ // mutation (idempotent operations like releaseTask on an already-absent entry),
261
+ // treat the outcome as a success rather than reporting a spurious failure.
262
+ let latest;
263
+ try { latest = readTasks(projectPath); } catch {}
264
+ if (latest) {
265
+ // Re-run the mutator on what's on disk; if the result is identical to
266
+ // what's already there, our desired state is already achieved.
267
+ try {
268
+ const wouldBe = mutatorFn(structuredClone(latest));
269
+ // Normalize _version/_writerId before comparing content
270
+ wouldBe._version = latest._version;
271
+ wouldBe._writerId = latest._writerId;
272
+ if (JSON.stringify(wouldBe) === JSON.stringify(latest)) {
273
+ return true;
274
+ }
275
+ } catch {}
276
+ }
277
+
278
+ console.error(
279
+ `[ERROR] updateTasks: all ${MAX_RETRIES} attempts failed due to concurrent writers on ${tasksPath}. ` +
280
+ `Another agent process is modifying the registry simultaneously. ` +
281
+ `Last known _version: ${lastVersion}. ` +
282
+ `Suggested recovery: wait for the competing process to finish, then retry the operation.`
283
+ );
284
+ return false;
285
+ }
286
+
287
+ /**
288
+ * Set active task in main project (uses optimistic locking)
154
289
  */
155
290
  function setActiveTask(task, projectPath = process.cwd()) {
156
- const tasks = readTasks(projectPath);
157
- tasks.active = {
158
- ...task,
159
- startedAt: new Date().toISOString()
160
- };
161
- return writeTasks(tasks, projectPath);
291
+ return updateTasks(tasks => {
292
+ tasks.active = { ...task, startedAt: new Date().toISOString() };
293
+ return tasks;
294
+ }, projectPath);
162
295
  }
163
296
 
164
297
  /**
165
- * Clear active task
298
+ * Clear active task (uses optimistic locking)
166
299
  */
167
300
  function clearActiveTask(projectPath = process.cwd()) {
168
- const tasks = readTasks(projectPath);
169
- tasks.active = null;
170
- return writeTasks(tasks, projectPath);
301
+ return updateTasks(tasks => {
302
+ tasks.active = null;
303
+ return tasks;
304
+ }, projectPath);
305
+ }
306
+
307
+ /**
308
+ * Claim a task in the registry (uses optimistic locking).
309
+ * Used by worktree-manager; replaces the raw fs.writeFileSync inline in agent prompts.
310
+ *
311
+ * @param {Object} entry - { id, source, title, branch, worktreePath, claimedBy }
312
+ * @param {string} projectPath
313
+ */
314
+ function claimTask(entry, projectPath = process.cwd()) {
315
+ if (!entry || !entry.id) {
316
+ console.error('[ERROR] claimTask: entry.id is required');
317
+ return false;
318
+ }
319
+ return updateTasks(tasks => {
320
+ const idx = tasks.tasks.findIndex(t => t.id === entry.id);
321
+ const record = {
322
+ ...entry,
323
+ status: 'claimed',
324
+ claimedAt: entry.claimedAt || new Date().toISOString(),
325
+ lastActivityAt: new Date().toISOString()
326
+ };
327
+ if (idx >= 0) {
328
+ tasks.tasks[idx] = record;
329
+ } else {
330
+ tasks.tasks.push(record);
331
+ }
332
+ return tasks;
333
+ }, projectPath);
334
+ }
335
+
336
+ /**
337
+ * Release a claimed task from the registry (uses optimistic locking).
338
+ * Used by ship and --abort; replaces the raw fs.writeFileSync inline cleanup.
339
+ *
340
+ * @param {string} taskId
341
+ * @param {string} projectPath
342
+ */
343
+ function releaseTask(taskId, projectPath = process.cwd()) {
344
+ if (!taskId) {
345
+ console.error('[ERROR] releaseTask: taskId is required');
346
+ return false;
347
+ }
348
+ return updateTasks(tasks => {
349
+ const before = tasks.tasks.length;
350
+ tasks.tasks = tasks.tasks.filter(t => t.id !== taskId);
351
+ if (tasks.tasks.length === before) {
352
+ // Not found — that's fine, idempotent
353
+ console.error(`[WARN] releaseTask: task ${taskId} was not found in tasks.json registry. It may have already been released or never claimed.`);
354
+ }
355
+ return tasks;
356
+ }, projectPath);
171
357
  }
172
358
 
173
359
  /**
174
- * Check if there's an active task
175
- * Uses != null to catch both null and undefined (legacy format safety)
360
+ * Check if there's an active task.
361
+ * Uses != null to catch both null and undefined (legacy format safety).
176
362
  */
177
363
  function hasActiveTask(projectPath = process.cwd()) {
178
364
  const tasks = readTasks(projectPath);
@@ -548,8 +734,11 @@ module.exports = {
548
734
  getTasksPath,
549
735
  readTasks,
550
736
  writeTasks,
737
+ updateTasks,
551
738
  setActiveTask,
552
739
  clearActiveTask,
740
+ claimTask,
741
+ releaseTask,
553
742
  hasActiveTask,
554
743
 
555
744
  // Flow (worktree)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentsys",
3
- "version": "5.8.3",
3
+ "version": "5.8.4",
4
4
  "description": "A modular runtime and orchestration system for AI agents - works with Claude Code, OpenCode, and Codex CLI",
5
5
  "main": "lib/platform/detect-platform.js",
6
6
  "type": "commonjs",
@@ -109,7 +109,8 @@ const STATIC_SKILLS = [
109
109
  { plugin: 'audit-project', name: 'audit-project' },
110
110
  { plugin: 'glidemq', name: 'glide-mq' },
111
111
  { plugin: 'glidemq', name: 'glide-mq-migrate-bullmq' },
112
- { plugin: 'glidemq', name: 'glide-mq-migrate-bee' }
112
+ { plugin: 'glidemq', name: 'glide-mq-migrate-bee' },
113
+ { plugin: 'agnix', name: 'agnix' }
113
114
  ];
114
115
 
115
116
  // Purpose mapping for architecture table
@@ -192,7 +193,7 @@ function generateCommandsTable(commands) {
192
193
  'next-task': 'Task workflow: discovery, implementation, PR, merge',
193
194
  'prepare-delivery': 'Pre-ship quality gates: deslop, review, validation, docs sync',
194
195
  'gate-and-ship': 'Quality gates then ship (/prepare-delivery + /ship)',
195
- 'agnix': 'Lint agent configurations (385 rules)',
196
+ 'agnix': 'Lint agent configurations (399 rules)',
196
197
  'ship': 'PR creation, CI monitoring, merge',
197
198
  'deslop': 'Clean AI slop patterns',
198
199
  'perf': 'Performance investigation with baselines and profiling',
@@ -395,9 +396,34 @@ function generateAgentCounts(agents, plugins) {
395
396
  /**
396
397
  * Update counts in site/content.json programmatically.
397
398
  */
398
- // Static counts for cross-repo plugins not discoverable locally
399
- const STATIC_PLUGIN_COUNT = 19;
400
- const STATIC_AGENT_COUNT = 47;
399
+ // Static counts for cross-repo plugins not discoverable locally.
400
+ // Per-plugin file-based agent counts. Update this map when agents are added/removed
401
+ // in a plugin repo - it's the canonical source for the STATIC_AGENT_COUNT fallback.
402
+ const STATIC_PLUGIN_AGENT_COUNTS = {
403
+ 'next-task': 8,
404
+ 'prepare-delivery': 3,
405
+ 'gate-and-ship': 0,
406
+ 'ship': 1,
407
+ 'deslop': 1,
408
+ 'audit-project': 0,
409
+ 'drift-detect': 1,
410
+ 'enhance': 8,
411
+ 'sync-docs': 1,
412
+ 'repo-intel': 1,
413
+ 'perf': 6,
414
+ 'learn': 1,
415
+ 'agnix': 1,
416
+ 'consult': 1,
417
+ 'debate': 1,
418
+ 'web-ctl': 1,
419
+ 'skillers': 2,
420
+ 'onboard': 1,
421
+ 'can-i-help': 1
422
+ };
423
+ const STATIC_PLUGIN_COUNT = Object.keys(STATIC_PLUGIN_AGENT_COUNTS).length;
424
+ const STATIC_FILE_BASED_AGENT_COUNT = Object.values(STATIC_PLUGIN_AGENT_COUNTS).reduce((sum, count) => sum + count, 0);
425
+ // Total = file-based + role-based (audit-project specialists, spawned dynamically)
426
+ const STATIC_AGENT_COUNT = STATIC_FILE_BASED_AGENT_COUNT + ROLE_BASED_AGENT_COUNT;
401
427
 
402
428
  function updateSiteContent(plugins, agents, skills) {
403
429
  const contentPath = path.join(ROOT_DIR, 'site', 'content.json');
@@ -652,6 +678,8 @@ module.exports = {
652
678
  PURPOSE_MAP,
653
679
  ROLE_BASED_AGENT_COUNT,
654
680
  STATIC_SKILLS,
681
+ STATIC_PLUGIN_AGENT_COUNTS,
655
682
  STATIC_PLUGIN_COUNT,
683
+ STATIC_FILE_BASED_AGENT_COUNT,
656
684
  STATIC_AGENT_COUNT
657
685
  };
package/site/content.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "meta": {
3
3
  "title": "agentsys",
4
- "description": "A modular runtime and orchestration system for AI agents. 19 plugins, 47 agents, 40 skills - structured pipelines for Claude Code, OpenCode, Codex CLI, Cursor, and Kiro.",
4
+ "description": "A modular runtime and orchestration system for AI agents. 19 plugins, 49 agents, 41 skills - structured pipelines for Claude Code, OpenCode, Codex CLI, Cursor, and Kiro.",
5
5
  "url": "https://agent-sh.github.io/agentsys",
6
6
  "repo": "https://github.com/agent-sh/agentsys",
7
7
  "npm": "https://www.npmjs.com/package/agentsys",
8
- "version": "5.8.3",
8
+ "version": "5.8.4",
9
9
  "author": "Avi Fenesh",
10
10
  "author_url": "https://github.com/avifenesh"
11
11
  },
@@ -28,12 +28,12 @@
28
28
  "suffix": ""
29
29
  },
30
30
  {
31
- "value": "47",
31
+ "value": "49",
32
32
  "label": "Agents",
33
33
  "suffix": ""
34
34
  },
35
35
  {
36
- "value": "40",
36
+ "value": "41",
37
37
  "label": "Skills",
38
38
  "suffix": ""
39
39
  },
@@ -43,7 +43,7 @@
43
43
  "suffix": ""
44
44
  },
45
45
  {
46
- "value": "3,750",
46
+ "value": "3,507",
47
47
  "label": "Tests",
48
48
  "suffix": ""
49
49
  },
@@ -112,7 +112,7 @@
112
112
  {
113
113
  "name": "/agnix",
114
114
  "tagline": "Lint agent configs before they break",
115
- "description": "385 validation rules (102 auto-fixable) for Skills, Memory, Hooks, MCP, and Plugins across 10+ AI tools including Claude Code, Cursor, GitHub Copilot, Codex CLI, OpenCode, Gemini CLI, Cline, Windsurf, Roo Code, and Amp. SARIF output for GitHub Code Scanning.",
115
+ "description": "399 validation rules (126 auto-fixable) for Skills, Memory, Hooks, MCP, and Plugins across 10+ AI tools including Claude Code, Cursor, GitHub Copilot, Codex CLI, OpenCode, Gemini CLI, Cline, Windsurf, Roo Code, and Amp. SARIF output for GitHub Code Scanning.",
116
116
  "example": "/agnix --fix",
117
117
  "category": "linting"
118
118
  },
@@ -154,7 +154,7 @@
154
154
  {
155
155
  "name": "/enhance",
156
156
  "tagline": "Analyze everything that shapes agent behavior",
157
- "description": "Seven parallel analyzers check your prompts, agents, plugins, docs, hooks, and skills. Certainty-graded findings with auto-fix support. Auto-learns false positives over time.",
157
+ "description": "Eight parallel analyzers check your prompts, agents, plugins, docs, hooks, and skills. Certainty-graded findings with auto-fix support. Auto-learns false positives over time.",
158
158
  "example": "/enhance",
159
159
  "category": "analysis"
160
160
  },
@@ -373,19 +373,28 @@
373
373
  }
374
374
  ],
375
375
  "agents": {
376
- "total": 47,
377
- "file_based": 37,
376
+ "total": 49,
377
+ "file_based": 39,
378
378
  "role_based": 10,
379
379
  "by_model": [
380
380
  {
381
381
  "model": "Opus",
382
382
  "use_case": "Complex reasoning, analysis",
383
383
  "agents": [
384
- "exploration-agent",
385
384
  "planning-agent",
386
385
  "implementation-agent",
387
386
  "perf-orchestrator",
388
- "learn-agent"
387
+ "perf-analyzer",
388
+ "perf-theory-gatherer",
389
+ "perf-theory-tester",
390
+ "agent-enhancer",
391
+ "claudemd-enhancer",
392
+ "docs-enhancer",
393
+ "hooks-enhancer",
394
+ "prompt-enhancer",
395
+ "skills-enhancer",
396
+ "debate-orchestrator",
397
+ "skillers-recommender"
389
398
  ]
390
399
  },
391
400
  {
@@ -393,10 +402,26 @@
393
402
  "use_case": "Validation, pattern matching",
394
403
  "agents": [
395
404
  "task-discoverer",
405
+ "exploration-agent",
406
+ "prepare-delivery-agent",
396
407
  "delivery-validator",
397
408
  "ci-fixer",
409
+ "test-coverage-checker",
398
410
  "deslop-agent",
399
- "enhancement reporters"
411
+ "cross-file-enhancer",
412
+ "plugin-enhancer",
413
+ "perf-code-paths",
414
+ "perf-investigation-logger",
415
+ "plan-synthesizer",
416
+ "learn-agent",
417
+ "sync-docs-agent",
418
+ "agnix-agent",
419
+ "consult-agent",
420
+ "web-session",
421
+ "skillers-compactor",
422
+ "release-agent",
423
+ "onboard-agent",
424
+ "can-i-help-agent"
400
425
  ]
401
426
  },
402
427
  {
@@ -405,7 +430,8 @@
405
430
  "agents": [
406
431
  "worktree-manager",
407
432
  "ci-monitor",
408
- "simple-fixer"
433
+ "simple-fixer",
434
+ "map-validator"
409
435
  ]
410
436
  }
411
437
  ]
@@ -505,7 +531,7 @@
505
531
  ],
506
532
  "research": {
507
533
  "knowledge_base": "8,000 lines of curated documentation from Anthropic, OpenAI, Google, and Microsoft",
508
- "testing": "3,750 tests passing",
534
+ "testing": "3,507 tests passing",
509
535
  "drift_detect_repos": "1,000+ repositories validated",
510
536
  "token_reduction": "77% fewer tokens for drift-detect vs multi-agent approaches"
511
537
  },
package/site/index.html CHANGED
@@ -4,12 +4,12 @@
4
4
  <meta charset="UTF-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1">
6
6
  <title>AgentSys - Agent Runtime &amp; Orchestration System</title>
7
- <meta name="description" content="A modular runtime and orchestration system for AI agents. 19 plugins, 47 agents, 40 skills structured pipelines for Claude Code, OpenCode, Codex CLI, Cursor, and Kiro.">
7
+ <meta name="description" content="A modular runtime and orchestration system for AI agents. 19 plugins, 49 agents, 41 skills - structured pipelines for Claude Code, OpenCode, Codex CLI, Cursor, and Kiro.">
8
8
  <meta name="theme-color" content="#09090b">
9
9
 
10
10
  <!-- Open Graph -->
11
11
  <meta property="og:title" content="AgentSys">
12
- <meta property="og:description" content="A modular runtime and orchestration system for AI agents. 19 plugins, 47 agents, 40 skills.">
12
+ <meta property="og:description" content="A modular runtime and orchestration system for AI agents. 19 plugins, 49 agents, 41 skills.">
13
13
  <meta property="og:image" content="https://agent-sh.github.io/agentsys/assets/logo.png">
14
14
  <meta property="og:url" content="https://agent-sh.github.io/agentsys/">
15
15
  <meta property="og:type" content="website">
@@ -17,7 +17,7 @@
17
17
  <!-- Twitter Card -->
18
18
  <meta name="twitter:card" content="summary_large_image">
19
19
  <meta name="twitter:title" content="AgentSys">
20
- <meta name="twitter:description" content="AI workflow automation. 19 plugins, 47 agents, 40 skills.">
20
+ <meta name="twitter:description" content="AI workflow automation. 19 plugins, 49 agents, 41 skills.">
21
21
  <meta name="twitter:image" content="https://agent-sh.github.io/agentsys/assets/logo.png">
22
22
 
23
23
  <!-- Content Security Policy -->
@@ -107,14 +107,14 @@
107
107
  <div class="hero__inner">
108
108
  <div class="hero__content">
109
109
  <div class="hero__badge anim-fade-in" data-delay="100">
110
- 19 plugins &middot; 47 agents &middot; 40 skills
110
+ 19 plugins &middot; 49 agents &middot; 41 skills
111
111
  </div>
112
112
  <h1 class="hero__title anim-fade-up" id="hero-title" data-delay="200">
113
113
  A modular <span class="text-gradient">runtime and orchestration system</span><br>
114
114
  for AI agents.
115
115
  </h1>
116
116
  <p class="hero__subtitle anim-fade-up" data-delay="350">
117
- Structured pipelines, gated phases, specialized agents. Works with Claude Code, OpenCode, Codex CLI, Cursor, and Kiro. 3,750 tests. Production-grade.
117
+ Structured pipelines, gated phases, specialized agents. Works with Claude Code, OpenCode, Codex CLI, Cursor, and Kiro. 3,507 tests. Production-grade.
118
118
  </p>
119
119
  <div class="hero__ctas anim-fade-up" data-delay="500">
120
120
  <a href="#install" class="btn btn--primary">Get Started</a>
@@ -160,15 +160,15 @@
160
160
  <span class="stats__label">Plugins</span>
161
161
  </div>
162
162
  <div class="stats__item">
163
- <span class="stats__number" aria-live="polite" data-target="47">0</span>
163
+ <span class="stats__number" aria-live="polite" data-target="49">0</span>
164
164
  <span class="stats__label">Agents</span>
165
165
  </div>
166
166
  <div class="stats__item">
167
- <span class="stats__number" aria-live="polite" data-target="40">0</span>
167
+ <span class="stats__number" aria-live="polite" data-target="41">0</span>
168
168
  <span class="stats__label">Skills</span>
169
169
  </div>
170
170
  <div class="stats__item">
171
- <span class="stats__number" aria-live="polite" data-target="3750">0</span>
171
+ <span class="stats__number" aria-live="polite" data-target="3507">0</span>
172
172
  <span class="stats__label">Tests Passing</span>
173
173
  </div>
174
174
  </div>
@@ -228,9 +228,9 @@
228
228
  <h3 class="tabs__panel-name">/agnix</h3>
229
229
  <p class="tabs__panel-tagline">Lint agent configs before they break</p>
230
230
  <ul class="tabs__panel-features">
231
- <li>385 validation rules across 36 categories</li>
231
+ <li>399 validation rules across 36 categories</li>
232
232
  <li>10+ AI tools: Claude Code, Cursor, Copilot, Codex, OpenCode, Gemini CLI</li>
233
- <li>102 auto-fixable rules with --fix flag</li>
233
+ <li>126 auto-fixable rules with --fix flag</li>
234
234
  <li>SARIF output for GitHub Code Scanning</li>
235
235
  </ul>
236
236
  <div class="code-block">
@@ -607,7 +607,7 @@
607
607
  <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><circle cx="12" cy="12" r="3"/></svg>
608
608
  </div>
609
609
  <h3 class="philosophy__card-title">One agent, one job, done well</h3>
610
- <p class="philosophy__card-desc"><span class="text-accent">47 specialized agents</span>, each with a narrow scope and clear success criteria. No agent tries to do everything.</p>
610
+ <p class="philosophy__card-desc"><span class="text-accent">49 specialized agents</span>, each with a narrow scope and clear success criteria. No agent tries to do everything.</p>
611
611
  </div>
612
612
  <div class="philosophy__card anim-fade-up" data-delay="200">
613
613
  <div class="philosophy__card-icon">
@@ -662,14 +662,14 @@
662
662
  <!-- ===== AGENTS & SKILLS ===== -->
663
663
  <section class="agents-skills" id="agents-skills" aria-labelledby="as-title">
664
664
  <div class="agents-skills__inner">
665
- <h2 class="agents-skills__title anim-fade-up" id="as-title">47 Agents. 40 Skills.</h2>
665
+ <h2 class="agents-skills__title anim-fade-up" id="as-title">49 Agents. 41 Skills.</h2>
666
666
  <p class="agents-skills__subtitle anim-fade-up" data-delay="100">Right model for the task. Opus reasons. Sonnet validates. Haiku executes.</p>
667
667
 
668
668
  <!-- Agent tier tabs -->
669
669
  <div class="agents-skills__tabs anim-fade-up" data-delay="200">
670
670
  <div class="agent-tabs" role="tablist" aria-label="Agent tiers">
671
- <button class="agent-tabs__tab agent-tabs__tab--active" role="tab" aria-selected="true" aria-controls="agent-tier-opus" id="agent-tab-opus" data-index="0">Opus <span class="agent-tabs__count">15</span></button>
672
- <button class="agent-tabs__tab" role="tab" aria-selected="false" aria-controls="agent-tier-sonnet" id="agent-tab-sonnet" tabindex="-1" data-index="1">Sonnet <span class="agent-tabs__count">18</span></button>
671
+ <button class="agent-tabs__tab agent-tabs__tab--active" role="tab" aria-selected="true" aria-controls="agent-tier-opus" id="agent-tab-opus" data-index="0">Opus <span class="agent-tabs__count">14</span></button>
672
+ <button class="agent-tabs__tab" role="tab" aria-selected="false" aria-controls="agent-tier-sonnet" id="agent-tab-sonnet" tabindex="-1" data-index="1">Sonnet <span class="agent-tabs__count">21</span></button>
673
673
  <button class="agent-tabs__tab" role="tab" aria-selected="false" aria-controls="agent-tier-haiku" id="agent-tab-haiku" tabindex="-1" data-index="2">Haiku <span class="agent-tabs__count">4</span></button>
674
674
  <button class="agent-tabs__tab" role="tab" aria-selected="false" aria-controls="agent-tier-specialists" id="agent-tab-specialists" tabindex="-1" data-index="3">Specialists <span class="agent-tabs__count">10</span></button>
675
675
  </div>
@@ -677,13 +677,12 @@
677
677
  <!-- Opus agents -->
678
678
  <div class="agent-tier tabs__panel tabs__panel--active" role="tabpanel" id="agent-tier-opus" aria-labelledby="agent-tab-opus">
679
679
  <div class="agent-grid">
680
- <div class="agent-card"><span class="agent-card__name">exploration-agent</span><span class="tier-badge tier-badge--opus">opus</span><p class="agent-card__desc">Deep codebase analysis and context gathering</p></div>
681
680
  <div class="agent-card"><span class="agent-card__name">planning-agent</span><span class="tier-badge tier-badge--opus">opus</span><p class="agent-card__desc">Step-by-step implementation design</p></div>
682
681
  <div class="agent-card"><span class="agent-card__name">implementation-agent</span><span class="tier-badge tier-badge--opus">opus</span><p class="agent-card__desc">Autonomous code writing and modification</p></div>
683
682
  <div class="agent-card"><span class="agent-card__name">perf-orchestrator</span><span class="tier-badge tier-badge--opus">opus</span><p class="agent-card__desc">Performance investigation coordination</p></div>
684
683
  <div class="agent-card"><span class="agent-card__name">perf-analyzer</span><span class="tier-badge tier-badge--opus">opus</span><p class="agent-card__desc">Deep performance analysis and profiling</p></div>
685
- <div class="agent-card"><span class="agent-card__name">learn-agent</span><span class="tier-badge tier-badge--opus">opus</span><p class="agent-card__desc">Web research and learning guide creation</p></div>
686
- <div class="agent-card"><span class="agent-card__name">plan-synthesizer</span><span class="tier-badge tier-badge--opus">opus</span><p class="agent-card__desc">Multi-source plan synthesis and merging</p></div>
684
+ <div class="agent-card"><span class="agent-card__name">perf-theory-gatherer</span><span class="tier-badge tier-badge--opus">opus</span><p class="agent-card__desc">Performance hypothesis generation</p></div>
685
+ <div class="agent-card"><span class="agent-card__name">perf-theory-tester</span><span class="tier-badge tier-badge--opus">opus</span><p class="agent-card__desc">Controlled experiment execution</p></div>
687
686
  <div class="agent-card"><span class="agent-card__name">agent-enhancer</span><span class="tier-badge tier-badge--opus">opus</span><p class="agent-card__desc">Agent configuration quality analysis</p></div>
688
687
  <div class="agent-card"><span class="agent-card__name">claudemd-enhancer</span><span class="tier-badge tier-badge--opus">opus</span><p class="agent-card__desc">CLAUDE.md file optimization</p></div>
689
688
  <div class="agent-card"><span class="agent-card__name">docs-enhancer</span><span class="tier-badge tier-badge--opus">opus</span><p class="agent-card__desc">Documentation quality improvement</p></div>
@@ -699,6 +698,8 @@
699
698
  <div class="agent-tier tabs__panel" role="tabpanel" id="agent-tier-sonnet" aria-labelledby="agent-tab-sonnet" hidden>
700
699
  <div class="agent-grid">
701
700
  <div class="agent-card"><span class="agent-card__name">task-discoverer</span><span class="tier-badge tier-badge--sonnet">sonnet</span><p class="agent-card__desc">Task source scanning and prioritization</p></div>
701
+ <div class="agent-card"><span class="agent-card__name">exploration-agent</span><span class="tier-badge tier-badge--sonnet">sonnet</span><p class="agent-card__desc">Deep codebase analysis and context gathering</p></div>
702
+ <div class="agent-card"><span class="agent-card__name">prepare-delivery-agent</span><span class="tier-badge tier-badge--sonnet">sonnet</span><p class="agent-card__desc">Pre-ship quality gate orchestration</p></div>
702
703
  <div class="agent-card"><span class="agent-card__name">delivery-validator</span><span class="tier-badge tier-badge--sonnet">sonnet</span><p class="agent-card__desc">Pre-ship quality gate validation</p></div>
703
704
  <div class="agent-card"><span class="agent-card__name">ci-fixer</span><span class="tier-badge tier-badge--sonnet">sonnet</span><p class="agent-card__desc">CI failure diagnosis and auto-repair</p></div>
704
705
  <div class="agent-card"><span class="agent-card__name">test-coverage-checker</span><span class="tier-badge tier-badge--sonnet">sonnet</span><p class="agent-card__desc">Test coverage analysis and gap detection</p></div>
@@ -707,8 +708,8 @@
707
708
  <div class="agent-card"><span class="agent-card__name">plugin-enhancer</span><span class="tier-badge tier-badge--sonnet">sonnet</span><p class="agent-card__desc">Plugin configuration validation</p></div>
708
709
  <div class="agent-card"><span class="agent-card__name">perf-code-paths</span><span class="tier-badge tier-badge--sonnet">sonnet</span><p class="agent-card__desc">Hot code path identification</p></div>
709
710
  <div class="agent-card"><span class="agent-card__name">perf-investigation-logger</span><span class="tier-badge tier-badge--sonnet">sonnet</span><p class="agent-card__desc">Performance investigation logging</p></div>
710
- <div class="agent-card"><span class="agent-card__name">perf-theory-gatherer</span><span class="tier-badge tier-badge--sonnet">sonnet</span><p class="agent-card__desc">Performance hypothesis generation</p></div>
711
- <div class="agent-card"><span class="agent-card__name">perf-theory-tester</span><span class="tier-badge tier-badge--sonnet">sonnet</span><p class="agent-card__desc">Controlled experiment execution</p></div>
711
+ <div class="agent-card"><span class="agent-card__name">plan-synthesizer</span><span class="tier-badge tier-badge--sonnet">sonnet</span><p class="agent-card__desc">Multi-source plan synthesis and merging</p></div>
712
+ <div class="agent-card"><span class="agent-card__name">learn-agent</span><span class="tier-badge tier-badge--sonnet">sonnet</span><p class="agent-card__desc">Web research and learning guide creation</p></div>
712
713
  <div class="agent-card"><span class="agent-card__name">sync-docs-agent</span><span class="tier-badge tier-badge--sonnet">sonnet</span><p class="agent-card__desc">Documentation sync and update</p></div>
713
714
  <div class="agent-card"><span class="agent-card__name">agnix-agent</span><span class="tier-badge tier-badge--sonnet">sonnet</span><p class="agent-card__desc">Agent config linting orchestration</p></div>
714
715
  <div class="agent-card"><span class="agent-card__name">consult-agent</span><span class="tier-badge tier-badge--sonnet">sonnet</span><p class="agent-card__desc">Cross-tool AI consultation orchestration</p></div>
@@ -716,6 +717,7 @@
716
717
  <div class="agent-card"><span class="agent-card__name">skillers-compactor</span><span class="tier-badge tier-badge--sonnet">sonnet</span><p class="agent-card__desc">Transcript compaction into knowledge themes</p></div>
717
718
  <div class="agent-card"><span class="agent-card__name">release-agent</span><span class="tier-badge tier-badge--sonnet">sonnet</span><p class="agent-card__desc">Versioned release with ecosystem detection</p></div>
718
719
  <div class="agent-card"><span class="agent-card__name">onboard-agent</span><span class="tier-badge tier-badge--sonnet">sonnet</span><p class="agent-card__desc">Codebase orientation and guided onboarding</p></div>
720
+ <div class="agent-card"><span class="agent-card__name">can-i-help-agent</span><span class="tier-badge tier-badge--sonnet">sonnet</span><p class="agent-card__desc">Contributor guidance matching skills to project needs</p></div>
719
721
  </div>
720
722
  </div>
721
723
 
@@ -747,7 +749,7 @@
747
749
  </div>
748
750
 
749
751
  <!-- Skills grid -->
750
- <h3 class="agents-skills__skills-title anim-fade-up" data-delay="300">40 Skills across 19 Plugins</h3>
752
+ <h3 class="agents-skills__skills-title anim-fade-up" data-delay="300">41 Skills across 19 Plugins</h3>
751
753
  <div class="skills-grid anim-fade-up" data-delay="350">
752
754
  <div class="skill-group">
753
755
  <span class="skill-group__label">prepare-delivery</span>
@@ -819,6 +821,7 @@
819
821
  <span class="skill-card">onboard</span>
820
822
  <span class="skill-card">can-i-help</span>
821
823
  <span class="skill-card">audit-project</span>
824
+ <span class="skill-card">agnix</span>
822
825
  </div>
823
826
  </div>
824
827
  <div class="skill-group">
package/site/ux-spec.md CHANGED
@@ -94,7 +94,7 @@ Scroll order with rationale for each section. All sections are full-width, alter
94
94
  - **Single column on mobile:** Text above, terminal below. Stack with 48px gap.
95
95
 
96
96
  ### Left Column Content
97
- 1. **Badge** (top, above title): Small pill showing version or "19 plugins . 47 agents . 40 skills"
97
+ 1. **Badge** (top, above title): Small pill showing version or "19 plugins . 49 agents . 41 skills"
98
98
  - Background: `rgba(99, 102, 241, 0.12)`, border: `1px solid rgba(99, 102, 241, 0.25)`, border-radius: 9999px
99
99
  - Font: 13px, font-weight 500, primary accent color
100
100
  - Padding: 4px 14px
@@ -104,7 +104,7 @@ Scroll order with rationale for each section. All sections are full-width, alter
104
104
  - Color: white
105
105
  - "entire dev workflow" portion highlighted with a subtle gradient text (primary-to-secondary accent via `background-clip: text`)
106
106
 
107
- 3. **Subtitle:** "19 plugins, 47 agents, 40 skills. From task selection to merged PR. Works with Claude Code, OpenCode, Codex CLI, Cursor, and Kiro."
107
+ 3. **Subtitle:** "19 plugins, 49 agents, 41 skills. From task selection to merged PR. Works with Claude Code, OpenCode, Codex CLI, Cursor, and Kiro."
108
108
  - Font: 18px on desktop, 16px on mobile, font-weight 400, line-height 1.6
109
109
  - Color: `rgba(255, 255, 255, 0.6)`
110
110
  - Max-width: 520px
@@ -226,10 +226,10 @@ Done. Task to merged PR in 12 minutes.
226
226
  ### Stats (left to right)
227
227
  | Stat | Value | Label |
228
228
  |------|-------|-------|
229
- | 1 | 14 | Plugins |
230
- | 2 | 43 | Agents |
231
- | 3 | 30 | Skills |
232
- | 4 | 3,750 | Tests Passing |
229
+ | 1 | 19 | Plugins |
230
+ | 2 | 49 | Agents |
231
+ | 3 | 40 | Skills |
232
+ | 4 | 3,507 | Tests Passing |
233
233
 
234
234
  ### Styling
235
235
  - **Number:** 48px, font-weight 700, white, `font-variant-numeric: tabular-nums` (prevents layout shift during count)
@@ -650,13 +650,13 @@ This disables:
650
650
  ### Head Content
651
651
  ```html
652
652
  <title>AgentSys - Agent Runtime &amp; Orchestration System</title>
653
- <meta name="description" content="A modular runtime and orchestration system for AI agents. 19 plugins, 47 agents, 40 skills structured pipelines for Claude Code, OpenCode, Codex CLI, Cursor, and Kiro.">
653
+ <meta name="description" content="A modular runtime and orchestration system for AI agents. 19 plugins, 49 agents, 41 skills - structured pipelines for Claude Code, OpenCode, Codex CLI, Cursor, and Kiro.">
654
654
  <meta name="viewport" content="width=device-width, initial-scale=1">
655
655
  <meta name="theme-color" content="#0a0a0f">
656
656
 
657
657
  <!-- Open Graph -->
658
658
  <meta property="og:title" content="AgentSys">
659
- <meta property="og:description" content="AI workflow automation. 19 plugins, 47 agents, 40 skills. Task to merged PR.">
659
+ <meta property="og:description" content="AI workflow automation. 19 plugins, 49 agents, 41 skills. Task to merged PR.">
660
660
  <meta property="og:image" content="https://agent-sh.github.io/agentsys/assets/og-image.png">
661
661
  <meta property="og:url" content="https://agent-sh.github.io/agentsys/">
662
662
  <meta property="og:type" content="website">
@@ -664,7 +664,7 @@ This disables:
664
664
  <!-- Twitter Card -->
665
665
  <meta name="twitter:card" content="summary_large_image">
666
666
  <meta name="twitter:title" content="AgentSys">
667
- <meta name="twitter:description" content="AI workflow automation. 19 plugins, 47 agents, 40 skills.">
667
+ <meta name="twitter:description" content="AI workflow automation. 19 plugins, 49 agents, 41 skills.">
668
668
  <meta name="twitter:image" content="https://agent-sh.github.io/agentsys/assets/og-image.png">
669
669
  ```
670
670