diff --git a/AGENTS.md b/AGENTS.md index 268944d..b4cf50e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -12,6 +12,8 @@ - Choose validation from the affected component's `package.json`. For a documentation-only change, check the diff and local links; report those checks separately from build, runtime, or live-app verification. +- Plugin development, package inspection, contribution, and GitHub prerelease + steps are maintained in [`plugin/DEVELOPMENT.md`](plugin/DEVELOPMENT.md). ## Shared quality configuration diff --git a/README.md b/README.md index 9a3f465..f974a51 100644 --- a/README.md +++ b/README.md @@ -29,10 +29,10 @@ OpenAI Imperium contains a CordisX reasoning-intensity presentation plugin and a Reset petition site. Each component has its own runtime and maintenance entry: -| Component | Usage and maintenance | -| ------------------------------------- | ---------------------------------------------------------------------------------------------- | -| CordisX plugin (`plugin/`) | [Plugin README](plugin/README.md): configuration, Host compatibility, and development commands | -| Reset petition site (repository root) | [Site README](app/README.md): experience, local development, and persistent ledger | +| Component | Usage and maintenance | +| ------------------------------------- | ---------------------------------------------------------------------------------------- | +| CordisX plugin (`plugin/`) | [Plugin README](plugin/README.md): installation, usage, configuration, and compatibility | +| Reset petition site (repository root) | [Site README](app/README.md): experience, local development, and persistent ledger | ![OpenAI Imperium — Veni. Vidi. Reset.](./public/og.png) @@ -40,8 +40,8 @@ a Reset petition site. Each component has its own runtime and maintenance entry: The plugin contributes an ascension presentation for reasoning intensity and an optional session backdrop. CordisX Host owns native interaction and rendering. -[`plugin/README.md`](plugin/README.md) is the source for plugin usage, -configuration, and development instructions. +[`plugin/README.md`](plugin/README.md) is the source for plugin installation, +usage, configuration, and compatibility. ### Plugin configuration @@ -54,8 +54,8 @@ history. Its [README](app/README.md) owns feature, runtime, and ledger details. ## Run locally -Choose the [plugin development instructions](plugin/README.md#development) or -[petition site instructions](app/README.md#run-locally) for the component you need. +Choose the [plugin maintainer guide](plugin/DEVELOPMENT.md) or [petition site +instructions](app/README.md#run-locally) for the component you need. ## License diff --git a/README.zh-CN.md b/README.zh-CN.md index d4137aa..9c71cd9 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -16,7 +16,7 @@

我来,我见,我 Reset。

- CordisX 插件 + CordisX 插件 · 加入 Reset 请愿 · 源码 · 反馈 @@ -27,7 +27,7 @@ OpenAI Imperium 在同一仓库中提供 CordisX 思考强度视觉插件与 Res | 组件 | 使用与维护说明 | | -------------------------- | ------------------------------------------------------------------- | -| CordisX 插件(`plugin/`) | [插件 README](plugin/README.md#中文):配置、Host 兼容条件与开发命令 | +| CordisX 插件(`plugin/`) | [插件 README](plugin/README.zh-Hans.md):安装、使用、配置与兼容条件 | | Reset 请愿站(仓库根目录) | [请愿站 README](app/README.zh-CN.md):体验介绍、本地运行与持久账本 | ![OpenAI Imperium——我来,我见,我 Reset。](./public/og.png) @@ -35,12 +35,12 @@ OpenAI Imperium 在同一仓库中提供 CordisX 思考强度视觉插件与 Res ## CordisX 插件 插件提供思考强度的升阶外观及可选会话背景,原生交互和渲染由 CordisX Host -负责。插件的使用、配置与开发说明统一维护在 -[`plugin/README.md`](plugin/README.md#中文)。 +负责。插件的安装、使用、配置与兼容说明统一维护在 +[`plugin/README.zh-Hans.md`](plugin/README.zh-Hans.md)。 ### 插件配置 -请参阅[插件配置说明](plugin/README.md#configuration)。 +请参阅[插件配置说明](plugin/README.zh-Hans.md#配置)。 ## Reset 请愿站 @@ -49,7 +49,7 @@ OpenAI Imperium 在同一仓库中提供 CordisX 思考强度视觉插件与 Res ## 本地运行 -根据要运行的组件选择[插件开发说明](plugin/README.md#development)或 +根据要运行的组件选择[插件维护指南](plugin/DEVELOPMENT.md)或 [请愿站本地运行说明](app/README.zh-CN.md#本地运行)。 ## 许可证与声明 diff --git a/plugin/DEVELOPMENT.md b/plugin/DEVELOPMENT.md new file mode 100644 index 0000000..d044b6d --- /dev/null +++ b/plugin/DEVELOPMENT.md @@ -0,0 +1,51 @@ +# Codex Ascension Maintainer Guide + +Run all commands in this guide from `plugin/`. Node.js 22.19 or newer is +required. + +## Develop and verify + +```sh +npm ci +npm run check +npm run dev:dry-run +npm run dev +``` + +`npm run check` type-checks the source, regenerates embedded image modules, +builds the TypeScript library and portable browser bundle, runs the focused +tests, and inspects the package archive. Also run `git diff --check` from the +repository root before committing. + +The browser bundle keeps Cordis and `cordisx/contracts` as Host-provided +facades. It bundles Schemastery and plugin-owned image data so the archive does +not depend on a sibling `node_modules` directory. + +## Package + +`cordisx-package.json` is the install descriptor. Its version must match +`package.json`; its runtime-manifest digest must match the exact bytes of +`runtime-manifest.json`. The runtime manifest must remain identical to the +plugin's exported manifest, including the empty capability list. + +Build and create the archive with: + +```sh +npm run check +npm pack +``` + +The archive must contain both READMEs, `cordisx-package.json`, +`runtime-manifest.json`, and the entry named by the package descriptor. + +## Release + +Releases use a GitHub prerelease, not npm. Merge through a protected pull +request, build the exact merged `main` commit, and create the private-package +archive with `npm pack`. Publish the archive as +`cordisx-codex-ascension-.tgz` together with `SHA256SUMS` under the +matching `v` tag. Download both assets afterward and verify their +hashes and archive contents. + +The Marketplace owner adds the artifact URL and SHA-256 digest separately. +Do not copy an older trust, Official, or Certified record. diff --git a/plugin/README.md b/plugin/README.md index 8f4f772..63dd676 100644 --- a/plugin/README.md +++ b/plugin/README.md @@ -1,77 +1,88 @@ -# @cordisx/codex-ascension +# Codex Ascension -The CordisX plugin for the OpenAI Imperium reasoning-intensity presentation. -It contributes five localized semantic stages—plastic, bronze, steel, silver, -and gold—through `composer.reasoning-intensity`, plus an optional staged -portrait and effects projection through `session.backdrop`. +[简体中文](README.zh-Hans.md) -The reasoning presentation declares an explicit `replace` claim named -`imperium`. It requests only the Host-safe `reasoningIntensity` property, -`setReasoningIntensity` command, and `reasoningIntensityChanged` event. CordisX -Host owns authorization, exclusive selection, native fallback, lease state, -native range discovery, DOM, styling, motion, accessibility, value mapping, -and cleanup. This plugin contains no selectors, CSS, callbacks, setting -mutations, native event code, or fabricated lease state. +Codex Ascension gives CordisX's reasoning-intensity control five theatrical +stages, from plastic through gold. It can also project a matching portrait and +ambient effects into the active session background. -The optional `session.backdrop` contribution remains a legacy structured -`compose` contribution and does not claim controlled-point ownership. +## Install + +Plugin ID: `codex-ascension`. Current release: `0.1.1`. + +```sh +FEED_URL=https://raw.githubusercontent.com/cordisx/marketplace/main/marketplace.json +npx cordisx@beta source add "$FEED_URL" --yes +npx cordisx@beta plugin install codex-ascension --source "$FEED_URL" --version 0.1.1 +``` + +Skip `source add` when that exact feed is already enabled. For another profile, +add the same `--profile ` argument to both commands. `--source` selects +an already configured and enabled source; it does not register one. `--yes` +confirms the source change only and does not approve plugin permissions. A +discovery source is not a trust root. + +The install command becomes available after the Marketplace v3 entry lists the +verified `0.1.1` artifact. Until then, download the archive and `SHA256SUMS` +from the +[GitHub prerelease](https://github.com/cordisx/plugin-codex-ascension/releases/tag/v0.1.1). + +## Use + +Open a Codex session in CordisX and choose a reasoning-intensity value. The +native control keeps its normal behavior while the selected value is presented +as one of five Ascension stages: + +| Reasoning stage | Ascension presentation | +| --------------- | ---------------------- | +| Lowest | Promptly Bankrupt | +| Low | Bronze Builder | +| Medium | Tool-Forged Tribune | +| High | Silver Context | +| Highest | Codex Maximus | + +The session backdrop follows the same stage when its portrait or effects are +enabled. ## Configuration -CordisX renders the plugin's structured configuration form. Each option is -enabled by default and can be changed independently: +CordisX renders three settings, all enabled by default: -| Option | Effect when disabled | +| Setting | Effect when disabled | | ------------------------ | -------------------------------------------------------- | | Replace reasoning slider | Leaves the native reasoning-intensity control unchanged. | -| Show backdrop portrait | Does not mount portrait images in the session backdrop. | -| Enable backdrop effects | Does not mount the glow or architectural effect layers. | +| Show backdrop portrait | Hides the staged portrait. | +| Enable backdrop effects | Hides the glow and architectural effects. | -If both backdrop options are disabled, the plugin does not register a -`session.backdrop` contribution. Saved changes apply with a plugin restart. +Saved changes apply after the plugin restarts. If both backdrop settings are +disabled, the plugin does not register a session backdrop. -## Development +## Permissions and limits -Run the following commands from `plugin/`. Its -[`package.json`](package.json) defines the Node.js requirement and checks; -the repository-root package runs the separate petition site. +Codex Ascension requests no CordisX capabilities. The Host owns authorization, +the reasoning value, native control behavior, rendering, accessibility, and +cleanup. The plugin changes presentation only; it does not change model +reasoning policy or submit settings on the user's behalf. -Requires a published CordisX prerelease containing -[cordisx/cordisx#187](https://github.com/cordisx/cordisx/pull/187). +The reasoning-control replacement requires a CordisX Host that supports the +controlled `composer.reasoning-intensity` contribution. The session backdrop +uses the legacy structured `session.backdrop` contribution. -```bash -npm install -npm run check -npm run dev:dry-run -npm run dev -``` +## Troubleshooting + +- **Version `0.1.1` is not found:** confirm the Marketplace entry lists the + release artifact. `--source` cannot add or repair a feed. +- **The native slider is unchanged:** enable **Replace reasoning slider**, save, + and restart the plugin. +- **The backdrop is missing:** enable at least one backdrop setting and restart + the plugin. + +## License -## Brand icon and source distribution - -The plugin owns its approved 256×256 brand PNG at -[`src/assets/identity/ascension.png`](src/assets/identity/ascension.png). The build -embeds these exact bytes in the public module `icon` export as -`{ mediaType: 'image/png', data }`, so Host plugin lists can consume the icon -without fetching a site asset. The petition site icons remain independent. - -This private package is distributed from repository source; merging the PNG and -its generated module to `main` updates that source distribution. No npm release -or version tag is required for the icon change. `npm run check` verifies the -built export against the selected PNG hash and dimensions. - -## 中文 - -这是 OpenAI Imperium 的 CordisX 思考强度主题插件。插件声明塑料白、青铜、 -钢、银、金五个语义档位,并可选提供会话背景人像与特效。思考强度外观通过 -名为 `imperium` 的显式 `replace` claim 接入,只请求 Host 安全投影的 -`reasoningIntensity` 属性、`setReasoningIntensity` 命令和 -`reasoningIntensityChanged` 事件;授权、排他选择、原生回退、lease 状态、 -原生滑块定位、DOM、样式、动画、可访问性、数值映射和卸载清理由 CordisX Host -统一负责。插件不包含 selector、CSS、callback、原生事件代码或伪造的 lease -状态。`session.backdrop` 仍是 legacy structured `compose` contribution,不声明 -受控点所有权。 - -CordisX 会从插件的结构化 Schema 渲染三个默认开启、可独立组合的配置项: -「替换思考强度 Slider」「显示背景人像」「启用背景特效」。关闭某项后 Host -不会挂载对应视觉层;两项背景配置都关闭时,插件不会注册 `session.backdrop`。 -保存配置后通过插件重启生效。 +The source code is available under the repository's +[MIT License](https://github.com/cordisx/plugin-codex-ascension/blob/main/LICENSE). +Portrait and brand-asset terms are described in the repository's +[asset notice](https://github.com/cordisx/plugin-codex-ascension/blob/main/ASSETS-LICENSE.md). +Maintainer setup, checks, packaging, and release instructions are in the source +repository's +[maintainer guide](https://github.com/cordisx/plugin-codex-ascension/blob/main/plugin/DEVELOPMENT.md). diff --git a/plugin/README.zh-Hans.md b/plugin/README.zh-Hans.md new file mode 100644 index 0000000..0b3b7ae --- /dev/null +++ b/plugin/README.zh-Hans.md @@ -0,0 +1,77 @@ +# Codex Ascension + +[English](README.md) + +Codex Ascension 为 CordisX 的思考强度控件提供五阶戏剧化外观,从塑料白一路 +升至黄金。插件还可以在当前会话背景中显示与档位对应的人像和环境特效。 + +## 安装 + +插件 ID:`codex-ascension`。当前版本:`0.1.1`。 + +```sh +FEED_URL=https://raw.githubusercontent.com/cordisx/marketplace/main/marketplace.json +npx cordisx@beta source add "$FEED_URL" --yes +npx cordisx@beta plugin install codex-ascension --source "$FEED_URL" --version 0.1.1 +``` + +若该 feed 已启用,可以跳过 `source add`。使用其他 profile 时,两条命令都要添加 +相同的 `--profile `。`--source` 只能选择已配置并启用的来源,不会注册 +来源;`--yes` 只确认来源变更,不会批准插件权限。发现来源也不等同于 trust root。 + +Marketplace v3 条目列出验证后的 `0.1.1` artifact 后,安装命令才可用。在此之前, +可从 +[GitHub 预发布](https://github.com/cordisx/plugin-codex-ascension/releases/tag/v0.1.1) +下载压缩包与 `SHA256SUMS`。 + +## 使用 + +在 CordisX 中打开 Codex 会话并选择思考强度。原生控件行为保持不变,所选档位会 +显示为五种 Ascension 外观之一: + +| 思考档位 | Ascension 外观 | +| -------- | -------------- | +| 最低 | 提示词破产 | +| 低 | 青铜构筑者 | +| 中 | 工具锻造官 | +| 高 | 白银上下文 | +| 最高 | Codex Maximus | + +启用背景人像或特效后,会话背景会跟随相同档位变化。 + +## 配置 + +CordisX 会渲染三个默认开启的设置: + +| 设置 | 关闭后的效果 | +| ------------------- | ---------------------------- | +| 替换思考强度 Slider | 保留原生思考强度控件的外观。 | +| 显示背景人像 | 隐藏当前档位的人像。 | +| 启用背景特效 | 隐藏光晕和建筑纹样特效。 | + +保存后需重启插件才能生效。两个背景设置都关闭时,插件不会注册会话背景。 + +## 权限与限制 + +Codex Ascension 不请求任何 CordisX capability。授权、思考强度值、原生控件行为、 +渲染、可访问性和清理由 Host 负责。插件只改变外观,不会更改模型的思考策略,也不会 +代替用户提交设置。 + +思考强度替换需要 Host 支持受控的 `composer.reasoning-intensity` contribution; +会话背景使用 legacy structured `session.backdrop` contribution。 + +## 排错 + +- **找不到 `0.1.1`:**确认 Marketplace 条目已列出该版本的 release artifact; + `--source` 不会添加或修复 feed。 +- **原生 Slider 外观未变化:**启用「替换思考强度 Slider」,保存并重启插件。 +- **没有会话背景:**至少启用一个背景设置,然后重启插件。 + +## 许可证 + +源代码采用仓库的 +[MIT License](https://github.com/cordisx/plugin-codex-ascension/blob/main/LICENSE)。 +肖像与品牌素材条款见仓库的 +[素材声明](https://github.com/cordisx/plugin-codex-ascension/blob/main/ASSETS-LICENSE.md)。 +维护者的环境、检查、打包与发布说明见源码仓库的 +[维护指南](https://github.com/cordisx/plugin-codex-ascension/blob/main/plugin/DEVELOPMENT.md)。 diff --git a/plugin/cordisx-package.json b/plugin/cordisx-package.json new file mode 100644 index 0000000..e9c1fab --- /dev/null +++ b/plugin/cordisx-package.json @@ -0,0 +1,25 @@ +{ + "$schema": "https://raw.githubusercontent.com/cordisx/cordisx-protocol/main/schemas/plugin-package.v3.schema.json", + "schemaVersion": 3, + "id": "codex-ascension", + "version": "0.1.1", + "entry": "./dist/runtime/module.js", + "readme": "./README.md", + "canonicalSource": "https://github.com/cordisx/plugin-codex-ascension", + "distribution": { + "mode": "explicit-local-v1", + "signature": "unsupported" + }, + "compatibility": { + "runtimeAbi": 1, + "protocolSchemas": [ + "https://raw.githubusercontent.com/cordisx/cordisx-protocol/main/schemas/plugin-manifest.v1.schema.json" + ] + }, + "dependencies": [], + "runtimeManifest": { + "path": "./runtime-manifest.json", + "schema": "https://raw.githubusercontent.com/cordisx/cordisx-protocol/main/schemas/plugin-manifest.v1.schema.json", + "digest": "sha256:6de4f425b84029aa6e04c27d76232ee92a5a1781460141dca4eb7f5a98e7f226" + } +} diff --git a/plugin/package-lock.json b/plugin/package-lock.json index 7df5e4d..c04c584 100644 --- a/plugin/package-lock.json +++ b/plugin/package-lock.json @@ -1,17 +1,18 @@ { "name": "@cordisx/codex-ascension", - "version": "0.1.0", + "version": "0.1.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@cordisx/codex-ascension", - "version": "0.1.0", + "version": "0.1.1", "license": "MIT", "devDependencies": { "@deepseek-ai/cordis": "4.0.1", "@deepseek-ai/schemastery": "^3.18.1", "cordisx": "0.1.0-beta.1", + "esbuild": "0.28.2", "typescript": "^5.9.2" }, "engines": { diff --git a/plugin/package.json b/plugin/package.json index 88ca8e0..47d56ab 100644 --- a/plugin/package.json +++ b/plugin/package.json @@ -1,24 +1,33 @@ { "name": "@cordisx/codex-ascension", - "version": "0.1.0", + "version": "0.1.1", "private": true, "license": "MIT", "description": "OpenAI Imperium reasoning-intensity presentation for CordisX", "type": "module", - "main": "./dist/codex-ascension.js", + "main": "./dist/runtime/module.js", "types": "./dist/codex-ascension.d.ts", + "files": [ + "dist", + "README.md", + "README.zh-Hans.md", + "cordisx-package.json", + "runtime-manifest.json" + ], "scripts": { - "build": "node scripts/generate-portrait-modules.mjs && tsc -p tsconfig.json", - "check": "npm run typecheck && npm run build && npm test", + "build": "node scripts/clean-dist.mjs && node scripts/generate-portrait-modules.mjs && tsc -p tsconfig.json && node scripts/build-runtime-bundle.mjs", + "check": "npm run typecheck && npm run build && npm test && npm run pack:check", "dev": "cordisx dev ./src/codex-ascension.ts", "dev:dry-run": "cordisx dev ./src/codex-ascension.ts --dry-run", - "test": "node --test test/manifest.mjs", + "pack:check": "node scripts/check-package.mjs", + "test": "node --test test/*.mjs", "typecheck": "node scripts/generate-portrait-modules.mjs && tsc -p tsconfig.json --noEmit" }, "devDependencies": { "@deepseek-ai/cordis": "4.0.1", "@deepseek-ai/schemastery": "^3.18.1", "cordisx": "0.1.0-beta.1", + "esbuild": "0.28.2", "typescript": "^5.9.2" }, "engines": { diff --git a/plugin/runtime-manifest.json b/plugin/runtime-manifest.json new file mode 100644 index 0000000..d757231 --- /dev/null +++ b/plugin/runtime-manifest.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://raw.githubusercontent.com/cordisx/cordisx-protocol/main/schemas/plugin-manifest.v1.schema.json", + "schemaVersion": 1, + "id": "codex-ascension", + "name": "Codex Ascension", + "capabilities": [] +} diff --git a/plugin/scripts/build-runtime-bundle.mjs b/plugin/scripts/build-runtime-bundle.mjs new file mode 100644 index 0000000..be17cec --- /dev/null +++ b/plugin/scripts/build-runtime-bundle.mjs @@ -0,0 +1,13 @@ +import { build } from 'esbuild'; + +await build({ + bundle: true, + entryPoints: ['src/codex-ascension.ts'], + external: ['@deepseek-ai/cordis', 'cordisx/contracts'], + format: 'esm', + metafile: true, + outfile: 'dist/runtime/module.js', + platform: 'browser', + sourcemap: false, + target: ['chrome120'], +}); diff --git a/plugin/scripts/check-package.mjs b/plugin/scripts/check-package.mjs new file mode 100644 index 0000000..154d673 --- /dev/null +++ b/plugin/scripts/check-package.mjs @@ -0,0 +1,63 @@ +import assert from 'node:assert/strict'; +import { spawnSync } from 'node:child_process'; +import { createHash } from 'node:crypto'; +import { mkdtemp, readFile, rm } from 'node:fs/promises'; +import { tmpdir } from 'node:os'; +import { join } from 'node:path'; + +const hostContracts = import.meta.resolve('cordisx/contracts'); +const { runtimeManifestV1 } = await import(new URL('./launcher/plugin-package.js', hostContracts)); +const { JsonPackageManifestV2Resolver } = await import(new URL('./launcher/packages/manifest.js', hostContracts)); + +const packageManifest = JSON.parse(await readFile('cordisx-package.json', 'utf8')); +const runtimeBytes = await readFile('runtime-manifest.json'); +const runtimeManifest = JSON.parse(runtimeBytes); +const packageJson = JSON.parse(await readFile('package.json', 'utf8')); +const builtPlugin = await import(new URL('../dist/codex-ascension.js', import.meta.url)); + +assert.equal(packageManifest.id, runtimeManifest.id); +assert.equal(packageManifest.version, packageJson.version); +assert.equal(packageManifest.entry, packageJson.main); +assert.equal(packageManifest.runtimeManifest.schema, runtimeManifest.$schema); +assert.equal( + packageManifest.runtimeManifest.digest, + `sha256:${createHash('sha256').update(runtimeBytes).digest('hex')}`, +); +assert.deepEqual(runtimeManifest.capabilities, []); +assert.deepEqual(builtPlugin.manifest, runtimeManifest); + +const runtimeSource = await readFile(packageManifest.entry, 'utf8'); +assert.doesNotMatch(runtimeSource, /from\s+['"]@deepseek-ai\/schemastery['"]/u); +assert.match(runtimeSource, /from\s+['"]cordisx\/contracts['"]/u); + +const resolver = new JsonPackageManifestV2Resolver({ + runtimeValidators: { + [runtimeManifest.$schema]: value => runtimeManifestV1(value, runtimeManifest.id), + }, +}); +const resolved = await resolver.resolve(process.cwd()); +assert.equal(resolved.packageManifest.pluginId, packageManifest.id); +assert.equal(resolved.packageManifest.version, packageManifest.version); +assert.deepEqual(resolved.runtimeManifest, runtimeManifest); + +const temporary = await mkdtemp(join(tmpdir(), 'codex-ascension-pack-')); +try { + const packed = spawnSync('npm', ['pack', '--json', '--pack-destination', temporary], { + encoding: 'utf8', + stdio: ['ignore', 'pipe', 'inherit'], + }); + assert.equal(packed.status, 0, packed.stdout); + const [metadata] = JSON.parse(packed.stdout); + const files = new Set(metadata.files.map(file => file.path)); + for ( + const required of [ + 'README.md', + 'README.zh-Hans.md', + 'cordisx-package.json', + 'runtime-manifest.json', + packageManifest.entry.slice(2), + ] + ) assert.ok(files.has(required), `package is missing ${required}`); +} finally { + await rm(temporary, { force: true, recursive: true }); +} diff --git a/plugin/scripts/clean-dist.mjs b/plugin/scripts/clean-dist.mjs new file mode 100644 index 0000000..e47a24d --- /dev/null +++ b/plugin/scripts/clean-dist.mjs @@ -0,0 +1,3 @@ +import { rm } from 'node:fs/promises'; + +await rm('dist', { force: true, recursive: true });