@catalyst-cloud/cli 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +75 -0
- package/LICENSE +21 -0
- package/README.md +205 -0
- package/bin/catalyst-skills.js +8 -0
- package/bin/catalyst.js +5 -0
- package/bin/launch.js +154 -0
- package/dist/args.js +280 -0
- package/dist/ask.js +161 -0
- package/dist/browser.js +20 -0
- package/dist/cli.js +397 -0
- package/dist/config.js +241 -0
- package/dist/contract-types.js +4 -0
- package/dist/contract.js +184 -0
- package/dist/detach.js +10 -0
- package/dist/environment.js +207 -0
- package/dist/errors.js +27 -0
- package/dist/events.js +106 -0
- package/dist/execution.js +451 -0
- package/dist/oauth.js +300 -0
- package/dist/pagination.js +76 -0
- package/dist/prompt.js +35 -0
- package/dist/published.js +79 -0
- package/dist/query.js +248 -0
- package/dist/ready.js +380 -0
- package/dist/release.js +142 -0
- package/dist/replica.js +614 -0
- package/dist/runtime-store.js +135 -0
- package/dist/runtime-verb.js +66 -0
- package/dist/runtime.js +87 -0
- package/dist/sdk.js +29 -0
- package/dist/secret.js +190 -0
- package/dist/semver.js +18 -0
- package/dist/skill-shape.js +189 -0
- package/dist/skills.js +129 -0
- package/dist/transport.js +205 -0
- package/dist/ts-deps-loader.js +113 -0
- package/dist/watch/consumer.js +141 -0
- package/dist/watch/cursor-file.js +62 -0
- package/dist/watch.js +175 -0
- package/dist/write.js +224 -0
- package/package.json +60 -0
- package/skills/catalyst-github/SKILL.md +35 -0
- package/skills/catalyst-github/agents/openai.yaml +6 -0
- package/skills/catalyst-github/agents/portability.yaml +4 -0
- package/skills/catalyst-github/references/is-it-mergeable.md +57 -0
- package/skills/catalyst-github/references/what-a-pr-accumulates.md +61 -0
- package/skills/catalyst-github/scripts/is-it-mergeable.mjs +124 -0
- package/skills/catalyst-github/scripts/lib/cli.mjs +103 -0
- package/skills/catalyst-github/scripts/lib/credential.mjs +29 -0
- package/skills/catalyst-github/scripts/lib/pull.mjs +82 -0
- package/skills/catalyst-github/scripts/read-pr.mjs +97 -0
- package/skills/catalyst-linear/SKILL.md +43 -0
- package/skills/catalyst-linear/agents/openai.yaml +6 -0
- package/skills/catalyst-linear/agents/portability.yaml +5 -0
- package/skills/catalyst-linear/references/reading-a-ticket.md +52 -0
- package/skills/catalyst-linear/references/what-a-ticket-accumulates.md +53 -0
- package/skills/catalyst-linear/references/writing-to-linear.md +43 -0
- package/skills/catalyst-linear/scripts/comment.mjs +59 -0
- package/skills/catalyst-linear/scripts/create-ticket.mjs +44 -0
- package/skills/catalyst-linear/scripts/label.mjs +48 -0
- package/skills/catalyst-linear/scripts/lib/cli.mjs +164 -0
- package/skills/catalyst-linear/scripts/lib/credential.mjs +29 -0
- package/skills/catalyst-linear/scripts/move.mjs +41 -0
- package/skills/catalyst-linear/scripts/read-ticket.mjs +93 -0
- package/skills/catalyst-linear/scripts/search.mjs +49 -0
- package/skills/catalyst-onboard/SKILL.md +57 -0
- package/skills/catalyst-onboard/agents/openai.yaml +6 -0
- package/skills/catalyst-onboard/agents/portability.yaml +5 -0
- package/skills/catalyst-onboard/references/declaring-a-repository.md +23 -0
- package/skills/catalyst-onboard/references/skill-sources.md +35 -0
- package/skills/catalyst-onboard/references/the-one-path.md +149 -0
- package/skills/catalyst-onboard/references/what-a-phase-needs.md +46 -0
- package/skills/catalyst-onboard/references/what-the-browser-owns.md +50 -0
- package/skills/catalyst-onboard/references/who-fixes-what.md +44 -0
- package/skills/catalyst-onboard/scripts/lib/cli.mjs +117 -0
- package/skills/catalyst-onboard/scripts/lib/credential.mjs +29 -0
- package/skills/catalyst-onboard/scripts/where-am-i.mjs +345 -0
- package/skills/catalyst-setup/SKILL.md +36 -0
- package/skills/catalyst-setup/agents/openai.yaml +6 -0
- package/skills/catalyst-setup/agents/portability.yaml +4 -0
- package/skills/catalyst-setup/references/what-each-check-means.md +88 -0
- package/skills/catalyst-setup/scripts/check.mjs +75 -0
- package/skills/catalyst-setup/scripts/lib/cli.mjs +103 -0
- package/skills/catalyst-setup/scripts/lib/credential.mjs +29 -0
- package/skills/catalyst-setup/scripts/replica-status.mjs +46 -0
- package/skills/connect-me/SKILL.md +63 -0
- package/skills/connect-me/agents/openai.yaml +6 -0
- package/skills/connect-me/agents/portability.yaml +5 -0
- package/skills/connect-me/references/keeping-the-replica-running.md +88 -0
- package/skills/connect-me/scripts/lib/cli.mjs +185 -0
- package/skills/connect-me/scripts/lib/credential.mjs +29 -0
- package/skills/connect-me/scripts/verify-connection.mjs +68 -0
- package/skills/how-catalyst-works/SKILL.md +43 -0
- package/skills/how-catalyst-works/agents/openai.yaml +6 -0
- package/skills/how-catalyst-works/agents/portability.yaml +4 -0
- package/skills/how-catalyst-works/references/coding-accounts.md +51 -0
- package/skills/how-catalyst-works/references/stages-and-mapping.md +56 -0
- package/skills/how-catalyst-works/references/the-ladder.md +41 -0
- package/skills/how-catalyst-works/references/what-catalyst-is.md +30 -0
- package/skills/how-catalyst-works/references/what-runs-next.md +77 -0
- package/skills/how-catalyst-works/references/when-a-phase-fails.md +57 -0
- package/skills/how-catalyst-works/scripts/explain-ticket.mjs +41 -0
- package/skills/how-catalyst-works/scripts/lib/cli.mjs +164 -0
- package/skills/how-catalyst-works/scripts/lib/credential.mjs +29 -0
- package/skills/how-catalyst-works/scripts/show-my-map.mjs +94 -0
- package/skills/how-catalyst-works/scripts/whats-running.mjs +65 -0
- package/skills/run-this-project/SKILL.md +45 -0
- package/skills/run-this-project/agents/openai.yaml +6 -0
- package/skills/run-this-project/agents/portability.yaml +5 -0
- package/skills/run-this-project/assets/stall-policy.json +15 -0
- package/skills/run-this-project/references/making-work-ready.md +60 -0
- package/skills/run-this-project/references/reacting-to-events.md +76 -0
- package/skills/run-this-project/references/stalls-and-escalation.md +63 -0
- package/skills/run-this-project/scripts/lib/cli.mjs +185 -0
- package/skills/run-this-project/scripts/lib/credential.mjs +29 -0
- package/skills/run-this-project/scripts/make-ready.mjs +64 -0
- package/skills/run-this-project/scripts/scope-status.mjs +0 -0
- package/skills/run-this-project/scripts/watch-scope.mjs +61 -0
- package/skills/unstick/SKILL.md +41 -0
- package/skills/unstick/agents/openai.yaml +6 -0
- package/skills/unstick/agents/portability.yaml +5 -0
- package/skills/unstick/references/playbook.md +51 -0
- package/skills/unstick/scripts/lib/cli.mjs +135 -0
- package/skills/unstick/scripts/lib/credential.mjs +29 -0
- package/skills/unstick/scripts/unstick.mjs +57 -0
- package/skills/what-needs-me/SKILL.md +41 -0
- package/skills/what-needs-me/agents/openai.yaml +6 -0
- package/skills/what-needs-me/agents/portability.yaml +5 -0
- package/skills/what-needs-me/references/raising-a-decision.md +41 -0
- package/skills/what-needs-me/references/reading-the-inbox.md +38 -0
- package/skills/what-needs-me/references/settling-an-answer.md +37 -0
- package/skills/what-needs-me/scripts/inbox.mjs +56 -0
- package/skills/what-needs-me/scripts/lib/cli.mjs +135 -0
- package/skills/what-needs-me/scripts/lib/credential.mjs +29 -0
- package/skills/what-needs-me/scripts/raise.mjs +53 -0
- package/skills/what-needs-me/scripts/settle.mjs +73 -0
- package/skills/whats-happening/SKILL.md +43 -0
- package/skills/whats-happening/agents/openai.yaml +6 -0
- package/skills/whats-happening/agents/portability.yaml +4 -0
- package/skills/whats-happening/assets/status-reply.json +77 -0
- package/skills/whats-happening/references/reading-the-board.md +43 -0
- package/skills/whats-happening/references/reprioritising.md +37 -0
- package/skills/whats-happening/references/routing-work.md +36 -0
- package/skills/whats-happening/references/status-reply.md +34 -0
- package/skills/whats-happening/references/why-is-it-stuck.md +62 -0
- package/skills/whats-happening/scripts/explain.mjs +28 -0
- package/skills/whats-happening/scripts/lib/cli.mjs +135 -0
- package/skills/whats-happening/scripts/lib/credential.mjs +29 -0
- package/skills/whats-happening/scripts/snapshot.mjs +149 -0
- package/vendor/README.md +9 -0
- package/vendor/paths/index.d.ts +85 -0
- package/vendor/paths/index.js +148 -0
- package/vendor/paths/legacy-installer.d.ts +36 -0
- package/vendor/paths/legacy-installer.js +154 -0
- package/vendor/paths/node.d.ts +18 -0
- package/vendor/paths/node.js +102 -0
- package/vendor/paths/provenance.json +17 -0
package/dist/release.js
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
// release.ts — `catalyst-skills release`: a person's release of a parked or held ticket, or of every
|
|
2
|
+
// ticket on one team parked under one failure class, through the contract's `ticket-release` and
|
|
3
|
+
// `ticket-release-class` routes. The cloud reads every governor holding the ticket and either releases
|
|
4
|
+
// all of them or releases nothing and names, per governor, the human action that does fix it; this verb
|
|
5
|
+
// prints that answer and exits 1 on a refusal so a script can branch on it.
|
|
6
|
+
//
|
|
7
|
+
// ⛔ NOTHING IS RELEASED WITHOUT A REASON. `--because` (what changed) is required on a real release and
|
|
8
|
+
// is recorded in the tenant's release audit; only `--dry-run` may omit it. `--retry-unchanged` is the
|
|
9
|
+
// explicit statement that something the mirror cannot see changed — the cloud refuses an unchanged
|
|
10
|
+
// cause without it.
|
|
11
|
+
import { flagBool, flagString, positionals } from "./args.js";
|
|
12
|
+
import { requireConfig } from "./config.js";
|
|
13
|
+
import { loadContract } from "./contract.js";
|
|
14
|
+
import { CliError, UsageError } from "./errors.js";
|
|
15
|
+
import { needsNewerCloud } from "./execution.js";
|
|
16
|
+
import { apiClient } from "./transport.js";
|
|
17
|
+
/** One release written as a person reads it: "unparked implement", "cleared the validate hold". */
|
|
18
|
+
export function describeAction(a) {
|
|
19
|
+
switch (a.op) {
|
|
20
|
+
case "unpark":
|
|
21
|
+
return `unparked ${a.phase ?? "a phase"}`;
|
|
22
|
+
case "clear_validate_hold":
|
|
23
|
+
return "cleared the validate hold";
|
|
24
|
+
case "clear_no_change_hold":
|
|
25
|
+
return "cleared the no-change hold";
|
|
26
|
+
case "grant_round_threshold_cycle":
|
|
27
|
+
return "bought one more repair cycle";
|
|
28
|
+
default:
|
|
29
|
+
return `${a.op}${a.phase ? ` at ${a.phase}` : ""}`;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
const refusalLine = (r) => ` ${r.code}: ${r.humanAction}`;
|
|
33
|
+
export function renderTicketRelease(ticket, r) {
|
|
34
|
+
if (r.error === "team_changed") {
|
|
35
|
+
return [`${ticket} moved from team ${r.expectedTeamKey ?? "(none)"} to ${r.teamKey ?? "(none)"} while the release was being checked — run it again`];
|
|
36
|
+
}
|
|
37
|
+
const lines = [];
|
|
38
|
+
const dry = r.dryRun === true;
|
|
39
|
+
if (r.outcome === "nothing-held") {
|
|
40
|
+
lines.push(`${ticket}: nothing holds this ticket — run \`catalyst-skills explain ${ticket}\` for why it is not running`);
|
|
41
|
+
}
|
|
42
|
+
else if (r.outcome === "refused") {
|
|
43
|
+
lines.push(dry ? `${ticket} (dry run): would be refused — nothing would be released:` : `${ticket}: refused — nothing was released:`);
|
|
44
|
+
for (const x of r.refused ?? [])
|
|
45
|
+
lines.push(refusalLine(x));
|
|
46
|
+
const blocked = r.releasable ?? [];
|
|
47
|
+
if (blocked.length > 0)
|
|
48
|
+
lines.push(` (it would otherwise have ${blocked.map(describeAction).join(", ")})`);
|
|
49
|
+
}
|
|
50
|
+
else if (dry) {
|
|
51
|
+
lines.push(`${ticket} (dry run): would release — ${(r.releasable ?? []).map(describeAction).join(", ")}`);
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
lines.push(`${ticket}: released — ${(r.released ?? []).map(describeAction).join(", ")}`);
|
|
55
|
+
}
|
|
56
|
+
for (const w of r.warnings ?? [])
|
|
57
|
+
lines.push(`warning: ${w}`);
|
|
58
|
+
return lines;
|
|
59
|
+
}
|
|
60
|
+
export function renderClassRelease(r) {
|
|
61
|
+
const released = r.released ?? [];
|
|
62
|
+
const refused = r.refused ?? [];
|
|
63
|
+
const nothing = r.nothingHeld ?? [];
|
|
64
|
+
const head = `${r.team ?? "?"} ${r.class ?? "?"}${r.dryRun ? " (dry run)" : ""}: released ${released.length}, refused ${refused.length}, nothing held ${nothing.length}${r.truncated ? " (more remain — run it again)" : ""}`;
|
|
65
|
+
const lines = [head];
|
|
66
|
+
for (const t of released) {
|
|
67
|
+
const actions = r.dryRun ? (t.releasable ?? []) : (t.released ?? []);
|
|
68
|
+
lines.push(` ${r.dryRun ? "would release" : "released"} ${t.ticket ?? "?"}: ${actions.map(describeAction).join(", ")}`);
|
|
69
|
+
}
|
|
70
|
+
for (const t of refused) {
|
|
71
|
+
for (const x of t.refused ?? [])
|
|
72
|
+
lines.push(` refused ${t.ticket ?? "?"} — ${x.code}: ${x.humanAction}`);
|
|
73
|
+
}
|
|
74
|
+
if (nothing.length > 0)
|
|
75
|
+
lines.push(` nothing held: ${nothing.join(", ")}`);
|
|
76
|
+
return lines;
|
|
77
|
+
}
|
|
78
|
+
/** The contract's route by name, or the "your cloud is older" error when this tenant does not serve it. */
|
|
79
|
+
function releaseRoute(doc, name, cfg) {
|
|
80
|
+
const route = doc.routes.find((r) => r.method === "POST" && r.path.split("/").filter(Boolean).at(-1) === name);
|
|
81
|
+
if (!route)
|
|
82
|
+
throw needsNewerCloud(`release (the tenant contract serves no "${name}" route)`, cfg);
|
|
83
|
+
return route.path;
|
|
84
|
+
}
|
|
85
|
+
export async function cmdRelease(args, ctx) {
|
|
86
|
+
const [ticket, ...extra] = positionals(args);
|
|
87
|
+
const failureClass = flagString(args, "class");
|
|
88
|
+
const team = flagString(args, "team");
|
|
89
|
+
const because = flagString(args, "because");
|
|
90
|
+
const dryRun = flagBool(args, "dry-run");
|
|
91
|
+
const retryUnchanged = flagBool(args, "retry-unchanged");
|
|
92
|
+
if (extra.length > 0)
|
|
93
|
+
throw new UsageError("release takes one ticket");
|
|
94
|
+
if (failureClass !== undefined && ticket !== undefined) {
|
|
95
|
+
throw new UsageError("release takes a ticket or --class with --team, not both");
|
|
96
|
+
}
|
|
97
|
+
if (failureClass === undefined && ticket === undefined) {
|
|
98
|
+
throw new UsageError("release needs a ticket, or --class <failure-class> --team <K>");
|
|
99
|
+
}
|
|
100
|
+
if (failureClass !== undefined && team === undefined)
|
|
101
|
+
throw new UsageError("release --class needs --team <K>");
|
|
102
|
+
if (because === undefined && !dryRun) {
|
|
103
|
+
throw new UsageError("release needs --because <what changed> (recorded in the release audit), or --dry-run to preview");
|
|
104
|
+
}
|
|
105
|
+
const limitRaw = flagString(args, "limit");
|
|
106
|
+
const limit = limitRaw === undefined ? undefined : Number(limitRaw);
|
|
107
|
+
if (limit !== undefined && !Number.isInteger(limit))
|
|
108
|
+
throw new UsageError("--limit must be an integer");
|
|
109
|
+
const cfg = requireConfig(ctx);
|
|
110
|
+
const { doc } = await loadContract(ctx, cfg);
|
|
111
|
+
const api = apiClient(cfg, ctx);
|
|
112
|
+
const common = { ...(because !== undefined ? { because } : {}), retryUnchanged, dryRun };
|
|
113
|
+
if (failureClass !== undefined) {
|
|
114
|
+
const path = releaseRoute(doc, "ticket-release-class", cfg);
|
|
115
|
+
const res = await api.postJson(path, {
|
|
116
|
+
team,
|
|
117
|
+
class: failureClass,
|
|
118
|
+
...common,
|
|
119
|
+
...(limit !== undefined ? { limit } : {}),
|
|
120
|
+
});
|
|
121
|
+
if (args.json)
|
|
122
|
+
ctx.stdout(JSON.stringify(res.body));
|
|
123
|
+
else
|
|
124
|
+
for (const line of renderClassRelease(res.body))
|
|
125
|
+
ctx.stdout(line);
|
|
126
|
+
// A real class release that refused any ticket exits 1, the same contract as a single refusal.
|
|
127
|
+
return res.body.dryRun !== true && (res.body.refused ?? []).length > 0 ? 1 : 0;
|
|
128
|
+
}
|
|
129
|
+
const id = ticket;
|
|
130
|
+
const path = releaseRoute(doc, "ticket-release", cfg);
|
|
131
|
+
const res = await api.postJson(path, { ticket: id, ...common }, { accept: [404, 409] });
|
|
132
|
+
if (res.status === 404) {
|
|
133
|
+
throw new CliError(`ticket ${id} is not in this tenant's mirror — check the identifier`, "ticket-unknown");
|
|
134
|
+
}
|
|
135
|
+
if (args.json)
|
|
136
|
+
ctx.stdout(JSON.stringify(res.body));
|
|
137
|
+
else
|
|
138
|
+
for (const line of renderTicketRelease(id, res.body))
|
|
139
|
+
ctx.stdout(line);
|
|
140
|
+
const refused = res.status === 409 || (res.body.outcome === "refused" && res.body.dryRun !== true);
|
|
141
|
+
return refused ? 1 : 0;
|
|
142
|
+
}
|