@ikunin/sprintpilot 1.0.0

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.
Files changed (86) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +330 -0
  3. package/_Sprintpilot/.secrets-allowlist +26 -0
  4. package/_Sprintpilot/Sprintpilot.md +216 -0
  5. package/_Sprintpilot/lib/runtime/args.js +77 -0
  6. package/_Sprintpilot/lib/runtime/git.js +24 -0
  7. package/_Sprintpilot/lib/runtime/http.js +96 -0
  8. package/_Sprintpilot/lib/runtime/log.js +30 -0
  9. package/_Sprintpilot/lib/runtime/secrets.js +151 -0
  10. package/_Sprintpilot/lib/runtime/spawn.js +68 -0
  11. package/_Sprintpilot/lib/runtime/text.js +26 -0
  12. package/_Sprintpilot/lib/runtime/yaml-lite.js +160 -0
  13. package/_Sprintpilot/manifest.yaml +26 -0
  14. package/_Sprintpilot/modules/autopilot/config.yaml +20 -0
  15. package/_Sprintpilot/modules/git/branching-and-pr-strategy.md +101 -0
  16. package/_Sprintpilot/modules/git/config.yaml +83 -0
  17. package/_Sprintpilot/modules/git/templates/commit-patch.txt +1 -0
  18. package/_Sprintpilot/modules/git/templates/commit-story.txt +1 -0
  19. package/_Sprintpilot/modules/git/templates/pr-body.md +20 -0
  20. package/_Sprintpilot/modules/ma/config.yaml +9 -0
  21. package/_Sprintpilot/scripts/create-pr.js +284 -0
  22. package/_Sprintpilot/scripts/detect-platform.js +64 -0
  23. package/_Sprintpilot/scripts/health-check.js +98 -0
  24. package/_Sprintpilot/scripts/lint-changed.js +249 -0
  25. package/_Sprintpilot/scripts/lock.js +195 -0
  26. package/_Sprintpilot/scripts/sanitize-branch.js +107 -0
  27. package/_Sprintpilot/scripts/stage-and-commit.js +190 -0
  28. package/_Sprintpilot/scripts/sync-status.js +141 -0
  29. package/_Sprintpilot/skills/sprint-autopilot-off/SKILL.md +6 -0
  30. package/_Sprintpilot/skills/sprint-autopilot-off/workflow.md +154 -0
  31. package/_Sprintpilot/skills/sprint-autopilot-on/SKILL.md +6 -0
  32. package/_Sprintpilot/skills/sprint-autopilot-on/workflow.md +1119 -0
  33. package/_Sprintpilot/skills/sprintpilot-assess/SKILL.md +6 -0
  34. package/_Sprintpilot/skills/sprintpilot-assess/agents/debt-classifier.md +64 -0
  35. package/_Sprintpilot/skills/sprintpilot-assess/agents/dependency-auditor.md +57 -0
  36. package/_Sprintpilot/skills/sprintpilot-assess/agents/migration-analyzer.md +62 -0
  37. package/_Sprintpilot/skills/sprintpilot-assess/workflow.md +114 -0
  38. package/_Sprintpilot/skills/sprintpilot-code-review/SKILL.md +6 -0
  39. package/_Sprintpilot/skills/sprintpilot-code-review/agents/acceptance-auditor.md +51 -0
  40. package/_Sprintpilot/skills/sprintpilot-code-review/agents/blind-hunter.md +39 -0
  41. package/_Sprintpilot/skills/sprintpilot-code-review/agents/edge-case-hunter.md +46 -0
  42. package/_Sprintpilot/skills/sprintpilot-code-review/workflow.md +111 -0
  43. package/_Sprintpilot/skills/sprintpilot-codebase-map/SKILL.md +6 -0
  44. package/_Sprintpilot/skills/sprintpilot-codebase-map/agents/architecture-mapper.md +129 -0
  45. package/_Sprintpilot/skills/sprintpilot-codebase-map/agents/concerns-hunter.md +135 -0
  46. package/_Sprintpilot/skills/sprintpilot-codebase-map/agents/integration-mapper.md +138 -0
  47. package/_Sprintpilot/skills/sprintpilot-codebase-map/agents/quality-assessor.md +143 -0
  48. package/_Sprintpilot/skills/sprintpilot-codebase-map/agents/stack-analyzer.md +133 -0
  49. package/_Sprintpilot/skills/sprintpilot-codebase-map/workflow.md +120 -0
  50. package/_Sprintpilot/skills/sprintpilot-migrate/SKILL.md +6 -0
  51. package/_Sprintpilot/skills/sprintpilot-migrate/agents/dependency-analyzer.md +51 -0
  52. package/_Sprintpilot/skills/sprintpilot-migrate/agents/risk-assessor.md +55 -0
  53. package/_Sprintpilot/skills/sprintpilot-migrate/agents/stack-mapper.md +49 -0
  54. package/_Sprintpilot/skills/sprintpilot-migrate/agents/test-parity-analyzer.md +49 -0
  55. package/_Sprintpilot/skills/sprintpilot-migrate/resources/coexistence-patterns.md +59 -0
  56. package/_Sprintpilot/skills/sprintpilot-migrate/resources/strategies.md +43 -0
  57. package/_Sprintpilot/skills/sprintpilot-migrate/templates/component-card.md +11 -0
  58. package/_Sprintpilot/skills/sprintpilot-migrate/templates/migration-epics.md +35 -0
  59. package/_Sprintpilot/skills/sprintpilot-migrate/templates/migration-plan.md +66 -0
  60. package/_Sprintpilot/skills/sprintpilot-migrate/workflow.md +235 -0
  61. package/_Sprintpilot/skills/sprintpilot-party-mode/SKILL.md +6 -0
  62. package/_Sprintpilot/skills/sprintpilot-party-mode/workflow.md +138 -0
  63. package/_Sprintpilot/skills/sprintpilot-research/SKILL.md +6 -0
  64. package/_Sprintpilot/skills/sprintpilot-research/workflow.md +128 -0
  65. package/_Sprintpilot/skills/sprintpilot-reverse-architect/SKILL.md +6 -0
  66. package/_Sprintpilot/skills/sprintpilot-reverse-architect/agents/component-mapper.md +53 -0
  67. package/_Sprintpilot/skills/sprintpilot-reverse-architect/agents/data-flow-tracer.md +54 -0
  68. package/_Sprintpilot/skills/sprintpilot-reverse-architect/agents/pattern-extractor.md +67 -0
  69. package/_Sprintpilot/skills/sprintpilot-reverse-architect/workflow.md +119 -0
  70. package/_Sprintpilot/skills/sprintpilot-update/SKILL.md +6 -0
  71. package/_Sprintpilot/skills/sprintpilot-update/workflow.md +46 -0
  72. package/_Sprintpilot/templates/agent-rules.md +43 -0
  73. package/bin/sprintpilot.js +95 -0
  74. package/lib/commands/check-update.js +54 -0
  75. package/lib/commands/install.js +876 -0
  76. package/lib/commands/uninstall.js +218 -0
  77. package/lib/core/bmad-config.js +113 -0
  78. package/lib/core/file-ops.js +90 -0
  79. package/lib/core/gitignore.js +54 -0
  80. package/lib/core/markers.js +126 -0
  81. package/lib/core/tool-registry.js +73 -0
  82. package/lib/core/update-check.js +39 -0
  83. package/lib/core/v1-detect.js +86 -0
  84. package/lib/prompts.js +82 -0
  85. package/lib/substitute.js +39 -0
  86. package/package.json +49 -0
@@ -0,0 +1,39 @@
1
+ 'use strict';
2
+
3
+ const { execFile } = require('node:child_process');
4
+ const semver = require('semver');
5
+
6
+ const PACKAGE_NAME = '@ikunin/sprintpilot';
7
+
8
+ function spawnCapture(cmd, args, { timeoutMs = 7000 } = {}) {
9
+ return new Promise((resolve) => {
10
+ const child = execFile(cmd, args, { timeout: timeoutMs, windowsHide: true }, (err, stdout) => {
11
+ if (err) return resolve(null);
12
+ resolve(String(stdout || '').trim());
13
+ });
14
+ child.on('error', () => resolve(null));
15
+ });
16
+ }
17
+
18
+ async function fetchLatestVersion() {
19
+ const out = await spawnCapture('npm', ['view', `${PACKAGE_NAME}@latest`, 'version']);
20
+ if (!out) return null;
21
+ const first = out.split(/\r?\n/)[0].trim();
22
+ return semver.valid(first) ? first : null;
23
+ }
24
+
25
+ function compareVersions(currentRaw, latestRaw) {
26
+ if (!currentRaw || !latestRaw) return 'unknown';
27
+ const current = semver.coerce(currentRaw)?.version || currentRaw;
28
+ const latest = semver.coerce(latestRaw)?.version || latestRaw;
29
+ if (!semver.valid(current) || !semver.valid(latest)) return 'unknown';
30
+ if (semver.gt(latest, current)) return 'behind';
31
+ if (semver.lt(latest, current)) return 'ahead';
32
+ return 'current';
33
+ }
34
+
35
+ module.exports = {
36
+ PACKAGE_NAME,
37
+ fetchLatestVersion,
38
+ compareVersions,
39
+ };
@@ -0,0 +1,86 @@
1
+ 'use strict';
2
+
3
+ const path = require('node:path');
4
+ const fs = require('fs-extra');
5
+
6
+ const { readYaml } = require('./bmad-config');
7
+
8
+ const V1_ADDON_DIR_NAME = '_bmad-addons';
9
+ const V1_MANIFEST_NAME = 'bmad-ma-git';
10
+ const V1_SKILL_NAMES = [
11
+ 'bmad-autopilot-on',
12
+ 'bmad-autopilot-off',
13
+ 'bmad-addon-update',
14
+ 'bmad-ma-code-review',
15
+ 'bmad-ma-codebase-map',
16
+ 'bmad-ma-assess',
17
+ 'bmad-ma-reverse-architect',
18
+ 'bmad-ma-migrate',
19
+ 'bmad-ma-research',
20
+ 'bmad-ma-party-mode',
21
+ ];
22
+
23
+ // Returns { v1Dir, v1Manifest, detectedVia, manifestAddonName } if the
24
+ // project at projectRoot looks like a bmad-autopilot-addon v1 install, or
25
+ // null otherwise. A "v1 signature" is either: manifest.yaml with
26
+ // addon.name === 'bmad-ma-git' OR (manifest missing/unreadable/naming a
27
+ // different addon but) a skills/ directory containing at least one
28
+ // v1-named skill dir. A malformed manifest does NOT short-circuit to
29
+ // "not v1" — we fall through to the skill-dir heuristic instead, because
30
+ // partial prior installs frequently leave a corrupt manifest behind.
31
+ //
32
+ // detectedVia distinguishes the trust level:
33
+ // 'manifest' — authoritative (manifest names bmad-ma-git)
34
+ // 'skills-no-manifest' — manifest missing, skill-dir heuristic triggered
35
+ // 'skills-unreadable-manifest' — manifest present but unparseable
36
+ // 'skills-other-addon' — manifest cleanly names a DIFFERENT addon,
37
+ // skill dirs still look v1-ish. Ambiguous —
38
+ // caller should require explicit confirmation.
39
+ async function detectV1Installation(projectRoot) {
40
+ const v1Dir = path.join(projectRoot, V1_ADDON_DIR_NAME);
41
+ if (!(await fs.pathExists(v1Dir))) return null;
42
+ const v1Manifest = path.join(v1Dir, 'manifest.yaml');
43
+
44
+ let isV1 = false;
45
+ let manifestAddonName = null;
46
+ let manifestState = 'missing'; // missing | unreadable | parsed
47
+ if (await fs.pathExists(v1Manifest)) {
48
+ try {
49
+ const data = await readYaml(v1Manifest);
50
+ if (data === null) {
51
+ manifestState = 'unreadable';
52
+ } else {
53
+ manifestState = 'parsed';
54
+ manifestAddonName = (data && data.addon && data.addon.name) || null;
55
+ if (manifestAddonName === V1_MANIFEST_NAME) isV1 = true;
56
+ }
57
+ } catch {
58
+ manifestState = 'unreadable';
59
+ }
60
+ }
61
+
62
+ let detectedVia = isV1 ? 'manifest' : null;
63
+
64
+ if (!isV1) {
65
+ const v1SkillsDir = path.join(v1Dir, 'skills');
66
+ if (await fs.pathExists(v1SkillsDir)) {
67
+ const entries = await fs.readdir(v1SkillsDir, { withFileTypes: true });
68
+ const names = entries.filter((e) => e.isDirectory()).map((e) => e.name);
69
+ if (names.some((n) => V1_SKILL_NAMES.includes(n))) {
70
+ isV1 = true;
71
+ if (manifestState === 'parsed') detectedVia = 'skills-other-addon';
72
+ else if (manifestState === 'unreadable') detectedVia = 'skills-unreadable-manifest';
73
+ else detectedVia = 'skills-no-manifest';
74
+ }
75
+ }
76
+ }
77
+
78
+ return isV1 ? { v1Dir, v1Manifest, detectedVia, manifestAddonName } : null;
79
+ }
80
+
81
+ module.exports = {
82
+ V1_ADDON_DIR_NAME,
83
+ V1_MANIFEST_NAME,
84
+ V1_SKILL_NAMES,
85
+ detectV1Installation,
86
+ };
package/lib/prompts.js ADDED
@@ -0,0 +1,82 @@
1
+ 'use strict';
2
+
3
+ let clackPromise;
4
+
5
+ function loadClack() {
6
+ if (!clackPromise) {
7
+ clackPromise = import('@clack/prompts');
8
+ }
9
+ return clackPromise;
10
+ }
11
+
12
+ async function multiselect(opts) {
13
+ const clack = await loadClack();
14
+ const result = await clack.multiselect(opts);
15
+ if (clack.isCancel(result)) {
16
+ clack.cancel('Cancelled');
17
+ process.exit(0);
18
+ }
19
+ return result;
20
+ }
21
+
22
+ async function confirm(opts) {
23
+ const clack = await loadClack();
24
+ const result = await clack.confirm(opts);
25
+ if (clack.isCancel(result)) {
26
+ clack.cancel('Cancelled');
27
+ process.exit(0);
28
+ }
29
+ return result;
30
+ }
31
+
32
+ async function intro(message) {
33
+ const clack = await loadClack();
34
+ clack.intro(message);
35
+ }
36
+
37
+ async function outro(message) {
38
+ const clack = await loadClack();
39
+ clack.outro(message);
40
+ }
41
+
42
+ async function note(message, title) {
43
+ const clack = await loadClack();
44
+ clack.note(message, title);
45
+ }
46
+
47
+ const log = {
48
+ async info(message) {
49
+ const clack = await loadClack();
50
+ clack.log.info(message);
51
+ },
52
+ async success(message) {
53
+ const clack = await loadClack();
54
+ clack.log.success(message);
55
+ },
56
+ async warn(message) {
57
+ const clack = await loadClack();
58
+ clack.log.warn(message);
59
+ },
60
+ async error(message) {
61
+ const clack = await loadClack();
62
+ clack.log.error(message);
63
+ },
64
+ async step(message) {
65
+ const clack = await loadClack();
66
+ clack.log.step(message);
67
+ },
68
+ async message(message) {
69
+ const clack = await loadClack();
70
+ clack.log.message(message);
71
+ },
72
+ };
73
+
74
+ module.exports = {
75
+ loadClack,
76
+ intro,
77
+ outro,
78
+ note,
79
+ multiselect,
80
+ confirm,
81
+ log,
82
+ };
@@ -0,0 +1,39 @@
1
+ 'use strict';
2
+
3
+ const path = require('node:path');
4
+
5
+ const TEXT_EXTENSIONS = new Set([
6
+ '.md', '.yaml', '.yml', '.json', '.sh', '.txt',
7
+ ]);
8
+
9
+ function isTextFile(filePath) {
10
+ return TEXT_EXTENSIONS.has(path.extname(filePath).toLowerCase());
11
+ }
12
+
13
+ function renderString(text, ctx) {
14
+ if (!text) return text;
15
+ let out = text;
16
+ for (const [key, value] of Object.entries(ctx)) {
17
+ if (value == null) continue;
18
+ const token = `{${key}}`;
19
+ if (out.includes(token)) {
20
+ out = out.split(token).join(value);
21
+ }
22
+ }
23
+ return out;
24
+ }
25
+
26
+ function buildContext({ outputFolder }) {
27
+ const out = outputFolder || '_bmad-output';
28
+ return {
29
+ output_folder: out,
30
+ planning_artifacts: `${out}/planning-artifacts`,
31
+ implementation_artifacts: `${out}/implementation-artifacts`,
32
+ };
33
+ }
34
+
35
+ module.exports = {
36
+ isTextFile,
37
+ renderString,
38
+ buildContext,
39
+ };
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "@ikunin/sprintpilot",
3
+ "version": "1.0.0",
4
+ "description": "Sprintpilot — autopilot and multi-agent addon for BMad Method v6: git workflow, parallel agents, autonomous story execution",
5
+ "license": "Apache-2.0",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/ikunin/sprintpilot.git"
9
+ },
10
+ "homepage": "https://github.com/ikunin/sprintpilot",
11
+ "bin": {
12
+ "sprintpilot": "bin/sprintpilot.js"
13
+ },
14
+ "files": [
15
+ "bin/",
16
+ "lib/",
17
+ "_Sprintpilot/"
18
+ ],
19
+ "keywords": [
20
+ "sprintpilot",
21
+ "autopilot",
22
+ "orchestrator",
23
+ "ai-development",
24
+ "claude",
25
+ "gemini",
26
+ "cursor",
27
+ "windsurf",
28
+ "cline",
29
+ "git-workflow",
30
+ "multi-agent",
31
+ "bmad-method-addon"
32
+ ],
33
+ "engines": {
34
+ "node": ">=18.0.0"
35
+ },
36
+ "dependencies": {
37
+ "@clack/core": "^1.0.0",
38
+ "@clack/prompts": "^1.0.0",
39
+ "commander": "^14.0.0",
40
+ "fs-extra": "^11.3.0",
41
+ "js-yaml": "^4.1.0",
42
+ "picocolors": "^1.1.1",
43
+ "semver": "^7.6.3"
44
+ },
45
+ "publishConfig": {
46
+ "access": "public",
47
+ "provenance": true
48
+ }
49
+ }