@catalyst-cloud/catalyst-skills 0.2.0 → 0.3.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 (48) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +39 -29
  3. package/bin/catalyst-skills.js +42 -2
  4. package/dist/args.js +14 -8
  5. package/dist/ask.js +26 -5
  6. package/dist/cli.js +20 -8
  7. package/dist/config.js +1 -1
  8. package/dist/contract.js +2 -2
  9. package/dist/execution.js +165 -13
  10. package/dist/http.js +55 -3
  11. package/dist/prompt.js +1 -1
  12. package/dist/query.js +42 -4
  13. package/dist/ready.js +2 -2
  14. package/package.json +4 -3
  15. package/skills/catalyst-github/SKILL.md +1 -1
  16. package/skills/catalyst-github/references/what-a-pr-accumulates.md +1 -1
  17. package/skills/catalyst-github/scripts/lib/cli.mjs +2 -2
  18. package/skills/catalyst-github/scripts/read-pr.mjs +1 -1
  19. package/skills/catalyst-linear/SKILL.md +1 -1
  20. package/skills/catalyst-linear/references/reading-a-ticket.md +2 -2
  21. package/skills/catalyst-linear/references/writing-to-linear.md +1 -1
  22. package/skills/catalyst-linear/scripts/lib/cli.mjs +1 -1
  23. package/skills/catalyst-setup/SKILL.md +3 -3
  24. package/skills/catalyst-setup/references/what-each-check-means.md +6 -5
  25. package/skills/catalyst-setup/scripts/lib/cli.mjs +2 -2
  26. package/skills/catalyst-setup/scripts/replica-status.mjs +1 -1
  27. package/skills/connect-me/SKILL.md +9 -9
  28. package/skills/connect-me/agents/openai.yaml +1 -1
  29. package/skills/connect-me/scripts/lib/cli.mjs +2 -2
  30. package/skills/how-catalyst-works/SKILL.md +2 -2
  31. package/skills/how-catalyst-works/references/coding-accounts.md +2 -2
  32. package/skills/how-catalyst-works/references/when-a-phase-fails.md +2 -2
  33. package/skills/how-catalyst-works/scripts/lib/cli.mjs +1 -1
  34. package/skills/how-catalyst-works/scripts/whats-running.mjs +1 -2
  35. package/skills/run-this-project/SKILL.md +2 -2
  36. package/skills/run-this-project/references/reacting-to-events.md +1 -1
  37. package/skills/run-this-project/references/stalls-and-escalation.md +1 -1
  38. package/skills/run-this-project/scripts/lib/cli.mjs +2 -2
  39. package/skills/what-needs-me/SKILL.md +2 -2
  40. package/skills/what-needs-me/references/reading-the-inbox.md +1 -1
  41. package/skills/what-needs-me/scripts/inbox.mjs +15 -6
  42. package/skills/what-needs-me/scripts/lib/cli.mjs +2 -2
  43. package/skills/whats-happening/SKILL.md +3 -3
  44. package/skills/whats-happening/assets/status-reply.json +1 -1
  45. package/skills/whats-happening/references/reading-the-board.md +1 -1
  46. package/skills/whats-happening/references/status-reply.md +1 -1
  47. package/skills/whats-happening/references/why-is-it-stuck.md +1 -1
  48. package/skills/whats-happening/scripts/lib/cli.mjs +2 -2
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: connect-me
3
- description:
4
- Connect this machine to the customer's Catalyst Cloud tenant with their account key, cache the tenant contract, and verify. Use when a person is getting started, when their config is missing or broken, when they rotated their key, when a skill script exits 2 saying the machine is not connected, or when they ask which tenant this machine belongs to. The key names the tenant, so nobody types an account id. Installing the skills is not this skill's job; the agent's own install command did that.
3
+ description: >-
4
+ Connect this machine to the person's Catalyst Cloud tenant with their own personal key, cache the tenant contract, and verify. Use when a person is getting started, when their config is missing or broken, when they rotated their key, when a skill script exits 2 saying the machine is not connected, or when they ask which tenant this machine belongs to. The key names the tenant and the person, so nobody types an account id. Installing the skills is not this skill's job; the agent's own install command did that.
5
5
  disable-model-invocation: true
6
6
  allowed-tools: Bash(catalyst-skills:*) Bash(npx @catalyst-cloud/catalyst-skills:*)
7
7
  ---
@@ -9,28 +9,28 @@ allowed-tools: Bash(catalyst-skills:*) Bash(npx @catalyst-cloud/catalyst-skills:
9
9
 
10
10
  # Connect me
11
11
 
12
- Connecting is one command. It asks the cloud who the key belongs to, writes the config every skill and the CLI read, and caches the tenant contract beside it.
12
+ Connecting is one command. It asks the cloud who the key belongs to — which tenant, and which person — writes the config every skill and the CLI read, and caches the tenant contract beside it.
13
13
 
14
14
  ```sh
15
- CATALYST_CLOUD_TOKEN=<account-key> catalyst-skills login
15
+ CATALYST_CLOUD_TOKEN=<your-personal-key> catalyst-skills login
16
16
  ```
17
17
 
18
- With no environment variable and a terminal attached, `catalyst-skills login` prompts for the key without echoing it. `--key <account-key>` is the third form, for a script. `npx @catalyst-cloud/catalyst-skills login` works when the package is not installed globally. A non-default cloud is pinned with `CATALYST_CLOUD_BASE_URL` or `--base-url`.
18
+ With no environment variable and a terminal attached, `catalyst-skills login` prompts for the key without echoing it. `--key <personal-key>` is the third form, for a script. `npx @catalyst-cloud/catalyst-skills login` works when the package is not installed globally. A non-default cloud is pinned with `CATALYST_CLOUD_BASE_URL` or `--base-url`.
19
19
 
20
20
  **This skill never installs skills.** You are already reading one, so the person's agent installed the set with its own command. Connecting is only about the credential and the contract.
21
21
 
22
- **What it writes.** `~/.config/catalyst-cloud/customer.json` (mode 0600) holding the key, the tenant it resolved, and the absolute path of this CLI so skill scripts can spawn it; `~/.config/catalyst-cloud/contract.json`, the tenant contract with its ETag.
22
+ **What it writes.** `~/.config/catalyst-cloud/customer.json` (mode 0600) holding the key, the tenant it resolved, the person it resolved (`user`: id, label, role, Linear user id), and the absolute path of this CLI so skill scripts can spawn it; `~/.config/catalyst-cloud/contract.json`, the tenant contract with its ETag.
23
23
 
24
24
  **The replica is optional and one command away.** Nothing has to be running for reads, writes, asks or explanations; the API is origin-fresh. `catalyst-skills replica start --detach` starts the local replica for cheap repeated reads and ad hoc SQL; `login --start-replica` does the same at the end. Every skill checks `catalyst-skills replica status` first and falls back to the API when the replica is absent or stale, saying so.
25
25
 
26
26
  ## What you do
27
27
 
28
- 1. Ask the person for their account key. Their tenant admin mints it in settings; you cannot. A workstation key connects but is refused by the contract and by machine-only reads (a one-line notice, not a failure); tell them an account key is needed for the full set.
29
- 2. Run the login command. Its output names the tenant (`Connected to <name> (<slug>)`), the config path, and the cached contract version.
28
+ 1. Ask the person to mint their **personal key** at Settings → API keys in the Catalyst Cloud web app (every active member can; no admin is needed) and hand it to the login command. It is shown once. Never put it in a file, a ticket, or this conversation beyond that one command. Do not ask an admin for the tenant's **account key** (`ctc_acct_`, Settings → Account keys): that is a host credential — runners, daemons, the host replica — and a person connected with it has no name on anything their agent writes, and "what needs me" cannot mean them. If they connect with one anyway, login says so on stderr and still works.
29
+ 2. Run the login command. Its output names the tenant (`Connected to <name> (<slug>)`), the person (`Connected as <label> (<role>)`), the config path, and the cached contract version. If the person line says their Linear identity is not matched yet, tell them: an admin matches it in Settings → Members, and until then "what needs me" shows everyone's asks.
30
30
  3. Verify with `node scripts/verify-connection.mjs`: one line each for the tenant, the contract version, and the replica; exit 1 when the machine is not connected.
31
31
  4. Run `catalyst-skills ready` and read the verdict to them.
32
32
  5. Offer the replica: `catalyst-skills replica start --detach`, then `catalyst-skills replica status`. For keeping it alive across a reboot, load `references/keeping-the-replica-running.md`.
33
- 6. If login fails: a `401` means a stale or mistyped key, back to the tenant admin, never a retry loop; a network error names the URL, check `--base-url`. If login succeeds but prints a line naming two contract versions, the tenant serves a contract outside this bundle's range: update the bundle before using the other skills.
33
+ 6. If login fails: a `401` means a stale, mistyped or revoked key — mint a new one at Settings → API keys, never a retry loop; a network error names the URL, check `--base-url`. A `403` on the contract naming an older cloud means the cloud has not yet deployed personal-key access: update the cloud, or connect with the account key until it has. If login succeeds but prints a line naming two contract versions, the tenant serves a contract outside this bundle's range: update the bundle before using the other skills.
34
34
 
35
35
  ## The verbs a session runs first
36
36
 
@@ -1,6 +1,6 @@
1
1
  interface:
2
2
  display_name: "Connect me"
3
- short_description: "Connect this machine to your Catalyst Cloud tenant with your account key, cache the tenant contract, and verify"
3
+ short_description: "Connect this machine to your Catalyst Cloud tenant with your own personal key, cache the tenant contract, and verify"
4
4
  default_prompt: "Use $connect-me to connect this machine to my Catalyst Cloud tenant."
5
5
  policy:
6
6
  allow_implicit_invocation: false
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  // lib/cli.mjs — the one way a skill script reaches Catalyst Cloud: by spawning the catalyst-skills
3
- // CLI. The CLI holds the SDK and the account key; this file holds neither. It reads
3
+ // CLI. The CLI holds the SDK and the key; this file holds neither. It reads
4
4
  // ~/.config/catalyst-cloud/customer.json (under CATALYST_SKILLS_HOME when set, else HOME) for the
5
5
  // CLI path that login recorded and falls back to `npx @catalyst-cloud/catalyst-skills`.
6
6
  //
@@ -44,7 +44,7 @@ export function loadCustomerConfig() {
44
44
  export function requireConfigured() {
45
45
  const cfg = loadCustomerConfig();
46
46
  if (cfg) return cfg;
47
- console.error(`not connected: ${configPath()} is missing or unreadable — run: CATALYST_CLOUD_TOKEN=<account key> npx ${PACKAGE_NAME} login`);
47
+ console.error(`not connected: ${configPath()} is missing or unreadable — run: CATALYST_CLOUD_TOKEN=<your personal key> npx ${PACKAGE_NAME} login`);
48
48
  process.exit(NOT_CONFIGURED_EXIT);
49
49
  }
50
50
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: how-catalyst-works
3
- description:
3
+ description: >-
4
4
  How Catalyst Cloud runs a ticket on the customer's own tenant, as facts an agent loads on demand: the eight-phase ladder and what each phase produces, the eleven board slots and this team's live stage map, what happens when a phase fails (retry, backoff, Remediate, park), how the queue is ordered and routed and every reason a ticket is excluded, and the coding-account model. Use when a person asks "how does this work?", "why did it do that?", "why is this stuck?", "what runs next?" or "how does it prioritise?". Read-only; its scripts explain one ticket's eligibility in plain English, show what is running and queued, and print the tenant's stage map and thresholds straight from the contract.
5
5
  allowed-tools: Bash(catalyst-skills:*) Bash(npx @catalyst-cloud/catalyst-skills:*)
6
6
  ---
@@ -38,5 +38,5 @@ Exit codes: 0 answered, 1 not found or a usage error, 2 this machine is not conn
38
38
  - **A reason is a layer.** Translate an exclusion reason through `references/what-runs-next.md`; name what releases it and who can do that (a clock, a comment, a push, an operator).
39
39
  - **Unknown is not absent.** An `unknown` verdict from the explainer means the cloud could not look; report it as inconclusive.
40
40
  - **System causes are one alert.** A provider outage, the runner image breaker or a paused repository holds many tickets for one reason; never escalate it ticket by ticket.
41
- - **Say what a key cannot see.** Coding-account status and per-ticket execution history are not readable with an account key yet; the scripts say so and name the settings page. Do not fill the gap with a guess.
41
+ - **Say what a key cannot see.** A few PR facts are not mirrored (labels, the reviewer's reaction) and a park is released only by an operator; the scripts say so and name the settings page. Do not fill the gap with a guess.
42
42
  - **Depth lives elsewhere.** What a ticket accumulates in Linear is `catalyst-linear`; what a PR accumulates and whether it is mergeable is `catalyst-github`; raising a decision is `what-needs-me`.
@@ -1,6 +1,6 @@
1
1
  # Coding accounts: slots, windows, walls, and what a key cannot read yet
2
2
 
3
- This reference restates the model, which does not vary per tenant. Your tenant's actual accounts, their usage and their state are NOT readable with an account key today: `node scripts/whats-running.mjs --accounts` prints that by name, with the settings page where the facts live. When a tenant-facing read ships, the same script will print the live rows and this reference stays true.
3
+ This reference restates the model, which does not vary per tenant. Your tenant's actual accounts — provider, harness, declared and observed state, usage windows, walls, quarantine — are readable with your key: `node scripts/whats-running.mjs --accounts` prints the live rows (`catalyst-skills accounts`). No credential or email ever rides in that read; the settings page (`/settings/coding-accounts`) is where an admin enrols, pauses or removes one.
4
4
 
5
5
  ## What a slot is
6
6
 
@@ -45,7 +45,7 @@ Your tenant's coding-accounts page lists each slot with a five-value status, fir
45
45
  Coding-account status (provider, declared and observed state, window percentages and resets, walls, quarantine, live holds) is served only behind the tenant's admin gate. So when a human asks "why is nothing running?":
46
46
 
47
47
  1. Run `node scripts/explain-ticket.mjs <ticket>` for a stuck ticket. `routing_unavailable` with a detail naming a slot or provider, or `no_eligible_account_slot` in the routing block, points at accounts.
48
- 2. Say plainly that the account key cannot read account state, and give the settings link the script prints. Do not guess a wall or a quarantine from silence.
48
+ 2. Read the live rows with `catalyst-skills accounts` and say what they show; an empty list means no account is enrolled, and the script prints the settings link. Do not guess a wall or a quarantine from silence — a wall is the `walled` field, a quarantine is `quarantined` with its reason.
49
49
  3. Treat it as ONE fleet-level cause for every ticket it holds, never as a per-ticket escalation.
50
50
 
51
51
  The customer session never holds or mints a coding-account credential; phases run in the cloud on the enrolled accounts, and repository access is a per-phase installation token.
@@ -38,7 +38,7 @@ Which parks release themselves:
38
38
  | missing branch | its own budgeted release loop |
39
39
  | rebase conflict | its own budgeted release loop |
40
40
 
41
- An account key cannot release a park today; the repair verbs are operator-only. When a ticket is parked, say so, name the failure class the explainer shows, and hand the release to whoever administers the tenant.
41
+ Your key cannot release a park; the repair verbs are operator-only. When a ticket is parked, say so, name the failure class the explainer shows, and hand the release to whoever administers the tenant.
42
42
 
43
43
  ## Two holds that are not failures
44
44
 
@@ -47,7 +47,7 @@ An account key cannot release a park today; the repair verbs are operator-only.
47
47
 
48
48
  ## What a human sees on the ticket
49
49
 
50
- Each attempt posts a phase-outcome comment (complete or FAILED, with phase, attempt, artifact, a summary and any park or hold block) and each remediation round posts a remediate-attempt comment naming the failure class it is repairing. `catalyst-linear` describes the shapes. The round count of the cap and the park history are not readable with an account key yet; `catalyst-skills explain --history <ticket>` says so and names where to read them.
50
+ Each attempt posts a phase-outcome comment (complete or FAILED, with phase, attempt, artifact, a summary and any park or hold block) and each remediation round posts a remediate-attempt comment naming the failure class it is repairing. `catalyst-linear` describes the shapes. The attempt ledger, the round count against the cap and the park history are readable: `catalyst-skills explain --history <ticket>` prints them from the cloud's own relay ledger.
51
51
 
52
52
  ## Rule of thumb for answering "why is it stuck?"
53
53
 
@@ -8,7 +8,7 @@ import { join } from "node:path";
8
8
  import { pathToFileURL } from "node:url";
9
9
 
10
10
  export const PACKAGE = "@catalyst-cloud/catalyst-skills";
11
- export const CONNECT_HINT = `CATALYST_CLOUD_TOKEN=<account key> npx ${PACKAGE} login`;
11
+ export const CONNECT_HINT = `CATALYST_CLOUD_TOKEN=<your personal key> npx ${PACKAGE} login`;
12
12
 
13
13
  /** ~/.config/catalyst-cloud/customer.json, honouring CATALYST_SKILLS_HOME (used by tests) over HOME. */
14
14
  export function configPath() {
@@ -9,8 +9,7 @@ Prints what is executing on your tenant. Wraps: catalyst-skills running, queue,
9
9
 
10
10
  --queue also print the dispatch queue (what runs next, in order)
11
11
  --team <key> with --queue: one team's queue
12
- --accounts also print the coding-account line (today: where to read it, since an account key
13
- cannot see coding-account status yet)
12
+ --accounts also print the coding-account line (provider, state, windows — never a credential)
14
13
  --json one JSON document: { running, queue?, accounts? }
15
14
  --help this text
16
15
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: run-this-project
3
- description:
3
+ description: >-
4
4
  Own one Catalyst Cloud project end to end until it closes. Use when the person says "run this project for me", "own this until it ships", "keep this moving", or hands you a project id or a set of tickets to drive. Subscribes to the tenant stream for the scope through the catalyst-skills CLI, reacts to each change in the same turn, makes tickets ready and moves them to dispatch, parks what should stop, chases stalls, escalates inward, and keeps one status summary current. Writes to Linear as the app actor; never polls.
5
5
  disable-model-invocation: true
6
6
  allowed-tools: Bash(catalyst-skills:*) Bash(npx @catalyst-cloud/catalyst-skills:*)
@@ -42,4 +42,4 @@ Every script exits 2 when this machine is not connected (run `catalyst-skills lo
42
42
  - **Escalate inward.** Instrument, then you, then the desk, then the human as an ask filed through `what-needs-me` with what it blocks. Decide the technical calls yourself; take the sane default and record it; a fleet or provider condition is one note, never one ask per ticket.
43
43
  - **Reply where the message arrived,** in-thread, tagged, as the app actor. Never post as the human, never answer someone else's ask. Bookkeeping records take the contract's marker (`catalyst-skills write comment --bookkeeping`).
44
44
  - **One status summary,** kept current after every reaction: in flight, blocked and on whom, closed, next, each line with a ticket id. Where a human decision is pending, the line carries the ask's id.
45
- - **Say what a key cannot see.** Execution history and coding-account status are not visible to an account key yet; the CLI says so by name and points at settings. Do not guess in their place.
45
+ - **Say what a key cannot see.** A park is released only by an operator, and PR labels and reactions are not mirrored; the CLI says so by name and points at settings. Execution history (`explain --history`) and coding-account status (`accounts`) ARE readable — read them rather than reconstructing them from comments.
@@ -73,4 +73,4 @@ Start with `--from head` when you are picking up a project that has been running
73
73
 
74
74
  ## The honest limit
75
75
 
76
- The stream carries the mirror's entity changes. It does not carry the relay ledger's phase failures, parks, remediate rounds or backoff timers as first-class frames. Until a tenant-facing execution-history route ships, you learn those from the outcome comments the cloud posts on the ticket, which do arrive as `comments` frames: a phase-failed card names the phase, the attempt and the failure class; a remediate-attempt card names the round; a board-health comment names a stall the cloud itself noticed. For the current verdict on any ticket, ask the explainer: `catalyst-skills explain <ticket>` turns the exclusion reason and the last failure into one paragraph. `catalyst-skills explain --history <ticket>` says, by name, that the history is not visible to an account key yet and where in settings a human can read it.
76
+ The stream carries the mirror's entity changes. It does not carry the relay ledger's phase failures, parks, remediate rounds or backoff timers as first-class frames. Between frames you learn those from the outcome comments the cloud posts on the ticket, which do arrive as `comments` frames: a phase-failed card names the phase, the attempt and the failure class; a remediate-attempt card names the round; a board-health comment names a stall the cloud itself noticed. For the current verdict on any ticket, ask the explainer: `catalyst-skills explain <ticket>` turns the exclusion reason and the last failure into one paragraph. `catalyst-skills explain --history <ticket>` prints the per-phase attempt ledger, the remediation rounds against the cap, and any park with what releases it.
@@ -40,7 +40,7 @@ Where the explainer names a reason not in this table, it prints the raw reason;
40
40
 
41
41
  ## Capacity and fleet conditions are one note, not many asks
42
42
 
43
- When several tickets in scope are offered and nothing picks them up, or the explainer names a routing, slot, provider or image condition, the cause is shared: coding-account headroom, a provider outage, a paused repository, a poisoned runner image. Write one line in the status summary naming the condition and the tickets it holds. Do not file an ask per ticket. Coding-account status is not visible to an account key yet; `catalyst-skills accounts` says so and names the settings page where a human can read it, and that page, not you, is where the answer lives.
43
+ When several tickets in scope are offered and nothing picks them up, or the explainer names a routing, slot, provider or image condition, the cause is shared: coding-account headroom, a provider outage, a paused repository, a poisoned runner image. Write one line in the status summary naming the condition and the tickets it holds. Do not file an ask per ticket. `catalyst-skills accounts` reads coding-account status (state, usage windows, walls, quarantine); enrolling, pausing or removing an account is the settings page, not you.
44
44
 
45
45
  ## Escalate inward, never outward
46
46
 
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  // lib/cli.mjs — the one way a skill script reaches Catalyst Cloud: by spawning the catalyst-skills
3
- // CLI. The CLI holds the SDK and the account key; this file holds neither. It reads
3
+ // CLI. The CLI holds the SDK and the key; this file holds neither. It reads
4
4
  // ~/.config/catalyst-cloud/customer.json (under CATALYST_SKILLS_HOME when set, else HOME) for the
5
5
  // CLI path that login recorded and falls back to `npx @catalyst-cloud/catalyst-skills`.
6
6
  //
@@ -44,7 +44,7 @@ export function loadCustomerConfig() {
44
44
  export function requireConfigured() {
45
45
  const cfg = loadCustomerConfig();
46
46
  if (cfg) return cfg;
47
- console.error(`not connected: ${configPath()} is missing or unreadable — run: CATALYST_CLOUD_TOKEN=<account key> npx ${PACKAGE_NAME} login`);
47
+ console.error(`not connected: ${configPath()} is missing or unreadable — run: CATALYST_CLOUD_TOKEN=<your personal key> npx ${PACKAGE_NAME} login`);
48
48
  process.exit(NOT_CONFIGURED_EXIT);
49
49
  }
50
50
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: what-needs-me
3
- description:
3
+ description: >-
4
4
  The human's decision inbox on a Catalyst Cloud tenant, and the one way an agent raises a decision on their behalf. Use when the person asks "what needs me?", "what am I blocking?", or when active work is gated on a choice only they can make. Lists open asks ranked by what each answer releases, files an ask through the cloud's ask route with the tenant's own template, and records the answer so the held work releases. Never answers as the human, never duplicates an open ask.
5
5
  disable-model-invocation: true
6
6
  allowed-tools: Bash(catalyst-skills:*) Bash(npx @catalyst-cloud/catalyst-skills:*)
@@ -15,7 +15,7 @@ An ask is one decision only the human can make, filed as a ticket in their own L
15
15
 
16
16
  Scripts are run, never read. Each prints `--help`; exit 2 means this machine is not connected (run the `connect-me` skill), exit 1 means the check itself failed or an argument was missing.
17
17
 
18
- - `node scripts/inbox.mjs --help` — the open asks, ranked by the priority-weighted work each holds; `--json` for the rows.
18
+ - `node scripts/inbox.mjs --help` — the open asks assigned to the connected person, ranked by the priority-weighted work each holds; `--anyone` for the whole tenant; `--json` for `{scope, asks}`.
19
19
  - `node scripts/raise.mjs --help` — file one decision: `--team`, `--title`, `--option` (repeated), `--default`, and `--blocks` (repeated) or `--nothing-to-block`.
20
20
  - `node scripts/settle.mjs --help` — record the answering comment on an ask and post a release note on every ticket it held; `--close` moves the ask to the done slot.
21
21
 
@@ -17,7 +17,7 @@ So an ask that holds nothing is real, but the person may never see it in their o
17
17
 
18
18
  ## What the script reads
19
19
 
20
- `catalyst-skills ask list` reads the open tickets carrying the team's ask label (by the label ids and prefix the contract serves), follows each one's blocking relations to the tickets it holds, drops held tickets that are already terminal, and scores the rest by priority weight: urgent 4, high 3, medium 2, low 1, none 1. It does not filter by assignee, because the account key reads the tenant, not one person. When the human asks "what needs me", the answer is the ranked list; when they ask "what needs anyone", it is the same list.
20
+ `catalyst-skills ask list` reads the open tickets carrying the team's ask label (by the label ids and prefix the contract serves), follows each one's blocking relations to the tickets it holds, drops held tickets that are already terminal, and scores the rest by priority weight: urgent 4, high 3, medium 2, low 1, none 1. It filters to **the connected person** by default: `login` recorded who they are and their Linear user id, and the list keeps only asks assigned to that id. `--anyone` lists the whole tenant. The JSON answer carries a `scope` — `mine` (with the label and Linear id), `anyone`, `unmatched` (the person's Linear identity is not matched yet: an admin does that in Settings → Members, and until then the whole list is shown with a stderr line saying so), or `no-person` (the machine is connected with the tenant's account key, which names nobody: the whole list, with a line saying to log in with a personal key). Read the scope before presenting the list, and say which you got: "what needs me" is the `mine` list, "what needs anyone" is `--anyone`, and an empty `mine` list names the wider count so it never reads as "nothing needs anyone".
21
21
 
22
22
  ## Presenting the queue
23
23
 
@@ -2,18 +2,20 @@
2
2
  // inbox.mjs — "what needs me?": the open asks on this tenant, ranked by what each answer releases.
3
3
  // A thin wrapper over `catalyst-skills ask list`, which reads the open tickets carrying the team's
4
4
  // ask label (from the contract), follows each one's blocking relations, and weights held work by
5
- // priority. Prints the ranked list; --json prints the CLI's rows unchanged.
5
+ // priority. By default the CLI keeps only the asks assigned to the connected person; --anyone widens
6
+ // to the whole tenant. Prints the ranked list; --json prints the CLI's {scope, asks} unchanged.
6
7
  import { mustRun, parseFlags, parseJson, printHelp } from "./lib/cli.mjs";
7
8
 
8
9
  const SPEC = {
9
- json: { value: false, help: "print the ranked rows as JSON: {identifier, title, state, blocks[], score}" },
10
+ json: { value: false, help: "print the CLI's answer as JSON: {scope, asks: [{identifier, title, state, blocks[], score, assigneeId}]}" },
10
11
  team: { value: true, help: "only asks whose identifier carries this team key" },
11
12
  all: { value: false, help: "include asks that hold nothing (by default they are listed last, marked)" },
13
+ anyone: { value: false, help: "every open ask in the tenant, not only the ones assigned to you" },
12
14
  };
13
15
 
14
16
  const { help, flags } = parseFlags(process.argv.slice(2), SPEC);
15
17
  if (help) {
16
- printHelp("node scripts/inbox.mjs [--json] [--team K] [--all] [--help]", SPEC, [
18
+ printHelp("node scripts/inbox.mjs [--json] [--team K] [--all] [--anyone] [--help]", SPEC, [
17
19
  "Rank: the sum over held open tickets of a priority weight (urgent 4 ... low 1, none 1), highest first.",
18
20
  "An ask that holds nothing is real but will not appear in the tenant's Waiting-on-me view; it is",
19
21
  "listed last with a marker so you can attach the work it should block (references/reading-the-inbox.md).",
@@ -21,14 +23,21 @@ if (help) {
21
23
  process.exit(0);
22
24
  }
23
25
 
24
- const rows = parseJson(mustRun(["ask", "list", "--json"], { quiet: true }).stdout, "ask list");
26
+ const answer = parseJson(mustRun(["ask", "list", "--json", ...(flags.anyone ? ["--anyone"] : [])], { quiet: true }).stdout, "ask list");
27
+ const rows = answer.asks;
28
+ const scope = answer.scope;
25
29
  const wanted = flags.team ? rows.filter((r) => String(r.identifier).toUpperCase().startsWith(`${flags.team.toUpperCase()}-`)) : rows;
26
30
  if (flags.json) {
27
- process.stdout.write(JSON.stringify(wanted) + "\n");
31
+ process.stdout.write(JSON.stringify({ scope, asks: wanted }) + "\n");
28
32
  process.exit(0);
29
33
  }
34
+ // Say whose list this is before the list, so an empty "mine" never reads as "nothing needs anyone".
35
+ if (scope.kind === "mine") process.stdout.write(`asks assigned to ${scope.label}:\n`);
36
+ else if (scope.kind === "anyone") process.stdout.write("every open ask in the tenant:\n");
37
+ else if (scope.kind === "unmatched") process.stdout.write(`every open ask (your Linear identity is not matched yet — an admin matches it in Settings → Members):\n`);
38
+ else process.stdout.write("every open ask (connected with the tenant's account key, which names no person — log in with your personal key to see only yours):\n");
30
39
  if (wanted.length === 0) {
31
- process.stdout.write("nothing needs you: no open asks\n");
40
+ process.stdout.write(scope.kind === "mine" ? "nothing needs you: no open asks assigned to you (--anyone lists the tenant's)\n" : "nothing needs anyone: no open asks\n");
32
41
  process.exit(0);
33
42
  }
34
43
  const holding = wanted.filter((r) => r.blocks.length > 0);
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  // lib/cli.mjs — the one way a skill script reaches Catalyst Cloud: spawn the catalyst-skills CLI.
3
- // The CLI holds the SDK and the account key; this file holds neither. It reads customer.json only
3
+ // The CLI holds the SDK and the key; this file holds neither. It reads customer.json only
4
4
  // to learn where the CLI lives, and it exits 2 with one line when the machine is not connected.
5
5
  // Run any script beside this one with --help; this file is a library and is never run directly.
6
6
  import { spawnSync } from "node:child_process";
@@ -30,7 +30,7 @@ export function loadConfig() {
30
30
  }
31
31
 
32
32
  function notConfigured(why) {
33
- process.stderr.write(`not connected (${why}) — run: CATALYST_CLOUD_TOKEN=<account key> npx ${PACKAGE} login\n`);
33
+ process.stderr.write(`not connected (${why}) — run: CATALYST_CLOUD_TOKEN=<your personal key> npx ${PACKAGE} login\n`);
34
34
  process.exit(NOT_CONFIGURED_EXIT);
35
35
  }
36
36
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: whats-happening
3
- description:
3
+ description: >-
4
4
  The desk for a Catalyst Cloud tenant. Use when the person asks "what's happening?", "where are we?", "why is that stuck?", "what closed?", "what's next?", or asks for something to be done rather than known. Reads the tenant contract, what is running and queued, the eligibility explainer and the open asks through the catalyst-skills CLI, and answers in one reply with ticket ids. Routes work to a project owner and decisions to what-needs-me. Never composes a URL, never polls, never answers as the human.
5
5
  allowed-tools: Bash(catalyst-skills:*) Bash(npx @catalyst-cloud/catalyst-skills:*)
6
6
  ---
@@ -33,10 +33,10 @@ For depth beyond these, load the fact skills: `how-catalyst-works` (the ladder,
33
33
 
34
34
  ## Rules
35
35
 
36
- - **Their tenant only.** Every read goes through the CLI, which holds the account key and the tenant. You never name, guess at, or try another tenant, and you never paste the key anywhere.
36
+ - **Their tenant, as them.** Every read goes through the CLI, which holds the person's own key, the tenant and who they are. You never name, guess at, or try another tenant, and you never paste the key anywhere. "You" in your reply means the connected person: their assigned tickets, their asks.
37
37
  - **Tenant facts come from the contract, live.** Stage names, label names, team keys, thresholds and the ladder are in the snapshot's `tenant` block; read them there each time and never restate them from memory.
38
38
  - **One reply, ticket ids on every line, source named.** The reply opens with when the snapshot was taken and whether the replica or the API answered. A stale replica is stated, never hidden.
39
- - **Say what a key cannot see.** Coding-account status and per-ticket execution history are not visible to an account key yet; the CLI prints the settings URL, and you repeat it instead of guessing.
39
+ - **Say what a key cannot see.** PR labels and reactions are not mirrored, and a park is released only by an operator; the CLI prints the settings URL, and you repeat it instead of guessing. Coding-account status (`accounts`) and per-ticket execution history (`explain --history`) are readable — read them.
40
40
  - **No polling.** One snapshot per question. Waiting on a change is the project owner's job (`run-this-project` subscribes to the tenant stream); the desk never loops a read.
41
41
  - **You are not the owner.** You route work and make it visible; you do not dispatch, overrule a project owner, or run long work in this session.
42
42
  - **Never answer as the human.** A decision is an ask through `what-needs-me`, filed before anyone proceeds on its default; the answer is recorded there as the app actor.
@@ -57,7 +57,7 @@
57
57
  },
58
58
  "cannotSee": {
59
59
  "type": "array",
60
- "description": "Facts the account key cannot read yet, named, with where the human can read them (the CLI prints the URL).",
60
+ "description": "Facts your key cannot read (PR labels and reactions; an operator-only park release), named, with where the human can read them (the CLI prints the URL).",
61
61
  "items": { "type": "string" }
62
62
  }
63
63
  },
@@ -35,7 +35,7 @@ Everything else is **waiting**, and the reply says what it is waiting on. Callin
35
35
 
36
36
  ## The signals the cloud posts on the ticket itself
37
37
 
38
- Before declaring anything, read the ticket's comments (`catalyst-skills query issue <id>`; the `catalyst-linear` skill explains each shape). The cloud posts a phase-outcome card on every completion and failure, a remediate-attempt card per repair round, a board-health note when it detects a stall itself, and a merge-wait note when a merge is held. Those comments are the execution history a key can read today; the per-ticket ledger behind them is not visible to an account key yet, and `explain --history` says so.
38
+ Before declaring anything, read the ticket's comments (`catalyst-skills query issue <id>`; the `catalyst-linear` skill explains each shape). The cloud posts a phase-outcome card on every completion and failure, a remediate-attempt card per repair round, a board-health note when it detects a stall itself, and a merge-wait note when a merge is held. Those comments are the narrative; the per-ticket ledger behind them — attempts, rounds against the cap, park state — is `catalyst-skills explain --history <ticket>`, and the two must agree.
39
39
 
40
40
  ## Two things that look like work and are not
41
41
 
@@ -14,7 +14,7 @@ The person asked one question and gets one reply. If they would need a second su
14
14
  4. **Closed.** What reached the done slot in the window the person asked about (or since your last reply). Source: `query issues` filtered by the team's done-slot stage name from the contract, or the change feed for a time window. When you did not read a window, say "since my last reply" and mean it.
15
15
  5. **Next.** What the queue picks up next, in the cloud's order, with the phase each will run. Source: the snapshot's `queue` block. Do not reorder it to what you think should be next; the levers are in `references/reprioritising.md`.
16
16
 
17
- A sixth block, **cannot see**, appears only when it is non-empty: the facts an account key cannot read yet (coding-account status, per-ticket execution history), each with the URL the CLI printed.
17
+ A sixth block, **cannot see**, appears only when it is non-empty: the facts your key cannot read (PR labels and reactions, which are not mirrored; an operator-only park release), each with the URL the CLI printed.
18
18
 
19
19
  ## The header line
20
20
 
@@ -38,7 +38,7 @@ This reference restates an invariant: the vocabulary the cloud's eligibility exp
38
38
 
39
39
  | reason | what it means | note |
40
40
  | -- | -- | -- |
41
- | `cooling_down` (parked after repeated failures, or the round cap was spent) | the phase is parked and does not release itself | an operator unparks it; an account key has no unpark verb yet, so the reply names the park and the settings page |
41
+ | `cooling_down` (parked after repeated failures, or the round cap was spent) | the phase is parked and does not release itself | an operator unparks it; your key has no unpark verb, so the reply names the park (from `explain --history`) and the settings page |
42
42
  | `remediate_parked` | the repair phase itself is parked, so the failing phase has nowhere to be repaired | as above |
43
43
  | `validate_class_spent` | this validate failure already spent its one repair round in this episode | as above; a human comment may release the hold |
44
44
  | `no_branch_to_remediate` / `branch_missing` / `branch_gone` | a branch-dependent phase has no branch to clone | the cloud releases missing-branch parks on its own budget; a deleted branch needs a human to decide |
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  // lib/cli.mjs — the one way a skill script reaches Catalyst Cloud: spawn the catalyst-skills CLI.
3
- // The CLI holds the SDK and the account key; this file holds neither. It reads customer.json only
3
+ // The CLI holds the SDK and the key; this file holds neither. It reads customer.json only
4
4
  // to learn where the CLI lives, and it exits 2 with one line when the machine is not connected.
5
5
  // Run any script beside this one with --help; this file is a library and is never run directly.
6
6
  import { spawnSync } from "node:child_process";
@@ -30,7 +30,7 @@ export function loadConfig() {
30
30
  }
31
31
 
32
32
  function notConfigured(why) {
33
- process.stderr.write(`not connected (${why}) — run: CATALYST_CLOUD_TOKEN=<account key> npx ${PACKAGE} login\n`);
33
+ process.stderr.write(`not connected (${why}) — run: CATALYST_CLOUD_TOKEN=<your personal key> npx ${PACKAGE} login\n`);
34
34
  process.exit(NOT_CONFIGURED_EXIT);
35
35
  }
36
36