@chief-clancy/plan 0.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/LICENSE +21 -0
- package/README.md +81 -0
- package/bin/plan.js +237 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/installer/install.d.ts +62 -0
- package/dist/installer/install.d.ts.map +1 -0
- package/dist/installer/install.js +126 -0
- package/dist/installer/install.js.map +1 -0
- package/package.json +48 -0
- package/src/commands/board-setup.md +11 -0
- package/src/commands/commands.test.ts +39 -0
- package/src/commands/plan.md +22 -0
- package/src/workflows/board-setup.md +369 -0
- package/src/workflows/plan.md +893 -0
- package/src/workflows/workflows.test.ts +168 -0
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structural tests for plan workflow files.
|
|
3
|
+
*
|
|
4
|
+
* Verifies the workflows directory contains the expected markdown files
|
|
5
|
+
* that the plan installer depends on.
|
|
6
|
+
*/
|
|
7
|
+
import { readdirSync, readFileSync } from 'node:fs';
|
|
8
|
+
import { fileURLToPath } from 'node:url';
|
|
9
|
+
|
|
10
|
+
import { describe, expect, it } from 'vitest';
|
|
11
|
+
|
|
12
|
+
const WORKFLOWS_DIR = fileURLToPath(new URL('.', import.meta.url));
|
|
13
|
+
|
|
14
|
+
const EXPECTED_WORKFLOWS = ['board-setup.md', 'plan.md'];
|
|
15
|
+
|
|
16
|
+
describe('workflows directory structure', () => {
|
|
17
|
+
it('contains exactly the expected workflow files', () => {
|
|
18
|
+
const workflows = readdirSync(WORKFLOWS_DIR)
|
|
19
|
+
.filter((f) => f.endsWith('.md'))
|
|
20
|
+
.sort();
|
|
21
|
+
|
|
22
|
+
expect(workflows).toEqual([...EXPECTED_WORKFLOWS].sort());
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('all workflow files start with a heading', () => {
|
|
26
|
+
const issues: string[] = [];
|
|
27
|
+
|
|
28
|
+
EXPECTED_WORKFLOWS.forEach((file) => {
|
|
29
|
+
const content = readFileSync(new URL(file, import.meta.url), 'utf8');
|
|
30
|
+
const firstLine = content.split('\n')[0]?.trim() ?? '';
|
|
31
|
+
|
|
32
|
+
if (!firstLine.startsWith('#')) {
|
|
33
|
+
issues.push(file);
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
expect(issues).toEqual([]);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('plan workflow references Step 1', () => {
|
|
41
|
+
const content = readFileSync(new URL('plan.md', import.meta.url), 'utf8');
|
|
42
|
+
|
|
43
|
+
expect(content).toContain('## Step 1');
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
// ---------------------------------------------------------------------------
|
|
48
|
+
// board-setup.md content assertions
|
|
49
|
+
// ---------------------------------------------------------------------------
|
|
50
|
+
|
|
51
|
+
describe('board-setup workflow', () => {
|
|
52
|
+
const content = readFileSync(
|
|
53
|
+
new URL('board-setup.md', import.meta.url),
|
|
54
|
+
'utf8',
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
it('checks for full pipeline before proceeding', () => {
|
|
58
|
+
expect(content).toContain('clancy-implement.js');
|
|
59
|
+
expect(content).toContain('/clancy:settings');
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('checks for existing board credentials', () => {
|
|
63
|
+
expect(content).toContain('Existing board credentials found');
|
|
64
|
+
expect(content).toContain('Reconfigure');
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('offers all 6 supported boards', () => {
|
|
68
|
+
expect(content).toContain('Jira');
|
|
69
|
+
expect(content).toContain('GitHub Issues');
|
|
70
|
+
expect(content).toContain('Linear');
|
|
71
|
+
expect(content).toContain('Shortcut');
|
|
72
|
+
expect(content).toContain('Notion');
|
|
73
|
+
expect(content).toContain('Azure DevOps');
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('includes credential prompts for each board', () => {
|
|
77
|
+
expect(content).toContain('JIRA_BASE_URL');
|
|
78
|
+
expect(content).toContain('GITHUB_TOKEN');
|
|
79
|
+
expect(content).toContain('LINEAR_API_KEY');
|
|
80
|
+
expect(content).toContain('SHORTCUT_API_TOKEN');
|
|
81
|
+
expect(content).toContain('NOTION_TOKEN');
|
|
82
|
+
expect(content).toContain('AZDO_PAT');
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('includes credential verification for each board', () => {
|
|
86
|
+
expect(content).toContain('Jira connected');
|
|
87
|
+
expect(content).toContain('GitHub connected');
|
|
88
|
+
expect(content).toContain('Linear connected');
|
|
89
|
+
expect(content).toContain('Shortcut connected');
|
|
90
|
+
expect(content).toContain('Notion connected');
|
|
91
|
+
expect(content).toContain('Azure DevOps connected');
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it('offers re-enter, skip, and cancel on verification failure', () => {
|
|
95
|
+
expect(content).toContain('Re-enter credentials');
|
|
96
|
+
expect(content).toContain('Skip verification');
|
|
97
|
+
expect(content).toContain('Cancel');
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it('warns about .gitignore', () => {
|
|
101
|
+
expect(content).toContain('.gitignore');
|
|
102
|
+
expect(content).toContain('.clancy/.env');
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it('notes credentials are per-project', () => {
|
|
106
|
+
expect(content).toContain('this project only');
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it('includes plan header comment in env file', () => {
|
|
110
|
+
expect(content).toContain('Configured by @chief-clancy/plan');
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it('references /clancy:plan not /clancy:brief', () => {
|
|
114
|
+
expect(content).toContain('/clancy:plan');
|
|
115
|
+
expect(content).not.toContain('/clancy:brief');
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
// ---------------------------------------------------------------------------
|
|
120
|
+
// plan.md content assertions
|
|
121
|
+
// ---------------------------------------------------------------------------
|
|
122
|
+
|
|
123
|
+
describe('three-state mode detection', () => {
|
|
124
|
+
const content = readFileSync(new URL('plan.md', import.meta.url), 'utf8');
|
|
125
|
+
|
|
126
|
+
it('Step 1 detects three installation states', () => {
|
|
127
|
+
expect(content).toContain('standalone mode');
|
|
128
|
+
expect(content).toContain('standalone+board mode');
|
|
129
|
+
expect(content).toContain('terminal mode');
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it('Step 1 checks .clancy/.env for credentials', () => {
|
|
133
|
+
expect(content).toContain('.clancy/.env');
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
it('Step 1 checks clancy-implement.js for terminal detection', () => {
|
|
137
|
+
expect(content).toContain('clancy-implement.js');
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it('Step 1 does not hard-stop on missing .clancy/.env', () => {
|
|
141
|
+
expect(content).not.toContain(
|
|
142
|
+
'.clancy/ not found. Run /clancy:init to set up Clancy first.',
|
|
143
|
+
);
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
it('CLANCY_ROLES check only runs in terminal mode', () => {
|
|
147
|
+
expect(content).toContain('Terminal-mode preflight');
|
|
148
|
+
expect(content).toContain(
|
|
149
|
+
'skip in standalone mode and standalone+board mode',
|
|
150
|
+
);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
it('standalone guard mentions /clancy:board-setup', () => {
|
|
154
|
+
expect(content).toContain('Standalone board-ticket guard');
|
|
155
|
+
expect(content).toContain('Board credentials not found');
|
|
156
|
+
expect(content).toContain('/clancy:board-setup');
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
it('Step 5 runs when board credentials are available', () => {
|
|
160
|
+
expect(content).toContain(
|
|
161
|
+
'when board credentials are available (terminal mode or standalone+board mode)',
|
|
162
|
+
);
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
it('approve-plan references include standalone guidance', () => {
|
|
166
|
+
expect(content).toContain('npx chief-clancy');
|
|
167
|
+
});
|
|
168
|
+
});
|