specweave 1.0.443 → 1.0.444

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "specweave",
3
- "version": "1.0.443",
3
+ "version": "1.0.444",
4
4
  "description": "100+ domain-expert AI skills — PM, Architect, Frontend, QA, Security and more. Skills learn your team's patterns permanently. Spec-first planning, autonomous execution, multi-agent teams, synced to GitHub/JIRA. Claude Code, Cursor, Copilot & more.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -0,0 +1 @@
1
+ {"timestamp":"2026-01-04T16:11:43Z","event":"session_stop","reason":"No auto session active","details":"approve_called:main","success":false,"iteration":0,"increment":"none"}
@@ -0,0 +1 @@
1
+ {"timestamp":"2026-01-04T16:11:43Z","sessionId":"unknown","reason":"No auto session active","details":"approve_called:main","success":false,"iteration":0,"increment":"none","testsRun":false,"testsPassed":0,"testsFailed":0}
@@ -0,0 +1,15 @@
1
+ {
2
+ "ran": false,
3
+ "inputSummary": {
4
+ "transcriptLines": 266
5
+ },
6
+ "extracted": {
7
+ "skillLearnings": []
8
+ },
9
+ "written": {
10
+ "learningsAdded": 0,
11
+ "learningsSkippedDuplicate": 0
12
+ },
13
+ "durationMs": 1.4448749999999997,
14
+ "reason": "CLAUDE.md not found in project"
15
+ }
@@ -0,0 +1,3 @@
1
+ [2026-02-03T22:03:06Z] [info] Starting reflection (265 lines)
2
+ [2026-02-03T22:03:06Z] [info] Reflection started in background
3
+ [2026-02-03T22:03:06Z] [info] Reflection completed - no learnings
@@ -0,0 +1 @@
1
+ [2026-02-03T22:03:06Z] APPROVE: No increments directory
@@ -166,15 +166,14 @@ Execute: `Skill({ skill: "sw:sync-docs" })` with the increment ID. Do NOT just m
166
166
 
167
167
  ### Step 10b: Update Links in Docs (MANDATORY)
168
168
 
169
- After living docs sync, update cross-references and bidirectional links so existing docs reference the newly created feature specs.
169
+ After living docs sync, update cross-references and bidirectional links so existing docs reference the newly created feature specs. Do NOT skip this step:
170
170
 
171
- Execute: `Skill({ skill: "sw:docs-updater" })` this verifies and repairs links between living docs, feature specs, and increment references. Do NOT skip this step. The docs-updater:
172
- 1. Reads the feature spec files created by Step 10
173
- 2. Updates existing docs (FEATURE-CATALOG, module docs, etc.) with links to the new specs
174
- 3. Verifies bidirectional links between increment feature spec living docs
175
- 4. Changes `[DRAFT]` → `[COMPLETE]` on doc sections matching completed ACs
171
+ 1. Read the feature spec files created by Step 10 (`.specweave/docs/internal/specs/{project}/FS-XXX/FEATURE.md` and `us-*.md`)
172
+ 2. Update existing docs (FEATURE-CATALOG, module docs, etc.) with links to the new specs
173
+ 3. Verify bidirectional links between increment feature spec living docs
174
+ 4. Change `[DRAFT]` `[COMPLETE]` on doc sections matching completed ACs
176
175
 
177
- If `sw:docs-updater` is unavailable, manually verify that `.specweave/docs/internal/specs/{project}/FS-XXX/` contains `FEATURE.md` and `us-*.md` files. If missing, re-run Step 10.
176
+ Verify that `.specweave/docs/internal/specs/{project}/FS-XXX/` contains `FEATURE.md` and `us-*.md` files. If missing, re-run Step 10.
178
177
 
179
178
  ### Step 11: Post-Closure Quality Assessment
180
179
 
@@ -50,7 +50,7 @@ STEP 1: Pre-flight (TDD mode, multi-project, Deep Interview check)
50
50
  STEP 2: Project Context (resolve project/board)
51
51
  STEP 3: Create Increment (via Template API) ← folder + ID exist after this
52
52
  STEP 3a: Deep Interview (if enabled) ← runs AFTER folder exists
53
- STEP 4: Delegation (architect + test-aware-planner)
53
+ STEP 4: Delegation (architect + planner)
54
54
  STEP 5: Post-Creation Sync
55
55
  STEP 6: Execution Strategy Recommendation
56
56
  ```
@@ -17,7 +17,7 @@ description: Generate plan.md and tasks.md for increment. Use when saying "creat
17
17
 
18
18
  ---
19
19
 
20
- Generate `plan.md` and `tasks.md` for an increment using Architect Agent and test-aware-planner.
20
+ Generate `plan.md` and `tasks.md` for an increment using Architect Agent.
21
21
 
22
22
  ## Usage
23
23
 
@@ -68,7 +68,7 @@ Generate `plan.md` and `tasks.md` for an increment using Architect Agent and tes
68
68
  - Dependencies
69
69
  - Risk assessment
70
70
 
71
- 4. **Generate tasks.md** (via test-aware-planner):
71
+ 4. **Generate tasks.md**:
72
72
  - Checkable task list
73
73
  - Embedded test plans (BDD format)
74
74
  - Coverage targets
@@ -227,7 +227,7 @@ Planning for framework features requires different considerations than user apps
227
227
  - `IncrementDetector`: Auto-detect or validate increment
228
228
  - `PlanValidator`: Validate pre-conditions
229
229
  - `ArchitectAgentInvoker`: Generate plan.md via Architect Agent
230
- - `TaskGeneratorInvoker`: Generate tasks.md via test-aware-planner
230
+ - `TaskGeneratorInvoker`: Generate tasks.md with BDD test plans
231
231
  - `PlanCommandOrchestrator`: Coordinate execution pipeline
232
232
 
233
233
  **State transitions**:
@@ -373,7 +373,6 @@ ${userStory.technicalContext}
373
373
  return mapping.task || "Task";
374
374
  case "Subtask":
375
375
  return mapping.task || "Task";
376
- // ADO doesn't have subtasks, use Task
377
376
  default:
378
377
  return "User Story";
379
378
  }
@@ -0,0 +1,180 @@
1
+ import { AdoClientV2 } from "./ado-client-v2.js";
2
+ import { EnhancedContentBuilder } from "../../../src/core/sync/enhanced-content-builder.js";
3
+ import { SpecIncrementMapper } from "../../../src/core/sync/spec-increment-mapper.js";
4
+ import { parseSpecContent } from "../../../src/core/spec-content-sync.js";
5
+ import path from "path";
6
+ import fs from "fs/promises";
7
+ async function syncSpecToAdoWithEnhancedContent(options) {
8
+ const { specPath, organization, project, dryRun = false, verbose = false } = options;
9
+ try {
10
+ const baseSpec = await parseSpecContent(specPath);
11
+ if (!baseSpec) {
12
+ return {
13
+ success: false,
14
+ action: "error",
15
+ error: "Failed to parse spec content"
16
+ };
17
+ }
18
+ if (verbose) {
19
+ console.log(`\u{1F4C4} Parsed spec: ${baseSpec.identifier.compact}`);
20
+ }
21
+ const specId = baseSpec.identifier.full || baseSpec.identifier.compact;
22
+ const rootDir = await findSpecWeaveRoot(specPath);
23
+ const mapper = new SpecIncrementMapper(rootDir);
24
+ const mapping = await mapper.mapSpecToIncrements(specId);
25
+ if (verbose) {
26
+ console.log(`\u{1F517} Found ${mapping.increments.length} related increments`);
27
+ }
28
+ const taskMapping = buildTaskMapping(mapping.increments, organization, project);
29
+ const architectureDocs = await findArchitectureDocs(rootDir, specId);
30
+ const enhancedSpec = {
31
+ ...baseSpec,
32
+ summary: baseSpec.description,
33
+ taskMapping,
34
+ architectureDocs
35
+ };
36
+ const builder = new EnhancedContentBuilder();
37
+ const description = builder.buildExternalDescription(enhancedSpec);
38
+ if (verbose) {
39
+ console.log(`\u{1F4DD} Generated description: ${description.length} characters`);
40
+ }
41
+ if (dryRun) {
42
+ console.log("\u{1F50D} DRY RUN - Would create/update feature with:");
43
+ console.log(` Title: ${baseSpec.title}`);
44
+ console.log(` Description length: ${description.length}`);
45
+ return {
46
+ success: true,
47
+ action: "no-change",
48
+ tasksLinked: taskMapping?.tasks.length || 0
49
+ };
50
+ }
51
+ if (!organization || !project) {
52
+ return {
53
+ success: false,
54
+ action: "error",
55
+ error: "Azure DevOps organization/project not specified"
56
+ };
57
+ }
58
+ const profile = {
59
+ provider: "ado",
60
+ displayName: `${organization}/${project}`,
61
+ config: {
62
+ organization,
63
+ project
64
+ },
65
+ timeRange: { default: "1M", max: "6M" }
66
+ };
67
+ const pat = process.env.AZURE_DEVOPS_PAT || "";
68
+ const client = new AdoClientV2(profile, pat);
69
+ const existingFeature = await findExistingFeature(client, baseSpec.identifier.compact);
70
+ let result;
71
+ if (existingFeature) {
72
+ await client.updateWorkItem(existingFeature.id, {
73
+ title: `[${baseSpec.identifier.compact}] ${baseSpec.title}`,
74
+ description
75
+ });
76
+ result = {
77
+ success: true,
78
+ action: "updated",
79
+ featureId: existingFeature.id,
80
+ featureUrl: `https://dev.azure.com/${organization}/${project}/_workitems/edit/${existingFeature.id}`,
81
+ tasksLinked: taskMapping?.tasks.length || 0
82
+ };
83
+ } else {
84
+ const feature = await client.createEpic({
85
+ title: `[${baseSpec.identifier.compact}] ${baseSpec.title}`,
86
+ description,
87
+ tags: ["spec", "external-tool-sync"]
88
+ });
89
+ result = {
90
+ success: true,
91
+ action: "created",
92
+ featureId: feature.id,
93
+ featureUrl: `https://dev.azure.com/${organization}/${project}/_workitems/edit/${feature.id}`,
94
+ tasksLinked: taskMapping?.tasks.length || 0
95
+ };
96
+ }
97
+ if (verbose) {
98
+ console.log(`\u2705 ${result.action === "created" ? "Created" : "Updated"} feature #${result.featureId}`);
99
+ }
100
+ return result;
101
+ } catch (error) {
102
+ return {
103
+ success: false,
104
+ action: "error",
105
+ error: error.message
106
+ };
107
+ }
108
+ }
109
+ async function findSpecWeaveRoot(specPath) {
110
+ let currentDir = path.dirname(specPath);
111
+ while (true) {
112
+ const specweaveDir = path.join(currentDir, ".specweave");
113
+ try {
114
+ await fs.access(specweaveDir);
115
+ return currentDir;
116
+ } catch {
117
+ const parentDir = path.dirname(currentDir);
118
+ if (parentDir === currentDir) {
119
+ throw new Error(".specweave directory not found");
120
+ }
121
+ currentDir = parentDir;
122
+ }
123
+ }
124
+ }
125
+ function buildTaskMapping(increments, organization, project) {
126
+ if (increments.length === 0) return void 0;
127
+ const firstIncrement = increments[0];
128
+ const tasks = firstIncrement.tasks.map((task) => ({
129
+ id: task.id,
130
+ title: task.title,
131
+ userStories: task.userStories
132
+ }));
133
+ // Derive repository name from git remote or fall back to project name
134
+ let repoName = project;
135
+ try {
136
+ const { execSync } = require("child_process");
137
+ const remoteUrl = execSync("git remote get-url origin", { encoding: "utf-8" }).trim();
138
+ const match = remoteUrl.match(/\/([^/]+?)(?:\.git)?$/);
139
+ if (match) repoName = match[1];
140
+ } catch {
141
+ // Fallback to project name if git is unavailable
142
+ }
143
+ return {
144
+ incrementId: firstIncrement.id,
145
+ tasks,
146
+ tasksUrl: `https://dev.azure.com/${organization}/${project}/_git/${repoName}?path=/.specweave/increments/${firstIncrement.id}/tasks.md`
147
+ };
148
+ }
149
+ async function findArchitectureDocs(rootDir, specId) {
150
+ const docs = [];
151
+ const archDir = path.join(rootDir, ".specweave/docs/internal/architecture");
152
+ try {
153
+ const adrDir = path.join(archDir, "adr");
154
+ try {
155
+ const adrs = await fs.readdir(adrDir);
156
+ const relatedAdrs = adrs.filter((file) => file.includes(specId.replace("spec-", "")));
157
+ for (const adr of relatedAdrs) {
158
+ docs.push({
159
+ type: "adr",
160
+ path: path.join(adrDir, adr),
161
+ title: adr.replace(".md", "").replace(/-/g, " ")
162
+ });
163
+ }
164
+ } catch {
165
+ }
166
+ } catch {
167
+ }
168
+ return docs;
169
+ }
170
+ async function findExistingFeature(client, specId) {
171
+ try {
172
+ const features = await client.queryWorkItems(`[System.Title] Contains '[${specId}]' AND [System.WorkItemType] = 'Feature'`);
173
+ return features[0] || null;
174
+ } catch {
175
+ return null;
176
+ }
177
+ }
178
+ export {
179
+ syncSpecToAdoWithEnhancedContent
180
+ };