spets 0.1.1 → 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
CHANGED
|
@@ -5,23 +5,27 @@ Spec Driven Development Execution Framework - 유저가 정의한 스텝대로 S
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
+
# 글로벌 설치 (선택)
|
|
8
9
|
npm install -g spets
|
|
10
|
+
|
|
11
|
+
# 또는 npx로 바로 사용 (설치 불필요)
|
|
12
|
+
npx spets init
|
|
9
13
|
```
|
|
10
14
|
|
|
11
15
|
## Quick Start
|
|
12
16
|
|
|
13
17
|
```bash
|
|
14
18
|
# 프로젝트에서 초기화
|
|
15
|
-
spets init
|
|
19
|
+
npx spets init
|
|
16
20
|
|
|
17
21
|
# 워크플로우 시작
|
|
18
|
-
spets start "TODO 앱 만들어줘"
|
|
22
|
+
npx spets start "TODO 앱 만들어줘"
|
|
19
23
|
|
|
20
24
|
# 상태 확인
|
|
21
|
-
spets status
|
|
25
|
+
npx spets status
|
|
22
26
|
|
|
23
27
|
# 중단된 워크플로우 재개
|
|
24
|
-
spets resume
|
|
28
|
+
npx spets resume
|
|
25
29
|
```
|
|
26
30
|
|
|
27
31
|
## How it Works
|
|
@@ -56,10 +60,10 @@ PR/Issue 코멘트로 워크플로우 제어:
|
|
|
56
60
|
|
|
57
61
|
```bash
|
|
58
62
|
# GitHub Actions 워크플로우 포함해서 초기화
|
|
59
|
-
spets init --github
|
|
63
|
+
npx spets init --github
|
|
60
64
|
|
|
61
65
|
# GitHub 플랫폼으로 시작
|
|
62
|
-
spets start "task" --platform github --owner myorg --repo myrepo --issue 42
|
|
66
|
+
npx spets start "task" --platform github --owner myorg --repo myrepo --issue 42
|
|
63
67
|
```
|
|
64
68
|
|
|
65
69
|
코멘트 명령어:
|
|
@@ -71,12 +75,14 @@ spets start "task" --platform github --owner myorg --repo myrepo --issue 42
|
|
|
71
75
|
|
|
72
76
|
```bash
|
|
73
77
|
# Claude Code 스킬 설치
|
|
74
|
-
spets plugin install claude
|
|
78
|
+
npx spets plugin install claude
|
|
75
79
|
|
|
76
80
|
# Claude Code에서 사용
|
|
77
81
|
/spets start "task description"
|
|
78
82
|
```
|
|
79
83
|
|
|
84
|
+
스킬이 설치되면 Claude Code 내에서 `npx spets` 명령어를 자동으로 실행합니다. 글로벌 설치 없이도 동작합니다.
|
|
85
|
+
|
|
80
86
|
## Configuration
|
|
81
87
|
|
|
82
88
|
`.sept/config.yml`:
|
|
@@ -52,6 +52,10 @@ function loadStepDefinition(stepName, cwd = process.cwd()) {
|
|
|
52
52
|
template
|
|
53
53
|
};
|
|
54
54
|
}
|
|
55
|
+
function getGitHubConfig(cwd = process.cwd()) {
|
|
56
|
+
const config = loadConfig(cwd);
|
|
57
|
+
return config.github;
|
|
58
|
+
}
|
|
55
59
|
|
|
56
60
|
// src/core/state.ts
|
|
57
61
|
function generateTaskId() {
|
|
@@ -194,6 +198,7 @@ export {
|
|
|
194
198
|
spetsExists,
|
|
195
199
|
loadConfig,
|
|
196
200
|
loadStepDefinition,
|
|
201
|
+
getGitHubConfig,
|
|
197
202
|
generateTaskId,
|
|
198
203
|
getTaskDir,
|
|
199
204
|
getOutputPath,
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
generateTaskId,
|
|
4
|
+
getGitHubConfig,
|
|
4
5
|
getOutputPath,
|
|
5
6
|
getSpetsDir,
|
|
6
7
|
getWorkflowState,
|
|
@@ -13,7 +14,7 @@ import {
|
|
|
13
14
|
saveTaskMetadata,
|
|
14
15
|
spetsExists,
|
|
15
16
|
updateDocumentStatus
|
|
16
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-XYU22TND.js";
|
|
17
18
|
|
|
18
19
|
// src/index.ts
|
|
19
20
|
import { Command } from "commander";
|
|
@@ -591,7 +592,7 @@ var Executor = class {
|
|
|
591
592
|
};
|
|
592
593
|
|
|
593
594
|
// src/platform/cli.ts
|
|
594
|
-
import { spawn as spawn2 } from "child_process";
|
|
595
|
+
import { spawn as spawn2, execSync } from "child_process";
|
|
595
596
|
import { input, select, confirm } from "@inquirer/prompts";
|
|
596
597
|
|
|
597
598
|
// src/platform/interface.ts
|
|
@@ -740,6 +741,24 @@ var CliPlatform = class extends BasePlatform {
|
|
|
740
741
|
});
|
|
741
742
|
});
|
|
742
743
|
}
|
|
744
|
+
isClaudeInstalled() {
|
|
745
|
+
try {
|
|
746
|
+
const command = process.platform === "win32" ? "where" : "which";
|
|
747
|
+
execSync(`${command} claude`, { stdio: "ignore" });
|
|
748
|
+
return true;
|
|
749
|
+
} catch {
|
|
750
|
+
return false;
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
getClaudeExecutable() {
|
|
754
|
+
if (this.claudeCommand !== "claude") {
|
|
755
|
+
return { command: this.claudeCommand, args: [] };
|
|
756
|
+
}
|
|
757
|
+
if (this.isClaudeInstalled()) {
|
|
758
|
+
return { command: "claude", args: [] };
|
|
759
|
+
}
|
|
760
|
+
return { command: "npx", args: ["--yes", "@anthropic-ai/claude-code"] };
|
|
761
|
+
}
|
|
743
762
|
parseResponse(response) {
|
|
744
763
|
const questions = [];
|
|
745
764
|
const questionMatch = response.match(/```questions\n([\s\S]*?)```/);
|
|
@@ -1015,19 +1034,24 @@ async function startCommand(query, options) {
|
|
|
1015
1034
|
saveTaskMetadata(taskId, query, cwd);
|
|
1016
1035
|
let platform;
|
|
1017
1036
|
if (options.platform === "github") {
|
|
1018
|
-
|
|
1019
|
-
|
|
1037
|
+
const githubConfig = getGitHubConfig(cwd);
|
|
1038
|
+
const owner = options.owner || githubConfig?.owner;
|
|
1039
|
+
const repo = options.repo || githubConfig?.repo;
|
|
1040
|
+
const pr = options.pr || (githubConfig?.defaultPr ? String(githubConfig.defaultPr) : void 0);
|
|
1041
|
+
const issue = options.issue || (githubConfig?.defaultIssue ? String(githubConfig.defaultIssue) : void 0);
|
|
1042
|
+
if (!owner || !repo) {
|
|
1043
|
+
console.error("GitHub platform requires --owner and --repo (or set in .spets/config.yml)");
|
|
1020
1044
|
process.exit(1);
|
|
1021
1045
|
}
|
|
1022
|
-
if (!
|
|
1023
|
-
console.error("GitHub platform requires --pr or --issue");
|
|
1046
|
+
if (!pr && !issue) {
|
|
1047
|
+
console.error("GitHub platform requires --pr or --issue (or set defaultPr/defaultIssue in .spets/config.yml)");
|
|
1024
1048
|
process.exit(1);
|
|
1025
1049
|
}
|
|
1026
1050
|
platform = new GitHubPlatform({
|
|
1027
|
-
owner
|
|
1028
|
-
repo
|
|
1029
|
-
prNumber:
|
|
1030
|
-
issueNumber:
|
|
1051
|
+
owner,
|
|
1052
|
+
repo,
|
|
1053
|
+
prNumber: pr ? parseInt(pr, 10) : void 0,
|
|
1054
|
+
issueNumber: issue ? parseInt(issue, 10) : void 0
|
|
1031
1055
|
});
|
|
1032
1056
|
} else {
|
|
1033
1057
|
platform = new CliPlatform();
|
|
@@ -1188,6 +1212,8 @@ function installClaudePlugin() {
|
|
|
1188
1212
|
console.log(' /spets start "your task description"');
|
|
1189
1213
|
console.log(" /spets status");
|
|
1190
1214
|
console.log(" /spets resume");
|
|
1215
|
+
console.log("");
|
|
1216
|
+
console.log("Note: The plugin uses npx to run spets, so global installation is not required.");
|
|
1191
1217
|
}
|
|
1192
1218
|
async function uninstallPlugin(name) {
|
|
1193
1219
|
if (name === "claude") {
|
|
@@ -1238,21 +1264,23 @@ When the user invokes this command:
|
|
|
1238
1264
|
2. Execute the appropriate spets CLI command using Bash
|
|
1239
1265
|
3. For 'start', read the generated documents and help iterate
|
|
1240
1266
|
|
|
1267
|
+
**Important**: Use \`npx spets\` to run commands. This ensures the command works even if spets is not globally installed.
|
|
1268
|
+
|
|
1241
1269
|
### Start Flow
|
|
1242
1270
|
|
|
1243
|
-
1. Run: \`spets start "<query>"\`
|
|
1271
|
+
1. Run: \`npx spets start "<query>"\`
|
|
1244
1272
|
2. Read the generated plan document from .spets/outputs/<taskId>/
|
|
1245
1273
|
3. Present the plan to the user
|
|
1246
1274
|
4. If user approves, continue. If they want changes, provide feedback.
|
|
1247
1275
|
|
|
1248
1276
|
### Status Flow
|
|
1249
1277
|
|
|
1250
|
-
1. Run: \`spets status\`
|
|
1278
|
+
1. Run: \`npx spets status\`
|
|
1251
1279
|
2. Present the current workflow state
|
|
1252
1280
|
|
|
1253
1281
|
### Resume Flow
|
|
1254
1282
|
|
|
1255
|
-
1. Run: \`spets resume\`
|
|
1283
|
+
1. Run: \`npx spets resume\`
|
|
1256
1284
|
2. Continue the workflow from where it paused
|
|
1257
1285
|
|
|
1258
1286
|
## Example Session
|
|
@@ -1260,11 +1288,11 @@ When the user invokes this command:
|
|
|
1260
1288
|
User: /spets start "Create a REST API for user management"
|
|
1261
1289
|
|
|
1262
1290
|
Claude:
|
|
1263
|
-
1. Runs \`spets start "Create a REST API for user management"\`
|
|
1291
|
+
1. Runs \`npx spets start "Create a REST API for user management"\`
|
|
1264
1292
|
2. Reads the generated plan
|
|
1265
1293
|
3. Asks user: "Here's the plan. [shows plan] Would you like to approve or revise?"
|
|
1266
|
-
4. On approve: \`spets resume --approve\`
|
|
1267
|
-
5. On revise: \`spets resume --revise "user feedback"\`
|
|
1294
|
+
4. On approve: \`npx spets resume --approve\`
|
|
1295
|
+
5. On revise: \`npx spets resume --revise "user feedback"\`
|
|
1268
1296
|
|
|
1269
1297
|
$ARGUMENTS
|
|
1270
1298
|
command: The spets command to run (start, status, resume)
|
|
@@ -1279,9 +1307,18 @@ async function githubCommand(options) {
|
|
|
1279
1307
|
console.error("Spets not initialized.");
|
|
1280
1308
|
process.exit(1);
|
|
1281
1309
|
}
|
|
1282
|
-
const
|
|
1310
|
+
const configGitHub = getGitHubConfig(cwd);
|
|
1311
|
+
const owner = options.owner || configGitHub?.owner;
|
|
1312
|
+
const repo = options.repo || configGitHub?.repo;
|
|
1313
|
+
const pr = options.pr || (configGitHub?.defaultPr ? String(configGitHub.defaultPr) : void 0);
|
|
1314
|
+
const issue = options.issue || (configGitHub?.defaultIssue ? String(configGitHub.defaultIssue) : void 0);
|
|
1315
|
+
const { comment, task } = options;
|
|
1316
|
+
if (!owner || !repo) {
|
|
1317
|
+
console.error("GitHub requires --owner and --repo (or set in .spets/config.yml)");
|
|
1318
|
+
process.exit(1);
|
|
1319
|
+
}
|
|
1283
1320
|
if (!pr && !issue) {
|
|
1284
|
-
console.error("Either --pr or --issue is required");
|
|
1321
|
+
console.error("Either --pr or --issue is required (or set defaultPr/defaultIssue in .spets/config.yml)");
|
|
1285
1322
|
process.exit(1);
|
|
1286
1323
|
}
|
|
1287
1324
|
const parsed = parseGitHubCommand(comment);
|
|
@@ -1299,7 +1336,7 @@ async function githubCommand(options) {
|
|
|
1299
1336
|
}
|
|
1300
1337
|
if (!taskId) {
|
|
1301
1338
|
const config2 = loadConfig(cwd);
|
|
1302
|
-
const { listTasks: listTasks2 } = await import("./state-
|
|
1339
|
+
const { listTasks: listTasks2 } = await import("./state-H2GQS43T.js");
|
|
1303
1340
|
const tasks = listTasks2(cwd);
|
|
1304
1341
|
for (const tid of tasks) {
|
|
1305
1342
|
const state2 = getWorkflowState(tid, config2, cwd);
|
|
@@ -1431,6 +1468,6 @@ program.command("init").description("Initialize spets in current directory").opt
|
|
|
1431
1468
|
program.command("status").description("Show current workflow status").option("-t, --task <taskId>", "Show status for specific task").action(statusCommand);
|
|
1432
1469
|
program.command("start").description("Start a new workflow").argument("<query>", "User query describing the task").option("-p, --platform <platform>", "Platform to use (cli, github)", "cli").option("--owner <owner>", "GitHub owner (for github platform)").option("--repo <repo>", "GitHub repo (for github platform)").option("--pr <number>", "GitHub PR number (for github platform)").option("--issue <number>", "GitHub issue number (for github platform)").action(startCommand);
|
|
1433
1470
|
program.command("resume").description("Resume paused workflow").option("-t, --task <taskId>", "Resume specific task").option("--approve", "Approve current document and proceed").option("--revise <feedback>", "Request revision with feedback").action(resumeCommand);
|
|
1434
|
-
program.command("github").description("Handle GitHub Action callback (internal)").
|
|
1471
|
+
program.command("github").description("Handle GitHub Action callback (internal)").option("--owner <owner>", "GitHub owner (or set in .spets/config.yml)").option("--repo <repo>", "GitHub repo (or set in .spets/config.yml)").option("--pr <number>", "PR number (or set defaultPr in .spets/config.yml)").option("--issue <number>", "Issue number (or set defaultIssue in .spets/config.yml)").option("-t, --task <taskId>", "Task ID").requiredOption("--comment <comment>", "Comment body").action(githubCommand);
|
|
1435
1472
|
program.command("plugin").description("Manage plugins").argument("<action>", "Action: install, uninstall, list").argument("[name]", "Plugin name").action(pluginCommand);
|
|
1436
1473
|
program.parse();
|