carrick 0.3.61 → 0.3.63

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.
@@ -1 +1 @@
1
- {"version":3,"file":"repos.js","sourceRoot":"","sources":["../../src/init/repos.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"repos.js","sourceRoot":"","sources":["../../src/init/repos.ts"],"names":[],"mappings":"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"}
@@ -1,13 +1,44 @@
1
+ import { type ResolvedRepos } from "../auth/read.ts";
2
+ /**
3
+ * The prompt that makes an agent write this repo's config and setup files.
4
+ *
5
+ * A copy of the `scaffold` MCP tool's own instructions and the dashboard copy
6
+ * beside them (carrick-cloud#800), whose test checks every filename against
7
+ * what the tool returns. It is printed here so the terminal path ends where
8
+ * the dashboard path ends, and it states the sequence the ruling in
9
+ * carrick-cloud#799 fixed: the agent writes a complete `carrick.json` from the
10
+ * proposal this command derived, `carrick index` proves it for nothing, and
11
+ * only then does the one paid scan run. Keep the two copies in step; the
12
+ * tool's instructions, not this text, decide what gets written.
13
+ *
14
+ * One clause is this side's alone, because only this side knows it: whether
15
+ * the workspace read found a hosted index for these repos. Where there is one,
16
+ * the paid scan has already run in CI and a laptop scan from a branch would
17
+ * replace that row for everyone in the workspace, so the agent is told not to
18
+ * run it (carrick#993, cloud half carrick-cloud#805).
19
+ */
20
+ export declare function agentScaffoldPrompt(hosted: boolean): string;
1
21
  export type InitOptions = {
2
22
  workspace: string;
3
23
  /** Require every proposed GitHub repo to belong to this project. */
4
24
  project: string | null;
25
+ /** The `owner/repo` to use when the origin remote names none (carrick#991). */
26
+ repo: string | null;
5
27
  /** Answer yes to the repo list rather than asking. */
6
28
  assumeYes: boolean;
7
- /** Write the files, print the lines, and do not build the index. */
8
- skipIndex: boolean;
9
29
  };
10
30
  export declare function parseArgs(argv: string[], cwd?: string): InitOptions | string;
31
+ /**
32
+ * The repos a project holds that this folder does not, one line per project.
33
+ *
34
+ * Carrick answers across every repo in a project, so a machine holding half of
35
+ * one gets half the answers, and the connection lines above name only what is
36
+ * here. `project_repos` is the workspace read's answer to that: the whole
37
+ * membership of every project the requested repos are in (carrick#993 row 18).
38
+ * Capped and counted like the identity lines, because a project can hold two
39
+ * hundred.
40
+ */
41
+ export declare function absentRepos(identity: ResolvedRepos, names: string[], project: string | null): string[];
11
42
  /**
12
43
  * The editor lines, one line per editor that is on the machine.
13
44
  *
package/dist/init/run.js CHANGED
@@ -6,35 +6,58 @@ import { spawnSync } from "node:child_process";
6
6
  import { readCredential } from "../auth/credentials.js";
7
7
  import { signIn } from "../auth/run.js";
8
8
  import { resolveRepos } from "../auth/read.js";
9
- import { deriveWorkspace, writeConfigs, githubRemote } from "./repos.js";
10
- import { connectRepos, reposAreInProject } from "./connect.js";
11
- import { listProjects, createProject, projectLines } from "./projects.js";
9
+ import { deriveWorkspace, writeProposal, PROPOSAL_FILE, repoIdentity } from "./repos.js";
10
+ import { connectRepos, reposAreInProject, projectAssignments } from "./connect.js";
11
+ import { ensureProject, projectStep, SLUG } from "./projects.js";
12
12
  import { connectMcpClients, mcpLines } from "./mcp.js";
13
13
  import { hookCommand, mergeCarrickHooks } from "./settings.js";
14
14
  import { renderTemplate } from "../templates.js";
15
- import { resolveNativeBinary, nativeEnv, packageRoot } from "../native.js";
15
+ import { packageRoot } from "../native.js";
16
16
  const EXTENSION_ID = "carrick-tools.carrick";
17
17
  /**
18
- * The prompt that makes an agent write this repo's setup files.
18
+ * The prompt that makes an agent write this repo's config and setup files.
19
19
  *
20
- * A copy, and deliberately a verbatim one: the source of truth is
21
- * `AGENT_SCAFFOLD_PROMPT` in the dashboard (carrick-cloud
22
- * `app/src/lib/onboarding.ts`), whose own test checks every filename in it
23
- * against what the `scaffold` MCP tool actually returns. It is printed here so
24
- * the terminal path ends where the dashboard path ends — with the one prompt
25
- * that turns a signed-in workspace into a repo that scans itself in CI
26
- * (carrick#955). Keep the two in step; the tool's instructions, not this text,
27
- * decide what gets written.
20
+ * A copy of the `scaffold` MCP tool's own instructions and the dashboard copy
21
+ * beside them (carrick-cloud#800), whose test checks every filename against
22
+ * what the tool returns. It is printed here so the terminal path ends where
23
+ * the dashboard path ends, and it states the sequence the ruling in
24
+ * carrick-cloud#799 fixed: the agent writes a complete `carrick.json` from the
25
+ * proposal this command derived, `carrick index` proves it for nothing, and
26
+ * only then does the one paid scan run. Keep the two copies in step; the
27
+ * tool's instructions, not this text, decide what gets written.
28
+ *
29
+ * One clause is this side's alone, because only this side knows it: whether
30
+ * the workspace read found a hosted index for these repos. Where there is one,
31
+ * the paid scan has already run in CI and a laptop scan from a branch would
32
+ * replace that row for everyone in the workspace, so the agent is told not to
33
+ * run it (carrick#993, cloud half carrick-cloud#805).
28
34
  */
29
- const AGENT_SCAFFOLD_PROMPT = "Run the carrick scaffold tool, passing this repo's owner/repo from " +
30
- "`git remote get-url origin` as `repo`, and follow the instructions it " +
31
- "returns: create each file at its path, populate carrick.json by scanning " +
32
- "this repo for its service(s) and the env vars / domains they call (use a " +
33
- "nested services config if it's a monorepo), and add the Carrick section " +
34
- "to AGENTS.md if this repo already has one. Answer the closing checklist " +
35
- "before you open the PR.";
35
+ export function agentScaffoldPrompt(hosted) {
36
+ return ("Run the carrick scaffold tool, passing this repo's owner/repo from " +
37
+ "`git remote get-url origin` as `repo`, and follow the instructions it " +
38
+ "returns: create each file at its path, and write carrick.json from the " +
39
+ "proposal in .carrick/proposal.json, taking applications as services and " +
40
+ "library workspace members as shared includes of the services that import " +
41
+ "them, with the env vars and domains each service calls. Add the Carrick " +
42
+ "section to AGENTS.md if this repo already has one. Then run `carrick " +
43
+ "index`, which is free and runs no model, and fix whatever it reports as " +
44
+ "unclassified or in no service. " +
45
+ (hosted
46
+ ? "Do not run `carrick index --infer`: this repo already has a hosted " +
47
+ "index, and a laptop scan from a branch replaces the CI row for " +
48
+ "everyone. "
49
+ : // carrick#960/#1003: an agent's shell caps a command well below the
50
+ // fifteen minutes a first paid scan takes, so the scan is detached and
51
+ // the agent asks `carrick status` how it went. Mirrors the scaffold
52
+ // tool's own wording (carrick-cloud#821).
53
+ "Then run `carrick index --infer --detach` once for the scan that " +
54
+ "builds the index, checking `carrick status` about once a minute " +
55
+ "until it says the scan finished, stopped or failed. ") +
56
+ "Answer the closing checklist before you open the PR.");
57
+ }
58
+ const OWNER_REPO = /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/;
36
59
  export function parseArgs(argv, cwd = process.cwd()) {
37
- const options = { workspace: cwd, project: null, assumeYes: false, skipIndex: false };
60
+ const options = { workspace: cwd, project: null, repo: null, assumeYes: false };
38
61
  for (let index = 0; index < argv.length; index += 1) {
39
62
  const argument = argv[index];
40
63
  switch (argument) {
@@ -42,20 +65,27 @@ export function parseArgs(argv, cwd = process.cwd()) {
42
65
  case "-y":
43
66
  options.assumeYes = true;
44
67
  break;
45
- case "--skip-index":
46
- options.skipIndex = true;
47
- break;
48
68
  case "--project": {
49
69
  const value = argv[index + 1];
50
70
  if (!value)
51
71
  return "--project needs a slug";
52
- if (!/^[a-z0-9](?:[a-z0-9]|-(?=[a-z0-9])){2,31}$/.test(value)) {
72
+ if (!SLUG.test(value)) {
53
73
  return `invalid project slug "${value}": use 3-32 lowercase letters, digits, and single hyphens`;
54
74
  }
55
75
  options.project = value;
56
76
  index += 1;
57
77
  break;
58
78
  }
79
+ case "--repo": {
80
+ const value = argv[index + 1];
81
+ if (!value)
82
+ return "--repo needs an owner/repo";
83
+ if (!OWNER_REPO.test(value))
84
+ return `invalid repo "${value}": use owner/repo as GitHub spells it`;
85
+ options.repo = value;
86
+ index += 1;
87
+ break;
88
+ }
59
89
  case "--workspace":
60
90
  case "-w": {
61
91
  const value = argv[index + 1];
@@ -78,19 +108,21 @@ export function parseArgs(argv, cwd = process.cwd()) {
78
108
  }
79
109
  function help() {
80
110
  return [
81
- "carrick init [DIRECTORY] [--project SLUG]",
111
+ "carrick init [DIRECTORY] [--project SLUG] [--repo OWNER/REPO]",
82
112
  "",
83
- "Sign in (here, or beforehand with carrick login), then configure services,",
84
- "hooks, the MCP connection and the first index in a repository or a folder",
85
- "of repos.",
113
+ "Sign in (here, or beforehand with carrick login), then set up a repository",
114
+ "or a folder of repos: the project, the repo connection, the agent hooks,",
115
+ "the MCP connection, and the service proposal your agent turns into",
116
+ "carrick.json. It writes nothing into the repository but the ignored",
117
+ ".carrick directory and the hook settings, and it runs no scan.",
86
118
  "With --project, a project missing from the workspace is offered for",
87
- "creation here; the browser assigns the repos and the CLI waits for Carrick",
88
- "to verify the assignment.",
119
+ "creation here, and the repos are put in it from the terminal once the",
120
+ "GitHub App grant connects them.",
89
121
  "",
90
122
  " -w, --workspace DIR The folder holding the repos (default: this one)",
91
123
  " --project SLUG Require these repos in this Carrick project",
124
+ " --repo OWNER/REPO Name the GitHub repo whose origin remote names none",
92
125
  " -y, --yes Take the repo list as proposed",
93
- " --skip-index Write the files and print the lines, index later",
94
126
  ].join("\n");
95
127
  }
96
128
  function say(line = "") {
@@ -106,6 +138,16 @@ async function confirm(question) {
106
138
  rl.close();
107
139
  }
108
140
  }
141
+ /** A typed answer, for the questions whose answer is not yes or no. */
142
+ async function ask(question) {
143
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
144
+ try {
145
+ return (await rl.question(`${question}\n> `)).trim();
146
+ }
147
+ finally {
148
+ rl.close();
149
+ }
150
+ }
109
151
  function writeIfChanged(target, body) {
110
152
  const existing = fs.existsSync(target) ? fs.readFileSync(target, "utf8") : null;
111
153
  if (existing === body)
@@ -121,6 +163,35 @@ function onPath(command) {
121
163
  });
122
164
  return probe.status === 0;
123
165
  }
166
+ /**
167
+ * The repos a project holds that this folder does not, one line per project.
168
+ *
169
+ * Carrick answers across every repo in a project, so a machine holding half of
170
+ * one gets half the answers, and the connection lines above name only what is
171
+ * here. `project_repos` is the workspace read's answer to that: the whole
172
+ * membership of every project the requested repos are in (carrick#993 row 18).
173
+ * Capped and counted like the identity lines, because a project can hold two
174
+ * hundred.
175
+ */
176
+ export function absentRepos(identity, names, project) {
177
+ const onDisk = new Set(names.map((name) => name.toLowerCase()));
178
+ const sole = identity.project_repos.length === 1;
179
+ const lines = [];
180
+ for (const entry of identity.project_repos) {
181
+ // With a project settled, the others are somebody else's business.
182
+ if (project !== null && entry.project_slug !== project)
183
+ continue;
184
+ const absent = entry.repos.filter((repo) => !onDisk.has(repo.toLowerCase()));
185
+ if (absent.length === 0)
186
+ continue;
187
+ const shown = absent.length > 10
188
+ ? `${absent.slice(0, 10).join(", ")} and ${absent.length - 10} more`
189
+ : absent.join(", ");
190
+ const where = sole || entry.project_slug === project ? "this project" : `project "${entry.project_slug}"`;
191
+ lines.push(`Also in ${where}, not on this machine: ${shown}.`);
192
+ }
193
+ return lines;
194
+ }
124
195
  /**
125
196
  * The editor lines, one line per editor that is on the machine.
126
197
  *
@@ -151,40 +222,6 @@ export function editorLines(onPath) {
151
222
  }
152
223
  return lines;
153
224
  }
154
- /**
155
- * Make sure the named project exists, from the terminal where that is possible.
156
- *
157
- * Returns whether this run can state that the project exists. `false` is the
158
- * honest answer for every case it could not settle — an API without the
159
- * actions, a declined offer, a refused create — and the caller then prints
160
- * today's browser instructions, which include creating it.
161
- */
162
- async function ensureProject(token, slug, options) {
163
- const { say } = options;
164
- const projects = await listProjects(token);
165
- if (projects === null)
166
- return false;
167
- if (projects.some((project) => project.slug === slug && !project.archived)) {
168
- say(`Project "${slug}" is in this workspace.`);
169
- return true;
170
- }
171
- say(projects.length === 0
172
- ? "This workspace has no projects yet."
173
- : "Projects in this workspace:");
174
- for (const line of projectLines(projects))
175
- say(line);
176
- const create = options.assumeYes || (options.interactive && (await confirm(`Create project "${slug}"?`)));
177
- if (!create)
178
- return false;
179
- const outcome = await createProject(token, slug);
180
- if (outcome.kind === "created") {
181
- say(`Created project "${slug}".`);
182
- return true;
183
- }
184
- if (outcome.kind === "refused")
185
- say(`Carrick did not create "${slug}": ${outcome.message}`);
186
- return false;
187
- }
188
225
  export async function init(argv) {
189
226
  const parsed = parseArgs(argv);
190
227
  if (typeof parsed === "string") {
@@ -198,7 +235,12 @@ export async function init(argv) {
198
235
  }
199
236
  const interactive = process.stdin.isTTY === true;
200
237
  // Authentication and all derivation validation precede local writes.
201
- let plan;
238
+ let derived;
239
+ // What the workspace read said about these repos, for the closing lines
240
+ // printed long after it: a repo Carrick already holds an index for must not
241
+ // be told to run the paid scan again (carrick#993).
242
+ let requested = [];
243
+ const hostedIndex = [];
202
244
  try {
203
245
  // A machine that has never signed in signs in here rather than being told
204
246
  // to run another command: `carrick login` is the same browser round trip,
@@ -212,12 +254,46 @@ export async function init(argv) {
212
254
  say("This machine is not signed in to Carrick.");
213
255
  credential = await signIn(say);
214
256
  }
215
- plan = deriveWorkspace(workspace);
216
- const repoIdentities = plan.repos.map((repo) => ({ path: repo.path, name: githubRemote(repo.path) }));
257
+ derived = deriveWorkspace(workspace);
258
+ const derivedIdentities = derived.plan.repos.map((repo) => repoIdentity(repo.path));
259
+ // `--repo` names what a remote could not: an ssh alias ssh itself cannot
260
+ // resolve, a mirror, a clone with no origin. It names one repository, so
261
+ // it is taken only when exactly one repo here is missing an identity.
262
+ const unnamed = derivedIdentities.filter((repo) => repo.name === null);
263
+ let taken = null;
264
+ if (parsed.repo !== null) {
265
+ if (unnamed.length > 1) {
266
+ throw new Error(`--repo names one repository, but ${unnamed.length} repos here have no GitHub identity: ${unnamed.map((repo) => repo.path).join(", ")}. Run carrick init --repo in each of them, or fix their origin remotes.`);
267
+ }
268
+ if (unnamed.length === 0) {
269
+ say(`--repo ${parsed.repo} was not needed: every repo here names its own GitHub repository.`);
270
+ }
271
+ else {
272
+ taken = unnamed[0].path;
273
+ say(`Taking ${parsed.repo} as the GitHub repository for ${taken}.`);
274
+ }
275
+ }
276
+ const repoIdentities = derivedIdentities.map((repo) => repo.path === taken ? { ...repo, name: parsed.repo, problem: null } : repo);
217
277
  const names = [...new Set(repoIdentities.map((repo) => repo.name).filter((name) => name !== null))];
218
278
  if (names.length > 200)
219
279
  throw new Error("This workspace has more than 200 GitHub repos. Initialise smaller workspace groups.");
220
280
  const missingIdentities = repoIdentities.filter((repo) => repo.name === null);
281
+ // Said before anything is requested, and said whether or not --project was
282
+ // given: a repo with no identity is left out of the project step, the
283
+ // connection check and the workspace read, and a run that dropped it in
284
+ // silence read as a complete one (carrick#991).
285
+ // A folder of clones can hold dozens, so the list is capped and the rest
286
+ // is counted rather than dropped.
287
+ for (const repo of missingIdentities.slice(0, 10)) {
288
+ say(`${repo.path} contributes no GitHub identity: ${repo.problem}.`);
289
+ }
290
+ if (missingIdentities.length > 10) {
291
+ say(`${missingIdentities.length - 10} more repos here name no GitHub identity either.`);
292
+ }
293
+ if (missingIdentities.length > 0) {
294
+ const one = missingIdentities.length === 1;
295
+ say(` Carrick has nothing to connect ${one ? "it" : "them"} to. Run carrick init --repo owner/repo${one ? "" : " in each of them"}, or give the alias a HostName github.com line in your ssh config.`);
296
+ }
221
297
  if (parsed.project && missingIdentities.length > 0) {
222
298
  throw new Error(`--project ${parsed.project} cannot verify ${missingIdentities.map((repo) => repo.path).join(", ")} because ${missingIdentities.length === 1 ? "it has" : "they have"} no GitHub origin. No project assignment was verified.`);
223
299
  }
@@ -229,25 +305,43 @@ export async function init(argv) {
229
305
  for (const name of names)
230
306
  say(` ${name}`);
231
307
  }
308
+ else if (names.length === 0) {
309
+ // The sentence that stops the rest of this run from reading as a
310
+ // complete one: no project is chosen, no connection is checked, and a
311
+ // later upload has no repo identity to resolve a project from.
312
+ say("No repo here names a GitHub repository, so this run chooses no project and checks no connection.");
313
+ }
314
+ requested = names;
232
315
  const initial = await resolveRepos(credential.token, names);
233
316
  // The project half of the browser round trip, where this API can do it
234
- // from here. Assignment still belongs to the browser, so this only ever
235
- // removes the "create the project" step from the wait.
236
- const projectExists = parsed.project && !reposAreInProject(initial, names, parsed.project)
237
- ? await ensureProject(credential.token, parsed.project, {
238
- say,
239
- interactive,
240
- assumeYes: parsed.assumeYes,
241
- })
242
- : false;
317
+ // from here: the project is created here, and `connectRepos` puts the
318
+ // repos in it as the grant connects them (carrick#999), so the wait is on
319
+ // the GitHub App grant and nothing else. Without --project the step reads
320
+ // the assignment the repos already have and offers the list, rather than
321
+ // doing nothing at all (carrick#987).
322
+ const prompts = { say, ask, confirm, interactive, assumeYes: parsed.assumeYes };
323
+ let project = parsed.project;
324
+ let projectExists = false;
325
+ if (project === null) {
326
+ const chosen = await projectStep(credential.token, projectAssignments(initial, names), prompts);
327
+ project = chosen.slug;
328
+ projectExists = chosen.exists;
329
+ }
330
+ else if (!reposAreInProject(initial, names, project)) {
331
+ projectExists = await ensureProject(credential.token, project, prompts);
332
+ }
243
333
  const identity = await connectRepos(credential.token, names, initial, {
244
334
  interactive,
245
- project: parsed.project ?? undefined,
335
+ project: project ?? undefined,
246
336
  projectExists,
247
337
  say,
248
338
  });
249
- if (parsed.project && !reposAreInProject(identity, names, parsed.project)) {
250
- throw new Error(`Project "${parsed.project}" was not verified for every requested repo. Complete the browser steps and run carrick init --project ${parsed.project} again.`);
339
+ if (project !== null && !reposAreInProject(identity, names, project)) {
340
+ // An unverified project does not end the run, whether it was named on
341
+ // the command line or picked here. Stopping cost someone their hooks and
342
+ // their proposal for a browser step they could only take afterwards, and
343
+ // the documented command then needed two runs (carrick#993 row 8).
344
+ say(`Setup continues; finish the browser steps above to put these repos in "${project}", then run carrick init --project ${project} again to verify.`);
251
345
  }
252
346
  say(`Carrick workspace: ${identity.workspace.slug}`);
253
347
  if (identity.allowance_sentence)
@@ -255,18 +349,25 @@ export async function init(argv) {
255
349
  for (const repo of identity.repos) {
256
350
  if (!repo.connected)
257
351
  say(`${repo.full_name} is not connected to this Carrick workspace.`);
258
- else if (repo.services.length === 0) {
352
+ // How to give it one is the last thing this command prints, once, rather
353
+ // than a workflow line per repo before anything is set up.
354
+ else if (repo.services.length === 0)
259
355
  say(`${repo.full_name} is connected and has no hosted index yet.`);
260
- say(" Add the workflow in that repo:");
261
- say(" mkdir -p .github/workflows");
262
- say(" carrick templates workflow > .github/workflows/carrick.yml");
263
- }
356
+ else
357
+ hostedIndex.push(repo.full_name);
264
358
  }
359
+ // The rest of the project, which this machine does not hold. Carrick
360
+ // answers across every repo in a project, so a folder holding half of one
361
+ // is a partial index and nothing here would otherwise say so
362
+ // (carrick#993 row 18).
363
+ for (const line of absentRepos(identity, names, project))
364
+ say(line);
265
365
  }
266
366
  catch (error) {
267
367
  process.stderr.write(`carrick init: ${error.message}\n`);
268
368
  return 1;
269
369
  }
370
+ const plan = derived.plan;
270
371
  say(`Repos to index, in ${plan.workspace} (${plan.repos_detected_by}):`);
271
372
  if (plan.parent_proposal) {
272
373
  const parent = plan.parent_proposal;
@@ -292,20 +393,20 @@ export async function init(argv) {
292
393
  process.stderr.write("carrick init: use --yes to accept this proposal without a terminal.\n");
293
394
  return 1;
294
395
  }
295
- if (!await confirm("Create missing configs and configure hooks?"))
396
+ if (!await confirm("Write this proposal and configure hooks?"))
296
397
  return 0;
297
398
  }
298
399
  try {
299
- for (const result of writeConfigs(plan))
300
- say(`${result.created ? "wrote" : "unchanged"} ${result.path}`);
301
- // Revalidate any file that appeared between preview and exclusive create.
302
- deriveWorkspace(workspace);
400
+ // The proposal is a seed for an agent, not a config: nothing derived
401
+ // without a model is written into the repository, because the first scan
402
+ // is the paid one and it has to run against a config someone has read
403
+ // (carrick-cloud#799).
404
+ say(`wrote ${writeProposal(plan.workspace, derived)}`);
303
405
  }
304
406
  catch (error) {
305
407
  process.stderr.write(`carrick init: ${error.message}\n`);
306
408
  return 1;
307
409
  }
308
- say("Review carrick.json service boundaries and shared includes before committing it.");
309
410
  // 3. The agent hooks. Merged by command: this file may already hold a user's
310
411
  // own hooks, or the hook pack the hosted index installs.
311
412
  const command = hookCommand({ onPath });
@@ -332,35 +433,7 @@ export async function init(argv) {
332
433
  catch (error) {
333
434
  say(`Could not configure Carrick hooks: ${error.message}. Fix the settings files and run carrick init again.`);
334
435
  }
335
- // 4. The index itself.
336
- if (parsed.skipIndex) {
337
- say();
338
- say("Skipped the index. Build it with: carrick index");
339
- }
340
- else {
341
- say();
342
- const binary = resolveNativeBinary();
343
- if (!binary.binary) {
344
- process.stderr.write(`carrick init: ${binary.problem}\n`);
345
- return 1;
346
- }
347
- // `--infer` is what makes the first run produce an index worth reading.
348
- // A local scan states the facts it can derive and leaves everything only
349
- // the model can classify unclassified; this run asks Carrick Cloud for
350
- // those, uploads the result, and writes the same payload into `.carrick`
351
- // from the same run — so there is no scan, then wait, then download
352
- // (carrick#956 §8.3). Every later `carrick index`, and every hook-driven
353
- // `carrick refresh`, is the free local one.
354
- const scan = spawnSync(binary.binary, ["index", "--workspace", workspace, "--infer"], {
355
- stdio: "inherit",
356
- env: nativeEnv(),
357
- });
358
- if (scan.status !== 0) {
359
- process.stderr.write(`carrick init: the first index did not finish. The files above are written, so fix what it reported and run: carrick index --infer\n`);
360
- return scan.status ?? 1;
361
- }
362
- }
363
- // 5. The MCP connection, for work that crosses repos this machine does not
436
+ // 4. The MCP connection, for work that crosses repos this machine does not
364
437
  // hold. Configured here for every client this machine has, rather than
365
438
  // printed for one of them (carrick#955).
366
439
  say();
@@ -369,19 +442,6 @@ export async function init(argv) {
369
442
  for (const line of mcpLines(connectMcpClients()))
370
443
  say(line);
371
444
  say();
372
- say(" The CI check, once per repo (it needs no secret). Paste this to your agent:");
373
- say();
374
- say(` ${AGENT_SCAFFOLD_PROMPT}`);
375
- say();
376
- say(" Or write the workflow yourself:");
377
- say(" mkdir -p .github/workflows");
378
- say(" carrick templates workflow > .github/workflows/carrick.yml");
379
- say();
380
- say(" The first scan on the repo's default branch writes the hosted index. A session");
381
- say(" started in this folder afterwards picks it up on its own; by hand it is:");
382
- say(" carrick refresh");
383
- say(" carrick status");
384
- say();
385
445
  for (const line of editorLines(onPath))
386
446
  say(line);
387
447
  say();
@@ -393,8 +453,40 @@ export async function init(argv) {
393
453
  say(" That plugin's language server is started as `carrick`, which this machine cannot resolve;");
394
454
  say(" install it globally first, or the hooks above are the channel.");
395
455
  }
456
+ say("Once the index exists, editing a file with a route or a call in it is what");
457
+ say("Carrick answers on; `carrick status` says what the index holds.");
458
+ say();
459
+ // No scan ran here, and that is the point (carrick-cloud#799): the one paid
460
+ // scan runs against a config someone has read, so the last thing this
461
+ // command prints is the prompt that produces that config.
462
+ //
463
+ // Unless CI has already built one. The hosted index is the whole workspace's
464
+ // row, and `--infer` from a laptop on a branch replaces it for everyone who
465
+ // queries it, so where the workspace read found services this says so and
466
+ // names the free command instead (carrick#993 row 2).
467
+ if (hostedIndex.length > 0) {
468
+ const subject = hostedIndex.length === requested.length && requested.length === 1
469
+ ? "This repo"
470
+ : hostedIndex.length > 3
471
+ ? `${hostedIndex.slice(0, 3).join(", ")} and ${hostedIndex.length - 3} more`
472
+ : hostedIndex.join(", ");
473
+ say(` ${subject} already ${hostedIndex.length === 1 ? "has" : "have"} a hosted index. Run \`carrick index\` (free); do not run`);
474
+ say(" `carrick index --infer`, a laptop scan from a branch replaces the CI row for");
475
+ say(` everyone. ${PROPOSAL_FILE} holds the services this run derived, to compare`);
476
+ say(" with the carrick.json already committed.");
477
+ }
478
+ else {
479
+ say(` There is no index yet. ${PROPOSAL_FILE} holds the services this run derived;`);
480
+ say(" an agent turns it into carrick.json, adds the CI check (which needs no secret),");
481
+ say(" and builds the index: `carrick index` is free and runs no model, and");
482
+ say(" `carrick index --infer` is the single scan that asks Carrick to classify the rest.");
483
+ say(" By hand instead: `carrick templates workflow > .github/workflows/carrick.yml`, a");
484
+ say(" carrick.json per https://docs.carrick.tools/carrick-json, then those two commands.");
485
+ }
486
+ say();
487
+ say(" Paste this to your agent:");
396
488
  say();
397
- say("Then: edit a file with a route or a call in it, and Carrick answers on the edit.");
489
+ say(` ${agentScaffoldPrompt(hostedIndex.length > 0)}`);
398
490
  return 0;
399
491
  }
400
492
  /** `carrick templates <name>`, so the workflow above is one command. */