@ikunin/sprintpilot 2.0.8 → 2.0.10
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/_Sprintpilot/manifest.yaml +1 -1
- package/_Sprintpilot/scripts/scan.js +109 -13
- package/_Sprintpilot/skills/sprintpilot-codebase-map/agents/architecture-mapper.md +9 -0
- package/_Sprintpilot/skills/sprintpilot-codebase-map/agents/concerns-hunter.md +9 -0
- package/_Sprintpilot/skills/sprintpilot-codebase-map/agents/integration-mapper.md +9 -0
- package/_Sprintpilot/skills/sprintpilot-codebase-map/agents/quality-assessor.md +9 -0
- package/_Sprintpilot/skills/sprintpilot-codebase-map/agents/stack-analyzer.md +10 -0
- package/_Sprintpilot/skills/sprintpilot-codebase-map/workflow.md +2 -0
- package/_Sprintpilot/skills/sprintpilot-reverse-architect/agents/component-mapper.md +7 -0
- package/_Sprintpilot/skills/sprintpilot-reverse-architect/agents/data-flow-tracer.md +7 -0
- package/_Sprintpilot/skills/sprintpilot-reverse-architect/agents/pattern-extractor.md +7 -0
- package/lib/commands/install.js +18 -2
- package/package.json +1 -1
|
@@ -15,6 +15,10 @@
|
|
|
15
15
|
* Flags: --include, --exclude, --root
|
|
16
16
|
* extensions Extension frequency histogram, descending.
|
|
17
17
|
* Flags: --exclude, --root, --limit (default 20)
|
|
18
|
+
*
|
|
19
|
+
* Ignore files: .gitignore and .aiexclude at the project root are parsed and
|
|
20
|
+
* applied as additional excludes by default. Pass --no-respect-ignore-files
|
|
21
|
+
* to disable. Negation patterns (`!pattern`) are logged to stderr and skipped.
|
|
18
22
|
*/
|
|
19
23
|
|
|
20
24
|
const fs = require('fs');
|
|
@@ -41,9 +45,74 @@ const DEFAULT_EXCLUDES = [
|
|
|
41
45
|
'.worktrees',
|
|
42
46
|
];
|
|
43
47
|
|
|
48
|
+
const IGNORE_FILES = ['.gitignore', '.aiexclude'];
|
|
49
|
+
|
|
50
|
+
// Translate one .gitignore / .aiexclude line into zero or more scan.js exclude
|
|
51
|
+
// patterns. Blank lines and `#` comments → []. Negation (`!`) is unsupported
|
|
52
|
+
// and returns []; the caller reports a stderr note. Trailing `/` marks a
|
|
53
|
+
// directory; we expand to both `dir` and `dir/**` so descendant files are also
|
|
54
|
+
// excluded. Leading `/` anchors to the ignore file's directory; we strip it
|
|
55
|
+
// and rely on scan.js's path-anchored exclude semantics for patterns that
|
|
56
|
+
// contain a slash.
|
|
57
|
+
function parseIgnorePattern(line) {
|
|
58
|
+
let p = line.trim();
|
|
59
|
+
if (!p || p.startsWith('#')) return { patterns: [], negation: false };
|
|
60
|
+
if (p.startsWith('!')) return { patterns: [], negation: true };
|
|
61
|
+
// Unescape leading `\#` and `\!` (gitignore literal escapes).
|
|
62
|
+
if (p.startsWith('\\#') || p.startsWith('\\!')) p = p.slice(1);
|
|
63
|
+
|
|
64
|
+
const isDir = p.endsWith('/');
|
|
65
|
+
if (isDir) p = p.slice(0, -1);
|
|
66
|
+
|
|
67
|
+
const anchored = p.startsWith('/');
|
|
68
|
+
const body = anchored ? p.slice(1) : p;
|
|
69
|
+
if (!body) return { patterns: [], negation: false };
|
|
70
|
+
// compilePatterns handles a leading '/' by anchoring the pattern to the
|
|
71
|
+
// root, so we keep it intact for anchored patterns.
|
|
72
|
+
const prefix = anchored ? '/' : '';
|
|
73
|
+
|
|
74
|
+
const patterns = [];
|
|
75
|
+
if (isDir) {
|
|
76
|
+
patterns.push(`${prefix}${body}`);
|
|
77
|
+
patterns.push(`${prefix}${body}/**`);
|
|
78
|
+
} else {
|
|
79
|
+
patterns.push(`${prefix}${body}`);
|
|
80
|
+
// A non-anchored pattern that has no slash matches files at any depth as
|
|
81
|
+
// a basename, which scan.js's matcher already does. If the same name is
|
|
82
|
+
// also a directory anywhere in the tree, exclude its descendants too.
|
|
83
|
+
if (!anchored && !body.includes('/')) patterns.push(`**/${body}/**`);
|
|
84
|
+
}
|
|
85
|
+
return { patterns, negation: false };
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function loadIgnoreFilePatterns(root) {
|
|
89
|
+
const out = [];
|
|
90
|
+
let negationCount = 0;
|
|
91
|
+
for (const name of IGNORE_FILES) {
|
|
92
|
+
const full = path.join(root, name);
|
|
93
|
+
let content;
|
|
94
|
+
try {
|
|
95
|
+
content = fs.readFileSync(full, 'utf8');
|
|
96
|
+
} catch {
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
for (const raw of content.split(/\r?\n/)) {
|
|
100
|
+
const { patterns, negation } = parseIgnorePattern(raw);
|
|
101
|
+
if (negation) negationCount++;
|
|
102
|
+
for (const p of patterns) out.push(p);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if (negationCount > 0) {
|
|
106
|
+
log.error(
|
|
107
|
+
`scan.js: ignored ${negationCount} negation pattern(s) from .gitignore/.aiexclude (not supported)`,
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
return out;
|
|
111
|
+
}
|
|
112
|
+
|
|
44
113
|
function help() {
|
|
45
114
|
log.out(
|
|
46
|
-
'Usage: scan.js <files|largest|loc|extensions> [--include <globs>] [--exclude <globs>] [--root <path>] [--limit <N>] [--count]',
|
|
115
|
+
'Usage: scan.js <files|largest|loc|extensions> [--include <globs>] [--exclude <globs>] [--root <path>] [--limit <N>] [--count] [--no-respect-ignore-files]',
|
|
47
116
|
);
|
|
48
117
|
}
|
|
49
118
|
|
|
@@ -183,12 +252,22 @@ function toPosix(p) {
|
|
|
183
252
|
// pathAnchored = true if the pattern contains a path separator; such patterns
|
|
184
253
|
// only match the full relative path. Basename-only patterns (no '/') match
|
|
185
254
|
// both the full path and the basename, so "*.ts" works at any depth.
|
|
255
|
+
// A leading '/' anchors the pattern to the root (relative paths have no
|
|
256
|
+
// leading slash, so we strip it but keep pathAnchored=true).
|
|
186
257
|
function compilePatterns(patterns) {
|
|
187
|
-
return patterns.map((p) =>
|
|
188
|
-
raw
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
258
|
+
return patterns.map((p) => {
|
|
259
|
+
let raw = p;
|
|
260
|
+
let leadingSlash = false;
|
|
261
|
+
if (raw.startsWith('/')) {
|
|
262
|
+
raw = raw.slice(1);
|
|
263
|
+
leadingSlash = true;
|
|
264
|
+
}
|
|
265
|
+
return {
|
|
266
|
+
raw,
|
|
267
|
+
re: globToRegex(raw),
|
|
268
|
+
pathAnchored: leadingSlash || raw.includes('/'),
|
|
269
|
+
};
|
|
270
|
+
});
|
|
192
271
|
}
|
|
193
272
|
|
|
194
273
|
function matchesAny(relPath, compiled) {
|
|
@@ -335,8 +414,8 @@ function resolveRoot(opts) {
|
|
|
335
414
|
return root;
|
|
336
415
|
}
|
|
337
416
|
|
|
338
|
-
function buildExcludes(extra) {
|
|
339
|
-
const list = [...DEFAULT_EXCLUDES, ...extra];
|
|
417
|
+
function buildExcludes(extra, ignoreFromFiles) {
|
|
418
|
+
const list = [...DEFAULT_EXCLUDES, ...extra, ...ignoreFromFiles];
|
|
340
419
|
// Patterns: match the basename of a directory OR any path containing it.
|
|
341
420
|
const patterns = [];
|
|
342
421
|
const basenames = new Set();
|
|
@@ -352,10 +431,18 @@ function buildExcludes(extra) {
|
|
|
352
431
|
return { compiled: compilePatterns(patterns), basenames };
|
|
353
432
|
}
|
|
354
433
|
|
|
434
|
+
function ignoreFilePatternsFor(root, opts) {
|
|
435
|
+
if (opts['no-respect-ignore-files'] === true) return [];
|
|
436
|
+
return loadIgnoreFilePatterns(root);
|
|
437
|
+
}
|
|
438
|
+
|
|
355
439
|
function cmdFiles(opts) {
|
|
356
440
|
const root = resolveRoot(opts);
|
|
357
441
|
const includes = compilePatterns(splitList(opts.include));
|
|
358
|
-
const { compiled: excludes, basenames } = buildExcludes(
|
|
442
|
+
const { compiled: excludes, basenames } = buildExcludes(
|
|
443
|
+
splitList(opts.exclude),
|
|
444
|
+
ignoreFilePatternsFor(root, opts),
|
|
445
|
+
);
|
|
359
446
|
const limit = opts.limit ? Number(opts.limit) : 0;
|
|
360
447
|
const count = opts.count === true || opts.count === 'true';
|
|
361
448
|
|
|
@@ -378,7 +465,10 @@ function cmdFiles(opts) {
|
|
|
378
465
|
function cmdLargest(opts) {
|
|
379
466
|
const root = resolveRoot(opts);
|
|
380
467
|
const includes = compilePatterns(splitList(opts.include));
|
|
381
|
-
const { compiled: excludes, basenames } = buildExcludes(
|
|
468
|
+
const { compiled: excludes, basenames } = buildExcludes(
|
|
469
|
+
splitList(opts.exclude),
|
|
470
|
+
ignoreFilePatternsFor(root, opts),
|
|
471
|
+
);
|
|
382
472
|
const limit = opts.limit ? Number(opts.limit) : 10;
|
|
383
473
|
|
|
384
474
|
const heap = []; // simple array; N is small so O(files * log N) is fine
|
|
@@ -396,7 +486,10 @@ function cmdLargest(opts) {
|
|
|
396
486
|
function cmdLoc(opts) {
|
|
397
487
|
const root = resolveRoot(opts);
|
|
398
488
|
const includes = compilePatterns(splitList(opts.include));
|
|
399
|
-
const { compiled: excludes, basenames } = buildExcludes(
|
|
489
|
+
const { compiled: excludes, basenames } = buildExcludes(
|
|
490
|
+
splitList(opts.exclude),
|
|
491
|
+
ignoreFilePatternsFor(root, opts),
|
|
492
|
+
);
|
|
400
493
|
|
|
401
494
|
let total = 0;
|
|
402
495
|
let fileCount = 0;
|
|
@@ -409,7 +502,10 @@ function cmdLoc(opts) {
|
|
|
409
502
|
|
|
410
503
|
function cmdExtensions(opts) {
|
|
411
504
|
const root = resolveRoot(opts);
|
|
412
|
-
const { compiled: excludes, basenames } = buildExcludes(
|
|
505
|
+
const { compiled: excludes, basenames } = buildExcludes(
|
|
506
|
+
splitList(opts.exclude),
|
|
507
|
+
ignoreFilePatternsFor(root, opts),
|
|
508
|
+
);
|
|
413
509
|
const limit = opts.limit ? Number(opts.limit) : 20;
|
|
414
510
|
|
|
415
511
|
const counts = new Map();
|
|
@@ -427,7 +523,7 @@ function cmdExtensions(opts) {
|
|
|
427
523
|
|
|
428
524
|
function main() {
|
|
429
525
|
const { opts, positional } = parseArgs(process.argv.slice(2), {
|
|
430
|
-
booleanFlags: ['count'],
|
|
526
|
+
booleanFlags: ['count', 'no-respect-ignore-files'],
|
|
431
527
|
});
|
|
432
528
|
if (opts.help || positional.length === 0) {
|
|
433
529
|
help();
|
|
@@ -19,6 +19,15 @@ Scan the project at `{{project_root}}` and write your findings to `{{output_file
|
|
|
19
19
|
- `*.key`, `*.pem`, `*.p12` (private keys)
|
|
20
20
|
- `credentials.json`, `service-account.json`
|
|
21
21
|
|
|
22
|
+
## Ignore-file Awareness
|
|
23
|
+
|
|
24
|
+
Before any Glob or Grep, read `{{project_root}}/.gitignore` and
|
|
25
|
+
`{{project_root}}/.aiexclude` if they exist. Treat every non-comment,
|
|
26
|
+
non-negation pattern as an additional excluded path: skip those files and
|
|
27
|
+
directories entirely, do not Read them, and filter them out of pattern search
|
|
28
|
+
results. `scan.js` applies these patterns automatically. Skip negation (`!`)
|
|
29
|
+
lines.
|
|
30
|
+
|
|
22
31
|
## Exploration
|
|
23
32
|
|
|
24
33
|
Use your native file tools (Read, Glob, Grep). The lists below describe what data to collect; pick the appropriate tool for your CLI.
|
|
@@ -20,6 +20,15 @@ Scan the project at `{{project_root}}` and write your findings to `{{output_file
|
|
|
20
20
|
- `credentials.json`, `service-account.json`
|
|
21
21
|
- Files in `.git/` directory
|
|
22
22
|
|
|
23
|
+
## Ignore-file Awareness
|
|
24
|
+
|
|
25
|
+
Before any Glob or Grep, read `{{project_root}}/.gitignore` and
|
|
26
|
+
`{{project_root}}/.aiexclude` if they exist. Treat every non-comment,
|
|
27
|
+
non-negation pattern as an additional excluded path: skip those files and
|
|
28
|
+
directories entirely, do not Read them, and filter them out of pattern search
|
|
29
|
+
results. `scan.js` applies these patterns automatically. Skip negation (`!`)
|
|
30
|
+
lines.
|
|
31
|
+
|
|
23
32
|
## Exploration
|
|
24
33
|
|
|
25
34
|
Use Grep for pattern searches and `scan.js` for aggregations. All Grep calls below should filter to code file types (e.g., `*.ts`, `*.js`, `*.py`, `*.java`, `*.go`, `*.rs`, `*.rb`, `*.cs`, `*.sql`, `*.sps`, `*.spb`, `*.xml`, `*.sh`, `*.c`, `*.h`, `*.cpp`, `*.hpp`, `*.cc`, `*.cxx`, `*.hxx`) and cap each result set (~20-50).
|
|
@@ -21,6 +21,15 @@ Scan the project at `{{project_root}}` and write your findings to `{{output_file
|
|
|
21
21
|
|
|
22
22
|
**DO read**: `.env.example`, `.env.sample`, `.env.template` (safe — contain variable names only)
|
|
23
23
|
|
|
24
|
+
## Ignore-file Awareness
|
|
25
|
+
|
|
26
|
+
Before any Glob or Grep, read `{{project_root}}/.gitignore` and
|
|
27
|
+
`{{project_root}}/.aiexclude` if they exist. Treat every non-comment,
|
|
28
|
+
non-negation pattern as an additional excluded path: skip those files and
|
|
29
|
+
directories entirely, do not Read them, and filter them out of pattern search
|
|
30
|
+
results. `scan.js` applies these patterns automatically. Skip negation (`!`)
|
|
31
|
+
lines.
|
|
32
|
+
|
|
24
33
|
## Exploration
|
|
25
34
|
|
|
26
35
|
Use Grep and Read. Below are the patterns to search for — file-type filters match the original language coverage (`*.ts`, `*.js`, `*.py`, `*.rb`, `*.go`, `*.rs`, `*.java`, `*.sh`, `*.c`, `*.h`, `*.cpp`, `*.hpp`, `*.cc`, `*.cxx`, `*.hxx`, `*.sql`, `*.sps`, `*.spb`, `*.xml`). Cap each result set (~15-30 matches).
|
|
@@ -19,6 +19,15 @@ Scan the project at `{{project_root}}` and write your findings to `{{output_file
|
|
|
19
19
|
- `*.key`, `*.pem`, `*.p12` (private keys)
|
|
20
20
|
- `credentials.json`, `service-account.json`
|
|
21
21
|
|
|
22
|
+
## Ignore-file Awareness
|
|
23
|
+
|
|
24
|
+
Before any Glob or Grep, read `{{project_root}}/.gitignore` and
|
|
25
|
+
`{{project_root}}/.aiexclude` if they exist. Treat every non-comment,
|
|
26
|
+
non-negation pattern as an additional excluded path: skip those files and
|
|
27
|
+
directories entirely, do not Read them, and filter them out of pattern search
|
|
28
|
+
results. `scan.js` applies these patterns automatically. Skip negation (`!`)
|
|
29
|
+
lines.
|
|
30
|
+
|
|
22
31
|
## Exploration
|
|
23
32
|
|
|
24
33
|
Use your native file tools (Read, Glob, Grep) plus the `scan.js` helper for aggregations.
|
|
@@ -20,6 +20,16 @@ Scan the project at `{{project_root}}` and write your findings to `{{output_file
|
|
|
20
20
|
- `credentials.json`, `service-account.json`
|
|
21
21
|
- `*.secret`, `*password*`, `*token*` (in filenames)
|
|
22
22
|
|
|
23
|
+
## Ignore-file Awareness
|
|
24
|
+
|
|
25
|
+
Before any Glob or Grep, read `{{project_root}}/.gitignore` and
|
|
26
|
+
`{{project_root}}/.aiexclude` if they exist. Treat every non-comment,
|
|
27
|
+
non-negation pattern as an additional excluded path: skip those files and
|
|
28
|
+
directories entirely, do not Read them, and filter them out of any pattern
|
|
29
|
+
search results. `scan.js` already applies these patterns automatically — pass
|
|
30
|
+
`--no-respect-ignore-files` only if you have a deliberate reason. Skip negation
|
|
31
|
+
(`!`) lines.
|
|
32
|
+
|
|
23
33
|
## Exploration
|
|
24
34
|
|
|
25
35
|
Gather data using your native file tools (Read, Glob, Grep). The commands below are illustrative — use the equivalent tool from your CLI. Skip files that don't exist; do not fail the task on missing manifests.
|
|
@@ -21,6 +21,8 @@ Complementary, not a replacement. `bmad-document-project` generates comprehensiv
|
|
|
21
21
|
<action>Create output directory `{output_folder}/codebase-analysis` (use your native file-create tool; it will create parent directories as needed). The first `Write` tool call targeting a file inside this directory will auto-create it, so no explicit mkdir is required in practice.</action>
|
|
22
22
|
<action>Determine project root absolute path: `{{project_root}}`</action>
|
|
23
23
|
|
|
24
|
+
<action>Note: each agent reads `{{project_root}}/.gitignore` and `{{project_root}}/.aiexclude` (if present) and treats every listed file/directory as off-limits. The `scan.js` helper applies these patterns automatically; agents apply them to their Glob/Grep operations as well. This prevents inclusion of build artifacts, vendored code, secrets, and explicitly AI-excluded paths in the analysis.</action>
|
|
25
|
+
|
|
24
26
|
---
|
|
25
27
|
|
|
26
28
|
## Step 2 — Launch 5 Analysis Agents in Parallel
|
|
@@ -6,6 +6,13 @@ You are extracting module boundaries and component contracts from an existing co
|
|
|
6
6
|
|
|
7
7
|
Using the architecture-analysis.md analysis as a starting point, go deeper: trace actual imports, identify public APIs, and map the internal dependency graph.
|
|
8
8
|
|
|
9
|
+
## Ignore-file Awareness
|
|
10
|
+
|
|
11
|
+
Before any Glob or Grep, read the project's `.gitignore` and `.aiexclude` if
|
|
12
|
+
they exist. Treat every non-comment, non-negation pattern as an additional
|
|
13
|
+
excluded path: skip those files and directories entirely, do not Read them,
|
|
14
|
+
and filter them out of pattern search results. Skip negation (`!`) lines.
|
|
15
|
+
|
|
9
16
|
## Method
|
|
10
17
|
|
|
11
18
|
1. For each module/directory identified in architecture-analysis.md:
|
|
@@ -6,6 +6,13 @@ You are tracing how data flows through the system — from entry points to stora
|
|
|
6
6
|
|
|
7
7
|
Using architecture-analysis.md and integrations-analysis.md as context, trace the actual request/data paths through the code.
|
|
8
8
|
|
|
9
|
+
## Ignore-file Awareness
|
|
10
|
+
|
|
11
|
+
Before any Glob or Grep, read the project's `.gitignore` and `.aiexclude` if
|
|
12
|
+
they exist. Treat every non-comment, non-negation pattern as an additional
|
|
13
|
+
excluded path: skip those files and directories entirely, do not Read them,
|
|
14
|
+
and filter them out of pattern search results. Skip negation (`!`) lines.
|
|
15
|
+
|
|
9
16
|
## Method
|
|
10
17
|
|
|
11
18
|
1. Start from entry points (routes, CLI handlers, event listeners)
|
|
@@ -6,6 +6,13 @@ You are identifying design patterns, conventions, and architectural decisions em
|
|
|
6
6
|
|
|
7
7
|
Using architecture-analysis.md and stack-analysis.md as context, identify the actual patterns the codebase follows (not what it claims to follow).
|
|
8
8
|
|
|
9
|
+
## Ignore-file Awareness
|
|
10
|
+
|
|
11
|
+
Before any Glob or Grep, read the project's `.gitignore` and `.aiexclude` if
|
|
12
|
+
they exist. Treat every non-comment, non-negation pattern as an additional
|
|
13
|
+
excluded path: skip those files and directories entirely, do not Read them,
|
|
14
|
+
and filter them out of pattern search results. Skip negation (`!`) lines.
|
|
15
|
+
|
|
9
16
|
## Method
|
|
10
17
|
|
|
11
18
|
1. Look for structural patterns: Factory, Repository, Observer, Middleware, Decorator
|
package/lib/commands/install.js
CHANGED
|
@@ -368,7 +368,7 @@ async function stripLegacyMarkers(projectRoot) {
|
|
|
368
368
|
// Evict v1 skill dirs from tool skill dirs INSIDE projectRoot only. We
|
|
369
369
|
// deliberately do NOT touch user-global ~/.claude/skills/ — a project-level
|
|
370
370
|
// install must not reach across projects on the same machine.
|
|
371
|
-
async function evictV1SkillsFromToolDirs(projectRoot) {
|
|
371
|
+
async function evictV1SkillsFromToolDirs(projectRoot, { dryRun = false } = {}) {
|
|
372
372
|
const removed = [];
|
|
373
373
|
const toolSkillDirs = [];
|
|
374
374
|
for (const tool of ALL_TOOLS) {
|
|
@@ -382,7 +382,7 @@ async function evictV1SkillsFromToolDirs(projectRoot) {
|
|
|
382
382
|
for (const v1Name of V1_SKILL_NAMES) {
|
|
383
383
|
const target = path.join(dir, v1Name);
|
|
384
384
|
if (await fs.pathExists(target)) {
|
|
385
|
-
await fs.remove(target);
|
|
385
|
+
if (!dryRun) await fs.remove(target);
|
|
386
386
|
removed.push(path.relative(projectRoot, target));
|
|
387
387
|
}
|
|
388
388
|
}
|
|
@@ -1001,6 +1001,22 @@ async function runInstall(options = {}) {
|
|
|
1001
1001
|
throw err;
|
|
1002
1002
|
}
|
|
1003
1003
|
|
|
1004
|
+
// 1b. Sweep orphaned v1-named skill dirs from tool dirs unconditionally.
|
|
1005
|
+
// evictV1Installation only fires when _bmad-addons/ is present, so a
|
|
1006
|
+
// user who upgraded long ago (and removed _bmad-addons/) never gets
|
|
1007
|
+
// stale .claude/skills/bmad-ma-* cleaned up — they linger as live
|
|
1008
|
+
// duplicates of the new sprintpilot-* skills. Idempotent, no-op when
|
|
1009
|
+
// nothing matches.
|
|
1010
|
+
const orphanedV1Skills = await evictV1SkillsFromToolDirs(projectRoot, { dryRun });
|
|
1011
|
+
if (orphanedV1Skills.length > 0) {
|
|
1012
|
+
console.log('');
|
|
1013
|
+
console.log(pc.yellow('Orphaned v1 skill directories found:'));
|
|
1014
|
+
for (const e of orphanedV1Skills) {
|
|
1015
|
+
console.log(` ${dryRun ? 'Would remove' : 'Removed'} legacy skill: ${e}`);
|
|
1016
|
+
}
|
|
1017
|
+
console.log('');
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1004
1020
|
// 2. Resolve output_folder
|
|
1005
1021
|
const outputFolder = await readOutputFolder(projectRoot);
|
|
1006
1022
|
if (outputFolder !== '_bmad-output') {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ikunin/sprintpilot",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.10",
|
|
4
4
|
"description": "Sprintpilot — autopilot and multi-agent addon for BMad Method v6: git workflow, parallel agents, autonomous story execution",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|