@chief-clancy/brief 0.1.0 → 0.1.2
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 +83 -0
- package/bin/brief.js +38 -24
- package/dist/installer/install.js +2 -2
- package/dist/installer/install.js.map +1 -1
- package/package.json +1 -1
- package/src/commands/board-setup.md +11 -0
- package/src/commands/brief.md +1 -1
- package/src/commands/commands.test.ts +1 -1
- package/src/workflows/board-setup.md +370 -0
- package/src/workflows/brief.md +66 -35
- package/src/workflows/workflows.test.ts +129 -1
package/README.md
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# @chief-clancy/brief
|
|
2
|
+
|
|
3
|
+
**Strategic brief generator for Claude Code.**
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@chief-clancy/brief) [](../../LICENSE)
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npx @chief-clancy/brief
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Turn feature ideas into structured strategic briefs with vertical-slice ticket decomposition. Works standalone — no board credentials, no pipeline, no config required.
|
|
12
|
+
|
|
13
|
+
## What it does
|
|
14
|
+
|
|
15
|
+
The `/clancy:brief` slash command researches your codebase, grills you (or itself) on requirements, and produces a brief document with:
|
|
16
|
+
|
|
17
|
+
- Problem statement and goals
|
|
18
|
+
- Discovery Q&A from the grill phase
|
|
19
|
+
- User stories
|
|
20
|
+
- Technical considerations
|
|
21
|
+
- Ticket decomposition table (vertical slices, sized, with dependencies)
|
|
22
|
+
- Open questions and risks
|
|
23
|
+
|
|
24
|
+
## How it works
|
|
25
|
+
|
|
26
|
+
1. **Install:** `npx @chief-clancy/brief` — choose global or local
|
|
27
|
+
2. **Run:** `/clancy:brief "Add dark mode support"` — inline text
|
|
28
|
+
3. **Or from a file:** `/clancy:brief --from docs/rfc.md`
|
|
29
|
+
|
|
30
|
+
Briefs are saved to `.clancy/briefs/` in your project.
|
|
31
|
+
|
|
32
|
+
## Input modes
|
|
33
|
+
|
|
34
|
+
| Mode | Example | Board needed? |
|
|
35
|
+
| ------------ | --------------------------------------------- | --------------------------- |
|
|
36
|
+
| Inline text | `/clancy:brief "Add dark mode"` | No |
|
|
37
|
+
| From file | `/clancy:brief --from docs/rfc.md` | No |
|
|
38
|
+
| Board ticket | `/clancy:brief #42`, `/clancy:brief PROJ-123` | Yes (`/clancy:board-setup`) |
|
|
39
|
+
| Batch | `/clancy:brief 3` | Yes (`/clancy:board-setup`) |
|
|
40
|
+
| Interactive | `/clancy:brief` | No |
|
|
41
|
+
|
|
42
|
+
## Flags
|
|
43
|
+
|
|
44
|
+
| Flag | Description |
|
|
45
|
+
| --------------- | ------------------------------------- |
|
|
46
|
+
| `--afk` | AI-grill instead of human interview |
|
|
47
|
+
| `--fresh` | Discard existing brief and start over |
|
|
48
|
+
| `--research` | Include web research in analysis |
|
|
49
|
+
| `--from <path>` | Brief from a local file |
|
|
50
|
+
| `--epic <KEY>` | Set parent for ticket creation |
|
|
51
|
+
| `--list` | Show inventory of existing briefs |
|
|
52
|
+
|
|
53
|
+
## Board ticket mode (optional)
|
|
54
|
+
|
|
55
|
+
To brief from board tickets without installing the full pipeline:
|
|
56
|
+
|
|
57
|
+
1. Run `/clancy:board-setup` in Claude Code
|
|
58
|
+
2. Follow the prompts to configure your board credentials
|
|
59
|
+
3. Run `/clancy:brief #42` (or your board's ticket format)
|
|
60
|
+
|
|
61
|
+
Credentials are stored in `.clancy/.env` and are per-project (not global).
|
|
62
|
+
|
|
63
|
+
## Full pipeline
|
|
64
|
+
|
|
65
|
+
For ticket creation, planning, and the full development pipeline, install the complete Clancy package:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
npx chief-clancy
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Part of the Clancy monorepo
|
|
72
|
+
|
|
73
|
+
- [`chief-clancy`](https://www.npmjs.com/package/chief-clancy) — full pipeline (install, configure, implement, autopilot)
|
|
74
|
+
- [`@chief-clancy/terminal`](https://www.npmjs.com/package/@chief-clancy/terminal) — installer, slash commands, hooks, runners
|
|
75
|
+
- [`@chief-clancy/core`](https://www.npmjs.com/package/@chief-clancy/core) — board integrations, pipeline phases, schemas
|
|
76
|
+
|
|
77
|
+
## Credits
|
|
78
|
+
|
|
79
|
+
Built on the [Ralph technique](https://ghuntley.com/ralph/) by Geoffrey Huntley. See [CREDITS.md](https://github.com/Pushedskydiver/chief-clancy/blob/main/CREDITS.md).
|
|
80
|
+
|
|
81
|
+
## License
|
|
82
|
+
|
|
83
|
+
MIT — see [LICENSE](https://github.com/Pushedskydiver/chief-clancy/blob/main/LICENSE).
|
package/bin/brief.js
CHANGED
|
@@ -80,6 +80,14 @@ const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
|
80
80
|
/** @param {string} label */
|
|
81
81
|
const ask = (label) => new Promise((resolve) => rl.question(label, resolve));
|
|
82
82
|
|
|
83
|
+
// ---------------------------------------------------------------------------
|
|
84
|
+
// File lists (keep in sync with install.ts)
|
|
85
|
+
// ---------------------------------------------------------------------------
|
|
86
|
+
|
|
87
|
+
const COMMAND_FILES = ['board-setup.md', 'brief.md'];
|
|
88
|
+
const WORKFLOW_FILES = ['board-setup.md', 'brief.md'];
|
|
89
|
+
const AGENT_FILES = ['devils-advocate.md'];
|
|
90
|
+
|
|
83
91
|
// ---------------------------------------------------------------------------
|
|
84
92
|
// Installer
|
|
85
93
|
// ---------------------------------------------------------------------------
|
|
@@ -102,20 +110,23 @@ function copyChecked(src, dest) {
|
|
|
102
110
|
}
|
|
103
111
|
|
|
104
112
|
/** Inline workflow @-references into command files (global mode only). */
|
|
105
|
-
function
|
|
113
|
+
function inlineWorkflows(commandsDest, workflowsDest) {
|
|
106
114
|
const WORKFLOW_REF = /^@\.claude\/clancy\/workflows\/([^/\\]+\.md)\r?$/gm;
|
|
107
|
-
const cmdPath = join(commandsDest, 'brief.md');
|
|
108
|
-
const content = readFileSync(cmdPath, 'utf8');
|
|
109
|
-
const resolved = content.replace(WORKFLOW_REF, (match, fileName) => {
|
|
110
|
-
const wfPath = join(workflowsDest, fileName);
|
|
111
|
-
if (!existsSync(wfPath)) return match;
|
|
112
|
-
return readFileSync(wfPath, 'utf8');
|
|
113
|
-
});
|
|
114
115
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
116
|
+
COMMAND_FILES.forEach((file) => {
|
|
117
|
+
const cmdPath = join(commandsDest, file);
|
|
118
|
+
const content = readFileSync(cmdPath, 'utf8');
|
|
119
|
+
const resolved = content.replace(WORKFLOW_REF, (match, fileName) => {
|
|
120
|
+
const wfPath = join(workflowsDest, fileName);
|
|
121
|
+
if (!existsSync(wfPath)) return match;
|
|
122
|
+
return readFileSync(wfPath, 'utf8');
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
if (resolved !== content) {
|
|
126
|
+
rejectSymlink(cmdPath);
|
|
127
|
+
writeFileSync(cmdPath, resolved);
|
|
128
|
+
}
|
|
129
|
+
});
|
|
119
130
|
}
|
|
120
131
|
|
|
121
132
|
// ---------------------------------------------------------------------------
|
|
@@ -178,22 +189,19 @@ async function main() {
|
|
|
178
189
|
mkdirSync(agentsDest, { recursive: true });
|
|
179
190
|
|
|
180
191
|
// Copy files
|
|
181
|
-
|
|
182
|
-
join(sources.commandsDir,
|
|
183
|
-
join(commandsDest, 'brief.md'),
|
|
192
|
+
COMMAND_FILES.forEach((f) =>
|
|
193
|
+
copyChecked(join(sources.commandsDir, f), join(commandsDest, f)),
|
|
184
194
|
);
|
|
185
|
-
|
|
186
|
-
join(sources.workflowsDir,
|
|
187
|
-
join(workflowsDest, 'brief.md'),
|
|
195
|
+
WORKFLOW_FILES.forEach((f) =>
|
|
196
|
+
copyChecked(join(sources.workflowsDir, f), join(workflowsDest, f)),
|
|
188
197
|
);
|
|
189
|
-
|
|
190
|
-
join(sources.agentsDir,
|
|
191
|
-
join(agentsDest, 'devils-advocate.md'),
|
|
198
|
+
AGENT_FILES.forEach((f) =>
|
|
199
|
+
copyChecked(join(sources.agentsDir, f), join(agentsDest, f)),
|
|
192
200
|
);
|
|
193
201
|
|
|
194
202
|
// Inline workflows for global mode
|
|
195
203
|
if (mode === 'global') {
|
|
196
|
-
|
|
204
|
+
inlineWorkflows(commandsDest, workflowsDest);
|
|
197
205
|
}
|
|
198
206
|
|
|
199
207
|
// Write version marker
|
|
@@ -205,15 +213,21 @@ async function main() {
|
|
|
205
213
|
console.log('');
|
|
206
214
|
console.log(green(' ✓ Clancy Brief installed successfully.'));
|
|
207
215
|
console.log('');
|
|
208
|
-
console.log('
|
|
216
|
+
console.log(' Commands available:');
|
|
209
217
|
console.log(
|
|
210
|
-
` ${cyan('/clancy:brief')}
|
|
218
|
+
` ${cyan('/clancy:brief')} ${dim('Generate a strategic brief')}`,
|
|
219
|
+
);
|
|
220
|
+
console.log(
|
|
221
|
+
` ${cyan('/clancy:board-setup')} ${dim('Configure board credentials (optional)')}`,
|
|
211
222
|
);
|
|
212
223
|
console.log('');
|
|
213
224
|
console.log(' Next steps:');
|
|
214
225
|
console.log(` 1. Open a project in Claude Code`);
|
|
215
226
|
console.log(` 2. Run: ${cyan('/clancy:brief "Your feature idea"')}`);
|
|
216
227
|
console.log('');
|
|
228
|
+
console.log(dim(' Want to brief from board tickets?'));
|
|
229
|
+
console.log(dim(` Run: ${cyan('/clancy:board-setup')}`));
|
|
230
|
+
console.log('');
|
|
217
231
|
console.log(
|
|
218
232
|
dim(' For the full pipeline (tickets, planning, implementation):'),
|
|
219
233
|
);
|
|
@@ -10,9 +10,9 @@ import { join } from 'node:path';
|
|
|
10
10
|
// Constants
|
|
11
11
|
// ---------------------------------------------------------------------------
|
|
12
12
|
/** Command files shipped with the brief package. */
|
|
13
|
-
const COMMAND_FILES = ['brief.md'];
|
|
13
|
+
const COMMAND_FILES = ['board-setup.md', 'brief.md'];
|
|
14
14
|
/** Workflow files shipped with the brief package. */
|
|
15
|
-
const WORKFLOW_FILES = ['brief.md'];
|
|
15
|
+
const WORKFLOW_FILES = ['board-setup.md', 'brief.md'];
|
|
16
16
|
/** Agent files shipped with the brief package. */
|
|
17
17
|
const AGENT_FILES = ['devils-advocate.md'];
|
|
18
18
|
/** Matches `@.claude/clancy/workflows/<filename>.md` on its own line. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/installer/install.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AA+CjC,8EAA8E;AAC9E,YAAY;AACZ,8EAA8E;AAE9E,oDAAoD;AACpD,MAAM,aAAa,GAAG,CAAC,UAAU,CAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/installer/install.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# /clancy:board-setup
|
|
2
|
+
|
|
3
|
+
Configure board credentials for standalone brief usage. Connects your project to a Kanban board so you can brief from board tickets.
|
|
4
|
+
|
|
5
|
+
Not needed if you have the full Clancy pipeline installed (`npx chief-clancy`) — use `/clancy:settings` instead.
|
|
6
|
+
|
|
7
|
+
Supported boards: Jira, GitHub Issues, Linear, Shortcut, Notion, Azure DevOps.
|
|
8
|
+
|
|
9
|
+
@.claude/clancy/workflows/board-setup.md
|
|
10
|
+
|
|
11
|
+
Follow the board setup workflow above. Collect credentials, verify the connection, and write them to `.clancy/.env`.
|
package/src/commands/brief.md
CHANGED
|
@@ -4,7 +4,7 @@ Generate a strategic brief for a feature idea. Researches the codebase, grills y
|
|
|
4
4
|
|
|
5
5
|
Accepts optional arguments:
|
|
6
6
|
|
|
7
|
-
- **Board ticket:** `/clancy:brief PROJ-123`, `/clancy:brief #42`, `/clancy:brief ENG-42` — brief from a board ticket
|
|
7
|
+
- **Board ticket:** `/clancy:brief PROJ-123`, `/clancy:brief #42`, `/clancy:brief ENG-42` — brief from a board ticket (requires credentials — run `/clancy:board-setup` or install the full pipeline with `npx chief-clancy`)
|
|
8
8
|
- **Inline text:** `/clancy:brief "Add dark mode"` — brief from a description
|
|
9
9
|
- **From file:** `/clancy:brief --from docs/rfc.md` — brief from a local file
|
|
10
10
|
- **Batch mode:** `/clancy:brief 3` — brief up to 3 tickets from the queue
|
|
@@ -11,7 +11,7 @@ import { describe, expect, it } from 'vitest';
|
|
|
11
11
|
|
|
12
12
|
const COMMANDS_DIR = fileURLToPath(new URL('.', import.meta.url));
|
|
13
13
|
|
|
14
|
-
const EXPECTED_COMMANDS = ['brief.md'];
|
|
14
|
+
const EXPECTED_COMMANDS = ['board-setup.md', 'brief.md'];
|
|
15
15
|
|
|
16
16
|
describe('commands directory structure', () => {
|
|
17
17
|
it('contains exactly the expected command files', () => {
|
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
# Board Setup Workflow
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Configure board credentials so `/clancy:brief` can fetch tickets and post briefs as comments. This workflow collects the minimum credentials needed for board access — no pipeline configuration, no role settings, no iteration limits.
|
|
6
|
+
|
|
7
|
+
Credentials are stored in `.clancy/.env` in the current project directory. They are per-project, not global.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Step 1 — Preflight checks
|
|
12
|
+
|
|
13
|
+
### 1. Check for full pipeline
|
|
14
|
+
|
|
15
|
+
Check if `.clancy/clancy-implement.js` exists in the project root.
|
|
16
|
+
|
|
17
|
+
If present, the full Clancy pipeline is installed. Show:
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
Full Clancy pipeline detected. Use /clancy:settings to manage board credentials.
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Stop. Do not proceed with standalone board setup.
|
|
24
|
+
|
|
25
|
+
### 2. Check for existing credentials
|
|
26
|
+
|
|
27
|
+
Check if `.clancy/.env` exists and contains board credentials (any of: `JIRA_BASE_URL`, `GITHUB_TOKEN`, `LINEAR_API_KEY`, `SHORTCUT_API_TOKEN`, `NOTION_TOKEN`, `AZDO_ORG`, `AZDO_PAT`, `AZDO_PROJECT`).
|
|
28
|
+
|
|
29
|
+
If board credentials are found, show:
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
Existing board credentials found in .clancy/.env.
|
|
33
|
+
|
|
34
|
+
[1] Reconfigure (replace current board)
|
|
35
|
+
[2] Cancel
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
If [2]: stop.
|
|
39
|
+
If [1]: continue to Step 2. The existing `.clancy/.env` will be updated (board-specific vars replaced, other vars preserved).
|
|
40
|
+
|
|
41
|
+
If `.clancy/.env` does not exist, or exists but has no board credentials: continue to Step 2.
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Step 2 — Board selection
|
|
46
|
+
|
|
47
|
+
Output:
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
Which board are you using?
|
|
51
|
+
|
|
52
|
+
[1] Jira
|
|
53
|
+
[2] GitHub Issues
|
|
54
|
+
[3] Linear
|
|
55
|
+
[4] Shortcut
|
|
56
|
+
[5] Notion
|
|
57
|
+
[6] Azure DevOps
|
|
58
|
+
[7] My board isn't listed
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
If the user selects [7], show:
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
Clancy currently supports Jira, GitHub Issues, Linear, Shortcut, Notion, and Azure DevOps.
|
|
65
|
+
|
|
66
|
+
Your board isn't supported yet — open an issue:
|
|
67
|
+
github.com/Pushedskydiver/chief-clancy/issues
|
|
68
|
+
|
|
69
|
+
You can still use /clancy:brief with inline text or file input:
|
|
70
|
+
/clancy:brief "Add dark mode support"
|
|
71
|
+
/clancy:brief --from docs/rfc.md
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Stop.
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Step 3 — Credential collection
|
|
79
|
+
|
|
80
|
+
Ask each question individually and wait for an answer before moving to the next.
|
|
81
|
+
|
|
82
|
+
### Jira
|
|
83
|
+
|
|
84
|
+
1. `What's your Jira base URL? (e.g. https://your-org.atlassian.net)`
|
|
85
|
+
2. `What's your Jira project key? (e.g. PROJ)`
|
|
86
|
+
3. `What email address do you use to log in to Atlassian?`
|
|
87
|
+
4. `Paste your Jira API token: (create one at id.atlassian.com/manage-profile/security/api-tokens)`
|
|
88
|
+
|
|
89
|
+
Store as `JIRA_BASE_URL`, `JIRA_PROJECT_KEY`, `JIRA_USER`, `JIRA_API_TOKEN`.
|
|
90
|
+
|
|
91
|
+
### GitHub Issues
|
|
92
|
+
|
|
93
|
+
1. `What's your GitHub repo? (owner/name, e.g. acme/my-app)`
|
|
94
|
+
2. `Paste your GitHub personal access token: (needs repo scope)`
|
|
95
|
+
|
|
96
|
+
Store as `GITHUB_REPO`, `GITHUB_TOKEN`.
|
|
97
|
+
|
|
98
|
+
After collecting credentials, show:
|
|
99
|
+
|
|
100
|
+
```
|
|
101
|
+
Note: Clancy only picks up GitHub Issues that have the "clancy" label applied.
|
|
102
|
+
Add this label to any issue you want Clancy to brief.
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Linear
|
|
106
|
+
|
|
107
|
+
1. `Paste your Linear API key: (create one at linear.app/settings/api)`
|
|
108
|
+
2. After verifying the API key (Step 4), auto-detect teams by querying `{ teams { nodes { id name } } }`.
|
|
109
|
+
- If exactly 1 team: use it automatically. Show `Using team: {name} ({id})`.
|
|
110
|
+
- If 2+ teams: show a numbered list and let the user pick.
|
|
111
|
+
- If the query fails or returns no teams: fall back to asking manually: `What's your Linear team ID? (find it at linear.app/settings/teams — click your team, copy the ID from the URL)`
|
|
112
|
+
|
|
113
|
+
Store as `LINEAR_API_KEY`, `LINEAR_TEAM_ID`.
|
|
114
|
+
|
|
115
|
+
### Shortcut
|
|
116
|
+
|
|
117
|
+
1. `Paste your Shortcut API token: (create one at app.shortcut.com/settings/account/api-tokens)`
|
|
118
|
+
|
|
119
|
+
Store as `SHORTCUT_API_TOKEN`.
|
|
120
|
+
|
|
121
|
+
### Notion
|
|
122
|
+
|
|
123
|
+
1. `Paste your Notion integration token: (create one at notion.so/my-integrations)`
|
|
124
|
+
2. `What's your Notion database ID? (the 32-character hex string in your database URL)`
|
|
125
|
+
|
|
126
|
+
Store as `NOTION_TOKEN`, `NOTION_DATABASE_ID`.
|
|
127
|
+
|
|
128
|
+
### Azure DevOps
|
|
129
|
+
|
|
130
|
+
1. `What's your Azure DevOps organisation name? (e.g. your-org)`
|
|
131
|
+
2. `What's your Azure DevOps project name?`
|
|
132
|
+
3. `Paste your Azure DevOps personal access token: (needs Work Items Read & Write scope)`
|
|
133
|
+
|
|
134
|
+
Store as `AZDO_ORG`, `AZDO_PROJECT`, `AZDO_PAT`.
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## Step 4 — Credential verification
|
|
139
|
+
|
|
140
|
+
After collecting all credentials for the chosen board, verify the connection before writing them.
|
|
141
|
+
|
|
142
|
+
### Jira
|
|
143
|
+
|
|
144
|
+
Call `GET {JIRA_BASE_URL}/rest/api/3/project/{JIRA_PROJECT_KEY}` with basic auth (`{JIRA_USER}:{JIRA_API_TOKEN}` base64-encoded in the `Authorization: Basic` header).
|
|
145
|
+
|
|
146
|
+
On success (HTTP 200):
|
|
147
|
+
|
|
148
|
+
```
|
|
149
|
+
✅ Jira connected — project {JIRA_PROJECT_KEY} reachable.
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### GitHub Issues
|
|
153
|
+
|
|
154
|
+
Call `GET https://api.github.com/repos/{GITHUB_REPO}` with `Authorization: Bearer {GITHUB_TOKEN}` and `X-GitHub-Api-Version: 2022-11-28`.
|
|
155
|
+
|
|
156
|
+
On success (HTTP 200):
|
|
157
|
+
|
|
158
|
+
```
|
|
159
|
+
✅ GitHub connected — {GITHUB_REPO} reachable.
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### Linear
|
|
163
|
+
|
|
164
|
+
Call `POST https://api.linear.app/graphql` with `Authorization: {LINEAR_API_KEY}` (no Bearer prefix) and body `{"query": "{ viewer { id name } }"}`.
|
|
165
|
+
|
|
166
|
+
On success (HTTP 200 with `data.viewer`):
|
|
167
|
+
|
|
168
|
+
```
|
|
169
|
+
✅ Linear connected — {viewer.name}.
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Shortcut
|
|
173
|
+
|
|
174
|
+
Call `GET https://api.app.shortcut.com/api/v3/member-info` with `Shortcut-Token: {SHORTCUT_API_TOKEN}`.
|
|
175
|
+
|
|
176
|
+
On success (HTTP 200):
|
|
177
|
+
|
|
178
|
+
```
|
|
179
|
+
✅ Shortcut connected.
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### Notion
|
|
183
|
+
|
|
184
|
+
Call `GET https://api.notion.com/v1/databases/{NOTION_DATABASE_ID}` with `Authorization: Bearer {NOTION_TOKEN}` and `Notion-Version: 2022-06-28`.
|
|
185
|
+
|
|
186
|
+
On success (HTTP 200):
|
|
187
|
+
|
|
188
|
+
```
|
|
189
|
+
✅ Notion connected — database reachable.
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Azure DevOps
|
|
193
|
+
|
|
194
|
+
Call `GET https://dev.azure.com/{AZDO_ORG}/{AZDO_PROJECT}/_apis/wit/workitemtypes?api-version=7.1` with basic auth (empty user, `AZDO_PAT` as password).
|
|
195
|
+
|
|
196
|
+
On success (HTTP 200):
|
|
197
|
+
|
|
198
|
+
```
|
|
199
|
+
✅ Azure DevOps connected — {AZDO_PROJECT} reachable.
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### On failure (any board)
|
|
203
|
+
|
|
204
|
+
```
|
|
205
|
+
❌ Couldn't connect to {board} (HTTP {status}).
|
|
206
|
+
Check your credentials.
|
|
207
|
+
|
|
208
|
+
[1] Re-enter credentials
|
|
209
|
+
[2] Skip verification (save anyway)
|
|
210
|
+
[3] Cancel
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
If [1]: go back to Step 3 for that board.
|
|
214
|
+
If [2]: save the unverified credentials and continue to Step 5.
|
|
215
|
+
If [3]: stop without saving.
|
|
216
|
+
|
|
217
|
+
Never silently continue with unverified credentials — the user must explicitly choose.
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
## Step 5 — Detect base branch
|
|
222
|
+
|
|
223
|
+
Auto-detect the default branch:
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
BASE_BRANCH_REF="$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null)"
|
|
227
|
+
echo "${BASE_BRANCH_REF#refs/remotes/origin/}"
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
If detection succeeds and the branch is `main` or `master`: use it silently. Store as `CLANCY_BASE_BRANCH`.
|
|
231
|
+
|
|
232
|
+
If detection fails or returns an unexpected branch name, ask:
|
|
233
|
+
|
|
234
|
+
```
|
|
235
|
+
What's your base branch? [main]
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
## Step 6 — Write credentials
|
|
241
|
+
|
|
242
|
+
### Create directory
|
|
243
|
+
|
|
244
|
+
Create `.clancy/` directory if it does not exist.
|
|
245
|
+
|
|
246
|
+
### Write `.clancy/.env`
|
|
247
|
+
|
|
248
|
+
If `.clancy/.env` already exists (reconfigure path from Step 1, or exists with no board credentials):
|
|
249
|
+
|
|
250
|
+
- Preserve all existing lines (comments, blank lines, non-board vars)
|
|
251
|
+
- Remove any existing board-specific env vars for ALL boards (not just the new one). Board vars to remove:
|
|
252
|
+
- Jira: `JIRA_BASE_URL`, `JIRA_PROJECT_KEY`, `JIRA_USER`, `JIRA_API_TOKEN`, `CLANCY_JQL_STATUS`, `CLANCY_JQL_SPRINT`
|
|
253
|
+
- GitHub: `GITHUB_REPO`, `GITHUB_TOKEN`
|
|
254
|
+
- Linear: `LINEAR_API_KEY`, `LINEAR_TEAM_ID`
|
|
255
|
+
- Shortcut: `SHORTCUT_API_TOKEN`, `SHORTCUT_WORKFLOW`
|
|
256
|
+
- Notion: `NOTION_TOKEN`, `NOTION_DATABASE_ID`, `CLANCY_NOTION_STATUS`, `CLANCY_NOTION_ASSIGNEE`, `CLANCY_NOTION_LABELS`, `CLANCY_NOTION_PARENT`, `CLANCY_NOTION_TODO`
|
|
257
|
+
- Azure DevOps: `AZDO_ORG`, `AZDO_PROJECT`, `AZDO_PAT`, `CLANCY_AZDO_WIT`, `CLANCY_AZDO_STATUS`
|
|
258
|
+
- Preserve all other lines (comments, blank lines, non-board vars like `CLANCY_BASE_BRANCH`)
|
|
259
|
+
- Append the new board's credentials at the end
|
|
260
|
+
- Update `CLANCY_BASE_BRANCH` if it exists, or append it
|
|
261
|
+
|
|
262
|
+
If `.clancy/.env` does not exist, write a new file:
|
|
263
|
+
|
|
264
|
+
```
|
|
265
|
+
# Clancy — Board credentials
|
|
266
|
+
# Configured by @chief-clancy/brief
|
|
267
|
+
# Do not commit this file to version control.
|
|
268
|
+
|
|
269
|
+
{BOARD_CREDENTIALS}
|
|
270
|
+
|
|
271
|
+
CLANCY_BASE_BRANCH={branch}
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
Where `{BOARD_CREDENTIALS}` is the board-specific key=value pairs collected in Step 3. Wrap values containing spaces in double quotes.
|
|
275
|
+
|
|
276
|
+
### Check .gitignore
|
|
277
|
+
|
|
278
|
+
Check if `.gitignore` exists and contains `.clancy/.env` (or a pattern that covers it, like `.clancy/` or `*.env`).
|
|
279
|
+
|
|
280
|
+
If not covered, show:
|
|
281
|
+
|
|
282
|
+
```
|
|
283
|
+
⚠️ Add .clancy/.env to your .gitignore to keep credentials out of version control:
|
|
284
|
+
|
|
285
|
+
echo '.clancy/.env' >> .gitignore
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
---
|
|
289
|
+
|
|
290
|
+
## Step 7 — Completion
|
|
291
|
+
|
|
292
|
+
Show the board-specific success message:
|
|
293
|
+
|
|
294
|
+
### Jira
|
|
295
|
+
|
|
296
|
+
```
|
|
297
|
+
Board credentials configured for Jira ({JIRA_PROJECT_KEY}).
|
|
298
|
+
|
|
299
|
+
You can now brief from Jira tickets:
|
|
300
|
+
/clancy:brief PROJ-123
|
|
301
|
+
|
|
302
|
+
Credentials are stored in .clancy/.env (this project only).
|
|
303
|
+
To reconfigure: /clancy:board-setup
|
|
304
|
+
For the full pipeline: npx chief-clancy
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
### GitHub Issues
|
|
308
|
+
|
|
309
|
+
```
|
|
310
|
+
Board credentials configured for GitHub Issues ({GITHUB_REPO}).
|
|
311
|
+
|
|
312
|
+
You can now brief from GitHub issues:
|
|
313
|
+
/clancy:brief #42
|
|
314
|
+
|
|
315
|
+
Credentials are stored in .clancy/.env (this project only).
|
|
316
|
+
To reconfigure: /clancy:board-setup
|
|
317
|
+
For the full pipeline: npx chief-clancy
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
### Linear
|
|
321
|
+
|
|
322
|
+
```
|
|
323
|
+
Board credentials configured for Linear.
|
|
324
|
+
|
|
325
|
+
You can now brief from Linear issues:
|
|
326
|
+
/clancy:brief ENG-42
|
|
327
|
+
|
|
328
|
+
Credentials are stored in .clancy/.env (this project only).
|
|
329
|
+
To reconfigure: /clancy:board-setup
|
|
330
|
+
For the full pipeline: npx chief-clancy
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
### Shortcut
|
|
334
|
+
|
|
335
|
+
```
|
|
336
|
+
Board credentials configured for Shortcut.
|
|
337
|
+
|
|
338
|
+
You can now brief from Shortcut stories:
|
|
339
|
+
/clancy:brief SC-123
|
|
340
|
+
|
|
341
|
+
Credentials are stored in .clancy/.env (this project only).
|
|
342
|
+
To reconfigure: /clancy:board-setup
|
|
343
|
+
For the full pipeline: npx chief-clancy
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
### Notion
|
|
347
|
+
|
|
348
|
+
```
|
|
349
|
+
Board credentials configured for Notion.
|
|
350
|
+
|
|
351
|
+
You can now brief from Notion pages:
|
|
352
|
+
/clancy:brief notion-XXXXXXXX
|
|
353
|
+
|
|
354
|
+
Credentials are stored in .clancy/.env (this project only).
|
|
355
|
+
To reconfigure: /clancy:board-setup
|
|
356
|
+
For the full pipeline: npx chief-clancy
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
### Azure DevOps
|
|
360
|
+
|
|
361
|
+
```
|
|
362
|
+
Board credentials configured for Azure DevOps ({AZDO_PROJECT}).
|
|
363
|
+
|
|
364
|
+
You can now brief from Azure DevOps work items:
|
|
365
|
+
/clancy:brief 42
|
|
366
|
+
|
|
367
|
+
Credentials are stored in .clancy/.env (this project only).
|
|
368
|
+
To reconfigure: /clancy:board-setup
|
|
369
|
+
For the full pipeline: npx chief-clancy
|
|
370
|
+
```
|
package/src/workflows/brief.md
CHANGED
|
@@ -2,47 +2,55 @@
|
|
|
2
2
|
|
|
3
3
|
## Overview
|
|
4
4
|
|
|
5
|
-
Research an idea, interrogate it thoroughly, and generate a structured strategic brief with vertical-slice ticket decomposition. Briefs are saved locally and optionally posted as comments on the source ticket. Does not create tickets —
|
|
5
|
+
Research an idea, interrogate it thoroughly, and generate a structured strategic brief with vertical-slice ticket decomposition. Briefs are saved locally and optionally posted as comments on the source ticket. Does not create tickets — in **terminal mode**, use `/clancy:approve-brief` for that. In **standalone mode** or **standalone+board mode**, install the full pipeline (`npx chief-clancy`) to create tickets from briefs.
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
## Step 1 — Preflight checks
|
|
10
10
|
|
|
11
|
-
1.
|
|
11
|
+
### 1. Detect installation context
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
.clancy/ not found. Run /clancy:init to set up Clancy first.
|
|
15
|
-
```
|
|
13
|
+
Check for `.clancy/.env`:
|
|
16
14
|
|
|
17
|
-
|
|
15
|
+
- **Absent** → **standalone mode**. No board credentials. Board ticket and batch modes are blocked.
|
|
16
|
+
- **Present** → continue to `.clancy/clancy-implement.js` check below.
|
|
18
17
|
|
|
19
|
-
|
|
18
|
+
If `.clancy/.env` is present, check for `.clancy/clancy-implement.js`:
|
|
20
19
|
|
|
21
|
-
|
|
20
|
+
- **Present** → **terminal mode**. Full Clancy pipeline installed.
|
|
21
|
+
- **Absent** → **standalone+board mode**. Board credentials available via `/clancy:board-setup`. Board ticket mode works. Steps 10/10a work. But `/clancy:approve-brief` is not available (requires full pipeline).
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
The Strategist role is not enabled. Add "strategist" to CLANCY_ROLES in .clancy/.env or run /clancy:settings.
|
|
25
|
-
```
|
|
23
|
+
### 2. Terminal-mode preflight (skip in standalone mode and standalone+board mode)
|
|
26
24
|
|
|
27
|
-
|
|
25
|
+
If in **terminal mode** (`.clancy/.env` present AND `.clancy/clancy-implement.js` present):
|
|
28
26
|
|
|
29
|
-
|
|
27
|
+
a. Source `.clancy/.env` and check board credentials are present.
|
|
30
28
|
|
|
31
|
-
|
|
29
|
+
b. Check `CLANCY_ROLES` includes `strategist` (or env var is unset, which indicates a global install where all roles are available). If `CLANCY_ROLES` is set but does not include `strategist`:
|
|
32
30
|
|
|
33
|
-
|
|
31
|
+
```
|
|
32
|
+
The Strategist role is not enabled. Add "strategist" to CLANCY_ROLES in .clancy/.env or run /clancy:settings.
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Stop.
|
|
36
|
+
|
|
37
|
+
### 3. Branch freshness check — run `git fetch origin` and compare the current HEAD with `origin/$CLANCY_BASE_BRANCH` (defaults to `main`). If the local branch is behind:
|
|
34
38
|
|
|
35
|
-
|
|
36
|
-
⚠️ Your local branch is behind origin/{CLANCY_BASE_BRANCH} by {N} commit(s).
|
|
39
|
+
**AFK mode** (`--afk` flag or `CLANCY_MODE=afk`): auto-pull without prompting. Run `git pull origin $CLANCY_BASE_BRANCH` and continue.
|
|
37
40
|
|
|
38
|
-
|
|
39
|
-
[2] Continue anyway
|
|
40
|
-
[3] Abort
|
|
41
|
-
```
|
|
41
|
+
**Interactive mode:**
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
43
|
+
```
|
|
44
|
+
⚠️ Your local branch is behind origin/{CLANCY_BASE_BRANCH} by {N} commit(s).
|
|
45
|
+
|
|
46
|
+
[1] Pull latest
|
|
47
|
+
[2] Continue anyway
|
|
48
|
+
[3] Abort
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
- [1] runs `git pull origin $CLANCY_BASE_BRANCH` and continues
|
|
52
|
+
- [2] continues without pulling
|
|
53
|
+
- [3] stops
|
|
46
54
|
|
|
47
55
|
---
|
|
48
56
|
|
|
@@ -56,7 +64,7 @@ Parse the arguments passed to the command. Arguments can appear in any order.
|
|
|
56
64
|
- **`--fresh`** — discard any existing brief and start over from scratch
|
|
57
65
|
- **`--research`** — force web research agent (adds 1 web agent to the research phase)
|
|
58
66
|
- **`--afk`** — use AI-grill instead of human grill (no interactive questions)
|
|
59
|
-
- **`--epic {KEY}`** — hint for `/clancy:approve-brief`
|
|
67
|
+
- **`--epic {KEY}`** — hint for the approve step later (terminal mode: `/clancy:approve-brief`). Stored in the brief's metadata. Ignored if the input is a board ticket (the source ticket is the parent).
|
|
60
68
|
|
|
61
69
|
### Input modes
|
|
62
70
|
|
|
@@ -82,6 +90,24 @@ If N > 10: `Maximum batch size is 10. Briefing 10 tickets.`
|
|
|
82
90
|
|
|
83
91
|
If `--list` is present (with or without other arguments), jump to Step 11 (Brief Inventory) and stop.
|
|
84
92
|
|
|
93
|
+
### Standalone board-ticket guard
|
|
94
|
+
|
|
95
|
+
If running in **standalone mode** (Step 1 detected no `.clancy/.env`) and the resolved input mode is **board ticket** or **batch mode**:
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
Board credentials not found. To brief from a board ticket:
|
|
99
|
+
/clancy:board-setup — configure board credentials (standalone)
|
|
100
|
+
npx chief-clancy — install the full pipeline
|
|
101
|
+
|
|
102
|
+
For now, use:
|
|
103
|
+
/clancy:brief "Add dark mode" — inline text
|
|
104
|
+
/clancy:brief --from docs/rfc.md — from a file
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Stop.
|
|
108
|
+
|
|
109
|
+
In **standalone+board mode**, board ticket and batch modes proceed normally — credentials are available.
|
|
110
|
+
|
|
85
111
|
---
|
|
86
112
|
|
|
87
113
|
## Step 3 — Gather idea (mode-specific)
|
|
@@ -553,7 +579,7 @@ Same relentless energy as the human grill, but directed at the strategist itself
|
|
|
553
579
|
2. Spawn the devil's advocate agent via the Agent tool, passing:
|
|
554
580
|
- The idea text (ticket title + description, or inline text, or file content)
|
|
555
581
|
- The 10-15 generated questions
|
|
556
|
-
- The path to the agent prompt:
|
|
582
|
+
- The path to the agent prompt: `.claude/clancy/agents/devils-advocate.md`
|
|
557
583
|
|
|
558
584
|
3. The devil's advocate agent answers each question by INTERROGATING ITS SOURCES:
|
|
559
585
|
- **Codebase:** explore affected areas, read `.clancy/docs/`, check existing patterns. Don't assume — look.
|
|
@@ -774,7 +800,7 @@ Using all gathered context (idea, grill output, research findings), generate the
|
|
|
774
800
|
|
|
775
801
|
---
|
|
776
802
|
|
|
777
|
-
_Generated by [Clancy](https://github.com/Pushedskydiver/chief-clancy). To answer open questions or request changes: comment on the source ticket or add a ## Feedback section to the brief file, then re-run `/clancy:brief` to revise. To
|
|
803
|
+
_Generated by [Clancy](https://github.com/Pushedskydiver/chief-clancy). To answer open questions or request changes: comment on the source ticket or add a ## Feedback section to the brief file, then re-run `/clancy:brief` to revise. To create tickets: `/clancy:approve-brief` (requires full pipeline — `npx chief-clancy`). To start over: `/clancy:brief --fresh`._
|
|
778
804
|
```
|
|
779
805
|
|
|
780
806
|
### Source field format
|
|
@@ -837,7 +863,9 @@ Write to `.clancy/briefs/{YYYY-MM-DD}-{slug}.md`.
|
|
|
837
863
|
|
|
838
864
|
## Step 10 — Post to board
|
|
839
865
|
|
|
840
|
-
Only for board-sourced briefs (
|
|
866
|
+
Only for board-sourced briefs when board credentials are available (terminal mode or standalone+board mode). In **standalone mode** (no `.clancy/.env`), skip this step and Step 10a entirely — the local file in `.clancy/briefs/` is the source of truth.
|
|
867
|
+
|
|
868
|
+
Inline text and file briefs are also local only — skip this step regardless of mode.
|
|
841
869
|
|
|
842
870
|
### GitHub — POST comment
|
|
843
871
|
|
|
@@ -951,7 +979,7 @@ Continue — do not stop. The local file is the source of truth.
|
|
|
951
979
|
|
|
952
980
|
## Step 10a — Apply pipeline label (board-sourced only)
|
|
953
981
|
|
|
954
|
-
Only for board-sourced briefs (
|
|
982
|
+
Only for board-sourced briefs when board credentials are available (terminal mode or standalone+board mode). In **standalone mode** (no `.clancy/.env`), skip this step entirely (see Step 10 guard). Inline text and file briefs also skip this step. Note: in standalone+board mode, this step creates a `clancy:brief` label on the board — this is expected behaviour when credentials are configured.
|
|
955
983
|
|
|
956
984
|
**This step is mandatory for board-sourced briefs — always apply the label.** Use `CLANCY_LABEL_BRIEF` from `.clancy/.env` if set. If not set, use `clancy:brief` as the default. Ensure the label exists on the board (create it if missing), then add it to the ticket. Also read `CLANCY_LABEL_PLAN` (default: `clancy:plan`) and `CLANCY_LABEL_BUILD` (default: `clancy:build`) for cleanup during re-briefs.
|
|
957
985
|
|
|
@@ -1219,7 +1247,8 @@ Clancy — Briefs
|
|
|
1219
1247
|
|
|
1220
1248
|
3 unapproved drafts. 1 stale (>7 days).
|
|
1221
1249
|
|
|
1222
|
-
To approve: /clancy:approve-brief <slug or index>
|
|
1250
|
+
To approve (terminal mode): /clancy:approve-brief <slug or index>
|
|
1251
|
+
To approve (standalone/standalone+board): npx chief-clancy, then /clancy:approve-brief
|
|
1223
1252
|
To review stale briefs: open the file and add ## Feedback, or delete it.
|
|
1224
1253
|
```
|
|
1225
1254
|
|
|
@@ -1253,7 +1282,8 @@ Next Steps
|
|
|
1253
1282
|
• Or add a ## Feedback section to the brief file
|
|
1254
1283
|
Then re-run: /clancy:brief {KEY}
|
|
1255
1284
|
|
|
1256
|
-
Approve: /clancy:approve-brief {KEY}
|
|
1285
|
+
Approve: /clancy:approve-brief {KEY} (terminal mode)
|
|
1286
|
+
Full pipeline: npx chief-clancy (if not terminal mode)
|
|
1257
1287
|
Start over: /clancy:brief --fresh {KEY}
|
|
1258
1288
|
```
|
|
1259
1289
|
|
|
@@ -1271,8 +1301,9 @@ Next Steps
|
|
|
1271
1301
|
.clancy/briefs/{date}-{slug}.feedback.md
|
|
1272
1302
|
Then re-run: /clancy:brief
|
|
1273
1303
|
|
|
1274
|
-
Approve: /clancy:approve-brief {slug}
|
|
1304
|
+
Approve: /clancy:approve-brief {slug} (terminal mode)
|
|
1275
1305
|
With parent: /clancy:approve-brief {slug} --epic {KEY}
|
|
1306
|
+
Full pipeline: npx chief-clancy (if not terminal mode)
|
|
1276
1307
|
Start over: /clancy:brief --fresh
|
|
1277
1308
|
```
|
|
1278
1309
|
|
|
@@ -1307,14 +1338,14 @@ Briefed {M} of {N} tickets. {K} skipped.
|
|
|
1307
1338
|
⏭️ [{KEY3}] {Title} — already briefed
|
|
1308
1339
|
⏭️ [{KEY4}] {Title} — not relevant
|
|
1309
1340
|
|
|
1310
|
-
Briefs saved to .clancy/briefs/.
|
|
1341
|
+
Briefs saved to .clancy/briefs/. To create tickets: /clancy:approve-brief (requires full pipeline — npx chief-clancy).
|
|
1311
1342
|
```
|
|
1312
1343
|
|
|
1313
1344
|
---
|
|
1314
1345
|
|
|
1315
1346
|
## Notes
|
|
1316
1347
|
|
|
1317
|
-
- This command does NOT create tickets — it generates briefs only. Ticket creation
|
|
1348
|
+
- This command does NOT create tickets — it generates briefs only. Ticket creation requires the full pipeline (`npx chief-clancy`) and `/clancy:approve-brief`.
|
|
1318
1349
|
- Briefs are saved locally in `.clancy/briefs/` and optionally posted as comments on the source ticket.
|
|
1319
1350
|
- The grill phase is the most important part — do not skip or rush it. Zero ambiguity is the goal.
|
|
1320
1351
|
- Re-running without `--fresh` auto-detects feedback: if feedback exists, revises; if no feedback, stops with guidance.
|
|
@@ -1322,7 +1353,7 @@ Briefs saved to .clancy/briefs/. Run /clancy:approve-brief to create tickets.
|
|
|
1322
1353
|
- The `--list` flag is an inventory display only — no brief generated, no API calls beyond the local filesystem.
|
|
1323
1354
|
- Batch mode (`/clancy:brief 3`) implies AI-grill — each ticket is briefed autonomously.
|
|
1324
1355
|
- All board API calls are best-effort — if a comment fails to post, print the brief and warn. The local file is the source of truth.
|
|
1325
|
-
- The `Clancy Strategic Brief` text in comments is the marker used by
|
|
1356
|
+
- The `Clancy Strategic Brief` text in comments is the marker used by `/clancy:brief` (to detect existing briefs and feedback) and by `/clancy:approve-brief` in terminal mode (to find the brief for ticket creation). Search case-insensitively and match regardless of heading level (`#`, `##`, or plain text).
|
|
1326
1357
|
- Jira uses ADF for comments (with `codeBlock` fallback). GitHub, Linear, and Shortcut accept Markdown directly.
|
|
1327
1358
|
- Linear personal API keys do NOT use `Bearer` prefix.
|
|
1328
1359
|
- Shortcut uses `Shortcut-Token` header (not `Authorization: Bearer`). API base: `https://api.app.shortcut.com/api/v3`. Stories use `name` (not `title`), `description` is markdown, dependencies use `story_links` with `blocks` verb, and workflow state transitions use `workflow_state_id`.
|
|
@@ -11,7 +11,7 @@ import { describe, expect, it } from 'vitest';
|
|
|
11
11
|
|
|
12
12
|
const WORKFLOWS_DIR = fileURLToPath(new URL('.', import.meta.url));
|
|
13
13
|
|
|
14
|
-
const EXPECTED_WORKFLOWS = ['brief.md'];
|
|
14
|
+
const EXPECTED_WORKFLOWS = ['board-setup.md', 'brief.md'];
|
|
15
15
|
|
|
16
16
|
describe('workflows directory structure', () => {
|
|
17
17
|
it('contains exactly the expected workflow files', () => {
|
|
@@ -44,3 +44,131 @@ describe('workflows directory structure', () => {
|
|
|
44
44
|
expect(content).toContain('.clancy/briefs/');
|
|
45
45
|
});
|
|
46
46
|
});
|
|
47
|
+
|
|
48
|
+
// ---------------------------------------------------------------------------
|
|
49
|
+
// board-setup.md content assertions
|
|
50
|
+
// ---------------------------------------------------------------------------
|
|
51
|
+
|
|
52
|
+
describe('board-setup workflow', () => {
|
|
53
|
+
const content = readFileSync(
|
|
54
|
+
new URL('board-setup.md', import.meta.url),
|
|
55
|
+
'utf8',
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
it('checks for full pipeline before proceeding', () => {
|
|
59
|
+
expect(content).toContain('clancy-implement.js');
|
|
60
|
+
expect(content).toContain('/clancy:settings');
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('checks for existing board credentials', () => {
|
|
64
|
+
expect(content).toContain('Existing board credentials found');
|
|
65
|
+
expect(content).toContain('Reconfigure');
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('offers all 6 supported boards', () => {
|
|
69
|
+
expect(content).toContain('Jira');
|
|
70
|
+
expect(content).toContain('GitHub Issues');
|
|
71
|
+
expect(content).toContain('Linear');
|
|
72
|
+
expect(content).toContain('Shortcut');
|
|
73
|
+
expect(content).toContain('Notion');
|
|
74
|
+
expect(content).toContain('Azure DevOps');
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('includes credential prompts for each board', () => {
|
|
78
|
+
expect(content).toContain('JIRA_BASE_URL');
|
|
79
|
+
expect(content).toContain('GITHUB_TOKEN');
|
|
80
|
+
expect(content).toContain('LINEAR_API_KEY');
|
|
81
|
+
expect(content).toContain('SHORTCUT_API_TOKEN');
|
|
82
|
+
expect(content).toContain('NOTION_TOKEN');
|
|
83
|
+
expect(content).toContain('AZDO_PAT');
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it('includes credential verification for each board', () => {
|
|
87
|
+
expect(content).toContain('Jira connected');
|
|
88
|
+
expect(content).toContain('GitHub connected');
|
|
89
|
+
expect(content).toContain('Linear connected');
|
|
90
|
+
expect(content).toContain('Shortcut connected');
|
|
91
|
+
expect(content).toContain('Notion connected');
|
|
92
|
+
expect(content).toContain('Azure DevOps connected');
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it('offers re-enter, skip, and cancel on verification failure', () => {
|
|
96
|
+
expect(content).toContain('Re-enter credentials');
|
|
97
|
+
expect(content).toContain('Skip verification');
|
|
98
|
+
expect(content).toContain('Cancel');
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it('warns about .gitignore', () => {
|
|
102
|
+
expect(content).toContain('.gitignore');
|
|
103
|
+
expect(content).toContain('.clancy/.env');
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it('notes credentials are per-project', () => {
|
|
107
|
+
expect(content).toContain('this project only');
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it('includes brief header comment in env file', () => {
|
|
111
|
+
expect(content).toContain('Configured by @chief-clancy/brief');
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
// ---------------------------------------------------------------------------
|
|
116
|
+
// brief.md content assertions
|
|
117
|
+
// ---------------------------------------------------------------------------
|
|
118
|
+
|
|
119
|
+
describe('three-state mode detection', () => {
|
|
120
|
+
const content = readFileSync(new URL('brief.md', import.meta.url), 'utf8');
|
|
121
|
+
|
|
122
|
+
it('Step 1 detects three installation states', () => {
|
|
123
|
+
expect(content).toContain('standalone mode');
|
|
124
|
+
expect(content).toContain('standalone+board mode');
|
|
125
|
+
expect(content).toContain('terminal mode');
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it('Step 1 checks .clancy/.env for credentials', () => {
|
|
129
|
+
expect(content).toContain('.clancy/.env');
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it('Step 1 checks clancy-implement.js for terminal detection', () => {
|
|
133
|
+
expect(content).toContain('clancy-implement.js');
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
it('Step 1 does not hard-stop on missing .clancy/.env', () => {
|
|
137
|
+
expect(content).not.toContain(
|
|
138
|
+
'.clancy/ not found. Run /clancy:init to set up Clancy first.',
|
|
139
|
+
);
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it('CLANCY_ROLES check only runs in terminal mode', () => {
|
|
143
|
+
expect(content).toContain('Terminal-mode preflight');
|
|
144
|
+
expect(content).toContain(
|
|
145
|
+
'skip in standalone mode and standalone+board mode',
|
|
146
|
+
);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it('standalone guard mentions /clancy:board-setup', () => {
|
|
150
|
+
expect(content).toContain('Standalone board-ticket guard');
|
|
151
|
+
expect(content).toContain('Board credentials not found');
|
|
152
|
+
expect(content).toContain('/clancy:board-setup');
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it('Step 10 runs when board credentials are available', () => {
|
|
156
|
+
expect(content).toContain(
|
|
157
|
+
'when board credentials are available (terminal mode or standalone+board mode)',
|
|
158
|
+
);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it('Step 10a runs when board credentials are available', () => {
|
|
162
|
+
expect(content).toContain('see Step 10 guard');
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
it('agent reference uses .claude/clancy/agents/ path', () => {
|
|
166
|
+
expect(content).toContain('.claude/clancy/agents/devils-advocate.md');
|
|
167
|
+
expect(content).not.toContain('src/agents/devils-advocate.md');
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
it('approve-brief references include standalone guidance', () => {
|
|
171
|
+
expect(content).not.toMatch(/that is `\/clancy:approve-brief`\./);
|
|
172
|
+
expect(content).toContain('npx chief-clancy');
|
|
173
|
+
});
|
|
174
|
+
});
|