@spekn/cli 1.0.0 → 1.0.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 +58 -0
- package/dist/main.js +40540 -32176
- package/dist/prompts/governance-analysis.prompt.md +109 -0
- package/dist/resources/prompts/repo-analysis.prompt.md +28 -136
- package/dist/resources/prompts/repo-sync-analysis.prompt.md +31 -68
- package/dist/tui/chunk-4WEASLXY.mjs +3444 -0
- package/dist/tui/chunk-755CADEG.mjs +3401 -0
- package/dist/tui/chunk-BUJQVTY5.mjs +3409 -0
- package/dist/tui/chunk-BZKKMGFB.mjs +1959 -0
- package/dist/tui/chunk-DJYOBCNM.mjs +3159 -0
- package/dist/tui/chunk-GTFTFDY4.mjs +3417 -0
- package/dist/tui/chunk-IMEBD2KA.mjs +3444 -0
- package/dist/tui/chunk-IX6DR5SW.mjs +3433 -0
- package/dist/tui/chunk-JKFOY4IF.mjs +2003 -0
- package/dist/tui/chunk-OXXZ3O5L.mjs +3378 -0
- package/dist/tui/chunk-SHJNIAAJ.mjs +1697 -0
- package/dist/tui/chunk-V4SNDRUS.mjs +1666 -0
- package/dist/tui/chunk-VXVHNZST.mjs +1666 -0
- package/dist/tui/chunk-WCTSFKTA.mjs +3459 -0
- package/dist/tui/chunk-X2XP5ACW.mjs +3443 -0
- package/dist/tui/chunk-YUYJ7VBG.mjs +2029 -0
- package/dist/tui/chunk-ZM3EI5IA.mjs +3384 -0
- package/dist/tui/chunk-ZYOX64HP.mjs +1653 -0
- package/dist/tui/index.mjs +6999 -6938
- package/dist/tui/prompts/spec-creation-system.prompt.md +47 -0
- package/dist/tui/prompts/spec-refinement-system.prompt.md +72 -0
- package/dist/tui/use-session-store-63YUGUFA.mjs +8 -0
- package/dist/tui/use-session-store-ACO2SMJC.mjs +8 -0
- package/dist/tui/use-session-store-BVFDAWOB.mjs +8 -0
- package/dist/tui/use-session-store-DJIZ3FQZ.mjs +9 -0
- package/dist/tui/use-session-store-EAIQA4UG.mjs +9 -0
- package/dist/tui/use-session-store-EFBAXC3G.mjs +8 -0
- package/dist/tui/use-session-store-FJOR4KTG.mjs +8 -0
- package/dist/tui/use-session-store-IJE5KVOC.mjs +8 -0
- package/dist/tui/use-session-store-KGAFXCKI.mjs +8 -0
- package/dist/tui/use-session-store-KS4DPNDY.mjs +8 -0
- package/dist/tui/use-session-store-MMHJENNL.mjs +8 -0
- package/dist/tui/use-session-store-OZ6HC4I2.mjs +9 -0
- package/dist/tui/use-session-store-PTMWISNJ.mjs +8 -0
- package/dist/tui/use-session-store-VCDECQMW.mjs +8 -0
- package/dist/tui/use-session-store-VOK5ML5J.mjs +9 -0
- package/package.json +33 -13
- package/dist/__tests__/export-cli.test.d.ts +0 -1
- package/dist/__tests__/export-cli.test.js +0 -70
- package/dist/__tests__/tui-args-policy.test.d.ts +0 -1
- package/dist/__tests__/tui-args-policy.test.js +0 -50
- package/dist/acp-S2MHZOAD.mjs +0 -23
- package/dist/acp-UCCI44JY.mjs +0 -25
- package/dist/auth/credentials-store.d.ts +0 -2
- package/dist/auth/credentials-store.js +0 -5
- package/dist/auth/device-flow.d.ts +0 -36
- package/dist/auth/device-flow.js +0 -189
- package/dist/auth/jwt.d.ts +0 -1
- package/dist/auth/jwt.js +0 -6
- package/dist/auth/session.d.ts +0 -67
- package/dist/auth/session.js +0 -86
- package/dist/auth-login.d.ts +0 -34
- package/dist/auth-login.js +0 -202
- package/dist/auth-logout.d.ts +0 -25
- package/dist/auth-logout.js +0 -115
- package/dist/auth-status.d.ts +0 -24
- package/dist/auth-status.js +0 -109
- package/dist/backlog-generate.d.ts +0 -11
- package/dist/backlog-generate.js +0 -308
- package/dist/backlog-health.d.ts +0 -11
- package/dist/backlog-health.js +0 -287
- package/dist/bridge-login.d.ts +0 -40
- package/dist/bridge-login.js +0 -277
- package/dist/chunk-3PAYRI4G.mjs +0 -2428
- package/dist/chunk-M4CS3A25.mjs +0 -2426
- package/dist/commands/auth/login.d.ts +0 -30
- package/dist/commands/auth/login.js +0 -164
- package/dist/commands/auth/logout.d.ts +0 -25
- package/dist/commands/auth/logout.js +0 -115
- package/dist/commands/auth/status.d.ts +0 -24
- package/dist/commands/auth/status.js +0 -109
- package/dist/commands/backlog/generate.d.ts +0 -11
- package/dist/commands/backlog/generate.js +0 -308
- package/dist/commands/backlog/health.d.ts +0 -11
- package/dist/commands/backlog/health.js +0 -287
- package/dist/commands/bridge/login.d.ts +0 -36
- package/dist/commands/bridge/login.js +0 -258
- package/dist/commands/export.d.ts +0 -35
- package/dist/commands/export.js +0 -485
- package/dist/commands/marketplace-export.d.ts +0 -21
- package/dist/commands/marketplace-export.js +0 -214
- package/dist/commands/project-clean.d.ts +0 -1
- package/dist/commands/project-clean.js +0 -126
- package/dist/commands/repo/common.d.ts +0 -105
- package/dist/commands/repo/common.js +0 -775
- package/dist/commands/repo/detach.d.ts +0 -2
- package/dist/commands/repo/detach.js +0 -120
- package/dist/commands/repo/register.d.ts +0 -21
- package/dist/commands/repo/register.js +0 -175
- package/dist/commands/repo/sync.d.ts +0 -22
- package/dist/commands/repo/sync.js +0 -873
- package/dist/commands/skills-import-local.d.ts +0 -16
- package/dist/commands/skills-import-local.js +0 -352
- package/dist/commands/spec/drift-check.d.ts +0 -3
- package/dist/commands/spec/drift-check.js +0 -186
- package/dist/commands/spec/frontmatter.d.ts +0 -11
- package/dist/commands/spec/frontmatter.js +0 -219
- package/dist/commands/spec/lint.d.ts +0 -11
- package/dist/commands/spec/lint.js +0 -499
- package/dist/commands/spec/parse.d.ts +0 -11
- package/dist/commands/spec/parse.js +0 -162
- package/dist/export.d.ts +0 -35
- package/dist/export.js +0 -485
- package/dist/main.d.ts +0 -1
- package/dist/marketplace-export.d.ts +0 -21
- package/dist/marketplace-export.js +0 -214
- package/dist/project-clean.d.ts +0 -1
- package/dist/project-clean.js +0 -126
- package/dist/project-context.d.ts +0 -99
- package/dist/project-context.js +0 -376
- package/dist/repo-common.d.ts +0 -101
- package/dist/repo-common.js +0 -671
- package/dist/repo-detach.d.ts +0 -2
- package/dist/repo-detach.js +0 -102
- package/dist/repo-ingest.d.ts +0 -29
- package/dist/repo-ingest.js +0 -305
- package/dist/repo-register.d.ts +0 -21
- package/dist/repo-register.js +0 -175
- package/dist/repo-sync.d.ts +0 -16
- package/dist/repo-sync.js +0 -152
- package/dist/resources/prompt-loader.d.ts +0 -1
- package/dist/resources/prompt-loader.js +0 -62
- package/dist/skills-import-local.d.ts +0 -16
- package/dist/skills-import-local.js +0 -352
- package/dist/spec-drift-check.d.ts +0 -3
- package/dist/spec-drift-check.js +0 -186
- package/dist/spec-frontmatter.d.ts +0 -11
- package/dist/spec-frontmatter.js +0 -219
- package/dist/spec-lint.d.ts +0 -11
- package/dist/spec-lint.js +0 -499
- package/dist/spec-parse.d.ts +0 -11
- package/dist/spec-parse.js +0 -162
- package/dist/stubs/dotenv.d.ts +0 -5
- package/dist/stubs/dotenv.js +0 -6
- package/dist/stubs/typeorm.d.ts +0 -22
- package/dist/stubs/typeorm.js +0 -28
- package/dist/tui-bundle.d.ts +0 -1
- package/dist/tui-bundle.js +0 -5
- package/dist/tui-entry.mjs +0 -1407
- package/dist/utils/cli-runtime.d.ts +0 -5
- package/dist/utils/cli-runtime.js +0 -22
- package/dist/utils/help-error.d.ts +0 -7
- package/dist/utils/help-error.js +0 -14
- package/dist/utils/interaction.d.ts +0 -19
- package/dist/utils/interaction.js +0 -93
- package/dist/utils/structured-log.d.ts +0 -7
- package/dist/utils/structured-log.js +0 -112
- package/dist/utils/trpc-url.d.ts +0 -4
- package/dist/utils/trpc-url.js +0 -15
package/dist/auth-logout.js
DELETED
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
"use strict";
|
|
3
|
-
/**
|
|
4
|
-
* auth logout CLI command
|
|
5
|
-
*
|
|
6
|
-
* Revokes the stored refresh token against Keycloak (best-effort) and then
|
|
7
|
-
* removes the local credentials file at ~/.spekn/credentials.json.
|
|
8
|
-
*
|
|
9
|
-
* Usage: spekn auth logout
|
|
10
|
-
*/
|
|
11
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.runAuthLogoutCli = runAuthLogoutCli;
|
|
13
|
-
exports.main = main;
|
|
14
|
-
exports.parseArgs = parseArgs;
|
|
15
|
-
const credentials_store_js_1 = require("./auth/credentials-store.js");
|
|
16
|
-
const help_error_1 = require("./utils/help-error");
|
|
17
|
-
const structured_log_1 = require("./utils/structured-log");
|
|
18
|
-
/** Default revocation implementation — best-effort, ignores errors. */
|
|
19
|
-
async function defaultRevokeToken(logoutUrl, body) {
|
|
20
|
-
await fetch(logoutUrl, {
|
|
21
|
-
method: "POST",
|
|
22
|
-
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
23
|
-
body: body.toString(),
|
|
24
|
-
});
|
|
25
|
-
}
|
|
26
|
-
const defaultDeps = {
|
|
27
|
-
stdout: process.stdout,
|
|
28
|
-
stderr: process.stderr,
|
|
29
|
-
credentialsStore: new credentials_store_js_1.CredentialsStore(),
|
|
30
|
-
revokeToken: defaultRevokeToken,
|
|
31
|
-
};
|
|
32
|
-
function resolveDeps(deps) {
|
|
33
|
-
return {
|
|
34
|
-
stdout: deps?.stdout ?? defaultDeps.stdout,
|
|
35
|
-
stderr: deps?.stderr ?? defaultDeps.stderr,
|
|
36
|
-
credentialsStore: deps?.credentialsStore ?? defaultDeps.credentialsStore,
|
|
37
|
-
revokeToken: deps?.revokeToken ?? defaultDeps.revokeToken,
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
function printHelp(stderr) {
|
|
41
|
-
stderr.write(`
|
|
42
|
-
auth logout - Revoke the current session and remove stored credentials
|
|
43
|
-
|
|
44
|
-
USAGE:
|
|
45
|
-
spekn auth logout
|
|
46
|
-
|
|
47
|
-
OPTIONS:
|
|
48
|
-
--help Show this help message
|
|
49
|
-
|
|
50
|
-
EXAMPLES:
|
|
51
|
-
spekn auth logout
|
|
52
|
-
`);
|
|
53
|
-
}
|
|
54
|
-
function parseArgs(args) {
|
|
55
|
-
for (const arg of args) {
|
|
56
|
-
if (arg === "--help" || arg === "-h") {
|
|
57
|
-
throw new help_error_1.HelpRequestedError();
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
async function runAuthLogoutCli(args, deps) {
|
|
62
|
-
const resolved = resolveDeps(deps);
|
|
63
|
-
try {
|
|
64
|
-
parseArgs(args);
|
|
65
|
-
(0, structured_log_1.appendCliStructuredLog)({
|
|
66
|
-
source: "cli.auth.logout",
|
|
67
|
-
level: "info",
|
|
68
|
-
message: "Starting auth logout",
|
|
69
|
-
});
|
|
70
|
-
const credentials = resolved.credentialsStore.load();
|
|
71
|
-
if (credentials !== null && credentials.refreshToken) {
|
|
72
|
-
const logoutUrl = `${credentials.keycloakUrl}/realms/${credentials.realm}/protocol/openid-connect/logout`;
|
|
73
|
-
const body = new URLSearchParams({
|
|
74
|
-
client_id: "spekn-cli",
|
|
75
|
-
refresh_token: credentials.refreshToken,
|
|
76
|
-
});
|
|
77
|
-
try {
|
|
78
|
-
await resolved.revokeToken(logoutUrl, body);
|
|
79
|
-
}
|
|
80
|
-
catch {
|
|
81
|
-
// Best-effort: ignore revocation errors so local credentials are always
|
|
82
|
-
// cleared even when Keycloak is unreachable.
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
resolved.credentialsStore.clear();
|
|
86
|
-
resolved.stdout.write("Logged out successfully.\n");
|
|
87
|
-
(0, structured_log_1.appendCliStructuredLog)({
|
|
88
|
-
source: "cli.auth.logout",
|
|
89
|
-
level: "info",
|
|
90
|
-
message: "Auth logout completed",
|
|
91
|
-
});
|
|
92
|
-
return 0;
|
|
93
|
-
}
|
|
94
|
-
catch (error) {
|
|
95
|
-
if (error instanceof help_error_1.HelpRequestedError) {
|
|
96
|
-
printHelp(resolved.stderr);
|
|
97
|
-
return 0;
|
|
98
|
-
}
|
|
99
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
100
|
-
resolved.stderr.write(`Error: ${message}\n`);
|
|
101
|
-
(0, structured_log_1.appendCliStructuredLog)({
|
|
102
|
-
source: "cli.auth.logout",
|
|
103
|
-
level: "error",
|
|
104
|
-
message,
|
|
105
|
-
});
|
|
106
|
-
return 1;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
async function main() {
|
|
110
|
-
const exitCode = await runAuthLogoutCli(process.argv.slice(2));
|
|
111
|
-
process.exit(exitCode);
|
|
112
|
-
}
|
|
113
|
-
if (require.main === module) {
|
|
114
|
-
void main();
|
|
115
|
-
}
|
package/dist/auth-status.d.ts
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* auth status CLI command
|
|
4
|
-
*
|
|
5
|
-
* Displays the current authentication state: logged-in user, token expiry,
|
|
6
|
-
* and organization (if set). Attempts a silent token refresh when the stored
|
|
7
|
-
* token is expired but a refresh token is available.
|
|
8
|
-
*
|
|
9
|
-
* Usage: spekn auth status
|
|
10
|
-
*/
|
|
11
|
-
import { CredentialsStore } from "./auth/credentials-store.js";
|
|
12
|
-
interface Deps {
|
|
13
|
-
stdout: {
|
|
14
|
-
write(s: string): void;
|
|
15
|
-
};
|
|
16
|
-
stderr: {
|
|
17
|
-
write(s: string): void;
|
|
18
|
-
};
|
|
19
|
-
credentialsStore: CredentialsStore;
|
|
20
|
-
}
|
|
21
|
-
declare function parseArgs(args: string[]): void;
|
|
22
|
-
export declare function runAuthStatusCli(args: string[], deps?: Partial<Deps>): Promise<number>;
|
|
23
|
-
declare function main(): Promise<void>;
|
|
24
|
-
export { main, parseArgs };
|
package/dist/auth-status.js
DELETED
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
"use strict";
|
|
3
|
-
/**
|
|
4
|
-
* auth status CLI command
|
|
5
|
-
*
|
|
6
|
-
* Displays the current authentication state: logged-in user, token expiry,
|
|
7
|
-
* and organization (if set). Attempts a silent token refresh when the stored
|
|
8
|
-
* token is expired but a refresh token is available.
|
|
9
|
-
*
|
|
10
|
-
* Usage: spekn auth status
|
|
11
|
-
*/
|
|
12
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
-
exports.runAuthStatusCli = runAuthStatusCli;
|
|
14
|
-
exports.main = main;
|
|
15
|
-
exports.parseArgs = parseArgs;
|
|
16
|
-
const credentials_store_js_1 = require("./auth/credentials-store.js");
|
|
17
|
-
const help_error_1 = require("./utils/help-error");
|
|
18
|
-
const structured_log_1 = require("./utils/structured-log");
|
|
19
|
-
const defaultDeps = {
|
|
20
|
-
stdout: process.stdout,
|
|
21
|
-
stderr: process.stderr,
|
|
22
|
-
credentialsStore: new credentials_store_js_1.CredentialsStore(),
|
|
23
|
-
};
|
|
24
|
-
function resolveDeps(deps) {
|
|
25
|
-
return {
|
|
26
|
-
stdout: deps?.stdout ?? defaultDeps.stdout,
|
|
27
|
-
stderr: deps?.stderr ?? defaultDeps.stderr,
|
|
28
|
-
credentialsStore: deps?.credentialsStore ?? defaultDeps.credentialsStore,
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
function printHelp(stderr) {
|
|
32
|
-
stderr.write(`
|
|
33
|
-
auth status - Show the current authentication status
|
|
34
|
-
|
|
35
|
-
USAGE:
|
|
36
|
-
spekn auth status
|
|
37
|
-
|
|
38
|
-
OPTIONS:
|
|
39
|
-
--help Show this help message
|
|
40
|
-
|
|
41
|
-
EXAMPLES:
|
|
42
|
-
spekn auth status
|
|
43
|
-
`);
|
|
44
|
-
}
|
|
45
|
-
function parseArgs(args) {
|
|
46
|
-
for (const arg of args) {
|
|
47
|
-
if (arg === "--help" || arg === "-h") {
|
|
48
|
-
throw new help_error_1.HelpRequestedError();
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
async function runAuthStatusCli(args, deps) {
|
|
53
|
-
const resolved = resolveDeps(deps);
|
|
54
|
-
try {
|
|
55
|
-
parseArgs(args);
|
|
56
|
-
(0, structured_log_1.appendCliStructuredLog)({
|
|
57
|
-
source: "cli.auth.status",
|
|
58
|
-
level: "info",
|
|
59
|
-
message: "Checking auth status",
|
|
60
|
-
});
|
|
61
|
-
const credentials = resolved.credentialsStore.load();
|
|
62
|
-
if (credentials === null) {
|
|
63
|
-
resolved.stdout.write("Not logged in. Run `spekn auth login` to authenticate.\n");
|
|
64
|
-
return 1;
|
|
65
|
-
}
|
|
66
|
-
const token = await resolved.credentialsStore.getValidToken();
|
|
67
|
-
if (token === null) {
|
|
68
|
-
resolved.stdout.write("Session expired. Run `spekn auth login` to re-authenticate.\n");
|
|
69
|
-
return 1;
|
|
70
|
-
}
|
|
71
|
-
// Reload credentials after a potential refresh so we report the updated
|
|
72
|
-
// expiry time rather than the stale one.
|
|
73
|
-
const fresh = resolved.credentialsStore.load() ?? credentials;
|
|
74
|
-
const email = fresh.user?.email ?? "unknown";
|
|
75
|
-
const expiresAt = new Date(fresh.expiresAt).toLocaleString();
|
|
76
|
-
const orgId = fresh.organizationId ?? "not set";
|
|
77
|
-
resolved.stdout.write(`Logged in as ${email}\n`);
|
|
78
|
-
resolved.stdout.write(`Token expires: ${expiresAt}\n`);
|
|
79
|
-
resolved.stdout.write(`Organization: ${orgId}\n`);
|
|
80
|
-
(0, structured_log_1.appendCliStructuredLog)({
|
|
81
|
-
source: "cli.auth.status",
|
|
82
|
-
level: "info",
|
|
83
|
-
message: "Auth status available",
|
|
84
|
-
details: { email, organizationId: orgId },
|
|
85
|
-
});
|
|
86
|
-
return 0;
|
|
87
|
-
}
|
|
88
|
-
catch (error) {
|
|
89
|
-
if (error instanceof help_error_1.HelpRequestedError) {
|
|
90
|
-
printHelp(resolved.stderr);
|
|
91
|
-
return 0;
|
|
92
|
-
}
|
|
93
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
94
|
-
resolved.stderr.write(`Error: ${message}\n`);
|
|
95
|
-
(0, structured_log_1.appendCliStructuredLog)({
|
|
96
|
-
source: "cli.auth.status",
|
|
97
|
-
level: "error",
|
|
98
|
-
message,
|
|
99
|
-
});
|
|
100
|
-
return 1;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
async function main() {
|
|
104
|
-
const exitCode = await runAuthStatusCli(process.argv.slice(2));
|
|
105
|
-
process.exit(exitCode);
|
|
106
|
-
}
|
|
107
|
-
if (require.main === module) {
|
|
108
|
-
void main();
|
|
109
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* backlog-generate CLI Tool
|
|
4
|
-
*
|
|
5
|
-
* Auto-generate tasks from specification anchors.
|
|
6
|
-
*
|
|
7
|
-
* Usage: npm run backlog-generate <spec-file-path> [OPTIONS]
|
|
8
|
-
* Example: npm run backlog-generate specs/WORKFLOW.md --project-id=<uuid>
|
|
9
|
-
*/
|
|
10
|
-
declare function main(argv?: string[]): Promise<number>;
|
|
11
|
-
export { main };
|
package/dist/backlog-generate.js
DELETED
|
@@ -1,308 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
"use strict";
|
|
3
|
-
/**
|
|
4
|
-
* backlog-generate CLI Tool
|
|
5
|
-
*
|
|
6
|
-
* Auto-generate tasks from specification anchors.
|
|
7
|
-
*
|
|
8
|
-
* Usage: npm run backlog-generate <spec-file-path> [OPTIONS]
|
|
9
|
-
* Example: npm run backlog-generate specs/WORKFLOW.md --project-id=<uuid>
|
|
10
|
-
*/
|
|
11
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
12
|
-
if (k2 === undefined) k2 = k;
|
|
13
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
14
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
15
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
16
|
-
}
|
|
17
|
-
Object.defineProperty(o, k2, desc);
|
|
18
|
-
}) : (function(o, m, k, k2) {
|
|
19
|
-
if (k2 === undefined) k2 = k;
|
|
20
|
-
o[k2] = m[k];
|
|
21
|
-
}));
|
|
22
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
23
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
24
|
-
}) : function(o, v) {
|
|
25
|
-
o["default"] = v;
|
|
26
|
-
});
|
|
27
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
28
|
-
var ownKeys = function(o) {
|
|
29
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
30
|
-
var ar = [];
|
|
31
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
32
|
-
return ar;
|
|
33
|
-
};
|
|
34
|
-
return ownKeys(o);
|
|
35
|
-
};
|
|
36
|
-
return function (mod) {
|
|
37
|
-
if (mod && mod.__esModule) return mod;
|
|
38
|
-
var result = {};
|
|
39
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
40
|
-
__setModuleDefault(result, mod);
|
|
41
|
-
return result;
|
|
42
|
-
};
|
|
43
|
-
})();
|
|
44
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
-
exports.main = main;
|
|
46
|
-
const fs = __importStar(require("fs"));
|
|
47
|
-
const path = __importStar(require("path"));
|
|
48
|
-
const agents_1 = require("@spekn/agents");
|
|
49
|
-
const shared_1 = require("@spekn/shared");
|
|
50
|
-
const shared_2 = require("@spekn/shared");
|
|
51
|
-
const shared_3 = require("@spekn/shared");
|
|
52
|
-
const cli_runtime_1 = require("./utils/cli-runtime");
|
|
53
|
-
function parseArgs(args) {
|
|
54
|
-
const options = { dryRun: false, verbose: false };
|
|
55
|
-
let filePath;
|
|
56
|
-
for (let i = 0; i < args.length; i++) {
|
|
57
|
-
const arg = args[i];
|
|
58
|
-
if (arg.startsWith("--project-id=")) {
|
|
59
|
-
options.projectId = arg.split("=")[1];
|
|
60
|
-
}
|
|
61
|
-
else if (arg.startsWith("--spec-id=")) {
|
|
62
|
-
options.specId = arg.split("=")[1];
|
|
63
|
-
}
|
|
64
|
-
else if (arg.startsWith("--priority=")) {
|
|
65
|
-
const priority = arg.split("=")[1];
|
|
66
|
-
if (Object.values(shared_2.TaskPriority).includes(priority)) {
|
|
67
|
-
options.priority = priority;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
else if (arg === "--dry-run" || arg === "-d") {
|
|
71
|
-
options.dryRun = true;
|
|
72
|
-
}
|
|
73
|
-
else if (arg === "--verbose" || arg === "-v") {
|
|
74
|
-
options.verbose = true;
|
|
75
|
-
}
|
|
76
|
-
else if (!arg.startsWith("-")) {
|
|
77
|
-
filePath = arg;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
if (!filePath) {
|
|
81
|
-
throw new Error("missing required argument: <spec-file-path>");
|
|
82
|
-
}
|
|
83
|
-
return { filePath, options };
|
|
84
|
-
}
|
|
85
|
-
function printHelp() {
|
|
86
|
-
console.log(`
|
|
87
|
-
backlog-generate - Auto-generate tasks from specification anchors
|
|
88
|
-
|
|
89
|
-
USAGE:
|
|
90
|
-
npm run backlog-generate <spec-file-path> [OPTIONS]
|
|
91
|
-
|
|
92
|
-
ARGUMENTS:
|
|
93
|
-
<spec-file-path> Path to the specification markdown file
|
|
94
|
-
|
|
95
|
-
OPTIONS:
|
|
96
|
-
--project-id=<id> Project ID to associate tasks with (required for DB insert)
|
|
97
|
-
--spec-id=<id> Specification ID to associate tasks with (required for DB insert)
|
|
98
|
-
--priority=<level> Default task priority (low|medium|high|critical, default: medium)
|
|
99
|
-
-d, --dry-run Preview tasks without creating them
|
|
100
|
-
-v, --verbose Show detailed output
|
|
101
|
-
-h, --help Show this help message
|
|
102
|
-
|
|
103
|
-
EXAMPLES:
|
|
104
|
-
npm run backlog-generate specs/WORKFLOW.md --dry-run
|
|
105
|
-
npm run backlog-generate specs/WORKFLOW.md --project-id=abc123 --spec-id=def456
|
|
106
|
-
npm run backlog-generate specs/SPECIFICATION.md --priority=high --verbose
|
|
107
|
-
`);
|
|
108
|
-
}
|
|
109
|
-
function extractAcceptanceCriteria(content) {
|
|
110
|
-
const criteria = [];
|
|
111
|
-
// Look for "Acceptance Criteria" section
|
|
112
|
-
const lines = content.split("\n");
|
|
113
|
-
let inCriteriaSection = false;
|
|
114
|
-
for (const line of lines) {
|
|
115
|
-
if (line.match(/^\*\*Acceptance Criteria\*\*:|^##\s*Acceptance Criteria|^###\s*Acceptance Criteria/i)) {
|
|
116
|
-
inCriteriaSection = true;
|
|
117
|
-
continue;
|
|
118
|
-
}
|
|
119
|
-
// Stop at next section heading or bold marker
|
|
120
|
-
if (inCriteriaSection &&
|
|
121
|
-
(line.match(/^##[^#]|^\*\*[^*]+\*\*:/) || line.trim() === "---")) {
|
|
122
|
-
break;
|
|
123
|
-
}
|
|
124
|
-
// Extract list items
|
|
125
|
-
if (inCriteriaSection && line.match(/^[-*]\s+/)) {
|
|
126
|
-
const criterion = line.replace(/^[-*]\s+/, "").trim();
|
|
127
|
-
if (criterion) {
|
|
128
|
-
criteria.push(criterion);
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
// If no explicit criteria found, look for bullet points
|
|
133
|
-
if (criteria.length === 0) {
|
|
134
|
-
for (const line of lines) {
|
|
135
|
-
if (line.match(/^[-*]\s+/)) {
|
|
136
|
-
const item = line.replace(/^[-*]\s+/, "").trim();
|
|
137
|
-
if (item && !item.startsWith("**")) {
|
|
138
|
-
criteria.push(item);
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
return criteria;
|
|
144
|
-
}
|
|
145
|
-
function extractDependencies(content) {
|
|
146
|
-
const dependencies = [];
|
|
147
|
-
// Look for "Dependencies" section
|
|
148
|
-
const dependencyMatch = content.match(/\*\*Dependencies\*\*:([^\n]+)/i);
|
|
149
|
-
if (dependencyMatch) {
|
|
150
|
-
const dependencyText = dependencyMatch[1];
|
|
151
|
-
const dependencyAnchors = dependencyText.match(/#[a-z0-9._-]+/gi);
|
|
152
|
-
if (dependencyAnchors) {
|
|
153
|
-
dependencies.push(...dependencyAnchors.map((d) => d.replace(/^#/, "")));
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
return dependencies;
|
|
157
|
-
}
|
|
158
|
-
async function main(argv) {
|
|
159
|
-
const args = argv ?? process.argv.slice(2);
|
|
160
|
-
if ((0, cli_runtime_1.hasHelpFlag)(args)) {
|
|
161
|
-
printHelp();
|
|
162
|
-
return 0;
|
|
163
|
-
}
|
|
164
|
-
let filePath;
|
|
165
|
-
let options;
|
|
166
|
-
try {
|
|
167
|
-
({ filePath, options } = parseArgs(args));
|
|
168
|
-
}
|
|
169
|
-
catch {
|
|
170
|
-
console.error("Error: Missing required argument <spec-file-path>");
|
|
171
|
-
printHelp();
|
|
172
|
-
return 1;
|
|
173
|
-
}
|
|
174
|
-
// Resolve file path
|
|
175
|
-
const resolvedPath = path.resolve(process.cwd(), filePath);
|
|
176
|
-
// Check if file exists
|
|
177
|
-
if (!fs.existsSync(resolvedPath)) {
|
|
178
|
-
console.error(`Error: File not found: ${resolvedPath}`);
|
|
179
|
-
return 1;
|
|
180
|
-
}
|
|
181
|
-
// Read file content
|
|
182
|
-
let content;
|
|
183
|
-
try {
|
|
184
|
-
content = fs.readFileSync(resolvedPath, "utf-8");
|
|
185
|
-
}
|
|
186
|
-
catch (error) {
|
|
187
|
-
console.error(`Error reading file: ${(0, cli_runtime_1.errorMessage)(error)}`);
|
|
188
|
-
return 1;
|
|
189
|
-
}
|
|
190
|
-
// Extract anchors
|
|
191
|
-
const anchors = (0, agents_1.extractAnchors)(content);
|
|
192
|
-
if (anchors.length === 0) {
|
|
193
|
-
console.log("No anchors found in the specification.");
|
|
194
|
-
return 0;
|
|
195
|
-
}
|
|
196
|
-
console.log(`\nFound ${anchors.length} anchor(s) in ${path.basename(filePath)}`);
|
|
197
|
-
// Generate tasks from anchors
|
|
198
|
-
const tasksToCreate = [];
|
|
199
|
-
for (const anchor of anchors) {
|
|
200
|
-
const anchorContent = (0, agents_1.extractAnchorContent)(anchor.anchor, content);
|
|
201
|
-
if (!anchorContent)
|
|
202
|
-
continue;
|
|
203
|
-
const acceptanceCriteria = extractAcceptanceCriteria(anchorContent);
|
|
204
|
-
const dependencies = extractDependencies(anchorContent);
|
|
205
|
-
// Extract first paragraph as description
|
|
206
|
-
const lines = anchorContent.split("\n").filter((l) => l.trim());
|
|
207
|
-
const descriptionLines = lines
|
|
208
|
-
.slice(1)
|
|
209
|
-
.filter((l) => !l.match(/^#{1,6}\s/) &&
|
|
210
|
-
!l.match(/^[-*]\s/) &&
|
|
211
|
-
!l.match(/^\*\*[^*]+\*\*:/) &&
|
|
212
|
-
l.trim() !== "---");
|
|
213
|
-
const description = descriptionLines.slice(0, 3).join("\n").trim() ||
|
|
214
|
-
`Implementation of ${anchor.anchor}`;
|
|
215
|
-
tasksToCreate.push({
|
|
216
|
-
title: anchor.headingText.replace(/^#+\s*#[a-z0-9._-]+\s*/i, "").trim() ||
|
|
217
|
-
anchor.anchor,
|
|
218
|
-
description,
|
|
219
|
-
anchor: anchor.anchor,
|
|
220
|
-
acceptanceCriteria: acceptanceCriteria.length > 0
|
|
221
|
-
? acceptanceCriteria
|
|
222
|
-
: ["Implementation complete", "Tests passing"],
|
|
223
|
-
dependencies,
|
|
224
|
-
priority: options.priority || shared_2.TaskPriority.MEDIUM,
|
|
225
|
-
});
|
|
226
|
-
}
|
|
227
|
-
// Display preview
|
|
228
|
-
console.log(`\nGenerated ${tasksToCreate.length} task(s):\n`);
|
|
229
|
-
tasksToCreate.forEach((task, index) => {
|
|
230
|
-
console.log(`${index + 1}. ${task.title}`);
|
|
231
|
-
console.log(` Anchor: ${task.anchor}`);
|
|
232
|
-
console.log(` Priority: ${task.priority}`);
|
|
233
|
-
if (task.dependencies.length > 0) {
|
|
234
|
-
console.log(` Dependencies: ${task.dependencies.join(", ")}`);
|
|
235
|
-
}
|
|
236
|
-
if (options.verbose) {
|
|
237
|
-
console.log(` Description: ${task.description}`);
|
|
238
|
-
console.log(` Acceptance Criteria:`);
|
|
239
|
-
task.acceptanceCriteria.forEach((criterion) => {
|
|
240
|
-
console.log(` - ${criterion}`);
|
|
241
|
-
});
|
|
242
|
-
}
|
|
243
|
-
console.log();
|
|
244
|
-
});
|
|
245
|
-
// Create tasks in database if not dry-run
|
|
246
|
-
if (!options.dryRun) {
|
|
247
|
-
if (!options.projectId || !options.specId) {
|
|
248
|
-
console.error("\nError: --project-id and --spec-id are required for task creation");
|
|
249
|
-
console.log("Use --dry-run to preview without creating tasks");
|
|
250
|
-
return 1;
|
|
251
|
-
}
|
|
252
|
-
console.log("Connecting to database...");
|
|
253
|
-
await shared_1.AppDataSource.initialize();
|
|
254
|
-
try {
|
|
255
|
-
// Verify project and spec exist
|
|
256
|
-
const specification = await shared_1.AppDataSource.getRepository(shared_3.Specification).findOne({
|
|
257
|
-
where: { id: options.specId },
|
|
258
|
-
});
|
|
259
|
-
if (!specification) {
|
|
260
|
-
console.error(`Error: Specification with ID ${options.specId} not found`);
|
|
261
|
-
return 1;
|
|
262
|
-
}
|
|
263
|
-
if (specification.projectId !== options.projectId) {
|
|
264
|
-
console.error(`Error: Specification belongs to project ${specification.projectId}, not ${options.projectId}`);
|
|
265
|
-
return 1;
|
|
266
|
-
}
|
|
267
|
-
// Create tasks
|
|
268
|
-
const taskRepository = shared_1.AppDataSource.getRepository(shared_2.Task);
|
|
269
|
-
const createdTasks = [];
|
|
270
|
-
for (const taskData of tasksToCreate) {
|
|
271
|
-
const task = taskRepository.create({
|
|
272
|
-
title: taskData.title,
|
|
273
|
-
description: taskData.description,
|
|
274
|
-
status: shared_2.TaskStatus.OPEN,
|
|
275
|
-
priority: taskData.priority,
|
|
276
|
-
acceptanceCriteria: taskData.acceptanceCriteria,
|
|
277
|
-
dependencies: taskData.dependencies,
|
|
278
|
-
specAnchor: taskData.anchor,
|
|
279
|
-
specificationId: options.specId,
|
|
280
|
-
projectId: options.projectId,
|
|
281
|
-
});
|
|
282
|
-
const saved = await taskRepository.save(task);
|
|
283
|
-
createdTasks.push(saved);
|
|
284
|
-
}
|
|
285
|
-
console.log(`\nSuccessfully created ${createdTasks.length} task(s)!`);
|
|
286
|
-
if (options.verbose) {
|
|
287
|
-
console.log("\nCreated Task IDs:");
|
|
288
|
-
createdTasks.forEach((task, index) => {
|
|
289
|
-
console.log(` ${index + 1}. ${task.id} - ${task.title}`);
|
|
290
|
-
});
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
catch (error) {
|
|
294
|
-
console.error(`\nError creating tasks: ${(0, cli_runtime_1.errorMessage)(error)}`);
|
|
295
|
-
return 1;
|
|
296
|
-
}
|
|
297
|
-
finally {
|
|
298
|
-
await shared_1.AppDataSource.destroy();
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
else {
|
|
302
|
-
console.log("Dry-run mode: Tasks not created. Use --project-id and --spec-id to create tasks.");
|
|
303
|
-
}
|
|
304
|
-
return 0;
|
|
305
|
-
}
|
|
306
|
-
if (require.main === module) {
|
|
307
|
-
void (0, cli_runtime_1.runCliMain)(main, { errorPrefix: "backlog-generate failed" });
|
|
308
|
-
}
|
package/dist/backlog-health.d.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* backlog-health CLI Tool
|
|
4
|
-
*
|
|
5
|
-
* Report backlog health metrics.
|
|
6
|
-
*
|
|
7
|
-
* Usage: npm run backlog-health [OPTIONS]
|
|
8
|
-
* Example: npm run backlog-health --project-id=<uuid>
|
|
9
|
-
*/
|
|
10
|
-
declare function main(argv?: string[]): Promise<number>;
|
|
11
|
-
export { main };
|