diff --git a/.claude/agent-memory/archgate-developer/MEMORY.md b/.claude/agent-memory/archgate-developer/MEMORY.md index 3fe0d890..dea02859 100644 --- a/.claude/agent-memory/archgate-developer/MEMORY.md +++ b/.claude/agent-memory/archgate-developer/MEMORY.md @@ -66,7 +66,7 @@ Skipping steps 2 or 3 is a workflow violation. The user should NEVER have to inv ## Distribution / Packaging -- **npm shim + GitHub Releases** — The npm package is a thin shim (`bin/archgate.cjs` + `scripts/postinstall.cjs`). On first run, the shim downloads the platform binary from GitHub Releases and caches it to `~/.archgate/bin/`. No platform-specific npm packages. +- **npm shim + GitHub Releases** — The npm package is a thin shim (`bin/archgate.cjs`). On first run, the shim downloads the platform binary from GitHub Releases and caches it to `~/.archgate/bin/`. No platform-specific npm packages. - **`.cjs` extension is mandatory** — Root `package.json` has `"type": "module"`. Any Node.js CJS wrapper script placed at the package root MUST use `.cjs`, not `.js`, or Node.js will attempt to parse it as ESM and fail. ## Telemetry Strategy diff --git a/CLAUDE.md b/CLAUDE.md index 0a9b4982..21dcdd71 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -48,7 +48,7 @@ Zod schemas are the single source of truth. Types derived via `z.infer<>` — ne ## npm Distribution -The npm package is a **thin shim** — it contains only `bin/archgate.cjs` and `scripts/postinstall.cjs`. The shim downloads the platform binary from GitHub Releases on first run and caches it to `~/.archgate/bin/`. All runtime dependencies (commander, inquirer, zod) are bundled into the compiled binary via `bun build --compile`, so they belong in `devDependencies`, not `dependencies`. +The npm package is a **thin shim** — it contains only `bin/archgate.cjs`. The shim downloads the platform binary from GitHub Releases on first run and caches it to `~/.archgate/bin/`. All runtime dependencies (commander, inquirer, zod) are bundled into the compiled binary via `bun build --compile`, so they belong in `devDependencies`, not `dependencies`. ## Conventions diff --git a/package.json b/package.json index e813f920..228abe44 100644 --- a/package.json +++ b/package.json @@ -27,8 +27,7 @@ "archgate": "bin/archgate.cjs" }, "files": [ - "bin/archgate.cjs", - "scripts/postinstall.cjs" + "bin/archgate.cjs" ], "os": [ "darwin", @@ -49,7 +48,6 @@ "format:check": "oxfmt --check .", "knip": "knip", "lint": "oxlint --deny-warnings .", - "postinstall": "node scripts/postinstall.cjs", "test": "bun test --timeout 60000", "test:coverage": "bun test --timeout 60000 --coverage --reporter=junit --reporter-outfile=coverage/junit.xml", "test:watch": "bun test --watch --timeout 60000", diff --git a/scripts/postinstall.cjs b/scripts/postinstall.cjs deleted file mode 100644 index b561fc5e..00000000 --- a/scripts/postinstall.cjs +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env node -"use strict"; - -// Best-effort pre-download: tries to fetch the binary during install so the -// first `archgate` invocation is instant. If this script is blocked by the -// package manager (--ignore-scripts, etc.), the bin shim will download -// on-demand at runtime instead. - -const path = require("path"); -const fs = require("fs"); -const os = require("os"); - -function isBinaryPresent() { - const binaryName = process.platform === "win32" ? "archgate.exe" : "archgate"; - const cachePath = path.join(os.homedir(), ".archgate", "bin", binaryName); - return fs.existsSync(cachePath); -} - -if (!isBinaryPresent()) { - // Delegate to the bin shim's download logic by running it with --version. - // This triggers the on-demand download without side effects. - try { - require("child_process").execFileSync( - process.execPath, - [path.join(__dirname, "..", "bin", "archgate.cjs"), "--version"], - { stdio: "inherit" } - ); - } catch { - // Postinstall must never block `npm install`. - console.warn( - "archgate: could not pre-download binary. It will be downloaded on first run." - ); - } -} diff --git a/src/commands/adr/import.ts b/src/commands/adr/import.ts index 09efd3de..2a840a3b 100644 --- a/src/commands/adr/import.ts +++ b/src/commands/adr/import.ts @@ -3,7 +3,6 @@ import { existsSync, mkdirSync, - readFileSync, rmSync, unlinkSync, writeFileSync, @@ -37,11 +36,13 @@ import { ensureRulesShim } from "../../helpers/rules-shim"; // ---------- Imports manifest I/O ---------- -function loadImportsManifest(projectRoot: string): ImportsManifest { +async function loadImportsManifest( + projectRoot: string +): Promise { const importsPath = join(projectRoot, ".archgate", "imports.json"); if (!existsSync(importsPath)) return { imports: [] }; - const raw = readFileSync(importsPath, "utf-8"); - return ImportsManifestSchema.parse(JSON.parse(raw)); + const raw = await Bun.file(importsPath).json(); + return ImportsManifestSchema.parse(raw); } function saveImportsManifest( @@ -255,7 +256,7 @@ export function registerAdrImportCommand(adr: Command) { // --list: show previously imported ADRs if (opts.list) { - const manifest = loadImportsManifest(projectRoot); + const manifest = await loadImportsManifest(projectRoot); if (useJson) { console.log(formatJSON(manifest, opts.json ? true : undefined)); } else if (manifest.imports.length === 0) { @@ -392,7 +393,7 @@ export function registerAdrImportCommand(adr: Command) { // ---------- Update imports.json ---------- - const manifest = loadImportsManifest(projectRoot); + const manifest = await loadImportsManifest(projectRoot); const sourceGroups = new Map< string, { version?: string; ids: string[] }