@bantay/cli 0.2.0 → 0.3.1
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/package.json +1 -1
- package/src/aide/discovery.ts +88 -0
- package/src/aide/index.ts +9 -0
- package/src/cli.ts +44 -2
- package/src/commands/aide.ts +432 -48
- package/src/commands/check.ts +9 -4
- package/src/commands/diff.ts +387 -0
- package/src/commands/init.ts +38 -1
- package/src/commands/status.ts +9 -7
- package/src/commands/tasks.ts +220 -0
- package/src/export/claude.ts +8 -5
- package/src/export/codex.ts +5 -3
- package/src/export/cursor.ts +5 -3
- package/src/export/invariants.ts +7 -5
- package/src/generators/claude-commands.ts +61 -0
- package/src/templates/commands/bantay-check.md +58 -0
- package/src/templates/commands/bantay-interview.md +155 -0
- package/src/templates/commands/bantay-orchestrate.md +164 -0
- package/src/templates/commands/bantay-status.md +39 -0
package/src/export/claude.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import { readFile, writeFile, access } from "fs/promises";
|
|
6
6
|
import { join } from "path";
|
|
7
|
-
import { read as readAide } from "../aide";
|
|
7
|
+
import { read as readAide, resolveAidePath } from "../aide";
|
|
8
8
|
import {
|
|
9
9
|
extractConstraints,
|
|
10
10
|
extractFoundations,
|
|
@@ -27,7 +27,8 @@ import {
|
|
|
27
27
|
export function generateClaudeSection(
|
|
28
28
|
constraints: ExtractedConstraint[],
|
|
29
29
|
foundations: ExtractedFoundation[],
|
|
30
|
-
invariants: ExtractedInvariant[]
|
|
30
|
+
invariants: ExtractedInvariant[],
|
|
31
|
+
aideFilename: string = "*.aide"
|
|
31
32
|
): string {
|
|
32
33
|
const lines: string[] = [];
|
|
33
34
|
|
|
@@ -35,7 +36,7 @@ export function generateClaudeSection(
|
|
|
35
36
|
lines.push("");
|
|
36
37
|
lines.push("## Bantay Project Rules");
|
|
37
38
|
lines.push("");
|
|
38
|
-
lines.push(
|
|
39
|
+
lines.push(`*Auto-generated from ${aideFilename}. Do not edit manually.*`);
|
|
39
40
|
lines.push("");
|
|
40
41
|
|
|
41
42
|
// Foundations as principles
|
|
@@ -184,7 +185,9 @@ export async function exportClaude(
|
|
|
184
185
|
projectPath: string,
|
|
185
186
|
options: ExportOptions = {}
|
|
186
187
|
): Promise<ExportResult> {
|
|
187
|
-
|
|
188
|
+
// Discover aide file if not explicitly provided
|
|
189
|
+
const resolved = await resolveAidePath(projectPath, options.aidePath);
|
|
190
|
+
const aidePath = resolved.path;
|
|
188
191
|
const outputPath = options.outputPath || join(projectPath, "CLAUDE.md");
|
|
189
192
|
|
|
190
193
|
// Read the aide tree
|
|
@@ -196,7 +199,7 @@ export async function exportClaude(
|
|
|
196
199
|
const invariants = extractInvariants(tree);
|
|
197
200
|
|
|
198
201
|
// Generate section content
|
|
199
|
-
const section = generateClaudeSection(constraints, foundations, invariants);
|
|
202
|
+
const section = generateClaudeSection(constraints, foundations, invariants, resolved.filename);
|
|
200
203
|
|
|
201
204
|
// Read existing file if it exists
|
|
202
205
|
let existingContent = "";
|
package/src/export/codex.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import { readFile, writeFile, access } from "fs/promises";
|
|
7
7
|
import { join } from "path";
|
|
8
|
-
import { read as readAide } from "../aide";
|
|
8
|
+
import { read as readAide, resolveAidePath } from "../aide";
|
|
9
9
|
import {
|
|
10
10
|
extractConstraints,
|
|
11
11
|
extractFoundations,
|
|
@@ -33,7 +33,9 @@ export async function exportCodex(
|
|
|
33
33
|
projectPath: string,
|
|
34
34
|
options: ExportOptions = {}
|
|
35
35
|
): Promise<ExportResult> {
|
|
36
|
-
|
|
36
|
+
// Discover aide file if not explicitly provided
|
|
37
|
+
const resolved = await resolveAidePath(projectPath, options.aidePath);
|
|
38
|
+
const aidePath = resolved.path;
|
|
37
39
|
const outputPath = options.outputPath || join(projectPath, "AGENTS.md");
|
|
38
40
|
|
|
39
41
|
// Read the aide tree
|
|
@@ -45,7 +47,7 @@ export async function exportCodex(
|
|
|
45
47
|
const invariants = extractInvariants(tree);
|
|
46
48
|
|
|
47
49
|
// Generate section content (same format as claude)
|
|
48
|
-
const section = generateClaudeSection(constraints, foundations, invariants);
|
|
50
|
+
const section = generateClaudeSection(constraints, foundations, invariants, resolved.filename);
|
|
49
51
|
|
|
50
52
|
// Read existing file if it exists
|
|
51
53
|
let existingContent = "";
|
package/src/export/cursor.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import { readFile, writeFile, access } from "fs/promises";
|
|
6
6
|
import { join } from "path";
|
|
7
|
-
import { read as readAide } from "../aide";
|
|
7
|
+
import { read as readAide, resolveAidePath } from "../aide";
|
|
8
8
|
import {
|
|
9
9
|
extractConstraints,
|
|
10
10
|
extractFoundations,
|
|
@@ -32,7 +32,9 @@ export async function exportCursor(
|
|
|
32
32
|
projectPath: string,
|
|
33
33
|
options: ExportOptions = {}
|
|
34
34
|
): Promise<ExportResult> {
|
|
35
|
-
|
|
35
|
+
// Discover aide file if not explicitly provided
|
|
36
|
+
const resolved = await resolveAidePath(projectPath, options.aidePath);
|
|
37
|
+
const aidePath = resolved.path;
|
|
36
38
|
const outputPath = options.outputPath || join(projectPath, ".cursorrules");
|
|
37
39
|
|
|
38
40
|
// Read the aide tree
|
|
@@ -44,7 +46,7 @@ export async function exportCursor(
|
|
|
44
46
|
const invariants = extractInvariants(tree);
|
|
45
47
|
|
|
46
48
|
// Generate section content (same format as claude)
|
|
47
|
-
const section = generateClaudeSection(constraints, foundations, invariants);
|
|
49
|
+
const section = generateClaudeSection(constraints, foundations, invariants, resolved.filename);
|
|
48
50
|
|
|
49
51
|
// Read existing file if it exists
|
|
50
52
|
let existingContent = "";
|
package/src/export/invariants.ts
CHANGED
|
@@ -4,19 +4,19 @@
|
|
|
4
4
|
|
|
5
5
|
import { readFile, writeFile } from "fs/promises";
|
|
6
6
|
import { join } from "path";
|
|
7
|
-
import { read as readAide } from "../aide";
|
|
7
|
+
import { read as readAide, resolveAidePath } from "../aide";
|
|
8
8
|
import { extractInvariants, groupBy } from "./aide-reader";
|
|
9
9
|
import type { ExportOptions, ExportResult, ExtractedInvariant } from "./types";
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Generate invariants.md content from the aide tree
|
|
13
13
|
*/
|
|
14
|
-
export function generateInvariantsMd(invariants: ExtractedInvariant[]): string {
|
|
14
|
+
export function generateInvariantsMd(invariants: ExtractedInvariant[], aideFilename: string = "*.aide"): string {
|
|
15
15
|
const lines: string[] = [];
|
|
16
16
|
|
|
17
17
|
lines.push("# Invariants");
|
|
18
18
|
lines.push("");
|
|
19
|
-
lines.push(
|
|
19
|
+
lines.push(`Rules this project must never break. Generated from ${aideFilename}.`);
|
|
20
20
|
lines.push("");
|
|
21
21
|
|
|
22
22
|
// Group by category
|
|
@@ -66,7 +66,9 @@ export async function exportInvariants(
|
|
|
66
66
|
projectPath: string,
|
|
67
67
|
options: ExportOptions = {}
|
|
68
68
|
): Promise<ExportResult> {
|
|
69
|
-
|
|
69
|
+
// Discover aide file if not explicitly provided
|
|
70
|
+
const resolved = await resolveAidePath(projectPath, options.aidePath);
|
|
71
|
+
const aidePath = resolved.path;
|
|
70
72
|
const outputPath = options.outputPath || join(projectPath, "invariants.md");
|
|
71
73
|
|
|
72
74
|
// Read the aide tree
|
|
@@ -76,7 +78,7 @@ export async function exportInvariants(
|
|
|
76
78
|
const invariants = extractInvariants(tree);
|
|
77
79
|
|
|
78
80
|
// Generate content
|
|
79
|
-
const content = generateInvariantsMd(invariants);
|
|
81
|
+
const content = generateInvariantsMd(invariants, resolved.filename);
|
|
80
82
|
|
|
81
83
|
// Write unless dry run
|
|
82
84
|
if (!options.dryRun) {
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generators for Claude Code slash command files
|
|
3
|
+
*
|
|
4
|
+
* These files are placed in .claude/commands/ and appear as
|
|
5
|
+
* slash commands in Claude Code (e.g., /bantay-interview)
|
|
6
|
+
*
|
|
7
|
+
* Prompts are stored as markdown files in src/templates/commands/
|
|
8
|
+
* for readability and easy editing.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { readFileSync } from "fs";
|
|
12
|
+
import { join } from "path";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Generate the bantay-interview.md command
|
|
16
|
+
*
|
|
17
|
+
* This command guides Claude through an interactive session to
|
|
18
|
+
* build out the project's aide structure through conversation.
|
|
19
|
+
*/
|
|
20
|
+
export function generateInterviewCommand(): string {
|
|
21
|
+
return readFileSync(
|
|
22
|
+
join(__dirname, "../templates/commands/bantay-interview.md"),
|
|
23
|
+
"utf-8"
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Generate the bantay-status.md command
|
|
29
|
+
*
|
|
30
|
+
* This command runs bantay status and discusses the results.
|
|
31
|
+
*/
|
|
32
|
+
export function generateStatusCommand(): string {
|
|
33
|
+
return readFileSync(
|
|
34
|
+
join(__dirname, "../templates/commands/bantay-status.md"),
|
|
35
|
+
"utf-8"
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Generate the bantay-check.md command
|
|
41
|
+
*
|
|
42
|
+
* This command runs bantay check and helps fix any failures.
|
|
43
|
+
*/
|
|
44
|
+
export function generateCheckCommand(): string {
|
|
45
|
+
return readFileSync(
|
|
46
|
+
join(__dirname, "../templates/commands/bantay-check.md"),
|
|
47
|
+
"utf-8"
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Generate the bantay-orchestrate.md command
|
|
53
|
+
*
|
|
54
|
+
* This command orchestrates multi-agent builds from the aide task list.
|
|
55
|
+
*/
|
|
56
|
+
export function generateOrchestrateCommand(): string {
|
|
57
|
+
return readFileSync(
|
|
58
|
+
join(__dirname, "../templates/commands/bantay-orchestrate.md"),
|
|
59
|
+
"utf-8"
|
|
60
|
+
);
|
|
61
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Bantay Check
|
|
2
|
+
|
|
3
|
+
Run `bantay check` to verify all invariants, explain any failures, and propose fixes.
|
|
4
|
+
|
|
5
|
+
## What to Do
|
|
6
|
+
|
|
7
|
+
1. Run the check command:
|
|
8
|
+
```bash
|
|
9
|
+
bantay check
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
2. If all checks pass:
|
|
13
|
+
- Confirm that all invariants are satisfied
|
|
14
|
+
- Note the total number of checks run
|
|
15
|
+
|
|
16
|
+
3. If any checks fail:
|
|
17
|
+
- Explain each failure clearly
|
|
18
|
+
- Show the file and line number where the violation occurred
|
|
19
|
+
- Explain WHY this violates the invariant
|
|
20
|
+
- Propose a specific fix
|
|
21
|
+
|
|
22
|
+
## Explaining Failures
|
|
23
|
+
|
|
24
|
+
For each failed invariant, provide:
|
|
25
|
+
|
|
26
|
+
1. **The Rule**: What the invariant requires
|
|
27
|
+
2. **The Violation**: What code breaks the rule
|
|
28
|
+
3. **The Risk**: Why this matters (security, data integrity, etc.)
|
|
29
|
+
4. **The Fix**: Specific code changes to resolve it
|
|
30
|
+
|
|
31
|
+
## Example Response
|
|
32
|
+
|
|
33
|
+
"Bantay check found 1 failure:
|
|
34
|
+
|
|
35
|
+
**inv_auth_required** - FAILED
|
|
36
|
+
- File: src/routes/admin.ts:45
|
|
37
|
+
- Violation: Route `/admin/users` has no authentication middleware
|
|
38
|
+
- Risk: Unauthenticated users could access admin functionality
|
|
39
|
+
- Fix: Add the auth middleware:
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
// Before
|
|
43
|
+
router.get('/admin/users', getUsers);
|
|
44
|
+
|
|
45
|
+
// After
|
|
46
|
+
router.get('/admin/users', requireAuth, requireAdmin, getUsers);
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Would you like me to apply this fix?"
|
|
50
|
+
|
|
51
|
+
## Diff Mode
|
|
52
|
+
|
|
53
|
+
For faster checks during development, suggest:
|
|
54
|
+
```bash
|
|
55
|
+
bantay check --diff HEAD
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
This only checks invariants affected by recent changes.
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# Bantay Aide Interview
|
|
2
|
+
|
|
3
|
+
You are the Bantay aide interviewer. You help the developer maintain
|
|
4
|
+
their project's behavioral specification through conversation.
|
|
5
|
+
|
|
6
|
+
Read CLAUDE.md and the .aide file before doing anything.
|
|
7
|
+
|
|
8
|
+
## Determine mode
|
|
9
|
+
|
|
10
|
+
First, check what exists:
|
|
11
|
+
|
|
12
|
+
1. `ls *.aide` — does an aide file exist?
|
|
13
|
+
- **No aide:** Start a new interview (see New Project below)
|
|
14
|
+
- **Aide exists:** Ask what brings them here today
|
|
15
|
+
|
|
16
|
+
2. If the aide exists, the developer is here for one of:
|
|
17
|
+
- **New feature** — behavior that doesn't exist yet
|
|
18
|
+
- **Bug report** — something isn't working right
|
|
19
|
+
- **Spec refinement** — tightening an existing scenario or invariant
|
|
20
|
+
|
|
21
|
+
## New project
|
|
22
|
+
|
|
23
|
+
If no aide file exists:
|
|
24
|
+
|
|
25
|
+
1. Ask the developer to describe their product in a few sentences
|
|
26
|
+
2. Ask: who are the primary users and what do they accomplish?
|
|
27
|
+
3. Propose CUJs grouped by area, confirm with the developer
|
|
28
|
+
4. For each CUJ, propose scenarios (given/when/then)
|
|
29
|
+
5. After scenarios, propose invariants — rules that must never break
|
|
30
|
+
6. Ask about constraints (tech stack, hosting, auth strategy)
|
|
31
|
+
7. Ask about foundations (design principles, non-negotiable values)
|
|
32
|
+
8. Ask about wisdom (hard-won lessons, things they've learned the hard way)
|
|
33
|
+
|
|
34
|
+
Use `bantay aide add`, `bantay aide update`, and `bantay aide link`
|
|
35
|
+
for all mutations. Never hand-edit the YAML.
|
|
36
|
+
|
|
37
|
+
Run `bantay aide validate` after each section.
|
|
38
|
+
|
|
39
|
+
## Bug report
|
|
40
|
+
|
|
41
|
+
When the developer reports a bug:
|
|
42
|
+
|
|
43
|
+
1. Understand the issue. Ask enough to reproduce it:
|
|
44
|
+
- What did you expect?
|
|
45
|
+
- What happened instead?
|
|
46
|
+
- Where in the app?
|
|
47
|
+
|
|
48
|
+
2. Check the aide for coverage:
|
|
49
|
+
```
|
|
50
|
+
bantay aide show <likely_cuj_id>
|
|
51
|
+
```
|
|
52
|
+
Look for a scenario that covers this behavior.
|
|
53
|
+
|
|
54
|
+
3. **If no scenario covers it** — this is an aide gap:
|
|
55
|
+
- Propose a new scenario with given/when/then
|
|
56
|
+
- Propose a new invariant if the bug reveals a rule that should never break
|
|
57
|
+
- Add threat signals to existing invariants if relevant
|
|
58
|
+
- After the developer confirms:
|
|
59
|
+
```
|
|
60
|
+
bantay aide add sc_... --parent <cuj> --prop "..."
|
|
61
|
+
bantay aide add inv_... --parent invariants --prop "..."
|
|
62
|
+
bantay aide link sc_... inv_... --type protected_by
|
|
63
|
+
bantay aide validate
|
|
64
|
+
bantay export all
|
|
65
|
+
bantay aide lock
|
|
66
|
+
```
|
|
67
|
+
- Then: `bantay diff` to show the classified changes
|
|
68
|
+
- Then: `bantay tasks` to generate the fix list
|
|
69
|
+
- The reconciliation loop handles the rest
|
|
70
|
+
|
|
71
|
+
4. **If a scenario already covers it** — this is a code bug:
|
|
72
|
+
- The aide is correct, the implementation is wrong
|
|
73
|
+
- Don't touch the aide
|
|
74
|
+
- Create a GitHub issue:
|
|
75
|
+
```
|
|
76
|
+
gh issue create \
|
|
77
|
+
--title "Bug: <short description>" \
|
|
78
|
+
--body "## Scenario
|
|
79
|
+
<scenario_id>: <scenario name>
|
|
80
|
+
|
|
81
|
+
**Given:** <given>
|
|
82
|
+
**When:** <when>
|
|
83
|
+
**Expected (from aide):** <then>
|
|
84
|
+
**Actual:** <what the developer reported>
|
|
85
|
+
|
|
86
|
+
## Linked invariant
|
|
87
|
+
<invariant_id>: <statement>
|
|
88
|
+
|
|
89
|
+
## Notes
|
|
90
|
+
The aide correctly specifies this behavior. The implementation
|
|
91
|
+
does not match. Fix the code to satisfy the scenario."
|
|
92
|
+
```
|
|
93
|
+
- Tell the developer: "The aide already covers this — it's an
|
|
94
|
+
implementation bug. I've created an issue. Run the fix against
|
|
95
|
+
the existing scenario."
|
|
96
|
+
|
|
97
|
+
5. **If partially covered** — the scenario exists but is too loose:
|
|
98
|
+
- Tighten the scenario (update given/when/then to be more specific)
|
|
99
|
+
- Add an invariant if the bug reveals a missing constraint
|
|
100
|
+
- Then follow the aide gap flow: validate → export → lock → diff → tasks
|
|
101
|
+
|
|
102
|
+
## Feature request
|
|
103
|
+
|
|
104
|
+
When the developer requests a new feature:
|
|
105
|
+
|
|
106
|
+
1. Understand the feature:
|
|
107
|
+
- What should the user be able to do?
|
|
108
|
+
- Which existing CUJ does this extend, or is it a new CUJ?
|
|
109
|
+
- Are there new invariants (rules that must hold)?
|
|
110
|
+
|
|
111
|
+
2. Check the aide:
|
|
112
|
+
```
|
|
113
|
+
bantay aide show <likely_cuj_id>
|
|
114
|
+
```
|
|
115
|
+
Does any existing scenario partially cover this?
|
|
116
|
+
|
|
117
|
+
3. **New CUJ** — if the feature is a new user journey:
|
|
118
|
+
- Propose the CUJ with feature description, tier, and area
|
|
119
|
+
- Propose scenarios with given/when/then
|
|
120
|
+
- Propose invariants
|
|
121
|
+
- Wire relationships (protected_by, depends_on)
|
|
122
|
+
- Validate → export → lock → diff → tasks
|
|
123
|
+
|
|
124
|
+
4. **Extending existing CUJ** — if adding scenarios to an existing journey:
|
|
125
|
+
- Propose new scenarios under the existing CUJ
|
|
126
|
+
- Check if new invariants are needed
|
|
127
|
+
- Wire relationships
|
|
128
|
+
- Validate → export → lock → diff → tasks
|
|
129
|
+
|
|
130
|
+
5. **Cross-cutting** — if the feature touches multiple CUJs:
|
|
131
|
+
- Propose scenarios under each affected CUJ
|
|
132
|
+
- Propose shared invariants
|
|
133
|
+
- Wire depends_on relationships between CUJs if needed
|
|
134
|
+
- Validate → export → lock → diff → tasks
|
|
135
|
+
|
|
136
|
+
## Spec refinement
|
|
137
|
+
|
|
138
|
+
When the developer wants to tighten the spec:
|
|
139
|
+
|
|
140
|
+
1. Show current state: `bantay aide show <entity_id>`
|
|
141
|
+
2. Discuss what's missing or too loose
|
|
142
|
+
3. Update scenarios, invariants, or constraints
|
|
143
|
+
4. Add threat signals to invariants that lack them
|
|
144
|
+
5. Validate → export → lock → diff → tasks
|
|
145
|
+
|
|
146
|
+
## Rules
|
|
147
|
+
|
|
148
|
+
- Always use the CLI for mutations. Never hand-edit YAML.
|
|
149
|
+
- Confirm every addition with the developer before running the command.
|
|
150
|
+
- Run `bantay aide validate` after every batch of changes.
|
|
151
|
+
- The aide is the source of truth. If the aide is correct and the code
|
|
152
|
+
is wrong, don't change the aide — file an issue.
|
|
153
|
+
- If the aide is missing something, update the aide first, then build.
|
|
154
|
+
- Always end with: validate → export → lock → diff → tasks.
|
|
155
|
+
That hands off to the reconciliation loop.
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
You are the team lead for a Bantay-orchestrated build.
|
|
2
|
+
|
|
3
|
+
Read CLAUDE.md and the .aide file before doing anything.
|
|
4
|
+
|
|
5
|
+
## Check build state
|
|
6
|
+
|
|
7
|
+
1. Check if `.bantay/builds/current.md` exists.
|
|
8
|
+
- **Exists with in_progress:** Resume from where it left off. Read the file, run `bantay status`, check worktrees with `git log`. Respawn any teammates that were mid-work.
|
|
9
|
+
- **Does not exist:** This is a fresh build or nothing to build. Run `bantay tasks` (diff mode). If no tasks, run `bantay tasks --all`. If still no tasks, report "nothing to build" and stop.
|
|
10
|
+
|
|
11
|
+
## Constraints
|
|
12
|
+
|
|
13
|
+
- Maximum 2 teammates at any time
|
|
14
|
+
- You do Phase 0 (foundation) directly — no teammates
|
|
15
|
+
- Every CUJ gets a written plan before a teammate is spawned
|
|
16
|
+
- No teammate is spawned without a validated and committed `.bantay/plans/<cuj_id>.md`
|
|
17
|
+
- Teammates work in separate git worktrees
|
|
18
|
+
- Run `bantay check` after merging each branch
|
|
19
|
+
- Commit and `git push` after every checkpoint update
|
|
20
|
+
|
|
21
|
+
## Phase 0 — Foundation (you do this directly)
|
|
22
|
+
|
|
23
|
+
1. Read the full aide — all CUJs, scenarios, invariants, constraints
|
|
24
|
+
2. Build the shared foundation: data model, types, database schema, API interfaces
|
|
25
|
+
3. Commit to main: `feat: foundation — data model, types, interfaces`
|
|
26
|
+
4. Run `bantay check`
|
|
27
|
+
5. Write `.bantay/builds/current.md` with Phase 0 complete
|
|
28
|
+
6. Commit and `git push`
|
|
29
|
+
7. `/compact` — shed Phase 0 context before planning Phase 1
|
|
30
|
+
|
|
31
|
+
## For each subsequent phase
|
|
32
|
+
|
|
33
|
+
### Plan (before spawning)
|
|
34
|
+
|
|
35
|
+
For each CUJ in this phase (max 2):
|
|
36
|
+
|
|
37
|
+
1. Read the CUJ scenarios from the aide
|
|
38
|
+
2. Read the existing codebase to understand what's built
|
|
39
|
+
3. Decompose into ordered implementation steps:
|
|
40
|
+
- Database schema / migrations needed
|
|
41
|
+
- API routes / server actions
|
|
42
|
+
- Core business logic
|
|
43
|
+
- UI components
|
|
44
|
+
- Integration between layers
|
|
45
|
+
- Tests mapped to each scenario
|
|
46
|
+
4. Write the plan to `.bantay/plans/<cuj_id>.md`
|
|
47
|
+
|
|
48
|
+
### Validate plan (before committing)
|
|
49
|
+
|
|
50
|
+
Do not commit or spawn until every check passes.
|
|
51
|
+
|
|
52
|
+
1. **Aide coverage** — Run `bantay aide show <cuj_id>`. Compare every
|
|
53
|
+
scenario's given/when/then against the plan. If a scenario is missing
|
|
54
|
+
or its acceptance criteria don't match, the plan is incomplete.
|
|
55
|
+
|
|
56
|
+
2. **File references** — For every file, table, route, type, or function
|
|
57
|
+
the plan references, verify it exists: `ls`, `grep`, or `cat` the
|
|
58
|
+
actual path. If it doesn't exist and the plan doesn't say "create new",
|
|
59
|
+
the plan is hallucinated. Fix it.
|
|
60
|
+
|
|
61
|
+
3. **Interface contracts** — For every function signature, API endpoint,
|
|
62
|
+
or type definition the plan depends on, read the actual source file
|
|
63
|
+
and confirm the signature matches. Don't trust your memory of Phase 0.
|
|
64
|
+
`cat` the file.
|
|
65
|
+
|
|
66
|
+
4. **Dependency check** — Cross-reference the plan against `bantay tasks`.
|
|
67
|
+
If the plan assumes something built in a later phase or an unmerged
|
|
68
|
+
worktree, the plan has a forward dependency. Remove it or reorder.
|
|
69
|
+
|
|
70
|
+
5. **Invariant coverage** — For every invariant linked to this CUJ's
|
|
71
|
+
scenarios (via `protected_by`), confirm the plan includes a step that
|
|
72
|
+
enforces or tests it. Missing invariant coverage = missing step.
|
|
73
|
+
|
|
74
|
+
If any check fails, fix the plan and re-validate. Only after all 5 pass:
|
|
75
|
+
commit the plan.
|
|
76
|
+
|
|
77
|
+
### Spawn teammates (max 2)
|
|
78
|
+
|
|
79
|
+
For each CUJ, spawn a teammate with this prompt:
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
You are building [CUJ feature] in worktree feat/[cuj-name].
|
|
83
|
+
|
|
84
|
+
YOUR PLAN: Read .bantay/plans/[cuj_id].md — execute the steps in order.
|
|
85
|
+
|
|
86
|
+
FIRST: Run bantay status to see what's already done. If scenarios
|
|
87
|
+
are already covered, skip to the first uncovered one.
|
|
88
|
+
|
|
89
|
+
BUILD RULES:
|
|
90
|
+
- Use red/green TDD. Write the test, confirm it fails, implement.
|
|
91
|
+
- Commit after each passing scenario.
|
|
92
|
+
Message: feat([cuj_name]): implement sc_[scenario_name]
|
|
93
|
+
- Run bantay check after each commit.
|
|
94
|
+
- Do not modify files outside your scope.
|
|
95
|
+
|
|
96
|
+
CONTEXT MANAGEMENT:
|
|
97
|
+
- After each scenario, check your context usage.
|
|
98
|
+
- If over 50%, /compact before continuing.
|
|
99
|
+
- If over 80%, commit everything and message the lead:
|
|
100
|
+
"Context full, requesting restart. Progress committed."
|
|
101
|
+
|
|
102
|
+
If you hit a rate limit, wait and retry — don't abandon work.
|
|
103
|
+
If something fails, commit what you have and message the lead.
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Monitor
|
|
107
|
+
|
|
108
|
+
- Check teammate progress periodically
|
|
109
|
+
- If a teammate goes silent for 10+ minutes, check its worktree:
|
|
110
|
+
```
|
|
111
|
+
cd .worktrees/<teammate>
|
|
112
|
+
git log --oneline -5
|
|
113
|
+
bantay status
|
|
114
|
+
```
|
|
115
|
+
- If a teammate dies:
|
|
116
|
+
1. The plan survives in `.bantay/plans/<cuj_id>.md`
|
|
117
|
+
2. Committed work survives in the worktree
|
|
118
|
+
3. `bantay status` shows exactly what's done
|
|
119
|
+
4. Spawn a replacement with the same prompt — it reads the plan and status, picks up from the first incomplete step
|
|
120
|
+
|
|
121
|
+
### Merge gate
|
|
122
|
+
|
|
123
|
+
After both teammates complete:
|
|
124
|
+
|
|
125
|
+
1. Merge both worktrees to main
|
|
126
|
+
2. Run `bantay check` on main
|
|
127
|
+
3. Run `bantay status`
|
|
128
|
+
4. If checks fail, fix on main before proceeding
|
|
129
|
+
5. Update `.bantay/builds/current.md`:
|
|
130
|
+
```
|
|
131
|
+
phase: N
|
|
132
|
+
started: <timestamp>
|
|
133
|
+
completed_cujs:
|
|
134
|
+
- cuj_onboarding
|
|
135
|
+
- cuj_manage_artifact
|
|
136
|
+
in_progress: []
|
|
137
|
+
status: X/Y scenarios covered
|
|
138
|
+
```
|
|
139
|
+
6. Commit and `git push`
|
|
140
|
+
7. `/compact` — shed this phase's context before the next one
|
|
141
|
+
|
|
142
|
+
If remaining CUJs in this phase, plan and spawn the next 2.
|
|
143
|
+
When phase complete, move to next phase.
|
|
144
|
+
|
|
145
|
+
## If you (the lead) need to restart
|
|
146
|
+
|
|
147
|
+
1. Read `.bantay/builds/current.md` — where we are
|
|
148
|
+
2. Read `.bantay/plans/` — what was intended for each CUJ
|
|
149
|
+
3. Run `bantay status` — what's actually built
|
|
150
|
+
4. Check each active worktree with `git log`
|
|
151
|
+
5. Resume orchestration from current state
|
|
152
|
+
6. Respawn any teammates that were mid-work
|
|
153
|
+
|
|
154
|
+
Nothing you know should exist only in your context window.
|
|
155
|
+
If you die, a new lead reading these files is indistinguishable from you.
|
|
156
|
+
|
|
157
|
+
## After all phases
|
|
158
|
+
|
|
159
|
+
1. Run `bantay status` — should show all scenarios covered
|
|
160
|
+
2. Run `bantay check` — should show all invariants passing
|
|
161
|
+
3. Delete `.bantay/builds/current.md` — clean state
|
|
162
|
+
4. Run `bantay aide lock` — snapshot the aide
|
|
163
|
+
5. Commit and `git push`
|
|
164
|
+
6. Report: phases completed, scenarios covered, invariants passing
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Bantay Status
|
|
2
|
+
|
|
3
|
+
Run `bantay status` and explain the results to the user.
|
|
4
|
+
|
|
5
|
+
## What to Do
|
|
6
|
+
|
|
7
|
+
1. Run the status command:
|
|
8
|
+
```bash
|
|
9
|
+
bantay status
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
2. Explain the output:
|
|
13
|
+
- How many scenarios are covered by tests
|
|
14
|
+
- Which scenarios are missing coverage
|
|
15
|
+
- Overall coverage percentage
|
|
16
|
+
|
|
17
|
+
3. If coverage is low, suggest:
|
|
18
|
+
- Which scenarios should be prioritized for testing
|
|
19
|
+
- How to create tests that reference scenarios with `@scenario` tags
|
|
20
|
+
|
|
21
|
+
## Understanding the Output
|
|
22
|
+
|
|
23
|
+
The status command auto-discovers the .aide file in the current directory.
|
|
24
|
+
|
|
25
|
+
The output shows:
|
|
26
|
+
- **Covered**: Scenarios that have at least one test file referencing them via `@scenario sc_<name>`
|
|
27
|
+
- **Uncovered**: Scenarios that exist in the .aide file but have no test coverage
|
|
28
|
+
- **Coverage %**: Ratio of covered to total scenarios
|
|
29
|
+
|
|
30
|
+
## Example Response
|
|
31
|
+
|
|
32
|
+
"Your Bantay status shows 15/20 scenarios covered (75%).
|
|
33
|
+
|
|
34
|
+
The uncovered scenarios are:
|
|
35
|
+
- sc_checkout_payment_failed - No test for payment failure handling
|
|
36
|
+
- sc_cart_item_out_of_stock - No test for inventory checks
|
|
37
|
+
- ...
|
|
38
|
+
|
|
39
|
+
I'd recommend prioritizing sc_checkout_payment_failed since payment handling is critical for user trust."
|