@catalyst-cloud/cli 0.9.5 → 0.13.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +28 -0
- package/README.md +28 -29
- package/dist/args.js +19 -1
- package/dist/ask.js +30 -18
- package/dist/capabilities.js +5 -0
- package/dist/cli.js +24 -6
- package/dist/env/declaration-rules.js +163 -0
- package/dist/env/group.js +51 -0
- package/dist/env/inventory.js +102 -0
- package/dist/env/render.js +39 -0
- package/dist/env/scan-env-example.js +62 -0
- package/dist/env/scan-source.js +43 -0
- package/dist/env/scan-workflow.js +123 -0
- package/dist/env/scan-wrangler.js +120 -0
- package/dist/env/types.js +1 -0
- package/dist/env/walk.js +87 -0
- package/dist/env.js +76 -0
- package/dist/environment.js +1 -1
- package/dist/legacy.js +224 -0
- package/dist/project.js +129 -0
- package/dist/release.js +1 -1
- package/dist/repo.js +297 -0
- package/dist/runtime-verb.js +1 -1
- package/dist/secret.js +1 -1
- package/dist/skill-shape.js +21 -13
- package/dist/skills.js +44 -4
- package/dist/transport.js +26 -1
- package/package.json +7 -6
- package/skills/catalyst-github/SKILL.md +7 -7
- package/skills/catalyst-github/references/is-it-mergeable.md +8 -2
- package/skills/catalyst-github/references/what-a-pr-accumulates.md +3 -3
- package/skills/catalyst-github/scripts/is-it-mergeable.mjs +3 -3
- package/skills/catalyst-github/scripts/lib/cli.mjs +9 -7
- package/skills/catalyst-github/scripts/lib/credential.mjs +2 -2
- package/skills/catalyst-github/scripts/read-pr.mjs +2 -2
- package/skills/catalyst-linear/SKILL.md +17 -19
- package/skills/catalyst-linear/agents/openai.yaml +1 -1
- package/skills/catalyst-linear/agents/portability.yaml +1 -1
- package/skills/catalyst-linear/references/reading-a-ticket.md +9 -26
- package/skills/catalyst-linear/references/what-a-ticket-accumulates.md +2 -2
- package/skills/catalyst-linear/references/writing-to-linear.md +7 -9
- package/skills/catalyst-linear/scripts/comment.mjs +1 -1
- package/skills/catalyst-linear/scripts/create-ticket.mjs +1 -1
- package/skills/catalyst-linear/scripts/label.mjs +1 -1
- package/skills/catalyst-linear/scripts/lib/cli.mjs +9 -7
- package/skills/catalyst-linear/scripts/lib/credential.mjs +2 -2
- package/skills/catalyst-linear/scripts/move.mjs +1 -1
- package/skills/catalyst-linear/scripts/read-ticket.mjs +1 -1
- package/skills/catalyst-linear/scripts/search.mjs +1 -1
- package/skills/catalyst-onboard/SKILL.md +37 -57
- package/skills/catalyst-onboard/agents/openai.yaml +2 -2
- package/skills/catalyst-onboard/agents/portability.yaml +1 -1
- package/skills/catalyst-onboard/references/connecting-this-machine.md +35 -0
- package/skills/catalyst-onboard/references/declaring-a-repository.md +7 -17
- package/skills/catalyst-onboard/references/local-sync.md +19 -7
- package/skills/catalyst-onboard/references/reading-ready.md +79 -0
- package/skills/catalyst-onboard/references/replacing-a-credential.md +8 -33
- package/skills/catalyst-onboard/references/repository-agent-setup.md +23 -0
- package/skills/catalyst-onboard/references/skill-sources.md +13 -19
- package/skills/catalyst-onboard/references/the-one-path.md +18 -74
- package/skills/catalyst-onboard/references/what-a-phase-needs.md +21 -28
- package/skills/catalyst-onboard/references/what-the-browser-owns.md +20 -37
- package/skills/{catalyst-setup → catalyst-onboard}/scripts/check.mjs +10 -9
- package/skills/catalyst-onboard/scripts/lib/cli.mjs +6 -4
- package/skills/catalyst-onboard/scripts/lib/credential.mjs +2 -2
- package/skills/catalyst-onboard/scripts/where-am-i.mjs +60 -4
- package/skills/run-this-project/SKILL.md +23 -25
- package/skills/run-this-project/agents/openai.yaml +1 -1
- package/skills/run-this-project/agents/portability.yaml +1 -1
- package/skills/run-this-project/references/making-work-ready.md +20 -37
- package/skills/run-this-project/references/reacting-to-events.md +25 -48
- package/skills/run-this-project/references/stalls-and-escalation.md +20 -42
- package/skills/run-this-project/scripts/lib/cli.mjs +7 -5
- package/skills/run-this-project/scripts/lib/credential.mjs +2 -2
- package/skills/run-this-project/scripts/scope-status.mjs +0 -0
- package/skills/run-this-project/scripts/watch-scope.mjs +1 -1
- package/skills/unstick/SKILL.md +12 -12
- package/skills/unstick/agents/openai.yaml +1 -1
- package/skills/unstick/agents/portability.yaml +1 -1
- package/skills/unstick/references/playbook.md +13 -13
- package/skills/unstick/scripts/lib/cli.mjs +6 -4
- package/skills/unstick/scripts/lib/credential.mjs +2 -2
- package/skills/unstick/scripts/unstick.mjs +1 -1
- package/skills/what-needs-me/SKILL.md +12 -14
- package/skills/what-needs-me/agents/openai.yaml +2 -2
- package/skills/what-needs-me/agents/portability.yaml +1 -1
- package/skills/what-needs-me/references/raising-a-decision.md +8 -16
- package/skills/what-needs-me/references/reading-the-inbox.md +9 -12
- package/skills/what-needs-me/references/settling-an-answer.md +6 -12
- package/skills/what-needs-me/scripts/inbox.mjs +14 -13
- package/skills/what-needs-me/scripts/lib/cli.mjs +6 -4
- package/skills/what-needs-me/scripts/lib/credential.mjs +2 -2
- package/skills/what-needs-me/scripts/raise.mjs +1 -1
- package/skills/what-needs-me/scripts/settle.mjs +1 -1
- package/skills/what-this-repo-needs/SKILL.md +31 -0
- package/skills/what-this-repo-needs/agents/openai.yaml +6 -0
- package/skills/what-this-repo-needs/agents/portability.yaml +4 -0
- package/skills/what-this-repo-needs/references/what-each-group-means.md +38 -0
- package/skills/what-this-repo-needs/scripts/check.mjs +64 -0
- package/skills/what-this-repo-needs/scripts/inventory.mjs +61 -0
- package/skills/{catalyst-setup → what-this-repo-needs}/scripts/lib/cli.mjs +35 -22
- package/skills/{catalyst-setup → what-this-repo-needs}/scripts/lib/credential.mjs +2 -2
- package/skills/whats-happening/SKILL.md +27 -21
- package/skills/whats-happening/agents/openai.yaml +1 -1
- package/skills/whats-happening/references/coding-accounts.md +24 -0
- package/skills/whats-happening/references/routing-work.md +11 -29
- package/skills/whats-happening/references/settings-and-where-they-live.md +20 -0
- package/skills/whats-happening/references/stages-and-mapping.md +25 -0
- package/skills/whats-happening/references/status-reply.md +21 -21
- package/skills/whats-happening/references/the-ladder.md +30 -0
- package/skills/whats-happening/references/what-runs-next.md +32 -0
- package/skills/whats-happening/references/when-a-phase-fails.md +27 -0
- package/skills/whats-happening/references/why-is-it-stuck.md +33 -40
- package/skills/whats-happening/scripts/explain.mjs +1 -1
- package/skills/whats-happening/scripts/lib/cli.mjs +7 -5
- package/skills/whats-happening/scripts/lib/credential.mjs +2 -2
- package/skills/{how-catalyst-works → whats-happening}/scripts/show-my-map.mjs +18 -32
- package/skills/whats-happening/scripts/snapshot.mjs +10 -6
- package/skills/catalyst-onboard/references/choosing-a-coding-account.md +0 -52
- package/skills/catalyst-onboard/references/who-fixes-what.md +0 -64
- package/skills/catalyst-setup/SKILL.md +0 -36
- package/skills/catalyst-setup/agents/openai.yaml +0 -6
- package/skills/catalyst-setup/agents/portability.yaml +0 -4
- package/skills/catalyst-setup/references/what-each-check-means.md +0 -88
- package/skills/catalyst-setup/scripts/replica-status.mjs +0 -46
- package/skills/connect-me/SKILL.md +0 -63
- package/skills/connect-me/agents/openai.yaml +0 -6
- package/skills/connect-me/agents/portability.yaml +0 -5
- package/skills/connect-me/references/keeping-the-replica-running.md +0 -88
- package/skills/connect-me/scripts/lib/cli.mjs +0 -185
- package/skills/connect-me/scripts/lib/credential.mjs +0 -29
- package/skills/connect-me/scripts/verify-connection.mjs +0 -68
- package/skills/how-catalyst-works/SKILL.md +0 -43
- package/skills/how-catalyst-works/agents/openai.yaml +0 -6
- package/skills/how-catalyst-works/agents/portability.yaml +0 -4
- package/skills/how-catalyst-works/references/coding-accounts.md +0 -51
- package/skills/how-catalyst-works/references/stages-and-mapping.md +0 -56
- package/skills/how-catalyst-works/references/the-ladder.md +0 -41
- package/skills/how-catalyst-works/references/what-catalyst-is.md +0 -30
- package/skills/how-catalyst-works/references/what-runs-next.md +0 -88
- package/skills/how-catalyst-works/references/when-a-phase-fails.md +0 -57
- package/skills/how-catalyst-works/scripts/explain-ticket.mjs +0 -41
- package/skills/how-catalyst-works/scripts/lib/cli.mjs +0 -164
- package/skills/how-catalyst-works/scripts/lib/credential.mjs +0 -29
- package/skills/how-catalyst-works/scripts/whats-running.mjs +0 -65
- package/skills/whats-happening/references/reading-the-board.md +0 -43
- package/skills/whats-happening/references/reprioritising.md +0 -37
|
@@ -1,115 +1,59 @@
|
|
|
1
1
|
# The one path
|
|
2
2
|
|
|
3
|
-
The steps run in the order a person can act on them,
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
13
|
+
## 1b. Leftovers of the old local runtime
|
|
22
14
|
|
|
23
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
31
|
+
A `blocked` project is not set up. Linear's own Git automation rules change only in Linear (Settings → Teams → the team → Workflow → Git automation → No action); hand that over, then re-check.
|
|
60
32
|
|
|
61
33
|
## 5. Install the GitHub App
|
|
62
34
|
|
|
63
|
-
|
|
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
|
-
|
|
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/repositories`, 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
|
-
|
|
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
|
-
|
|
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
|
+
Ask "Shall I draft it from your repository's own build files?", then follow `references/declaring-a-repository.md`. Mention the approval after the merge as context, not a second task. A workspace-wide declaration goes through `catalyst environment` (read, propose, `--approve`).
|
|
98
48
|
|
|
99
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
9
|
+
### The kinds, and enrolling
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
| state | what it says | what to do |
|
|
11
|
+
| they say | kind | the page asks for |
|
|
14
12
|
| -- | -- | -- |
|
|
15
|
-
|
|
|
16
|
-
|
|
|
17
|
-
|
|
|
18
|
-
|
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
22
|
+
### The states
|
|
27
23
|
|
|
28
|
-
**Instrument:**
|
|
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
|
-
|
|
31
|
-
|
|
32
|
-
| reading | what it says | what to do |
|
|
26
|
+
| state | what it says | what to do |
|
|
33
27
|
| -- | -- | -- |
|
|
34
|
-
| `
|
|
35
|
-
| `
|
|
36
|
-
| `
|
|
37
|
-
| `
|
|
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
|
-
**
|
|
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
|
-
|
|
35
|
+
## Host
|
|
43
36
|
|
|
44
|
-
|
|
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
|
-
|
|
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.
|
|
@@ -1,51 +1,34 @@
|
|
|
1
1
|
# What the browser owns
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
## Browser by construction
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Each is an authorization a person grants in their own session, so no command will ever do it. Say **by construction**; a person told "not supported yet" waits for a feature that will never come.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
| step | where |
|
|
8
|
+
| -- | -- |
|
|
9
|
+
| approving the login | the URL and short code `catalyst login` printed |
|
|
10
|
+
| enrolling a coding account, or replacing its credential | the AI accounts page the script printed |
|
|
11
|
+
| connecting the Linear integration, installing the GitHub App | `<their cloud>/settings/connections` |
|
|
12
|
+
| creating `<your GitHub org>/thoughts` and letting the App reach it | GitHub, then the App's installation page for that org: All repositories, or add `thoughts` (step 5 of `references/the-one-path.md`) |
|
|
13
|
+
| connecting personal Linear, then personal GitHub | the URL `catalyst connections personal <linear\|github> start` printed |
|
|
8
14
|
|
|
9
|
-
|
|
10
|
-
| -- | -- | -- |
|
|
11
|
-
| approving the login | the URL and short code that `catalyst login` printed | "I have started the login. It printed this code and this URL — approve it in your browser, or on your phone, and tell me when it is done." |
|
|
12
|
-
| enrolling a coding account, or replacing its credential | the AI accounts page the script printed for the `coding accounts` part | "Choose the provider, give the account a label you will recognise, and paste the credential the page asks for. Nothing on this side sees it. Tell me when it is saved and I will read it back." |
|
|
13
|
-
| connecting the Linear integration | `<their cloud>/settings/connections` (the Integrations page; Settings labels it Connections today) | "Open this page and connect Linear. It will send you to Linear to authorize it and bring you back." |
|
|
14
|
-
| installing the GitHub App | `<their cloud>/settings/connections` | "Open the same page and install the GitHub App, granting it the repository you want worked and `<your GitHub org>/thoughts`." |
|
|
15
|
-
| creating or confirming `<your GitHub org>/thoughts`, and letting the GitHub App reach it | GitHub, then the GitHub App's installation page for that org | "Catalyst's cloud phases write their notes to `<your GitHub org>/thoughts`, in the org that owns the code repository. Check it exists. If not, create a private repository named `thoughts`, initialized with a README. Then, on the GitHub App's installation page for that org, choose All repositories, or add `thoughts` to the selected repositories." |
|
|
16
|
-
| connecting personal Linear | the URL printed by `catalyst connections personal linear start` | "Approve your own Linear account in this browser. I will check the grant status afterward." |
|
|
17
|
-
| connecting personal GitHub, after the tenant GitHub App is installed and its repository is registered | the URL printed by `catalyst connections personal github start` | "Approve your own GitHub account in this browser. I will check the grant status afterward." |
|
|
15
|
+
## Not a command yet
|
|
18
16
|
|
|
19
|
-
|
|
17
|
+
Their routes take a browser session, not a key. Call them gaps, route the person through the browser, and never guess at a route.
|
|
20
18
|
|
|
21
|
-
|
|
19
|
+
| step | where |
|
|
20
|
+
| -- | -- |
|
|
21
|
+
| registering a repository and attaching it to a project | `<their cloud>/settings/repositories` |
|
|
22
|
+
| approving one repository's declaration, and entering its values | that repository's Environment page (`references/declaring-a-repository.md`) |
|
|
22
23
|
|
|
23
|
-
|
|
24
|
+
`catalyst environment` handles a workspace-wide declaration. ⛔ Only the CLI makes requests; if you find yourself building a URL for one of these, stop.
|
|
24
25
|
|
|
25
|
-
|
|
26
|
-
| -- | -- | -- |
|
|
27
|
-
| registering a repository | `<their cloud>/settings/repositories` | "Add the repository here, and attach it to the project you just mapped, in the same form." |
|
|
28
|
-
| approving the environment **for one repository**, and entering its values | that repository's Environment page under `<their cloud>/settings/repositories`: the Setup declaration tab's Approve this revision button approves, and the Environment variables and Secrets tabs take the values | "The names come from `.catalyst/catalyst.toml` in the repository, which I can write with you. Approving it and entering the values happen here, once, by you. Nothing I run ever sees a value." (Account-wide names are **not** on this list: `catalyst environment` does those.) |
|
|
26
|
+
## The link to hand over
|
|
29
27
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
## The URL to hand over
|
|
33
|
-
|
|
34
|
-
Never type a host from memory. `catalyst status` prints the API it is connected to on its `API:` line, and `node scripts/where-am-i.mjs` prints ready-made links built from it. Use those. A person pointed at the wrong tenant's settings page has a worse afternoon than one pointed at no page at all.
|
|
28
|
+
Use the links `node scripts/where-am-i.mjs` prints, built from the `API:` line of `catalyst status`, never a host from memory: the wrong account's settings page costs more than none.
|
|
35
29
|
|
|
36
30
|
## Handing over, and coming back
|
|
37
31
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
1. **What to open.** One link, and what they will see on it.
|
|
41
|
-
2. **What to do there.** One action, named the way the page names it.
|
|
42
|
-
3. **What you need back.** Not "let me know when you are done" — say what you will check and how. "When you have saved it, say so and I will re-read your tenant and tell you what it now says."
|
|
43
|
-
|
|
44
|
-
Then **wait**. Do not run anything while they are mid-flow, do not narrate, and do not move to the next step.
|
|
45
|
-
|
|
46
|
-
When they come back:
|
|
32
|
+
Hand over one link, one action named the way the page names it, and what you will check when they are back. Then wait, without running anything.
|
|
47
33
|
|
|
48
|
-
|
|
49
|
-
- If it changed, say what it now says and move on.
|
|
50
|
-
- If it did not, refresh the contract once (`catalyst contract --refresh`) and read it again — the contract is cached, and a page can be ahead of it by a few seconds.
|
|
51
|
-
- If it still did not, report both: what the page told them, and what the instrument says. Ask what they saw. **Never mark a step done because the person said a page worked** — the instrument is the record, and this is exactly where a confident false "all set" costs them an hour later.
|
|
34
|
+
When they come back, read the part again (step 5 of a turn in `SKILL.md`). The contract is cached, so a page can be seconds ahead of it: refresh once before reporting a disagreement, then ask what they saw. A step is done when the instrument reads done.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// check.mjs — "am I set up?" in one verdict: the machine checks the CLI runs (Node, the connection,
|
|
3
3
|
// the cached contract, the CLI path, the skills, the SDK, the optional replica) plus every team's
|
|
4
|
-
// readiness
|
|
5
|
-
// `catalyst
|
|
6
|
-
import {
|
|
4
|
+
// readiness from the account's contract, then the list of who can click what. Wraps
|
|
5
|
+
// `catalyst ready --json`; reports, never repairs. Exit 0 READY, 1 NOT READY, 2 not connected.
|
|
6
|
+
import { runCli, tryJson } from "./lib/cli.mjs";
|
|
7
7
|
|
|
8
8
|
const HELP = `Usage: node scripts/check.mjs [--json]
|
|
9
9
|
|
|
@@ -12,7 +12,8 @@ verdict, and a "who can click what" list grouped by the person or role each fix
|
|
|
12
12
|
A note never flips the verdict (the replica is optional; an informational readiness check is a note).
|
|
13
13
|
|
|
14
14
|
--json prints the CLI's report document {ready, checks[]} unchanged.
|
|
15
|
-
Exit 0 READY, 1 NOT READY, 2 this machine is not connected
|
|
15
|
+
Exit 0 READY, 1 NOT READY, 2 this machine is not connected yet or the CLI could not run.
|
|
16
|
+
How to read each line: references/reading-ready.md.`;
|
|
16
17
|
|
|
17
18
|
const args = process.argv.slice(2);
|
|
18
19
|
if (args.includes("--help") || args.includes("-h")) {
|
|
@@ -27,13 +28,13 @@ if (unknown.length > 0) {
|
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
const res = runCli(["ready", "--json"]);
|
|
30
|
-
|
|
31
|
-
|
|
31
|
+
const report = tryJson(res.stdout);
|
|
32
|
+
if (!res.ran || (res.code === 2 && !report)) {
|
|
33
|
+
console.error(res.stderr.trim() || "catalyst ready refused");
|
|
32
34
|
process.exit(2);
|
|
33
35
|
}
|
|
34
|
-
const report = parseJson(res.stdout);
|
|
35
36
|
if (!report || !Array.isArray(report.checks)) {
|
|
36
|
-
console.error(res.stderr.trim() || res.stdout.trim() || "catalyst
|
|
37
|
+
console.error(res.stderr.trim() || res.stdout.trim() || "catalyst ready printed no report");
|
|
37
38
|
process.exit(res.code === 0 ? 1 : res.code);
|
|
38
39
|
}
|
|
39
40
|
if (args.includes("--json")) {
|
|
@@ -70,6 +71,6 @@ if (failures.length > 0) {
|
|
|
70
71
|
const notes = report.checks.filter((c) => c.note && !c.ok);
|
|
71
72
|
if (notes.length > 0) {
|
|
72
73
|
console.log("");
|
|
73
|
-
console.log(`Notes that do not block: ${notes.map((c) => c.id).join(", ")} — see references/
|
|
74
|
+
console.log(`Notes that do not block: ${notes.map((c) => c.id).join(", ")} — see references/reading-ready.md`);
|
|
74
75
|
}
|
|
75
76
|
process.exit(report.ready ? 0 : 1);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// lib/cli.mjs — the one way a skill script reaches Catalyst Cloud: spawn the catalyst
|
|
2
|
+
// lib/cli.mjs — the one way a skill script reaches Catalyst Cloud: spawn the catalyst CLI.
|
|
3
3
|
// The CLI holds the SDK and the key; this file holds neither. It reads customer.json only to learn
|
|
4
4
|
// where the CLI lives. Run any script beside this one with --help; this file is a library.
|
|
5
5
|
//
|
|
@@ -13,7 +13,9 @@ import { existsSync, readFileSync } from "node:fs";
|
|
|
13
13
|
import { join } from "node:path";
|
|
14
14
|
import { CONNECT_COMMAND, hasCredential } from "./credential.mjs";
|
|
15
15
|
|
|
16
|
-
export const PACKAGE = "@catalyst-cloud/
|
|
16
|
+
export const PACKAGE = "@catalyst-cloud/cli";
|
|
17
|
+
/** The package ships two commands, so npx needs the one to run named: `npx -p <package> catalyst`. */
|
|
18
|
+
export const NPX_ARGS = ["-p", PACKAGE, "catalyst"];
|
|
17
19
|
export const NOT_CONFIGURED_EXIT = 2;
|
|
18
20
|
export const CONNECT_LINE = CONNECT_COMMAND;
|
|
19
21
|
|
|
@@ -53,11 +55,11 @@ export function cliTarget(cfg = tryLoadConfig()) {
|
|
|
53
55
|
const recorded = recordedPath !== null;
|
|
54
56
|
return recorded
|
|
55
57
|
? { command: process.execPath, prefix: [cfg.cliPath], via: `node ${cfg.cliPath}`, recorded: true }
|
|
56
|
-
: { command: "npx", prefix:
|
|
58
|
+
: { command: "npx", prefix: NPX_ARGS, via: `npx -p ${PACKAGE} catalyst`, recorded: false };
|
|
57
59
|
}
|
|
58
60
|
|
|
59
61
|
/**
|
|
60
|
-
* Run one catalyst
|
|
62
|
+
* Run one catalyst verb. Returns {code, stdout, stderr, ran} and never exits: a verb that
|
|
61
63
|
* refuses because the machine is not connected is a READING, not a failure of this script.
|
|
62
64
|
* `ran` is false when the CLI could not be started at all.
|
|
63
65
|
*/
|
|
@@ -6,12 +6,12 @@
|
|
|
6
6
|
//
|
|
7
7
|
// customer.json carries exactly one credential: a personal key (`key`), or the keyless login's
|
|
8
8
|
// session (`auth`, the recommended rail). A script never reads either for its value: it spawns the
|
|
9
|
-
// catalyst
|
|
9
|
+
// catalyst CLI, which authenticates with whichever is present and refreshes a login's token
|
|
10
10
|
// itself. A new credential kind lands here, once.
|
|
11
11
|
|
|
12
12
|
/** The command that connects this machine, as every not-connected line names it. */
|
|
13
13
|
export const CONNECT_COMMAND =
|
|
14
|
-
"npx @catalyst-cloud/catalyst
|
|
14
|
+
"npx -p @catalyst-cloud/cli catalyst login (or, with a personal key: CATALYST_CLOUD_TOKEN=<your personal key> npx -p @catalyst-cloud/cli catalyst login)";
|
|
15
15
|
|
|
16
16
|
/** True when `cfg` (parsed customer.json) holds a usable credential of either kind. Never throws. */
|
|
17
17
|
export function hasCredential(cfg) {
|
|
@@ -14,6 +14,7 @@ import { runLocalSync } from "./local-sync.mjs";
|
|
|
14
14
|
const SPEC = {
|
|
15
15
|
next: { help: "print only the single next step" },
|
|
16
16
|
json: { help: "one JSON document instead of the report" },
|
|
17
|
+
repo: { value: true, help: "a checkout of a mapped repository on this machine: its agent setup (AGENTS.md block, portable layout) is read and reported, never changed" },
|
|
17
18
|
};
|
|
18
19
|
const NOTES = [
|
|
19
20
|
"Reads, in this order: `status` (machine), `ready --json` (machine checks and project checks, kept apart),",
|
|
@@ -22,6 +23,8 @@ const NOTES = [
|
|
|
22
23
|
"`contract --path codingAccounts` and `accounts --json` (coding accounts, and which one needs a new credential), and each",
|
|
23
24
|
"project's hosts_current check with its fixedWhere (host), and each project's environment_declared check with its per-repository notes (repository declarations). The teams read is refreshed, so a mapping just saved reads back mapped.",
|
|
24
25
|
"Reads `capabilities --json` once: when the installed CLI can run a step for this person's role (`team check`, `team map`), the next step is that command; otherwise the page, with who can.",
|
|
26
|
+
"Reads `legacy --json` when the CLI has the verb: leftovers of the old local Catalyst runtime become a machine line and a note; removing them is the person's yes.",
|
|
27
|
+
"With --repo <path>, reads `repo agent-setup <path> --json` (a read; nothing changes) and adds a `repository agent setup` part that never blocks: the Catalyst block in AGENTS.md and the portable layout, with the writes named for the person to approve.",
|
|
25
28
|
"Also runs `gh repo view <owner>/thoughts` for each registered repository's owner, as a note: it shows the repository exists, never that the GitHub App can reach it.",
|
|
26
29
|
"When the tenant serves a contract version this CLI refuses, runs `npm view @catalyst-cloud/cli version` once to say whether a newer CLI is published.",
|
|
27
30
|
"Writes nothing and changes nothing. Runs before this machine is connected — that is one of the states it reports.",
|
|
@@ -29,7 +32,7 @@ const NOTES = [
|
|
|
29
32
|
|
|
30
33
|
const { help, flags, positionals } = parseFlags(process.argv.slice(2), SPEC);
|
|
31
34
|
if (help) {
|
|
32
|
-
printHelp("node scripts/where-am-i.mjs [--next] [--json]", SPEC, NOTES);
|
|
35
|
+
printHelp("node scripts/where-am-i.mjs [--next] [--json] [--repo <path>]", SPEC, NOTES);
|
|
33
36
|
process.exit(0);
|
|
34
37
|
}
|
|
35
38
|
if (positionals.length > 0) {
|
|
@@ -155,6 +158,19 @@ if (connected) {
|
|
|
155
158
|
const capDoc = tryJson(runCli(["capabilities", "--json"]).stdout);
|
|
156
159
|
capabilities = Array.isArray(capDoc?.capabilities) ? capDoc.capabilities : null;
|
|
157
160
|
}
|
|
161
|
+
// Leftovers of the old local Catalyst runtime (its plugin, jobs, commands, state), from the CLI's own
|
|
162
|
+
// fixed list. Reported on the machine part and as a note; removal is the person's yes, never this script's.
|
|
163
|
+
let legacyNote = null;
|
|
164
|
+
if (verbAvailable("legacy")) {
|
|
165
|
+
const legacyDoc = tryJson(runCli(["legacy", "--json"]).stdout);
|
|
166
|
+
const found = Array.isArray(legacyDoc?.found) ? legacyDoc.found : [];
|
|
167
|
+
if (found.length > 0) {
|
|
168
|
+
const machine = parts.find((p) => p.part === "machine");
|
|
169
|
+
const names = found.map((f) => `${f.kind} ${f.name}`);
|
|
170
|
+
machine?.lines.push(`note leftovers of the old local Catalyst runtime (${found.length}): ${names.slice(0, 6).join(", ")}${found.length > 6 ? ", …" : ""}; removing them is strongly recommended: catalyst legacy --remove (the data folders are a separate yes, --data)`);
|
|
171
|
+
legacyNote = `this machine still carries ${found.length} piece${found.length === 1 ? "" : "s"} of the old local Catalyst runtime (${names.slice(0, 4).join(", ")}${found.length > 4 ? ", …" : ""}); offer catalyst legacy --remove once, strongly recommended, then --data as a separate question`;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
158
174
|
|
|
159
175
|
// ── person ────────────────────────────────────────────────────────────────────────────────────────
|
|
160
176
|
if (!connected) {
|
|
@@ -593,6 +609,45 @@ if (!connected) {
|
|
|
593
609
|
}
|
|
594
610
|
}
|
|
595
611
|
|
|
612
|
+
// ── repository agent setup (only with --repo) ─────────────────────────────────────────────────────
|
|
613
|
+
// A checkout the person named. Read through the CLI's own verb, never by this script opening files:
|
|
614
|
+
// the verb is the one place that knows the block's words and the portable layout. Never blocking:
|
|
615
|
+
// a repository that is not portable still runs; this is an offer, and the writes wait for a yes.
|
|
616
|
+
let repoNote = null;
|
|
617
|
+
let repoNext = null;
|
|
618
|
+
if (typeof flags.repo === "string" && flags.repo !== "") {
|
|
619
|
+
const REPO_INSTRUMENT = `repo agent-setup ${flags.repo} --json`;
|
|
620
|
+
if (!connected) {
|
|
621
|
+
add("repository agent setup", REPO_INSTRUMENT, "unreadable", ["not readable until this machine is connected"], null, null, false);
|
|
622
|
+
} else if (!verbAvailable("repo agent-setup")) {
|
|
623
|
+
add("repository agent setup", REPO_INSTRUMENT, "unreadable", ["this CLI has no repo agent-setup verb; update the CLI to read a checkout's agent setup"], null, null, false).next =
|
|
624
|
+
"update the CLI (it lacks repo agent-setup); the checkout's agent setup cannot be read until then (does not block anything)";
|
|
625
|
+
} else {
|
|
626
|
+
const res = runCli(["repo", "agent-setup", flags.repo, "--json"]);
|
|
627
|
+
const doc = tryJson(res.stdout);
|
|
628
|
+
if (doc === null) {
|
|
629
|
+
add("repository agent setup", REPO_INSTRUMENT, "unreadable", [`the checkout could not be read (${(res.stderr || res.stdout).trim().split("\n")[0] || "no output"})`], null, null, false).next =
|
|
630
|
+
`run this again with the checkout's real path; ${flags.repo} could not be read`;
|
|
631
|
+
} else {
|
|
632
|
+
const block = doc.agentsMd?.block ?? "unknown";
|
|
633
|
+
const verdict = doc.verdict ?? "unknown";
|
|
634
|
+
const ok = verdict === "portable" && block === "current";
|
|
635
|
+
const lines = [
|
|
636
|
+
`AGENTS.md: ${doc.agentsMd?.present ? `present; Catalyst block ${block}` : "absent"}`,
|
|
637
|
+
`CLAUDE.md: ${doc.claudeMd?.present ? (doc.claudeMd.importsAgentsMd ? "imports AGENTS.md" : `${doc.claudeMd.otherLines ?? "?"} lines of its own guidance, no @AGENTS.md import`) : "absent"}`,
|
|
638
|
+
`layout: ${verdict}${Array.isArray(doc.plan) && doc.plan.length ? ` — ${doc.plan.join("; ")}` : ""}${Array.isArray(doc.blockers) && doc.blockers.length ? ` — by hand: ${doc.blockers.join("; ")}` : ""}`,
|
|
639
|
+
];
|
|
640
|
+
const offers = [];
|
|
641
|
+
if (block !== "current") offers.push(`the Catalyst block for AGENTS.md (catalyst repo agents-block ${flags.repo} --write)`);
|
|
642
|
+
if (verdict === "convertible") offers.push(`the portable layout (catalyst repo agent-setup ${flags.repo} --apply)`);
|
|
643
|
+
if (verdict === "needs_hand_merge") offers.push("a hand merge first (the layout line names what)");
|
|
644
|
+
repoNext = ok ? null : `say in one clause what the checkout holds, then offer ${offers.join(" and ")}, each after a yes, on a branch for the pull request the person opens`;
|
|
645
|
+
add("repository agent setup", REPO_INSTRUMENT, ok ? "ok" : "unfinished", lines, ok ? null : "you, after the person's yes, in their checkout; the pull request is theirs", ok ? null : `catalyst repo agent-setup ${flags.repo}`, false);
|
|
646
|
+
if (!ok) repoNote = `repository ${flags.repo}: Catalyst block ${block}, layout ${verdict} — offer ${offers.join(" and ")} after a yes (references/repository-agent-setup.md)`;
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
|
|
596
651
|
// ── the single next step ──────────────────────────────────────────────────────────────────────────
|
|
597
652
|
// The machine's next action is not one sentence: an unconnected machine needs the login, and a
|
|
598
653
|
// connected one needs whatever check failed — and `ready` already printed that check's own fix, so
|
|
@@ -620,6 +675,7 @@ const NEXT = {
|
|
|
620
675
|
repositories: "install the GitHub App on the Connections page, granting it the repository you want worked; registering that repository on the Repositories page, attached to the project, is the step right after",
|
|
621
676
|
"coding accounts": accountsNext,
|
|
622
677
|
"repository declarations": declNext,
|
|
678
|
+
"repository agent setup": repoNext ?? "read the checkout's agent setup again",
|
|
623
679
|
host: "connect a Catalyst host",
|
|
624
680
|
};
|
|
625
681
|
// The parts are read in the order their data allows and reported in the order a person can act on
|
|
@@ -627,7 +683,7 @@ const NEXT = {
|
|
|
627
683
|
// workspace's Linear integration, the project, the GitHub App with its repository, the person's own
|
|
628
684
|
// connected accounts (personal GitHub after the repository proves the App), the repository's
|
|
629
685
|
// declaration, and last the host. `--next` is the first unfinished part in this order.
|
|
630
|
-
const ORDER = ["machine", "coding accounts", "account", "projects", "repositories", "person", "repository declarations", "host"];
|
|
686
|
+
const ORDER = ["machine", "coding accounts", "account", "projects", "repositories", "person", "repository declarations", "repository agent setup", "host"];
|
|
631
687
|
parts.sort((a, b) => ORDER.indexOf(a.part) - ORDER.indexOf(b.part));
|
|
632
688
|
// A personal Linear grant cannot start until the tenant's Linear workspace exists. Once that account
|
|
633
689
|
// connection is present, a missing personal grant becomes the next member step before project setup.
|
|
@@ -680,9 +736,9 @@ if (contractMismatch !== null && stuck !== null) {
|
|
|
680
736
|
const finished = parts.every((p) => p.verdict === "ok");
|
|
681
737
|
|
|
682
738
|
if (flags.json) {
|
|
683
|
-
console.log(JSON.stringify({ cli: via, connected, cloud, personalConnections, parts, localSync, next, finished, notes: retireNote
|
|
739
|
+
console.log(JSON.stringify({ cli: via, connected, cloud, personalConnections, parts, localSync, next, finished, notes: [retireNote, repoNote, legacyNote].filter((n) => n !== null) }));
|
|
684
740
|
} else if (flags.next) {
|
|
685
|
-
process.on("exit", () => {
|
|
741
|
+
process.on("exit", () => { for (const n of [retireNote, repoNote, legacyNote]) if (n !== null) console.log(`note: ${n}`); });
|
|
686
742
|
if (next === null) console.log("nothing left: every part is finished, a coding account is enrolled and the host check passes. Move one card into the project's start stage (usually Todo).");
|
|
687
743
|
else console.log(`${next.part}: ${next.action}${next.blocking ? "" : " (does not block the steps below)"}${next.owner ? ` — who: ${next.owner}` : ""}${next.where ? ` — ${next.where.startsWith("http") ? "where" : "do"}: ${next.where}` : ""}`);
|
|
688
744
|
} else {
|