specweave 1.0.488 → 1.0.490

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.
Files changed (151) hide show
  1. package/README.md +1 -1
  2. package/dist/plugins/specweave-ado/lib/ado-ac-checkbox-sync.d.ts +13 -5
  3. package/dist/plugins/specweave-ado/lib/ado-ac-checkbox-sync.d.ts.map +1 -1
  4. package/dist/plugins/specweave-ado/lib/ado-ac-checkbox-sync.js +28 -26
  5. package/dist/plugins/specweave-ado/lib/ado-ac-checkbox-sync.js.map +1 -1
  6. package/dist/plugins/specweave-ado/lib/ado-client.d.ts +14 -0
  7. package/dist/plugins/specweave-ado/lib/ado-client.d.ts.map +1 -1
  8. package/dist/plugins/specweave-ado/lib/ado-client.js +29 -1
  9. package/dist/plugins/specweave-ado/lib/ado-client.js.map +1 -1
  10. package/dist/plugins/specweave-ado/lib/ado-pull-sync.d.ts +35 -0
  11. package/dist/plugins/specweave-ado/lib/ado-pull-sync.d.ts.map +1 -0
  12. package/dist/plugins/specweave-ado/lib/ado-pull-sync.js +53 -0
  13. package/dist/plugins/specweave-ado/lib/ado-pull-sync.js.map +1 -0
  14. package/dist/plugins/specweave-ado/lib/ado-rate-limiter.d.ts +46 -0
  15. package/dist/plugins/specweave-ado/lib/ado-rate-limiter.d.ts.map +1 -0
  16. package/dist/plugins/specweave-ado/lib/ado-rate-limiter.js +65 -0
  17. package/dist/plugins/specweave-ado/lib/ado-rate-limiter.js.map +1 -0
  18. package/dist/plugins/specweave-ado/lib/ado-spec-sync.d.ts +7 -1
  19. package/dist/plugins/specweave-ado/lib/ado-spec-sync.d.ts.map +1 -1
  20. package/dist/plugins/specweave-ado/lib/ado-spec-sync.js +25 -1
  21. package/dist/plugins/specweave-ado/lib/ado-spec-sync.js.map +1 -1
  22. package/dist/plugins/specweave-ado/lib/ado-status-sync.d.ts +17 -1
  23. package/dist/plugins/specweave-ado/lib/ado-status-sync.d.ts.map +1 -1
  24. package/dist/plugins/specweave-ado/lib/ado-status-sync.js +51 -9
  25. package/dist/plugins/specweave-ado/lib/ado-status-sync.js.map +1 -1
  26. package/dist/plugins/specweave-github/lib/github-client-v2.js +1 -1
  27. package/dist/plugins/specweave-github/lib/github-client-v2.js.map +1 -1
  28. package/dist/plugins/specweave-github/lib/github-push-sync.d.ts.map +1 -1
  29. package/dist/plugins/specweave-github/lib/github-push-sync.js +15 -3
  30. package/dist/plugins/specweave-github/lib/github-push-sync.js.map +1 -1
  31. package/dist/plugins/specweave-jira/lib/jira-spec-sync.d.ts +31 -1
  32. package/dist/plugins/specweave-jira/lib/jira-spec-sync.d.ts.map +1 -1
  33. package/dist/plugins/specweave-jira/lib/jira-spec-sync.js +170 -97
  34. package/dist/plugins/specweave-jira/lib/jira-spec-sync.js.map +1 -1
  35. package/dist/plugins/specweave-jira/lib/jira-status-sync.d.ts +36 -1
  36. package/dist/plugins/specweave-jira/lib/jira-status-sync.d.ts.map +1 -1
  37. package/dist/plugins/specweave-jira/lib/jira-status-sync.js +185 -82
  38. package/dist/plugins/specweave-jira/lib/jira-status-sync.js.map +1 -1
  39. package/dist/src/adapters/adapter-loader.d.ts.map +1 -1
  40. package/dist/src/adapters/adapter-loader.js +8 -2
  41. package/dist/src/adapters/adapter-loader.js.map +1 -1
  42. package/dist/src/adapters/codex/adapter.d.ts.map +1 -1
  43. package/dist/src/adapters/codex/adapter.js +1 -0
  44. package/dist/src/adapters/codex/adapter.js.map +1 -1
  45. package/dist/src/adapters/cursor/adapter.d.ts.map +1 -1
  46. package/dist/src/adapters/cursor/adapter.js +1 -0
  47. package/dist/src/adapters/cursor/adapter.js.map +1 -1
  48. package/dist/src/adapters/generic/adapter.d.ts +6 -3
  49. package/dist/src/adapters/generic/adapter.d.ts.map +1 -1
  50. package/dist/src/adapters/generic/adapter.js +53 -47
  51. package/dist/src/adapters/generic/adapter.js.map +1 -1
  52. package/dist/src/adapters/kimi/adapter.d.ts +21 -0
  53. package/dist/src/adapters/kimi/adapter.d.ts.map +1 -0
  54. package/dist/src/adapters/kimi/adapter.js +57 -0
  55. package/dist/src/adapters/kimi/adapter.js.map +1 -0
  56. package/dist/src/adapters/opencode/adapter.d.ts +24 -0
  57. package/dist/src/adapters/opencode/adapter.d.ts.map +1 -0
  58. package/dist/src/adapters/opencode/adapter.js +71 -0
  59. package/dist/src/adapters/opencode/adapter.js.map +1 -0
  60. package/dist/src/adapters/registry.yaml +59 -0
  61. package/dist/src/adapters/trae/adapter.d.ts +21 -0
  62. package/dist/src/adapters/trae/adapter.d.ts.map +1 -0
  63. package/dist/src/adapters/trae/adapter.js +64 -0
  64. package/dist/src/adapters/trae/adapter.js.map +1 -0
  65. package/dist/src/cli/commands/init.d.ts.map +1 -1
  66. package/dist/src/cli/commands/init.js +156 -5
  67. package/dist/src/cli/commands/init.js.map +1 -1
  68. package/dist/src/cli/commands/update-instructions.d.ts.map +1 -1
  69. package/dist/src/cli/commands/update-instructions.js +10 -0
  70. package/dist/src/cli/commands/update-instructions.js.map +1 -1
  71. package/dist/src/cli/helpers/init/index.d.ts +1 -0
  72. package/dist/src/cli/helpers/init/index.d.ts.map +1 -1
  73. package/dist/src/cli/helpers/init/index.js +2 -0
  74. package/dist/src/cli/helpers/init/index.js.map +1 -1
  75. package/dist/src/cli/helpers/init/next-steps.d.ts.map +1 -1
  76. package/dist/src/cli/helpers/init/next-steps.js +52 -0
  77. package/dist/src/cli/helpers/init/next-steps.js.map +1 -1
  78. package/dist/src/cli/helpers/init/skill-creator-installer.d.ts +24 -0
  79. package/dist/src/cli/helpers/init/skill-creator-installer.d.ts.map +1 -0
  80. package/dist/src/cli/helpers/init/skill-creator-installer.js +54 -0
  81. package/dist/src/cli/helpers/init/skill-creator-installer.js.map +1 -0
  82. package/dist/src/core/ado-description-updater.d.ts +22 -0
  83. package/dist/src/core/ado-description-updater.d.ts.map +1 -0
  84. package/dist/src/core/ado-description-updater.js +46 -0
  85. package/dist/src/core/ado-description-updater.js.map +1 -0
  86. package/dist/src/core/closure-dispatcher.d.ts +96 -0
  87. package/dist/src/core/closure-dispatcher.d.ts.map +1 -0
  88. package/dist/src/core/closure-dispatcher.js +116 -0
  89. package/dist/src/core/closure-dispatcher.js.map +1 -0
  90. package/dist/src/core/config/types.d.ts +2 -0
  91. package/dist/src/core/config/types.d.ts.map +1 -1
  92. package/dist/src/core/config/types.js.map +1 -1
  93. package/dist/src/core/errors/sync-error.d.ts +12 -0
  94. package/dist/src/core/errors/sync-error.d.ts.map +1 -0
  95. package/dist/src/core/errors/sync-error.js +19 -0
  96. package/dist/src/core/errors/sync-error.js.map +1 -0
  97. package/dist/src/core/skill-gen/rule-collector.d.ts +28 -0
  98. package/dist/src/core/skill-gen/rule-collector.d.ts.map +1 -0
  99. package/dist/src/core/skill-gen/rule-collector.js +112 -0
  100. package/dist/src/core/skill-gen/rule-collector.js.map +1 -0
  101. package/dist/src/core/skill-gen/signal-collector.d.ts +2 -1
  102. package/dist/src/core/skill-gen/signal-collector.d.ts.map +1 -1
  103. package/dist/src/core/skill-gen/signal-collector.js +21 -5
  104. package/dist/src/core/skill-gen/signal-collector.js.map +1 -1
  105. package/dist/src/core/sync/persistent-circuit-breaker.d.ts +22 -0
  106. package/dist/src/core/sync/persistent-circuit-breaker.d.ts.map +1 -0
  107. package/dist/src/core/sync/persistent-circuit-breaker.js +65 -0
  108. package/dist/src/core/sync/persistent-circuit-breaker.js.map +1 -0
  109. package/dist/src/core/sync/retry-wrapper.d.ts +13 -0
  110. package/dist/src/core/sync/retry-wrapper.d.ts.map +1 -0
  111. package/dist/src/core/sync/retry-wrapper.js +37 -0
  112. package/dist/src/core/sync/retry-wrapper.js.map +1 -0
  113. package/dist/src/importers/ac-parser.d.ts +27 -0
  114. package/dist/src/importers/ac-parser.d.ts.map +1 -0
  115. package/dist/src/importers/ac-parser.js +47 -0
  116. package/dist/src/importers/ac-parser.js.map +1 -0
  117. package/dist/src/sync/types.d.ts +8 -0
  118. package/dist/src/sync/types.d.ts.map +1 -1
  119. package/dist/src/sync/types.js +12 -0
  120. package/dist/src/sync/types.js.map +1 -1
  121. package/package.json +1 -1
  122. package/plugins/specweave/PLUGIN.md +1 -0
  123. package/plugins/specweave/hooks/v2/guards/increment-existence-guard.sh +9 -3
  124. package/plugins/specweave/skills/code-reviewer/SKILL.md +401 -0
  125. package/plugins/specweave/skills/code-reviewer/agents/reviewer-silent-failures.md +65 -0
  126. package/plugins/specweave/skills/code-reviewer/agents/reviewer-spec-compliance.md +83 -0
  127. package/plugins/specweave/skills/code-reviewer/agents/reviewer-types.md +68 -0
  128. package/plugins/specweave/skills/skill-gen/SKILL.md +20 -3
  129. package/plugins/specweave/skills/team-lead/SKILL.md +155 -4
  130. package/plugins/specweave/skills/team-lead/agents/architect.md +52 -0
  131. package/plugins/specweave/skills/team-lead/agents/pm.md +50 -0
  132. package/plugins/specweave/skills/team-lead/agents/researcher.md +64 -0
  133. package/plugins/specweave-ado/lib/ado-ac-checkbox-sync.js +23 -21
  134. package/plugins/specweave-ado/lib/ado-ac-checkbox-sync.ts +37 -29
  135. package/plugins/specweave-ado/lib/ado-client.js +27 -1
  136. package/plugins/specweave-ado/lib/ado-client.ts +37 -2
  137. package/plugins/specweave-ado/lib/ado-pull-sync.js +35 -0
  138. package/plugins/specweave-ado/lib/ado-pull-sync.ts +74 -0
  139. package/plugins/specweave-ado/lib/ado-rate-limiter.js +56 -0
  140. package/plugins/specweave-ado/lib/ado-rate-limiter.ts +86 -0
  141. package/plugins/specweave-ado/lib/ado-spec-sync.js +25 -1
  142. package/plugins/specweave-ado/lib/ado-spec-sync.ts +32 -2
  143. package/plugins/specweave-ado/lib/ado-status-sync.js +52 -14
  144. package/plugins/specweave-ado/lib/ado-status-sync.ts +64 -16
  145. package/plugins/specweave-github/lib/github-client-v2.ts +1 -1
  146. package/plugins/specweave-github/lib/github-push-sync.js +11 -3
  147. package/plugins/specweave-github/lib/github-push-sync.ts +16 -3
  148. package/plugins/specweave-jira/lib/jira-spec-sync.js +60 -1
  149. package/plugins/specweave-jira/lib/jira-spec-sync.ts +93 -1
  150. package/plugins/specweave-jira/lib/jira-status-sync.js +151 -109
  151. package/plugins/specweave-jira/lib/jira-status-sync.ts +161 -39
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: Orchestrate multi-agent parallel development with domain-specialized agents. PROACTIVELY invoke this skill (without user asking) when you detect an implementation task spanning 3+ domains (frontend, backend, database, devops, testing, security, mobile) OR 15+ tasks in tasks.md. Warn the user about higher token cost but recommend it for quality. Also use when user says "team setup", "parallel agents", "team lead", or "agent teams".
2
+ description: Phase-agnostic orchestrator for parallel multi-agent work brainstorm, plan, implement, review, research, or test. Auto-detects mode from intent. Use for implementation (3+ domains or 15+ tasks), brainstorming (multiple perspectives), parallel planning (PM + Architect), code review (delegates to /sw:code-reviewer), research (multiple topics), or testing (parallel test layers). Also use when user says "team setup", "parallel agents", "team lead", "agent teams", "brainstorm with agents", "plan in parallel", "review code", "research this".
3
3
  hooks:
4
4
  PreToolUse:
5
5
  - matcher: TeamCreate
@@ -62,12 +62,164 @@ hooks:
62
62
  | Option | Description | Default |
63
63
  |--------|-------------|---------|
64
64
  | `--dry-run` | Show proposed agent plan without launching | false |
65
+ | `--mode` | Force operating mode: `brainstorm`, `plan`, `implement`, `review`, `research`, `test` | auto-detect |
65
66
  | `--domains` | Override domain detection (e.g., `--domains frontend,backend,testing`) | auto-detect |
66
67
  | `--max-agents` | Maximum number of concurrent agents | 6 |
67
68
 
68
69
  ---
69
70
 
70
- ## 0. Increment Pre-Flight (CONDITIONAL)
71
+ ## 0. Mode Detection (BEFORE Increment Pre-Flight)
72
+
73
+ **Detect operating mode FIRST. This determines the entire workflow path.**
74
+
75
+ ### Detection Rules (priority order)
76
+
77
+ 1. **Explicit flag**: `--mode brainstorm|plan|implement|review|research|test`
78
+ 2. **team_name prefix**: `review-*`, `brainstorm-*`, `research-*`, `plan-*`, `test-*`
79
+ 3. **Intent keywords** in the user's request:
80
+
81
+ | Keywords | Mode | Go To |
82
+ |----------|------|-------|
83
+ | "brainstorm", "ideate", "explore ideas", "what if", "pros and cons" | BRAINSTORM | Section 0a |
84
+ | "plan", "spec", "design", "architect", "define requirements" | PLANNING | Section 0b |
85
+ | "implement", "build", "code", "develop" *(or default)* | IMPLEMENTATION | Section 1 |
86
+ | "review", "audit", "check code", "review PR", "code quality" | REVIEW | Section 0c |
87
+ | "research", "investigate", "analyze", "explore codebase" | RESEARCH | Section 0d |
88
+ | "test", "write tests", "test strategy", "test coverage" | TESTING | Section 0e |
89
+
90
+ 4. **Default**: IMPLEMENTATION mode if no keywords match.
91
+
92
+ ### Mode Configuration
93
+
94
+ | Mode | Increment? | Agent Templates | Coordination | Output |
95
+ |------|-----------|-----------------|--------------|--------|
96
+ | BRAINSTORM | No | brainstorm-advocate, brainstorm-critic, brainstorm-pragmatist | Parallel → synthesize | Decision matrix |
97
+ | PLANNING | Creates one | pm, architect (+ optional security reviewer) | PM first → Architect parallel | spec.md, plan.md, tasks.md |
98
+ | IMPLEMENTATION | Required | backend, frontend, database, testing, security | Contract-first phases | Working code |
99
+ | REVIEW | Optional | Delegates to /sw:code-reviewer | Parallel | Review report |
100
+ | RESEARCH | No | researcher (1-3 instances) | Parallel → merge | Research report |
101
+ | TESTING | Required | testing (split by layer) | Parallel | Test suites |
102
+
103
+ ---
104
+
105
+ ### 0a. BRAINSTORM Mode
106
+
107
+ **team_name**: `brainstorm-{topic-slug}`
108
+
109
+ Skip increment pre-flight entirely. Brainstorm doesn't need a spec — it explores possibilities.
110
+
111
+ 1. Create team: `TeamCreate({ team_name: "brainstorm-{slug}", description: "Brainstorm: {topic}" })`
112
+ 2. Read agent templates from `agents/brainstorm-advocate.md`, `agents/brainstorm-critic.md`, `agents/brainstorm-pragmatist.md`
113
+ 3. Replace `[BRAINSTORM_QUESTION]` with the user's question/topic
114
+ 4. Spawn all 3 agents in parallel via `Task()` with `mode: "bypassPermissions"`
115
+ 5. Collect `PERSPECTIVE_COMPLETE:` messages from all agents
116
+ 6. Synthesize perspectives into a decision matrix:
117
+ - Compare approaches across dimensions (effort, risk, value, alignment)
118
+ - Highlight points of agreement and disagreement
119
+ - Provide a ranked recommendation
120
+ 7. Offer handoff: "Ready to proceed? Run `/sw:increment` to formalize the chosen approach."
121
+ 8. Cleanup: shutdown agents, TeamDelete
122
+ 9. **STOP** — do not proceed to implementation sections
123
+
124
+ ---
125
+
126
+ ### 0b. PLANNING Mode
127
+
128
+ **team_name**: `plan-{feature-slug}`
129
+
130
+ Planning mode runs PM and Architect agents in parallel for richer, faster spec creation.
131
+
132
+ 1. **Check for existing increment**:
133
+ - If increment exists: read it as context, agents will update/enhance its spec and plan
134
+ - If no increment: create one (folder + metadata.json only, agents will write spec/plan)
135
+
136
+ 2. **Phase 1 — PM Agent** (upstream):
137
+ - Read `agents/pm.md`, replace `[INCREMENT_ID]`, `[MASTER_INCREMENT_PATH]`, `[FEATURE_DESCRIPTION]`
138
+ - Spawn via `Task()` with `mode: "bypassPermissions"`
139
+ - PM writes spec.md with user stories and ACs
140
+ - Wait for PM's `PLAN_READY:` or `COMPLETION:` message
141
+
142
+ 3. **Phase 2 — Architect + Security** (parallel, after PM):
143
+ - Read `agents/architect.md`, replace placeholders, spawn Architect agent
144
+ - Optionally read `agents/reviewer-security.md` from team-lead agents, replace `[REVIEW_TARGET]` with the spec, spawn Security reviewer
145
+ - Both run in parallel: Architect writes plan.md, Security reviewer flags design-level vulnerabilities
146
+ - Wait for both `COMPLETION:` messages
147
+
148
+ 4. **Post-planning**:
149
+ - Run `specweave sync-living-docs {increment-id}` to sync external tools
150
+ - Present the spec + plan summary to the user
151
+ - Recommend execution strategy: `/sw:do`, `/sw:auto`, or `/sw:team-lead` (implementation mode)
152
+
153
+ 5. Cleanup: shutdown agents, TeamDelete
154
+ 6. **STOP** — do not proceed to implementation sections
155
+
156
+ ---
157
+
158
+ ### 0c. REVIEW Mode
159
+
160
+ **Delegates entirely to `/sw:code-reviewer`.**
161
+
162
+ Team-lead does NOT spawn its own reviewer agents for review mode. The code-reviewer skill handles its own orchestration with 6 specialized reviewers.
163
+
164
+ ```typescript
165
+ Skill({ skill: "sw:code-reviewer", args: "<user's review target or flags>" })
166
+ ```
167
+
168
+ Pass through any arguments the user provided (--pr N, --changes, --cross-repo, path).
169
+
170
+ **STOP** after the skill completes — do not proceed to implementation sections.
171
+
172
+ ---
173
+
174
+ ### 0d. RESEARCH Mode
175
+
176
+ **team_name**: `research-{topic-slug}`
177
+
178
+ Skip increment pre-flight. Research is exploratory — no spec needed.
179
+
180
+ 1. Create team: `TeamCreate({ team_name: "research-{slug}", description: "Research: {topic}" })`
181
+ 2. **Determine research agents**:
182
+ - Single topic: spawn 1 researcher from `agents/researcher.md`
183
+ - Multi-faceted topic: spawn 2-3 researchers with different scopes
184
+ (e.g., "research auth" → one agent on OAuth providers, one on session management, one on security best practices)
185
+ 3. Replace `[RESEARCH_TOPIC]` and `[RESEARCH_SCOPE]` in each agent prompt
186
+ 4. Spawn all researchers in parallel via `Task()` with `mode: "bypassPermissions"`
187
+ 5. Collect `RESEARCH_COMPLETE:` messages
188
+ 6. Merge findings into a unified research report:
189
+ - Cross-reference findings between agents
190
+ - Resolve contradictions
191
+ - Produce ranked recommendations
192
+ 7. Offer handoff: `/sw:increment` (to act on findings) or `/sw:brainstorm` (to explore approaches)
193
+ 8. Cleanup: shutdown agents, TeamDelete
194
+ 9. **STOP** — do not proceed to implementation sections
195
+
196
+ ---
197
+
198
+ ### 0e. TESTING Mode
199
+
200
+ **team_name**: `test-{increment-id}`
201
+
202
+ Testing mode requires an increment (it needs to know WHAT to test).
203
+
204
+ 1. **Verify increment exists** (same as implementation mode — see below)
205
+ 2. Create team: `TeamCreate({ team_name: "test-{id}", description: "Testing: {increment}" })`
206
+ 3. Spawn testing agents split by layer:
207
+ - **Unit test agent**: read `agents/testing.md`, override scope to unit tests only
208
+ - **E2E test agent**: read `agents/testing.md`, override scope to E2E tests only
209
+ - Split scope via the agent prompt, not via separate templates
210
+ 4. Spawn both in parallel via `Task()` with `mode: "bypassPermissions"`
211
+ 5. Collect `COMPLETION:` messages
212
+ 6. Run test suites to verify: `npx vitest run` + `npx playwright test`
213
+ 7. Report results: pass/fail counts, coverage, uncovered ACs
214
+ 8. Cleanup: shutdown agents, TeamDelete
215
+ 9. **STOP** — do not proceed to implementation sections
216
+
217
+ ---
218
+
219
+ ## 0.5. Increment Pre-Flight (IMPLEMENTATION and TESTING modes only)
220
+
221
+ **This section applies only to IMPLEMENTATION mode (default) and TESTING mode.**
222
+ All other modes handle their own increment logic (or skip it entirely) in Section 0a-0e above.
71
223
 
72
224
  The team-lead works best with an increment (spec.md, plan.md, tasks.md) but can also run **without one** in free-form mode.
73
225
 
@@ -75,10 +227,9 @@ The team-lead works best with an increment (spec.md, plan.md, tasks.md) but can
75
227
 
76
228
  **Free-form mode** (no increment needed) applies when:
77
229
  - `SPECWEAVE_NO_INCREMENT=1` is set (via `specweave team --no-increment`)
78
- - The team_name uses a non-implementation prefix (`review-*`, `brainstorm-*`, `analysis-*`)
79
230
  - The user explicitly opted out of increment creation
80
231
 
81
- In free-form mode: **skip the rest of Section 0** and proceed directly to Step 1. Agents will work from the natural language description instead of a spec. Note: without a spec, `/sw:done` closure is not available — the team-lead simply coordinates agent completion.
232
+ In free-form mode: **skip the rest of Section 0.5** and proceed directly to Step 1. Agents will work from the natural language description instead of a spec. Note: without a spec, `/sw:done` closure is not available — the team-lead simply coordinates agent completion.
82
233
 
83
234
  ### Standard mode: Verify increment exists
84
235
 
@@ -0,0 +1,52 @@
1
+ You are the ARCHITECT PLANNING agent for increment [INCREMENT_ID].
2
+
3
+ MASTER SPEC (SOURCE OF TRUTH):
4
+ The feature is specified in [MASTER_INCREMENT_PATH]/spec.md.
5
+ Read the spec BEFORE designing anything. Your architecture MUST satisfy all ACs.
6
+
7
+ MISSION:
8
+ Produce plan.md with system architecture, component design, and ADRs for key decisions.
9
+ You own the HOW — defining the technical approach. You work in parallel with
10
+ the Security reviewer who validates your design for vulnerabilities.
11
+
12
+ SKILLS TO INVOKE:
13
+ Skill({ skill: "sw:architect" })
14
+
15
+ FILE OWNERSHIP (WRITE access):
16
+ [MASTER_INCREMENT_PATH]/plan.md
17
+ .specweave/docs/internal/architecture/adr/ (new ADRs only)
18
+
19
+ READ ACCESS: Any file in the repository
20
+
21
+ UPSTREAM DEPENDENCY:
22
+ Wait for the PM agent to signal PLAN_READY or COMPLETION before starting.
23
+ You need spec.md to exist with user stories and ACs before you can design.
24
+
25
+ WORKFLOW:
26
+ 1. Read spec.md at [MASTER_INCREMENT_PATH]/spec.md
27
+ 2. Explore the codebase to understand existing architecture, patterns, and tech stack
28
+ 3. Check existing ADRs at .specweave/docs/internal/architecture/adr/
29
+ 4. Design system architecture:
30
+ - Component boundaries and responsibilities
31
+ - Data flow and state management
32
+ - API contracts and integration points
33
+ - Error handling strategy
34
+ - Performance considerations
35
+ 5. Write ADRs for significant architectural decisions (use ADR template format)
36
+ 6. Write plan.md to [MASTER_INCREMENT_PATH]/plan.md
37
+ 7. Signal architecture decisions:
38
+ SendMessage({ type: "message", recipient: "team-lead",
39
+ content: "CONTRACT_READY: Architecture defined in plan.md.\nComponents: [list]\nKey patterns: [e.g., CQRS, event-driven]\nADRs created: [list or 'none']\nTech stack: [decisions]",
40
+ summary: "Architect: plan.md ready with architecture" })
41
+ 8. Signal COMPLETION:
42
+ SendMessage({ type: "message", recipient: "team-lead",
43
+ content: "COMPLETION: plan.md finalized.\nComponents: [count]\nADRs: [count]\nKey risk: [biggest concern]",
44
+ summary: "Architect agent: plan complete" })
45
+
46
+ RULES:
47
+ - WRITE only plan.md and ADRs — do not modify spec.md or create tasks.md
48
+ - Every architectural decision must be justified (not just "use X because it's popular")
49
+ - Consider scalability, maintainability, testability, and security
50
+ - Reference existing codebase patterns — don't propose patterns alien to the project
51
+ - Flag technical risks and mitigation strategies
52
+ - Keep plan.md actionable — an implementer should be able to code from it
@@ -0,0 +1,50 @@
1
+ You are the PM PLANNING agent for increment [INCREMENT_ID].
2
+
3
+ FEATURE DESCRIPTION: [FEATURE_DESCRIPTION]
4
+
5
+ MASTER INCREMENT PATH: [MASTER_INCREMENT_PATH]
6
+
7
+ MISSION:
8
+ Produce a comprehensive spec.md with user stories, acceptance criteria, and scope
9
+ boundaries. You own the WHAT — defining what the feature does and how success is
10
+ measured. You work in parallel with the Architect agent who owns the HOW.
11
+
12
+ SKILLS TO INVOKE:
13
+ Skill({ skill: "sw:pm" })
14
+
15
+ FILE OWNERSHIP (WRITE access):
16
+ [MASTER_INCREMENT_PATH]/spec.md
17
+
18
+ READ ACCESS: Any file in the repository (for understanding existing patterns and domain)
19
+
20
+ WORKFLOW:
21
+ 1. Read the feature description and any existing context
22
+ 2. Explore the codebase to understand the domain, existing patterns, and constraints
23
+ 3. Identify stakeholders, personas, and key use cases
24
+ 4. Write user stories with acceptance criteria following the format:
25
+ ### US-NNN: Story Title
26
+ **Project**: [project-name]
27
+ **As a** [role]
28
+ **I want** [capability]
29
+ **So that** [benefit]
30
+ **Acceptance Criteria**:
31
+ - [ ] **AC-USNN-01**: [Criterion]
32
+ 5. Define scope boundaries (in-scope vs out-of-scope)
33
+ 6. Write spec.md to [MASTER_INCREMENT_PATH]/spec.md
34
+ 7. Send PLAN_READY notification (do NOT wait for response):
35
+ SendMessage({ type: "message", recipient: "team-lead",
36
+ content: "PLAN_READY: spec.md written at [MASTER_INCREMENT_PATH]/spec.md\nUser Stories: [count]\nACs: [count]\nKey decisions: [1-2 sentence summary]",
37
+ summary: "PM: spec.md ready — proceeding" })
38
+ 8. Proceed immediately. If team-lead sends PLAN_CORRECTION, revise spec.md accordingly.
39
+ 9. Signal COMPLETION:
40
+ SendMessage({ type: "message", recipient: "team-lead",
41
+ content: "COMPLETION: spec.md finalized.\nStories: [count]\nACs: [count]\nScope: [brief summary]",
42
+ summary: "PM agent: spec complete" })
43
+
44
+ RULES:
45
+ - WRITE only spec.md — do not create plan.md or tasks.md (Architect and Planner own those)
46
+ - Every user story MUST have a **Project**: field
47
+ - Every AC MUST use the AC-USNN-NN format for bidirectional linking
48
+ - Be specific in ACs — testable, not vague ("user can log in" not "auth works")
49
+ - Consider edge cases, error states, and non-functional requirements
50
+ - Do NOT scope-creep — stick to the feature description
@@ -0,0 +1,64 @@
1
+ You are the RESEARCHER agent.
2
+
3
+ RESEARCH TOPIC: [RESEARCH_TOPIC]
4
+ RESEARCH SCOPE: [RESEARCH_SCOPE]
5
+
6
+ MISSION:
7
+ Investigate the given topic thoroughly — explore the codebase, search the web,
8
+ analyze patterns, and compile actionable findings. You are a read-only analyst.
9
+ Your job is to FIND information, not implement changes.
10
+
11
+ APPROACH:
12
+ 1. Parse the research scope to understand what information is needed
13
+ 2. Explore the codebase for relevant patterns, implementations, and conventions
14
+ 3. Search the web for related technologies, best practices, and alternatives
15
+ 4. Cross-reference findings — validate web claims against actual codebase state
16
+ 5. Compile a structured research report
17
+
18
+ YOUR REPORT MUST INCLUDE:
19
+
20
+ ### Executive Summary
21
+ 2-3 sentence overview of key findings and recommendation.
22
+
23
+ ### Current State
24
+ What exists today in the codebase. Include file paths and line references.
25
+
26
+ ### External Research
27
+ What the broader ecosystem offers. Technologies, libraries, patterns considered.
28
+ Include sources and links where relevant.
29
+
30
+ ### Analysis
31
+ Compare options. Use a decision matrix if comparing 3+ alternatives:
32
+ | Option | Pros | Cons | Effort | Fit |
33
+
34
+ ### Recommendations
35
+ Concrete, actionable recommendations ranked by priority.
36
+ Each should include: what to do, why, and estimated effort.
37
+
38
+ ### Open Questions
39
+ Things that need further investigation or user input.
40
+
41
+ COMMUNICATION:
42
+ When done, signal completion:
43
+ SendMessage({
44
+ type: "message",
45
+ recipient: "team-lead",
46
+ content: "RESEARCH_COMPLETE: [topic] research finished.\nKey finding: [most important insight]\nRecommendation: [primary recommendation]\nOpen questions: [count]",
47
+ summary: "Research complete: [topic]"
48
+ })
49
+
50
+ For significant discoveries during research:
51
+ SendMessage({
52
+ type: "message",
53
+ recipient: "team-lead",
54
+ content: "INSIGHT: [important discovery that may affect scope or approach]",
55
+ summary: "Researcher found insight"
56
+ })
57
+
58
+ RULES:
59
+ - READ-ONLY: Do not modify any files
60
+ - Be thorough: explore multiple angles, not just the first result
61
+ - Be specific: include file paths, line numbers, URLs — not vague references
62
+ - Be honest: flag uncertainty and gaps in knowledge
63
+ - Stay scoped: answer the research question, don't expand into tangential topics
64
+ - Cite sources: for web findings, include the source URL or reference
@@ -5,6 +5,7 @@ import axios from "axios";
5
5
  import { consoleLogger } from "../../specweave/lib/vendor/utils/logger.js";
6
6
  import { deriveFeatureId } from "../../specweave/lib/vendor/utils/feature-id-derivation.js";
7
7
  import { GitHubACCheckboxSync } from "../../specweave-github/lib/github-ac-checkbox-sync.js";
8
+ import { AdoDescriptionUpdater } from "../../../src/core/ado-description-updater.js";
8
9
  class AdoACCheckboxSync {
9
10
  constructor(options) {
10
11
  this.projectRoot = options.projectRoot;
@@ -88,47 +89,48 @@ class AdoACCheckboxSync {
88
89
  }
89
90
  }
90
91
  /**
91
- * Fetch current HTML description, regex-flip ☐/☑ for matching ACs, PATCH back.
92
- * Posts a comment listing all AC statuses when any AC changed.
92
+ * Update a work item's AC section using API-based section manipulation.
93
+ *
94
+ * GET description → formatACCheckboxes → updateAcSection → PATCH with
95
+ * JSON Patch op:"replace". No regex used at any point.
93
96
  */
94
- async updateStoryCheckboxes(client, adoConfig, storyId, acStatus) {
97
+ async updateWorkItemACSection(client, storyId, acStatus) {
98
+ const updater = new AdoDescriptionUpdater();
95
99
  const resp = await client.get(
96
100
  `/wit/workitems/${storyId}?fields=System.Description&api-version=7.0`
97
101
  );
98
- let description = resp.data?.fields?.["System.Description"] ?? "";
99
- const original = description;
100
- let updatedCount = 0;
101
- for (const [acId, completed] of acStatus) {
102
- const escaped = acId.replace(/-/g, "\\-");
103
- const beforeRegex = new RegExp(`(\u2610|\u2611)\\s+(${escaped}:)`, "g");
104
- const newCheckbox = completed ? "\u2611" : "\u2610";
105
- const replaced = description.replace(beforeRegex, `${newCheckbox} $2`);
106
- if (replaced !== description) {
107
- updatedCount++;
108
- description = replaced;
109
- }
110
- }
111
- if (description === original) return 0;
102
+ const currentDescription = resp.data?.fields?.["System.Description"] ?? "";
103
+ const newAcHtml = updater.formatACCheckboxes(acStatus);
104
+ if (!newAcHtml) return 0;
105
+ const updatedDescription = updater.updateAcSection(currentDescription, newAcHtml);
106
+ if (updatedDescription === currentDescription) return 0;
112
107
  await client.patch(
113
108
  `/wit/workitems/${storyId}?api-version=7.0`,
114
- [{ op: "replace", path: "/fields/System.Description", value: description }],
109
+ [{ op: "replace", path: "/fields/System.Description", value: updatedDescription }],
115
110
  { headers: { "Content-Type": "application/json-patch+json" } }
116
111
  );
117
112
  const completedCount = [...acStatus.values()].filter(Boolean).length;
118
113
  const totalCount = acStatus.size;
119
114
  const percentage = Math.round(completedCount / totalCount * 100);
120
115
  const acLines = [...acStatus.entries()].map(([id, done]) => `<li>${done ? "\u2705" : "\u2B1C"} ${id}</li>`).join("\n");
121
- const commentHtml = `<h3>\u{1F4CA} AC Progress Update</h3>
116
+ const commentHtml = `<h3>AC Progress Update</h3>
122
117
  <p><strong>Acceptance Criteria</strong>: ${completedCount}/${totalCount} (${percentage}%)</p>
123
118
  <ul>
124
119
  ${acLines}
125
120
  </ul>
126
- <p>\u{1F916} Auto-updated by SpecWeave AC Completion Gate</p>`;
121
+ <p>Auto-updated by SpecWeave</p>`;
127
122
  await client.post(
128
123
  `/wit/workItems/${storyId}/comments?api-version=7.1-preview.3`,
129
124
  { text: commentHtml }
130
125
  );
131
- return updatedCount;
126
+ return acStatus.size;
127
+ }
128
+ /**
129
+ * Legacy: Fetch current HTML description, regex-flip checkboxes, PATCH back.
130
+ * Kept for backward compatibility. New code should use updateWorkItemACSection.
131
+ */
132
+ async updateStoryCheckboxes(client, adoConfig, storyId, acStatus) {
133
+ return this.updateWorkItemACSection(client, storyId, acStatus);
132
134
  }
133
135
  buildClient(adoConfig) {
134
136
  const token = Buffer.from(`:${adoConfig.pat}`).toString("base64");
@@ -2,10 +2,10 @@
2
2
  * ADO AC Checkbox Sync
3
3
  *
4
4
  * When ACs are marked complete in spec.md, updates the HTML description
5
- * of the linked ADO work item (☐ ☑) and posts a progress comment.
5
+ * of the linked ADO work item using API-based section update (not regex).
6
6
  *
7
- * Mirrors jira-ac-checkbox-sync.ts pattern for ADO.
8
- * The ADO description is HTML — we use regex to flip ☐/☑ by AC ID.
7
+ * Uses AdoDescriptionUpdater for clean HTML section manipulation via
8
+ * sentinel comments (<!-- AC_SECTION_START/END -->).
9
9
  */
10
10
 
11
11
  import { promises as fs, existsSync } from 'fs';
@@ -15,6 +15,7 @@ import axios, { AxiosInstance } from 'axios';
15
15
  import { Logger, consoleLogger } from '../../specweave/lib/vendor/utils/logger.js';
16
16
  import { deriveFeatureId } from '../../specweave/lib/vendor/utils/feature-id-derivation.js';
17
17
  import { GitHubACCheckboxSync } from '../../specweave-github/lib/github-ac-checkbox-sync.js';
18
+ import { AdoDescriptionUpdater } from '../../../src/core/ado-description-updater.js';
18
19
  import type { SpecWeaveConfig } from '../../../src/core/config/types.js';
19
20
  import type { LivingDocsUSFile } from '../../../src/types/living-docs-us-file.js';
20
21
 
@@ -131,41 +132,35 @@ export class AdoACCheckboxSync {
131
132
  }
132
133
 
133
134
  /**
134
- * Fetch current HTML description, regex-flip ☐/☑ for matching ACs, PATCH back.
135
- * Posts a comment listing all AC statuses when any AC changed.
135
+ * Update a work item's AC section using API-based section manipulation.
136
+ *
137
+ * GET description → formatACCheckboxes → updateAcSection → PATCH with
138
+ * JSON Patch op:"replace". No regex used at any point.
136
139
  */
137
- private async updateStoryCheckboxes(
140
+ async updateWorkItemACSection(
138
141
  client: AxiosInstance,
139
- adoConfig: { organization: string; project: string; pat: string },
140
142
  storyId: number,
141
- acStatus: Map<string, boolean>
143
+ acStatus: Map<string, boolean>,
142
144
  ): Promise<number> {
145
+ const updater = new AdoDescriptionUpdater();
146
+
143
147
  const resp = await client.get(
144
148
  `/wit/workitems/${storyId}?fields=System.Description&api-version=7.0`
145
149
  );
146
150
 
147
- let description: string = resp.data?.fields?.['System.Description'] ?? '';
148
- const original = description;
149
- let updatedCount = 0;
150
-
151
- for (const [acId, completed] of acStatus) {
152
- const escaped = acId.replace(/-/g, '\\-');
153
- // Pattern: ☐ AC-US1-01: or ☑ AC-US1-01:
154
- const beforeRegex = new RegExp(`(☐|☑)\\s+(${escaped}:)`, 'g');
155
- const newCheckbox = completed ? '☑' : '☐';
156
- const replaced = description.replace(beforeRegex, `${newCheckbox} $2`);
157
- if (replaced !== description) {
158
- updatedCount++;
159
- description = replaced;
160
- }
161
- }
151
+ const currentDescription: string = resp.data?.fields?.['System.Description'] ?? '';
152
+ const newAcHtml = updater.formatACCheckboxes(acStatus);
153
+
154
+ if (!newAcHtml) return 0;
162
155
 
163
- if (description === original) return 0;
156
+ const updatedDescription = updater.updateAcSection(currentDescription, newAcHtml);
164
157
 
165
- // PATCH description
158
+ if (updatedDescription === currentDescription) return 0;
159
+
160
+ // PATCH description via JSON Patch
166
161
  await client.patch(
167
162
  `/wit/workitems/${storyId}?api-version=7.0`,
168
- [{ op: 'replace', path: '/fields/System.Description', value: description }],
163
+ [{ op: 'replace', path: '/fields/System.Description', value: updatedDescription }],
169
164
  { headers: { 'Content-Type': 'application/json-patch+json' } }
170
165
  );
171
166
 
@@ -178,19 +173,32 @@ export class AdoACCheckboxSync {
178
173
  .map(([id, done]) => `<li>${done ? '✅' : '⬜'} ${id}</li>`)
179
174
  .join('\n');
180
175
 
181
- const commentHtml = `<h3>📊 AC Progress Update</h3>
176
+ const commentHtml = `<h3>AC Progress Update</h3>
182
177
  <p><strong>Acceptance Criteria</strong>: ${completedCount}/${totalCount} (${percentage}%)</p>
183
178
  <ul>
184
179
  ${acLines}
185
180
  </ul>
186
- <p>🤖 Auto-updated by SpecWeave AC Completion Gate</p>`;
181
+ <p>Auto-updated by SpecWeave</p>`;
187
182
 
188
183
  await client.post(
189
184
  `/wit/workItems/${storyId}/comments?api-version=7.1-preview.3`,
190
185
  { text: commentHtml }
191
186
  );
192
187
 
193
- return updatedCount;
188
+ return acStatus.size;
189
+ }
190
+
191
+ /**
192
+ * Legacy: Fetch current HTML description, regex-flip checkboxes, PATCH back.
193
+ * Kept for backward compatibility. New code should use updateWorkItemACSection.
194
+ */
195
+ private async updateStoryCheckboxes(
196
+ client: AxiosInstance,
197
+ adoConfig: { organization: string; project: string; pat: string },
198
+ storyId: number,
199
+ acStatus: Map<string, boolean>
200
+ ): Promise<number> {
201
+ return this.updateWorkItemACSection(client, storyId, acStatus);
194
202
  }
195
203
 
196
204
  private buildClient(adoConfig: { organization: string; project: string; pat: string }): AxiosInstance {
@@ -3,6 +3,7 @@ class AdoClient {
3
3
  constructor(config) {
4
4
  this.config = config;
5
5
  this.baseUrl = `https://dev.azure.com/${config.organization}/${config.project}`;
6
+ this.rateLimiter = config.rateLimiter;
6
7
  this.authHeader = "Basic " + Buffer.from(`:${config.personalAccessToken}`).toString("base64");
7
8
  }
8
9
  // ==========================================================================
@@ -114,6 +115,20 @@ class AdoClient {
114
115
  const url = `${this.baseUrl}/_apis/wit/workitems/${id}?api-version=7.1`;
115
116
  await this.request("DELETE", url);
116
117
  }
118
+ /**
119
+ * Pull the current state of a work item for bidirectional sync.
120
+ *
121
+ * @param id - ADO work item ID
122
+ * @returns state and last-modified timestamp
123
+ */
124
+ async pullWorkItemState(id) {
125
+ const url = `${this.baseUrl}/_apis/wit/workitems/${id}?$select=System.State,System.ChangedDate&api-version=7.1`;
126
+ const item = await this.request("GET", url);
127
+ return {
128
+ state: item.fields["System.State"],
129
+ modifiedAt: new Date(item.fields["System.ChangedDate"])
130
+ };
131
+ }
117
132
  // ==========================================================================
118
133
  // Comment Operations
119
134
  // ==========================================================================
@@ -166,6 +181,9 @@ class AdoClient {
166
181
  * Make HTTP request to ADO API
167
182
  */
168
183
  async request(method, url, body, additionalHeaders) {
184
+ if (this.rateLimiter && !this.rateLimiter.consume()) {
185
+ throw new Error("ADO rate limit exceeded \u2014 try again later");
186
+ }
169
187
  return new Promise((resolve, reject) => {
170
188
  const urlObj = new URL(url);
171
189
  const options = {
@@ -196,6 +214,12 @@ class AdoClient {
196
214
  reject(new Error(`Failed to parse JSON response: ${error}`));
197
215
  }
198
216
  } else {
217
+ if (res.statusCode === 429 && this.rateLimiter) {
218
+ const retryAfter = parseInt(res.headers["retry-after"], 10);
219
+ if (retryAfter > 0) {
220
+ this.rateLimiter.applyRetryAfter(retryAfter);
221
+ }
222
+ }
199
223
  let errorMessage = `ADO API error: ${res.statusCode} ${res.statusMessage}`;
200
224
  try {
201
225
  const errorData = JSON.parse(data);
@@ -204,7 +228,9 @@ class AdoClient {
204
228
  }
205
229
  } catch {
206
230
  }
207
- reject(new Error(errorMessage));
231
+ const err = new Error(errorMessage);
232
+ err.status = res.statusCode;
233
+ reject(err);
208
234
  }
209
235
  });
210
236
  });