@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/package.json
CHANGED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { readdir } from "fs/promises";
|
|
2
|
+
import { join } from "path";
|
|
3
|
+
|
|
4
|
+
export interface DiscoveryResult {
|
|
5
|
+
found: string[];
|
|
6
|
+
error?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface ResolvedAidePath {
|
|
10
|
+
path: string;
|
|
11
|
+
filename: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Discover .aide files in a directory
|
|
16
|
+
*/
|
|
17
|
+
export async function discoverAideFiles(cwd: string): Promise<DiscoveryResult> {
|
|
18
|
+
try {
|
|
19
|
+
const files = await readdir(cwd);
|
|
20
|
+
const aideFiles = files.filter((f) => f.endsWith(".aide"));
|
|
21
|
+
return { found: aideFiles };
|
|
22
|
+
} catch (error) {
|
|
23
|
+
return { found: [], error: error instanceof Error ? error.message : String(error) };
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Resolve the aide file path for a project directory
|
|
29
|
+
* - If explicitPath is provided, use it
|
|
30
|
+
* - Otherwise, glob for *.aide in projectPath
|
|
31
|
+
* - If exactly one found, use it
|
|
32
|
+
* - If multiple found, throw error
|
|
33
|
+
* - If none found, throw error
|
|
34
|
+
*
|
|
35
|
+
* @param projectPath - The project directory to search in
|
|
36
|
+
* @param explicitPath - Optional explicit path to an aide file
|
|
37
|
+
* @returns The resolved aide file path
|
|
38
|
+
* @throws Error if no aide file found or multiple found without explicit path
|
|
39
|
+
*/
|
|
40
|
+
export async function resolveAidePath(
|
|
41
|
+
projectPath: string,
|
|
42
|
+
explicitPath?: string
|
|
43
|
+
): Promise<ResolvedAidePath> {
|
|
44
|
+
// If explicit path provided, use it
|
|
45
|
+
if (explicitPath) {
|
|
46
|
+
const fullPath = explicitPath.startsWith("/")
|
|
47
|
+
? explicitPath
|
|
48
|
+
: join(projectPath, explicitPath);
|
|
49
|
+
const filename = explicitPath.split("/").pop() || explicitPath;
|
|
50
|
+
return { path: fullPath, filename };
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Auto-discover
|
|
54
|
+
const { found, error } = await discoverAideFiles(projectPath);
|
|
55
|
+
|
|
56
|
+
if (error) {
|
|
57
|
+
throw new Error(`Error discovering aide files: ${error}`);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (found.length === 0) {
|
|
61
|
+
throw new Error("No .aide file found. Run 'bantay aide init' to create one.");
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (found.length > 1) {
|
|
65
|
+
throw new Error(
|
|
66
|
+
`Multiple .aide files found. Specify one with --aide <path>\nFound: ${found.join(", ")}`
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return {
|
|
71
|
+
path: join(projectPath, found[0]),
|
|
72
|
+
filename: found[0],
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Try to resolve aide path, returning null if not found (non-throwing version)
|
|
78
|
+
*/
|
|
79
|
+
export async function tryResolveAidePath(
|
|
80
|
+
projectPath: string,
|
|
81
|
+
explicitPath?: string
|
|
82
|
+
): Promise<ResolvedAidePath | null> {
|
|
83
|
+
try {
|
|
84
|
+
return await resolveAidePath(projectPath, explicitPath);
|
|
85
|
+
} catch {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
}
|
package/src/aide/index.ts
CHANGED
|
@@ -16,6 +16,15 @@ import {
|
|
|
16
16
|
// Re-export types
|
|
17
17
|
export type { AideTree, Entity, Relationship } from "./types";
|
|
18
18
|
|
|
19
|
+
// Re-export discovery functions
|
|
20
|
+
export {
|
|
21
|
+
discoverAideFiles,
|
|
22
|
+
resolveAidePath,
|
|
23
|
+
tryResolveAidePath,
|
|
24
|
+
type DiscoveryResult,
|
|
25
|
+
type ResolvedAidePath,
|
|
26
|
+
} from "./discovery";
|
|
27
|
+
|
|
19
28
|
/**
|
|
20
29
|
* Read and parse a .aide YAML file
|
|
21
30
|
*/
|
package/src/cli.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { runInit } from "./commands/init";
|
|
|
3
3
|
import { runCheck, formatCheckResults, formatCheckResultsJson } from "./commands/check";
|
|
4
4
|
import { checkAllPrerequisites } from "./prerequisites";
|
|
5
5
|
import {
|
|
6
|
+
handleAideInit,
|
|
6
7
|
handleAideAdd,
|
|
7
8
|
handleAideUpdate,
|
|
8
9
|
handleAideRemove,
|
|
@@ -10,11 +11,14 @@ import {
|
|
|
10
11
|
handleAideShow,
|
|
11
12
|
handleAideValidate,
|
|
12
13
|
handleAideLock,
|
|
14
|
+
handleAideDiff,
|
|
13
15
|
printAideHelp,
|
|
14
16
|
} from "./commands/aide";
|
|
15
17
|
import { exportInvariants, exportClaude, exportCursor, exportCodex, exportAll } from "./export";
|
|
16
18
|
import { runStatus, formatStatus } from "./commands/status";
|
|
17
19
|
import { runCi, type CiOptions } from "./commands/ci";
|
|
20
|
+
import { runTasks, formatTasks } from "./commands/tasks";
|
|
21
|
+
import { handleDiff } from "./commands/diff";
|
|
18
22
|
|
|
19
23
|
const args = process.argv.slice(2);
|
|
20
24
|
const command = args[0];
|
|
@@ -40,6 +44,10 @@ async function main() {
|
|
|
40
44
|
await handleExport(args.slice(1));
|
|
41
45
|
} else if (command === "status") {
|
|
42
46
|
await handleStatus(args.slice(1));
|
|
47
|
+
} else if (command === "tasks") {
|
|
48
|
+
await handleTasks(args.slice(1));
|
|
49
|
+
} else if (command === "diff") {
|
|
50
|
+
await handleDiff(args.slice(1));
|
|
43
51
|
} else {
|
|
44
52
|
console.error(`Unknown command: ${command}`);
|
|
45
53
|
console.error('Run "bantay help" for usage information.');
|
|
@@ -72,18 +80,23 @@ Usage: bantay <command> [options]
|
|
|
72
80
|
Commands:
|
|
73
81
|
init Initialize Bantay in the current project
|
|
74
82
|
check Check all invariants against the codebase
|
|
83
|
+
diff Show classified aide changes (wraps aide diff)
|
|
75
84
|
aide Manage the aide entity tree (add, remove, link, show, validate, lock)
|
|
76
85
|
ci Generate CI workflow configuration
|
|
77
86
|
export Export invariants to agent context files
|
|
78
87
|
status Show scenario implementation status
|
|
88
|
+
tasks Generate task list from aide CUJs
|
|
79
89
|
|
|
80
90
|
Options:
|
|
81
91
|
-h, --help Show this help message
|
|
82
92
|
|
|
83
93
|
Examples:
|
|
84
94
|
bantay init Initialize in current directory
|
|
95
|
+
bantay init --force Regenerate slash commands
|
|
85
96
|
bantay check Run full invariant check
|
|
86
97
|
bantay check --diff HEAD~1 Check only affected invariants
|
|
98
|
+
bantay diff Show classified aide changes
|
|
99
|
+
bantay diff --json Output changes as JSON
|
|
87
100
|
bantay aide show Show the aide entity tree
|
|
88
101
|
bantay aide add inv_test --parent invariants --prop "statement=Test"
|
|
89
102
|
bantay ci --github-actions Generate GitHub Actions workflow
|
|
@@ -93,6 +106,8 @@ Examples:
|
|
|
93
106
|
bantay export cursor Export to .cursorrules
|
|
94
107
|
bantay status Show scenario implementation status
|
|
95
108
|
bantay status --json Output as JSON
|
|
109
|
+
bantay tasks Generate tasks for changed CUJs (requires lock)
|
|
110
|
+
bantay tasks --all Generate tasks for all CUJs
|
|
96
111
|
|
|
97
112
|
Run "bantay aide help" for aide subcommand details.
|
|
98
113
|
`);
|
|
@@ -101,6 +116,7 @@ Run "bantay aide help" for aide subcommand details.
|
|
|
101
116
|
async function handleInit(args: string[]) {
|
|
102
117
|
const projectPath = process.cwd();
|
|
103
118
|
const regenerateConfig = args.includes("--regenerate-config");
|
|
119
|
+
const force = args.includes("--force");
|
|
104
120
|
const dryRun = args.includes("--dry-run");
|
|
105
121
|
|
|
106
122
|
console.log("Initializing Bantay...\n");
|
|
@@ -111,7 +127,7 @@ async function handleInit(args: string[]) {
|
|
|
111
127
|
}
|
|
112
128
|
|
|
113
129
|
try {
|
|
114
|
-
const result = await runInit(projectPath, { regenerateConfig });
|
|
130
|
+
const result = await runInit(projectPath, { regenerateConfig, force });
|
|
115
131
|
|
|
116
132
|
// Display detection results
|
|
117
133
|
console.log("Stack Detection:");
|
|
@@ -363,6 +379,28 @@ async function handleStatus(args: string[]) {
|
|
|
363
379
|
}
|
|
364
380
|
}
|
|
365
381
|
|
|
382
|
+
async function handleTasks(args: string[]) {
|
|
383
|
+
const projectPath = process.cwd();
|
|
384
|
+
const allFlag = args.includes("--all");
|
|
385
|
+
|
|
386
|
+
// Parse --aide option
|
|
387
|
+
const aideIndex = args.indexOf("--aide");
|
|
388
|
+
const aideFile = aideIndex !== -1 ? args[aideIndex + 1] : undefined;
|
|
389
|
+
|
|
390
|
+
try {
|
|
391
|
+
const result = await runTasks(projectPath, { all: allFlag, aide: aideFile });
|
|
392
|
+
console.log(formatTasks(result));
|
|
393
|
+
process.exit(0);
|
|
394
|
+
} catch (error) {
|
|
395
|
+
if (error instanceof Error) {
|
|
396
|
+
console.error(`Error: ${error.message}`);
|
|
397
|
+
} else {
|
|
398
|
+
console.error("Error running tasks:", error);
|
|
399
|
+
}
|
|
400
|
+
process.exit(1);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
366
404
|
async function handleAide(args: string[]) {
|
|
367
405
|
const subcommand = args[0];
|
|
368
406
|
|
|
@@ -373,7 +411,9 @@ async function handleAide(args: string[]) {
|
|
|
373
411
|
|
|
374
412
|
const subArgs = args.slice(1);
|
|
375
413
|
|
|
376
|
-
if (subcommand === "
|
|
414
|
+
if (subcommand === "init") {
|
|
415
|
+
await handleAideInit(subArgs);
|
|
416
|
+
} else if (subcommand === "add") {
|
|
377
417
|
await handleAideAdd(subArgs);
|
|
378
418
|
} else if (subcommand === "update") {
|
|
379
419
|
await handleAideUpdate(subArgs);
|
|
@@ -387,6 +427,8 @@ async function handleAide(args: string[]) {
|
|
|
387
427
|
await handleAideValidate(subArgs);
|
|
388
428
|
} else if (subcommand === "lock") {
|
|
389
429
|
await handleAideLock(subArgs);
|
|
430
|
+
} else if (subcommand === "diff") {
|
|
431
|
+
await handleAideDiff(subArgs);
|
|
390
432
|
} else {
|
|
391
433
|
console.error(`Unknown aide subcommand: ${subcommand}`);
|
|
392
434
|
console.error('Run "bantay aide help" for usage information.');
|