@wemuda/launchrail 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/LICENSE +21 -0
  2. package/assets/ralph.workflow.js +476 -0
  3. package/dist/commands/add.d.ts +13 -0
  4. package/dist/commands/add.js +189 -0
  5. package/dist/commands/add.js.map +1 -0
  6. package/dist/commands/diff.d.ts +13 -0
  7. package/dist/commands/diff.js +44 -0
  8. package/dist/commands/diff.js.map +1 -0
  9. package/dist/commands/doctor.d.ts +12 -0
  10. package/dist/commands/doctor.js +171 -0
  11. package/dist/commands/doctor.js.map +1 -0
  12. package/dist/commands/eject.d.ts +17 -0
  13. package/dist/commands/eject.js +80 -0
  14. package/dist/commands/eject.js.map +1 -0
  15. package/dist/commands/init.d.ts +13 -0
  16. package/dist/commands/init.js +173 -0
  17. package/dist/commands/init.js.map +1 -0
  18. package/dist/commands/smoke.d.ts +21 -0
  19. package/dist/commands/smoke.js +171 -0
  20. package/dist/commands/smoke.js.map +1 -0
  21. package/dist/commands/status.d.ts +15 -0
  22. package/dist/commands/status.js +91 -0
  23. package/dist/commands/status.js.map +1 -0
  24. package/dist/commands/sync.d.ts +19 -0
  25. package/dist/commands/sync.js +83 -0
  26. package/dist/commands/sync.js.map +1 -0
  27. package/dist/commands/verify.d.ts +18 -0
  28. package/dist/commands/verify.js +50 -0
  29. package/dist/commands/verify.js.map +1 -0
  30. package/dist/index.d.ts +2 -0
  31. package/dist/index.js +127 -0
  32. package/dist/index.js.map +1 -0
  33. package/dist/lib/browser-testing.d.ts +16 -0
  34. package/dist/lib/browser-testing.js +170 -0
  35. package/dist/lib/browser-testing.js.map +1 -0
  36. package/dist/lib/checksum.d.ts +1 -0
  37. package/dist/lib/checksum.js +5 -0
  38. package/dist/lib/checksum.js.map +1 -0
  39. package/dist/lib/claudeSettings.d.ts +21 -0
  40. package/dist/lib/claudeSettings.js +71 -0
  41. package/dist/lib/claudeSettings.js.map +1 -0
  42. package/dist/lib/detect.d.ts +23 -0
  43. package/dist/lib/detect.js +88 -0
  44. package/dist/lib/detect.js.map +1 -0
  45. package/dist/lib/diff.d.ts +12 -0
  46. package/dist/lib/diff.js +99 -0
  47. package/dist/lib/diff.js.map +1 -0
  48. package/dist/lib/lockfile.d.ts +25 -0
  49. package/dist/lib/lockfile.js +44 -0
  50. package/dist/lib/lockfile.js.map +1 -0
  51. package/dist/lib/manifest.d.ts +41 -0
  52. package/dist/lib/manifest.js +127 -0
  53. package/dist/lib/manifest.js.map +1 -0
  54. package/dist/lib/migrations.d.ts +47 -0
  55. package/dist/lib/migrations.js +76 -0
  56. package/dist/lib/migrations.js.map +1 -0
  57. package/dist/lib/project.d.ts +22 -0
  58. package/dist/lib/project.js +53 -0
  59. package/dist/lib/project.js.map +1 -0
  60. package/dist/lib/ralph.d.ts +12 -0
  61. package/dist/lib/ralph.js +21 -0
  62. package/dist/lib/ralph.js.map +1 -0
  63. package/dist/lib/seeds.d.ts +11 -0
  64. package/dist/lib/seeds.js +120 -0
  65. package/dist/lib/seeds.js.map +1 -0
  66. package/dist/lib/upstream.d.ts +21 -0
  67. package/dist/lib/upstream.js +37 -0
  68. package/dist/lib/upstream.js.map +1 -0
  69. package/dist/lib/writer.d.ts +26 -0
  70. package/dist/lib/writer.js +62 -0
  71. package/dist/lib/writer.js.map +1 -0
  72. package/dist/version.d.ts +1 -0
  73. package/dist/version.js +4 -0
  74. package/dist/version.js.map +1 -0
  75. package/package.json +36 -0
@@ -0,0 +1,173 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import * as p from "@clack/prompts";
4
+ import { applyPluginDeclaration, CLAUDE_SETTINGS_PATH, planPluginDeclaration, } from "../lib/claudeSettings.js";
5
+ import { detectRepo } from "../lib/detect.js";
6
+ import { emptyLockfile, readLockfile, writeLockfile } from "../lib/lockfile.js";
7
+ import { migrationIds } from "../lib/migrations.js";
8
+ import { ISSUE_TRACKERS, MANIFEST_FILENAME, parseManifest, serializeManifest, } from "../lib/manifest.js";
9
+ import { seedFiles } from "../lib/seeds.js";
10
+ import { ACTION_LABEL, applyPlan, planWrites } from "../lib/writer.js";
11
+ import { VERSION } from "../version.js";
12
+ function suggestedTestCommand(detection) {
13
+ if (!detection.testScript)
14
+ return null;
15
+ return `${detection.packageManager ?? "npm"} test`;
16
+ }
17
+ function defaultTesting(detection) {
18
+ return {
19
+ unitCommand: suggestedTestCommand(detection),
20
+ devCommand: detection.devScript ? `${detection.packageManager ?? "npm"} run dev` : null,
21
+ e2eCommand: null,
22
+ smokeCommand: null,
23
+ appUrl: null,
24
+ };
25
+ }
26
+ function defaultManifestFor(detection) {
27
+ return {
28
+ schemaVersion: 1,
29
+ mode: "standard-mvp",
30
+ issueTracker: detection.gitRemoteUrl?.includes("github.com") ? "github" : "none",
31
+ conventions: {
32
+ conventionalCommits: detection.conventionalCommitRatio === null ? true : detection.conventionalCommitRatio >= 0.5,
33
+ },
34
+ testing: defaultTesting(detection),
35
+ modules: { core: true },
36
+ };
37
+ }
38
+ async function interview(detection) {
39
+ const defaults = defaultManifestFor(detection);
40
+ p.intro("launchrail init");
41
+ if (!detection.isGitRepo) {
42
+ p.log.warn("This is not a git repository. Launchrail relies on git history for safe writes.");
43
+ }
44
+ const answers = await p.group({
45
+ mode: () => p.select({
46
+ message: "Project mode",
47
+ initialValue: defaults.mode,
48
+ options: [
49
+ { value: "standard-mvp", label: "Standard MVP", hint: "default product workflow" },
50
+ { value: "spike", label: "Spike", hint: "short experiment; disposable or highly uncertain" },
51
+ { value: "high-rigor", label: "High-rigor", hint: "security-sensitive, regulated, or multi-team" },
52
+ ],
53
+ }),
54
+ issueTracker: () => p.select({
55
+ message: "Issue tracker",
56
+ initialValue: defaults.issueTracker,
57
+ options: ISSUE_TRACKERS.map((t) => ({ value: t, label: t })),
58
+ }),
59
+ conventionalCommits: () => p.confirm({
60
+ message: "Use Conventional Commits? (recorded in the seeded AGENTS.md so agents follow it)",
61
+ initialValue: defaults.conventions.conventionalCommits,
62
+ }),
63
+ unitCommand: () => p.text({
64
+ message: "Deterministic test command (empty to decide later)",
65
+ initialValue: defaults.testing.unitCommand ?? "",
66
+ placeholder: "e.g. pnpm test",
67
+ }),
68
+ }, {
69
+ onCancel: () => {
70
+ p.cancel("Cancelled — nothing was written.");
71
+ process.exit(130);
72
+ },
73
+ });
74
+ return {
75
+ schemaVersion: 1,
76
+ mode: answers.mode,
77
+ issueTracker: answers.issueTracker,
78
+ conventions: { conventionalCommits: answers.conventionalCommits },
79
+ testing: {
80
+ ...defaultTesting(detection),
81
+ unitCommand: answers.unitCommand.trim() === "" ? null : answers.unitCommand.trim(),
82
+ },
83
+ modules: { core: true },
84
+ };
85
+ }
86
+ const SETTINGS_LABEL = {
87
+ create: "create ",
88
+ merge: "update ",
89
+ "skip-declared": "ok ",
90
+ "skip-invalid": "conflict",
91
+ };
92
+ export async function runInit(opts) {
93
+ const detection = detectRepo(opts.cwd);
94
+ const settings = planPluginDeclaration(opts.cwd);
95
+ const interactive = !opts.yes && process.stdin.isTTY === true && process.stdout.isTTY === true;
96
+ let manifest;
97
+ if (detection.hasManifest) {
98
+ const parsed = parseManifest(readFileSync(join(opts.cwd, MANIFEST_FILENAME), "utf8"));
99
+ if (!parsed.manifest) {
100
+ console.error(`launchrail: existing ${MANIFEST_FILENAME} is invalid:`);
101
+ for (const error of parsed.errors)
102
+ console.error(` - ${error}`);
103
+ return { code: 1, actions: [], settings };
104
+ }
105
+ manifest = parsed.manifest;
106
+ console.log(`Found existing ${MANIFEST_FILENAME} — using its configuration (init is idempotent).`);
107
+ }
108
+ else if (interactive) {
109
+ manifest = await interview(detection);
110
+ }
111
+ else if (opts.yes) {
112
+ manifest = defaultManifestFor(detection);
113
+ }
114
+ else {
115
+ console.error("launchrail: non-interactive session — re-run with --yes to accept defaults.");
116
+ return { code: 1, actions: [], settings };
117
+ }
118
+ const specs = [
119
+ { relPath: MANIFEST_FILENAME, content: serializeManifest(manifest), ownership: "seeded" },
120
+ ...seedFiles({ projectName: detection.projectName, manifest, launchrailVersion: VERSION }),
121
+ ];
122
+ const existing = readLockfile(opts.cwd);
123
+ if (existing.error) {
124
+ console.error(`launchrail: ${existing.error} — refusing to continue. Fix or remove the lockfile first.`);
125
+ return { code: 1, actions: [], settings };
126
+ }
127
+ const lockfile = existing.lockfile ?? emptyLockfile(VERSION);
128
+ if (!existing.lockfile) {
129
+ // A fresh init produces the current structure, so every shipped migration
130
+ // is satisfied by definition. Existing lockfiles are left to `sync`.
131
+ lockfile.migrations = migrationIds().sort();
132
+ }
133
+ const lockBefore = JSON.stringify(lockfile);
134
+ const actions = planWrites(opts.cwd, specs, lockfile);
135
+ console.log("");
136
+ for (const action of actions) {
137
+ console.log(` ${ACTION_LABEL[action.kind]} ${action.spec.relPath} (${action.detail})`);
138
+ }
139
+ console.log(` ${SETTINGS_LABEL[settings.kind]} ${CLAUDE_SETTINGS_PATH} (${settings.detail})`);
140
+ if (opts.dryRun) {
141
+ console.log("\nDry run — nothing was written.");
142
+ return { code: 0, actions, settings };
143
+ }
144
+ const written = applyPlan(opts.cwd, actions, lockfile);
145
+ if (applyPluginDeclaration(opts.cwd, settings))
146
+ written.push(CLAUDE_SETTINGS_PATH);
147
+ lockfile.launchrailVersion = VERSION;
148
+ lockfile.decisions = {
149
+ ...lockfile.decisions,
150
+ mode: manifest.mode,
151
+ issueTracker: manifest.issueTracker,
152
+ conventionalCommits: manifest.conventions.conventionalCommits,
153
+ unitCommand: manifest.testing.unitCommand,
154
+ };
155
+ if (JSON.stringify(lockfile) !== lockBefore || !existing.lockfile) {
156
+ writeLockfile(opts.cwd, lockfile);
157
+ }
158
+ console.log(written.length > 0
159
+ ? `\nWrote ${written.length} file(s).`
160
+ : "\nEverything already up to date — nothing written.");
161
+ if (!detection.isGitRepo) {
162
+ console.log("\n⚠ Not a git repository. Run `git init` before letting agents work here — Launchrail relies on git for safe writes.");
163
+ }
164
+ console.log("\nNext steps:");
165
+ console.log(" 1. Review the seeded AGENTS.md and fill in the TODO sections.");
166
+ if (!detection.hasMattPocockSetup) {
167
+ console.log(" 2. Install Matt Pocock's skills and run /setup-matt-pocock-skills (expected output: docs/agents/).");
168
+ }
169
+ console.log(` ${detection.hasMattPocockSetup ? "2" : "3"}. Run \`npx @wemuda/launchrail doctor\` to validate the setup.`);
170
+ console.log(` ${detection.hasMattPocockSetup ? "3" : "4"}. Commit the result.`);
171
+ return { code: 0, actions, settings };
172
+ }
173
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ export interface SmokeOptions {
2
+ cwd: string;
3
+ url: string | null;
4
+ dryRun: boolean;
5
+ }
6
+ export interface SmokeOutcome {
7
+ code: number;
8
+ /** Absolute path of the created run directory, when one was created. */
9
+ runDir: string | null;
10
+ }
11
+ export type SmokeEnvironment = "local" | "ci" | "cloud";
12
+ export declare function parseJourneyNames(source: string): string[];
13
+ /**
14
+ * Prepare an agentic smoke run: confirm the app is reachable, then scaffold a
15
+ * traceable evidence bundle under artifacts/verification/<run-id>/. The agent
16
+ * (browser-smoke skill) drives the journeys and fills the bundle in.
17
+ *
18
+ * Only ever creates new files in a fresh run directory — it never modifies
19
+ * existing project files, so no checksum tracking is needed.
20
+ */
21
+ export declare function runSmoke(opts: SmokeOptions): Promise<SmokeOutcome>;
@@ -0,0 +1,171 @@
1
+ import { execFileSync } from "node:child_process";
2
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
3
+ import { join } from "node:path";
4
+ import { BROWSER_TESTING_MODULE, SMOKE_JOURNEYS_PATH } from "../lib/browser-testing.js";
5
+ import { MANIFEST_FILENAME, parseManifest } from "../lib/manifest.js";
6
+ import { VERSION } from "../version.js";
7
+ function detectEnvironment(env) {
8
+ if (env.CLAUDE_CODE_REMOTE === "true")
9
+ return "cloud";
10
+ if (env.CI)
11
+ return "ci";
12
+ return "local";
13
+ }
14
+ function git(cwd, args) {
15
+ try {
16
+ return execFileSync("git", args, { cwd, encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim();
17
+ }
18
+ catch {
19
+ return null;
20
+ }
21
+ }
22
+ export function parseJourneyNames(source) {
23
+ return source
24
+ .split("\n")
25
+ .filter((line) => line.startsWith("## Journey:"))
26
+ .map((line) => line.slice("## Journey:".length).trim())
27
+ .filter((name) => name.length > 0);
28
+ }
29
+ const EVIDENCE_GITIGNORE = `# Managed by Launchrail: keep summaries and deviations reviewable, ignore bulky evidence.
30
+ *
31
+ !.gitignore
32
+ !*/
33
+ !*/summary.md
34
+ !*/deviations.md
35
+ !*/meta.json
36
+ `;
37
+ function summaryTemplate(opts) {
38
+ const journeyLines = opts.journeys.length > 0
39
+ ? opts.journeys.map((name) => `- [ ] ${name}`).join("\n")
40
+ : `_No journeys defined in ${SMOKE_JOURNEYS_PATH} — record the journeys actually driven (e.g. from the ticket under verification)._`;
41
+ return `# Smoke verification — ${opts.runId}
42
+
43
+ - Commit: ${opts.commitSha ?? "no git history"}${opts.gitDirty ? " (working tree dirty)" : ""}
44
+ - Base URL: ${opts.baseUrl} (responded ${opts.appStatus})
45
+ - Environment: ${opts.environment}
46
+ - Launchrail: v${VERSION}
47
+ - Spec / ticket references: _fill in_
48
+
49
+ ## Journeys
50
+
51
+ ${journeyLines}
52
+
53
+ ## Standard checks
54
+
55
+ - [ ] No uncaught console errors
56
+ - [ ] No failed API requests
57
+ - [ ] Success state visible for each journey
58
+ - [ ] Data remains after refresh
59
+
60
+ ## Evidence
61
+
62
+ _Reference files in this directory: screenshots/, traces/, console.log, network-errors.json, test-results.json._
63
+
64
+ ## Deviations from spec or design
65
+
66
+ _None recorded — add details here and in deviations.md when found._
67
+
68
+ ## New regression tests
69
+
70
+ _Deterministic tests added from smoke findings._
71
+
72
+ ## Blockers
73
+
74
+ _None._
75
+ `;
76
+ }
77
+ /**
78
+ * Prepare an agentic smoke run: confirm the app is reachable, then scaffold a
79
+ * traceable evidence bundle under artifacts/verification/<run-id>/. The agent
80
+ * (browser-smoke skill) drives the journeys and fills the bundle in.
81
+ *
82
+ * Only ever creates new files in a fresh run directory — it never modifies
83
+ * existing project files, so no checksum tracking is needed.
84
+ */
85
+ export async function runSmoke(opts) {
86
+ const manifestPath = join(opts.cwd, MANIFEST_FILENAME);
87
+ if (!existsSync(manifestPath)) {
88
+ console.error(`launchrail: ${MANIFEST_FILENAME} not found — run \`launchrail init\` first.`);
89
+ return { code: 1, runDir: null };
90
+ }
91
+ const parsed = parseManifest(readFileSync(manifestPath, "utf8"));
92
+ if (!parsed.manifest) {
93
+ console.error(`launchrail: ${MANIFEST_FILENAME} is invalid:`);
94
+ for (const error of parsed.errors)
95
+ console.error(` - ${error}`);
96
+ return { code: 1, runDir: null };
97
+ }
98
+ if (!parsed.manifest.modules[BROWSER_TESTING_MODULE]) {
99
+ console.error(`launchrail: the ${BROWSER_TESTING_MODULE} module is not enabled — run \`launchrail add ${BROWSER_TESTING_MODULE}\` first.`);
100
+ return { code: 1, runDir: null };
101
+ }
102
+ const baseUrl = opts.url ?? parsed.manifest.testing.appUrl;
103
+ if (!baseUrl) {
104
+ console.error(`launchrail: no app URL — set testing.appUrl in ${MANIFEST_FILENAME} or pass --url <url>.`);
105
+ return { code: 1, runDir: null };
106
+ }
107
+ let appStatus = null;
108
+ try {
109
+ const response = await fetch(baseUrl, { signal: AbortSignal.timeout(3000), redirect: "manual" });
110
+ appStatus = `HTTP ${response.status}`;
111
+ }
112
+ catch {
113
+ // Any response counts as reachable; only a connection failure aborts the run.
114
+ }
115
+ if (appStatus === null) {
116
+ console.error(`launchrail: ${baseUrl} is not responding. Start the app first (\`node scripts/dev.mjs --background\`) or pass --url <url>.`);
117
+ return { code: 1, runDir: null };
118
+ }
119
+ const journeysPath = join(opts.cwd, SMOKE_JOURNEYS_PATH);
120
+ const journeys = existsSync(journeysPath) ? parseJourneyNames(readFileSync(journeysPath, "utf8")) : [];
121
+ const commitSha = git(opts.cwd, ["rev-parse", "HEAD"]);
122
+ const gitDirty = (git(opts.cwd, ["status", "--porcelain"]) ?? "") !== "";
123
+ const environment = detectEnvironment(process.env);
124
+ const stamp = new Date().toISOString().replace(/[-:]/g, "").replace("T", "-").slice(0, 15);
125
+ let runId = `${stamp}-${commitSha?.slice(0, 7) ?? "nogit"}`;
126
+ const verificationDir = join(opts.cwd, "artifacts", "verification");
127
+ for (let n = 2; existsSync(join(verificationDir, runId)); n += 1) {
128
+ runId = `${stamp}-${commitSha?.slice(0, 7) ?? "nogit"}-${n}`;
129
+ }
130
+ const runDir = join(verificationDir, runId);
131
+ console.log(`App responding at ${baseUrl} (${appStatus}).`);
132
+ if (journeys.length > 0) {
133
+ console.log(`\n${journeys.length} journey(s) from ${SMOKE_JOURNEYS_PATH}:`);
134
+ for (const name of journeys)
135
+ console.log(` - ${name}`);
136
+ }
137
+ else {
138
+ console.log(`\nNo journeys defined in ${SMOKE_JOURNEYS_PATH} — drive the journeys defined by the work under verification.`);
139
+ }
140
+ if (opts.dryRun) {
141
+ console.log(`\nDry run — would create artifacts/verification/${runId}/ (meta.json, summary.md, screenshots/, traces/).`);
142
+ return { code: 0, runDir: null };
143
+ }
144
+ mkdirSync(join(runDir, "screenshots"), { recursive: true });
145
+ mkdirSync(join(runDir, "traces"), { recursive: true });
146
+ const gitignorePath = join(verificationDir, ".gitignore");
147
+ if (!existsSync(gitignorePath))
148
+ writeFileSync(gitignorePath, EVIDENCE_GITIGNORE, "utf8");
149
+ const meta = {
150
+ schemaVersion: 1,
151
+ runId,
152
+ createdAt: new Date().toISOString(),
153
+ commitSha,
154
+ gitDirty,
155
+ baseUrl,
156
+ appStatus,
157
+ environment,
158
+ launchrailVersion: VERSION,
159
+ journeys,
160
+ };
161
+ writeFileSync(join(runDir, "meta.json"), JSON.stringify(meta, null, 2) + "\n", "utf8");
162
+ writeFileSync(join(runDir, "summary.md"), summaryTemplate({ runId, baseUrl, commitSha, gitDirty, environment, appStatus, journeys }), "utf8");
163
+ console.log(`\nEvidence bundle scaffolded: artifacts/verification/${runId}/`);
164
+ console.log(" - summary.md fill in as journeys complete; check every box you verified");
165
+ console.log(" - screenshots/ capture key states as you go");
166
+ console.log(" - traces/ Playwright traces where available");
167
+ console.log(" - console.log / network-errors.json / test-results.json — write these when relevant");
168
+ console.log("\nEvery journey must pass the standard checks. Convert real bugs into failing deterministic tests before fixing.");
169
+ return { code: 0, runDir };
170
+ }
171
+ //# sourceMappingURL=smoke.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"smoke.js","sourceRoot":"","sources":["../../src/commands/smoke.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import { type UpstreamAdvisory } from "../lib/upstream.js";
2
+ import { type PlannedAction } from "../lib/writer.js";
3
+ export interface StatusReport {
4
+ code: number;
5
+ errors: string[];
6
+ cliVersion: string;
7
+ lockfileVersion: string | null;
8
+ modules: string[];
9
+ ejected: string[];
10
+ actions: PlannedAction[];
11
+ pendingMigrationIds: string[];
12
+ advisories: UpstreamAdvisory[];
13
+ }
14
+ export declare function runStatus(cwd: string): StatusReport;
15
+ export declare function printStatus(report: StatusReport): void;
@@ -0,0 +1,91 @@
1
+ import { loadProject, desiredSpecs } from "../lib/project.js";
2
+ import { pendingMigrations } from "../lib/migrations.js";
3
+ import { scanUpstreamReferences } from "../lib/upstream.js";
4
+ import { planWrites } from "../lib/writer.js";
5
+ import { VERSION } from "../version.js";
6
+ export function runStatus(cwd) {
7
+ const { state, errors } = loadProject(cwd);
8
+ if (!state) {
9
+ return {
10
+ code: 1,
11
+ errors,
12
+ cliVersion: VERSION,
13
+ lockfileVersion: null,
14
+ modules: [],
15
+ ejected: [],
16
+ actions: [],
17
+ pendingMigrationIds: [],
18
+ advisories: [],
19
+ };
20
+ }
21
+ return {
22
+ code: 0,
23
+ errors: [],
24
+ cliVersion: VERSION,
25
+ lockfileVersion: state.lockfile.launchrailVersion,
26
+ modules: Object.entries(state.manifest.modules)
27
+ .filter(([, enabled]) => enabled)
28
+ .map(([name]) => name),
29
+ ejected: Object.entries(state.lockfile.files)
30
+ .filter(([, file]) => file.class === "ejected")
31
+ .map(([relPath]) => relPath),
32
+ actions: planWrites(cwd, desiredSpecs(state), state.lockfile),
33
+ pendingMigrationIds: pendingMigrations(state.lockfile).map((m) => m.id),
34
+ advisories: scanUpstreamReferences(cwd),
35
+ };
36
+ }
37
+ function fileLine(action) {
38
+ const path = action.spec.relPath;
39
+ switch (action.kind) {
40
+ case "create":
41
+ return ` missing ${path} — sync will create it`;
42
+ case "update":
43
+ return ` outdated ${path} — sync will update it`;
44
+ case "conflict":
45
+ return ` modified ${path} — locally modified managed file; sync keeps your version`;
46
+ case "skip-seeded-exists":
47
+ case "skip-unchanged":
48
+ return ` ok ${path}`;
49
+ case "skip-ejected":
50
+ return ` ejected ${path}`;
51
+ }
52
+ }
53
+ export function printStatus(report) {
54
+ if (report.errors.length > 0) {
55
+ for (const error of report.errors)
56
+ console.error(`launchrail: ${error}`);
57
+ return;
58
+ }
59
+ console.log(`launchrail ${report.cliVersion} — lockfile written by ${report.lockfileVersion}`);
60
+ console.log(` modules: ${report.modules.join(", ")}`);
61
+ if (report.ejected.length > 0) {
62
+ console.log(` ejected: ${report.ejected.join(", ")}`);
63
+ }
64
+ console.log("\nFiles:");
65
+ for (const action of report.actions)
66
+ console.log(fileLine(action));
67
+ if (report.pendingMigrationIds.length > 0) {
68
+ console.log("\nPending migrations:");
69
+ for (const id of report.pendingMigrationIds)
70
+ console.log(` ${id}`);
71
+ }
72
+ if (report.advisories.length > 0) {
73
+ console.log("\nUpstream renames:");
74
+ for (const advisory of report.advisories) {
75
+ const note = advisory.rename.note ? ` (${advisory.rename.note})` : "";
76
+ console.log(` ${advisory.relPath} references \`${advisory.rename.from}\` — renamed upstream to \`${advisory.rename.to}\`${note}`);
77
+ }
78
+ }
79
+ const updates = report.actions.filter((a) => a.kind === "create" || a.kind === "update").length;
80
+ const conflicts = report.actions.filter((a) => a.kind === "conflict").length;
81
+ if (updates + report.pendingMigrationIds.length > 0) {
82
+ console.log(`\n${updates} update(s) and ${report.pendingMigrationIds.length} migration(s) available — run \`launchrail sync\` (or \`launchrail diff\` to preview).`);
83
+ }
84
+ else if (conflicts > 0) {
85
+ console.log(`\nUp to date; ${conflicts} file(s) carry local modifications (run \`launchrail eject <file>\` to own them permanently).`);
86
+ }
87
+ else {
88
+ console.log("\nEverything up to date.");
89
+ }
90
+ }
91
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,sBAAsB,EAAyB,MAAM,oBAAoB,CAAC;AACnF,OAAO,EAAE,UAAU,EAAsB,MAAM,kBAAkB,CAAC;AAClE,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAcxC,MAAM,UAAU,SAAS,CAAC,GAAW;IACnC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;IAC3C,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO;YACL,IAAI,EAAE,CAAC;YACP,MAAM;YACN,UAAU,EAAE,OAAO;YACnB,eAAe,EAAE,IAAI;YACrB,OAAO,EAAE,EAAE;YACX,OAAO,EAAE,EAAE;YACX,OAAO,EAAE,EAAE;YACX,mBAAmB,EAAE,EAAE;YACvB,UAAU,EAAE,EAAE;SACf,CAAC;IACJ,CAAC;IACD,OAAO;QACL,IAAI,EAAE,CAAC;QACP,MAAM,EAAE,EAAE;QACV,UAAU,EAAE,OAAO;QACnB,eAAe,EAAE,KAAK,CAAC,QAAQ,CAAC,iBAAiB;QACjD,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC;aAC5C,MAAM,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC;aAChC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC;QACxB,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC;aAC1C,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,KAAK,SAAS,CAAC;aAC9C,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC;QAC9B,OAAO,EAAE,UAAU,CAAC,GAAG,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,QAAQ,CAAC;QAC7D,mBAAmB,EAAE,iBAAiB,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACvE,UAAU,EAAE,sBAAsB,CAAC,GAAG,CAAC;KACxC,CAAC;AACJ,CAAC;AAED,SAAS,QAAQ,CAAC,MAAqB;IACrC,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC;IACjC,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;QACpB,KAAK,QAAQ;YACX,OAAO,eAAe,IAAI,wBAAwB,CAAC;QACrD,KAAK,QAAQ;YACX,OAAO,eAAe,IAAI,wBAAwB,CAAC;QACrD,KAAK,UAAU;YACb,OAAO,eAAe,IAAI,2DAA2D,CAAC;QACxF,KAAK,oBAAoB,CAAC;QAC1B,KAAK,gBAAgB;YACnB,OAAO,eAAe,IAAI,EAAE,CAAC;QAC/B,KAAK,cAAc;YACjB,OAAO,eAAe,IAAI,EAAE,CAAC;IACjC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,MAAoB;IAC9C,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM;YAAE,OAAO,CAAC,KAAK,CAAC,eAAe,KAAK,EAAE,CAAC,CAAC;QACzE,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,cAAc,MAAM,CAAC,UAAU,0BAA0B,MAAM,CAAC,eAAe,EAAE,CAAC,CAAC;IAC/F,OAAO,CAAC,GAAG,CAAC,cAAc,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACvD,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9B,OAAO,CAAC,GAAG,CAAC,cAAc,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACzD,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IACxB,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,OAAO;QAAE,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;IAEnE,IAAI,MAAM,CAAC,mBAAmB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1C,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;QACrC,KAAK,MAAM,EAAE,IAAI,MAAM,CAAC,mBAAmB;YAAE,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACtE,CAAC;IAED,IAAI,MAAM,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACjC,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;QACnC,KAAK,MAAM,QAAQ,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;YACzC,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,QAAQ,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YACtE,OAAO,CAAC,GAAG,CACT,KAAK,QAAQ,CAAC,OAAO,iBAAiB,QAAQ,CAAC,MAAM,CAAC,IAAI,8BAA8B,QAAQ,CAAC,MAAM,CAAC,EAAE,KAAK,IAAI,EAAE,CACtH,CAAC;QACJ,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,MAAM,CAAC;IAChG,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,MAAM,CAAC;IAC7E,IAAI,OAAO,GAAG,MAAM,CAAC,mBAAmB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpD,OAAO,CAAC,GAAG,CAAC,KAAK,OAAO,kBAAkB,MAAM,CAAC,mBAAmB,CAAC,MAAM,wFAAwF,CAAC,CAAC;IACvK,CAAC;SAAM,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;QACzB,OAAO,CAAC,GAAG,CAAC,iBAAiB,SAAS,+FAA+F,CAAC,CAAC;IACzI,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC;IAC1C,CAAC;AACH,CAAC"}
@@ -0,0 +1,19 @@
1
+ import { type Migration, type MigrationResult } from "../lib/migrations.js";
2
+ import { type PlannedAction } from "../lib/writer.js";
3
+ export interface SyncOptions {
4
+ cwd: string;
5
+ dryRun: boolean;
6
+ /** Migration registry override for tests; defaults to all shipped migrations. */
7
+ registry?: Migration[];
8
+ }
9
+ export interface SyncOutcome {
10
+ code: number;
11
+ actions: PlannedAction[];
12
+ migrations: MigrationResult[];
13
+ }
14
+ /**
15
+ * Bring an initialized project up to the current toolchain: run pending
16
+ * migrations in order, then regenerate the managed/seeded surface through the
17
+ * safe writer (unmodified managed files update, local modifications win).
18
+ */
19
+ export declare function runSync(opts: SyncOptions): SyncOutcome;
@@ -0,0 +1,83 @@
1
+ import { writeLockfile } from "../lib/lockfile.js";
2
+ import { applyPendingMigrations, MIGRATIONS, planPendingMigrations, } from "../lib/migrations.js";
3
+ import { loadProject, desiredSpecs } from "../lib/project.js";
4
+ import { ACTION_LABEL, applyPlan, planWrites } from "../lib/writer.js";
5
+ import { VERSION } from "../version.js";
6
+ function printActions(actions) {
7
+ for (const action of actions) {
8
+ console.log(` ${ACTION_LABEL[action.kind]} ${action.spec.relPath} (${action.detail})`);
9
+ }
10
+ }
11
+ function reportConflicts(actions) {
12
+ const conflicts = actions.filter((a) => a.kind === "conflict");
13
+ if (conflicts.length === 0)
14
+ return;
15
+ console.log(`\n${conflicts.length} managed file(s) kept local modifications:`);
16
+ for (const action of conflicts)
17
+ console.log(` ${action.spec.relPath}`);
18
+ console.log("Revert the local edits to receive updates, or run `launchrail eject <file>` to own them permanently.");
19
+ }
20
+ /**
21
+ * Bring an initialized project up to the current toolchain: run pending
22
+ * migrations in order, then regenerate the managed/seeded surface through the
23
+ * safe writer (unmodified managed files update, local modifications win).
24
+ */
25
+ export function runSync(opts) {
26
+ const registry = opts.registry ?? MIGRATIONS;
27
+ const { state, errors } = loadProject(opts.cwd);
28
+ if (!state) {
29
+ for (const error of errors)
30
+ console.error(`launchrail: ${error}`);
31
+ return { code: 1, actions: [], migrations: [] };
32
+ }
33
+ const ctx = { cwd: opts.cwd, lockfile: state.lockfile };
34
+ const lockBefore = JSON.stringify(state.lockfile);
35
+ if (opts.dryRun) {
36
+ const planned = planPendingMigrations(ctx, registry);
37
+ if (planned.length > 0) {
38
+ console.log("Pending migrations:");
39
+ for (const migration of planned) {
40
+ console.log(` ${migration.id} — ${migration.description}`);
41
+ for (const change of migration.changes)
42
+ console.log(` ${change}`);
43
+ if (migration.changes.length === 0)
44
+ console.log(" already satisfied — will be recorded");
45
+ }
46
+ console.log("");
47
+ }
48
+ const actions = planWrites(opts.cwd, desiredSpecs(state), state.lockfile);
49
+ printActions(actions);
50
+ reportConflicts(actions);
51
+ console.log("\nDry run — nothing was written.");
52
+ return { code: 0, actions, migrations: [] };
53
+ }
54
+ // Migrations first: structural changes land before the file surface regenerates.
55
+ const migrations = applyPendingMigrations(ctx, registry);
56
+ for (const result of migrations) {
57
+ if (result.status === "failed")
58
+ continue;
59
+ const detail = result.status === "applied" ? result.changes.join("; ") : "already satisfied";
60
+ console.log(` migrate ${result.id} (${detail})`);
61
+ }
62
+ const failed = migrations.find((result) => result.status === "failed");
63
+ if (failed) {
64
+ if (JSON.stringify(state.lockfile) !== lockBefore)
65
+ writeLockfile(opts.cwd, state.lockfile);
66
+ console.error(`\nlaunchrail: migration ${failed.id} failed: ${failed.error}`);
67
+ console.error("Migrations applied before the failure are recorded; fix the cause and re-run `launchrail sync`.");
68
+ return { code: 1, actions: [], migrations };
69
+ }
70
+ const actions = planWrites(opts.cwd, desiredSpecs(state), state.lockfile);
71
+ printActions(actions);
72
+ const written = applyPlan(opts.cwd, actions, state.lockfile);
73
+ state.lockfile.launchrailVersion = VERSION;
74
+ if (JSON.stringify(state.lockfile) !== lockBefore)
75
+ writeLockfile(opts.cwd, state.lockfile);
76
+ reportConflicts(actions);
77
+ const migrated = migrations.filter((result) => result.status === "applied").length;
78
+ console.log(written.length + migrated > 0
79
+ ? `\nApplied ${migrated} migration(s), wrote ${written.length} file(s).`
80
+ : "\nEverything already up to date — nothing written.");
81
+ return { code: 0, actions, migrations };
82
+ }
83
+ //# sourceMappingURL=sync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/commands/sync.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ export interface VerifyStep {
2
+ name: string;
3
+ command: string;
4
+ }
5
+ export interface VerifyResult {
6
+ step: VerifyStep;
7
+ status: number;
8
+ }
9
+ export interface VerifyOutcome {
10
+ code: number;
11
+ results: VerifyResult[];
12
+ }
13
+ /**
14
+ * Run the project's deterministic verification contract: every configured
15
+ * check, in order, with a pass/fail summary. Agentic smoke testing is separate
16
+ * (`launchrail smoke`) — verify is the stable release gate.
17
+ */
18
+ export declare function runVerify(cwd: string): VerifyOutcome;