@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,120 @@
1
+ function agentsMd(ctx) {
2
+ const { manifest } = ctx;
3
+ const commands = manifest.testing.unitCommand
4
+ ? "```bash\n" + manifest.testing.unitCommand + "\n```"
5
+ : "TODO: document the commands agents must run (setup, tests, checks).";
6
+ const commitSection = manifest.conventions.conventionalCommits
7
+ ? `
8
+ ## Commit conventions
9
+
10
+ Conventional Commits: \`type(scope): summary\` — types \`feat\`, \`fix\`, \`docs\`, \`chore\`, \`refactor\`, \`test\`, \`build\`, \`ci\`.
11
+ `
12
+ : "";
13
+ return `# Agent operating contract — ${ctx.projectName}
14
+
15
+ This file is the vendor-neutral contract for any coding agent working in this repository.
16
+
17
+ ## Project purpose
18
+
19
+ TODO: One paragraph on what this project is, who it serves, and what it is not.
20
+
21
+ ## Canonical context
22
+
23
+ 1. [docs/vision.md](docs/vision.md) — product vision and non-goals
24
+ 2. [docs/adr/](docs/adr/) — accepted architecture decisions
25
+ 3. [docs/specs/](docs/specs/) — approved specifications
26
+
27
+ ## Commands
28
+
29
+ ${commands}
30
+ ${commitSection}
31
+ ## Workflow rules
32
+
33
+ - Do not silently change scope; surface deviations from the spec or ADRs.
34
+ - If implementation invalidates an artifact (vision, spec, ADR, design note), update that artifact in the same change.
35
+ - Meaningful decisions become lightweight ADRs in \`docs/adr/\` using [docs/adr/0000-template.md](docs/adr/0000-template.md).
36
+
37
+ ## Definition of done
38
+
39
+ - The change matches the relevant spec or ADR, or updates it.
40
+ - Deterministic checks pass${manifest.testing.unitCommand ? ` (\`${manifest.testing.unitCommand}\`)` : ""}.
41
+ - Evidence over assertion: "done" requires passing checks, not agent say-so.
42
+ `;
43
+ }
44
+ function claudeMd() {
45
+ return `@AGENTS.md
46
+ @.launchrail/CLAUDE.generated.md
47
+
48
+ ## Project-specific Claude Code instructions
49
+
50
+ Add project-specific Claude behavior here. This file is yours — Launchrail never overwrites it.
51
+ `;
52
+ }
53
+ function claudeGeneratedMd(ctx) {
54
+ const browserTesting = ctx.manifest.modules["browser-testing"]
55
+ ? `
56
+ ## Browser testing
57
+
58
+ - User-facing changes are verified twice: deterministic checks (\`node scripts/verify.mjs\`) and agentic smoke journeys from \`docs/testing/smoke-journeys.md\` (browser-smoke skill).
59
+ - Start the app with \`node scripts/dev.mjs\` (\`--background\` in cloud or CI sessions); prepare an evidence bundle with \`npx @wemuda/launchrail smoke\`.
60
+ - Smoke evidence lives in \`artifacts/verification/<run-id>/\` — fill in \`summary.md\`; only summary, deviations, and meta are meant to be committed.
61
+ - When a smoke run finds a real bug: reproduce it, add a failing deterministic test, fix, prove the test passes, re-run the journey.
62
+ `
63
+ : "";
64
+ const ralph = ctx.manifest.modules.ralph
65
+ ? `
66
+ ## Ralph campaigns
67
+
68
+ - Bounded implementation runs through the Ralph loop: the \`launchrail:ralph\` skill (watchable, checkpointed) or the \`ralph\` workflow in \`.claude/workflows/ralph.js\` (wide or long runs). Both are only ever started explicitly by the user.
69
+ - Tickets enter the loop with the \`ready-for-agent\` label and explicit \`Blocked by: #n\` edges; parked tickets carry \`needs-info\` plus their failure history.
70
+ - A ticket counts done only when its PR is merged on the remote, the issue is closed, and \`npx @wemuda/launchrail verify\` is green — agent reports are claims, not evidence.
71
+ - \`.claude/workflows/ralph.js\` is managed by Launchrail: override policy per run via workflow args (e.g. \`{ width: 1 }\`), never by editing the file.
72
+ `
73
+ : "";
74
+ return `<!-- Managed by Launchrail v${ctx.launchrailVersion}. Do not edit: \`launchrail sync\` may replace this file. Project-specific instructions belong in CLAUDE.md. -->
75
+
76
+ # Launchrail workflow instructions
77
+
78
+ - This project follows the Launchrail development loop: vision → design exploration → grill/research → ADRs → spec → visual validation → tickets → bounded implementation → verification → release.
79
+ - Product knowledge (vision, specs, ADRs, designs, tickets, code) is project-owned; Launchrail never overwrites it.
80
+ - \`.launchrail.yml\` is project configuration; \`.launchrail-lock.json\` is machine-managed — do not hand-edit it.
81
+ - Before claiming completion, run the project's deterministic checks. Completion requires evidence, not assertion.
82
+ - Run \`npx @wemuda/launchrail doctor\` when repository state seems inconsistent.
83
+ ${browserTesting}${ralph}`;
84
+ }
85
+ function adrTemplate() {
86
+ return `# ADR-NNNN: Short decision title
87
+
88
+ ## Status
89
+ Proposed | Accepted | Superseded by ADR-NNNN
90
+
91
+ ## Context
92
+ What requirement or constraint requires a decision?
93
+
94
+ ## Decision
95
+ What was selected?
96
+
97
+ ## Alternatives considered
98
+ What realistic alternatives were rejected?
99
+
100
+ ## Consequences
101
+ What becomes easier, harder, or constrained?
102
+
103
+ ## Revisit when
104
+ What change would justify reconsidering this decision?
105
+ `;
106
+ }
107
+ /** The managed Claude instructions file — regenerated whenever module configuration changes. */
108
+ export function claudeGeneratedFile(ctx) {
109
+ return { relPath: ".launchrail/CLAUDE.generated.md", content: claudeGeneratedMd(ctx), ownership: "managed" };
110
+ }
111
+ /** Everything init seeds beyond the manifest and lockfile. */
112
+ export function seedFiles(ctx) {
113
+ return [
114
+ { relPath: "AGENTS.md", content: agentsMd(ctx), ownership: "seeded" },
115
+ { relPath: "CLAUDE.md", content: claudeMd(), ownership: "seeded" },
116
+ { relPath: "docs/adr/0000-template.md", content: adrTemplate(), ownership: "seeded" },
117
+ claudeGeneratedFile(ctx),
118
+ ];
119
+ }
120
+ //# sourceMappingURL=seeds.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"seeds.js","sourceRoot":"","sources":["../../src/lib/seeds.ts"],"names":[],"mappings":"AASA,SAAS,QAAQ,CAAC,GAAgB;IAChC,MAAM,EAAE,QAAQ,EAAE,GAAG,GAAG,CAAC;IACzB,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,WAAW;QAC3C,CAAC,CAAC,WAAW,GAAG,QAAQ,CAAC,OAAO,CAAC,WAAW,GAAG,OAAO;QACtD,CAAC,CAAC,qEAAqE,CAAC;IAE1E,MAAM,aAAa,GAAG,QAAQ,CAAC,WAAW,CAAC,mBAAmB;QAC5D,CAAC,CAAC;;;;CAIL;QACG,CAAC,CAAC,EAAE,CAAC;IAEP,OAAO,gCAAgC,GAAG,CAAC,WAAW;;;;;;;;;;;;;;;;EAgBtD,QAAQ;EACR,aAAa;;;;;;;;;;6BAUc,QAAQ,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,QAAQ,CAAC,OAAO,CAAC,WAAW,KAAK,CAAC,CAAC,CAAC,EAAE;;CAExG,CAAC;AACF,CAAC;AAED,SAAS,QAAQ;IACf,OAAO;;;;;;CAMR,CAAC;AACF,CAAC;AAED,SAAS,iBAAiB,CAAC,GAAgB;IACzC,MAAM,cAAc,GAAG,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,iBAAiB,CAAC;QAC5D,CAAC,CAAC;;;;;;;CAOL;QACG,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,KAAK,GAAG,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK;QACtC,CAAC,CAAC;;;;;;;CAOL;QACG,CAAC,CAAC,EAAE,CAAC;IAEP,OAAO,+BAA+B,GAAG,CAAC,iBAAiB;;;;;;;;;EAS3D,cAAc,GAAG,KAAK,EAAE,CAAC;AAC3B,CAAC;AAED,SAAS,WAAW;IAClB,OAAO;;;;;;;;;;;;;;;;;;;CAmBR,CAAC;AACF,CAAC;AAED,gGAAgG;AAChG,MAAM,UAAU,mBAAmB,CAAC,GAAgB;IAClD,OAAO,EAAE,OAAO,EAAE,iCAAiC,EAAE,OAAO,EAAE,iBAAiB,CAAC,GAAG,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC;AAC/G,CAAC;AAED,8DAA8D;AAC9D,MAAM,UAAU,SAAS,CAAC,GAAgB;IACxC,OAAO;QACL,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,QAAQ,CAAC,GAAG,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE;QACrE,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE;QAClE,EAAE,OAAO,EAAE,2BAA2B,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE;QACrF,mBAAmB,CAAC,GAAG,CAAC;KACzB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Upstream dependency compatibility tracking (ADR-0006). Launchrail composes
3
+ * external capabilities — Matt Pocock's skills, Claude Design, the Ralph
4
+ * plugin — whose names end up in project-owned docs. When an upstream rename
5
+ * ships, an entry lands in this registry and `status` reports stale
6
+ * references. Project-owned files are never edited automatically: advisories
7
+ * only, the fix stays a human (or agent) decision.
8
+ */
9
+ export interface UpstreamRename {
10
+ /** The retired name, matched as a whole word (hyphens count as word characters). */
11
+ from: string;
12
+ to: string;
13
+ note?: string;
14
+ }
15
+ /** Known upstream renames. Empty until an upstream rename actually ships. */
16
+ export declare const UPSTREAM_RENAMES: UpstreamRename[];
17
+ export interface UpstreamAdvisory {
18
+ relPath: string;
19
+ rename: UpstreamRename;
20
+ }
21
+ export declare function scanUpstreamReferences(root: string, renames?: UpstreamRename[]): UpstreamAdvisory[];
@@ -0,0 +1,37 @@
1
+ import { existsSync, readdirSync, readFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ /** Known upstream renames. Empty until an upstream rename actually ships. */
4
+ export const UPSTREAM_RENAMES = [];
5
+ /** Project-owned docs worth scanning: agent contracts and Matt Pocock's setup output. */
6
+ const SCAN_FILES = ["AGENTS.md", "CLAUDE.md", "docs/workflow.md"];
7
+ const SCAN_DIRS = ["docs/agents"];
8
+ function scanTargets(root) {
9
+ const targets = SCAN_FILES.filter((rel) => existsSync(join(root, rel)));
10
+ for (const dir of SCAN_DIRS) {
11
+ if (!existsSync(join(root, dir)))
12
+ continue;
13
+ for (const entry of readdirSync(join(root, dir))) {
14
+ if (entry.endsWith(".md"))
15
+ targets.push(`${dir}/${entry}`);
16
+ }
17
+ }
18
+ return targets;
19
+ }
20
+ function escapeRegExp(text) {
21
+ return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
22
+ }
23
+ export function scanUpstreamReferences(root, renames = UPSTREAM_RENAMES) {
24
+ if (renames.length === 0)
25
+ return [];
26
+ const advisories = [];
27
+ for (const relPath of scanTargets(root)) {
28
+ const content = readFileSync(join(root, relPath), "utf8");
29
+ for (const rename of renames) {
30
+ const pattern = new RegExp(`(?<![\\w-])${escapeRegExp(rename.from)}(?![\\w-])`);
31
+ if (pattern.test(content))
32
+ advisories.push({ relPath, rename });
33
+ }
34
+ }
35
+ return advisories;
36
+ }
37
+ //# sourceMappingURL=upstream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upstream.js","sourceRoot":"","sources":["../../src/lib/upstream.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAChE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAiBjC,6EAA6E;AAC7E,MAAM,CAAC,MAAM,gBAAgB,GAAqB,EAAE,CAAC;AAErD,yFAAyF;AACzF,MAAM,UAAU,GAAG,CAAC,WAAW,EAAE,WAAW,EAAE,kBAAkB,CAAC,CAAC;AAClE,MAAM,SAAS,GAAG,CAAC,aAAa,CAAC,CAAC;AAOlC,SAAS,WAAW,CAAC,IAAY;IAC/B,MAAM,OAAO,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;IACxE,KAAK,MAAM,GAAG,IAAI,SAAS,EAAE,CAAC;QAC5B,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YAAE,SAAS;QAC3C,KAAK,MAAM,KAAK,IAAI,WAAW,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC;YACjD,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC;gBAAE,OAAO,CAAC,IAAI,CAAC,GAAG,GAAG,IAAI,KAAK,EAAE,CAAC,CAAC;QAC7D,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,YAAY,CAAC,IAAY;IAChC,OAAO,IAAI,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;AACrD,CAAC;AAED,MAAM,UAAU,sBAAsB,CACpC,IAAY,EACZ,UAA4B,gBAAgB;IAE5C,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACpC,MAAM,UAAU,GAAuB,EAAE,CAAC;IAC1C,KAAK,MAAM,OAAO,IAAI,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;QACxC,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,CAAC;QAC1D,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,MAAM,OAAO,GAAG,IAAI,MAAM,CAAC,cAAc,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YAChF,IAAI,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC;gBAAE,UAAU,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QAClE,CAAC;IACH,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC"}
@@ -0,0 +1,26 @@
1
+ import type { Lockfile, OwnershipClass } from "./lockfile.js";
2
+ export interface FileSpec {
3
+ relPath: string;
4
+ content: string;
5
+ ownership: OwnershipClass;
6
+ /** Mark scripts executable after writing (no-op on Windows). */
7
+ executable?: boolean;
8
+ }
9
+ export type ActionKind = "create" | "update" | "skip-unchanged" | "skip-seeded-exists" | "skip-ejected" | "conflict";
10
+ export interface PlannedAction {
11
+ spec: FileSpec;
12
+ kind: ActionKind;
13
+ detail: string;
14
+ }
15
+ export declare const ACTION_LABEL: Record<ActionKind, string>;
16
+ /**
17
+ * Decide what would happen for each desired file without touching disk.
18
+ *
19
+ * - ejected paths are never touched again, not even to recreate them
20
+ * - seeded files are never overwritten once they exist
21
+ * - managed files are only replaced when their on-disk checksum matches the
22
+ * lockfile (i.e. nobody edited them since Launchrail last wrote them)
23
+ */
24
+ export declare function planWrites(root: string, specs: FileSpec[], lockfile: Lockfile): PlannedAction[];
25
+ /** Execute a plan. Mutates `lockfile.files` to reflect what is now on disk. */
26
+ export declare function applyPlan(root: string, actions: PlannedAction[], lockfile: Lockfile): string[];
@@ -0,0 +1,62 @@
1
+ import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { sha256 } from "./checksum.js";
4
+ export const ACTION_LABEL = {
5
+ create: "create ",
6
+ update: "update ",
7
+ "skip-unchanged": "ok ",
8
+ "skip-seeded-exists": "keep ",
9
+ "skip-ejected": "ejected ",
10
+ conflict: "conflict",
11
+ };
12
+ /**
13
+ * Decide what would happen for each desired file without touching disk.
14
+ *
15
+ * - ejected paths are never touched again, not even to recreate them
16
+ * - seeded files are never overwritten once they exist
17
+ * - managed files are only replaced when their on-disk checksum matches the
18
+ * lockfile (i.e. nobody edited them since Launchrail last wrote them)
19
+ */
20
+ export function planWrites(root, specs, lockfile) {
21
+ return specs.map((spec) => {
22
+ const abs = join(root, spec.relPath);
23
+ if (lockfile.files[spec.relPath]?.class === "ejected") {
24
+ return { spec, kind: "skip-ejected", detail: "ejected — Launchrail no longer manages this path" };
25
+ }
26
+ if (!existsSync(abs)) {
27
+ return { spec, kind: "create", detail: "new file" };
28
+ }
29
+ const current = readFileSync(abs, "utf8");
30
+ if (current === spec.content) {
31
+ return { spec, kind: "skip-unchanged", detail: "already up to date" };
32
+ }
33
+ if (spec.ownership === "seeded") {
34
+ return { spec, kind: "skip-seeded-exists", detail: "exists — seeded files are never overwritten" };
35
+ }
36
+ const locked = lockfile.files[spec.relPath];
37
+ if (locked && sha256(current) === locked.checksum) {
38
+ return { spec, kind: "update", detail: "managed file, unmodified since last write" };
39
+ }
40
+ return { spec, kind: "conflict", detail: "managed file has local modifications — not overwriting" };
41
+ });
42
+ }
43
+ /** Execute a plan. Mutates `lockfile.files` to reflect what is now on disk. */
44
+ export function applyPlan(root, actions, lockfile) {
45
+ const written = [];
46
+ for (const action of actions) {
47
+ const { spec, kind } = action;
48
+ if (kind === "create" || kind === "update") {
49
+ const abs = join(root, spec.relPath);
50
+ mkdirSync(dirname(abs), { recursive: true });
51
+ writeFileSync(abs, spec.content, "utf8");
52
+ if (spec.executable && process.platform !== "win32")
53
+ chmodSync(abs, 0o755);
54
+ written.push(spec.relPath);
55
+ }
56
+ if (kind === "create" || kind === "update" || kind === "skip-unchanged") {
57
+ lockfile.files[spec.relPath] = { class: spec.ownership, checksum: sha256(spec.content) };
58
+ }
59
+ }
60
+ return written;
61
+ }
62
+ //# sourceMappingURL=writer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"writer.js","sourceRoot":"","sources":["../../src/lib/writer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare const VERSION: string;
@@ -0,0 +1,4 @@
1
+ import { createRequire } from "node:module";
2
+ const require = createRequire(import.meta.url);
3
+ export const VERSION = require("../package.json").version;
4
+ //# sourceMappingURL=version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAE/C,MAAM,CAAC,MAAM,OAAO,GAAW,OAAO,CAAC,iBAAiB,CAAC,CAAC,OAAO,CAAC"}
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "@wemuda/launchrail",
3
+ "version": "1.0.0",
4
+ "description": "Launchrail — initialize, inspect, update, and validate repositories using the Launchrail development system.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "bin": {
8
+ "launchrail": "./dist/index.js"
9
+ },
10
+ "files": [
11
+ "dist",
12
+ "assets"
13
+ ],
14
+ "engines": {
15
+ "node": ">=22"
16
+ },
17
+ "scripts": {
18
+ "build": "tsc",
19
+ "dev": "tsc --watch",
20
+ "test": "vitest run"
21
+ },
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "git+https://github.com/wemuda/launchrail.git",
25
+ "directory": "packages/cli"
26
+ },
27
+ "devDependencies": {
28
+ "@types/node": "^22",
29
+ "typescript": "^5.7.0",
30
+ "vitest": "^4.1.10"
31
+ },
32
+ "dependencies": {
33
+ "@clack/prompts": "^1.7.0",
34
+ "yaml": "^2.9.0"
35
+ }
36
+ }