@ngocsangairvds/vsaf 3.0.3 → 3.0.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.
- package/README.md +4 -4
- package/bin/vsaf.js +15 -8
- package/package.json +1 -1
- package/src/project.js +0 -8
- package/src/status.js +1 -2
- package/src/workflow.js +35 -16
package/README.md
CHANGED
|
@@ -64,12 +64,12 @@ first 30 days.
|
|
|
64
64
|
```
|
|
65
65
|
.
|
|
66
66
|
├── .claude/
|
|
67
|
-
│ ├── settings.json #
|
|
67
|
+
│ ├── settings.json # Local AI settings (optional hook policy)
|
|
68
68
|
│ └── skills/ # Coding standards for Go, Rust, Python
|
|
69
69
|
├── docs/
|
|
70
70
|
│ ├── architecture/ # Architecture documents (from BMAD Architect)
|
|
71
71
|
│ └── onboarding/ # Developer onboarding (see table above)
|
|
72
|
-
├── githooks/ #
|
|
72
|
+
├── githooks/ # Optional local hooks (disabled by default)
|
|
73
73
|
├── graphify-out/ # Graphify output (gitignored, regenerated by `vsaf index`)
|
|
74
74
|
├── openspec/ # OpenSpec workspace (proposals, specs, designs, tasks)
|
|
75
75
|
├── scripts/
|
|
@@ -111,7 +111,7 @@ for a full command-by-command example.
|
|
|
111
111
|
| **BMAD Method** | AI agents for planning: Analyst, PM, Architect, Product Owner | Free |
|
|
112
112
|
| **OpenSpec** | Spec-driven development: proposals, specs, designs, task lists, verification | Free |
|
|
113
113
|
| **Superpowers** | Methodology engine: brainstorm, plan, TDD execution, code review | Free |
|
|
114
|
-
| **Security guardrails** |
|
|
114
|
+
| **Security guardrails** | Optional hooks/policies + coding standards (team-defined security scanning) | Free |
|
|
115
115
|
| **GitNexus** | Code knowledge graph via MCP — impact analysis, dependency queries | Free |
|
|
116
116
|
| **Graphify** | Multimodal knowledge graph — visual dependency maps, path tracing | Free |
|
|
117
117
|
| **claude-mem** | Auto-pilot memory — captures sessions, re-injects context next time | Free |
|
|
@@ -121,4 +121,4 @@ for a full command-by-command example.
|
|
|
121
121
|
|
|
122
122
|
**Core principles:** Spec before code. Context is king. Git is source of truth.
|
|
123
123
|
3-layer review before every PR. Re-index after every merge. Mine decisions
|
|
124
|
-
weekly.
|
|
124
|
+
weekly. Hooks are optional in the current simplified setup.
|
package/bin/vsaf.js
CHANGED
|
@@ -12,7 +12,7 @@ USAGE
|
|
|
12
12
|
vsaf project Scaffold project files only (assumes global done)
|
|
13
13
|
vsaf status Show installation status
|
|
14
14
|
vsaf index Re-index codebase (GitNexus + Graphify)
|
|
15
|
-
vsaf verify Check implementation against OpenSpec specs
|
|
15
|
+
vsaf verify Check implementation against OpenSpec specs (manual pre-push gate)
|
|
16
16
|
vsaf review Run 3-layer review flow
|
|
17
17
|
vsaf archive Archive specs and re-index
|
|
18
18
|
vsaf mine Mine conversations into MemPalace
|
|
@@ -23,7 +23,7 @@ GLOBAL (once per machine → ~/.claude/)
|
|
|
23
23
|
Binaries: gitnexus, openspec, graphify, mempalace, bun, claude-mem
|
|
24
24
|
|
|
25
25
|
PER PROJECT (per repo, run inside the repo root)
|
|
26
|
-
.claude/settings.json
|
|
26
|
+
.claude/settings.json Local AI settings (optional hook policy)
|
|
27
27
|
.claude/skills + .codex/skills BMAD skills synced for local clients
|
|
28
28
|
_bmad + _bmad-output BMAD workspace + generated artifacts folders
|
|
29
29
|
CLAUDE.md 10-step workflow rules
|
|
@@ -36,6 +36,13 @@ EXAMPLES
|
|
|
36
36
|
`;
|
|
37
37
|
|
|
38
38
|
async function main() {
|
|
39
|
+
const runAndExit = (result, label) => {
|
|
40
|
+
if (result === false) {
|
|
41
|
+
console.error(`\n${label} failed.`);
|
|
42
|
+
process.exit(1);
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
|
|
39
46
|
switch (cmd) {
|
|
40
47
|
case 'init': {
|
|
41
48
|
const { installGlobal } = require('../src/global');
|
|
@@ -61,32 +68,32 @@ async function main() {
|
|
|
61
68
|
}
|
|
62
69
|
case 'index': {
|
|
63
70
|
const { runIndex } = require('../src/workflow');
|
|
64
|
-
runIndex();
|
|
71
|
+
runAndExit(runIndex(), 'Index');
|
|
65
72
|
break;
|
|
66
73
|
}
|
|
67
74
|
case 'verify': {
|
|
68
75
|
const { runVerify } = require('../src/workflow');
|
|
69
|
-
runVerify();
|
|
76
|
+
runAndExit(runVerify(), 'Verify');
|
|
70
77
|
break;
|
|
71
78
|
}
|
|
72
79
|
case 'review': {
|
|
73
80
|
const { runReview } = require('../src/workflow');
|
|
74
|
-
runReview();
|
|
81
|
+
runAndExit(runReview(), 'Review');
|
|
75
82
|
break;
|
|
76
83
|
}
|
|
77
84
|
case 'archive': {
|
|
78
85
|
const { runArchive } = require('../src/workflow');
|
|
79
|
-
runArchive();
|
|
86
|
+
runAndExit(runArchive(), 'Archive');
|
|
80
87
|
break;
|
|
81
88
|
}
|
|
82
89
|
case 'mine': {
|
|
83
90
|
const { runMine } = require('../src/workflow');
|
|
84
|
-
runMine();
|
|
91
|
+
runAndExit(runMine(), 'Mine');
|
|
85
92
|
break;
|
|
86
93
|
}
|
|
87
94
|
case 'clean': {
|
|
88
95
|
const { runClean } = require('../src/workflow');
|
|
89
|
-
runClean();
|
|
96
|
+
runAndExit(runClean(), 'Clean');
|
|
90
97
|
break;
|
|
91
98
|
}
|
|
92
99
|
default:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ngocsangairvds/vsaf",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.4",
|
|
4
4
|
"description": "VSAF — Agentic AI SDLC Framework. Spec-driven development, 3-layer review, 7 integrated tools.",
|
|
5
5
|
"keywords": ["claude", "claude-code", "ai", "sdlc", "framework", "bmad", "openspec"],
|
|
6
6
|
"bin": {
|
package/src/project.js
CHANGED
|
@@ -20,7 +20,6 @@ async function installProject() {
|
|
|
20
20
|
initOpenSpec();
|
|
21
21
|
initGitNexus();
|
|
22
22
|
initMemPalace();
|
|
23
|
-
configureGitHooks();
|
|
24
23
|
|
|
25
24
|
console.log('\n\x1b[32m\x1b[1m✓ Project ready.\x1b[0m');
|
|
26
25
|
console.log('\n Next steps:');
|
|
@@ -164,12 +163,5 @@ function initMemPalace() {
|
|
|
164
163
|
exec(`mempalace init --yes "${CWD}"`, { cwd: CWD }) ? ok('MemPalace initialised') : warn('mempalace init failed — run manually');
|
|
165
164
|
}
|
|
166
165
|
|
|
167
|
-
function configureGitHooks() {
|
|
168
|
-
step('Git hooks');
|
|
169
|
-
if (!fs.existsSync(path.join(CWD, '.git'))) { warn('Not a git repo — skipping'); return; }
|
|
170
|
-
fs.mkdirSync(path.join(CWD, 'githooks'), { recursive: true });
|
|
171
|
-
exec('git config core.hooksPath githooks/', { cwd: CWD });
|
|
172
|
-
ok('Git hooks path → githooks/');
|
|
173
|
-
}
|
|
174
166
|
|
|
175
167
|
module.exports = { installProject };
|
package/src/status.js
CHANGED
|
@@ -17,7 +17,7 @@ async function showStatus() {
|
|
|
17
17
|
|
|
18
18
|
// ── Project ────────────────────────────────────────────────────────────────
|
|
19
19
|
console.log('\n\x1b[1mProject (current repo)\x1b[0m');
|
|
20
|
-
checkPath('.claude/settings.json', 'Project settings');
|
|
20
|
+
checkPath('.claude/settings.json', 'Project settings (optional hooks)');
|
|
21
21
|
checkPath('CLAUDE.md', 'Workflow rules');
|
|
22
22
|
checkPath('_bmad', 'BMAD workspace');
|
|
23
23
|
checkPath('_bmad-output', 'BMAD output folder');
|
|
@@ -26,7 +26,6 @@ async function showStatus() {
|
|
|
26
26
|
checkPath('.gitnexus', 'GitNexus index');
|
|
27
27
|
checkPath('openspec', 'OpenSpec');
|
|
28
28
|
checkPath('mempalace.yaml', 'MemPalace');
|
|
29
|
-
checkPath('githooks', 'Git hooks');
|
|
30
29
|
console.log('');
|
|
31
30
|
}
|
|
32
31
|
|
package/src/workflow.js
CHANGED
|
@@ -7,76 +7,95 @@ function runIndex() {
|
|
|
7
7
|
|
|
8
8
|
if (!hasCommand('gitnexus')) {
|
|
9
9
|
warn('gitnexus not found — run: vsaf global');
|
|
10
|
-
return;
|
|
10
|
+
return false;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
info('Running gitnexus analyze...');
|
|
14
|
-
|
|
14
|
+
const gitnexusOk = exec('gitnexus analyze');
|
|
15
|
+
gitnexusOk ? ok('GitNexus index updated') : warn('gitnexus analyze failed — run manually');
|
|
15
16
|
|
|
16
17
|
if (!hasCommand('graphify')) {
|
|
17
18
|
warn('graphify not found — skipping graphify update');
|
|
18
|
-
return;
|
|
19
|
+
return false;
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
info('Running graphify update...');
|
|
22
|
-
|
|
23
|
+
const graphifyOk = exec('graphify update .');
|
|
24
|
+
graphifyOk ? ok('Graphify updated') : warn('graphify update failed — run manually');
|
|
25
|
+
|
|
26
|
+
return gitnexusOk && graphifyOk;
|
|
23
27
|
}
|
|
24
28
|
|
|
25
29
|
function runVerify() {
|
|
26
30
|
step('Verify');
|
|
27
31
|
if (!hasCommand('openspec')) {
|
|
28
32
|
warn('openspec not found — run: vsaf global');
|
|
29
|
-
return;
|
|
33
|
+
return false;
|
|
30
34
|
}
|
|
31
35
|
|
|
32
36
|
info('Running openspec validate --all...');
|
|
33
|
-
exec('openspec validate --all')
|
|
37
|
+
const okVerify = exec('openspec validate --all');
|
|
38
|
+
okVerify ? ok('OpenSpec verification passed') : warn('OpenSpec verification failed');
|
|
39
|
+
return okVerify;
|
|
34
40
|
}
|
|
35
41
|
|
|
36
42
|
function runReview() {
|
|
37
43
|
step('Review (3-layer)');
|
|
38
44
|
info('Layer 1: Methodology review — run in Claude Code: /superpowers:code-review');
|
|
39
45
|
info('Layer 2: Spec compliance');
|
|
40
|
-
runVerify();
|
|
46
|
+
const verifyOk = runVerify();
|
|
41
47
|
info('Layer 3: Knowledge graph sync');
|
|
42
|
-
runIndex();
|
|
43
|
-
|
|
48
|
+
const indexOk = runIndex();
|
|
49
|
+
|
|
50
|
+
if (verifyOk && indexOk) {
|
|
51
|
+
ok('Review flow completed');
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
warn('Review flow completed with failures. Fix warnings and re-run.');
|
|
56
|
+
return false;
|
|
44
57
|
}
|
|
45
58
|
|
|
46
59
|
function runArchive() {
|
|
47
60
|
step('Archive');
|
|
48
61
|
if (!hasCommand('openspec')) {
|
|
49
62
|
warn('openspec not found — run: vsaf global');
|
|
50
|
-
return;
|
|
63
|
+
return false;
|
|
51
64
|
}
|
|
52
65
|
|
|
53
66
|
info('Running openspec archive...');
|
|
54
|
-
|
|
55
|
-
|
|
67
|
+
const archiveOk = exec('openspec archive');
|
|
68
|
+
archiveOk ? ok('OpenSpec archived') : warn('openspec archive failed — run manually');
|
|
69
|
+
const indexOk = runIndex();
|
|
70
|
+
return archiveOk && indexOk;
|
|
56
71
|
}
|
|
57
72
|
|
|
58
73
|
function runMine() {
|
|
59
74
|
step('Mine');
|
|
60
75
|
if (!hasCommand('mempalace')) {
|
|
61
76
|
warn('mempalace not found — run: vsaf global');
|
|
62
|
-
return;
|
|
77
|
+
return false;
|
|
63
78
|
}
|
|
64
79
|
|
|
65
80
|
info('Running mempalace mine ~/chats/ --mode convos --extract general...');
|
|
66
|
-
exec('mempalace mine ~/chats/ --mode convos --extract general')
|
|
81
|
+
const mineOk = exec('mempalace mine ~/chats/ --mode convos --extract general');
|
|
82
|
+
mineOk
|
|
67
83
|
? ok('MemPalace mine completed')
|
|
68
84
|
: warn('mempalace mine failed — run manually');
|
|
85
|
+
return mineOk;
|
|
69
86
|
}
|
|
70
87
|
|
|
71
88
|
function runClean() {
|
|
72
89
|
step('Clean');
|
|
73
90
|
if (!hasCommand('gitnexus')) {
|
|
74
91
|
warn('gitnexus not found — run: vsaf global');
|
|
75
|
-
return;
|
|
92
|
+
return false;
|
|
76
93
|
}
|
|
77
94
|
|
|
78
95
|
info('Running gitnexus clean...');
|
|
79
|
-
|
|
96
|
+
const cleanOk = exec('gitnexus clean');
|
|
97
|
+
cleanOk ? ok('GitNexus index cleaned') : warn('gitnexus clean failed — run manually');
|
|
98
|
+
return cleanOk;
|
|
80
99
|
}
|
|
81
100
|
|
|
82
101
|
module.exports = { runIndex, runVerify, runReview, runArchive, runMine, runClean };
|