@atlanticus-ai/relay

中文文档
2.58.1发布于 2026/11/07SEE LICENSE IN LICENSEES Module零依赖近 30 天下载 1809

Session operating system for owner-gated, agent-executed development. Fail-closed session gates, an append-only paper trail, and one protocol across many projects.

原始使用文档
文档目录14 节
  1. Why
  2. Commands
  3. Layout
  4. Running the tests
  5. The browser suite
  6. Fixtures — two directories, and the distinction is load-bea…
  7. CI
  8. Publish Check (the deploy gate)
  9. This repo is Relay-governed
  10. Vendor into a project
  11. relay-site (static site generator)
  12. Dependencies
  13. Distribution and licence
  14. If a bad version ships

relay

Session operating system for owner-gated, agent-executed development. Fail-closed session gates, an append-only paper trail, and one protocol across many projects.

npm install --save-dev @atlanticus-ai/relay
npx relay init                        # scaffold: slash commands, config, session docs (never overwrites)
npx relay verify-open                 # every open — the first one detects itself, no flag
npx relay selftest                    # did the install work? one line per check, exit 0/1

Then every session: npx relay verify-open → work → npx relay verify-close.

Why

An agent that can commit, push and release needs gates that fail closed and a paper trail it cannot quietly skip. Relay is that: a session opens against a machine-checked handoff, closes against a second gate, and records what actually happened — verbatim gate output, scored objectives, token cost — in files that live in your repo, not in a chat log.

Owner gates are absolute. The agent may implement, commit and propose; git push, git tag, version bumps and marking a ticket done belong to a human, every time.

Commands

relay verify-open      session-start gate (fail-closed)      relay site         build the static site
relay verify-close     session-close gate                    relay compile      compile paper-trail fragments
relay tokens           token accounting for the handoff      relay doctor --container   container probe
relay session-log      append a session lifecycle record     relay docs-check   documentation debt
relay log              append a dispatch/footer record       relay init         scaffold into a repo
relay cp               copy the handoff block to the clipboard

Everything is configured by one relay.config.json in the target repo. relay --help lists the rest.

Layout

  • RELAY-CORE.md — the protocol (15-min read; new adopters start here). Ships with the package, so a consumer always has the version of the protocol its tooling implements.
  • kit/ — the tooling. Zero project-specific strings; every project fact comes from relay.config.json. Node ≥18, one runtime dependency (micromatch).
  • db/ · query/ · ui/ — the optional Relay index: Postgres projection of the paper trail and a local read-only dashboard. Not packaged — npm install gets you the gates, not a database.
  • attic/sync-relay.sh <target> — the legacy file-copy vendoring path, moved to attic/ at RL-D014 and kept as an INERT BACKUP (it is the revert if a migration fails), used until the existing consumers migrate to the package. It translates npx relay … back to vendored script paths on the way out.

Running the tests

npm test              the full suite — relay-site fixtures, gate smoke, kit fixtures, d13
npm run test:fast     the per-commit subset (never writes or clears the pass stamp)
npm run test:e2e      the browser suite — Playwright, Chromium, two viewports

⛔ test:fast and npm test are not interchangeable, and the difference is the stamp. Only the full run writes test/LAST-PASS.json, which verify-close's tests_fresh assert reads — so a close backed by fast alone is a claim about a suite that did not run. Run fast after each commit inside a dispatch and npm test once, before composing the handoff.

The browser suite

npm run test:e2e builds ui/, serves it, and drives real Chromium. No database is opened — every /api/* response is served from a fixture by test/e2e/mock-api.ts, which is strictly stronger than merely avoiding relay_live.

Every spec runs once per viewport, from test/e2e/viewports.ts:

projectsizeSchedule drawer
1280x8001280 × 800yields — the table shrinks (≥ lg)
768x800768 × 800covers — the drawer sits over the table (< lg)

⚠️ These are not "desktop and mobile". They are the exact viewports the owner verified F1 and F2 at, which is what makes a red here mean the same thing as a red on their screen. 800 is deliberately short — a taller window would hide F2 entirely. ⭐ Adding a width adds a ROW here, not a test file; a spec never names a number, it asks viewportOf().

Run one project or one spec:

npx playwright test --project=1280x800
npx playwright test test/e2e/f3-raw-body-never-rendered.spec.ts

Fixtures — two directories, and the distinction is load-bearing

directorywhat it holds
test/fixtures/api/REAL CAPTURES — bodies taken from the live database
test/e2e/fixtures/HAND-BUILT payloads, each carrying a _note saying so at its own site

⛔ Do not put an invented payload in test/fixtures/api/. Its name is a claim about provenance that other things rely on: test/no-mjs-references.test.ts excludes that directory precisely because captures legitimately quote retired paths, and an invented file would inherit an exemption it has not earned.

Hand-built lives there for one of two reasons, both recorded in the file:

  • the endpoint cannot be captured — /api/sessions returns 500 column "track" does not exist while migration 034 is unapplied (an owner gate), and /api/session-prompts was never captured;
  • the payload is a probe — test/e2e/fixtures/portfolio.json.

⚠️ The three prompt fixtures deliberately carry raw_body NEXT TO text, and the two are deliberately different. That is the premise of f3-raw-body-never-rendered.spec.ts: against a payload with no raw_body, "the body is not on the page" passes identically whether the surface refused to render it or there was nothing to render. ⭐ A leak with no raw_body identifier in the source — a {...row} spread, a debug <pre> — is invisible to the static guard in test/ui-guardrails.test.ts and caught by this spec; that gap is the reason it exists.

⛔ An unmapped /api/* route is a 501 naming the route, never an empty 200. A blank success would render as "no data", and a surface that looks healthy and empty is the exact failure the harness is meant to catch.

CI

.github/workflows/ci.yml runs two jobs:

  • test suite (relay-site + verify-open + d13) — npm test against a Postgres service rebuilt by db/fixtures/d13.ts, then the coverage ratchet, then verify-open as a gating step (see ADR 0014). The asserts CI cannot satisfy are declared in relay.config.json under verifyOpen.ciSkipAsserts, print as – skipped in CI: <reason>, and are na — never pass.
  • e2e (chromium, 1280x800 + 768x800) — the browser suite, in its own job, and it gates: no || true.

Publish Check (the deploy gate)

Before Scriptorium is built, every archived dispatch and return is scanned for secrets, and a hit refuses the deploy — it names the file and the rule and never the match. It detects and refuses; it never edits a file. The gate lives inside query/build-corpus.ts, which is the first half of vercel.json's buildCommand, so a non-zero exit stops the build before the UI is built.

Config is relay.config.json → publishCheck. Run it yourself with node query/build-corpus.ts --census.

⛔ If Publish Check refuses a deploy, the instructions are docs/PUBLISH-CHECK.md — the refusal output ends with that path, because a control nobody remembers how to operate gets bypassed (DN9-D104).

This repo is Relay-governed

It carries its own relay.config.json, ROADMAP.md, WAYS-OF-WORKING.md and docs/sessions/ paper trail, and runs the kit's own gates on itself:

npx relay verify-open         # the same command a consumer runs — the bin resolves locally either way
npx relay verify-close
npm test

Session ids here are RL-D<n>-P<seq>. Legacy RELAY-D* / CF-D* ids in CHANGELOG.md are a different, historical series — see WAYS-OF-WORKING.md § 2.1. Start with WAYS-OF-WORKING.md and docs/sessions/SESSION-HANDOFF.md.

⚠️ Never run attic/sync-relay.sh against this repo. It vendors kit/ into a consumer; this repo is the source. Pointed here it would overwrite kit/ with a copy of itself and stamp a consumer relayVersion. The script REFUSES a self-target in code (TD-RELAY-SYNC-SELF-GUARD, shipped RL-D008) — this paragraph previously said no guard existed, which stopped being true at RL-D008 and was corrected at RL-D014. The refusal is asserted from the attic/ path in test/distribution.test.mjs. The standing obligation SO-KIT-IS-SOURCE was RETIRED at RL-D015 once both consumers of the day (HZ + CF, the only two that existed then) moved to npm — the prohibition above is unchanged and the in-code guard stays; what ended is the re-confirm-every-close ceremony for a mechanism nobody uses any more. The script itself is archived, not deleted.

Vendor into a project

./attic/sync-relay.sh --dry-run ~/path/to/project    # preview
./attic/sync-relay.sh ~/path/to/project              # apply (target must be clean)

Then ensure the target's relay.config.json has the required keys (see kit/CLAUDE.md.skeleton and RELAY-CORE.md § Config): projectPrefix, ownerName (required), docsCheck, etc.

relay-site (static site generator)

Turns a project's ROADMAP.md + docs/relay/ session artifacts into a static site. Opt-in: add a site block to the target's relay.config.json. No site block → the script exits 0 with "not configured" and writes nothing, so it is inert in every project that has not asked for it.

npx relay site                        # or: make site
npx serve docs/site                   # generator does NOT serve — preview separately

Design brief, config schema, and the ROADMAP.md convention the parser expects: docs/relay-site.md. Tests: ./test/run-tests.sh (synthetic fixture; no real project is touched).

Dependencies

The kit is vendored by file copy, not installed by a package manager — so a target repo receives the scripts without receiving what they import. kit-dependencies.json declares the gap:

DependencyNeeded byIf missing
Node >=18all kit scriptsESM + top-level await; fetch/AbortController in verify-close.mjs
micromatch ^4.0.8 (runtime)kit/docs-check.mjsdocs:check cannot run at all — the import throws before any check executes

sync-relay.sh reads this file and checks the target after vendoring, printing the exact install command for anything unmet. It reports only — it never installs, and never edits the target's package.json. Adding a dependency to a target repo is that repo owner's decision, not the sync script's.

Everything else the kit imports is a node: builtin.

The two channels classify micromatch differently, and both are correct. A vendored consumer receives readable kit/docs-check.mjs, which imports micromatch at module load — so for that channel it is a genuine runtime requirement, which is what kit-dependencies.json declares. The published npm package ships a bundled build with micromatch inlined, so it has no runtime dependency at all; there micromatch is a build-time tool and sits in devDependencies. The published tarball's third-party dependency count is zero.

Distribution and licence

Relay is distributed under a proprietary licence — all rights reserved. See LICENSE. It is not open source, and the ISC declaration that appeared in package.json before v1.6.11 was a placeholder that never matched any licence text.

⚠️ The current LICENSE text is a DRAFT pending trademark and licensing review by counsel (RL-D010). It must be cleared before the first public npm publish.

The published package is a bundled, minified build produced by npm run build from kit/ into dist/. Source is not distributed and source maps are never emitted — build.mjs sets sourcemap: false and both the build and the test suite fail if a .map file or a sourceMappingURL string reaches the output. A source map would ship the entire readable source and silently undo this.

Some files ship readable by design, each for a stated reason (see VERBATIM in build.mjs): RELAY-CORE.md (the protocol is meant to be read), the four commands/*.md, CLAUDE.md.skeleton, Makefile.template and settings.presets.json — all of which relay init writes into your repository, where being readable is the product rather than a leak.

The package runs no code on your machine at install time — ever. There is no postinstall, and no preinstall, install, prepare or prepublish either. relay init writes into .claude/, the directory an agent takes its instructions from, so it must stay a typed command: a package that edits agent instructions as a side effect of npm install could change an agent's behaviour during an unrelated dependency bump. The test suite asserts every install-time hook is absent.

prepublishOnly is the deliberate exception, and it is not the same class. It runs node build.mjs && npm test on the publisher's machine during npm publish — never on a consumer's, and it is not even present in the published tarball's execution path. It exists because "remember to run the build before publishing" is a manual step guarding the difference between shipping the current code and shipping a stale dist/, and manual steps of that shape have already failed here (the version-file sync incidents). Mechanised, it cannot be forgotten. See docs/npm-deprecation-policy.md § Lifecycle hooks for the full install-time/publisher-side split.

If a bad version ships

Corrections go forward, never backward — see docs/npm-deprecation-policy.md. npm restricts unpublishing after 72 hours, and unpublishing breaks every install that already resolved to that version. A bad publish is fixed with a patch release plus npm deprecate on the bad version, not by withdrawing it.

版本与发布记录

@atlanticus-ai/relay 共发布 12 个版本,首次发布于 2026/10/30;过去 12 个月发布了 12 个版本。

版本发布日期距今
2.58.1latest2026/11/071 天前
2.51.02026/11/035 天前
2.50.02026/11/025 天前
2.49.02026/11/026 天前
2.48.02026/11/016 天前
2.47.02026/11/017 天前

关于 @atlanticus-ai/relay 的常见问题

@atlanticus-ai/relay 是什么?

Session operating system for owner-gated, agent-executed development. Fail-closed session gates, an append-only paper trail, and one protocol across many projects.

如何安装 @atlanticus-ai/relay?

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

@atlanticus-ai/relay 支持 TypeScript 吗?

该包的 package.json 没有声明类型入口。需要类型提示时,可以在 npm 上查找社区维护的 @types/atlanticus-ai__relay 是否存在。

@atlanticus-ai/relay 支持 ESM 还是 CommonJS?

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

@atlanticus-ai/relay 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=24。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@atlanticus-ai/relay 可以商用吗?

@atlanticus-ai/relay 使用 SEE LICENSE IN LICENSE 许可。许可条款写在包内的独立文件中,请阅读该文件确认可否商用。以上为概括,不构成法律意见,请以许可原文为准。

@atlanticus-ai/relay 的下载量有多少?

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

@atlanticus-ai/relay 还在维护吗?

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