@h-rig/init-plugin 0.0.6-alpha.157 → 0.0.6-alpha.158

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.
@@ -1,3 +1,2 @@
1
- export * from "./rig-init-builder";
2
- export * from "./setup";
1
+ export * from "@rig/init-lib";
3
2
  export * from "./plugin";
package/dist/src/index.js CHANGED
@@ -1,498 +1,43 @@
1
1
  // @bun
2
- var __defProp = Object.defineProperty;
3
- var __returnValue = (v) => v;
4
- function __exportSetter(name, newValue) {
5
- this[name] = __returnValue.bind(null, newValue);
6
- }
7
- var __export = (target, all) => {
8
- for (var name in all)
9
- __defProp(target, name, {
10
- get: all[name],
11
- enumerable: true,
12
- configurable: true,
13
- set: __exportSetter.bind(all, name)
14
- });
15
- };
16
- var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
17
-
18
- // packages/init-plugin/src/rig-init-builder.ts
19
- function buildRigInitConfigSource(input) {
20
- const lines = [`import { defineConfig } from "@rig/core/config";`];
21
- if (input.useStandardPlugin) {
22
- lines.push(`import { standardPlugins } from "@rig/standard-plugin/bundle";`);
23
- if (input.taskSource.kind === "github-issues") {
24
- lines.push(`import { createStateGitHubCredentialProvider } from "@rig/standard-plugin";`);
25
- }
26
- }
27
- lines.push(``, `export default defineConfig({`);
28
- const projectRepo = input.projectRepo ?? (input.taskSource.kind === "github-issues" ? `${input.taskSource.owner}/${input.taskSource.repo}` : undefined);
29
- lines.push(projectRepo ? ` project: { name: ${JSON.stringify(input.projectName)}, repo: ${JSON.stringify(projectRepo)} },` : ` project: { name: ${JSON.stringify(input.projectName)} },`);
30
- if (input.useStandardPlugin && input.taskSource.kind === "github-issues") {
31
- lines.push(` plugins: [...standardPlugins({`);
32
- lines.push(` taskSources: {`);
33
- lines.push(` githubCredentialProvider: createStateGitHubCredentialProvider(),`);
34
- lines.push(` githubWorkspaceId: ${JSON.stringify(`${input.taskSource.owner}/${input.taskSource.repo}`)},`);
35
- lines.push(` githubUserId: process.env.RIG_GITHUB_USER_ID ?? "server-selected-user",`);
36
- lines.push(` },`);
37
- lines.push(` })],`);
38
- } else {
39
- lines.push(` plugins: [${input.useStandardPlugin ? "...standardPlugins()" : ""}],`);
40
- }
41
- if (input.taskSource.kind === "github-issues") {
42
- lines.push(` taskSource: {`);
43
- lines.push(` kind: "github-issues",`);
44
- lines.push(` owner: ${JSON.stringify(input.taskSource.owner)},`);
45
- lines.push(` repo: ${JSON.stringify(input.taskSource.repo)},`);
46
- lines.push(` // labels: ["task"], // uncomment to filter by labels`);
47
- lines.push(` state: "open",`);
48
- if (input.taskSource.assignee?.trim()) {
49
- lines.push(` options: { assignee: ${JSON.stringify(input.taskSource.assignee.trim())} },`);
50
- }
51
- lines.push(` },`);
52
- } else {
53
- lines.push(` taskSource: {`);
54
- lines.push(` kind: "files",`);
55
- lines.push(` path: ${JSON.stringify(input.taskSource.path)},`);
56
- lines.push(` },`);
57
- }
58
- lines.push(` workspace: { mainRepo: ".", isolation: "worktree" },`);
59
- const sshTarget = input.sshTarget?.trim();
60
- lines.push(sshTarget ? ` runtime: { harness: "pi", mode: "yolo", server: { sshTarget: ${JSON.stringify(sshTarget)} } },` : ` runtime: { harness: "pi", mode: "yolo" }, // server.sshTarget unset = local placement`);
61
- lines.push(` planning: { mode: "auto" },`);
62
- lines.push(` github: {`);
63
- lines.push(` issueUpdates: "lifecycle",`);
64
- lines.push(` projects: { enabled: false },`);
65
- lines.push(` },`);
66
- lines.push(` automation: { maxValidationAttempts: 30, maxPrFixIterations: 100500 },`);
67
- lines.push(` pr: { mode: "auto", watchChecks: true, autoFixChecks: true, autoFixReview: true },`);
68
- lines.push(` merge: { mode: "auto", method: "repo-default", deleteBranch: "repo-default", bypass: false },`);
69
- lines.push(` issueAnalysis: { enabled: true, harness: "pi", mode: "continuous" },`);
70
- lines.push(`});`);
71
- lines.push(``);
72
- return lines.join(`
73
- `);
74
- }
75
-
76
- // packages/init-plugin/src/setup.ts
77
- var exports_setup = {};
78
- __export(exports_setup, {
79
- writeRigConnectionState: () => writeRigConnectionState,
80
- writeRigConfig: () => writeRigConfig,
81
- validateGitHubAuth: () => validateGitHubAuth,
82
- saveGitHubTokenLocally: () => saveGitHubTokenLocally,
83
- runSetup: () => runSetup,
84
- readRigConnectionStatus: () => readRigConnectionStatus,
85
- readRigConfigStatus: () => readRigConfigStatus,
86
- readGhAuthToken: () => readGhAuthToken,
87
- parseRepoSlugFromRemote: () => parseRepoSlugFromRemote,
88
- parseRepoSlug: () => parseRepoSlug,
89
- ensureRigPrivateDirs: () => ensureRigPrivateDirs,
90
- ensurePiRigInstalledForSetup: () => ensurePiRigInstalledForSetup,
91
- ensureGitignoreEntries: () => ensureGitignoreEntries,
92
- ensureGitHubLabels: () => ensureGitHubLabels,
93
- ensureGitHubAuth: () => ensureGitHubAuth,
94
- detectStartupStatus: () => detectStartupStatus,
95
- detectRigStartupStatus: () => detectRigStartupStatus,
96
- detectOriginRepoSlug: () => detectOriginRepoSlug,
97
- detectGhAuth: () => detectGhAuth,
98
- applyRigSetupProject: () => applyRigSetupProject
99
- });
100
- import { spawnSync } from "child_process";
101
- import { appendFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
102
- import { dirname, resolve } from "path";
103
- import {
104
- createGitHubAuthStore,
105
- probeGitHubRepository,
106
- resolveGitHubAuthStatus,
107
- saveGitHubTokenForProject
108
- } from "@rig/github-provider-plugin";
109
- import { addPlacement, selectPlacement } from "@rig/runtime/control-plane/placement";
110
- function cleanString(value) {
111
- return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
112
- }
113
- function parseRepoSlugFromRemote(remoteUrl) {
114
- const trimmed = remoteUrl.trim();
115
- const match = trimmed.match(/github\.com[:/]([^/\s]+)\/([^/\s.]+)(?:\.git)?$/i);
116
- return match ? `${match[1]}/${match[2]}` : null;
117
- }
118
- function parseRepoSlug(value) {
119
- const match = value.trim().match(/^([^/\s]+)\/([^/\s]+)$/);
120
- if (!match)
121
- throw new Error(`Invalid GitHub repo slug "${value}". Expected owner/repo.`);
122
- return { owner: match[1], repo: match[2], slug: `${match[1]}/${match[2]}` };
123
- }
124
- function runSyncCommand(command, input = {}) {
125
- const executable = command[0];
126
- if (!executable)
127
- throw new Error("command is required");
128
- return (input.spawn ?? spawnSync)(executable, [...command.slice(1)], {
129
- cwd: input.cwd,
130
- encoding: "utf8",
131
- timeout: input.timeoutMs ?? 1e4,
132
- env: input.env ?? process.env
133
- });
134
- }
135
- function detectOriginRepoSlug(projectRoot, deps = {}) {
136
- const result = runSyncCommand(["git", "-C", projectRoot, "remote", "get-url", "origin"], { timeoutMs: 5000, spawn: deps.spawn });
137
- if (result.status !== 0 || result.error)
138
- return null;
139
- return parseRepoSlugFromRemote(result.stdout.trim());
140
- }
141
- function connectionStatePath(projectRoot) {
142
- return resolve(projectRoot, ".rig", "state", "connection.json");
143
- }
144
- function projectLinkStatePath(projectRoot) {
145
- return resolve(projectRoot, ".rig", "state", "project-link.json");
146
- }
147
- function readJsonRecord(path) {
148
- if (!existsSync(path))
149
- return null;
150
- try {
151
- const parsed = JSON.parse(readFileSync(path, "utf-8"));
152
- return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
153
- } catch {
154
- return null;
155
- }
156
- }
157
- function writeJsonFile(path, value) {
158
- mkdirSync(dirname(path), { recursive: true });
159
- writeFileSync(path, `${JSON.stringify(value, null, 2)}
160
- `, "utf-8");
161
- }
162
- function ensureRigPrivateDirs(projectRoot) {
163
- mkdirSync(resolve(projectRoot, ".rig", "state"), { recursive: true });
164
- mkdirSync(resolve(projectRoot, ".rig", "logs"), { recursive: true });
165
- mkdirSync(resolve(projectRoot, ".rig", "runs"), { recursive: true });
166
- mkdirSync(resolve(projectRoot, ".rig", "tmp"), { recursive: true });
167
- mkdirSync(resolve(projectRoot, "artifacts"), { recursive: true });
168
- const taskConfigPath = resolve(projectRoot, ".rig", "task-config.json");
169
- if (!existsSync(taskConfigPath))
170
- writeFileSync(taskConfigPath, `{}
171
- `, "utf-8");
172
- }
173
- function ensureGitignoreEntries(projectRoot) {
174
- const path = resolve(projectRoot, ".gitignore");
175
- const existing = existsSync(path) ? readFileSync(path, "utf-8") : "";
176
- const lines = new Set(existing.split(/\r?\n/));
177
- const missing = [".rig/state/", ".rig/logs/", ".rig/runs/", ".rig/tmp/"].filter((entry) => !lines.has(entry));
178
- if (missing.length === 0)
179
- return;
180
- const prefix = existing.length > 0 && !existing.endsWith(`
181
- `) ? `
182
- ` : "";
183
- appendFileSync(path, `${prefix}${missing.join(`
184
- `)}
185
- `, "utf-8");
186
- }
187
- function writeRigConnectionState(projectRoot, slug, placement) {
188
- const previous = readJsonRecord(connectionStatePath(projectRoot)) ?? {};
189
- writeJsonFile(connectionStatePath(projectRoot), {
190
- ...previous,
191
- selected: placement.alias,
192
- project: slug,
193
- linkedAt: new Date().toISOString()
194
- });
195
- writeJsonFile(projectLinkStatePath(projectRoot), {
196
- repoSlug: slug,
197
- connection: placement.alias,
198
- linkedAt: new Date().toISOString()
199
- });
200
- if (placement.alias === "local")
201
- delete process.env.RIG_REMOTE_ALIAS;
202
- else
203
- process.env.RIG_REMOTE_ALIAS = placement.alias;
204
- }
205
- function writeRigConfig(projectRoot, slug) {
206
- const repo = parseRepoSlug(slug);
207
- writeFileSync(resolve(projectRoot, "rig.config.ts"), buildRigInitConfigSource({
208
- projectName: repo.slug,
209
- projectRepo: repo.slug,
210
- taskSource: { kind: "github-issues", owner: repo.owner, repo: repo.repo },
211
- useStandardPlugin: true
212
- }), "utf-8");
213
- }
214
- function readRigConfigStatus(projectRoot) {
215
- const path = resolve(projectRoot, "rig.config.ts");
216
- if (!existsSync(path))
217
- return { exists: false, valid: false, path, slug: null, reason: "missing rig.config.ts" };
218
- try {
219
- const source = readFileSync(path, "utf-8");
220
- const owner = source.match(/\bowner:\s*["']([^"']+)["']/)?.[1] ?? null;
221
- const repoValues = [...source.matchAll(/\brepo:\s*["']([^"']+)["']/g)].map((match) => match[1]).filter(Boolean);
222
- const taskRepo = repoValues.find((value) => !value.includes("/")) ?? null;
223
- const projectRepo = repoValues.find((value) => value.includes("/")) ?? null;
224
- const githubIssues = /\bkind:\s*["']github-issues["']/.test(source);
225
- const slug = owner && taskRepo ? `${owner}/${taskRepo}` : projectRepo;
226
- if (!githubIssues || !slug)
227
- return { exists: true, valid: false, path, slug: slug ?? null, reason: "rig.config.ts is not a GitHub Issues Rig config" };
228
- parseRepoSlug(slug);
229
- return { exists: true, valid: true, path, slug };
230
- } catch (error) {
231
- return { exists: true, valid: false, path, slug: null, reason: error instanceof Error ? error.message : String(error) };
232
- }
233
- }
234
- function readRigConnectionStatus(projectRoot) {
235
- const stateDir = resolve(projectRoot, ".rig", "state");
236
- if (!existsSync(stateDir))
237
- return { valid: false, selected: null, project: null, reason: "missing .rig/state" };
238
- const connection = readJsonRecord(connectionStatePath(projectRoot));
239
- if (!connection)
240
- return { valid: false, selected: null, project: null, reason: "missing or invalid .rig/state/connection.json" };
241
- const selected = cleanString(connection.selected);
242
- const project = cleanString(connection.project);
243
- if (!selected)
244
- return { valid: false, selected: null, project, reason: "connection.json is missing selected placement" };
245
- if (!project)
246
- return { valid: false, selected, project: null, reason: "connection.json is missing project slug" };
247
- try {
248
- parseRepoSlug(project);
249
- } catch (error) {
250
- return { valid: false, selected, project, reason: error instanceof Error ? error.message : String(error) };
251
- }
252
- return { valid: true, selected, project };
253
- }
254
- function detectGhAuth(projectRoot, slug, deps = {}) {
255
- const user = runSyncCommand(["gh", "api", "user", "--jq", ".login"], { cwd: projectRoot, timeoutMs: 5000, spawn: deps.spawn });
256
- if (user.status !== 0 || user.error || !user.stdout.trim())
257
- return null;
258
- const repo = runSyncCommand(["gh", "repo", "view", slug, "--json", "nameWithOwner", "--jq", ".nameWithOwner"], { cwd: projectRoot, timeoutMs: 5000, spawn: deps.spawn });
259
- if (repo.status !== 0 || repo.error)
260
- return { ok: false, source: "gh", login: user.stdout.trim(), detail: (repo.stderr || repo.stdout || "gh cannot access the selected repository").trim() };
261
- return { ok: true, source: "gh", login: user.stdout.trim(), detail: "gh CLI authentication can access the selected repository" };
262
- }
263
- async function validateGitHubAuth(projectRoot, slug, deps = {}) {
264
- if (!slug)
265
- return { ok: false, source: "missing", detail: "GitHub repo slug is unknown" };
266
- const status = resolveGitHubAuthStatus({ projectRoot, oauthConfigured: Boolean(process.env.RIG_GITHUB_OAUTH_CLIENT_ID?.trim()) });
267
- if (status.signedIn) {
268
- const store = createGitHubAuthStore(projectRoot);
269
- if (!status.selectedRepo) {
270
- store.saveSelectedRepo(slug);
271
- return { ok: true, source: "stored-token", login: status.login, detail: "stored Rig GitHub token selected for this repo", status: store.status({ oauthConfigured: status.oauthConfigured }) };
272
- }
273
- if (status.selectedRepo !== slug)
274
- return { ok: false, source: "stored-token", login: status.login, detail: `stored GitHub token is scoped to ${status.selectedRepo}, not ${slug}`, status };
275
- return { ok: true, source: "stored-token", login: status.login, detail: "stored Rig GitHub token is present", status };
276
- }
277
- const gh = detectGhAuth(projectRoot, slug, deps);
278
- if (gh)
279
- return gh;
280
- return { ok: false, source: "missing", detail: "Sign in with `gh auth login`, choose Setup \u2192 GitHub auth, or paste a token." };
281
- }
282
- async function saveGitHubTokenLocally(projectRoot, token, slug, deps = {}) {
283
- ensureRigPrivateDirs(projectRoot);
284
- await saveGitHubTokenForProject({
285
- projectRoot,
286
- token,
287
- tokenSource: "manual-token",
288
- selectedRepo: slug,
289
- ...deps.fetchUser ? { fetchUser: deps.fetchUser } : {}
290
- });
291
- createGitHubAuthStore(projectRoot).copyToLocalProjectRoot(projectRoot);
292
- }
293
- function readGhAuthToken(projectRoot, deps = {}) {
294
- const result = runSyncCommand(["gh", "auth", "token"], { cwd: projectRoot, timeoutMs: 1e4, spawn: deps.spawn });
295
- if (result.status !== 0 || result.error || !result.stdout.trim())
296
- throw new Error((result.stderr || result.stdout || "Could not read GitHub token from `gh auth token`.").trim());
297
- return result.stdout.trim();
298
- }
299
- async function ensureGitHubAuth(input) {
300
- const current = await validateGitHubAuth(input.projectRoot, input.slug, input.deps);
301
- if (current.ok && !input.token && !input.importGhToken)
302
- return current;
303
- if (input.token?.trim())
304
- await saveGitHubTokenLocally(input.projectRoot, input.token.trim(), input.slug, input.deps);
305
- else if (input.importGhToken)
306
- await saveGitHubTokenLocally(input.projectRoot, readGhAuthToken(input.projectRoot, input.deps), input.slug, input.deps);
307
- return validateGitHubAuth(input.projectRoot, input.slug, input.deps);
308
- }
309
- async function ensureGitHubLabels(input) {
310
- const repo = parseRepoSlug(input.slug);
311
- const token = input.token?.trim() || createGitHubAuthStore(input.projectRoot).readToken();
312
- if (token) {
313
- const fetchLabels = input.deps?.fetch ?? fetch;
314
- for (const name of RIG_LABELS_TO_ENSURE) {
315
- const metadata = RIG_LABEL_METADATA[name];
316
- const response = await fetchLabels(`https://api.github.com/repos/${encodeURIComponent(repo.owner)}/${encodeURIComponent(repo.repo)}/labels`, {
317
- method: "POST",
318
- headers: {
319
- accept: "application/vnd.github+json",
320
- authorization: `Bearer ${token}`,
321
- "content-type": "application/json",
322
- "user-agent": "rig"
323
- },
324
- body: JSON.stringify({ name, color: metadata.color, description: metadata.description })
325
- });
326
- if (response.ok)
327
- continue;
328
- const text = await response.text().catch(() => "");
329
- if (response.status === 422 && /already_exists|already exists|exists/i.test(text))
330
- continue;
331
- throw new Error(`Could not create GitHub label ${name}: ${response.status} ${text || response.statusText}`);
332
- }
333
- return { ok: true, method: "api", labels: RIG_LABELS_TO_ENSURE };
334
- }
335
- const gh = detectGhAuth(input.projectRoot, input.slug, input.deps);
336
- if (!gh?.ok)
337
- throw new Error("GitHub labels require a stored Rig token or gh auth.");
338
- for (const name of RIG_LABELS_TO_ENSURE) {
339
- const metadata = RIG_LABEL_METADATA[name];
340
- const result = runSyncCommand(["gh", "label", "create", name, "--repo", input.slug, "--color", metadata.color, "--description", metadata.description, "--force"], { cwd: input.projectRoot, timeoutMs: 1e4, spawn: input.deps?.spawn });
341
- if (result.status !== 0 || result.error)
342
- throw new Error(`gh label create ${name} failed: ${(result.stderr || result.stdout || result.error?.message || "unknown error").trim()}`);
343
- }
344
- return { ok: true, method: "gh", labels: RIG_LABELS_TO_ENSURE };
345
- }
346
- function piListContainsRigExtension(output) {
347
- return output.split(/\r?\n/).some((line) => line.includes("@h-rig/pi-rig") || /(?:^|[\\/])packages[\\/]pi-rig(?:$|\s)/.test(line));
348
- }
349
- function splitInstallCommand(value) {
350
- return value.match(/(?:[^\s"']+|"[^"]*"|'[^']*')+/g)?.map((part) => part.replace(/^["']|["']$/g, "")) ?? [];
351
- }
352
- function ensurePiRigInstalledForSetup(projectRoot, deps = {}) {
353
- if (process.env.RIG_TEST_FAKE_PI_INSTALL === "1")
354
- return { ok: true, detail: "fake-pi" };
355
- let version = runSyncCommand(["pi", "--version"], { cwd: projectRoot, timeoutMs: 1e4, spawn: deps.spawn });
356
- if (version.status !== 0 || version.error) {
357
- const installCommand = process.env.RIG_PI_INSTALL_COMMAND?.trim();
358
- if (!installCommand)
359
- throw new Error(`Pi/OMP is not available: ${(version.stderr || version.stdout || version.error?.message || "pi --version failed").trim()}. Install Pi/OMP or set RIG_PI_INSTALL_COMMAND.`);
360
- const parts = splitInstallCommand(installCommand);
361
- if (parts.length === 0)
362
- throw new Error("RIG_PI_INSTALL_COMMAND is empty.");
363
- const install = runSyncCommand(parts, { cwd: projectRoot, timeoutMs: 120000, spawn: deps.spawn });
364
- if (install.status !== 0 || install.error)
365
- throw new Error(`Pi/OMP install command failed: ${(install.stderr || install.stdout || install.error?.message || "unknown error").trim()}`);
366
- version = runSyncCommand(["pi", "--version"], { cwd: projectRoot, timeoutMs: 1e4, spawn: deps.spawn });
367
- if (version.status !== 0 || version.error)
368
- throw new Error(`Pi/OMP is still unavailable after install: ${(version.stderr || version.stdout || version.error?.message || "pi --version failed").trim()}`);
369
- }
370
- let list = runSyncCommand(["pi", "list"], { cwd: projectRoot, timeoutMs: 1e4, spawn: deps.spawn });
371
- if (!piListContainsRigExtension(`${list.stdout}
372
- ${list.stderr}`)) {
373
- const packageSource = existsSync(resolve(projectRoot, "packages", "pi-rig", "package.json")) ? resolve(projectRoot, "packages", "pi-rig") : "npm:@h-rig/pi-rig";
374
- const install = runSyncCommand(["pi", "install", packageSource], { cwd: projectRoot, timeoutMs: 120000, spawn: deps.spawn });
375
- if (install.status !== 0 || install.error)
376
- throw new Error(`Could not install/register the Rig OMP extension: ${(install.stderr || install.stdout || install.error?.message || "pi install failed").trim()}`);
377
- list = runSyncCommand(["pi", "list"], { cwd: projectRoot, timeoutMs: 1e4, spawn: deps.spawn });
378
- if (!piListContainsRigExtension(`${list.stdout}
379
- ${list.stderr}`))
380
- throw new Error("Pi/OMP is installed, but `pi list` does not show the Rig extension.");
381
- }
382
- return { ok: true, detail: (version.stdout || version.stderr).trim() || "pi available; rig extension registered" };
383
- }
384
- async function detectRigStartupStatus(input) {
385
- const projectRoot = input.projectRoot;
386
- const config = readRigConfigStatus(projectRoot);
387
- const state = readRigConnectionStatus(projectRoot);
388
- const detectedSlug = detectOriginRepoSlug(projectRoot, input.deps);
389
- const slug = config.slug ?? state.project ?? detectedSlug;
390
- const reasons = [];
391
- if (!detectedSlug)
392
- reasons.push("git origin does not point at a GitHub owner/repo remote");
393
- if (!config.exists || !config.valid)
394
- reasons.push(config.reason ?? "rig.config.ts is invalid");
395
- if (!state.valid)
396
- reasons.push(state.reason ?? ".rig/state/connection.json is invalid");
397
- if (config.slug && state.project && config.slug !== state.project)
398
- reasons.push(`rig.config.ts repo ${config.slug} does not match connection project ${state.project}`);
399
- if (slug && detectedSlug && slug !== detectedSlug)
400
- reasons.push(`configured repo ${slug} does not match git origin ${detectedSlug}`);
401
- const auth = await validateGitHubAuth(projectRoot, slug, input.deps);
402
- if (!auth.ok)
403
- reasons.push(auth.detail);
404
- return { configured: reasons.length === 0, projectRoot, slug, config, state, auth, reasons };
405
- }
406
- async function applyRigSetupProject(input) {
407
- const repo = parseRepoSlug(input.slug);
408
- ensureRigPrivateDirs(input.projectRoot);
409
- ensureGitignoreEntries(input.projectRoot);
410
- if (input.placement.alias !== "local" && input.placement.host) {
411
- addPlacement(input.projectRoot, { alias: input.placement.alias, host: input.placement.host, port: input.placement.port, token: input.placement.token, select: true });
412
- } else {
413
- selectPlacement(input.projectRoot, input.placement.alias);
414
- }
415
- writeRigConnectionState(input.projectRoot, repo.slug, input.placement);
416
- if (input.rewriteConfig)
417
- writeRigConfig(input.projectRoot, repo.slug);
418
- const labels = input.ensureLabels === false ? { skipped: true } : await ensureGitHubLabels({ projectRoot: input.projectRoot, slug: repo.slug, deps: input.deps });
419
- const pi = input.ensurePi === false ? { skipped: true } : ensurePiRigInstalledForSetup(input.projectRoot, input.deps);
420
- return { repoSlug: repo.slug, placement: input.placement.alias, configWritten: input.rewriteConfig, labels, pi };
421
- }
422
- async function runSetup(input) {
423
- const repo = parseRepoSlug(input.slug);
424
- const auth = await ensureGitHubAuth({ projectRoot: input.projectRoot, slug: repo.slug, token: input.githubToken, importGhToken: input.importGhToken, deps: input.deps });
425
- if (!auth.ok)
426
- throw new Error(auth.detail);
427
- const token = createGitHubAuthStore(input.projectRoot).readToken();
428
- const probe = await probeGitHubRepository({
429
- owner: repo.owner,
430
- repo: repo.repo,
431
- token,
432
- scopes: auth.status?.scopes ?? [],
433
- ...input.deps?.fetch ? { fetchRepository: input.deps.fetch } : {}
434
- });
435
- if (!probe.ok)
436
- throw new Error(probe.message);
437
- const result = await applyRigSetupProject({
438
- projectRoot: input.projectRoot,
439
- slug: repo.slug,
440
- placement: input.placement,
441
- rewriteConfig: input.rewriteConfig ?? true,
442
- ensurePi: input.ensurePi,
443
- ensureLabels: input.ensureLabels,
444
- deps: input.deps
445
- });
446
- const status = await detectRigStartupStatus({ projectRoot: input.projectRoot, deps: input.deps });
447
- if (!status.configured)
448
- throw new Error(`Setup wrote state but doctor still reports: ${status.reasons.join("; ")}`);
449
- return { ...result, status };
450
- }
451
- var RIG_LABELS_TO_ENSURE, RIG_LABEL_METADATA, detectStartupStatus;
452
- var init_setup = __esm(() => {
453
- RIG_LABELS_TO_ENSURE = [
454
- "rig:running",
455
- "rig:pr-open",
456
- "rig:ci-fixing",
457
- "rig:merging",
458
- "rig:done",
459
- "rig:needs-attention",
460
- "rig:ready",
461
- "rig:blocked",
462
- "rig:generated"
463
- ];
464
- RIG_LABEL_METADATA = {
465
- "rig:running": { color: "1d76db", description: "Rig is actively working on this issue." },
466
- "rig:pr-open": { color: "5319e7", description: "Rig opened a pull request for this issue." },
467
- "rig:ci-fixing": { color: "fbca04", description: "Rig is fixing CI or review feedback for this issue." },
468
- "rig:merging": { color: "0052cc", description: "Rig is merging the completed change for this issue." },
469
- "rig:done": { color: "0e8a16", description: "Rig completed this issue." },
470
- "rig:needs-attention": { color: "d93f0b", description: "Rig needs operator attention for this issue." },
471
- "rig:ready": { color: "0e8a16", description: "Rig issue analysis marked this issue ready." },
472
- "rig:blocked": { color: "d93f0b", description: "Rig issue analysis found blockers for this issue." },
473
- "rig:generated": { color: "c5def5", description: "Rig generated this follow-up issue." }
474
- };
475
- detectStartupStatus = detectRigStartupStatus;
476
- });
477
-
478
2
  // packages/init-plugin/src/index.ts
479
- init_setup();
3
+ export * from "@rig/init-lib";
480
4
 
481
5
  // packages/init-plugin/src/plugin.ts
482
6
  import { definePlugin } from "@rig/core/config";
7
+ import { defineCapability } from "@rig/core/capability";
8
+ import { DEPENDENCY_PREFLIGHT_CAPABILITY, PROJECT_SETUP, WORKSPACE_CONFIG_ENSURE } from "@rig/contracts";
9
+ import { ensureDeclarativeConfig, ensureRigConfigDependenciesInstalled, runSetup } from "@rig/init-lib";
483
10
  var INIT_PLUGIN_NAME = "@rig/init-plugin";
484
- var SETUP_CAPABILITY_ID = "workspace.setup";
11
+ var ProjectSetupCap = defineCapability(PROJECT_SETUP);
12
+ var DependencyPreflightCap = defineCapability(DEPENDENCY_PREFLIGHT_CAPABILITY);
13
+ var WorkspaceConfigEnsureCap = defineCapability(WORKSPACE_CONFIG_ENSURE);
14
+ var setupService = {
15
+ async runSetup(input) {
16
+ const kind = input.placement.kind === "remote" ? "remote" : "local";
17
+ return runSetup({ ...input, placement: { ...input.placement, kind } });
18
+ }
19
+ };
485
20
  var initPlugin = definePlugin({
486
21
  name: INIT_PLUGIN_NAME,
487
22
  version: "0.0.0-alpha.1",
488
23
  contributes: {
489
24
  capabilities: [
490
- {
491
- id: SETUP_CAPABILITY_ID,
25
+ ProjectSetupCap.provide(() => setupService, {
492
26
  title: "Project setup",
493
- description: "Scaffold rig.config.ts, ensure rig:* labels, install the Pi/OMP extension, and verify GitHub auth.",
494
- run: async (input) => (await Promise.resolve().then(() => (init_setup(), exports_setup))).runSetup(input)
495
- }
27
+ description: "Scaffold rig.config.ts, ensure rig:* labels, install the Pi/OMP extension, and verify GitHub auth."
28
+ }),
29
+ DependencyPreflightCap.provide(async () => {
30
+ return { ensureInstalled: ensureRigConfigDependenciesInstalled };
31
+ }, {
32
+ title: "Rig config dependency preflight",
33
+ description: "Pin a project's @rig/* config dependencies and run the package manager's install so a user-authored rig.config.ts can be evaluated."
34
+ }),
35
+ WorkspaceConfigEnsureCap.provide(async () => {
36
+ return { ensureDeclarativeConfig: ({ projectRoot, repoSlug }) => ensureDeclarativeConfig(projectRoot, repoSlug ? { repoSlug } : {}) };
37
+ }, {
38
+ title: "Rig declarative config ensure",
39
+ description: "Autocreate the embedded declarative .rig/rigfig.toml config from the standard plugin defaults when a project has none."
40
+ })
496
41
  ]
497
42
  }
498
43
  });
@@ -500,29 +45,7 @@ function createInitPlugin() {
500
45
  return initPlugin;
501
46
  }
502
47
  export {
503
- writeRigConnectionState,
504
- writeRigConfig,
505
- validateGitHubAuth,
506
- saveGitHubTokenLocally,
507
- runSetup,
508
- readRigConnectionStatus,
509
- readRigConfigStatus,
510
- readGhAuthToken,
511
- parseRepoSlugFromRemote,
512
- parseRepoSlug,
513
48
  initPlugin,
514
- ensureRigPrivateDirs,
515
- ensurePiRigInstalledForSetup,
516
- ensureGitignoreEntries,
517
- ensureGitHubLabels,
518
- ensureGitHubAuth,
519
- detectStartupStatus,
520
- detectRigStartupStatus,
521
- detectOriginRepoSlug,
522
- detectGhAuth,
523
49
  createInitPlugin,
524
- buildRigInitConfigSource,
525
- applyRigSetupProject,
526
- SETUP_CAPABILITY_ID,
527
50
  INIT_PLUGIN_NAME
528
51
  };
@@ -1,5 +1,4 @@
1
1
  export declare const INIT_PLUGIN_NAME = "@rig/init-plugin";
2
- export declare const SETUP_CAPABILITY_ID = "workspace.setup";
3
- export declare const initPlugin: import("@rig/core").RigPlugin;
4
- export declare function createInitPlugin(): import("@rig/core").RigPlugin;
2
+ export declare const initPlugin: import("@rig/core/config").RigPlugin;
3
+ export declare function createInitPlugin(): import("@rig/core/config").RigPlugin;
5
4
  export default initPlugin;