intentdocs 0.10.0 → 0.11.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.
- package/README.md +6 -1
- package/dist/chunk-64I7RLP3.js +171 -0
- package/dist/{chunk-IDNUBI2P.js → chunk-65EDM7QH.js} +6 -6
- package/dist/{chunk-NFIXRIHM.js → chunk-BNEU6TLJ.js} +55 -21
- package/dist/chunk-GFKZ5CRL.js +12 -0
- package/dist/{chunk-5USVG4DW.js → chunk-ID4B5RZ2.js} +42 -21
- package/dist/{chunk-EEKEF2FD.js → chunk-IORMKLAQ.js} +178 -121
- package/dist/{chunk-UF535HZL.js → chunk-K5SNF6CG.js} +13 -2
- package/dist/{chunk-HEHHSSUM.js → chunk-KPQ42YE6.js} +1 -1
- package/dist/{chunk-YUW3W43S.js → chunk-KTGQO3AE.js} +31 -8
- package/dist/{chunk-UR73WX5I.js → chunk-UQDMUKLP.js} +2 -2
- package/dist/{chunk-LXQXJULN.js → chunk-XZE2XP6O.js} +3 -3
- package/dist/ci-NOCV3XUV.js +11 -0
- package/dist/{complexity-ZOB3BPVD.js → complexity-OJVM37NF.js} +4 -4
- package/dist/{import-prd-MJUCIMHX.js → import-prd-5FCVXCYO.js} +14 -7
- package/dist/index.js +377 -359
- package/dist/{keys-5PA3D6CX.js → keys-2W5V56FS.js} +32 -11
- package/dist/{log-EVLWM64C.js → log-DFCCAAJN.js} +23 -7
- package/dist/{map-extract-W6WJLVOF.js → map-extract-YUCFLGJS.js} +2 -2
- package/dist/{map-import-LL4AIAQE.js → map-import-7RN2NEUZ.js} +7 -6
- package/dist/{map-schema-6GL2UKZQ.js → map-schema-5BEIJM2J.js} +1 -1
- package/dist/{projects-F7GMH66U.js → projects-AYAYVFKL.js} +2 -2
- package/dist/push-33V7ANJW.js +462 -0
- package/dist/{research-4ASCZSZN.js → research-SHO5SXVQ.js} +4 -4
- package/dist/scope-RRGJHS2G.js +13 -0
- package/dist/setup-UILQVYIB.js +14 -0
- package/package.json +6 -5
- package/dist/ci-LBOCMRKZ.js +0 -11
- package/dist/scope-S3LZZ3KB.js +0 -11
- package/dist/setup-YLUPBLK6.js +0 -14
package/README.md
CHANGED
|
@@ -98,6 +98,11 @@ intent sync # Refresh INTENT.md
|
|
|
98
98
|
intent sync --context # Regenerate CLAUDE.md from your project page
|
|
99
99
|
```
|
|
100
100
|
|
|
101
|
+
`intent` is a short alias for typing. Another tool on your machine may also be
|
|
102
|
+
called `intent`, so everything the CLI writes for your agent (CLAUDE.md, slash
|
|
103
|
+
commands, hints) spells commands as `npx intentdocs …`, which always runs this
|
|
104
|
+
package.
|
|
105
|
+
|
|
101
106
|
---
|
|
102
107
|
|
|
103
108
|
## All Commands
|
|
@@ -177,7 +182,7 @@ The intentdocs MCP server exposes **tools** (actions your agent can take) and **
|
|
|
177
182
|
|
|
178
183
|
Give Claude Code or Cursor native tool and resource access to your story map.
|
|
179
184
|
|
|
180
|
-
|
|
185
|
+
`intent setup` registers it for Claude Code in the project's `.mcp.json`. To add it yourself, run `claude mcp add --scope project intent -- npx intentdocs mcp` in the project, or add this to `.mcp.json` (Claude Code) or your Cursor MCP config:
|
|
181
186
|
|
|
182
187
|
```json
|
|
183
188
|
{
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import {
|
|
2
|
+
bindingLabel,
|
|
3
|
+
clearAuth,
|
|
4
|
+
getAuth,
|
|
5
|
+
saveAuth,
|
|
6
|
+
validateAuth
|
|
7
|
+
} from "./chunk-XZE2XP6O.js";
|
|
8
|
+
import {
|
|
9
|
+
API_BASE
|
|
10
|
+
} from "./chunk-UYTVTYNB.js";
|
|
11
|
+
|
|
12
|
+
// src/commands/login.ts
|
|
13
|
+
import { exec } from "child_process";
|
|
14
|
+
function finishLogin(data) {
|
|
15
|
+
saveAuth({
|
|
16
|
+
token: data.token,
|
|
17
|
+
apiBase: API_BASE,
|
|
18
|
+
...data.userId && { userId: data.userId },
|
|
19
|
+
binding: data.binding ?? null,
|
|
20
|
+
...data.posthogKey && { posthogKey: data.posthogKey },
|
|
21
|
+
...data.posthogHost && { posthogHost: data.posthogHost }
|
|
22
|
+
});
|
|
23
|
+
console.log(`
|
|
24
|
+
|
|
25
|
+
\u2705 Logged in as ${data.userId ?? "unknown user"} \u2014 token ${bindingLabel(data.binding)}
|
|
26
|
+
`);
|
|
27
|
+
if (data.binding?.approvalStatus === "pending") {
|
|
28
|
+
console.log("An admin has been asked to approve it. Until they do, this token reads your personal projects only.\n");
|
|
29
|
+
}
|
|
30
|
+
console.log("You can now run: npx intentdocs init");
|
|
31
|
+
console.log(
|
|
32
|
+
"Optional: add your Anthropic API key to unlock AI features on any plan \u2014 npx intentdocs keys set"
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
function openBrowser(url) {
|
|
36
|
+
const cmd = process.platform === "darwin" ? `open "${url}"` : process.platform === "win32" ? `start "${url}"` : `xdg-open "${url}"`;
|
|
37
|
+
exec(cmd);
|
|
38
|
+
}
|
|
39
|
+
function sleep(ms) {
|
|
40
|
+
return new Promise((r) => setTimeout(r, ms));
|
|
41
|
+
}
|
|
42
|
+
async function login() {
|
|
43
|
+
const existing = getAuth();
|
|
44
|
+
if (existing) {
|
|
45
|
+
const result = await validateAuth();
|
|
46
|
+
if (result.valid) {
|
|
47
|
+
console.log(`Already logged in (user: ${result.userId}). Run \`intentdocs logout\` to switch accounts.`);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
switch (result.reason) {
|
|
51
|
+
case "revoked":
|
|
52
|
+
console.log("Your stored token has been revoked. Starting a fresh login...\n");
|
|
53
|
+
break;
|
|
54
|
+
case "not_found":
|
|
55
|
+
console.log("Your stored token is no longer valid. Starting a fresh login...\n");
|
|
56
|
+
break;
|
|
57
|
+
case "network_error":
|
|
58
|
+
console.error("Could not reach intentdocs.com to verify your token. Check your internet connection and try again.");
|
|
59
|
+
process.exit(1);
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
clearAuth();
|
|
63
|
+
}
|
|
64
|
+
console.log("Logging in to intentdocs...\n");
|
|
65
|
+
const res = await fetch(`${API_BASE}/api/cli/auth`, { method: "POST" });
|
|
66
|
+
if (!res.ok) {
|
|
67
|
+
console.error("Failed to start login flow. Try again.");
|
|
68
|
+
process.exit(1);
|
|
69
|
+
}
|
|
70
|
+
const { code } = await res.json();
|
|
71
|
+
const authUrl = `${API_BASE}/cli/auth?code=${code}`;
|
|
72
|
+
console.log("Opening browser to authorize...");
|
|
73
|
+
console.log(`If it doesn't open, visit: ${authUrl}
|
|
74
|
+
`);
|
|
75
|
+
openBrowser(authUrl);
|
|
76
|
+
const POLL_INTERVAL_MS = 3e3;
|
|
77
|
+
const INITIAL_TIMEOUT_S = 300;
|
|
78
|
+
const EXTEND_TIMEOUT_S = 120;
|
|
79
|
+
let totalWaitedS = 0;
|
|
80
|
+
let phase = "initial";
|
|
81
|
+
let timeoutS = INITIAL_TIMEOUT_S;
|
|
82
|
+
while (totalWaitedS < timeoutS) {
|
|
83
|
+
const elapsed = totalWaitedS;
|
|
84
|
+
const minutesLeft = Math.ceil((timeoutS - elapsed) / 60);
|
|
85
|
+
if (elapsed === 0) {
|
|
86
|
+
process.stdout.write("Waiting for browser approval...");
|
|
87
|
+
} else if (elapsed % 30 === 0) {
|
|
88
|
+
process.stdout.write(`
|
|
89
|
+
Still waiting for approval (${minutesLeft}m remaining)...`);
|
|
90
|
+
} else {
|
|
91
|
+
process.stdout.write(".");
|
|
92
|
+
}
|
|
93
|
+
await sleep(POLL_INTERVAL_MS);
|
|
94
|
+
totalWaitedS += POLL_INTERVAL_MS / 1e3;
|
|
95
|
+
try {
|
|
96
|
+
const checkRes = await fetch(`${API_BASE}/api/cli/auth?code=${code}`);
|
|
97
|
+
if (!checkRes.ok) continue;
|
|
98
|
+
const data = await checkRes.json();
|
|
99
|
+
if (data.status === "approved" && data.token) {
|
|
100
|
+
finishLogin(data);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
if (data.status === "expired") {
|
|
104
|
+
console.error("\n\nThe server-side login request expired. Run `npx intentdocs login` to start a new one.");
|
|
105
|
+
process.exit(1);
|
|
106
|
+
}
|
|
107
|
+
} catch {
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
if (phase === "initial") {
|
|
111
|
+
console.log("\n\nThe initial wait has ended. The browser approval hasn't come through yet.");
|
|
112
|
+
console.log("This can happen if you needed to create an account or got distracted.\n");
|
|
113
|
+
const rl = await import("readline");
|
|
114
|
+
const iface = rl.createInterface({ input: process.stdin, output: process.stdout });
|
|
115
|
+
const answer = await new Promise(
|
|
116
|
+
(resolve) => iface.question("Keep waiting? (y/n): ", resolve)
|
|
117
|
+
);
|
|
118
|
+
iface.close();
|
|
119
|
+
if (answer.trim().toLowerCase().startsWith("y")) {
|
|
120
|
+
phase = "extended";
|
|
121
|
+
timeoutS = totalWaitedS + EXTEND_TIMEOUT_S;
|
|
122
|
+
console.log(`
|
|
123
|
+
Waiting ${EXTEND_TIMEOUT_S / 60} more minutes...`);
|
|
124
|
+
while (totalWaitedS < timeoutS) {
|
|
125
|
+
const minutesLeft = Math.ceil((timeoutS - totalWaitedS) / 60);
|
|
126
|
+
if (Math.floor(totalWaitedS) % 30 === 0 && totalWaitedS > INITIAL_TIMEOUT_S) {
|
|
127
|
+
process.stdout.write(`
|
|
128
|
+
Still waiting (${minutesLeft}m remaining)...`);
|
|
129
|
+
} else {
|
|
130
|
+
process.stdout.write(".");
|
|
131
|
+
}
|
|
132
|
+
await sleep(POLL_INTERVAL_MS);
|
|
133
|
+
totalWaitedS += POLL_INTERVAL_MS / 1e3;
|
|
134
|
+
try {
|
|
135
|
+
const checkRes = await fetch(`${API_BASE}/api/cli/auth?code=${code}`);
|
|
136
|
+
if (!checkRes.ok) continue;
|
|
137
|
+
const data = await checkRes.json();
|
|
138
|
+
if (data.status === "approved" && data.token) {
|
|
139
|
+
finishLogin(data);
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
if (data.status === "expired") {
|
|
143
|
+
console.error("\n\nThe server-side login request expired. Run `npx intentdocs login` to start a new one.");
|
|
144
|
+
process.exit(1);
|
|
145
|
+
}
|
|
146
|
+
} catch {
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
console.error("\n\nLogin timed out. Run `npx intentdocs login` to try again.");
|
|
152
|
+
console.error("If the browser page is still open, complete it and re-run the command \u2014 your approval will still work within 10 minutes.\n");
|
|
153
|
+
process.exit(1);
|
|
154
|
+
}
|
|
155
|
+
async function logout() {
|
|
156
|
+
const { existsSync, unlinkSync } = await import("fs");
|
|
157
|
+
const { join } = await import("path");
|
|
158
|
+
const { homedir } = await import("os");
|
|
159
|
+
const authFile = join(homedir(), ".intent", "auth.json");
|
|
160
|
+
if (existsSync(authFile)) {
|
|
161
|
+
unlinkSync(authFile);
|
|
162
|
+
console.log("Logged out.");
|
|
163
|
+
} else {
|
|
164
|
+
console.log("Not logged in.");
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export {
|
|
169
|
+
login,
|
|
170
|
+
logout
|
|
171
|
+
};
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
captureCli,
|
|
3
3
|
shutdownCliAnalytics
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-KPQ42YE6.js";
|
|
5
5
|
import {
|
|
6
6
|
requireConfig
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-K5SNF6CG.js";
|
|
8
8
|
import {
|
|
9
9
|
closePrompt,
|
|
10
10
|
confirm,
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
import {
|
|
14
14
|
authenticatedFetch,
|
|
15
15
|
requireValidAuth
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-XZE2XP6O.js";
|
|
17
17
|
import {
|
|
18
18
|
canonicalApiBase
|
|
19
19
|
} from "./chunk-UYTVTYNB.js";
|
|
@@ -173,7 +173,7 @@ async function listKeys(projectId) {
|
|
|
173
173
|
async function reportStatus(projectId) {
|
|
174
174
|
const keys = (await listKeys(projectId)).filter((k) => !k.revoked_at);
|
|
175
175
|
if (keys.length === 0) {
|
|
176
|
-
console.log("No CI key yet. Run `intentdocs ci` to set up test reporting.");
|
|
176
|
+
console.log("No CI key yet. Run `npx intentdocs ci` to set up test reporting.");
|
|
177
177
|
return;
|
|
178
178
|
}
|
|
179
179
|
const reported = keys.filter((k) => k.last_report_at);
|
|
@@ -198,7 +198,7 @@ async function ci(opts = {}) {
|
|
|
198
198
|
await requireValidAuth();
|
|
199
199
|
const projectId = config.projectId;
|
|
200
200
|
if (!projectId) {
|
|
201
|
-
console.error("This checkout has no project id. Run `intentdocs init` to reconnect.");
|
|
201
|
+
console.error("This checkout has no project id. Run `npx intentdocs init` to reconnect.");
|
|
202
202
|
process.exit(1);
|
|
203
203
|
}
|
|
204
204
|
if (opts.status) {
|
|
@@ -278,7 +278,7 @@ Tell your agent to save each test with its file and full name so CI results can
|
|
|
278
278
|
{ project: projectId }
|
|
279
279
|
);
|
|
280
280
|
console.log(`
|
|
281
|
-
After your next default-branch CI run, check how results matched with: intentdocs ci --status
|
|
281
|
+
After your next default-branch CI run, check how results matched with: npx intentdocs ci --status
|
|
282
282
|
`);
|
|
283
283
|
} finally {
|
|
284
284
|
closePrompt();
|
|
@@ -79,9 +79,56 @@ var CONTEXT_DIR = ".intent/stories";
|
|
|
79
79
|
function storyContextPath(storyId) {
|
|
80
80
|
return join(process.cwd(), CONTEXT_DIR, `${storyId}.md`);
|
|
81
81
|
}
|
|
82
|
+
var HAND_WRITTEN_SECTIONS = {
|
|
83
|
+
"Approach": "_Plan your approach here",
|
|
84
|
+
"Implementation notes": "_Notes added via",
|
|
85
|
+
"Decisions": "_Log decisions via",
|
|
86
|
+
"Relevant files": "_Add file paths here"
|
|
87
|
+
};
|
|
88
|
+
var GENERATED_HEADINGS = /* @__PURE__ */ new Set([
|
|
89
|
+
"User story",
|
|
90
|
+
"Done when",
|
|
91
|
+
"Design references",
|
|
92
|
+
"Spec",
|
|
93
|
+
"Implementation Plan",
|
|
94
|
+
...Object.keys(HAND_WRITTEN_SECTIONS)
|
|
95
|
+
]);
|
|
96
|
+
function readHandWrittenSections(content) {
|
|
97
|
+
const body = content.replace(/\n---\s*\n\s*Mark done:[^\n]*\s*$/, "\n");
|
|
98
|
+
const sections = /* @__PURE__ */ new Map();
|
|
99
|
+
let current = null;
|
|
100
|
+
let buffer = [];
|
|
101
|
+
const flush = () => {
|
|
102
|
+
if (current && current in HAND_WRITTEN_SECTIONS) {
|
|
103
|
+
const placeholder = HAND_WRITTEN_SECTIONS[current];
|
|
104
|
+
const text = buffer.filter((line) => !line.trim().startsWith(placeholder)).join("\n").trim();
|
|
105
|
+
if (text) sections.set(current, text);
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
for (const line of body.split("\n")) {
|
|
109
|
+
const heading = line.match(/^## (.+?)\s*$/);
|
|
110
|
+
if (heading && GENERATED_HEADINGS.has(heading[1])) {
|
|
111
|
+
flush();
|
|
112
|
+
current = heading[1];
|
|
113
|
+
buffer = [];
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
if (current) buffer.push(line);
|
|
117
|
+
}
|
|
118
|
+
flush();
|
|
119
|
+
return sections;
|
|
120
|
+
}
|
|
82
121
|
function writeStoryContext(story) {
|
|
83
122
|
const dir = join(process.cwd(), CONTEXT_DIR);
|
|
84
123
|
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
124
|
+
const path = storyContextPath(story.id);
|
|
125
|
+
const kept = existsSync(path) ? readHandWrittenSections(readFileSync(path, "utf-8")) : /* @__PURE__ */ new Map();
|
|
126
|
+
const section = (heading, placeholder) => [
|
|
127
|
+
`## ${heading}`,
|
|
128
|
+
``,
|
|
129
|
+
kept.get(heading) ?? placeholder,
|
|
130
|
+
``
|
|
131
|
+
];
|
|
85
132
|
const acLines = story.acceptance_criteria.length ? story.acceptance_criteria.flatMap((ac) => renderCriterionLines(ac)).join("\n") : "_No acceptance criteria defined._";
|
|
86
133
|
const specSection = story.notes?.trim() ? [`## Spec`, ``, story.notes.trim(), ``] : [];
|
|
87
134
|
const designRefs = story.design_refs ?? [];
|
|
@@ -96,13 +143,10 @@ function writeStoryContext(story) {
|
|
|
96
143
|
plan.markdown,
|
|
97
144
|
``,
|
|
98
145
|
...plan.files_to_create?.length ? [`### Files to create`, ``, ...plan.files_to_create.map((f) => `- \`${f}\``), ``] : [],
|
|
99
|
-
...plan.files_to_modify?.length ? [`### Files to modify`, ``, ...plan.files_to_modify.map((f) => `- \`${f}\``), ``] : []
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
`_Plan your approach here before writing code._`,
|
|
104
|
-
``
|
|
105
|
-
];
|
|
146
|
+
...plan.files_to_modify?.length ? [`### Files to modify`, ``, ...plan.files_to_modify.map((f) => `- \`${f}\``), ``] : [],
|
|
147
|
+
// An approach written before the plan arrived is still the developer's.
|
|
148
|
+
...kept.has("Approach") ? section("Approach", "") : []
|
|
149
|
+
] : section("Approach", `_Plan your approach here before writing code._`);
|
|
106
150
|
const md = [
|
|
107
151
|
`# ${story.title}`,
|
|
108
152
|
``,
|
|
@@ -122,23 +166,13 @@ function writeStoryContext(story) {
|
|
|
122
166
|
...designRefsSection,
|
|
123
167
|
...specSection,
|
|
124
168
|
...approachSection,
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
`
|
|
128
|
-
``,
|
|
129
|
-
`## Decisions`,
|
|
130
|
-
``,
|
|
131
|
-
`_Log decisions via \`intentdocs decide "..." -s ${storyRef(story)}\`_`,
|
|
132
|
-
``,
|
|
133
|
-
`## Relevant files`,
|
|
134
|
-
``,
|
|
135
|
-
`_Add file paths here as you explore the codebase._`,
|
|
136
|
-
``,
|
|
169
|
+
...section("Implementation notes", `_Notes added via \`npx intentdocs note ${storyRef(story)} "..."\`_`),
|
|
170
|
+
...section("Decisions", `_Log decisions via \`npx intentdocs decide "..." -s ${storyRef(story)}\`_`),
|
|
171
|
+
...section("Relevant files", `_Add file paths here as you explore the codebase._`),
|
|
137
172
|
`---`,
|
|
138
173
|
``,
|
|
139
|
-
`Mark done: \`intentdocs done ${storyRef(story)}\``
|
|
174
|
+
`Mark done: \`npx intentdocs done ${storyRef(story)}\``
|
|
140
175
|
].join("\n");
|
|
141
|
-
const path = storyContextPath(story.id);
|
|
142
176
|
writeFileSync(path, md);
|
|
143
177
|
return path;
|
|
144
178
|
}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getContext
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-KTGQO3AE.js";
|
|
4
4
|
import {
|
|
5
|
+
checkoutConfig,
|
|
6
|
+
hasConfig,
|
|
5
7
|
writeConfig
|
|
6
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-K5SNF6CG.js";
|
|
7
9
|
import {
|
|
8
10
|
ask,
|
|
9
11
|
closePrompt,
|
|
@@ -12,7 +14,7 @@ import {
|
|
|
12
14
|
import {
|
|
13
15
|
authenticatedFetch,
|
|
14
16
|
requireValidAuth
|
|
15
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-XZE2XP6O.js";
|
|
16
18
|
import {
|
|
17
19
|
API_BASE
|
|
18
20
|
} from "./chunk-UYTVTYNB.js";
|
|
@@ -20,8 +22,36 @@ import {
|
|
|
20
22
|
// src/commands/scope.ts
|
|
21
23
|
import { writeFileSync, existsSync } from "fs";
|
|
22
24
|
import { join } from "path";
|
|
25
|
+
async function connectCheckout(apiBase, projectId) {
|
|
26
|
+
if (hasConfig()) {
|
|
27
|
+
console.log(" This checkout is already connected (.intent/config.json) \u2014 left as is.");
|
|
28
|
+
console.log(" Run `npx intentdocs sync` to refresh it, or remove .intent/config.json and run `npx intentdocs init` to connect it to this project.\n");
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
const mapsRes = await authenticatedFetch(`/api/cli/projects/${projectId}/maps`);
|
|
32
|
+
if (!mapsRes.ok) {
|
|
33
|
+
console.log(" \u26A0 Could not fetch the project's story map \u2014 run `npx intentdocs init` to connect.\n");
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
const { maps, appUrl } = await mapsRes.json();
|
|
37
|
+
const map = maps[0];
|
|
38
|
+
if (!map) {
|
|
39
|
+
console.log(" \u26A0 The project has no story map yet \u2014 run `npx intentdocs init` once it has one.\n");
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
let workspace = null;
|
|
43
|
+
const projectsRes = await authenticatedFetch("/api/cli/projects");
|
|
44
|
+
if (projectsRes.ok) {
|
|
45
|
+
const { projects } = await projectsRes.json();
|
|
46
|
+
workspace = projects.find((p) => p.id === projectId)?.workspace ?? null;
|
|
47
|
+
}
|
|
48
|
+
const config = checkoutConfig({ apiBase, project: { id: projectId, workspace }, map, appUrl });
|
|
49
|
+
writeConfig(config);
|
|
50
|
+
console.log(" \u2713 Connected\n");
|
|
51
|
+
return config;
|
|
52
|
+
}
|
|
23
53
|
async function scope(projectId) {
|
|
24
|
-
await requireValidAuth();
|
|
54
|
+
const auth = await requireValidAuth();
|
|
25
55
|
if (!projectId) {
|
|
26
56
|
projectId = await ask(" Project ID (from `intentdocs start`): ");
|
|
27
57
|
}
|
|
@@ -112,18 +142,8 @@ async function scope(projectId) {
|
|
|
112
142
|
console.log(" \u2713 Blueprint generated (couldn't parse summary)\n");
|
|
113
143
|
}
|
|
114
144
|
console.log("\n Connecting project to your codebase...");
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
);
|
|
118
|
-
let mapId = null;
|
|
119
|
-
if (mapsRes.ok) {
|
|
120
|
-
const mapData = await mapsRes.json();
|
|
121
|
-
if (mapData.mapId) mapId = mapData.mapId;
|
|
122
|
-
}
|
|
123
|
-
if (mapId) {
|
|
124
|
-
const config = { apiBase: API_BASE, projectId, mapId };
|
|
125
|
-
writeConfig(config);
|
|
126
|
-
console.log(" \u2713 Connected\n");
|
|
145
|
+
const config = await connectCheckout(auth.apiBase, projectId);
|
|
146
|
+
if (config) {
|
|
127
147
|
try {
|
|
128
148
|
const md = await getContext(config);
|
|
129
149
|
writeFileSync(join(process.cwd(), "INTENT.md"), md);
|
|
@@ -176,7 +196,7 @@ async function scope(projectId) {
|
|
|
176
196
|
" Configure your AI tool (Claude Code / Cursor) with intentdocs agent workflows?"
|
|
177
197
|
);
|
|
178
198
|
if (wantSetup) {
|
|
179
|
-
const { setup } = await import("./setup-
|
|
199
|
+
const { setup } = await import("./setup-UILQVYIB.js");
|
|
180
200
|
await setup();
|
|
181
201
|
return;
|
|
182
202
|
}
|
|
@@ -184,10 +204,10 @@ async function scope(projectId) {
|
|
|
184
204
|
\u2705 Your project is scoped and ready to build!
|
|
185
205
|
|
|
186
206
|
Next steps:
|
|
187
|
-
\u2022
|
|
188
|
-
\u2022
|
|
189
|
-
\u2022
|
|
190
|
-
\u2022
|
|
207
|
+
\u2022 npx intentdocs setup \u2014 configure your AI tool
|
|
208
|
+
\u2022 npx intentdocs status \u2014 see your story map progress
|
|
209
|
+
\u2022 npx intentdocs next \u2014 see what to build first
|
|
210
|
+
\u2022 npx intentdocs done <id> \u2014 mark stories as you complete them
|
|
191
211
|
|
|
192
212
|
Your story map is also live at ${API_BASE}
|
|
193
213
|
Seek advice from the community and our resources.
|
|
@@ -226,5 +246,6 @@ ${projectId}
|
|
|
226
246
|
}
|
|
227
247
|
|
|
228
248
|
export {
|
|
249
|
+
connectCheckout,
|
|
229
250
|
scope
|
|
230
251
|
};
|