@catalyst-cloud/cli 0.13.0 → 0.14.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 (149) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md +27 -30
  3. package/dist/args.js +299 -61
  4. package/dist/ask.js +30 -18
  5. package/dist/capabilities.js +7 -0
  6. package/dist/cli.js +125 -20
  7. package/dist/config.js +3 -1
  8. package/dist/env/draft.js +134 -0
  9. package/dist/env/legacy.js +54 -0
  10. package/dist/env/parse-env.js +50 -0
  11. package/dist/env/settings-toml.js +66 -0
  12. package/dist/env.js +126 -26
  13. package/dist/environment.js +1 -1
  14. package/dist/legacy.js +224 -0
  15. package/dist/onboard-consent.js +65 -0
  16. package/dist/onboard.js +836 -0
  17. package/dist/project.js +191 -0
  18. package/dist/ready.js +11 -1
  19. package/dist/release.js +1 -1
  20. package/dist/repo.js +297 -0
  21. package/dist/runtime-verb.js +1 -1
  22. package/dist/secret.js +25 -4
  23. package/dist/skill-shape.js +21 -13
  24. package/dist/skills.js +44 -4
  25. package/dist/transport.js +26 -1
  26. package/dist/var.js +118 -0
  27. package/package.json +6 -4
  28. package/skills/catalyst-github/SKILL.md +7 -7
  29. package/skills/catalyst-github/references/is-it-mergeable.md +8 -2
  30. package/skills/catalyst-github/references/what-a-pr-accumulates.md +3 -3
  31. package/skills/catalyst-github/scripts/is-it-mergeable.mjs +3 -3
  32. package/skills/catalyst-github/scripts/lib/cli.mjs +9 -7
  33. package/skills/catalyst-github/scripts/lib/credential.mjs +2 -2
  34. package/skills/catalyst-github/scripts/read-pr.mjs +2 -2
  35. package/skills/catalyst-linear/SKILL.md +17 -19
  36. package/skills/catalyst-linear/agents/openai.yaml +1 -1
  37. package/skills/catalyst-linear/agents/portability.yaml +1 -1
  38. package/skills/catalyst-linear/references/reading-a-ticket.md +9 -26
  39. package/skills/catalyst-linear/references/what-a-ticket-accumulates.md +2 -2
  40. package/skills/catalyst-linear/references/writing-to-linear.md +7 -9
  41. package/skills/catalyst-linear/scripts/comment.mjs +1 -1
  42. package/skills/catalyst-linear/scripts/create-ticket.mjs +1 -1
  43. package/skills/catalyst-linear/scripts/label.mjs +1 -1
  44. package/skills/catalyst-linear/scripts/lib/cli.mjs +9 -7
  45. package/skills/catalyst-linear/scripts/lib/credential.mjs +2 -2
  46. package/skills/catalyst-linear/scripts/move.mjs +1 -1
  47. package/skills/catalyst-linear/scripts/read-ticket.mjs +1 -1
  48. package/skills/catalyst-linear/scripts/search.mjs +1 -1
  49. package/skills/catalyst-onboard/SKILL.md +37 -57
  50. package/skills/catalyst-onboard/agents/openai.yaml +2 -2
  51. package/skills/catalyst-onboard/agents/portability.yaml +1 -1
  52. package/skills/catalyst-onboard/references/connecting-this-machine.md +35 -0
  53. package/skills/catalyst-onboard/references/declaring-a-repository.md +18 -21
  54. package/skills/catalyst-onboard/references/local-sync.md +19 -7
  55. package/skills/catalyst-onboard/references/reading-ready.md +79 -0
  56. package/skills/catalyst-onboard/references/replacing-a-credential.md +8 -33
  57. package/skills/catalyst-onboard/references/repository-agent-setup.md +23 -0
  58. package/skills/catalyst-onboard/references/skill-sources.md +13 -19
  59. package/skills/catalyst-onboard/references/the-one-path.md +18 -74
  60. package/skills/catalyst-onboard/references/what-a-phase-needs.md +21 -28
  61. package/skills/catalyst-onboard/references/what-the-browser-owns.md +20 -37
  62. package/skills/{catalyst-setup → catalyst-onboard}/scripts/check.mjs +10 -9
  63. package/skills/catalyst-onboard/scripts/lib/cli.mjs +6 -4
  64. package/skills/catalyst-onboard/scripts/lib/credential.mjs +2 -2
  65. package/skills/catalyst-onboard/scripts/lib/project-coverage.mjs +53 -0
  66. package/skills/catalyst-onboard/scripts/where-am-i.mjs +929 -184
  67. package/skills/run-this-project/SKILL.md +23 -25
  68. package/skills/run-this-project/agents/openai.yaml +1 -1
  69. package/skills/run-this-project/agents/portability.yaml +1 -1
  70. package/skills/run-this-project/references/making-work-ready.md +20 -37
  71. package/skills/run-this-project/references/reacting-to-events.md +25 -48
  72. package/skills/run-this-project/references/stalls-and-escalation.md +20 -42
  73. package/skills/run-this-project/scripts/lib/cli.mjs +7 -5
  74. package/skills/run-this-project/scripts/lib/credential.mjs +2 -2
  75. package/skills/run-this-project/scripts/scope-status.mjs +0 -0
  76. package/skills/run-this-project/scripts/watch-scope.mjs +1 -1
  77. package/skills/unstick/SKILL.md +12 -12
  78. package/skills/unstick/agents/openai.yaml +1 -1
  79. package/skills/unstick/agents/portability.yaml +1 -1
  80. package/skills/unstick/references/playbook.md +13 -13
  81. package/skills/unstick/scripts/lib/cli.mjs +6 -4
  82. package/skills/unstick/scripts/lib/credential.mjs +2 -2
  83. package/skills/unstick/scripts/unstick.mjs +1 -1
  84. package/skills/what-needs-me/SKILL.md +12 -14
  85. package/skills/what-needs-me/agents/openai.yaml +2 -2
  86. package/skills/what-needs-me/agents/portability.yaml +1 -1
  87. package/skills/what-needs-me/references/raising-a-decision.md +8 -16
  88. package/skills/what-needs-me/references/reading-the-inbox.md +6 -13
  89. package/skills/what-needs-me/references/settling-an-answer.md +6 -12
  90. package/skills/what-needs-me/scripts/inbox.mjs +14 -13
  91. package/skills/what-needs-me/scripts/lib/cli.mjs +6 -4
  92. package/skills/what-needs-me/scripts/lib/credential.mjs +2 -2
  93. package/skills/what-needs-me/scripts/raise.mjs +1 -1
  94. package/skills/what-needs-me/scripts/settle.mjs +1 -1
  95. package/skills/what-this-repo-needs/SKILL.md +10 -19
  96. package/skills/what-this-repo-needs/references/what-each-group-means.md +14 -44
  97. package/skills/what-this-repo-needs/scripts/check.mjs +13 -14
  98. package/skills/what-this-repo-needs/scripts/inventory.mjs +2 -2
  99. package/skills/what-this-repo-needs/scripts/lib/cli.mjs +11 -9
  100. package/skills/what-this-repo-needs/scripts/lib/credential.mjs +2 -2
  101. package/skills/whats-happening/SKILL.md +20 -30
  102. package/skills/whats-happening/agents/openai.yaml +1 -1
  103. package/skills/whats-happening/references/coding-accounts.md +11 -0
  104. package/skills/whats-happening/references/routing-work.md +4 -33
  105. package/skills/whats-happening/references/settings-and-where-they-live.md +17 -0
  106. package/skills/whats-happening/references/stages-and-mapping.md +19 -0
  107. package/skills/whats-happening/references/status-reply.md +11 -31
  108. package/skills/whats-happening/references/the-ladder.md +20 -0
  109. package/skills/whats-happening/references/what-runs-next.md +13 -0
  110. package/skills/whats-happening/references/when-a-phase-fails.md +21 -0
  111. package/skills/whats-happening/references/why-is-it-stuck.md +38 -62
  112. package/skills/whats-happening/scripts/explain.mjs +1 -1
  113. package/skills/whats-happening/scripts/lib/cli.mjs +7 -5
  114. package/skills/whats-happening/scripts/lib/credential.mjs +2 -2
  115. package/skills/{how-catalyst-works → whats-happening}/scripts/show-my-map.mjs +18 -32
  116. package/skills/whats-happening/scripts/snapshot.mjs +10 -6
  117. package/dist/env/declaration-rules.js +0 -163
  118. package/skills/catalyst-onboard/references/choosing-a-coding-account.md +0 -52
  119. package/skills/catalyst-onboard/references/who-fixes-what.md +0 -64
  120. package/skills/catalyst-setup/SKILL.md +0 -36
  121. package/skills/catalyst-setup/agents/openai.yaml +0 -6
  122. package/skills/catalyst-setup/agents/portability.yaml +0 -4
  123. package/skills/catalyst-setup/references/what-each-check-means.md +0 -88
  124. package/skills/catalyst-setup/scripts/lib/cli.mjs +0 -103
  125. package/skills/catalyst-setup/scripts/lib/credential.mjs +0 -29
  126. package/skills/catalyst-setup/scripts/replica-status.mjs +0 -46
  127. package/skills/connect-me/SKILL.md +0 -63
  128. package/skills/connect-me/agents/openai.yaml +0 -6
  129. package/skills/connect-me/agents/portability.yaml +0 -5
  130. package/skills/connect-me/references/keeping-the-replica-running.md +0 -88
  131. package/skills/connect-me/scripts/lib/cli.mjs +0 -185
  132. package/skills/connect-me/scripts/lib/credential.mjs +0 -29
  133. package/skills/connect-me/scripts/verify-connection.mjs +0 -68
  134. package/skills/how-catalyst-works/SKILL.md +0 -45
  135. package/skills/how-catalyst-works/agents/openai.yaml +0 -6
  136. package/skills/how-catalyst-works/agents/portability.yaml +0 -4
  137. package/skills/how-catalyst-works/references/coding-accounts.md +0 -51
  138. package/skills/how-catalyst-works/references/settings-and-where-they-live.md +0 -20
  139. package/skills/how-catalyst-works/references/stages-and-mapping.md +0 -56
  140. package/skills/how-catalyst-works/references/the-ladder.md +0 -41
  141. package/skills/how-catalyst-works/references/what-catalyst-is.md +0 -30
  142. package/skills/how-catalyst-works/references/what-runs-next.md +0 -95
  143. package/skills/how-catalyst-works/references/when-a-phase-fails.md +0 -57
  144. package/skills/how-catalyst-works/scripts/explain-ticket.mjs +0 -41
  145. package/skills/how-catalyst-works/scripts/lib/cli.mjs +0 -164
  146. package/skills/how-catalyst-works/scripts/lib/credential.mjs +0 -29
  147. package/skills/how-catalyst-works/scripts/whats-running.mjs +0 -65
  148. package/skills/whats-happening/references/reading-the-board.md +0 -43
  149. package/skills/whats-happening/references/reprioritising.md +0 -37
@@ -1,15 +1,27 @@
1
- # Optional local events and replica
1
+ # The optional local replica and event cache
2
2
 
3
- **For:** a person who wants an on-machine event file and searchable replica. The normal API-backed skills work without this, so ask before starting a background writer.
3
+ The replica is an on-machine SQLite copy of the account for cheap repeated reads and ad hoc SQL; the event cache holds recent events. Every skill works without them through the API, which is origin-fresh. Start a background writer only when the person asks for local data.
4
4
 
5
- **You run:** `node scripts/local-sync.mjs` to show the current local state. Only if the person opts in, run `node scripts/local-sync.mjs --start`. The script uses `catalyst replica start --detach`, whose writer also starts the local event cache. It waits up to 90 seconds; `--wait <seconds>` sets a bounded wait from 0 to 300.
5
+ ## The replica's exit codes
6
6
 
7
- **Read back:** `Local sync current` only when both the replica and event cache have live writer heartbeats and each cursor equals its own cloud head. A detached process starting, one fresh heartbeat alone, or replica freshness alone does not prove event freshness. `catalyst replica status --probe --json` checks the replica cursor; `catalyst events status --probe --json` checks the separate event cursor. Either command can report stale or unknown; unknown means the cloud comparison could not be proved, not that the cache is stale. Exit 0 means current, 1 stale, 2 unknown or not connected, and 3 absent. Do not tell the person local data is current unless the combined check says so.
7
+ `catalyst replica status` needs no network. Exit 0 is fresh (a live writer, a heartbeat under 15 seconds, a cursor), and skills read the replica. Exit 1 is stale and 3 is absent; skills read the API, and `catalyst replica start --detach` restarts a stale one. Exit 2 is not connected (`references/connecting-this-machine.md`). `--probe` adds one network call comparing the local cursor with the cloud head. Every read verb names its source on standard error.
8
8
 
9
- **Owner:** you check and, with the person's opt-in, start. The local writer is optional. A reboot recovery service is separate work; if this machine restarts, recheck status before relying on local data.
9
+ ## Checking and starting both
10
+
11
+ `node scripts/local-sync.mjs` shows the local state. Only after the person opts in, `--start` starts the replica and event cache writers and waits up to 90 seconds (`--wait <seconds>`, 0 to 300).
12
+
13
+ Say `Local sync current` only when both writers have live heartbeats and each cursor equals its cloud head. A detached process starting, one fresh heartbeat, or replica freshness alone does not prove event freshness. `catalyst replica status --probe --json` checks the replica cursor; `catalyst events status --probe --json` checks the separate event cursor. Unknown means the comparison could not be proved, which is not stale. The script exits 0 current, 1 stale, 3 absent, and 2 for "not connected" or "unknown", with a printed reason. After a restart, check again before relying on local data.
10
14
 
11
15
  ## First ticket event
12
16
 
13
- Ask before starting the local writer. Before the person moves a card, run `node scripts/local-sync.mjs --start` after they opt in and wait until it reports current. Then run `catalyst events status --probe --json` and record its `cursor` as `<cursor-before-move>`. Move the card only after this baseline is captured. Once the card is moved, run `catalyst events wait-for --ticket <ticket-identifier> --after <cursor-before-move> --timeout 300` with the identifier `explain` printed. Do not guess an event type. The explicit cursor lets `wait-for` find the event if it reached the local cache before the command began.
17
+ Before the person moves a card, run `node scripts/local-sync.mjs --start` (after they opt in) and wait until it reports current. Then run `catalyst events status --probe --json` and record its `cursor` as `<cursor-before-move>`. Move the card only after this baseline is captured. Then run `catalyst events wait-for --ticket <ticket-identifier> --after <cursor-before-move> --timeout 300` with the identifier `explain` printed, and no guessed event type. The explicit cursor finds an event that reached the cache before the command began.
18
+
19
+ Exit 0 prints a matching event after the baseline, proving it reached this machine's cache. Exit 1 means no matching cached event arrived within five minutes; recheck `node scripts/local-sync.mjs` and report stale or unknown evidence without inferring a cloud or webhook failure. Exit 3 means the event cache is absent; ask before starting it. Other errors are unknown. `explain` stays the API-backed answer to why a ticket can or cannot run.
20
+
21
+ ## The writer
22
+
23
+ `catalyst replica --help` lists `start`, `stop`, `sql` and `schema`. It needs Node 22.15 or newer, or bun 1.4 or newer, and its files stay bounded under `~/.config/catalyst-cloud/`. The first start seeds the whole snapshot before going live, so `status` reads stale until the cursor appears; ask again after the live line, or watch `status --probe` count down. The lock refuses a second writer on the same file.
24
+
25
+ The writer backs off after a failed snapshot pull and gives up after five consecutive snapshot failures; `catalyst replica status` and `catalyst ready` then name the stopped state, the last error and the restart command, and the file reads stale (exit 1).
14
26
 
15
- Exit 0 prints a matching event after the recorded baseline and proves it reached this machine's cache. Exit 1 means no matching cached event arrived within five minutes; recheck `node scripts/local-sync.mjs` and report stale or unknown evidence without inferring a cloud or webhook failure. Exit 3 means the event cache is absent; ask before starting it. Other errors are unknown. `explain` remains the API-backed source for why a ticket can or cannot run.
27
+ To survive a reboot, run `catalyst replica start` without `--detach` under the platform's supervisor: a launchd agent with `KeepAlive` on macOS, a systemd user unit with `Restart=on-failure` on Linux (plus `loginctl enable-linger $USER` to run while logged out), or a Task Scheduler task at logon on Windows.
@@ -0,0 +1,79 @@
1
+ # Reading `catalyst ready`: what each check proves and who fixes it
2
+
3
+ Read this before telling a person something is not ready or what to do about it. `catalyst ready` prints one verdict over the machine and every project; `node scripts/check.mjs` adds each failure's fix and owner and a "who can click what" list.
4
+
5
+ ## The parts, and the instrument that owns each
6
+
7
+ | part | instrument | a pass does not prove |
8
+ | -- | -- | -- |
9
+ | **machine** | `catalyst status`, and the machine checks of `ready` | anything about the cloud account |
10
+ | **person** | `catalyst me`, `catalyst connections personal <linear|github> status` | an active seat (an owner or admin fixes it in Settings → Members) |
11
+ | **account** | `catalyst contract --path account` (a resolved Linear workspace) | that the GitHub App is installed |
12
+ | **project** | `catalyst team list`, then `team check <KEY>` and the `team:` checks of `ready` | that an unchecked team is ready |
13
+ | **repository** | `catalyst contract --path merge.repositories` | that it is active, attached to a project, or declared |
14
+ | **repository declarations** | `environment_declared` in `catalyst contract --path teams` | that the values behind the names exist |
15
+ | **coding accounts**, **host** | `references/what-a-phase-needs.md` | that a phase has headroom |
16
+
17
+ ⛔ **An empty contract project list means nothing is mapped yet**; pick one from `catalyst team list`. `team check --all` checks every team and may file an ask for each. ⛔ **A registered repository is not a dispatchable one**; if a card does not start, `catalyst explain <ticket>` names the reason.
18
+
19
+ ## Triaging NOT READY
20
+
21
+ Split the verdict first. In `catalyst ready --json`, an id that begins with `team:` is a **project** finding; the rest are **machine** findings. Report the two groups separately, machine first, each with its owner, its `pass`, `fail` and `unknown` counts, and when each team verdict was computed (`teams[].readiness.checkedAt`, null before any pass).
22
+
23
+ - **A machine check failed:** the person's, here, now. Do its `fix` line.
24
+ - **A project check failed:** name the check, the project and the `who`. A mapping is repaired with `catalyst team check`, `team map` or `team adopt`; a Linear connection, permission or team setting in a browser. Re-running `ready` fixes nothing.
25
+ - **A note** never moves the verdict; waiting is not failing, and unknown is not a pass.
26
+
27
+ End every readiness answer with the verdict and the who-can-click-what list, in that order. Run each check once; waiting for one to clear is the project owner's watch (`run-this-project`).
28
+
29
+ ## The checks
30
+
31
+ The contract's `readinessChecks[]` is the list of record, with each check's severity; `teams[].readiness` holds each team's states. A check listed there and not here is newer than this page: `node scripts/check.mjs` still prints its line, fix and owner, so read that and say you did.
32
+
33
+ A team is `ready`, `degraded`, `blocked` or `unchecked` (no pass yet, a note). Severity decides whether a failing check blocks, degrades or only informs; an unknown (the engine could not look) degrades regardless. Readiness is stamped with the mapping revision it read, so a stale verdict shows as stale.
34
+
35
+ | check id | proves | when it fails | who clicks |
36
+ | -- | -- | -- | -- |
37
+ | `oauth_scope` | the Linear connection has the permissions it needs | re-authorise it | owner or admin, in settings |
38
+ | `token_live` | the Linear connection is accepted now | reconnect if expired, revoked or never connected; re-check if Linear was unreachable | owner or admin |
39
+ | `team_visible` | Catalyst can see the team | usually it went private: grant access in Linear | owner or admin, in Linear |
40
+ | `mapped_states_exist` | every mapped stage still exists | `catalyst team map <KEY>`; `stages_pending_write` means a mapping was just saved, so wait | owner or admin |
41
+ | `mapping_total` | every stage Catalyst moves tickets into is mapped | map them ("absent": never mapped) | owner or admin |
42
+ | `types_compatible` | each load-bearing stage is the right kind (dispatch and intake unstarted or backlog, PR started, done completed, canceled canceled) | map a stage of the right kind | owner or admin |
43
+ | `labels_present` | Catalyst's labels exist | none: they are created on first use | nobody |
44
+ | `writes_land` | Catalyst has written to the team | `no_write_observed` clears on the first move; a refused write: check the connection and permissions | owner or admin when refused; otherwise nobody |
45
+ | `webhook_covers_team` | the team's events arrive | `no_delivery_observed` clears once a registered repository's events flow | owner or admin, by registering the repository |
46
+ | `hosts_current` | no connected host runs an older mapping | `references/what-a-phase-needs.md`; `no_host_connected` is waiting | whoever runs that host |
47
+ | `environment_declared` | the default repository's `.catalyst/catalyst.toml` is ingested, valid and approved | the reason names the step: register a default repository, commit or fix the file, or approve it (`references/declaring-a-repository.md`) | owner or admin, except committing the file, which is whoever can push |
48
+ | `tools_resolvable` | every MCP server and CLI the declaration names resolves | `tool_reference_unresolved`: add the secret or fix the declaration; `toolchain_cli_missing` is not self-service | owner or admin, in the declaration or Settings → Environment |
49
+ | `reviewer_required` | the repository can merge under its policy | a strict policy with no reviewer: configure one at Settings → Your projects → the project → Repositories → the repository → Code reviews, or relax the policy; only the merge waits | owner or admin, in settings |
50
+ | `reviewer_configured` | a code reviewer is configured at all | configure one there; a fail never blocks or degrades | owner or admin, in settings; nobody is required when it fails |
51
+
52
+ ## The machine checks the CLI adds
53
+
54
+ Each failing line prints its own fix.
55
+
56
+ | id | proves |
57
+ | -- | -- |
58
+ | `runtime` | this runtime can run the CLI: Node 22.15+ or bun 1.4+. The fix, `npx -y -p @catalyst-cloud/cli catalyst runtime install`, puts a pinned Node in the CLI's cache and leaves the default Node alone |
59
+ | `config` | `customer.json` exists and loads (`references/connecting-this-machine.md`) |
60
+ | `contract` | the contract is cached and its major version is in this bundle's range |
61
+ | `bundle` | the CLI meets the account's minimum version; a note |
62
+ | `cliPath` | the CLI path recorded at login still exists |
63
+ | `skills` | the Cloud pack's copied skills are all present; a pack installed another way reads as a note (`references/skill-sources.md`) |
64
+ | `cliRelease` | the CLI is not behind the newest release; a note |
65
+ | `skillsRelease` | the skill files are not behind the newest bundle; "could not run" means the registry was unreachable |
66
+ | `sdk` | the SDK loads, so the replica and the watch are available; reads work through the API meanwhile |
67
+ | `replica` | the optional replica is fresh; a note (`references/local-sync.md`) |
68
+
69
+ ## Setting up one team at a time
70
+
71
+ A team receives work once its stages are saved. Saving one team changes no other team's stages or tickets; only the labels Adopt creates are shared. Once saved, tickets in its dispatch stage start, so pilot on a low-stakes team and first move anything there that should wait back to Backlog. Nothing reads `gitAutomation` in the contract.
72
+
73
+ Each action exists in the terminal and on `<their cloud>/settings/linear-teams`:
74
+
75
+ - **Check** (`catalyst team check <KEY>`, Re-check) saves the team's verdict, changing no ticket or mapping, and files one setup ticket for an admin if something is missing.
76
+ - **Map** (`catalyst team map <KEY>`, Map my stages) saves a mapping from the team's existing stages and creates nothing in Linear.
77
+ - **Adopt** (`catalyst team adopt <KEY>`, Adopt the Catalyst workflow) creates the missing stages and Catalyst's labels with the admin's own Linear authorisation, including the hold label a failed phase uses when the team has no remediate stage (`teams[].labels.hold`). The label alone means nothing failed.
78
+
79
+ Map when the team's stages already cover the work, Adopt when they do not.
@@ -1,51 +1,26 @@
1
1
  # Replacing a coding account's credential
2
2
 
3
- When the script prints "<provider> account <slot> needs a new credential", replace that account's credential on its own page. Do not enroll a second account. A second account is a duplicate, and the dead one stays in place.
4
-
5
- ## Why an account needs one
6
-
7
- The script flags an account in three cases:
8
-
9
- - it is quarantined;
10
- - it is expired or revoked;
11
- - its last polls failed on the credential itself, such as `no_access_token`, three or more times in a row. The script can see this only when the cloud reports each account's polls.
12
-
13
- Other accounts can be healthy at the same time. The contract can still say `enrolled`, so that line alone never proves every account works.
14
-
15
- ## Who does it
16
-
17
- A tenant owner or admin, in the browser. The person copies the credential and pastes it. You never read it, print it, or paste it. The script prints the page link; use it, and never type a host.
3
+ When the script prints "<provider> account <slot> needs a new credential" (quarantined, expired, revoked, or three or more polls failed on the credential), replace that account's credential on its own page. Do not enroll a second account. It would be a duplicate beside the dead one. A workspace owner or admin does it in the browser, from the link the script prints; the person copies and pastes the credential, and you never read, print or paste it.
18
4
 
19
5
  ## Codex
20
6
 
21
7
  The person runs these steps on their own machine:
22
8
 
23
9
  1. Run `codex login` and choose "Sign in with ChatGPT".
24
- 2. The login writes `~/.codex/auth.json`. If `CODEX_HOME` is set, the file is `$CODEX_HOME/auth.json`. On macOS, `pbcopy < ~/.codex/auth.json` copies it.
25
- 3. In the browser, open Settings → AI accounts, then open that Codex account.
10
+ 2. The login writes `~/.codex/auth.json`, or `$CODEX_HOME/auth.json` when `CODEX_HOME` is set. On macOS, `pbcopy < ~/.codex/auth.json` copies it.
11
+ 3. In the browser, open Settings → AI accounts, then that Codex account.
26
12
  4. Paste the file into "Replacement auth.json contents", then press Replace credential.
27
13
 
28
- Then you run `node scripts/where-am-i.mjs` again and read back the `coding accounts` part.
29
-
30
- Say these two things plainly:
31
-
32
- - Do not enroll a second account. Replace the credential on the one the script named.
33
- - Catalyst takes over this login. Its refresh token is single-use, so the copy on this machine stops working once Catalyst uses it. To use Codex locally, sign in to Codex again, separately, after the replacement.
14
+ Say plainly that Catalyst takes over this login: its refresh token is single-use, so the local copy stops working once Catalyst uses it, and to use Codex locally they sign in to Codex again, separately, after the replacement.
34
15
 
35
16
  ## Claude
36
17
 
37
- The same page takes a Claude account's new credential. Its field is "Replacement setup token". `claude setup-token` mints a token for whichever Claude account the terminal is logged into, not for the slot. So first match them: read the slot's account on the AI accounts page (its label or email), then have the person run `claude` and `/status` to see the email the terminal is logged into. If they differ, stop, and log in to the slot's account first. Only then run `claude setup-token`, paste the token into that field, and press Replace credential. Then re-run the script.
38
-
39
- ## A cancelled or ended account
40
-
41
- An account whose subscription is cancelled, or which has ended, is not a credential problem, and no token revives it. It stays enrolled for reporting, is not used, and is not something to retire or delete. Never replace its credential with a token from another account: that puts a working account's login onto a dead slot. If the subscription is live again, the person reactivates it on its own page.
18
+ The field is "Replacement setup token". `claude setup-token` mints a token for whichever account the terminal is logged into, not for the slot, so match them first: compare the slot's email on the AI accounts page with what `/status` in `claude` shows, and log in to the slot's account if they differ. Then run `claude setup-token`, paste the token, and press Replace credential.
42
19
 
43
20
  ## Any other provider
44
21
 
45
- Replace its credential on the same page, with the credential that page asks for.
46
-
47
- ## What Replace credential does
22
+ The same page, with the credential it asks for. A cancelled or ended account is not a credential problem, and no token revives it.
48
23
 
49
- It stores the new credential and clears the account's quarantine in the same step. A tenant owner or admin can do it. An operator is not needed.
24
+ ## Afterwards
50
25
 
51
- A failed poll is recorded until the account is polled again. If the script still names the account right after the replacement, wait for the next poll and read it again. If it still names it, report both: what the page said, and what the script says.
26
+ Replace credential also clears the quarantine; no operator is needed. Run `node scripts/where-am-i.mjs` again. A failed poll stays on record until the next poll, so if the script still names the account, wait for that poll before reporting a disagreement.
@@ -0,0 +1,23 @@
1
+ # The repository's agent setup
2
+
3
+ Two CLI verbs, both on a checkout the person names, both writing only to its working tree. Nothing here pushes or reaches the cloud; the branch, commit and pull request are the person's, never on the default branch. When `catalyst capabilities` lacks `repo agents-block` and `repo agent-setup`, say the CLI is older and skip this; never paste the block by hand.
4
+
5
+ Say in one clause what the report found ("CLAUDE.md carries your guidance, there is no AGENTS.md, and `.claude/skills` is a real directory"), then offer each write below after its own yes, in the same pull request as the settings file when that is open.
6
+
7
+ ## The Catalyst block in AGENTS.md
8
+
9
+ `catalyst repo agents-block <path>` reads AGENTS.md as `absent`, `missing` (no block), `stale` (words differ from this CLI's) or `current`. `--write` creates the file, appends the block, or replaces the region between `<!-- catalyst:start -->` and `<!-- catalyst:end -->`; a rerun changes nothing. The block says the repository is worked through Catalyst and names the skills that explain the process; it carries no process of its own, so it never goes stale with the pipeline.
10
+
11
+ ## The portable layout
12
+
13
+ `catalyst repo agent-setup <path>` reports AGENTS.md (size, block state), CLAUDE.md (whether a line is exactly `@AGENTS.md`, and its own line count), `.agents/skills|rules` and `.claude/skills|rules` (absent, real directory, or symlink and target), and other agent files it saw (`.codex`, `.cursor`, `GEMINI.md`), then one verdict:
14
+
15
+ - **portable**: AGENTS.md is canonical, CLAUDE.md imports it, each `.claude/` twin is absent or a relative symlink into `.agents/`. Offer only the block if it is missing.
16
+ - **convertible**: the report lists the plan (CLAUDE.md's guidance moves into AGENTS.md and CLAUDE.md becomes `@AGENTS.md` plus Claude-only notes; `.claude/skills|rules` move to `.agents/` behind a relative symlink). `--apply` does exactly that.
17
+ - **needs a hand merge**: both directories are real, or a symlink points elsewhere. `--apply` refuses and names each blocker.
18
+
19
+ Portable means one AGENTS.md serves every coding agent, so a second harness finds the same instructions and skills without a drifting copy.
20
+
21
+ `--with-check` writes `scripts/agents-md-check.mjs`, a dependency-free CI script that fails when CLAUDE.md stops importing AGENTS.md, a `.claude/` twin stops being a relative symlink into `.agents/`, AGENTS.md outgrows 120 lines or 16 KiB (`AGENTS_MD_MAX_LINES`, `AGENTS_MD_MAX_BYTES`), or a backticked path it cites is gone. The person wires it into CI.
22
+
23
+ **Read back:** rerun `catalyst repo agent-setup <path>` after any write. Exit 0 is portable with the block current; exit 1 lists what is still open.
@@ -1,38 +1,32 @@
1
1
  # Catalyst skill sources
2
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.
3
+ The installer at the cloud's `/install.sh` (the app's setup page shows the command) installs both packs from exact commits, stops on any same-named skill it does not recognise, and on a home install schedules a daily refresh. Re-run it to refresh or repair; the table is the by-hand equivalent.
6
4
 
7
5
  | Pack | Purpose | By hand | Optional Claude Code plugin |
8
6
  | -- | -- | -- | -- |
9
- | `coalesce-labs/catalyst-cloud-skills` | Tenant setup and operation | `npx skills@latest add coalesce-labs/catalyst-cloud-skills --all -g` | `catalyst@catalyst-cloud` |
7
+ | `coalesce-labs/catalyst-cloud-skills` | Cloud account setup and operation | `npx skills@latest add coalesce-labs/catalyst-cloud-skills --all -g` | `catalyst@catalyst-cloud` |
10
8
  | `coalesce-labs/catalyst-dev-skills` | Coding workflows | `npx skills@latest add coalesce-labs/catalyst-dev-skills --all -g` | `catalyst-dev@catalyst-dev-skills` |
11
9
 
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.
10
+ Install each pack by one method: `npx skills` or its plugin.
13
11
 
14
12
  ## Where each install lands
15
13
 
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
-
14
+ Global (`-g`) installs go to `~/.agents/skills/`, linked from `~/.claude/skills/`, with the lock at `$XDG_STATE_HOME/skills/.skill-lock.json` or `~/.agents/.skill-lock.json`. Project installs go to `.agents/skills/` and `.claude/skills/` with `skills-lock.json`. Links are relative; resolve each with `readlink -f` before comparing paths.
21
15
 
22
- The `npx skills add --all` command replaces existing same-named directories and links. Before a first install or refresh on an existing machine, read the lock above. Inspect every same-named agent destination. Proceed only when each destination is absent or a verified, unmodified copy of the intended pack or its symlink. A lock entry alone does not verify every destination. Keep independent, changed, or uncertain copies in place and resolve the conflict before adding either pack. Do not schedule raw add commands as an unattended refresh.
16
+ `npx skills add --all` replaces same-named directories and links. Before running it on an existing machine, inspect every same-named destination and proceed only when each is absent or a verified, unmodified copy of the intended pack (a lock entry verifies nothing on disk). Resolve any other copy first. Schedule only the installer, never raw add commands.
23
17
 
24
18
  ## Is each pack there
25
19
 
26
- `catalyst 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).
20
+ `catalyst ready` checks the Cloud pack only. Look for `catalyst-onboard/SKILL.md` (Cloud) and `research-codebase/SKILL.md` (development) in the intended directory.
27
21
 
28
- ## Migrate an existing installation
22
+ ## Migrating an existing installation
29
23
 
30
24
  Inventory source and scope before removing anything:
31
25
 
32
- 1. Run `claude plugin list` and record whether `catalyst-dev@catalyst` is installed and at which scope.
33
- 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.
34
- 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`. For a copied skill whose lock source names the deprecated Catalyst runtime repository, use `npx skills remove <name> -g -y` only when every existing global agent path is that canonical copy or a symlink to it. Omit `-g` for a proven project install and inspect every same-named project agent path first. The command removes that name across agent directories. Leave independent or uncertain copies in place and report the conflict.
35
- 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.
36
- 5. Read back the plugin list, the lock for each changed scope, and the destination skill folders. Start a new agent session after changing Claude plugins.
26
+ 1. `claude plugin list`: record whether `catalyst-dev@catalyst` is installed, and at which scope.
27
+ 2. Inspect the home and project skill directories separately, with their locks and provenance markers; a folder name does not prove its source, and `.claude/skills` may link elsewhere.
28
+ 3. Remove only `catalyst-dev@catalyst`: `claude plugin uninstall catalyst-dev@catalyst --scope user --keep-data --yes`. For a copied skill whose lock source is the deprecated Catalyst runtime repository, `npx skills remove <name> -g -y` (no `-g` for a proven project install), and only when every agent path with that name is that copy or a link to it. Remove by name, never with `--all`.
29
+ 4. Install the replacement packs in the intended scope with the commands above.
30
+ 5. Read back the plugin list, each changed lock and the folders, and start a new agent session after a plugin change.
37
31
 
38
- 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.
32
+ Keep any Catalyst checkout, local project data, and same-named skill of unknown source; if source or scope is ambiguous, stop and report it.
@@ -1,115 +1,59 @@
1
1
  # The one path
2
2
 
3
- The steps run in the order a person can act on them, and the order says why: the coding account first, because nothing runs without one and it needs nothing else; the Linear integration, because the project list cannot be read without it; one project; the GitHub App and the repository it will work in; the person's own connected accounts, GitHub last because a registered repository is the proof the App is usable; the repository's settings file; then the first ticket. Each step 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 it is for, in a sentence, and ask one question or do one thing. 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. Two or three short sentences per turn is the right size.
6
-
7
- Each step states: what it is for, what you ask or run or hand over, **what you read back to prove it landed**, and **who owns it**.
3
+ The steps run in the order a person can act on them, each the cheapest place to catch what the next would hide. The script prints each step's owner and link; this page adds why it matters, what to ask, and its trap. Browser handovers follow `references/what-the-browser-owns.md`.
8
4
 
9
5
  ## 0. Where are we
10
6
 
11
- **For:** starting from the truth instead of an assumption. A person arrives having done anything from nothing to most of it, and the installer has usually connected the machine already.
12
-
13
- **You run:** `node scripts/where-am-i.mjs --next`. Read the one line, then say in a sentence which step is next and whose it is. Do not paste the full report.
14
-
15
- **Owner:** you.
7
+ Run `node scripts/where-am-i.mjs --next` and say which step is next and whose it is.
16
8
 
17
9
  ## 1. Connect this machine
18
10
 
19
- **For:** giving this machine a credential, so every later read is the person's own. The installer normally did this; you are here only when the script says the machine is not connected.
11
+ Only when the script says the machine is not connected: ask "Shall I start the login now?", then follow `references/connecting-this-machine.md`.
20
12
 
21
- **You ask:** "Shall I start the login now?" On a yes, run `catalyst login`. It prints a short code and a URL. The person approves it in a browser, from a phone if this machine has none. Do not offer the key form; it exists for a person who already holds a personal key and says so.
13
+ ## 1b. Leftovers of the old local runtime
22
14
 
23
- **Read back:** the `Connected to …` and `Connected as …` lines, then the script again so the machine part flips.
24
-
25
- **Owner:** you run it; the approval is the person's, in a browser, and always will be. Do not re-run the command while a code is outstanding. If it refuses, stop and use the `connect-me` skill.
15
+ Only when the script notes them (from the CLI's fixed list; current jobs are never on it); left in place they can start old jobs or shadow current commands. Ask once, recommending it: "Shall I remove the old runtime's leftovers now? It keeps your data folders." On a yes, run `catalyst legacy --remove --yes` and read back its `removed:` and `re-checked:` lines; offer `--data` separately. On a no, the note stays.
26
16
 
27
17
  ## 2. A coding account
28
18
 
29
- **For:** what the work runs on. Catalyst runs each stage of a ticket on an account the person owns, at their own rate, under their own name. With none enrolled, every later step can be finished and nothing will ever start.
30
-
31
- **You ask:** "Do you already have a coding account you want Catalyst to run on?" Then `references/choosing-a-coding-account.md`: the four kinds, what each asks for, how to enrol one, and what to do with an account that is out of rotation, needs a new credential, or has ended.
32
-
33
- **Read back:** the `coding accounts` part: an enrolled, active account, named by its label. A cancelled or ended one is kept for reporting, not used, never re-tokened, and does not hold this step up.
34
-
35
- **Owner:** a workspace owner or admin, in a browser, on the AI accounts page. Nothing you run ever sees the credential.
19
+ Each stage of a ticket runs on an account the person owns, at their own rate, under their own name; with none, nothing ever starts. It needs nothing else, so it comes first. Ask "Do you already have a coding account you want Catalyst to run on?", then follow `references/what-a-phase-needs.md`.
36
20
 
37
21
  ## 3. Connect the Linear integration
38
22
 
39
- **For:** the workspace. Until the workspace's Linear connection exists, no project can be read or mapped. Say that this is the one connection the whole workspace shares, made once by an admin.
40
-
41
- **You hand over:** `<their cloud>/settings/connections` (the Integrations page; Settings labels it Connections today), and say: connect Linear. It sends them to Linear to authorise and brings them back.
42
-
43
- **Read back:** after they say it is done, re-run the script and read them the `account` line. A resolved workspace is proof. If it still reads unresolved, run `catalyst contract --refresh` and read it again.
44
-
45
- **Owner:** a workspace owner or admin, in a browser. **Browser by construction**: it is an authorization grant, and no key can perform one.
23
+ The one Linear connection the whole workspace shares, made once by an owner or admin on `<their cloud>/settings/connections`; no project can be read without it.
46
24
 
47
25
  ## 4. Pick one project, and map its stages
48
26
 
49
- **For:** the project. A project is one Linear team plus the repositories registered to it. 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 workspace sees no activity.
50
-
51
- **You run:** `catalyst team list` to see the teams without checking readiness. Have the person choose one team key. Then `catalyst team map <KEY>`, or `catalyst team adopt <KEY>` if they want Catalyst's stages created for them: each prints a preview; show it, and pass `--yes --plan-hash <hash>` only after they approve that exact plan. Run `catalyst team check <KEY>` only for the selected team when you need its verdict. The same steps exist on `<their cloud>/settings/linear-teams` (**Map my stages**, **Adopt the Catalyst workflow**) for a person who prefers the page.
52
-
53
- **Read back:** re-run the script and read the `projects` line: the verdict and any failing checks by name. A project that reads `blocked` is not set up whatever its gate says; the script names the blocking checks and their owner. Three of them are Linear's own Git automation rules (in Linear: Settings → Teams → the team → Workflow → Git automation, set the named rule to No action). No Catalyst key can change those, so say so, hand it over, and afterwards run `catalyst team check <KEY>`.
54
-
55
- For manual setup, `catalyst team checklist <KEY>` prints the same lines as the browser. If it cannot read the live stages, fix the Linear connection and retry. Moving tickets out of old stages is a separate decision: preview with `team migrate <KEY>`, review source and destination ids and counts, then confirm with `--yes --plan-hash <hash>` from that preview. Retiring emptied source stages requires a later `team migrate <KEY> --retire` preview and a separate approval using its preview hash. `team adopt <KEY> --undo` likewise previews the exact stages previously created by Adopt before asking for confirmation.
27
+ A card moved into an unmapped project does nothing, the most common reason a new workspace sees no activity. Lead with the pilot: one project changes no other (`references/reading-ready.md`, "Setting up one team at a time", which also says Map or Adopt).
56
28
 
57
- **Owner:** a workspace owner or admin, with their own login. You run the commands; the person picks the team and approves each write after seeing its preview. A run that exits 3 stopped before applying anything.
29
+ `catalyst team list` shows the teams without checking readiness; the person picks one key. `catalyst team map <KEY>` or `catalyst team adopt <KEY>` prints a preview to approve before `--yes --plan-hash <hash>` (exit 3 applied nothing). Run `catalyst team check <KEY>` only for the selected team. `team migrate <KEY>`, its `--retire`, and `team adopt <KEY> --undo` each preview and need their own approval. `catalyst capabilities` says which verbs this cloud serves.
58
30
 
59
- ⭐ **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: the project they care least about breaking.
31
+ A `blocked` project is not set up. Change Linear's own Git automation rules in Linear for now (Settings → Teams → the team → Workflow → Workflows & automations → Pull request and commit automations → No action); hand that over, then re-check.
60
32
 
61
33
  ## 5. Install the GitHub App
62
34
 
63
- **For:** the workspace's GitHub integration. Without it Catalyst can read tickets but cannot touch code.
64
-
65
- **You hand over:** the same Connections page, and say: install the GitHub App, and grant it the repository they want worked and `<org>/thoughts`. Catalyst's cloud phases write their notes to `<org>/thoughts`, where `<org>` owns the code repository. If it does not exist, they create a private repository named `thoughts`, initialized with a README, and then on the App's installation page for that org choose All repositories, or add `thoughts` to the selected repositories. The script's `repositories` part notes whether `gh` can see that repository, never that the App can reach it, so do not claim that.
66
-
67
- **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.
68
-
69
- **Owner:** a workspace owner or admin, in a browser. Browser by construction, same reason as step 3.
35
+ Without it Catalyst cannot touch code. On the same page, the owner or admin installs the App and grants it the repository plus `<org>/thoughts`, where cloud phases write their notes (`<org>` owns the code repository). If it does not exist, they create a private repository named `thoughts`, initialized with a README, then on the App's installation page for that org choose All repositories or add `thoughts`. The script notes whether `gh` can see that repository, never that the App can reach it. Step 6 succeeding is the proof the App is installed.
70
36
 
71
37
  ## 6. Register the repository
72
38
 
73
- **For:** the repository. Registering, attached to a project, is what makes a repository something that project can dispatch work into.
74
-
75
- **You hand over:** `<their cloud>/settings/repositories`, and say: add the repository, **and attach it to the project you mapped in step 4**, in the same form.
76
-
77
- **Read back:** re-run the script and read the `repositories` line. The repository appearing there proves it was registered, and only that; see `references/who-fixes-what.md` for what registration does not prove.
78
-
79
- **Owner:** a workspace owner or admin. ⛔ Registering is settings-page work today. ⛔ A repository registered without a project attached is the trap: the call succeeds, the repository is listed, and nothing can ever dispatch into it.
39
+ On `<their cloud>/settings/projects`, add the repository **and attach it to the project from step 4** in the same form. A repository registered without a project is listed and never receives work.
80
40
 
81
41
  ## 7. Connect your own accounts
82
42
 
83
- **For:** the person. The integrations serve the whole workspace; a connected account is this person's own Linear or GitHub login, so that what Catalyst does for them is attributed to them, and asks assigned to them can be told apart from everyone else's.
84
-
85
- **You run:** `catalyst connections personal linear start`. It prints a short-lived URL and tries to open it; if the browser does not open, hand them the URL. Then `catalyst connections personal linear status`. Do GitHub the same way, with `github`, only after the GitHub App is installed and the repository is registered: `catalyst connections personal github start`, then `status`.
86
-
87
- **Read back:** each `status`, and the script's `person` part: their label and role, whether their Linear identity is matched, and each grant. A URL opening is not proof a grant landed. If Linear identity stays unmatched after consent, `catalyst identity linear status`, then `options`; the person picks their own listed identity and you run `catalyst identity linear set <linearUserId>`. An already-resolved or claimed identity, and an inactive seat, need an owner or admin.
88
-
89
- **Owner:** you start and check; the person approves in a browser.
43
+ The person's own logins, so work done for them is attributed to them and their asks can be told apart. Run `catalyst connections personal linear start` (hand over the URL if no browser opens), then `catalyst connections personal linear status`. Do GitHub the same way, only after the GitHub App is installed and the repository is registered. An unmatched Linear identity is in `references/connecting-this-machine.md`.
90
44
 
91
45
  ## 8. The repository's settings file
92
46
 
93
- **For:** the repository's own settings, in `.catalyst/catalyst.toml` on its default branch: the Linear team it belongs to, the names of the variables and secrets its build needs, and its setup commands. Names leave the machine; values are entered once, by them, in the app.
94
-
95
- **You ask:** one thing at a time. First: "Shall I draft it from your repository's own build files?" On a yes, ask where the repository is checked out on this machine; if it is not, write the file here for them to add. Then `references/declaring-a-repository.md`: the inventory, the file's shape, the pull request. Say what happens after the merge as context, not as a second task for now. After the merge, an owner or admin approves the revision on the repository's Environment page (Settings → Repositories → the repository → Environment → Setup declaration → Approve this revision) and enters the values on the same page. A workspace-wide declaration, if they want one, goes through `catalyst environment` (read, propose, `--approve`), the one setup write you can perform.
96
-
97
- **Read back:** the script's `repository declarations` part, read from each project's `environment_declared` check: no file yet, invalid, awaiting approval, or in effect, per repository. Names only, never a value.
47
+ Inspect and draft the repository settings file yourself from its build and test files; follow `references/declaring-a-repository.md`. Show the summary and get approval before writing or opening the PR. Mention the declaration approval after merge as context, not a second task. A workspace-wide declaration goes through `catalyst environment` (read, propose, `--approve`).
98
48
 
99
- **Owner:** the person, with you, in the repository; a workspace owner or admin for the approval.
49
+ Once you know the checkout path, rerun `node scripts/where-am-i.mjs --next --repo <path>` (a read) and follow `references/repository-agent-setup.md` for the offers it notes.
100
50
 
101
51
  ## 9. Verify, then run the first ticket
102
52
 
103
- **For:** the only thing that proves setup worked.
104
-
105
- **You run:** `catalyst team check <KEY>` first when the script's next step names it (an owner or admin whose CLI has the verb), then `catalyst ready`. Its READY does not cover the coding account or the host; the script does. Read them the verdict and every failing line with its own fix and owner. If it says NOT READY, go to `references/who-fixes-what.md` before you touch anything.
106
-
107
- **Then:** one question, worded like this: "Move one ticket into ENG's start stage (usually Todo) and tell me its id." Nothing else in that turn: no offer to explain the pipeline, to look at the board, or to pick one for them. Then watch. `catalyst explain <ticket>` says why it is or is not about to run. If they opted into local sync, use the optional first-event check in `references/local-sync.md`.
108
-
109
- **Read back:** what `explain` actually said, and the first comment the agent leaves on the ticket. If `explain` says the ticket cannot start, the reason it names is the answer; use the `how-catalyst-works` skill for what it means, then `unstick` if something is holding it.
53
+ Run `catalyst ready`; READY covers neither the coding account nor the host, which the script reads. On NOT READY, read `references/reading-ready.md` before touching anything.
110
54
 
111
- **Owner:** the card move is theirs. The verdict is the workspace's.
55
+ Then ask one thing: "Move one ticket into ENG's start stage (usually Todo) and tell me its id." Nothing else that turn. `catalyst explain <ticket>` says why it is or is not about to run, and the agent's first comment on the ticket confirms it started. With local sync on, use the optional first-event check in `references/local-sync.md`. A reason it cannot start goes to the `whats-happening` skill, then `unstick`.
112
56
 
113
57
  ## When you are done
114
58
 
115
- 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. 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.
59
+ Say what is set up and name anything unfinished with its owner; work can run only when the `coding accounts` and `host` parts are finished.
@@ -1,46 +1,39 @@
1
1
  # What a phase needs to run
2
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.
3
+ A phase needs the `coding accounts` and `host` parts of `node scripts/where-am-i.mjs`, however much else is finished. Say a phase can run only when the script's last line says nothing is left; otherwise name the unfinished part and its owner, and say no work will start yet.
4
4
 
5
5
  ## Coding accounts
6
6
 
7
- **For:** a phase runs on one of the tenant's own enrolled coding accounts. With none active, no phase can start.
7
+ One coding account is enough to start. A second, on another provider or plan, gives the router somewhere to go at a limit; offer it later.
8
8
 
9
- **Instrument:** `codingAccounts` in `catalyst 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. When the state is `enrolled`, the script also reads `catalyst accounts` to check each account's credential.
9
+ ### The kinds, and enrolling
10
10
 
11
- **What each state means:**
12
-
13
- | state | what it says | what to do |
11
+ | they say | kind | the page asks for |
14
12
  | -- | -- | -- |
15
- | `enrolled` | at least one account is active. Another account can still have a dead credential | read the account lines. If one says "<provider> account <slot> needs a new credential", that is the next step: follow `references/replacing-a-credential.md`. If the part reads `unreadable`, the accounts could not be checked in detail; say so and read it again later. Otherwise 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 |
13
+ | "Claude Pro or Max", "I use Claude Code" | Claude setup token | what `claude setup-token` prints, after `/status` in `claude` shows the account they mean |
14
+ | "ChatGPT", "Codex" | Codex auth file | `~/.codex/auth.json` after `codex login` (steps in `references/replacing-a-credential.md`) |
15
+ | "a GLM key", "Z.ai" | GLM API key | the key from the provider's console |
16
+ | "a Qwen key", "Alibaba Model Studio" | Qwen API key | the key from the provider's console |
19
17
 
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. Which kinds of account exist, what each asks for, and what to do with an ended or cancelled one are in `references/choosing-a-coding-account.md`; it is step 2 of the path, the first thing asked.
18
+ A plain Anthropic or OpenAI API key cannot be enrolled; say so and ask whether they have one of these. Before a Codex paste, say Catalyst takes over that login: its refresh token is single-use, so they sign in to Codex again locally afterwards.
21
19
 
22
- **Older cloud:** if the contract has no `codingAccounts`, the script says the cloud is older and reads `catalyst 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
20
+ Enrolling is a browser step by construction: on Settings → AI accounts, an owner or admin picks the provider, labels the account, and pastes the credential into a write-only field. Call an account by its label, else its email, else its slot (`displayName` in `catalyst accounts --json`).
25
21
 
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.
22
+ ### The states
27
23
 
28
- **Instrument:** the `hosts_current` check in `catalyst contract --path teams`, and its owner in `catalyst contract --path readinessChecks`.
24
+ **Instrument:** `codingAccounts` in `catalyst contract`; with `enrolled`, the script also reads `catalyst accounts` for each credential. With no `codingAccounts` (an older cloud) it reads `catalyst accounts` alone, and the owner is an owner or admin at `<their cloud>/settings/coding-accounts`.
29
25
 
30
- **What each reading means:**
31
-
32
- | reading | what it says | what to do |
26
+ | state | what it says | what to do |
33
27
  | -- | -- | -- |
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 | run `catalyst team check <KEY>` when the script names it (it does when the CLI has the verb and the person is an owner or admin); otherwise press Re-check on the projects page; then read it again |
28
+ | `enrolled` | one is active; another can still have a dead credential | "<provider> account <slot> needs a new credential" is the next step: `references/replacing-a-credential.md`. `unreadable` detail: read again later |
29
+ | `none_enrolled` | none enrolled | hand over the page to the enroller the contract names |
30
+ | `inactive` | every account is out of rotation | reactivate one on its page, never enrol another |
31
+ | `unread` | the cloud could not read them | it is not "no accounts"; read again later |
39
32
 
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.
33
+ **A cancelled or ended account** stays for reporting, unused, and does not hold setup up; say so in one clause. It keeps its own login: a token from another login would put a live account onto a dead slot. It stays enrolled rather than retired or deleted, and a returning subscription reactivates it on its page.
41
34
 
42
- ⛔ `catalyst 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.
35
+ ## Host
43
36
 
44
- ## Saying it is ready
37
+ The `hosts_current` check reads the same on every project, because it is about the whole account. `pass` means nothing waits on a host, including an account that runs none. `no_host_connected`, `hosts_unreported` (clears when the host reconnects) and `hosts_behind` each mean: name the owner and stop. `unreadable` means no project has been checked yet. The owner and where they act (`fixedWhere`) come from `catalyst contract --path readinessChecks`; when `fixedWhere` is null, name the owner with no page.
45
38
 
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.
39
+ ⛔ `catalyst ready` treats this check as a note, so it can print READY while no host is connected. The `host` part, not READY, says whether a phase can run.