@catalyst-cloud/cli 0.8.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.
Files changed (157) hide show
  1. package/CHANGELOG.md +75 -0
  2. package/LICENSE +21 -0
  3. package/README.md +205 -0
  4. package/bin/catalyst-skills.js +8 -0
  5. package/bin/catalyst.js +5 -0
  6. package/bin/launch.js +154 -0
  7. package/dist/args.js +280 -0
  8. package/dist/ask.js +161 -0
  9. package/dist/browser.js +20 -0
  10. package/dist/cli.js +397 -0
  11. package/dist/config.js +241 -0
  12. package/dist/contract-types.js +4 -0
  13. package/dist/contract.js +184 -0
  14. package/dist/detach.js +10 -0
  15. package/dist/environment.js +207 -0
  16. package/dist/errors.js +27 -0
  17. package/dist/events.js +106 -0
  18. package/dist/execution.js +451 -0
  19. package/dist/oauth.js +300 -0
  20. package/dist/pagination.js +76 -0
  21. package/dist/prompt.js +35 -0
  22. package/dist/published.js +79 -0
  23. package/dist/query.js +248 -0
  24. package/dist/ready.js +380 -0
  25. package/dist/release.js +142 -0
  26. package/dist/replica.js +614 -0
  27. package/dist/runtime-store.js +135 -0
  28. package/dist/runtime-verb.js +66 -0
  29. package/dist/runtime.js +87 -0
  30. package/dist/sdk.js +29 -0
  31. package/dist/secret.js +190 -0
  32. package/dist/semver.js +18 -0
  33. package/dist/skill-shape.js +189 -0
  34. package/dist/skills.js +129 -0
  35. package/dist/transport.js +205 -0
  36. package/dist/ts-deps-loader.js +113 -0
  37. package/dist/watch/consumer.js +141 -0
  38. package/dist/watch/cursor-file.js +62 -0
  39. package/dist/watch.js +175 -0
  40. package/dist/write.js +224 -0
  41. package/package.json +60 -0
  42. package/skills/catalyst-github/SKILL.md +35 -0
  43. package/skills/catalyst-github/agents/openai.yaml +6 -0
  44. package/skills/catalyst-github/agents/portability.yaml +4 -0
  45. package/skills/catalyst-github/references/is-it-mergeable.md +57 -0
  46. package/skills/catalyst-github/references/what-a-pr-accumulates.md +61 -0
  47. package/skills/catalyst-github/scripts/is-it-mergeable.mjs +124 -0
  48. package/skills/catalyst-github/scripts/lib/cli.mjs +103 -0
  49. package/skills/catalyst-github/scripts/lib/credential.mjs +29 -0
  50. package/skills/catalyst-github/scripts/lib/pull.mjs +82 -0
  51. package/skills/catalyst-github/scripts/read-pr.mjs +97 -0
  52. package/skills/catalyst-linear/SKILL.md +43 -0
  53. package/skills/catalyst-linear/agents/openai.yaml +6 -0
  54. package/skills/catalyst-linear/agents/portability.yaml +5 -0
  55. package/skills/catalyst-linear/references/reading-a-ticket.md +52 -0
  56. package/skills/catalyst-linear/references/what-a-ticket-accumulates.md +53 -0
  57. package/skills/catalyst-linear/references/writing-to-linear.md +43 -0
  58. package/skills/catalyst-linear/scripts/comment.mjs +59 -0
  59. package/skills/catalyst-linear/scripts/create-ticket.mjs +44 -0
  60. package/skills/catalyst-linear/scripts/label.mjs +48 -0
  61. package/skills/catalyst-linear/scripts/lib/cli.mjs +164 -0
  62. package/skills/catalyst-linear/scripts/lib/credential.mjs +29 -0
  63. package/skills/catalyst-linear/scripts/move.mjs +41 -0
  64. package/skills/catalyst-linear/scripts/read-ticket.mjs +93 -0
  65. package/skills/catalyst-linear/scripts/search.mjs +49 -0
  66. package/skills/catalyst-onboard/SKILL.md +57 -0
  67. package/skills/catalyst-onboard/agents/openai.yaml +6 -0
  68. package/skills/catalyst-onboard/agents/portability.yaml +5 -0
  69. package/skills/catalyst-onboard/references/declaring-a-repository.md +23 -0
  70. package/skills/catalyst-onboard/references/skill-sources.md +35 -0
  71. package/skills/catalyst-onboard/references/the-one-path.md +149 -0
  72. package/skills/catalyst-onboard/references/what-a-phase-needs.md +46 -0
  73. package/skills/catalyst-onboard/references/what-the-browser-owns.md +50 -0
  74. package/skills/catalyst-onboard/references/who-fixes-what.md +44 -0
  75. package/skills/catalyst-onboard/scripts/lib/cli.mjs +117 -0
  76. package/skills/catalyst-onboard/scripts/lib/credential.mjs +29 -0
  77. package/skills/catalyst-onboard/scripts/where-am-i.mjs +345 -0
  78. package/skills/catalyst-setup/SKILL.md +36 -0
  79. package/skills/catalyst-setup/agents/openai.yaml +6 -0
  80. package/skills/catalyst-setup/agents/portability.yaml +4 -0
  81. package/skills/catalyst-setup/references/what-each-check-means.md +88 -0
  82. package/skills/catalyst-setup/scripts/check.mjs +75 -0
  83. package/skills/catalyst-setup/scripts/lib/cli.mjs +103 -0
  84. package/skills/catalyst-setup/scripts/lib/credential.mjs +29 -0
  85. package/skills/catalyst-setup/scripts/replica-status.mjs +46 -0
  86. package/skills/connect-me/SKILL.md +63 -0
  87. package/skills/connect-me/agents/openai.yaml +6 -0
  88. package/skills/connect-me/agents/portability.yaml +5 -0
  89. package/skills/connect-me/references/keeping-the-replica-running.md +88 -0
  90. package/skills/connect-me/scripts/lib/cli.mjs +185 -0
  91. package/skills/connect-me/scripts/lib/credential.mjs +29 -0
  92. package/skills/connect-me/scripts/verify-connection.mjs +68 -0
  93. package/skills/how-catalyst-works/SKILL.md +43 -0
  94. package/skills/how-catalyst-works/agents/openai.yaml +6 -0
  95. package/skills/how-catalyst-works/agents/portability.yaml +4 -0
  96. package/skills/how-catalyst-works/references/coding-accounts.md +51 -0
  97. package/skills/how-catalyst-works/references/stages-and-mapping.md +56 -0
  98. package/skills/how-catalyst-works/references/the-ladder.md +41 -0
  99. package/skills/how-catalyst-works/references/what-catalyst-is.md +30 -0
  100. package/skills/how-catalyst-works/references/what-runs-next.md +77 -0
  101. package/skills/how-catalyst-works/references/when-a-phase-fails.md +57 -0
  102. package/skills/how-catalyst-works/scripts/explain-ticket.mjs +41 -0
  103. package/skills/how-catalyst-works/scripts/lib/cli.mjs +164 -0
  104. package/skills/how-catalyst-works/scripts/lib/credential.mjs +29 -0
  105. package/skills/how-catalyst-works/scripts/show-my-map.mjs +94 -0
  106. package/skills/how-catalyst-works/scripts/whats-running.mjs +65 -0
  107. package/skills/run-this-project/SKILL.md +45 -0
  108. package/skills/run-this-project/agents/openai.yaml +6 -0
  109. package/skills/run-this-project/agents/portability.yaml +5 -0
  110. package/skills/run-this-project/assets/stall-policy.json +15 -0
  111. package/skills/run-this-project/references/making-work-ready.md +60 -0
  112. package/skills/run-this-project/references/reacting-to-events.md +76 -0
  113. package/skills/run-this-project/references/stalls-and-escalation.md +63 -0
  114. package/skills/run-this-project/scripts/lib/cli.mjs +185 -0
  115. package/skills/run-this-project/scripts/lib/credential.mjs +29 -0
  116. package/skills/run-this-project/scripts/make-ready.mjs +64 -0
  117. package/skills/run-this-project/scripts/scope-status.mjs +0 -0
  118. package/skills/run-this-project/scripts/watch-scope.mjs +61 -0
  119. package/skills/unstick/SKILL.md +41 -0
  120. package/skills/unstick/agents/openai.yaml +6 -0
  121. package/skills/unstick/agents/portability.yaml +5 -0
  122. package/skills/unstick/references/playbook.md +51 -0
  123. package/skills/unstick/scripts/lib/cli.mjs +135 -0
  124. package/skills/unstick/scripts/lib/credential.mjs +29 -0
  125. package/skills/unstick/scripts/unstick.mjs +57 -0
  126. package/skills/what-needs-me/SKILL.md +41 -0
  127. package/skills/what-needs-me/agents/openai.yaml +6 -0
  128. package/skills/what-needs-me/agents/portability.yaml +5 -0
  129. package/skills/what-needs-me/references/raising-a-decision.md +41 -0
  130. package/skills/what-needs-me/references/reading-the-inbox.md +38 -0
  131. package/skills/what-needs-me/references/settling-an-answer.md +37 -0
  132. package/skills/what-needs-me/scripts/inbox.mjs +56 -0
  133. package/skills/what-needs-me/scripts/lib/cli.mjs +135 -0
  134. package/skills/what-needs-me/scripts/lib/credential.mjs +29 -0
  135. package/skills/what-needs-me/scripts/raise.mjs +53 -0
  136. package/skills/what-needs-me/scripts/settle.mjs +73 -0
  137. package/skills/whats-happening/SKILL.md +43 -0
  138. package/skills/whats-happening/agents/openai.yaml +6 -0
  139. package/skills/whats-happening/agents/portability.yaml +4 -0
  140. package/skills/whats-happening/assets/status-reply.json +77 -0
  141. package/skills/whats-happening/references/reading-the-board.md +43 -0
  142. package/skills/whats-happening/references/reprioritising.md +37 -0
  143. package/skills/whats-happening/references/routing-work.md +36 -0
  144. package/skills/whats-happening/references/status-reply.md +34 -0
  145. package/skills/whats-happening/references/why-is-it-stuck.md +62 -0
  146. package/skills/whats-happening/scripts/explain.mjs +28 -0
  147. package/skills/whats-happening/scripts/lib/cli.mjs +135 -0
  148. package/skills/whats-happening/scripts/lib/credential.mjs +29 -0
  149. package/skills/whats-happening/scripts/snapshot.mjs +149 -0
  150. package/vendor/README.md +9 -0
  151. package/vendor/paths/index.d.ts +85 -0
  152. package/vendor/paths/index.js +148 -0
  153. package/vendor/paths/legacy-installer.d.ts +36 -0
  154. package/vendor/paths/legacy-installer.js +154 -0
  155. package/vendor/paths/node.d.ts +18 -0
  156. package/vendor/paths/node.js +102 -0
  157. package/vendor/paths/provenance.json +17 -0
@@ -0,0 +1,93 @@
1
+ #!/usr/bin/env node
2
+ // read-ticket.mjs — one ticket with its comments, relations, labels, linked pull requests and agent
3
+ // sessions inline, from the replica when it is fresh, else the origin-fresh API. The source line the
4
+ // CLI prints on stderr is the freshness verdict; it is always shown.
5
+ import { parseFlags, parseJson, relayStderr, runCli, usage, wantsHelp } from "./lib/cli.mjs";
6
+
7
+ const HELP = `Usage: node scripts/read-ticket.mjs <ticket> [--comments] [--source replica|api] [--json]
8
+
9
+ Reads one ticket record. Wraps: catalyst-skills query issue.
10
+
11
+ <ticket> the Linear identifier, e.g. KEY-123
12
+ --comments also print every comment (id, author, time, body)
13
+ --source replica|api force one source; default is the replica when fresh, else the API
14
+ --json print the full record as JSON
15
+
16
+ The first stderr line names the source ("source: replica (cursor N)" or "source: api (replica
17
+ stale|absent|not configured)"); quote it when the freshness of the answer matters.
18
+
19
+ Exit 0 found, 1 not found or a usage error, 2 when this machine is not connected to a tenant or the
20
+ cloud refused the read (the line says which).`;
21
+
22
+ const argv = process.argv.slice(2);
23
+ if (wantsHelp(argv)) {
24
+ console.log(HELP);
25
+ process.exit(0);
26
+ }
27
+ const { flags, positionals } = parseFlags(argv, { bool: ["comments", "json"], value: ["source"] });
28
+ const ticket = positionals[0];
29
+ if (!ticket) usage("read-ticket needs a ticket identifier (see --help)");
30
+
31
+ const args = ["query", "issue", ticket, "--json"];
32
+ if (flags.source) args.push("--source", flags.source);
33
+ const r = runCli(args);
34
+ relayStderr(r);
35
+ if (r.code !== 0) {
36
+ const out = r.stdout.trimEnd();
37
+ if (out) console.log(out);
38
+ process.exit(r.code);
39
+ }
40
+ const row = parseJson(r.stdout);
41
+ if (!row || typeof row !== "object") {
42
+ console.log(r.stdout.trimEnd());
43
+ process.exit(1);
44
+ }
45
+ if (flags.json) {
46
+ console.log(JSON.stringify(row));
47
+ process.exit(0);
48
+ }
49
+
50
+ const line = (label, value) => {
51
+ if (value === undefined || value === null || value === "") return;
52
+ console.log(`${label}: ${typeof value === "string" ? value : JSON.stringify(value)}`);
53
+ };
54
+ const names = (list, key) => (Array.isArray(list) ? list.map((x) => (x && typeof x === "object" ? (x[key] ?? JSON.stringify(x)) : String(x))) : []);
55
+
56
+ line("ticket", row.identifier ?? row.id);
57
+ line("title", row.title);
58
+ line("state", row.state);
59
+ line("priority", row.priority_label ?? row.priority);
60
+ line("assignee", row.assignee_name ?? row.assignee);
61
+ line("delegate", row.delegate_name ?? row.delegate);
62
+ line("team", row.team_key ?? row.team_name ?? row.team_id);
63
+ line("project", row.project_name ?? row.project_id);
64
+ line("cycle", row.cycle_name ?? row.cycle_id);
65
+ line("parent", row.parent_identifier);
66
+ line("labels", names(row.labels, "name").join(", "));
67
+ line("url", row.url);
68
+ line("updated", row.updated_at);
69
+ if (Array.isArray(row.relations) && row.relations.length) {
70
+ console.log(`relations (${row.relations.length}):`);
71
+ for (const rel of row.relations) console.log(` ${rel.type ?? "?"}: ${rel.issue_identifier ?? ""} -> ${rel.related_identifier ?? JSON.stringify(rel)}`);
72
+ }
73
+ if (Array.isArray(row.linked_pulls) && row.linked_pulls.length) {
74
+ console.log(`linked pull requests (${row.linked_pulls.length}):`);
75
+ for (const pr of row.linked_pulls) console.log(` #${pr.number ?? "?"} ${pr.repo_id ?? ""} [${pr.node_id ?? ""}]`);
76
+ }
77
+ if (Array.isArray(row.agent_sessions)) line("agent sessions", row.agent_sessions.length);
78
+ if (Array.isArray(row.activity)) line("activity entries", row.activity.length);
79
+ if (Array.isArray(row.comments)) line("comments", row.comments.length);
80
+ if (row.description) {
81
+ console.log("description:");
82
+ console.log(String(row.description).trimEnd());
83
+ }
84
+ if (flags.comments && Array.isArray(row.comments)) {
85
+ console.log(`== comments (${row.comments.length})`);
86
+ for (const c of row.comments) {
87
+ const who = c.author_name ?? c.author_id ?? "?";
88
+ const bot = c.is_bot ? " [bot]" : "";
89
+ const parent = c.parent_id ? ` reply-to ${c.parent_id}` : "";
90
+ console.log(`-- ${c.id} · ${who}${bot} · ${c.updated_at ?? c.created_at ?? ""}${parent}`);
91
+ console.log(String(c.body ?? "").trimEnd());
92
+ }
93
+ }
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/env node
2
+ // search.mjs — tenant search across ticket identifiers and titles, pull-request titles, project and
3
+ // initiative names. Always the origin-fresh API (the replica holds no search view).
4
+ import { exitOnFailure, parseFlags, parseJson, relayStderr, runCli, usage, wantsHelp } from "./lib/cli.mjs";
5
+
6
+ const HELP = `Usage: node scripts/search.mjs <terms...> [--limit <n>] [--json]
7
+
8
+ Searches your tenant for tickets, pull requests, projects and initiatives matching the terms.
9
+ Wraps: catalyst-skills query search.
10
+
11
+ <terms> one or more words; matched against identifiers, titles and names
12
+ --limit <n> max rows (default 50)
13
+ --json print the rows as JSON
14
+
15
+ Exit 0 (an empty result is still 0 and prints "no matches"), 1 on a usage error, 2 when this
16
+ machine is not connected to a tenant or the cloud refused the search (the line says which).`;
17
+
18
+ const argv = process.argv.slice(2);
19
+ if (wantsHelp(argv)) {
20
+ console.log(HELP);
21
+ process.exit(0);
22
+ }
23
+ const { flags, positionals } = parseFlags(argv, { bool: ["json"], value: ["limit"] });
24
+ if (positionals.length === 0) usage("search needs at least one term (see --help)");
25
+
26
+ const args = ["query", "search", ...positionals, "--json"];
27
+ if (flags.limit) args.push("--limit", flags.limit);
28
+ const r = runCli(args);
29
+ exitOnFailure(r);
30
+ relayStderr(r);
31
+ const rows = parseJson(r.stdout);
32
+ if (flags.json) {
33
+ console.log(JSON.stringify(rows ?? r.stdout.trimEnd()));
34
+ process.exit(0);
35
+ }
36
+ const list = Array.isArray(rows) ? rows : rows && typeof rows === "object" ? Object.values(rows).flat() : [];
37
+ if (list.length === 0) {
38
+ console.log("no matches");
39
+ process.exit(0);
40
+ }
41
+ for (const row of list) {
42
+ if (!row || typeof row !== "object") {
43
+ console.log(String(row));
44
+ continue;
45
+ }
46
+ const kind = row.kind ?? (row.identifier ? "issue" : row.number ? "pull" : "row");
47
+ const id = row.identifier ?? (row.number !== undefined ? `#${row.number}` : row.id ?? "");
48
+ console.log(`${kind} ${id} ${row.title ?? row.name ?? ""}${row.state ? ` (${row.state})` : ""}`);
49
+ }
@@ -0,0 +1,57 @@
1
+ ---
2
+ name: catalyst-onboard
3
+ description: >-
4
+ Walk a person from nothing to their first Catalyst Cloud ticket running, one step at a time, hand-held. Use when someone says "set me up", "onboard me", "I just signed up", "get me started", "what do I do first", or when they have the Catalyst Cloud skills installed and nothing else. Reads each part of the setup with the instrument that owns it — this machine, the person, the account, one project, one repository — never folding one into another, does every step a key can do through the catalyst-skills CLI, and for the steps only a browser can do hands over the exact page and says what to come back with. Never claims a step it did not watch succeed.
5
+ disable-model-invocation: true
6
+ allowed-tools: Bash(catalyst-skills:*) Bash(npx @catalyst-cloud/catalyst-skills:*)
7
+ ---
8
+ <!-- vendored-from: @catalyst-cloud/catalyst-skills@0.8.0 — written in this repository for customer tenants -->
9
+
10
+ # Onboard me
11
+
12
+ You take one person from "the skills are installed" to "a ticket is running on my own tenant". You do it **one step at a time**: do the step, show them what actually came back, say what it means and what is next, then stop and let them answer. You never print the whole ladder at them and you never batch several steps into one turn.
13
+
14
+ Setup has seven parts and each is read by its own instrument: this **machine**, the **person**, the **account**, one **project** (a project is one Linear team), one **repository**, the **coding accounts** a phase runs on, and the **host**. Never say work can run while either of the last two is unfinished. A failure in one is not a failure in another, and a failing part names who can fix it and where. Getting that wrong is the one mistake that wastes a person's afternoon: a project problem reported as a machine problem sends them retrying a local command that was never going to help.
15
+
16
+ ## Run first
17
+
18
+ Scripts are run, never read. Each prints `--help`.
19
+
20
+ - `node scripts/where-am-i.mjs` — every part, each with the instrument that read it, its verdict, and for anything unfinished who can fix it and the page it is on. Works before the machine is connected; that is one of the states it reports.
21
+ - `node scripts/where-am-i.mjs --next` — the same reading, reduced to the single next step.
22
+ - `node scripts/where-am-i.mjs --json` — the same document for you to branch on.
23
+
24
+ Start every session with it, and run it again after every step the person completes. It is the only thing that decides where you are.
25
+
26
+ ## Load on demand
27
+
28
+ | when | read |
29
+ | -- | -- |
30
+ | walking the steps — what each one does, what to read back, when it is done | `references/the-one-path.md` |
31
+ | anything reports not ready, or you are about to say who should fix something | `references/who-fixes-what.md` |
32
+ | the next step is a browser page, or a page said it worked and you have to confirm it | `references/what-the-browser-owns.md` |
33
+ | the person asks what Catalyst actually is, or how a ticket gets worked | the `how-catalyst-works` skill |
34
+ | the machine will not connect, or a login expired | the `connect-me` skill |
35
+ | the person asks how to install, update, or migrate Catalyst skills | `references/skill-sources.md` |
36
+ | the person's repository needs environment names declared | `references/declaring-a-repository.md` |
37
+ | the `coding accounts` or `host` part is not ok, or you are about to say work can run | `references/what-a-phase-needs.md` |
38
+ | setup is finished and they want the standing readiness verdict | the `catalyst-setup` skill |
39
+ | the first ticket did not start and you need the reason | the `how-catalyst-works` skill, then `unstick` |
40
+
41
+ ## Rules
42
+
43
+ - **One step, then stop.** Say what you are about to do, do it, show the real output, say what it means and what comes next. Never queue several steps into one message, and never move on from a step you did not watch finish.
44
+ - **Report what you observed, not what you expected.** Print the lines the command actually produced. "That worked" without the output it produced is the single easiest thing to get wrong here, and a person who later finds it did not work stops trusting every other step you reported.
45
+ - **Each part by its own instrument.** Read the machine with the machine's instrument and the project with the project's, and label every finding with the part it belongs to. The script does this for you; keep it that way when you summarize.
46
+ - **Not ready is a question about who, not a reason to retry.** When something reports not ready, name which check, who can fix it, and where. If the owner is not the person in front of you, say so and stop — re-running a local command cannot move a check that belongs to a tenant owner, an admin, or a browser page.
47
+ - **Never invent a count or a list.** Every number and every name comes from what a command printed. If you want to tell them how many projects are mapped, read it off the script's output; do not carry one over from an earlier turn.
48
+ - **Three steps belong to a browser and always will**: approving the login, connecting Linear, and installing the GitHub App. Hand over the page and say what you need back. Do not claim you did them.
49
+ - **Some steps a key cannot do yet.** Listing every project, saving a stage mapping, adopting the workflow, registering a repository and approving one repository's environment are settings-page work today; a key-callable path for them is being built. Route those through the browser and say plainly that it is a gap, not the design. Never guess at a route for them.
50
+ - **The account-wide environment declaration is the exception, and the one setup write you can perform.** `catalyst-skills environment` reads it, proposes it and approves it. Use the verb; do not send them to a page for it.
51
+ - **Their tenant, as them.** Everything goes through the CLI and the person's own login. You never name another tenant, and you never ask for a key you could avoid — the keyless login needs nothing pasted.
52
+ - **Use the right skill source.** This tenant onboarding skill comes from `catalyst-cloud-skills`. Coding workflows come from `catalyst-dev-skills`. Never direct a person to install skills from the deprecated local runtime or its `catalyst-dev@catalyst` plugin.
53
+ - **Write like a capable colleague.** Plain words, short sentences, one idea each, active voice. Say what a thing does with a fact or a number. No em dashes, no emoji, no chatbot openers or flattery, and bold only the rare thing. Reread each message before you send it and fix what sounds machine-written.
54
+ - **Ask once before you write to their machine.** Say what you found, what you will write and where, then wait for a yes. A skill migration asks again before each removal.
55
+ - **A blocked command is the person's call.** If the harness blocks `npx`, a global `npm install -g`, or a tool permission, ask for approval or hand them the command. Never skip it silently, never edit your own permission settings, and never report a step you did not see succeed.
56
+ - **An older cloud is not a broken command.** When the CLI says the cloud is older than the bundle, say so and move on. The command exists; this tenant's cloud has not deployed it yet.
57
+ - **Stop at a wall you cannot pass.** A suspended account, a seat that is not active, a person who is not an owner or admin where one is required: say what you found, name who can act, and stop. Do not loop.
@@ -0,0 +1,6 @@
1
+ interface:
2
+ display_name: "Onboard me"
3
+ short_description: "Walk a person from nothing to their first Catalyst Cloud ticket running, one step at a time, saying who owns each step"
4
+ default_prompt: "Use $catalyst-onboard to set me up on Catalyst Cloud, one step at a time."
5
+ policy:
6
+ allow_implicit_invocation: false
@@ -0,0 +1,5 @@
1
+ identity: { pack: catalyst-cloud-skills, skill: catalyst-onboard }
2
+ effects: [local-write, external-write]
3
+ mutating: true
4
+ invocation: explicit
5
+ exposure: [catalog]
@@ -0,0 +1,23 @@
1
+ # Declaring what one repository's containers need
2
+
3
+ The cloud containers build and test the repository. They need the names of the variables and secrets it reads. You write the names; the person enters the values in the app. Never read or print a value.
4
+
5
+ ## The inventory, in order
6
+
7
+ 1. Start from the commands that already build and test the repository: the README's setup section, the scripts in `package.json` or its equivalent, and the build and test steps in CI. Those are what the container runs. A name they never read does not belong in the file.
8
+ 2. For each name, record the file it came from: a `.env.example` (never `.env`, which holds live values), a CI secret in a workflow's `env:` block, or a platform binding. A name you cannot tie to a file is a guess. Say so instead of listing it.
9
+ 3. Mark whether the container needs it to build and test, or only to deploy. Containers build and test. They do not deploy.
10
+ 4. Leave platform bindings and deploy-only CI secrets out by default. The platform supplies a binding at run time, and no build or test reads a deploy-only secret. Include one only when the person says the build needs it, and say why.
11
+ 5. Write the names into `catalyst.env.json` at the repository root and open a pull request. Use that exact name and place; the cloud reads no other file. It reads the file once the pull request merges to the default branch. A tenant owner or admin then approves it at Settings → Repositories → the repository → Environment, and the person enters the values on that page.
12
+
13
+ ## The file's shape
14
+
15
+ `"version": 1` plus eight arrays, each present even when empty: `toolchains`, `systemPackages`, `setup`, `verify`, `services`, `environment`, `agentAssets`, `provenance`. The repository's Environment page in the app shows a complete, valid example. Start from it rather than from memory.
16
+
17
+ - `setup` and `verify` carry this repository's own install and test commands. `command` is an argument list, not a shell string.
18
+ - Each name under `environment` says whether it is `required`. Add `"secret": true` beside a secret.
19
+ - Each `provenanceIds` entry points at a record under `provenance` that names the file the name came from.
20
+
21
+ ## After the merge
22
+
23
+ `catalyst-skills ready` reports `environment_declared` for the team's default repository and names the next step: commit the file, fix it, or approve it. The `catalyst-setup` check table has each reason. The account-wide declaration is separate; `catalyst-skills environment` handles it (step 7 of `references/the-one-path.md`).
@@ -0,0 +1,35 @@
1
+ # Catalyst skill sources
2
+
3
+ Catalyst has two supported skill packs. They have separate purposes and versions.
4
+
5
+ The installer the person ran first, at their cloud's `/install.sh` (the app's setup page shows the command), installs both packs in one pass. It stages them with a pinned skills CLI, installs exact commits, and stops on any same-named skill it does not recognise, naming the path. A home install schedules a daily refresh that also picks up new skills. Re-run it to refresh or repair either pack. The commands in the table are the by-hand equivalent.
6
+
7
+ | Pack | Purpose | By hand | Optional Claude Code plugin |
8
+ | -- | -- | -- | -- |
9
+ | `coalesce-labs/catalyst-cloud-skills` | Tenant setup and operation | `npx skills@latest add coalesce-labs/catalyst-cloud-skills --all -g` | `catalyst@catalyst-cloud` |
10
+ | `coalesce-labs/catalyst-dev-skills` | Coding workflows | `npx skills@latest add coalesce-labs/catalyst-dev-skills --all -g` | `catalyst-dev@catalyst-dev-skills` |
11
+
12
+ Install both packs on a workstation used for coding and tenant operations. Each Claude plugin is an alternative to `npx skills` for that same pack. Do not install a pack through both methods.
13
+
14
+ ## Where each install lands
15
+
16
+ - Global (`-g`): the skills go in `~/.agents/skills/`, and `~/.claude/skills/` holds links into it. Codex, Cursor and OpenCode read `~/.agents/skills/`; nothing fills `~/.codex/skills/` or `~/.cursor/skills/`.
17
+ - Project (no `-g`): `.agents/skills/`, `.claude/skills/` and `skills-lock.json` at the project root. Nothing lands in the home directory.
18
+ - The global lock is `$XDG_STATE_HOME/skills/.skill-lock.json` when `XDG_STATE_HOME` is set, else `~/.agents/.skill-lock.json`. A project uses its own `skills-lock.json`.
19
+ - The installer writes relative links. Resolve each with `readlink -f` before you compare paths.
20
+
21
+ ## Is each pack there
22
+
23
+ `catalyst-skills ready` checks the Cloud pack only. Check `catalyst-onboard/SKILL.md` (Cloud pack) and `research-codebase/SKILL.md` (development pack) in the intended directory. If both are there, have the person type `/catalyst-onboard` (`$catalyst-onboard` in Codex).
24
+
25
+ ## Migrate an existing installation
26
+
27
+ Inventory source and scope before removing anything:
28
+
29
+ 1. Run `claude plugin list` and record whether `catalyst-dev@catalyst` is installed and at which scope.
30
+ 2. Inspect the selected agent's home skill directory and the current project's skill directory separately. Read any `skills-lock.json` files and source/provenance markers. A folder name alone does not prove which repository supplied it. Check whether `.claude/skills` is a symlink to another skills directory before changing either path.
31
+ 3. If the old plugin is active, remove only `catalyst-dev@catalyst`: `claude plugin uninstall catalyst-dev@catalyst --scope user --keep-data --yes`. Keep `catalyst-dev@catalyst-dev-skills` and `catalyst@catalyst-cloud`. If old skill copies are present, remove only copies whose recorded source is the deprecated local runtime. Keep unrelated skills and plugin installs.
32
+ 4. Install the replacement pack or packs in the intended scope with the commands above. For the Cloud pack, omit `-g` only when a project-scoped install is intended. Do not use a blanket `npx skills remove --all` during migration.
33
+ 5. Read back the plugin list or skill lock and the destination skill folders. Start a new agent session after changing Claude plugins.
34
+
35
+ Do not delete a Catalyst checkout, local project data, or a same-named skill whose source is not known. If the source or scope is ambiguous, stop and report what is unclear before removing anything.
@@ -0,0 +1,149 @@
1
+ # The one path
2
+
3
+ Nine steps, in this order. The order is the product's own: the tenant-side steps run Linear, then the project, then GitHub, then the repository, because each one is the cheapest place to catch the failure the next one would otherwise hide.
4
+
5
+ Walk them **one at a time**. Before each step say what you are about to do and why; after it, show what actually came back. `node scripts/where-am-i.mjs --next` decides which step you are on — never your memory of the last turn.
6
+
7
+ Each step below states: what it is for, what you run or hand over, **what you read back to prove it landed**, and **who owns it**.
8
+
9
+ ---
10
+
11
+ ## 0 — Where are we
12
+
13
+ **For:** starting from the truth instead of from an assumption. A person arrives here having done anything from nothing to most of it.
14
+
15
+ **You run:** `node scripts/where-am-i.mjs`
16
+
17
+ **Read back:** the whole thing, as it printed. Then say in one sentence which part is unfinished and whose it is.
18
+
19
+ **Owner:** you.
20
+
21
+ ---
22
+
23
+ ## 1 — Connect this machine
24
+
25
+ **For:** giving this machine a credential, so every later read is the person's own.
26
+
27
+ **You run:** `catalyst-skills login`. It prints a short code and a URL. The person approves it in a browser — from a phone, if this machine has none.
28
+
29
+ **Read back:** the `Connected to …` and `Connected as …` lines the command printed, then `node scripts/where-am-i.mjs` again so the machine part flips.
30
+
31
+ **Owner:** you run it; **the approval is the person's, in a browser, and always will be.** Wait for them. Do not re-run the command while a code is outstanding — that invalidates the code they are typing.
32
+
33
+ If it refuses, stop here and use the `connect-me` skill; it owns every failure mode of this step.
34
+
35
+ ---
36
+
37
+ ## 2 — Who you are
38
+
39
+ **For:** the person grain. A connected machine does not mean an active seat, and an active seat does not mean their Linear identity is matched.
40
+
41
+ **You run:** it is already in the step 0 script's `person` line.
42
+
43
+ **Read back:** their label and role, and whether their Linear identity is matched.
44
+
45
+ **Owner:** an unmatched Linear identity is fixed by a tenant owner or admin in Settings → Members. A seat that is not active is the same. Say which, and move on — neither blocks the steps below, but an unmatched identity means "what needs me" will show everyone's asks until it is fixed, and they should know that now rather than later.
46
+
47
+ ---
48
+
49
+ ## 3 — Connect Linear
50
+
51
+ **For:** the account grain. Nothing about a project can be read or mapped until the tenant's Linear workspace is connected.
52
+
53
+ **You hand over:** `<their cloud>/settings/connections`, and say: connect Linear.
54
+
55
+ **Read back:** after they say it is done, re-run `node scripts/where-am-i.mjs` and read them the `account` line. A resolved workspace is proof. If it still reads unresolved, say the contract may be cached and run `catalyst-skills contract --refresh`, then read it again.
56
+
57
+ **Owner:** a tenant owner or admin, in a browser. **This is a browser step by construction** — it is an authorization grant, and no key can perform one.
58
+
59
+ ---
60
+
61
+ ## 4 — Pick one project, and map its stages
62
+
63
+ **For:** the project grain. A project is one Linear team. Until a project's stages are mapped, a card moved into it does nothing at all — this is the single most common reason a new tenant sees no activity.
64
+
65
+ **You hand over:** `<their cloud>/settings/linear-teams`. They pick one project and press **Map my stages**, or **Adopt the Catalyst workflow** if they want Catalyst's own stages created for them.
66
+
67
+ **Read back:** re-run the script and read the `projects` line. A project that now appears with a readiness verdict is proof it was saved. Read them the verdict and any failing checks by name.
68
+
69
+ **Owner:** a tenant owner or admin. ⛔ **Listing the projects and saving a mapping are settings-page work today** — a key cannot do either yet, and a key-callable path is being built. Say that plainly; it is a gap in the product, not something they did wrong.
70
+
71
+ ⭐ **One project at a time is safe, and lead with this.** Mapping one project changes no other project's stages and moves no other project's tickets. Encourage a pilot: pick the project they care least about breaking.
72
+
73
+ ---
74
+
75
+ ## 5 — Install the GitHub App
76
+
77
+ **For:** the account grain again. Without it Catalyst can read tickets but cannot touch code.
78
+
79
+ **You hand over:** `<their cloud>/settings/connections`, and say: install the GitHub App, and grant it the repository they want worked.
80
+
81
+ **Read back:** it is confirmed by step 6 succeeding — a repository cannot be registered through an app that is not installed. Say that is what you are waiting for rather than claiming you verified it here.
82
+
83
+ **Owner:** a tenant owner or admin, in a browser. **Browser by construction**, same reason as step 3.
84
+
85
+ ---
86
+
87
+ ## 6 — Register the repository
88
+
89
+ **For:** the repository grain. Registering is what makes a repository something a project can dispatch work into.
90
+
91
+ **You hand over:** `<their cloud>/settings/repositories`, and say: add the repository, **and attach it to the project you mapped in step 4**.
92
+
93
+ **Read back:** re-run the script and read the `repositories` line. The repository appearing there is proof it was registered — and **only that**. It is not proof it can be dispatched to; see `references/who-fixes-what.md` for what registration does and does not prove.
94
+
95
+ **Owner:** a tenant owner or admin. ⛔ **Registering is settings-page work today**; a key-callable path is being built. ⛔ A repository registered without a project attached is the trap here: the call succeeds, the repository is listed, and nothing can ever dispatch into it. Make sure they attach the project in the same form, and say why.
96
+
97
+ ---
98
+
99
+ ## 7 — Declare what the containers need
100
+
101
+ **For:** the environment a phase runs in — the names of the variables and secrets the person's code needs. Names leave the machine; values are entered once, by them, in the app.
102
+
103
+ ⭐ **This is the one setup step you can actually do.** Every other step above is a page. This one is a command, and it is worth saying so to the person.
104
+
105
+ **You run:** `catalyst-skills environment` first, to read what the tenant already declares — the current revision, whether it is approved, and which revision a phase's checkout actually carries. Those last two are different things more often than people expect: a proposal that nobody approved changes nothing.
106
+
107
+ To change it, write the declaration to a JSON file and propose it:
108
+
109
+ ```sh
110
+ catalyst-skills environment propose --file declaration.json
111
+ ```
112
+
113
+ Add `--approve` to approve exactly the revision that propose just returned, which is the one-command form and the one to prefer — it is a compare-and-set, and nothing gets copied between two commands by hand. `catalyst-skills environment approve` on its own reads the current revision and approves that.
114
+
115
+ **Read back:** the revision and hash the command printed, and whether it says the declaration is now what a phase's checkout carries. If it prints `referenced but not set on this tenant yet`, read those names out: the declaration names them and the tenant has no value for them, so a phase that needs one will fail on it until someone adds it in the app.
116
+
117
+ **Owner:** you can read it from any active seat; proposing and approving need an admin or owner seat, and the cloud refuses with that sentence if the person does not have one — read the refusal to them rather than retrying.
118
+
119
+ ⛔ **Values never pass through you.** The declaration carries the *names* a build needs. The values are entered by the person, once, in the app, and nothing you run ever sees them. Say that plainly; a person asked for a secret by an agent is right to be suspicious. The names one repository needs go in its own committed `catalyst.env.json`. See `references/declaring-a-repository.md`.
120
+
121
+ If they do not know what their build needs yet, skip this step. It blocks nothing until a phase needs a secret.
122
+
123
+ ---
124
+
125
+ ## 8 — A coding account, and a host
126
+
127
+ **For:** what a phase runs on. Without an enrolled coding account and a passing host check, every step above can be done and nothing starts.
128
+
129
+ **You run:** it is already in the script, as the `coding accounts` and `host` parts. What each reading means, who owns it, and what to hand over are in `references/what-a-phase-needs.md`. The contract names who enrols the account and who owns the host.
130
+
131
+ ---
132
+
133
+ ## 9 — Verify, then run the first ticket
134
+
135
+ **For:** the only thing that proves setup worked.
136
+
137
+ **You run:** `catalyst-skills ready`. Its READY does not cover step 8; the script does. Read them the verdict and every failing line, each with its own fix and owner. If it says NOT READY, go to `references/who-fixes-what.md` before you touch anything — a project check failing is not something re-running anything on this machine can fix.
138
+
139
+ **Then:** have them move one card into the project's dispatch stage, and watch. `catalyst-skills explain <ticket>` says why it is or is not about to run.
140
+
141
+ **Read back:** what `explain` actually said. If it says the ticket cannot start, the reason it names is the answer — read it to them and use the `how-catalyst-works` skill for what the reason means, then `unstick` if something is holding it.
142
+
143
+ **Owner:** the card move is theirs. The verdict is the tenant's.
144
+
145
+ ---
146
+
147
+ ## When you are done
148
+
149
+ Say what is set up, name anything still unfinished with its owner, and never say work can run while the `coding accounts` or `host` part is unfinished, and tell them the standing question "am I set up?" now belongs to the `catalyst-setup` skill, and "what's happening?" to `whats-happening`. You do not need to be invoked again.
@@ -0,0 +1,46 @@
1
+ # What a phase needs to run
2
+
3
+ A person can finish every other step and still see nothing run. A phase needs two more things: an enrolled coding account, and a host check that passes. `node scripts/where-am-i.mjs` reads both, as the `coding accounts` and `host` parts. Read those parts; never assume either.
4
+
5
+ ## Coding accounts
6
+
7
+ **For:** a phase runs on one of the tenant's own enrolled coding accounts. With none active, no phase can start.
8
+
9
+ **Instrument:** `codingAccounts` in `catalyst-skills contract`. It carries a `state`, a printable `line`, who enrolls an account (`enrolledByLine`) and the `page`. The script prints all of them. It never shows a credential or an email.
10
+
11
+ **What each state means:**
12
+
13
+ | state | what it says | what to do |
14
+ | -- | -- | -- |
15
+ | `enrolled` | at least one account is active | nothing |
16
+ | `none_enrolled` | no account is enrolled | hand over the page; the enroller the contract names enrols one |
17
+ | `inactive` | accounts exist, but every one is out of rotation | reactivate one on the page. Never tell them to enrol another |
18
+ | `unread` | the cloud could not read the accounts | say it could not be read. It is not "no accounts". Do not tell them to enrol one; read it again later |
19
+
20
+ **Owner:** the one the contract names. The person does it in the browser. Never ask for the credential, and never handle it. A key cannot enrol one.
21
+
22
+ **Older cloud:** if the contract has no `codingAccounts`, the script says the cloud is older and reads `catalyst-skills accounts` instead. That list counts the accounts enrolled and the ones able to take work. An expired, revoked or quarantined account does not count. The owner is then a tenant owner or admin, at `<their cloud>/settings/coding-accounts`.
23
+
24
+ ## Host
25
+
26
+ **For:** the contract carries this as the `hosts_current` readiness check on each project. It reads the same on every project, because it is about the whole account.
27
+
28
+ **Instrument:** the `hosts_current` check in `catalyst-skills contract --path teams`, and its owner in `catalyst-skills contract --path readinessChecks`.
29
+
30
+ **What each reading means:**
31
+
32
+ | reading | what it says | what to do |
33
+ | -- | -- | -- |
34
+ | `pass` | nothing is waiting on a host. A tenant that runs no host of its own reads this too | nothing |
35
+ | `unknown`, `no_host_connected` | no Catalyst host is connected | name the owner and stop |
36
+ | `unknown`, `hosts_unreported` | a host is connected but has not said which mapping it loaded | name the owner; it clears when the host reconnects |
37
+ | `fail`, `hosts_behind` | a connected host runs an older mapping | name the owner |
38
+ | the part reads `unreadable` | no project has been checked yet | press Re-check on the projects page, then read it again |
39
+
40
+ **Owner:** the contract names the owner of `hosts_current`, and where they act in its `fixedWhere`. When `fixedWhere` has a page, the script prints it, and the command too when there is one. When it is null, which it is today, the script prints the owner sentence alone. Then there is no page, so do not invent one. Say who owns it and that they connect it.
41
+
42
+ ⛔ `catalyst-skills ready` treats this check as a note, so it can print READY while no host is connected. READY there is not proof a phase can run. The `host` part is.
43
+
44
+ ## Saying it is ready
45
+
46
+ Say a phase can run only when the script's last line says nothing is left. While either part is unfinished or unreadable, name that part, its owner, and where, and say plainly that no work will start yet.
@@ -0,0 +1,50 @@
1
+ # What the browser owns
2
+
3
+ Some steps you cannot do, and the honest thing is to say which and why. There are two kinds, and they deserve different sentences.
4
+
5
+ ## Kind one: browser by construction
6
+
7
+ These will never be a command, on any release. Each is an authorization a person grants in their own session; a credential that could perform one would defeat the point of it.
8
+
9
+ | step | where | what you say |
10
+ | -- | -- | -- |
11
+ | approving the login | the URL and short code that `catalyst-skills login` printed | "I have started the login. It printed this code and this URL — approve it in your browser, or on your phone, and tell me when it is done." |
12
+ | connecting Linear | `<their cloud>/settings/connections` | "Open this page and connect Linear. It will send you to Linear to authorize it and bring you back." |
13
+ | installing the GitHub App | `<their cloud>/settings/connections` | "Open the same page and install the GitHub App, granting it the repository you want worked." |
14
+
15
+ Say **by construction**, not "not supported yet". A person who thinks it is a missing feature will wait for it.
16
+
17
+ ## Kind two: not a command yet
18
+
19
+ These are settings pages today because the routes behind them take a browser session and not a key. A key-callable path is being built. They are gaps, and you should say so in those words — but you must still route the person through the browser, and you must not guess at a route. Trying one and being refused wastes their time and teaches them the tool is unreliable.
20
+
21
+ | step | where | what you say |
22
+ | -- | -- | -- |
23
+ | seeing every project they could set up | `<their cloud>/settings/linear-teams` | "I can read the projects that are already mapped, but the full list is only on this page today. Open it and tell me the ones you see." |
24
+ | checking a project's readiness, or re-checking it | the same page | "I can read the verdict your tenant last stored, from the contract. Asking for a fresh check is on that page." |
25
+ | mapping stages, or adopting the workflow | the same page, per project | "Pick one project, then **Map my stages** — or **Adopt the Catalyst workflow** if you want Catalyst's stages created for you." |
26
+ | registering a repository | `<their cloud>/settings/repositories` | "Add the repository here, and attach it to the project you just mapped, in the same form." |
27
+ | approving the environment **for one repository**, and entering its values | that repository's environment section under `<their cloud>/settings/repositories` | "The names come from `catalyst.env.json` in the repository, which I can write with you. Approving it and entering the values happen here, once, by you. Nothing I run ever sees a value." (Account-wide names are **not** on this list: `catalyst-skills environment` does those.) |
28
+
29
+ ⛔ **Do not compose a request for any of these.** A skill script never makes a request of its own; only the CLI does, and the CLI has no verb for them. If you find yourself constructing a URL, stop.
30
+
31
+ ## The URL to hand over
32
+
33
+ Never type a host from memory. `catalyst-skills status` prints the API it is connected to on its `API:` line, and `node scripts/where-am-i.mjs` prints ready-made links built from it. Use those. A person pointed at the wrong tenant's settings page has a worse afternoon than one pointed at no page at all.
34
+
35
+ ## Handing over, and coming back
36
+
37
+ The shape is always the same three parts, and all three matter:
38
+
39
+ 1. **What to open.** One link, and what they will see on it.
40
+ 2. **What to do there.** One action, named the way the page names it.
41
+ 3. **What you need back.** Not "let me know when you are done" — say what you will check and how. "When you have saved it, say so and I will re-read your tenant and tell you what it now says."
42
+
43
+ Then **wait**. Do not run anything while they are mid-flow, do not narrate, and do not move to the next step.
44
+
45
+ When they come back:
46
+
47
+ - Re-run `node scripts/where-am-i.mjs` and read them the part that should have changed.
48
+ - If it changed, say what it now says and move on.
49
+ - If it did not, refresh the contract once (`catalyst-skills contract --refresh`) and read it again — the contract is cached, and a page can be ahead of it by a few seconds.
50
+ - If it still did not, report both: what the page told them, and what the instrument says. Ask what they saw. **Never mark a step done because the person said a page worked** — the instrument is the record, and this is exactly where a confident false "all set" costs them an hour later.
@@ -0,0 +1,44 @@
1
+ # Who fixes what
2
+
3
+ Setup is seven parts. Each has one instrument, and each instrument answers about its own part and nothing else. Read this before you tell a person that something is not ready, and before you tell them to do anything about it.
4
+
5
+ ## The seven parts, and the instrument that owns each
6
+
7
+ | part | instrument | what a pass proves | what it does **not** prove | who fixes a failure, and where |
8
+ | -- | -- | -- | -- | -- |
9
+ | **machine** | `catalyst-skills status`, and the non-team checks of `catalyst-skills ready` | Node is new enough, this machine holds a credential, the CLI is where the config says, the contract is cached, the skills are on disk | anything at all about the tenant | the person at this keyboard, here |
10
+ | **person** | `catalyst-skills me` | the credential resolves to this person, with a role, and whether their Linear identity is matched | that their seat is active, or that they may change tenant settings | a tenant owner or admin, Settings → Members |
11
+ | **account** | `catalyst-skills contract --path account` | a resolved Linear workspace means the tenant's Linear grant landed | that the GitHub App is installed — the contract does not carry it | a tenant owner or admin, `<their cloud>/settings/connections` |
12
+ | **project** | `catalyst-skills contract --path teams`, and the `team:` checks of `ready` | for each project **that has been mapped**: its readiness verdict and each failing check by name | that this is every project they have — see below | a tenant owner or admin, `<their cloud>/settings/linear-teams` |
13
+ | **repository** | `catalyst-skills contract --path merge.repositories` | the repository is registered to the account | that it is active, that a project can dispatch into it, or that its environment is declared | a tenant owner or admin, `<their cloud>/settings/repositories` |
14
+ | **coding accounts** | `codingAccounts` in `catalyst-skills contract` (`catalyst-skills accounts` on an older cloud) | an account is enrolled and active | that it has headroom left for the next phase | the enroller and page the contract names; see `references/what-a-phase-needs.md` |
15
+ | **host** | the `hosts_current` check in `catalyst-skills contract --path teams` | no host is missing or behind, or the tenant runs none | anything before a project has been checked | the owner the contract names for `hosts_current`; see `references/what-a-phase-needs.md` |
16
+
17
+ `node scripts/where-am-i.mjs` runs all seven and labels each finding with its part. Use it rather than composing this by hand.
18
+
19
+ ## The two silences that are not absences
20
+
21
+ ⛔ **An empty project list means nothing is mapped yet — it does not mean they have no projects.** The tenant contract carries a project only once someone has saved a stage mapping for it. A brand-new tenant has projects in Linear and an empty list here, and reading that as "you have no projects" sends the person looking for a problem that does not exist. Say: *nothing is mapped yet*, and go to step 4. The list of every project they could map is browser-only today.
22
+
23
+ ⛔ **A registered repository is not a dispatchable one.** The contract's repository list carries no status and no project attachment, so a paused repository and an active one look identical there, and a repository registered without a project attached looks exactly like a correctly attached one. Registration is all it proves. If a card does not start, `catalyst-skills explain <ticket>` names the real reason; do not conclude anything about the repository from its presence in a list.
24
+
25
+ ⭐ And the general form of both: **an instrument that answers about a part it does not own will answer confidently and wrongly.** When you are unsure which part something belongs to, look it up in the table above rather than guessing from the wording of an error.
26
+
27
+ ## Triaging NOT READY
28
+
29
+ `catalyst-skills ready` prints one verdict over every check, machine and project together. That single verdict is correct for "can work run?" and useless for "what should I do now?", because it folds two parts into one word. Split it before you act:
30
+
31
+ 1. Run `catalyst-skills ready --json`. Every check has an `id`.
32
+ 2. A check whose id begins with `team:` is a **project** finding. Everything else is a **machine** finding.
33
+ 3. Report the two groups separately, in that order, each with its own owner.
34
+
35
+ - **A machine check failed.** This is the person's, here, now. Each failing check carries its own `fix` line; read it and do it. A missing or partial skill set is `catalyst-skills install`; a stale contract is `catalyst-skills contract --refresh`; a missing CLI path is one more `catalyst-skills login`.
36
+ - **A project check failed.** ⛔ **Nothing you run on this machine can move it.** Name the check, name the project, and name the owner — the `who` field carries the tenant's own owners and admins. Point at `<their cloud>/settings/linear-teams`. Then stop. Re-running `ready` in a loop is the failure this section exists to prevent: it will keep saying NOT READY for a reason that lives somewhere else entirely.
37
+ - **A check is a note.** Notes never move the verdict. A stale or absent replica is optional; a check that has never been run is waiting, not failing; a check the engine could not run is unknown, which is not a pass and not a failure. Say which of the three it is.
38
+
39
+ ## When to stop rather than continue
40
+
41
+ - **They have no account yet.** There is no self-serve sign-up. Coalesce Labs provisions each account, and a person joins one by invitation from its admin. Say so and stop; the next step is theirs.
42
+ - **The account is suspended.** Setup cannot proceed and no retry changes that. Say so and name the conversation they need to have.
43
+ - **Their seat is not active, or they are not an owner or admin where one is required.** Say who is, and what to ask for. Do not offer a workaround.
44
+ - **A page said it worked and the instrument still disagrees.** Refresh the contract once (`catalyst-skills contract --refresh`) and read it again. If it still disagrees, report both facts — what the page said and what the instrument says — and let the person decide. Do not pick one for them.