specweave 1.0.67 ā 1.0.68
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.
|
|
3
|
+
"version": "1.0.68",
|
|
4
4
|
"description": "Spec-driven development framework for Claude Code. AI-native workflow with living documentation, intelligent agents, and multilingual support (9 languages). Enterprise-grade traceability with permanent specs and temporary increments.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -13,6 +13,14 @@ description: Start autonomous execution session with stop hook integration. Work
|
|
|
13
13
|
/sw:auto [INCREMENT_IDS...] [OPTIONS]
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
+
:::tip š Claude Code's Game-Changing Features for Auto Mode
|
|
17
|
+
**Compact Command (VSCode)** ā Use `compact` mode to keep Claude Code inside your VSCode window. Work continuously for **hours** in the same session without context switching between terminal and editor. Perfect for long auto mode sessions!
|
|
18
|
+
|
|
19
|
+
**STOP Hooks with Subagents** ā Stop hooks now work with spawned subagents! This means `/sw:auto` can validate quality gates at EVERY level of execution. When auto mode spawns specialized agents (QA, Security, Performance), the stop hook validates their results before allowing the session to continue.
|
|
20
|
+
|
|
21
|
+
**Real-world proof**: Boris Cherny (Claude Code creator) shipped 259 PRs, 497 commits, 40,000 lines in one month without opening an IDE ā using autonomous execution with stop hooks. [See demo](https://x.com/bcherny/status/2004916410687050167)
|
|
22
|
+
:::
|
|
23
|
+
|
|
16
24
|
## Arguments
|
|
17
25
|
|
|
18
26
|
- `INCREMENT_IDS`: One or more increment IDs to process (e.g., `0001`, `0001-feature`)
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { ACStatusManager } from "../vendor/core/increment/ac-status-manager.js";
|
|
3
|
+
import { SyncCoordinator } from "../../../../dist/src/sync/sync-coordinator.js";
|
|
4
|
+
import { consoleLogger } from "../vendor/utils/logger.js";
|
|
5
|
+
import { readFileSync, existsSync } from "fs";
|
|
6
|
+
import * as path from "path";
|
|
3
7
|
async function updateACStatus(incrementId) {
|
|
4
8
|
try {
|
|
5
9
|
const projectRoot = process.cwd();
|
|
@@ -25,6 +29,7 @@ async function updateACStatus(incrementId) {
|
|
|
25
29
|
console.log("\n\u{1F4DD} Changes:");
|
|
26
30
|
result.changes.forEach((change) => console.log(` ${change}`));
|
|
27
31
|
}
|
|
32
|
+
await syncACsToGitHub(projectRoot, incrementId);
|
|
28
33
|
} else if (result.synced) {
|
|
29
34
|
console.log("\u2705 All ACs already in sync (no changes needed)");
|
|
30
35
|
} else {
|
|
@@ -34,6 +39,51 @@ async function updateACStatus(incrementId) {
|
|
|
34
39
|
console.error("\u274C Error updating AC status:", error);
|
|
35
40
|
}
|
|
36
41
|
}
|
|
42
|
+
async function syncACsToGitHub(projectRoot, incrementId) {
|
|
43
|
+
try {
|
|
44
|
+
const configPath = path.join(projectRoot, ".specweave/config.json");
|
|
45
|
+
if (!existsSync(configPath)) {
|
|
46
|
+
console.log("\u2139\uFE0F No config.json found, skipping GitHub sync");
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
const configContent = readFileSync(configPath, "utf-8");
|
|
50
|
+
const config = JSON.parse(configContent);
|
|
51
|
+
const isGitHubEnabled = config.sync?.github?.enabled || config.sync?.profiles && Object.values(config.sync.profiles).some(
|
|
52
|
+
(p) => p?.provider === "github"
|
|
53
|
+
) || config.sync?.provider === "github";
|
|
54
|
+
if (!isGitHubEnabled) {
|
|
55
|
+
console.log("\u2139\uFE0F GitHub sync not enabled, skipping");
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
const canUpdateExternal = config.sync?.settings?.canUpdateExternalItems !== false;
|
|
59
|
+
if (!canUpdateExternal) {
|
|
60
|
+
console.log("\u2139\uFE0F canUpdateExternalItems=false, skipping GitHub sync");
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
console.log("\n\u{1F517} Syncing AC checkboxes to GitHub...");
|
|
64
|
+
const coordinator = new SyncCoordinator({
|
|
65
|
+
projectRoot,
|
|
66
|
+
incrementId,
|
|
67
|
+
logger: consoleLogger
|
|
68
|
+
});
|
|
69
|
+
const syncResult = await coordinator.syncACCheckboxesToGitHub(config, {
|
|
70
|
+
addComment: false
|
|
71
|
+
// Don't add comment on every AC update (prevent spam)
|
|
72
|
+
});
|
|
73
|
+
if (syncResult.success && syncResult.updated > 0) {
|
|
74
|
+
console.log(` \u2705 Updated ${syncResult.updated} AC(s) in GitHub issues`);
|
|
75
|
+
if (syncResult.issues.length > 0) {
|
|
76
|
+
console.log(` \u{1F4DD} Issues updated: ${syncResult.issues.join(", ")}`);
|
|
77
|
+
}
|
|
78
|
+
} else if (syncResult.success) {
|
|
79
|
+
console.log(" \u2139\uFE0F No GitHub updates needed");
|
|
80
|
+
} else {
|
|
81
|
+
console.log(" \u26A0\uFE0F GitHub sync had errors (non-blocking)");
|
|
82
|
+
}
|
|
83
|
+
} catch (error) {
|
|
84
|
+
console.log(` \u26A0\uFE0F GitHub sync failed: ${error.message}`);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
37
87
|
const isMainModule = import.meta.url === `file://${process.argv[1]}`;
|
|
38
88
|
if (isMainModule) {
|
|
39
89
|
const incrementId = process.argv[2];
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* - Warns about orphaned ACs (no implementing tasks)
|
|
10
10
|
* - Provides detailed sync result with diff
|
|
11
11
|
* - Atomic file writes to prevent corruption
|
|
12
|
+
* - **NEW v1.0.68**: Auto-syncs AC checkboxes to GitHub issues
|
|
12
13
|
*
|
|
13
14
|
* Flow:
|
|
14
15
|
* 1. Parse tasks.md ā Map AC-IDs to completion status
|
|
@@ -16,17 +17,23 @@
|
|
|
16
17
|
* 3. Compare task completion vs spec checkboxes
|
|
17
18
|
* 4. Update spec.md only for 100% complete ACs
|
|
18
19
|
* 5. Log conflicts, warnings, and changes
|
|
20
|
+
* 6. **NEW**: Sync updated ACs to linked GitHub issues
|
|
19
21
|
*
|
|
20
22
|
* Called by: plugins/specweave/hooks/post-task-completion.sh
|
|
21
23
|
*
|
|
22
24
|
* Example:
|
|
23
25
|
* - Tasks: T-001 [x], T-002 [x] (both have AC-US1-01) ā AC-US1-01 100% complete
|
|
24
26
|
* - spec.md: - [ ] AC-US1-01 ā - [x] AC-US1-01 ā
|
|
27
|
+
* - GitHub issue: - [ ] **AC-US1-01** ā - [x] **AC-US1-01** š
|
|
25
28
|
* - Tasks: T-003 [x], T-004 [ ] (both have AC-US1-02) ā AC-US1-02 50% complete
|
|
26
29
|
* - spec.md: - [ ] AC-US1-02 ā NO CHANGE (partial completion)
|
|
27
30
|
*/
|
|
28
31
|
|
|
29
32
|
import { ACStatusManager } from '../vendor/core/increment/ac-status-manager.js';
|
|
33
|
+
import { SyncCoordinator } from '../../../../dist/src/sync/sync-coordinator.js';
|
|
34
|
+
import { consoleLogger } from '../vendor/utils/logger.js';
|
|
35
|
+
import { readFileSync, existsSync } from 'fs';
|
|
36
|
+
import * as path from 'path';
|
|
30
37
|
|
|
31
38
|
/**
|
|
32
39
|
* Main entry point - uses ACStatusManager for sophisticated sync
|
|
@@ -68,6 +75,9 @@ async function updateACStatus(incrementId: string): Promise<void> {
|
|
|
68
75
|
console.log('\nš Changes:');
|
|
69
76
|
result.changes.forEach((change: string) => console.log(` ${change}`));
|
|
70
77
|
}
|
|
78
|
+
|
|
79
|
+
// NEW v1.0.68: Auto-sync AC checkboxes to GitHub issues
|
|
80
|
+
await syncACsToGitHub(projectRoot, incrementId);
|
|
71
81
|
} else if (result.synced) {
|
|
72
82
|
console.log('ā
All ACs already in sync (no changes needed)');
|
|
73
83
|
} else {
|
|
@@ -80,6 +90,79 @@ async function updateACStatus(incrementId: string): Promise<void> {
|
|
|
80
90
|
}
|
|
81
91
|
}
|
|
82
92
|
|
|
93
|
+
/**
|
|
94
|
+
* Sync AC checkboxes to GitHub issues (v1.0.68)
|
|
95
|
+
*
|
|
96
|
+
* CRITICAL FIX: Previously, AC completion only updated spec.md locally.
|
|
97
|
+
* GitHub issues were NOT updated until manual /sw:sync-progress was run.
|
|
98
|
+
* This fixes issue #966 by auto-syncing to GitHub after AC updates.
|
|
99
|
+
*
|
|
100
|
+
* @param projectRoot - Project root directory
|
|
101
|
+
* @param incrementId - Increment ID
|
|
102
|
+
*/
|
|
103
|
+
async function syncACsToGitHub(projectRoot: string, incrementId: string): Promise<void> {
|
|
104
|
+
try {
|
|
105
|
+
// Check if GitHub sync is enabled in config
|
|
106
|
+
const configPath = path.join(projectRoot, '.specweave/config.json');
|
|
107
|
+
if (!existsSync(configPath)) {
|
|
108
|
+
console.log('ā¹ļø No config.json found, skipping GitHub sync');
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const configContent = readFileSync(configPath, 'utf-8');
|
|
113
|
+
const config = JSON.parse(configContent);
|
|
114
|
+
|
|
115
|
+
// Check for GitHub sync enabled
|
|
116
|
+
const isGitHubEnabled =
|
|
117
|
+
config.sync?.github?.enabled ||
|
|
118
|
+
(config.sync?.profiles && Object.values(config.sync.profiles).some(
|
|
119
|
+
(p: any) => p?.provider === 'github'
|
|
120
|
+
)) ||
|
|
121
|
+
config.sync?.provider === 'github';
|
|
122
|
+
|
|
123
|
+
if (!isGitHubEnabled) {
|
|
124
|
+
console.log('ā¹ļø GitHub sync not enabled, skipping');
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Check if external sync is allowed
|
|
129
|
+
const canUpdateExternal = config.sync?.settings?.canUpdateExternalItems !== false;
|
|
130
|
+
if (!canUpdateExternal) {
|
|
131
|
+
console.log('ā¹ļø canUpdateExternalItems=false, skipping GitHub sync');
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
console.log('\nš Syncing AC checkboxes to GitHub...');
|
|
136
|
+
|
|
137
|
+
// Use SyncCoordinator for GitHub sync
|
|
138
|
+
const coordinator = new SyncCoordinator({
|
|
139
|
+
projectRoot,
|
|
140
|
+
incrementId,
|
|
141
|
+
logger: consoleLogger
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
const syncResult = await coordinator.syncACCheckboxesToGitHub(config, {
|
|
145
|
+
addComment: false // Don't add comment on every AC update (prevent spam)
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
if (syncResult.success && syncResult.updated > 0) {
|
|
149
|
+
console.log(` ā
Updated ${syncResult.updated} AC(s) in GitHub issues`);
|
|
150
|
+
if (syncResult.issues.length > 0) {
|
|
151
|
+
console.log(` š Issues updated: ${syncResult.issues.join(', ')}`);
|
|
152
|
+
}
|
|
153
|
+
} else if (syncResult.success) {
|
|
154
|
+
console.log(' ā¹ļø No GitHub updates needed');
|
|
155
|
+
} else {
|
|
156
|
+
console.log(' ā ļø GitHub sync had errors (non-blocking)');
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
} catch (error: any) {
|
|
160
|
+
// Non-blocking: Log but don't fail the hook
|
|
161
|
+
console.log(` ā ļø GitHub sync failed: ${error.message}`);
|
|
162
|
+
// Continue - local AC sync already succeeded
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
83
166
|
// CLI Entry Point (ES Module)
|
|
84
167
|
const isMainModule = import.meta.url === `file://${process.argv[1]}`;
|
|
85
168
|
|