specstocode 0.5.0

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.
@@ -0,0 +1,98 @@
1
+ import {
2
+ appendNoteToContext,
3
+ storyContextPath
4
+ } from "./chunk-J22FYEMI.js";
5
+ import {
6
+ ask,
7
+ closePrompt
8
+ } from "./chunk-WPVDURTJ.js";
9
+ import {
10
+ requireConfig
11
+ } from "./chunk-NAOZWXOF.js";
12
+
13
+ // src/commands/log.ts
14
+ async function logDecision(title, opts) {
15
+ const config = requireConfig();
16
+ if (!title) {
17
+ title = await ask(" Decision title: ");
18
+ }
19
+ let description = opts?.description;
20
+ if (!description) {
21
+ description = await ask(" Description (what was decided and why): ");
22
+ }
23
+ if (!title?.trim() || !description?.trim()) {
24
+ console.log(" Title and description required.");
25
+ closePrompt();
26
+ return;
27
+ }
28
+ const res = await fetch(
29
+ `${config.apiBase}/api/sync/${config.syncToken}/decisions`,
30
+ {
31
+ method: "POST",
32
+ headers: { "Content-Type": "application/json" },
33
+ body: JSON.stringify({
34
+ title: title.trim(),
35
+ description: description.trim(),
36
+ category: opts?.category ?? "technical",
37
+ story_id: opts?.story ?? void 0
38
+ })
39
+ }
40
+ );
41
+ if (res.ok) {
42
+ console.log(` \u2713 Decision logged: ${title}`);
43
+ } else {
44
+ console.error(" Failed to log decision.");
45
+ }
46
+ closePrompt();
47
+ }
48
+ async function logNote(storyId, note) {
49
+ const config = requireConfig();
50
+ if (!note) {
51
+ note = await ask(" Note: ");
52
+ }
53
+ if (!note?.trim()) {
54
+ console.log(" Note required.");
55
+ closePrompt();
56
+ return;
57
+ }
58
+ const listRes = await fetch(
59
+ `${config.apiBase}/api/sync/${config.syncToken}/stories`
60
+ );
61
+ if (!listRes.ok) {
62
+ console.error(" Failed to fetch stories.");
63
+ closePrompt();
64
+ return;
65
+ }
66
+ const data = await listRes.json();
67
+ const match = data.stories.find((s) => s.id.startsWith(storyId));
68
+ if (!match) {
69
+ console.error(` No story found matching "${storyId}"`);
70
+ closePrompt();
71
+ return;
72
+ }
73
+ const res = await fetch(
74
+ `${config.apiBase}/api/sync/${config.syncToken}/stories`,
75
+ {
76
+ method: "PATCH",
77
+ headers: { "Content-Type": "application/json" },
78
+ body: JSON.stringify({
79
+ stories: [{ id: match.id, notes: note.trim() }]
80
+ })
81
+ }
82
+ );
83
+ if (res.ok) {
84
+ console.log(` \u2713 Note added to: ${match.title.slice(0, 60)}`);
85
+ } else {
86
+ console.error(" Failed to add note.");
87
+ }
88
+ const appended = appendNoteToContext(match.id, note.trim());
89
+ if (appended) {
90
+ const relPath = storyContextPath(match.id).replace(process.cwd() + "/", "");
91
+ console.log(` \u2713 Updated local context: ${relPath}`);
92
+ }
93
+ closePrompt();
94
+ }
95
+ export {
96
+ logDecision,
97
+ logNote
98
+ };
@@ -0,0 +1,16 @@
1
+ import {
2
+ ask,
3
+ askMultiline,
4
+ choose,
5
+ closePrompt,
6
+ confirm,
7
+ pausePrompt
8
+ } from "./chunk-WPVDURTJ.js";
9
+ export {
10
+ ask,
11
+ askMultiline,
12
+ choose,
13
+ closePrompt,
14
+ confirm,
15
+ pausePrompt
16
+ };
@@ -0,0 +1,49 @@
1
+ import {
2
+ ask,
3
+ closePrompt
4
+ } from "./chunk-WPVDURTJ.js";
5
+ import {
6
+ requireConfig
7
+ } from "./chunk-NAOZWXOF.js";
8
+
9
+ // src/commands/research.ts
10
+ import ora from "ora";
11
+ async function research(query) {
12
+ const config = requireConfig();
13
+ if (!query) {
14
+ query = await ask(" What do you want to research?\n > ");
15
+ if (!query?.trim()) {
16
+ console.log(" Query required.");
17
+ closePrompt();
18
+ return;
19
+ }
20
+ closePrompt();
21
+ }
22
+ const spinner = ora(" Researching...").start();
23
+ try {
24
+ const res = await fetch(
25
+ `${config.apiBase}/api/sync/${config.syncToken}/research`,
26
+ {
27
+ method: "POST",
28
+ headers: { "Content-Type": "application/json" },
29
+ body: JSON.stringify({ query })
30
+ }
31
+ );
32
+ if (!res.ok) {
33
+ spinner.fail(" Research failed");
34
+ return;
35
+ }
36
+ const result = await res.json();
37
+ spinner.succeed(` Research complete
38
+ `);
39
+ console.log(` Query: ${result.query}
40
+ `);
41
+ console.log(result.research);
42
+ console.log();
43
+ } catch (err) {
44
+ spinner.fail(` Error: ${err.message}`);
45
+ }
46
+ }
47
+ export {
48
+ research
49
+ };
@@ -0,0 +1,10 @@
1
+ import {
2
+ scope
3
+ } from "./chunk-P4M7CVDK.js";
4
+ import "./chunk-CYA6I7NV.js";
5
+ import "./chunk-QKMZ2SBR.js";
6
+ import "./chunk-WPVDURTJ.js";
7
+ import "./chunk-NAOZWXOF.js";
8
+ export {
9
+ scope
10
+ };
@@ -0,0 +1,9 @@
1
+ import {
2
+ setup
3
+ } from "./chunk-55DTUCLY.js";
4
+ import "./chunk-CYA6I7NV.js";
5
+ import "./chunk-WPVDURTJ.js";
6
+ import "./chunk-NAOZWXOF.js";
7
+ export {
8
+ setup
9
+ };
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "specstocode",
3
+ "version": "0.5.0",
4
+ "description": "CLI for specstocode.com — connect your codebase to your product story map",
5
+ "bin": {
6
+ "specstocode": "bin/specstocode.js",
7
+ "productbuilders": "bin/productbuilders.js"
8
+ },
9
+ "scripts": {
10
+ "build": "tsup src/index.ts --format esm --clean && chmod +x dist/index.js && chmod +x bin/specstocode.js && chmod +x bin/productbuilders.js",
11
+ "dev": "tsup src/index.ts --format esm --watch",
12
+ "test": "vitest run",
13
+ "prepublishOnly": "npm run build"
14
+ },
15
+ "type": "module",
16
+ "files": [
17
+ "dist",
18
+ "bin",
19
+ "README.md"
20
+ ],
21
+ "keywords": [
22
+ "specstocode",
23
+ "story-map",
24
+ "product-management",
25
+ "claude-code",
26
+ "mcp"
27
+ ],
28
+ "author": "specstocode.com",
29
+ "license": "MIT",
30
+ "dependencies": {
31
+ "@modelcontextprotocol/sdk": "^1.0.0",
32
+ "commander": "^12.0.0",
33
+ "chalk": "^5.3.0",
34
+ "ora": "^8.0.0"
35
+ },
36
+ "devDependencies": {
37
+ "tsup": "^8.0.0",
38
+ "typescript": "^5.4.0",
39
+ "@types/node": "^20.0.0",
40
+ "vitest": "^4.1.2"
41
+ }
42
+ }