beth-copilot 1.1.0 → 2.1.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.
- package/CHANGELOG.md +51 -1
- package/README.md +121 -132
- package/assets/beth-questioning.png +0 -0
- package/assets/yellowstone-beth.png +0 -0
- package/bin/cli.js +359 -445
- package/dist/__tests__/inject-skills.test.d.ts +9 -0
- package/dist/__tests__/inject-skills.test.d.ts.map +1 -0
- package/dist/__tests__/inject-skills.test.js +143 -0
- package/dist/__tests__/inject-skills.test.js.map +1 -0
- package/dist/__tests__/skills/disambiguation.test.d.ts +10 -0
- package/dist/__tests__/skills/disambiguation.test.d.ts.map +1 -0
- package/dist/__tests__/skills/disambiguation.test.js +192 -0
- package/dist/__tests__/skills/disambiguation.test.js.map +1 -0
- package/dist/__tests__/skills/hook-injection.test.d.ts +11 -0
- package/dist/__tests__/skills/hook-injection.test.d.ts.map +1 -0
- package/dist/__tests__/skills/hook-injection.test.js +173 -0
- package/dist/__tests__/skills/hook-injection.test.js.map +1 -0
- package/dist/__tests__/skills/mapping-completeness.test.d.ts +17 -0
- package/dist/__tests__/skills/mapping-completeness.test.d.ts.map +1 -0
- package/dist/__tests__/skills/mapping-completeness.test.js +281 -0
- package/dist/__tests__/skills/mapping-completeness.test.js.map +1 -0
- package/dist/__tests__/skills/pipeline-integration.test.d.ts +18 -0
- package/dist/__tests__/skills/pipeline-integration.test.d.ts.map +1 -0
- package/dist/__tests__/skills/pipeline-integration.test.js +234 -0
- package/dist/__tests__/skills/pipeline-integration.test.js.map +1 -0
- package/dist/__tests__/skills/skill-routing.test.d.ts +15 -0
- package/dist/__tests__/skills/skill-routing.test.d.ts.map +1 -0
- package/dist/__tests__/skills/skill-routing.test.js +723 -0
- package/dist/__tests__/skills/skill-routing.test.js.map +1 -0
- package/dist/__tests__/skills/trigger-coverage.test.d.ts +24 -0
- package/dist/__tests__/skills/trigger-coverage.test.d.ts.map +1 -0
- package/dist/__tests__/skills/trigger-coverage.test.js +746 -0
- package/dist/__tests__/skills/trigger-coverage.test.js.map +1 -0
- package/dist/__tests__/smoke.test.js +13 -0
- package/dist/__tests__/smoke.test.js.map +1 -1
- package/dist/__tests__/verify-skills.test.d.ts +9 -0
- package/dist/__tests__/verify-skills.test.d.ts.map +1 -0
- package/dist/__tests__/verify-skills.test.js +78 -0
- package/dist/__tests__/verify-skills.test.js.map +1 -0
- package/dist/cli/commands/beads.e2e.test.d.ts +4 -2
- package/dist/cli/commands/beads.e2e.test.d.ts.map +1 -1
- package/dist/cli/commands/beads.e2e.test.js +97 -38
- package/dist/cli/commands/beads.e2e.test.js.map +1 -1
- package/dist/cli/commands/cli-edge-cases.e2e.test.js +1 -1
- package/dist/cli/commands/cli-edge-cases.e2e.test.js.map +1 -1
- package/dist/cli/commands/close.d.ts +11 -46
- package/dist/cli/commands/close.d.ts.map +1 -1
- package/dist/cli/commands/close.e2e.test.d.ts +4 -20
- package/dist/cli/commands/close.e2e.test.d.ts.map +1 -1
- package/dist/cli/commands/close.e2e.test.js +23 -204
- package/dist/cli/commands/close.e2e.test.js.map +1 -1
- package/dist/cli/commands/close.js +26 -240
- package/dist/cli/commands/close.js.map +1 -1
- package/dist/cli/commands/close.test.d.ts +7 -9
- package/dist/cli/commands/close.test.d.ts.map +1 -1
- package/dist/cli/commands/close.test.js +44 -424
- package/dist/cli/commands/close.test.js.map +1 -1
- package/dist/cli/commands/doctor.d.ts +16 -22
- package/dist/cli/commands/doctor.d.ts.map +1 -1
- package/dist/cli/commands/doctor.e2e.test.js +3 -59
- package/dist/cli/commands/doctor.e2e.test.js.map +1 -1
- package/dist/cli/commands/doctor.js +87 -103
- package/dist/cli/commands/doctor.js.map +1 -1
- package/dist/cli/commands/doctor.test.js +120 -229
- package/dist/cli/commands/doctor.test.js.map +1 -1
- package/dist/cli/commands/framework-isolation.test.d.ts +1 -1
- package/dist/cli/commands/framework-isolation.test.js +2 -3
- package/dist/cli/commands/framework-isolation.test.js.map +1 -1
- package/dist/cli/commands/help.e2e.test.js +1 -5
- package/dist/cli/commands/help.e2e.test.js.map +1 -1
- package/dist/cli/commands/init-logic.e2e.test.js +114 -2
- package/dist/cli/commands/init-logic.e2e.test.js.map +1 -1
- package/dist/cli/commands/init.test.js +4 -21
- package/dist/cli/commands/init.test.js.map +1 -1
- package/dist/cli/commands/land.d.ts +3 -15
- package/dist/cli/commands/land.d.ts.map +1 -1
- package/dist/cli/commands/land.js +13 -68
- package/dist/cli/commands/land.js.map +1 -1
- package/dist/cli/commands/land.test.d.ts +0 -1
- package/dist/cli/commands/land.test.d.ts.map +1 -1
- package/dist/cli/commands/land.test.js +2 -57
- package/dist/cli/commands/land.test.js.map +1 -1
- package/dist/cli/commands/mcp.e2e.test.js +28 -3
- package/dist/cli/commands/mcp.e2e.test.js.map +1 -1
- package/dist/cli/commands/pipeline.e2e.test.js +23 -26
- package/dist/cli/commands/pipeline.e2e.test.js.map +1 -1
- package/dist/cli/commands/pre-push-guard.d.ts +2 -12
- package/dist/cli/commands/pre-push-guard.d.ts.map +1 -1
- package/dist/cli/commands/pre-push-guard.e2e.test.js +1 -1
- package/dist/cli/commands/pre-push-guard.e2e.test.js.map +1 -1
- package/dist/cli/commands/pre-push-guard.js +2 -47
- package/dist/cli/commands/pre-push-guard.js.map +1 -1
- package/dist/cli/commands/pre-push-guard.test.d.ts +0 -1
- package/dist/cli/commands/pre-push-guard.test.d.ts.map +1 -1
- package/dist/cli/commands/pre-push-guard.test.js +15 -98
- package/dist/cli/commands/pre-push-guard.test.js.map +1 -1
- package/dist/cli/commands/quickstart-expanded.e2e.test.d.ts +1 -1
- package/dist/cli/commands/quickstart-expanded.e2e.test.js +3 -30
- package/dist/cli/commands/quickstart-expanded.e2e.test.js.map +1 -1
- package/dist/cli/commands/quickstart.d.ts +0 -1
- package/dist/cli/commands/quickstart.d.ts.map +1 -1
- package/dist/cli/commands/quickstart.js +2 -60
- package/dist/cli/commands/quickstart.js.map +1 -1
- package/dist/cli/commands/quickstart.test.js +10 -104
- package/dist/cli/commands/quickstart.test.js.map +1 -1
- package/dist/cli/commands/uninstall.test.d.ts +5 -0
- package/dist/cli/commands/uninstall.test.d.ts.map +1 -0
- package/dist/cli/commands/uninstall.test.js +223 -0
- package/dist/cli/commands/uninstall.test.js.map +1 -0
- package/dist/cli/commands/update.d.ts +35 -0
- package/dist/cli/commands/update.d.ts.map +1 -0
- package/dist/cli/commands/update.e2e.test.d.ts +24 -0
- package/dist/cli/commands/update.e2e.test.d.ts.map +1 -0
- package/dist/cli/commands/update.e2e.test.js +238 -0
- package/dist/cli/commands/update.e2e.test.js.map +1 -0
- package/dist/cli/commands/update.js +255 -0
- package/dist/cli/commands/update.js.map +1 -0
- package/dist/core/agents/frontmatter.test.js +1 -1
- package/dist/core/agents/frontmatter.test.js.map +1 -1
- package/dist/core/agents/handoffs.test.js +1 -1
- package/dist/core/agents/handoffs.test.js.map +1 -1
- package/dist/core/agents/loader.d.ts +4 -2
- package/dist/core/agents/loader.d.ts.map +1 -1
- package/dist/core/agents/loader.js +5 -3
- package/dist/core/agents/loader.js.map +1 -1
- package/dist/core/agents/loader.test.js +42 -4
- package/dist/core/agents/loader.test.js.map +1 -1
- package/dist/core/agents/suite.test.js +8 -7
- package/dist/core/agents/suite.test.js.map +1 -1
- package/dist/core/agents/tools.test.js +10 -8
- package/dist/core/agents/tools.test.js.map +1 -1
- package/dist/core/agents/types.test.js +1 -1
- package/dist/core/agents/types.test.js.map +1 -1
- package/dist/core/skills/loader.test.js +1 -1
- package/dist/core/skills/loader.test.js.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -2
- package/dist/index.js.map +1 -1
- package/dist/lib/pathValidation.d.ts +0 -5
- package/dist/lib/pathValidation.d.ts.map +1 -1
- package/dist/lib/pathValidation.js +0 -11
- package/dist/lib/pathValidation.js.map +1 -1
- package/dist/lib/pathValidation.test.js +2 -14
- package/dist/lib/pathValidation.test.js.map +1 -1
- package/package.json +3 -6
- package/sbom.json +259 -371
- package/templates/.github/agents/beth.agent.md +194 -122
- package/templates/.github/agents/developer.agent.md +30 -22
- package/templates/.github/agents/product-manager.agent.md +15 -6
- package/templates/.github/agents/researcher.agent.md +10 -7
- package/templates/.github/agents/security-reviewer.agent.md +16 -7
- package/templates/.github/agents/tester.agent.md +16 -8
- package/templates/.github/agents/ux-designer.agent.md +12 -9
- package/templates/.github/copilot-instructions.md +33 -4
- package/templates/.github/copilot-mcp-config.json +12 -0
- package/templates/.github/dependabot.yml +68 -0
- package/templates/.github/hooks/scripts/inject-skills.mjs +139 -0
- package/templates/.github/hooks/scripts/verify-skills.mjs +47 -0
- package/templates/.github/hooks/skill-enforcement.json +18 -0
- package/templates/.github/pull_request_template.md +48 -0
- package/templates/.github/skills/framer-components/SKILL.md +0 -0
- package/templates/.github/skills/prd/SKILL.md +0 -0
- package/templates/.github/skills/security-analysis/SKILL.md +798 -798
- package/templates/.github/skills/shadcn-ui/SKILL.md +561 -561
- package/templates/.github/skills/vercel-react-best-practices/AGENTS.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/SKILL.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/advanced-event-handler-refs.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/advanced-use-latest.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/async-api-routes.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/async-defer-await.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/async-dependencies.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/async-parallel.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/async-suspense-boundaries.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/bundle-barrel-imports.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/bundle-conditional.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/bundle-defer-third-party.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/bundle-dynamic-imports.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/bundle-preload.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/client-event-listeners.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/client-localstorage-schema.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/client-passive-event-listeners.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/client-swr-dedup.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/js-batch-dom-css.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/js-cache-function-results.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/js-cache-property-access.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/js-cache-storage.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/js-combine-iterations.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/js-early-exit.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/js-hoist-regexp.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/js-index-maps.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/js-length-check-first.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/js-min-max-loop.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/js-set-map-lookups.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/js-tosorted-immutable.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/rendering-activity.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/rendering-conditional-render.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/rendering-content-visibility.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/rendering-hoist-jsx.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/rendering-svg-precision.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/rerender-defer-reads.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/rerender-dependencies.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/rerender-derived-state.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/rerender-functional-setstate.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/rerender-lazy-state-init.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/rerender-memo.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/rerender-simple-expression-in-memo.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/rerender-transitions.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/server-after-nonblocking.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/server-auth-actions.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/server-cache-lru.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/server-cache-react.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/server-dedup-props.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/server-parallel-fetching.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/server-serialization.md +0 -0
- package/templates/.github/skills/web-design-guidelines/SKILL.md +0 -0
- package/templates/.vscode/settings.json +16 -16
- package/templates/AGENTS.md +59 -98
- package/templates/Backlog.md +80 -80
- package/templates/mcp.json.example +8 -0
- package/assets/beth-portrait-small.txt +0 -13
- package/assets/beth-portrait.txt +0 -60
- package/bin/beth-animation.sh +0 -155
- package/bin/lib/animation.js +0 -189
- package/bin/lib/pathValidation.js +0 -233
- package/bin/lib/pathValidation.test.js +0 -280
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Close Command —
|
|
2
|
+
* Close Command — DEPRECATED
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* - Passes through to `bd close` when all checks pass
|
|
10
|
-
* - --force bypasses enforcement checks
|
|
4
|
+
* Previously wrapped `bd close` with dependency enforcement.
|
|
5
|
+
* Beads has been removed — use Backlog.md for task tracking.
|
|
6
|
+
*
|
|
7
|
+
* This command is retained as a no-op with a helpful message
|
|
8
|
+
* to guide users who have muscle memory from the old workflow.
|
|
11
9
|
*/
|
|
12
|
-
import { execFileSync } from 'child_process';
|
|
13
10
|
const COLORS = {
|
|
14
11
|
reset: '\x1b[0m',
|
|
15
12
|
bright: '\x1b[1m',
|
|
@@ -18,153 +15,23 @@ const COLORS = {
|
|
|
18
15
|
yellow: '\x1b[33m',
|
|
19
16
|
cyan: '\x1b[36m',
|
|
20
17
|
};
|
|
21
|
-
//
|
|
22
|
-
// e.g. beth-cip, beth-cip.1, beth-abc123, hq-xyz.42
|
|
18
|
+
// Kept for test compatibility
|
|
23
19
|
const ISSUE_ID_PATTERN = /^[a-z]+-[a-z0-9]{2,10}(\.\d+)?$/;
|
|
24
|
-
// Test subtask title patterns — at least one of each category required for epics
|
|
25
20
|
const TEST_PATTERNS = {
|
|
26
21
|
unit: /\bunit\s+test/i,
|
|
27
22
|
e2e: /\b(e2e|end.to.end|integration)\s+test/i,
|
|
28
23
|
security: /\bsecurity\s+test/i,
|
|
29
24
|
};
|
|
30
|
-
/**
|
|
31
|
-
* Validate a beads issue ID format.
|
|
32
|
-
* Strict pattern prevents injection via execFileSync args.
|
|
33
|
-
*/
|
|
34
25
|
export function validateIssueId(id) {
|
|
35
26
|
return ISSUE_ID_PATTERN.test(id);
|
|
36
27
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
export function
|
|
42
|
-
try {
|
|
43
|
-
const output = execFileSync('bd', ['show', issueId, '--json'], {
|
|
44
|
-
encoding: 'utf-8',
|
|
45
|
-
timeout: 10000,
|
|
46
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
47
|
-
});
|
|
48
|
-
const parsed = JSON.parse(output);
|
|
49
|
-
// bd show --json returns an array with one item
|
|
50
|
-
if (Array.isArray(parsed) && parsed.length > 0) {
|
|
51
|
-
const item = parsed[0];
|
|
52
|
-
if (typeof item === 'object' &&
|
|
53
|
-
item !== null &&
|
|
54
|
-
'id' in item &&
|
|
55
|
-
'issue_type' in item) {
|
|
56
|
-
return item;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
return null;
|
|
60
|
-
}
|
|
61
|
-
catch {
|
|
62
|
-
return null;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
* Get open children for an issue via `bd children --json`.
|
|
67
|
-
* Returns empty array if issue has no children or bd is unavailable.
|
|
68
|
-
*/
|
|
69
|
-
export function getOpenChildren(issueId) {
|
|
70
|
-
try {
|
|
71
|
-
const output = execFileSync('bd', ['children', issueId, '--json'], {
|
|
72
|
-
encoding: 'utf-8',
|
|
73
|
-
timeout: 10000,
|
|
74
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
75
|
-
});
|
|
76
|
-
const parsed = JSON.parse(output);
|
|
77
|
-
// bd children --json returns an array (only open children by default)
|
|
78
|
-
if (!Array.isArray(parsed)) {
|
|
79
|
-
return [];
|
|
80
|
-
}
|
|
81
|
-
return parsed
|
|
82
|
-
.filter((item) => typeof item === 'object' &&
|
|
83
|
-
item !== null &&
|
|
84
|
-
'id' in item &&
|
|
85
|
-
'title' in item &&
|
|
86
|
-
'status' in item)
|
|
87
|
-
.filter((child) => child.status !== 'closed');
|
|
88
|
-
}
|
|
89
|
-
catch {
|
|
90
|
-
// bd not available, no children, or parse error — allow close
|
|
91
|
-
return [];
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
/**
|
|
95
|
-
* Get ALL children (including closed) for test subtask validation.
|
|
96
|
-
* Uses bd show --json which includes dependents.
|
|
97
|
-
*/
|
|
98
|
-
export function getAllChildren(issueId) {
|
|
99
|
-
try {
|
|
100
|
-
// bd show returns dependents array with all children
|
|
101
|
-
const output = execFileSync('bd', ['show', issueId, '--json'], {
|
|
102
|
-
encoding: 'utf-8',
|
|
103
|
-
timeout: 10000,
|
|
104
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
105
|
-
});
|
|
106
|
-
const parsed = JSON.parse(output);
|
|
107
|
-
if (!Array.isArray(parsed) || parsed.length === 0) {
|
|
108
|
-
return [];
|
|
109
|
-
}
|
|
110
|
-
const issue = parsed[0];
|
|
111
|
-
if (typeof issue !== 'object' ||
|
|
112
|
-
issue === null ||
|
|
113
|
-
!('dependents' in issue)) {
|
|
114
|
-
return [];
|
|
115
|
-
}
|
|
116
|
-
const dependents = issue.dependents;
|
|
117
|
-
if (!Array.isArray(dependents)) {
|
|
118
|
-
return [];
|
|
119
|
-
}
|
|
120
|
-
return dependents.filter((item) => typeof item === 'object' &&
|
|
121
|
-
item !== null &&
|
|
122
|
-
'id' in item &&
|
|
123
|
-
'title' in item &&
|
|
124
|
-
'status' in item);
|
|
125
|
-
}
|
|
126
|
-
catch {
|
|
127
|
-
return [];
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
/**
|
|
131
|
-
* Get open blockers for an issue via `bd dep list --json`.
|
|
132
|
-
* Returns only non-parent-child dependencies that are still open.
|
|
133
|
-
*/
|
|
134
|
-
export function getOpenBlockers(issueId) {
|
|
135
|
-
try {
|
|
136
|
-
const output = execFileSync('bd', ['dep', 'list', issueId, '--json'], {
|
|
137
|
-
encoding: 'utf-8',
|
|
138
|
-
timeout: 10000,
|
|
139
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
140
|
-
});
|
|
141
|
-
const parsed = JSON.parse(output);
|
|
142
|
-
if (!Array.isArray(parsed)) {
|
|
143
|
-
return [];
|
|
144
|
-
}
|
|
145
|
-
return parsed
|
|
146
|
-
.filter((item) => typeof item === 'object' &&
|
|
147
|
-
item !== null &&
|
|
148
|
-
'id' in item &&
|
|
149
|
-
'title' in item &&
|
|
150
|
-
'status' in item &&
|
|
151
|
-
'dependency_type' in item)
|
|
152
|
-
.filter((dep) => dep.dependency_type !== 'parent-child' && dep.status !== 'closed');
|
|
153
|
-
}
|
|
154
|
-
catch {
|
|
155
|
-
return [];
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
/**
|
|
159
|
-
* Check if an epic has the mandatory test subtasks.
|
|
160
|
-
* Returns list of missing test categories.
|
|
161
|
-
*/
|
|
28
|
+
// Stubs — beads removed
|
|
29
|
+
export function getIssueInfo(_issueId) { return null; }
|
|
30
|
+
export function getOpenChildren(_issueId) { return []; }
|
|
31
|
+
export function getAllChildren(_issueId) { return []; }
|
|
32
|
+
export function getOpenBlockers(_issueId) { return []; }
|
|
162
33
|
export function getMissingTestSubtasks(children) {
|
|
163
|
-
const found = {
|
|
164
|
-
unit: false,
|
|
165
|
-
e2e: false,
|
|
166
|
-
security: false,
|
|
167
|
-
};
|
|
34
|
+
const found = { unit: false, e2e: false, security: false };
|
|
168
35
|
for (const child of children) {
|
|
169
36
|
if (TEST_PATTERNS.unit.test(child.title))
|
|
170
37
|
found.unit = true;
|
|
@@ -182,10 +49,6 @@ export function getMissingTestSubtasks(children) {
|
|
|
182
49
|
missing.push('Security tests');
|
|
183
50
|
return missing;
|
|
184
51
|
}
|
|
185
|
-
/**
|
|
186
|
-
* Parse close command arguments.
|
|
187
|
-
* Returns issue IDs, reason, and flags.
|
|
188
|
-
*/
|
|
189
52
|
export function parseCloseArgs(rawArgs) {
|
|
190
53
|
const issueIds = [];
|
|
191
54
|
let reason;
|
|
@@ -196,7 +59,6 @@ export function parseCloseArgs(rawArgs) {
|
|
|
196
59
|
force = true;
|
|
197
60
|
}
|
|
198
61
|
else if (arg === '--reason' || arg === '-r') {
|
|
199
|
-
// Next arg is the reason text
|
|
200
62
|
reason = rawArgs[++i];
|
|
201
63
|
}
|
|
202
64
|
else if (arg.startsWith('--reason=')) {
|
|
@@ -205,105 +67,29 @@ export function parseCloseArgs(rawArgs) {
|
|
|
205
67
|
else if (!arg.startsWith('-')) {
|
|
206
68
|
issueIds.push(arg);
|
|
207
69
|
}
|
|
208
|
-
// Skip other flags (--json, --verbose, etc.)
|
|
209
70
|
}
|
|
210
71
|
return { issueIds, reason, force };
|
|
211
72
|
}
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
// Validate issue ID format
|
|
218
|
-
if (!validateIssueId(issueId)) {
|
|
219
|
-
console.error(`${COLORS.red}✗ Invalid issue ID: "${issueId}"${COLORS.reset}`);
|
|
220
|
-
console.error(` Expected format: <rig>-<hash>[.<number>] (e.g. beth-abc123, beth-abc123.1)`);
|
|
221
|
-
return { success: false };
|
|
222
|
-
}
|
|
223
|
-
if (!options.force) {
|
|
224
|
-
// 1. Check for open blockers (non-parent dependencies)
|
|
225
|
-
const openBlockers = getOpenBlockers(issueId);
|
|
226
|
-
if (openBlockers.length > 0) {
|
|
227
|
-
console.error(`\n${COLORS.red}✗ Cannot close ${COLORS.bright}${issueId}${COLORS.reset}${COLORS.red} — ${openBlockers.length} unresolved blocker${openBlockers.length === 1 ? '' : 's'}:${COLORS.reset}\n`);
|
|
228
|
-
for (const blocker of openBlockers) {
|
|
229
|
-
console.error(` ● ${COLORS.cyan}${blocker.id}${COLORS.reset}: ${blocker.title} [${blocker.status}] (${blocker.dependency_type})`);
|
|
230
|
-
}
|
|
231
|
-
console.error(`\n${COLORS.yellow}Resolve blockers first, or use --force to override.${COLORS.reset}\n`);
|
|
232
|
-
return { success: false, blockers: openBlockers };
|
|
233
|
-
}
|
|
234
|
-
// 2. Check for open children
|
|
235
|
-
const openChildren = getOpenChildren(issueId);
|
|
236
|
-
if (openChildren.length > 0) {
|
|
237
|
-
console.error(`\n${COLORS.red}✗ Cannot close ${COLORS.bright}${issueId}${COLORS.reset}${COLORS.red} — ${openChildren.length} open child${openChildren.length === 1 ? '' : 'ren'}:${COLORS.reset}\n`);
|
|
238
|
-
for (const child of openChildren) {
|
|
239
|
-
console.error(` ○ ${COLORS.cyan}${child.id}${COLORS.reset}: ${child.title} [${child.status}]`);
|
|
240
|
-
}
|
|
241
|
-
console.error(`\n${COLORS.yellow}Close all children first, or use --force to override.${COLORS.reset}\n`);
|
|
242
|
-
return { success: false, blocked: openChildren };
|
|
243
|
-
}
|
|
244
|
-
// 3. For epics: verify mandatory test subtasks exist
|
|
245
|
-
const issueInfo = getIssueInfo(issueId);
|
|
246
|
-
if (issueInfo && issueInfo.issue_type === 'epic') {
|
|
247
|
-
// Prefer children/dependents from the existing bd show response for this epic,
|
|
248
|
-
// falling back to getAllChildren(issueId) only if necessary.
|
|
249
|
-
const allChildren = (Array.isArray(issueInfo.dependents) &&
|
|
250
|
-
issueInfo.dependents.length > 0
|
|
251
|
-
? issueInfo.dependents
|
|
252
|
-
: getAllChildren(issueId));
|
|
253
|
-
const missingTests = getMissingTestSubtasks(allChildren);
|
|
254
|
-
if (missingTests.length > 0) {
|
|
255
|
-
console.error(`\n${COLORS.red}✗ Cannot close epic ${COLORS.bright}${issueId}${COLORS.reset}${COLORS.red} — missing mandatory test subtasks:${COLORS.reset}\n`);
|
|
256
|
-
for (const missing of missingTests) {
|
|
257
|
-
console.error(` ✗ ${COLORS.yellow}${missing}${COLORS.reset}`);
|
|
258
|
-
}
|
|
259
|
-
console.error(`\n${COLORS.yellow}Create test subtasks with: bd create "<type> tests for <feature>" --parent ${issueId}${COLORS.reset}`);
|
|
260
|
-
console.error(`${COLORS.yellow}Or use --force to override.${COLORS.reset}\n`);
|
|
261
|
-
return { success: false, missingTests };
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
// Build bd close args
|
|
266
|
-
const bdArgs = ['close', issueId];
|
|
267
|
-
if (options.reason) {
|
|
268
|
-
bdArgs.push('--reason', options.reason);
|
|
269
|
-
}
|
|
270
|
-
if (options.force) {
|
|
271
|
-
bdArgs.push('--force');
|
|
272
|
-
}
|
|
273
|
-
// Execute bd close (no shell — execFileSync is injection-safe)
|
|
274
|
-
try {
|
|
275
|
-
execFileSync('bd', bdArgs, {
|
|
276
|
-
encoding: 'utf-8',
|
|
277
|
-
timeout: 10000,
|
|
278
|
-
stdio: 'inherit',
|
|
279
|
-
});
|
|
280
|
-
return { success: true };
|
|
281
|
-
}
|
|
282
|
-
catch {
|
|
283
|
-
return { success: false };
|
|
284
|
-
}
|
|
73
|
+
export function closeIssue(_issueId, _options) {
|
|
74
|
+
console.log(`${COLORS.yellow}⚠ The 'close' command has been deprecated.${COLORS.reset}`);
|
|
75
|
+
console.log(` Beads has been removed. Use Backlog.md for task tracking.`);
|
|
76
|
+
console.log(` Example: backlog task edit <task-id> -s "Done"`);
|
|
77
|
+
return { success: false };
|
|
285
78
|
}
|
|
286
79
|
/**
|
|
287
80
|
* Main close command entry point.
|
|
288
|
-
* Called from CLI routing with raw args after 'close'.
|
|
289
81
|
*/
|
|
290
82
|
export async function close(rawArgs) {
|
|
291
|
-
const { issueIds
|
|
83
|
+
const { issueIds } = parseCloseArgs(rawArgs);
|
|
292
84
|
if (issueIds.length === 0) {
|
|
293
|
-
console.
|
|
294
|
-
console.
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
}
|
|
298
|
-
let allSucceeded = true;
|
|
299
|
-
for (const id of issueIds) {
|
|
300
|
-
const result = closeIssue(id, { reason, force });
|
|
301
|
-
if (!result.success) {
|
|
302
|
-
allSucceeded = false;
|
|
303
|
-
}
|
|
85
|
+
console.log(`${COLORS.yellow}⚠ The 'close' command has been deprecated.${COLORS.reset}`);
|
|
86
|
+
console.log(` Beads has been removed. Use Backlog.md for task tracking.`);
|
|
87
|
+
process.exitCode = 1;
|
|
88
|
+
return;
|
|
304
89
|
}
|
|
305
|
-
|
|
306
|
-
|
|
90
|
+
for (const _id of issueIds) {
|
|
91
|
+
closeIssue(_id, {});
|
|
307
92
|
}
|
|
93
|
+
process.exitCode = 1;
|
|
308
94
|
}
|
|
309
95
|
//# sourceMappingURL=close.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"close.js","sourceRoot":"","sources":["../../../src/cli/commands/close.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"close.js","sourceRoot":"","sources":["../../../src/cli/commands/close.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Close Command Tests
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* -
|
|
7
|
-
* -
|
|
8
|
-
* -
|
|
9
|
-
* -
|
|
10
|
-
* -
|
|
11
|
-
* - Blocked close behavior
|
|
12
|
-
* - Force bypass
|
|
4
|
+
* The close command is deprecated — beads has been removed.
|
|
5
|
+
* Tests verify:
|
|
6
|
+
* - Issue ID validation (still has real logic)
|
|
7
|
+
* - Stub functions return expected values (null / empty arrays)
|
|
8
|
+
* - getMissingTestSubtasks (still has real logic)
|
|
9
|
+
* - Arg parsing (still has real logic)
|
|
10
|
+
* - closeIssue prints deprecation and returns success: false
|
|
13
11
|
*/
|
|
14
12
|
export {};
|
|
15
13
|
//# sourceMappingURL=close.test.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"close.test.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/close.test.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"close.test.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/close.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG"}
|