specweave 1.0.334 → 1.0.336
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/bin/specweave.js +15 -0
- package/dist/src/cli/commands/sync-living-docs.d.ts +20 -0
- package/dist/src/cli/commands/sync-living-docs.d.ts.map +1 -0
- package/dist/src/cli/commands/sync-living-docs.js +129 -0
- package/dist/src/cli/commands/sync-living-docs.js.map +1 -0
- package/package.json +1 -1
- package/plugins/specweave/commands/sync-setup.md +2 -6
- package/plugins/specweave/skills/sync-docs/SKILL.md +5 -6
- package/plugins/specweave-ado/skills/ado-resource-validator/SKILL.md +4 -10
- package/plugins/specweave-github/commands/sync.md +3 -3
- package/plugins/specweave-jira/skills/jira-resource-validator/SKILL.md +3 -6
package/bin/specweave.js
CHANGED
|
@@ -909,6 +909,21 @@ program
|
|
|
909
909
|
await syncProgress(args);
|
|
910
910
|
});
|
|
911
911
|
|
|
912
|
+
// Sync-living-docs command - Sync living docs for a specific increment
|
|
913
|
+
program
|
|
914
|
+
.command('sync-living-docs [increment-id]')
|
|
915
|
+
.description('Sync living documentation for an increment (feature spec + user story files)')
|
|
916
|
+
.option('--dry-run', 'Preview without making changes')
|
|
917
|
+
.option('--force', 'Force sync even if no changes detected')
|
|
918
|
+
.action(async (incrementId, options) => {
|
|
919
|
+
const { syncLivingDocs } = await import('../dist/src/cli/commands/sync-living-docs.js');
|
|
920
|
+
const args = [];
|
|
921
|
+
if (incrementId) args.push(incrementId);
|
|
922
|
+
if (options.dryRun) args.push('--dry-run');
|
|
923
|
+
if (options.force) args.push('--force');
|
|
924
|
+
await syncLivingDocs(args);
|
|
925
|
+
});
|
|
926
|
+
|
|
912
927
|
// Docs command - Documentation preview, build, validation
|
|
913
928
|
const docsCmd = program
|
|
914
929
|
.command('docs')
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI Command: sync-living-docs
|
|
3
|
+
*
|
|
4
|
+
* Sync living documentation for a specific increment.
|
|
5
|
+
* Generates or updates feature specs and user story files
|
|
6
|
+
* under .specweave/docs/internal/specs/.
|
|
7
|
+
*
|
|
8
|
+
* This is a focused command that ONLY syncs living docs.
|
|
9
|
+
* For full progress sync (including external tools), use sync-progress.
|
|
10
|
+
*/
|
|
11
|
+
import { Logger } from '../../utils/logger.js';
|
|
12
|
+
export interface SyncLivingDocsArgs {
|
|
13
|
+
incrementId?: string;
|
|
14
|
+
dryRun?: boolean;
|
|
15
|
+
force?: boolean;
|
|
16
|
+
}
|
|
17
|
+
export declare function syncLivingDocs(args: string[], options?: {
|
|
18
|
+
logger?: Logger;
|
|
19
|
+
}): Promise<void>;
|
|
20
|
+
//# sourceMappingURL=sync-living-docs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-living-docs.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/sync-living-docs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH,OAAO,EAAE,MAAM,EAAiB,MAAM,uBAAuB,CAAC;AAG9D,MAAM,WAAW,kBAAkB;IACjC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,wBAAsB,cAAc,CAClC,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAO,GAChC,OAAO,CAAC,IAAI,CAAC,CAgEf"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI Command: sync-living-docs
|
|
3
|
+
*
|
|
4
|
+
* Sync living documentation for a specific increment.
|
|
5
|
+
* Generates or updates feature specs and user story files
|
|
6
|
+
* under .specweave/docs/internal/specs/.
|
|
7
|
+
*
|
|
8
|
+
* This is a focused command that ONLY syncs living docs.
|
|
9
|
+
* For full progress sync (including external tools), use sync-progress.
|
|
10
|
+
*/
|
|
11
|
+
import path from 'path';
|
|
12
|
+
import { existsSync, readdirSync } from 'fs';
|
|
13
|
+
import { LivingDocsSync } from '../../core/living-docs/living-docs-sync.js';
|
|
14
|
+
import { consoleLogger } from '../../utils/logger.js';
|
|
15
|
+
import { ActiveIncrementManager } from '../../core/increment/active-increment-manager.js';
|
|
16
|
+
export async function syncLivingDocs(args, options = {}) {
|
|
17
|
+
const logger = options.logger ?? consoleLogger;
|
|
18
|
+
const parsedArgs = parseArgs(args);
|
|
19
|
+
const projectRoot = process.cwd();
|
|
20
|
+
// Resolve increment ID
|
|
21
|
+
let incrementId = parsedArgs.incrementId;
|
|
22
|
+
if (!incrementId) {
|
|
23
|
+
incrementId = detectActiveIncrement(projectRoot, logger) ?? undefined;
|
|
24
|
+
}
|
|
25
|
+
if (!incrementId) {
|
|
26
|
+
logger.error('No active increment found.');
|
|
27
|
+
logger.error('Usage: specweave sync-living-docs <increment-id>');
|
|
28
|
+
process.exit(1);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
// Verify increment exists
|
|
32
|
+
if (!incrementExists(projectRoot, incrementId)) {
|
|
33
|
+
logger.error(`Increment ${incrementId} not found.`);
|
|
34
|
+
process.exit(1);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
if (parsedArgs.dryRun) {
|
|
38
|
+
logger.log('[DRY RUN] No files will be modified.');
|
|
39
|
+
}
|
|
40
|
+
logger.log(`Syncing living docs for increment: ${incrementId}`);
|
|
41
|
+
try {
|
|
42
|
+
const sync = new LivingDocsSync(projectRoot, { logger });
|
|
43
|
+
const result = await sync.syncIncrement(incrementId, {
|
|
44
|
+
dryRun: parsedArgs.dryRun,
|
|
45
|
+
force: parsedArgs.force,
|
|
46
|
+
});
|
|
47
|
+
// Report results
|
|
48
|
+
logger.log('');
|
|
49
|
+
if (result.success) {
|
|
50
|
+
logger.log('Living Docs Sync Results:');
|
|
51
|
+
logger.log(` Feature ID: ${result.featureId}`);
|
|
52
|
+
logger.log(` Files created: ${result.filesCreated.length}`);
|
|
53
|
+
logger.log(` Files updated: ${result.filesUpdated.length}`);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
logger.error('Living docs sync failed.');
|
|
57
|
+
}
|
|
58
|
+
if (result.errors.length > 0) {
|
|
59
|
+
logger.log(' Warnings:');
|
|
60
|
+
for (const err of result.errors) {
|
|
61
|
+
logger.log(` - ${err}`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
if (!result.success) {
|
|
65
|
+
process.exit(1);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
70
|
+
logger.error(`Sync failed: ${msg}`);
|
|
71
|
+
process.exit(1);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
function parseArgs(args) {
|
|
75
|
+
const result = {};
|
|
76
|
+
for (const arg of args) {
|
|
77
|
+
if (arg === '--dry-run') {
|
|
78
|
+
result.dryRun = true;
|
|
79
|
+
}
|
|
80
|
+
else if (arg === '--force') {
|
|
81
|
+
result.force = true;
|
|
82
|
+
}
|
|
83
|
+
else if (!arg.startsWith('-') && !result.incrementId) {
|
|
84
|
+
result.incrementId = arg;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return result;
|
|
88
|
+
}
|
|
89
|
+
function detectActiveIncrement(projectRoot, logger) {
|
|
90
|
+
try {
|
|
91
|
+
const manager = new ActiveIncrementManager(projectRoot);
|
|
92
|
+
const active = manager.getActive();
|
|
93
|
+
if (active.length > 0) {
|
|
94
|
+
logger.log(`Auto-detected active increment: ${active[0]}`);
|
|
95
|
+
return active[0];
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
// Silent fallback
|
|
100
|
+
}
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
function incrementExists(projectRoot, id) {
|
|
104
|
+
const incrementsDir = path.join(projectRoot, '.specweave/increments');
|
|
105
|
+
// Direct match
|
|
106
|
+
if (existsSync(path.join(incrementsDir, id)))
|
|
107
|
+
return true;
|
|
108
|
+
// Archive match
|
|
109
|
+
if (existsSync(path.join(incrementsDir, '_archive', id)))
|
|
110
|
+
return true;
|
|
111
|
+
// Prefix match (e.g., "0001" matching "0001-feature-name")
|
|
112
|
+
try {
|
|
113
|
+
const entries = readdirSync(incrementsDir);
|
|
114
|
+
for (const entry of entries) {
|
|
115
|
+
if (entry.startsWith(id + '-') || entry === id)
|
|
116
|
+
return true;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
// Directory doesn't exist
|
|
121
|
+
}
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
// Main entry point when run directly
|
|
125
|
+
if (process.argv[1]?.endsWith('sync-living-docs.js') || process.argv[1]?.endsWith('sync-living-docs.ts')) {
|
|
126
|
+
const args = process.argv.slice(2);
|
|
127
|
+
syncLivingDocs(args).catch(console.error);
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=sync-living-docs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-living-docs.js","sourceRoot":"","sources":["../../../../src/cli/commands/sync-living-docs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,IAAI,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,4CAA4C,CAAC;AAC5E,OAAO,EAAU,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,sBAAsB,EAAE,MAAM,kDAAkD,CAAC;AAQ1F,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,IAAc,EACd,UAA+B,EAAE;IAEjC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,aAAa,CAAC;IAC/C,MAAM,UAAU,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAElC,uBAAuB;IACvB,IAAI,WAAW,GAAG,UAAU,CAAC,WAAW,CAAC;IACzC,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,WAAW,GAAG,qBAAqB,CAAC,WAAW,EAAE,MAAM,CAAC,IAAI,SAAS,CAAC;IACxE,CAAC;IAED,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,CAAC,KAAK,CAAC,4BAA4B,CAAC,CAAC;QAC3C,MAAM,CAAC,KAAK,CAAC,kDAAkD,CAAC,CAAC;QACjE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAChB,OAAO;IACT,CAAC;IAED,0BAA0B;IAC1B,IAAI,CAAC,eAAe,CAAC,WAAW,EAAE,WAAW,CAAC,EAAE,CAAC;QAC/C,MAAM,CAAC,KAAK,CAAC,aAAa,WAAW,aAAa,CAAC,CAAC;QACpD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAChB,OAAO;IACT,CAAC;IAED,IAAI,UAAU,CAAC,MAAM,EAAE,CAAC;QACtB,MAAM,CAAC,GAAG,CAAC,sCAAsC,CAAC,CAAC;IACrD,CAAC;IAED,MAAM,CAAC,GAAG,CAAC,sCAAsC,WAAW,EAAE,CAAC,CAAC;IAEhE,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,IAAI,cAAc,CAAC,WAAW,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;QACzD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,WAAW,EAAE;YACnD,MAAM,EAAE,UAAU,CAAC,MAAM;YACzB,KAAK,EAAE,UAAU,CAAC,KAAK;SACxB,CAAC,CAAC;QAEH,iBAAiB;QACjB,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACf,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,MAAM,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;YACxC,MAAM,CAAC,GAAG,CAAC,iBAAiB,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC;YAChD,MAAM,CAAC,GAAG,CAAC,oBAAoB,MAAM,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC,CAAC;YAC7D,MAAM,CAAC,GAAG,CAAC,oBAAoB,MAAM,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC,CAAC;QAC/D,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;QAC3C,CAAC;QAED,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7B,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;YAC1B,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;gBAChC,MAAM,CAAC,GAAG,CAAC,SAAS,GAAG,EAAE,CAAC,CAAC;YAC7B,CAAC;QACH,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,GAAG,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACnE,MAAM,CAAC,KAAK,CAAC,gBAAgB,GAAG,EAAE,CAAC,CAAC;QACpC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,SAAS,SAAS,CAAC,IAAc;IAC/B,MAAM,MAAM,GAAuB,EAAE,CAAC;IACtC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,GAAG,KAAK,WAAW,EAAE,CAAC;YACxB,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC;QACvB,CAAC;aAAM,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YAC7B,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC;QACtB,CAAC;aAAM,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;YACvD,MAAM,CAAC,WAAW,GAAG,GAAG,CAAC;QAC3B,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,qBAAqB,CAAC,WAAmB,EAAE,MAAc;IAChE,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,sBAAsB,CAAC,WAAW,CAAC,CAAC;QACxD,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;QACnC,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACtB,MAAM,CAAC,GAAG,CAAC,mCAAmC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAC3D,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC;QACnB,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,kBAAkB;IACpB,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,eAAe,CAAC,WAAmB,EAAE,EAAU;IACtD,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,uBAAuB,CAAC,CAAC;IAEtE,eAAe;IACf,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IAE1D,gBAAgB;IAChB,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,UAAU,EAAE,EAAE,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IAEtE,2DAA2D;IAC3D,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,WAAW,CAAC,aAAa,CAAC,CAAC;QAC3C,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,IAAI,KAAK,CAAC,UAAU,CAAC,EAAE,GAAG,GAAG,CAAC,IAAI,KAAK,KAAK,EAAE;gBAAE,OAAO,IAAI,CAAC;QAC9D,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,0BAA0B;IAC5B,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,qCAAqC;AACrC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,qBAAqB,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,qBAAqB,CAAC,EAAE,CAAC;IACzG,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACnC,cAAc,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC5C,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "specweave",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.336",
|
|
4
4
|
"description": "Spec-driven development framework for AI coding agents. Works with Claude Code, Codex, Antigravity, Cursor, Copilot & more. 100+ skills, 49 CLI commands, verified skill certification, autonomous execution, and living documentation.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -99,12 +99,8 @@ Write the following:
|
|
|
99
99
|
Run a test sync (read-only) to verify configuration:
|
|
100
100
|
|
|
101
101
|
```bash
|
|
102
|
-
# Test each enabled provider
|
|
103
|
-
|
|
104
|
-
import { SyncEngine } from './src/sync/engine.js';
|
|
105
|
-
import { GitHubAdapter } from './src/sync/providers/github.js';
|
|
106
|
-
// ... test connection for each provider
|
|
107
|
-
"
|
|
102
|
+
# Test each enabled provider with dry-run
|
|
103
|
+
specweave sync-progress --dry-run
|
|
108
104
|
```
|
|
109
105
|
|
|
110
106
|
Report results and confirm setup is complete.
|
|
@@ -39,12 +39,11 @@ Run the living docs sync via CLI:
|
|
|
39
39
|
# Normal mode
|
|
40
40
|
specweave sync-living-docs <increment-id>
|
|
41
41
|
|
|
42
|
-
#
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
"
|
|
42
|
+
# Review mode (dry-run)
|
|
43
|
+
specweave sync-living-docs <increment-id> --dry-run
|
|
44
|
+
|
|
45
|
+
# If CLI command not available, use sync-progress as fallback:
|
|
46
|
+
specweave sync-progress <increment-id> --no-github --no-jira --no-ado
|
|
48
47
|
```
|
|
49
48
|
|
|
50
49
|
### Step 4: Report Results
|
|
@@ -470,11 +470,8 @@ npx specweave init
|
|
|
470
470
|
# Via skill activation
|
|
471
471
|
"Can you validate my Azure DevOps configuration?"
|
|
472
472
|
|
|
473
|
-
# Via
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
# Via CLI (future command - planned)
|
|
477
|
-
specweave validate-ado
|
|
473
|
+
# Via ADO sync (validates automatically before syncing)
|
|
474
|
+
/sw-ado:sync <increment-id>
|
|
478
475
|
```
|
|
479
476
|
|
|
480
477
|
**Validation output**:
|
|
@@ -771,11 +768,8 @@ Run validation independently:
|
|
|
771
768
|
# Via skill
|
|
772
769
|
"Validate my Azure DevOps configuration"
|
|
773
770
|
|
|
774
|
-
# Via
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
# Via CLI (future)
|
|
778
|
-
specweave validate-ado
|
|
771
|
+
# Via ADO sync (validates automatically before syncing)
|
|
772
|
+
/sw-ado:sync <increment-id>
|
|
779
773
|
```
|
|
780
774
|
|
|
781
775
|
## Best Practices
|
|
@@ -66,11 +66,11 @@ fi
|
|
|
66
66
|
Use the Feature Sync CLI:
|
|
67
67
|
|
|
68
68
|
```bash
|
|
69
|
-
# Run feature sync
|
|
70
|
-
|
|
69
|
+
# Run feature sync via CLI
|
|
70
|
+
specweave sync-progress <increment-id>
|
|
71
71
|
|
|
72
72
|
# Example
|
|
73
|
-
|
|
73
|
+
specweave sync-progress 0062
|
|
74
74
|
```
|
|
75
75
|
|
|
76
76
|
---
|
|
@@ -401,8 +401,8 @@ Enter correct board ID or name: 3
|
|
|
401
401
|
|
|
402
402
|
**Manual validation**:
|
|
403
403
|
```bash
|
|
404
|
-
#
|
|
405
|
-
|
|
404
|
+
# Via CLI
|
|
405
|
+
specweave validate-jira
|
|
406
406
|
|
|
407
407
|
# Or via skill activation
|
|
408
408
|
"Can you validate my Jira configuration?"
|
|
@@ -684,10 +684,7 @@ Run validation independently:
|
|
|
684
684
|
# Via skill
|
|
685
685
|
"Validate my Jira configuration"
|
|
686
686
|
|
|
687
|
-
# Via
|
|
688
|
-
npx tsx src/utils/external-resource-validator.ts
|
|
689
|
-
|
|
690
|
-
# Via CLI (future)
|
|
687
|
+
# Via CLI
|
|
691
688
|
specweave validate-jira
|
|
692
689
|
```
|
|
693
690
|
|