@columenlabs/lumen-ship

中文文档
0.1.219发布于 2026/11/09MITTypeScriptES Module零依赖近 30 天下载 4.3万

Lumen's shipping kit: release notes, the What's new changelog, lint guards and the behavior check.

原始使用文档
文档目录8 节
  1. Install
  2. Releases
  3. Notes
  4. Changelog for What's new
  5. lumen-ship.json
  6. Lint guards
  7. Behavior check
  8. Versions

@columenlabs/lumen-ship

Lumen's shipping kit: one release command that writes each release's notes with Claude, the changelog What's new reads, and the lint guards every Lumen app runs. Bash plus a small TypeScript reader, no framework.

Install

bun add -d @columenlabs/lumen-ship

Pin it to the same exact version as the other Lumen packages. The command needs bash, git, gh (with REST access to the repo), jq and curl.

Releases

lumen-ship release cuts a repo's GitHub releases. Run it from the repo root, on each merge to main (a CI job) or by hand.

CommandWhat it does
lumen-ship releaseOne patch release at main once cadence.every merges landed since the newest release tag, or on the first merge cadence.days days after it. FORCE=1 cuts it now
lumen-ship release minorTags main as the next minor. Its notes are the hand-written docs/releases/v<major>.<minor>.0.md, which must be on main
lumen-ship release notesSets the newest minor's notes from its file again
lumen-ship release tag v1.2.3Makes the release of a tag that already exists (for a publish job that tags first). REDO=1 writes its notes again

DRY_RUN=1 prints what it would do and creates nothing.

Notes

Claude writes each release's notes from the merged pull requests since the tag before (commits stand in where there are none), from your prompt. A reply is published only when whole: anything cut short, refused or failed is asked again, at most 3 times, then the release fails. Without ANTHROPIC_API_KEY the notes are GitHub's own list of pull requests.

Set LUMEN_FORBIDDEN_NAMES (a regex alternation, A|B) in a public repo: notes that name one are asked again and never published, and the pull request list shows numbers only.

Changelog for What's new

With changelog.path set, each release's Key takeaways are also committed to main as JSON, newest first, and the tag goes on that commit, so the release deploys its own notes. Each takeaway bullet opens with tags: type tags ([Feature], [Improvement], [Fix], [Performance], [Security]) become its chips, and tags listed in changelog.apps become its apps. Ask for them in your prompt:

- [Fix] [Console] **Exports finish**: ...
[{ "tag": "v0.3.2", "published_at": "2026-10-24T18:00:00Z",
   "takeaways": [{ "text": "**Exports finish**: ...", "types": ["fix"], "apps": ["console"] }] }]

Serve it to WhatsNew (LumenShell's releases prop) with the reader:

import { RELEASES_HEADERS, listReleases, type Release } from '@columenlabs/lumen-ship/releases';
import changelog from './changelog.json';

app.get('/api/releases', (c) =>
  c.json(
    { releases: listReleases(changelog as Release[], {
        limit: c.req.query('limit'),
        before: c.req.query('before'),
        canSee: (apps) => apps.some((a) => mayOpen(c, a)),   // optional
      }) },
    200,
    RELEASES_HEADERS,
  ),
);

listReleases pages newest first (limit 1 to 50, 20 by default; before an ISO time) and, with canSee, keeps a takeaway about some apps only for people who may open one of them.

lumen-ship.json

At the repo root (or the path in LUMEN_SHIP_CONFIG):

{
  "repo": "owner/name",
  "notes": { "prompt": ".github/release-prompt.md", "model": "claude-sonnet-5-5", "maxTokens": 16000 },
  "changelog": { "path": "src/changelog.json", "apps": { "console": "console", "api": "api" } },
  "tags": "v0.*",
  "promote": "release",
  "cadence": { "every": 10, "days": 7 }
}
Key
repoThe GitHub repo the releases go on. Required
notes.promptA file with the prompt; {tag} becomes the release's tag. Required
notes.model, notes.maxTokensThe model and its output limit (the model thinks first, so keep it large)
changelog.pathWhere the What's new JSON lives on main; left out, no changelog
changelog.appsTag (lower case) → app id, for takeaways about one app
tagsThe release tags as a git glob, v[0-9]* by default; narrow it when older tags of another scheme sort higher
promoteA branch fast-forwarded to each new release (a production deploy branch, say)
cadence.every, cadence.daysWhen a patch is due. RELEASE_EVERY overrides every

Lint guards

lumen-ship check kit-neutral [paths]   # no name from LUMEN_FORBIDDEN_NAMES (default: src package.json README.md)
lumen-ship check suppressions          # a useExhaustiveDependencies suppression needs a reason of 3+ words
lumen-ship check settings-copy         # a Settings section description is one plain line of 64 characters or less
lumen-ship check magic-numbers         # hard-coded px/rem class values may only go down
lumen-ship check parts <folders>       # the kit's part pages: hint-text, text-action, raw-overlay, settings-page may only go down

Run each from a package folder in its lint script; run parts from the repo root with the app folders (lumen-ship check parts apps/*/web/src). magic-numbers reads the repo's scripts/magic-numbers.baseline (or LUMEN_SHIP_BASELINE): one <folder> <count> a line, lowered in the change that removes one. parts reads scripts/parts.baseline (or LUMEN_SHIP_PARTS_BASELINE): one <folder> <rule> <count> a line; --write-baseline writes today's counts on a first run. Each rule is explained, with what to write instead, at https://lumen.columenlabs.com/parts/README.md.

Behavior check

@columenlabs/lumen-ship/behavior checks how an app's Durable Objects act over time, without naming any bug. A sanity run drives the app in the local runtime on a simulated clock, records every wake, and holds every store to the same vital signs.

  • simClock() replaces the global Date with a clock the run moves forward. SimAlarms keeps each store's alarm instead of the runtime, so nothing fires on real time. The run jumps the clock to the earliest alarm, fires it, and repeats, so a simulated day takes seconds.
  • judge(wakes, { from, to, stopped }, limits?) reads the recorded Wakes and returns numbers (for a diff against main) and broken (every vital sign broken, in plain words). Pure: no runtime, no I/O.
Vital signBroken when (defaults in VITALS)
Idle wakesover 12 wakes in one hour wrote nothing and called nothing
Quick idleover 5 idle wakes in one hour set the next alarm under 60 s ahead
Wake rateover 120 wakes in one hour, working or not
Alarm in the pasta wake set an alarm before its own time
Rows per wakeone wake read or wrote over 10k rows
Rows per dayone store read over 800k or wrote over 40k rows in a day
Settlesthe last 6 hours still woke over 12 an hour
Errorsa wake threw or logged an error
Runawaythe run stopped at 2,000 wakes before the day ended
import { judge, type Wake } from '@columenlabs/lumen-ship/behavior';

const { numbers, broken } = judge(wakes, { from, to, stopped });
if (broken.length) console.log(broken.map((b) => `${b.rule}: ${b.detail}`).join('\n'));

Give it varied starting states, not failure cases: a returning user's store, the same store 30 days later, a first visit. A loop, a runaway read or stuck work then breaks a vital sign by itself, whatever caused it.

Versions

0.x: any minor may break things until 1.0. Every merge to Lumen's main publishes the next patch of every Lumen package; see the releases.

版本与发布记录

@columenlabs/lumen-ship 共发布 192 个版本,首次发布于 2026/10/25;过去 12 个月发布了 192 个版本。

版本发布日期距今
0.1.219latest2026/11/091 天前
0.1.2182026/11/091 天前
0.1.2172026/11/091 天前
0.1.2162026/11/091 天前
0.1.2152026/11/091 天前
0.1.2142026/11/091 天前

关于 @columenlabs/lumen-ship 的常见问题

@columenlabs/lumen-ship 是什么?

Lumen's shipping kit: release notes, the What's new changelog, lint guards and the behavior check.

如何安装 @columenlabs/lumen-ship?

在项目目录运行 npm install @columenlabs/lumen-ship,或使用 pnpm add / yarn add / bun add。它还提供命令行工具 lumen-ship,可以用 npx lumen-ship 直接运行。

@columenlabs/lumen-ship 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@columenlabs/lumen-ship 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@columenlabs/lumen-ship 可以商用吗?

@columenlabs/lumen-ship 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@columenlabs/lumen-ship 的下载量有多少?

根据 npm 官方下载统计,@columenlabs/lumen-ship 在 2026/10/11 – 2026/11/09 这 30 天内被下载 42,548 次,日均约 1,418 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@columenlabs/lumen-ship 还在维护吗?

最新版本 0.1.219 发布于 2026/11/09(1 天前);至今共发布 192 个版本,其中过去 12 个月发布了 192 个;首次发布于 2026/10/25。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。