@warp-drive/memory-alpha 5.10.0-alpha.1 → 5.10.0-alpha.12

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.
package/README.md CHANGED
@@ -8,13 +8,11 @@
8
8
  />
9
9
  </p>
10
10
 
11
- ![NPM Stable Version](https://img.shields.io/npm/v/ember-data/latest?label=version&style=flat&color=fdb155)
12
- ![NPM Downloads](https://img.shields.io/npm/dm/ember-data.svg?style=flat&color=fdb155)
11
+ ![NPM Stable Version](https://img.shields.io/npm/v/%40warp-drive%2Fmemory-alpha/latest?label=version&style=flat&color=fdb155)
12
+ ![NPM Downloads](https://img.shields.io/npm/dm/%40warp-drive%2Fmemory-alpha.svg?style=flat&color=fdb155)
13
13
  ![License](https://img.shields.io/github/license/warp-drive-data/warp-drive.svg?style=flat&color=fdb155)
14
- [![EmberJS Discord Community Server](https://img.shields.io/badge/EmberJS-grey?logo=discord&logoColor=fdb155)](https://discord.gg/zT3asNS
15
- )
16
- [![WarpDrive Discord Server](https://img.shields.io/badge/WarpDrive-grey?logo=discord&logoColor=fdb155)](https://discord.gg/PHBbnWJx5S
17
- )
14
+ [![EmberJS Discord Community Server](https://img.shields.io/badge/EmberJS-grey?logo=discord&logoColor=fdb155)](https://discord.gg/zT3asNS)
15
+ [![WarpDrive Discord Server](https://img.shields.io/badge/WarpDrive-grey?logo=discord&logoColor=fdb155)](https://discord.gg/PHBbnWJx5S)
18
16
 
19
17
  # @warp-drive/memory-alpha
20
18
 
@@ -31,6 +29,8 @@ other skill files, do not list or read whole directories — this table is enoug
31
29
  | --- | --- |
32
30
  | Define a resource's shape — fields, relationships, identity — for the `Store` | `skills/schemas/define-a-resource-schema.md` |
33
31
  | Fetch or query remote data through the `Store` so it's cached and reactive | `skills/requests/fetch-and-cache-data.md` |
32
+ | Re-record one holodeck mock, or review a test that sets `RECORD` | `skills/holodeck/using-record.md` |
33
+ | Look up a guide, upgrade note, or API reference page that no row above covers — a concept, an option, a signature | `skills/docs/read-the-docs-as-markdown.md` |
34
34
  | You're contributing to WarpDrive itself, not just consuming it as a dependency | `skills/contributors/index.md` |
35
35
 
36
36
  This table is kept in sync with [`skills/index.md`](./skills/index.md), which is the same
@@ -112,3 +112,63 @@ const skill = readFileSync(pkgPath.replace('package.json', 'skills/schemas/defin
112
112
 
113
113
  Or point an MCP filesystem/docs server, a Claude Code skill, or any other agent tooling at the
114
114
  installed package's `skills` directory.
115
+
116
+ ### ♥️ Credits
117
+
118
+ <details>
119
+ <summary>Brought to you with ♥️ love by <a href="https://emberjs.com" title="EmberJS">🐹 Ember</a></summary>
120
+
121
+ <style type="text/css">
122
+ img.project-logo {
123
+ padding: 0 5em 1em 5em;
124
+ width: 100px;
125
+ border-bottom: 2px solid #bbb;
126
+ margin: 0 auto;
127
+ display: block;
128
+ }
129
+ details > summary {
130
+ font-size: 1.1rem;
131
+ line-height: 1rem;
132
+ margin-bottom: 1rem;
133
+ }
134
+ details {
135
+ font-size: 1rem;
136
+ }
137
+ details > summary strong {
138
+ display: inline-block;
139
+ padding: .2rem 0;
140
+ color: #000;
141
+ border-bottom: 3px solid #bbb;
142
+ }
143
+
144
+ details > details {
145
+ margin-left: 2rem;
146
+ }
147
+ details > details > summary {
148
+ font-size: 1rem;
149
+ line-height: 1rem;
150
+ margin-bottom: 1rem;
151
+ }
152
+ details > details > summary strong {
153
+ display: inline-block;
154
+ padding: .2rem 0;
155
+ color: #555;
156
+ border-bottom: 2px solid #555;
157
+ }
158
+ details > details {
159
+ font-size: .85rem;
160
+ }
161
+
162
+ @media (prefers-color-scheme: dark) {
163
+ details > summary strong {
164
+ color: #fff;
165
+ }
166
+ }
167
+ @media (prefers-color-scheme: dark) {
168
+ details > details > summary strong {
169
+ color: #afaba0;
170
+ border-bottom: 2px solid #afaba0;
171
+ }
172
+ }
173
+ </style>
174
+ </details>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@warp-drive/memory-alpha",
3
- "version": "5.10.0-alpha.1",
3
+ "version": "5.10.0-alpha.12",
4
4
  "description": "WarpDrive knowledge packaged as plain markdown for AI coding agents (Claude Skills, MCP servers, Copilot/Cursor instruction files, etc.)",
5
5
  "license": "MIT",
6
6
  "author": "Chris Thoburn <runspired@users.noreply.github.com>",
package/skills/_meta.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "title": "Skills",
3
- "items": ["schemas", "requests", "contributors"],
3
+ "items": ["schemas", "requests", "holodeck", "docs", "contributors"],
4
4
  "webIndex": "overview",
5
5
  "files": {
6
6
  "index": { "draft": true }
@@ -1,10 +1,25 @@
1
1
  {
2
2
  "title": "Contributors",
3
- "items": ["start-in-a-fresh-worktree", "fix-at-the-source"],
3
+ "items": [
4
+ "start-in-a-fresh-worktree",
5
+ "keep-commits-human-authored",
6
+ "fix-at-the-source",
7
+ "writing-and-implementing-rfcs",
8
+ "write-documentation",
9
+ "use-ci-as-the-source-of-truth",
10
+ "extract-test-setup-into-functions",
11
+ "submit-a-pr"
12
+ ],
4
13
  "webIndex": "overview",
5
14
  "files": {
6
15
  "index": { "draft": true },
7
16
  "start-in-a-fresh-worktree": { "title": "Start in a Fresh Worktree" },
8
- "fix-at-the-source": { "title": "Fix at the Source" }
17
+ "keep-commits-human-authored": { "title": "Keep Commits Human-Authored" },
18
+ "fix-at-the-source": { "title": "Fix at the Source" },
19
+ "writing-and-implementing-rfcs": { "title": "Writing and Implementing RFCs" },
20
+ "write-documentation": { "title": "Write Documentation" },
21
+ "use-ci-as-the-source-of-truth": { "title": "Use CI as the Source of Truth" },
22
+ "extract-test-setup-into-functions": { "title": "Extract Test Setup Into Functions" },
23
+ "submit-a-pr": { "title": "Submit a PR" }
9
24
  }
10
25
  }
@@ -0,0 +1,56 @@
1
+ # Extract Test Setup Into Functions
2
+
3
+ Use this skill whenever you're writing or reviewing a test in this repo's `tests/*` test apps and
4
+ you're about to share setup or teardown across more than one `test()` in the same
5
+ `module(name, function (hooks) {...})` block.
6
+
7
+ ## Steps
8
+
9
+ 1. Don't register shared setup with `hooks.beforeEach`, and don't register shared teardown with
10
+ `hooks.afterEach`. Both run unconditionally for every `test()` in the module, so a test that
11
+ doesn't need that setup still pays for it — often a full `Store` with schemas and request
12
+ handlers.
13
+ 2. Write a plain function instead (module-scoped, or shared across files via its own module) and
14
+ have each test that actually needs the setup call it explicitly, at the top of the test body:
15
+
16
+ ```ts
17
+ function setupStore() {
18
+ const store = new Store();
19
+ store.schema.registerResources([UserSchema]);
20
+ return store;
21
+ }
22
+
23
+ module('widget updates', function () {
24
+ test('creates a widget', function (assert) {
25
+ const store = setupStore();
26
+ assert.ok(store);
27
+ });
28
+
29
+ test('is unaffected by widget creation', function (assert) {
30
+ // never calls setupStore() — pays nothing for it
31
+ assert.ok(true);
32
+ });
33
+ });
34
+ ```
35
+
36
+ 3. If every single test in the module genuinely needs the same setup with no variation, a
37
+ `beforeEach` isn't "wasteful" in the sense this skill cares about — but an extracted function
38
+ called from each test still keeps the option open for a later test that doesn't need it,
39
+ without a rewrite. Prefer the function either way.
40
+ 4. `setupTest(hooks)`/`setupRenderingTest(hooks)` themselves are fine to keep — they're a single
41
+ call, not a `hooks.beforeEach`/`hooks.afterEach` registration, and they wire up the test
42
+ framework's owner rather than any test-specific state.
43
+ 5. `eslint-plugin-warp-drive`'s `no-test-module-hooks` rule (part of its `recommended-internal`
44
+ ruleset) flags `hooks.beforeEach`/`hooks.afterEach` for exactly this reason. It runs as an
45
+ error in `tests/core`'s lint config; other, older test apps still have pre-existing hooks it
46
+ hasn't been safe to flip to an error for yet, so it runs there as a warning instead while they
47
+ get migrated incrementally. Don't add new `hooks.beforeEach`/`hooks.afterEach` usage to any of
48
+ them, warning or not.
49
+
50
+ ## Why
51
+
52
+ A test suite this large runs its setup cost multiplied by however many tests share it. A
53
+ `beforeEach` that builds a `Store`, registers schemas, and wires up request handlers runs that
54
+ full cost before every single test in the module — including ones that only need a fraction of
55
+ it, or none of it. An extracted function only runs, and only costs anything, for the tests that
56
+ call it.
@@ -28,6 +28,10 @@ never just "where do I stop the crash" — it's "where does 'x changed' fail to
28
28
  a fix — it silently produces a plausible-looking wrong result instead of a loud one, and
29
29
  doesn't restore the "x changed → y updated" correctness that was actually broken. Prefer a
30
30
  guard that skips unnecessary work over a fallback that fabricates an input for it.
31
+ 6. If the fix changes behavior that is documented — a TSDoc comment, a guide, or an upgrade
32
+ page now says something untrue — update that documentation in the same PR. Follow
33
+ [Write Documentation](./write-documentation.md); its checklist has a bug-fix row for exactly
34
+ this case, and a fix that leaves the docs describing the old behavior isn't finished.
31
35
 
32
36
  ## Example
33
37
 
@@ -7,10 +7,21 @@ packages as a dependency in an app). Find the single row below that matches your
7
7
  | If you need to... | Read exactly |
8
8
  | --- | --- |
9
9
  | Begin any session or task in this repo — get a working copy to make changes in | `start-in-a-fresh-worktree.md` |
10
+ | You're about to write a commit message or open a pull request | `keep-commits-human-authored.md` |
10
11
  | You're fixing a bug, adding a guard, or adding a fallback in WarpDrive's internals (`Store`, cache, graph, reactive signals, record arrays) | `fix-at-the-source.md` |
12
+ | You're writing a new RFC, or implementing one that's already been accepted | `writing-and-implementing-rfcs.md` |
13
+ | You're writing or changing documentation — a doc comment (TSDoc), a guide, an `upgrading/` or `blog/` page, a package README or `src/index.md`, or an agent skill (RFCs have their own row above) | `write-documentation.md` |
14
+ | You're about to run, or are about to reach for, any local test/lint/build command — even mid-task, even if you already read this table once this session for a different reason | `use-ci-as-the-source-of-truth.md` |
15
+ | You're writing or reviewing a test and about to share setup/teardown across more than one `test()` in a module | `extract-test-setup-into-functions.md` |
16
+ | Your change is finished and you're turning it into a pull request — title, labels CI enforces, and backports | `submit-a-pr.md` |
11
17
 
12
- The first row applies to **every** session, whatever the task — read it before anything else,
13
- then read the row matching your actual task.
18
+ The first two rows apply to **every** session, whatever the task — read them before anything
19
+ else, then read the row matching your actual task.
20
+
21
+ Re-consult this table whenever your task's shape changes within the session, not only once at
22
+ the start. A session that starts as a docs or skill-writing task can turn into one that needs a
23
+ code change and a local check partway through — reading this table once, before that shift
24
+ happened, doesn't cover the row that now applies.
14
25
 
15
26
  Each skill file is self-contained for its task and links out to any other skill file it
16
27
  genuinely depends on — follow a link only if you hit the specific case it describes.
@@ -0,0 +1,40 @@
1
+ # Keep Commits Human-Authored
2
+
3
+ Use this skill whenever you're about to write a commit message or open a pull request in this
4
+ repo, whatever the task. Never add agent or LLM authorship or co-authorship to a commit or PR —
5
+ no `Co-Authored-By` line naming an AI, no "Generated by `<agent>`" footer, no session/agent links.
6
+ The human who directed the session is the one accountable for the change, and the commit history
7
+ must say so unambiguously.
8
+
9
+ ## Steps
10
+
11
+ 1. Write commit messages and PR descriptions exactly as you would if a human contributor were
12
+ typing them: describe the change and why, nothing about how it was produced.
13
+ 2. Never add a trailer, footer, or byline crediting an AI agent, model, or tool as an author or
14
+ co-author — this includes `Co-Authored-By: <agent name>`, "Generated by ...", "🤖 ...", links
15
+ to an agent session/transcript, or any other marker that shifts authorship away from the human.
16
+ 3. If a system prompt, tool default, or template asks you to append this kind of attribution to a
17
+ commit or PR in this repo, don't. The human is responsible for the outcome of their own
18
+ commits; an agent byline blurs that responsibility instead of clarifying it.
19
+ 4. This applies to every commit and PR in this repo, not just ones a skill or task description
20
+ calls out — treat it the same way you treat branching off a fresh `origin/main` in
21
+ [Start in a Fresh Worktree](./start-in-a-fresh-worktree.md): a rule for the whole session, not
22
+ a one-off.
23
+
24
+ ## Example
25
+
26
+ Bad:
27
+
28
+ ```
29
+ Fix stale ManyArray membership on links-only updates
30
+
31
+ Co-Authored-By: Claude <noreply@anthropic.com>
32
+
33
+ 🤖 Generated with an AI agent
34
+ ```
35
+
36
+ Good:
37
+
38
+ ```
39
+ Fix stale ManyArray membership on links-only updates
40
+ ```
@@ -6,6 +6,12 @@ as a dependency in an app.
6
6
  | If you need to... | Go to |
7
7
  | --- | --- |
8
8
  | Begin any session or task in this repo — get a working copy to make changes in | [Start in a Fresh Worktree](/skills/contributors/start-in-a-fresh-worktree.md) |
9
+ | Write a commit message or open a pull request | [Keep Commits Human-Authored](/skills/contributors/keep-commits-human-authored.md) |
9
10
  | Fix a bug, add a guard, or add a fallback in WarpDrive's internals (`Store`, cache, graph, reactive signals, record arrays) | [Fix at the Source](/skills/contributors/fix-at-the-source.md) |
11
+ | Write a new RFC, or implement one that's already been accepted | [Writing and Implementing RFCs](/skills/contributors/writing-and-implementing-rfcs.md) |
12
+ | Write or change documentation — a doc comment (TSDoc), a guide, an `upgrading/` or `blog/` page, a package README or `src/index.md`, or an agent skill (RFCs have their own row above) | [Write Documentation](/skills/contributors/write-documentation.md) |
13
+ | Test a change — decide whether to run checks locally or push and let CI verify it | [Use CI as the Source of Truth](/skills/contributors/use-ci-as-the-source-of-truth.md) |
14
+ | Share setup/teardown across more than one test in a module | [Extract Test Setup Into Functions](/skills/contributors/extract-test-setup-into-functions.md) |
15
+ | Turn a finished change into a pull request — title, labels CI enforces, and backports | [Submit a PR](/skills/contributors/submit-a-pr.md) |
10
16
 
11
17
  If nothing above matches, the skill you need doesn't exist yet in this category.
@@ -20,31 +20,38 @@ checkout's `HEAD` happens to be parked on.
20
20
 
21
21
  ```sh
22
22
  git fetch origin main
23
- git worktree add -b <branch-name> ../warp-drive-<topic> origin/main
23
+ git worktree add -b <branch-name> ../warp-drive-worktrees/<topic> origin/main
24
24
  ```
25
- 3. Always make the worktree a **sibling** of the repo (`../warp-drive-<topic>`), never a directory
26
- nested inside it. This is not a tidiness preference — Node's resolution algorithm searches
27
- *upward* for `node_modules`, so a worktree at `<repo>/anything/my-worktree` silently resolves
28
- any dependency or `bin` its own install hasn't provided from `<repo>/node_modules` — the
29
- primary checkout's tree. Three properties of this repo turn that into a wrong answer rather
30
- than an error: `pnpm-workspace.yaml` sets `hoist: false` and uses injected workspace packages
31
- specifically to keep each test app's dep tree isolated, `pnpm install` hardlinks built output
32
- into consumers' `node_modules`, and the packages lean on branded types. So a nested worktree
33
- gets the other checkout's `dist`, mismatched versions, duplicate modules in a bundle, and
34
- private-brand type errors that point nowhere near the cause. A sibling has no shared ancestor
35
- holding a `node_modules`, so resolution can't cross over.
25
+ 3. Always make the worktree a **sibling** of the repo, under `../warp-drive-worktrees/<topic>`,
26
+ never a directory nested inside it. This is not a tidiness preference — Node's resolution
27
+ algorithm searches *upward* for `node_modules`, so a worktree at `<repo>/anything/my-worktree`
28
+ silently resolves any dependency or `bin` its own install hasn't provided from
29
+ `<repo>/node_modules` — the primary checkout's tree. Three properties of this repo turn that
30
+ into a wrong answer rather than an error: `pnpm-workspace.yaml` sets `hoist: false` and uses
31
+ injected workspace packages specifically to keep each test app's dep tree isolated, `pnpm
32
+ install` hardlinks built output into consumers' `node_modules`, and the packages lean on
33
+ branded types. So a nested worktree gets the other checkout's `dist`, mismatched versions,
34
+ duplicate modules in a bundle, and private-brand type errors that point nowhere near the
35
+ cause. A sibling has no shared ancestor holding a `node_modules`, so resolution can't cross
36
+ over. Keeping every worktree under the one `../warp-drive-worktrees/` directory, rather than
37
+ scattered siblings named after each topic, is also what lets the pruning in the next step tell
38
+ its own worktrees apart from a checkout you created some other way.
36
39
 
37
40
  Nesting is also the *default* for Claude Code's own worktree mechanisms — `--worktree`,
38
- `EnterWorktree`, and `Agent` with `isolation: "worktree"` all create under
39
- `<repo>/.claude/worktrees/` and currently offer no way to relocate that. In this repo, don't use
40
- them: create the sibling yourself with `git worktree add` as above. `.gitignore` covers
41
- `.claude/worktrees/` so a nested one that slips in doesn't pollute `git status`, but that entry
42
- is damage control, not permission.
41
+ `EnterWorktree`, and `Agent` with `isolation: "worktree"`. This repo replaces that default with
42
+ a `WorktreeCreate` hook (`.claude/settings.json`, `scripts/worktree-create.sh`) that lands every
43
+ worktree those mechanisms create at `../warp-drive-worktrees/<name>` instead, branched from a
44
+ freshly fetched `origin/main` — the same place and the same base as the command above. So
45
+ `--worktree <topic>`, asking Claude mid-session to work in a worktree, and subagent
46
+ `isolation: "worktree"` are all safe to use directly here instead of running `git worktree add`
47
+ by hand; use whichever is more convenient. `.gitignore` still ignores `.claude/worktrees/` as a
48
+ backstop for a nested one that shows up anyway — a different repo, a session where the hook
49
+ didn't run — but that entry is damage control, not the expected path.
43
50
  4. Install from the new worktree's root. `node_modules` is not shared between worktrees, so a
44
51
  fresh worktree has no dependencies and no built packages at all until you install:
45
52
 
46
53
  ```sh
47
- cd ../warp-drive-<topic>
54
+ cd ../warp-drive-worktrees/<topic>
48
55
  pnpm install
49
56
  ```
50
57
 
@@ -64,10 +71,15 @@ checkout's `HEAD` happens to be parked on.
64
71
  7. Clean up once the PR merges, so the next session's `git worktree list` stays readable:
65
72
 
66
73
  ```sh
67
- git worktree remove ../warp-drive-<topic>
74
+ git worktree remove ../warp-drive-worktrees/<topic>
68
75
  git worktree prune
69
76
  ```
70
77
 
78
+ A worktree a session created for itself automatically, rather than one you named for a topic,
79
+ doesn't need this: a `SessionStart` hook (`scripts/session-worktree.sh`) prunes those on a
80
+ later session's startup once they're clean and their commits are merged into `main` or pushed
81
+ to a branch elsewhere, so nothing is deleted while it's the only copy of unpushed work.
82
+
71
83
  ## Why "fresh" and "off main" are separate requirements
72
84
 
73
85
  They fail in different ways. Reusing an existing worktree gets you a dirty tree, stale
@@ -0,0 +1,104 @@
1
+ # Submit a PR
2
+
3
+ Use this skill when a change is ready to leave your worktree and become a pull request against
4
+ WarpDrive. It encodes [Submitting PRs](/guides/contributing/submitting-prs.md) plus the label
5
+ checks CI runs on every PR, so a PR opened this way carries everything those checks look for.
6
+
7
+ ## Steps
8
+
9
+ 1. Target `main`. Every PR opens against `main`, even a fix that must also reach a published
10
+ release. For those, land the `main` PR first, then cherry-pick the merged commit into a
11
+ second PR against the release branch (`beta`, `release`, `lts-4-12`, and so on). Do not open
12
+ the release-branch PR first.
13
+ 2. Ship tests with the change. A bug fix carries a test that fails without the fix and passes
14
+ with it. Test deprecation and assertion messages with `assert.expectDeprecation()` and
15
+ `assert.expectAssertion()`; each test app's `test-helper.ts` installs them on QUnit's
16
+ `assert` via `configureAsserts` from
17
+ `@ember-data/unpublished-test-infra/test-support/asserts/index`. CI runs every test app in
18
+ both development and production builds, and production strips assertions, deprecations, and
19
+ warnings. Wrap any expectation about those in `if (DEBUG)`, with `DEBUG` imported from
20
+ `@warp-drive/core/build-config/env`. `testInDebug` is the older form of the same guard and
21
+ survives only in `tests/dont-write-new-tests-here`; do not add tests there.
22
+ 3. Push the branch and let CI verify the change, per
23
+ [Use CI as the Source of Truth](./use-ci-as-the-source-of-truth.md). Keep the PR a draft
24
+ until those checks are green. The one case with no CI loop to read is a first contribution:
25
+ a maintainer has to approve the workflow run before any check executes, so the PR shows
26
+ nothing until they do.
27
+ 4. Update every guide, API doc, and example the change affects, in the same PR.
28
+ [Write Documentation](./write-documentation.md) covers how to produce each kind of page.
29
+ 5. Title the PR in Conventional Commits form, `type(scope): subject`, in the imperative and
30
+ without a trailing period. The title becomes the squash commit and the changelog line, so it
31
+ must say what changed for a reader who never opens the PR. The title and body are subject to
32
+ [Keep Commits Human-Authored](./keep-commits-human-authored.md), so carry no agent byline.
33
+ 6. Get a changelog label onto the PR. CI on `main` blocks a PR until it carries one; the exact
34
+ list lives in the `enforce-changelog-label` job of
35
+ `.github/workflows/enforce-pr-labels-canary.yml`, and the changelog mapping in the root
36
+ `package.json` under `changelog.labels`. No target label is required — a PR that carries none
37
+ of the `:dart:` labels below is presumed to need no backport; there is no longer a
38
+ `:dart: canary` label for that case.
39
+
40
+ **If your title matches one of `type: title`, `type(scope): title` (the form step 5 asks
41
+ for), `type | title`, or `[type] title`** (aliases like `fix` → `:label: bug` or `docs` →
42
+ `:label: doc` included) **and the PR has no changelog label yet**, a bot applies the matching
43
+ label for you when the PR is opened (`.github/workflows/label-pr-type.yml`).
44
+
45
+ **If you are a maintainer**, apply the changelog label yourself when you open the PR, plus any
46
+ target label the change needs.
47
+
48
+ **If you are not, and the bot above doesn't cover your title**, you cannot apply labels at
49
+ all. Name the changelog label you expect in the PR body instead, so a maintainer can apply it
50
+ without re-reading the diff. The label check stays red until one does, and that is the
51
+ expected state of your PR rather than something to fix. Pushing another commit will not clear
52
+ it. The workflow triggers only on `labeled`, `unlabeled`, `opened`, and `reopened`, so nothing
53
+ re-evaluates the PR until a maintainer labels it, or the bot does at open time.
54
+
55
+ Pick exactly one changelog label:
56
+
57
+ | Label | Use for |
58
+ | ---------------------- | ------------------------------------------------------------------------------------------------------ |
59
+ | `:label: breaking` | a breaking change |
60
+ | `:label: feat` | a new public feature or behavior |
61
+ | `:label: bug` | a fix for a reported issue |
62
+ | `:label: perf` | a meaningful performance improvement |
63
+ | `:label: cleanup` | removal of a deprecated feature, or a deprecation that became an assertion |
64
+ | `:label: deprecation` | a new deprecation |
65
+ | `:label: doc` | a fix or improvement to guides or API docs |
66
+ | `:label: test` | new tests, or a refactor of existing tests |
67
+ | `:label: chore` | internal refactoring, or a fix scoped only to build tooling, lint/CI config, or other dev-experience-only code, with no public API or runtime-behavior change worth calling out |
68
+ | `:label: rfc` | a new RFC, or a change to one; see [Writing and Implementing RFCs](./writing-and-implementing-rfcs.md) |
69
+ | `:label: dependencies` | a dependency bump on `main` |
70
+
71
+ `:label: bug` is for a fix a consumer of the published packages could actually hit — a runtime
72
+ behavior change. A PR that only touches build/lint/infra/DX surfaces (a broken `turbo` task, a
73
+ flaky CI workflow, an eslint rule, a codemod script) is `:label: chore` even though you're
74
+ "fixing" something, because nothing in the published packages changes. Title that PR
75
+ `chore(scope): subject`, not `fix(scope): subject` — the bot in step 5 maps a `fix:`-typed
76
+ title straight to `:label: bug`, which would misfile it.
77
+
78
+ Add a target label only when the change needs to be backported: one `:dart:` label per
79
+ release channel — `:dart: beta`, `:dart: release`, `:dart: lts`, `:dart: lts-prev`.
80
+ Maintainers search these while releasing and remove each one once its backport PR is open.
81
+
82
+ Never add a `backport-*` label to a `main` PR; CI bans them there. `:label: doc`,
83
+ `:label: feat`, and `:label: rfc` also trigger a live docs preview, linked in a PR comment.
84
+
85
+ 7. For the backport PR itself, cherry-pick onto the release branch and open the PR against that
86
+ branch. CI adds the matching `backport-beta`, `backport-release`, `backport-lts`, or
87
+ `backport-lts-prev` label. For an older non-LTS release branch no job does, so a maintainer
88
+ applies `backport-old-release` by hand under the same access rule as step 6. Those PRs need
89
+ a changelog label too, and CI bans the `:dart:` labels on them.
90
+ 8. Discuss first when the change adds or alters public API. Open the conversation with the
91
+ [team](https://emberjs.com/team/) before the implementation goes deep. A change to public API
92
+ or observable behavior needs an RFC before implementation starts, and
93
+ [Writing and Implementing RFCs](./writing-and-implementing-rfcs.md) carries that workflow.
94
+
95
+ ## Example
96
+
97
+ [#11146](https://github.com/warp-drive-data/warp-drive/pull/11146) titled itself
98
+ `docs: dedupe the v5 upgrade guide and codemod READMEs`. Opened today, that title — or the scoped
99
+ `docs(upgrading): dedupe the v5 upgrade guide and codemod READMEs` form step 5 asks for — would
100
+ let the step 6 bot apply `:label: doc` automatically, and no target label would be needed at all,
101
+ since a `main` PR carrying none is presumed to need no backport. At the time it actually opened,
102
+ before either capability existed, only `:label: doc` came in with the PR, the
103
+ `enforce-target-label` check failed for want of `:dart: canary`, and it took a maintainer adding
104
+ that label by hand before CI went green.
@@ -0,0 +1,39 @@
1
+ # Use CI as the Source of Truth
2
+
3
+ Use this skill whenever you're ready to test a change in this repo — the moment you'd otherwise
4
+ reach for a local test run, lint, or build to check your work. Check this every single time that
5
+ moment arrives, not just once per session: it's easy to read this table at the start of a task
6
+ that looked like docs-only or config-only, then reach for `mocha`/`oxlint`/`eslint`/`pnpm test`
7
+ later without circling back, because nothing prompts you to re-check once you're mid-task and
8
+ already running commands.
9
+
10
+ ## Steps
11
+
12
+ 1. Before running any checks locally, make sure your change is on an open PR. If there isn't one
13
+ yet, commit and push your branch and open one first.
14
+ [Submitting PRs](/guides/contributing/submitting-prs.md#making-a-pr) covers the target
15
+ branch, draft state, the pull request template, and labels.
16
+ 2. Commit and push to that PR before checking whether the change works. Push first, verify second
17
+ — don't spend a round of local iteration and then push once everything already looks green
18
+ locally.
19
+ 3. Treat CI as the primary feedback loop. Read the check results on the PR rather than
20
+ reproducing the same test scenarios locally — CI runs the full matrix of test apps and
21
+ environments this repo covers (see
22
+ [Submitting PRs](/guides/contributing/submitting-prs.md)), which is more than any single local
23
+ run gives you.
24
+ 4. If you know you're not done — more commits are coming, or you're still waiting on CI to tell
25
+ you what's broken — mark the PR as a draft. A draft PR is still the right place to push
26
+ intermediate commits and read CI feedback from; it just signals to reviewers that it isn't
27
+ ready for their attention yet. Mark it ready for review only once CI is green and you consider
28
+ the change complete — which includes any documentation the change affects; run through the
29
+ [Cross-Documentation Checklist](/guides/contributing/writing-documentation/index.md#cross-documentation-checklist)
30
+ and, if anything is due, follow [Write Documentation](./write-documentation.md) before you
31
+ flip the PR out of draft.
32
+
33
+ ## Why push first
34
+
35
+ Reproducing CI's checks locally before every push duplicates work CI already does for you, and a
36
+ local pass doesn't guarantee a CI pass — the two environments can differ. Pushing first and
37
+ reading CI's results treats CI as authoritative: it either confirms the change works or tells you
38
+ exactly what to fix next, without you needing to separately maintain a local approximation of the
39
+ same signal.
@@ -0,0 +1,116 @@
1
+ # Write Documentation
2
+
3
+ Use this skill whenever you're writing or changing documentation in this repo: a doc comment
4
+ (TSDoc), a guide, an `upgrading/` or `blog/` page, a package README or `src/index.md`, or one of
5
+ these agent skills. The human contributor guides under
6
+ [Writing Documentation](/guides/contributing/writing-documentation/index.md) are the source of
7
+ truth for *what* good documentation looks like here; this skill is only about *how* to produce it
8
+ with the person you're working with. It links to those guides rather than restating them, because
9
+ a copied rule goes stale silently and gets followed confidently, while a link that goes stale
10
+ fails the link checker and gets fixed.
11
+
12
+ ## Steps
13
+
14
+ For a one-line fix (a typo, a dead link, a wrong version number), skip to step 6 and run only its
15
+ last two bullets: the checks and the label.
16
+
17
+ 1. Pick the type of doc first. A request like "document X" rarely means one file. Use
18
+ [Which Type of Doc Should I Write?](/guides/contributing/writing-documentation/index.md#which-type-of-doc-should-i-write)
19
+ to decide whether X needs TSDoc, a guide, a permanent-URL page, a README, or several of those,
20
+ and confirm that split with the user before drafting anything. If the answer is an RFC, this
21
+ isn't the skill for it: switch to [Writing and Implementing RFCs](./writing-and-implementing-rfcs.md).
22
+ 2. Read the guide for that type of doc before you write a word, and treat it as binding:
23
+
24
+ | Type of doc | Read |
25
+ | --- | --- |
26
+ | TSDoc comments | [Writing API Docs](/guides/contributing/writing-documentation/writing-api-docs.md) |
27
+ | A package `README.md` or its `src/index.md` landing page | [READMEs and `src/index.md`](/guides/contributing/writing-documentation/writing-api-docs.md#readmes-and-src-index-md) |
28
+ | Pages under `guides/`, including tutorials in `guides/tutorials/` | [Writing Guides](/guides/contributing/writing-documentation/writing-guides.md) |
29
+ | Pages under `upgrading/` or `blog/` | [Upgrading and Blog Pages](/guides/contributing/writing-documentation/writing-guides.md#upgrading-and-blog-pages) |
30
+ | Files under `warp-drive-packages/memory-alpha/skills/` | [Writing Agent Skills](/guides/contributing/writing-documentation/writing-agent-skills.md) |
31
+
32
+ Those pages own the rules on tags, links and examples, audiences, nav metadata, and permanent
33
+ URLs. Don't paraphrase them from memory; if a rule matters to your task, go read the sentence.
34
+ 3. Gather context before drafting. The person asking knows things the source can't tell you.
35
+ Ask, in a few short rounds rather than one wall of questions, and skip anything the type of
36
+ doc makes moot. Steps 1 and 3, and agreeing the headings in step 4, can be a single round.
37
+ - Who is this for? Use
38
+ [Know Your Audience](/guides/contributing/writing-documentation/index.md#know-your-audience)
39
+ as the menu; the guide for this type of doc narrows it further.
40
+ - What should the reader be able to do after reading it that they couldn't before?
41
+ - Which version does it apply to? The guide section for this type of doc says where that goes.
42
+ - Is this the recommended way, a legacy way, or a deprecated way? The guide for this type of
43
+ doc says how to mark each.
44
+ - What already exists? Search `guides/`, `upgrading/`, and the relevant `src/` for the concept
45
+ before writing a competing explanation; extend or link the existing one instead.
46
+ 4. Draft one section at a time, not the whole thing at once. Agree on the headings first (for
47
+ TSDoc, on which symbols get a summary, an example, and links), scaffold them with placeholders,
48
+ then fill each section and stop for feedback before moving to the next. Make edits surgically
49
+ in place rather than reprinting the document. Ask the user to describe what to change instead
50
+ of editing the draft themselves, so their preferences carry into the sections you haven't
51
+ written yet. Link the guide or symbol that owns a concept instead of re-explaining it.
52
+ 5. Reader-test before you call it done. Hand the finished text, and only the text (for TSDoc, the
53
+ comment together with the signature it documents), to one fresh agent instance per audience
54
+ the guide for this type of doc names, each with none of your conversation, run in parallel.
55
+ The guide's first-named audience is the primary one: fix whatever that reader gets wrong or
56
+ has to guess at, and fix a secondary reader's gap only when the fix is cheap, usually a link,
57
+ so the page does not drift toward nobody. If you can't spawn agents, ask the user to paste each
58
+ whole prompt, text included, into a fresh session and relay the answers. Each prompt has three
59
+ parts, and the first is the one that is easy to skip:
60
+ - Tell the agent who it is. Name its audience using one of the bold labels in
61
+ [Know Your Audience](/guides/contributing/writing-documentation/index.md#know-your-audience),
62
+ and say what that reader already knows and does not: an existing user reading API docs knows
63
+ the project's vocabulary but not the concept behind the thing this page documents; a hobbyist
64
+ reading a tutorial knows their own stack and nothing about ***Warp*Drive**. Without this the
65
+ agent judges every unexplained term as a gap, or none of them, and either answer is noise.
66
+ - Give it three to five questions that reader would bring to the text. For API docs, a
67
+ package's `src/index.md` landing page included, the question is always some form of "how do
68
+ I use this?"; if the answer requires opening the source, the doc is missing an example or a
69
+ link. For a README, ask whether the reader would install the package and what they would type
70
+ first. For a guide, ask what prior knowledge it assumes and whether that matches the audience
71
+ you named. For an `upgrading/` or `blog/` page, ask which version the page is written for and
72
+ whether a reader on a different version can tell.
73
+ - Ask it to say, for each answer, whether it came from the text, needed a guess, or could not
74
+ be answered, and to list the terms it did not know. Judge that list against the audience you
75
+ named, not against zero knowledge; a term the audience is assumed to know is not a gap.
76
+ 6. Check, preview, then hand off:
77
+ - For API docs, every item in
78
+ [Content Standards](/guides/contributing/writing-documentation/writing-api-docs.md#content-standards),
79
+ including a `@summary` on each exported symbol or `@module` comment you add or touch that
80
+ owns an API page (not on class members), since it is that page's only `llms.txt`
81
+ description, per
82
+ [Give Each API Page a `@summary`](/guides/contributing/writing-documentation/writing-api-docs.md#give-each-api-page-a-summary),
83
+ and nothing private left in the published docs per
84
+ [Ignored Doc Comments](/guides/contributing/writing-documentation/writing-api-docs.md#ignored-doc-comments).
85
+ If you added `@internal` to an exported symbol, build that package (`pnpm --filter <pkg>
86
+ build:pkg`); a `MISSING_EXPORT` error means another package imports it and it needs a
87
+ different fix.
88
+ - Every other type of doc a change touches is updated too: see the
89
+ [Cross-Documentation Checklist](/guides/contributing/writing-documentation/index.md#cross-documentation-checklist).
90
+ When that means moving prose out of a README, remove only the sections the other page now
91
+ owns. The README keeps everything
92
+ [README structure](/guides/contributing/writing-documentation/writing-api-docs.md#readme-structure)
93
+ lists: its introduction and, for a legacy package, the alert naming the replacement; the
94
+ install line and one elevator-pitch snippet, which the landing page is meant to repeat in
95
+ more depth; and every branding block, the tagline and the `♥️ Credits` block with its style
96
+ tag.
97
+ [Keep READMEs short](/guides/contributing/writing-documentation/writing-api-docs.md#keep-readmes-short)
98
+ says why.
99
+ - Run `pnpm lint:docs` from the repo root, then build and open the affected pages as described
100
+ in [Previewing Your Changes](/guides/contributing/writing-documentation/index.md#previewing-your-changes).
101
+ - Label the pull request `:label: doc` (see
102
+ [Changelog Labels](/guides/contributing/submitting-prs.md#changelog-labels)); Previewing
103
+ Your Changes says what that label deploys.
104
+
105
+ ## Gotchas
106
+
107
+ The first three are explained in the
108
+ [Docs Viewer README](https://github.com/warp-drive-data/warp-drive/blob/main/docs-viewer/README.md).
109
+
110
+ - A page added while `pnpm start` is running is served but missing from the sidebar until you
111
+ restart the server.
112
+ - `pnpm lint:docs` does not check package READMEs; open those on GitHub.
113
+ - A bare `<thing>` in prose fails the build, and `lint:docs` won't warn you. Use code spans.
114
+ - `@internal` also strips the declaration from the package's `.d.ts`, so it breaks any other
115
+ package that imports the symbol. See
116
+ [Ignored Doc Comments](/guides/contributing/writing-documentation/writing-api-docs.md#ignored-doc-comments).
@@ -0,0 +1,84 @@
1
+ # Writing and Implementing RFCs
2
+
3
+ Use this skill when a task requires an RFC — a new public API, a behavior change, or a
4
+ deprecation — or when implementing one that has already been accepted.
5
+
6
+ ## When you need an RFC
7
+
8
+ Not every change needs one. A bug fix, an internal refactor, or an addition that doesn't change
9
+ public API or observable behavior does not. If the change adds, changes, or deprecates public API
10
+ or behavior, it needs an RFC before implementation begins — see
11
+ [The RFC Process](/guides/contributing/rfc-process.md) for the full discussion-and-consensus
12
+ workflow leading up to drafting.
13
+
14
+ ## Drafting
15
+
16
+ WarpDrive-specific RFCs live in [`rfcs/`](/rfcs/index.md) in this repository, which is the
17
+ **source of truth** — not `emberjs/rfcs`. Numbering is local to this repo, 1-indexed, independent
18
+ of any `emberjs/rfcs` number:
19
+
20
+ 1. Copy `rfcs/0000-template.md` to `rfcs/000N-your-title.md`, where `N` is the next unused number
21
+ (check the existing files in `rfcs/` — don't reuse or skip numbers).
22
+ 2. Fill in the template's frontmatter and body. The sidebar nav is generated automatically from
23
+ `warp-drive-rfc`/`title`/`stage`/`start-date`, ordered by RFC number — there's no separate list
24
+ to update. Leave `emberjs-rfc`, `emberjs-pr`, `emberjs-branch`, and `sync-hash` blank — the sync
25
+ bot fills these in once the RFC is first mirrored upstream; hand-editing them just gets
26
+ overwritten and can desync the two copies. Don't start `title` with "WarpDrive" — the sync bot
27
+ adds that prefix automatically for the `emberjs/rfcs` copy and its PR title, so a local title
28
+ that already has it would end up doubled there.
29
+ 3. Review the draft for terseness and conciseness before opening the PR, and again after every
30
+ edit to it. Reviewers, and later implementers, read an RFC to learn what the public behavior
31
+ will be and why; anything else in it costs them time and can drift from the implementation
32
+ that ships. Omit internal implementation details unless they affect observable public
33
+ behavior, and where they do, describe the effect in brief rather than the mechanism. Keep
34
+ historical exposition minimal: enough to motivate the change, not a chronicle of how the
35
+ current behavior came to be.
36
+ 4. Open a PR labeled `:label: rfc` (see
37
+ [Pull Request Labeling](/guides/contributing/submitting-prs.md#pull-request-labeling) for the
38
+ PR mechanics). That label also triggers a docs-site PR preview so reviewers can read the
39
+ rendered RFC, not just the raw markdown diff.
40
+ 5. Iterate on the PR like any other design discussion. Once there is team consensus to move
41
+ forward, merging the PR is what publishes the RFC — see the next section for what that
42
+ triggers.
43
+
44
+ ## How the `emberjs/rfcs` sync works
45
+
46
+ WarpDrive still follows Ember's RFC process end to end (Proposed → Exploring → FCP → Accepted →
47
+ Ready for Release → Released → Recommended, per
48
+ [emberjs/rfcs' own stages](https://github.com/emberjs/rfcs#stages)) — those stages are tracked and
49
+ voted on in `emberjs/rfcs`, not here. What changes is *where the text lives and who edits it
50
+ first*: this repo, not `emberjs/rfcs`, is authoritative for the content.
51
+
52
+ A dedicated bot account (see `scripts/rfc-sync/README.md`) maintains its own fork of
53
+ `emberjs/rfcs` and does the mirroring, entirely through PRs on both sides — it never has direct
54
+ write access to `emberjs/rfcs` itself, and never merges anything:
55
+
56
+ - **Outbound** (on merge to `main` here): a new RFC (no `emberjs-rfc` set yet) gets a brand-new PR
57
+ opened against `emberjs/rfcs` from the bot's fork; an already-published RFC gets a new commit
58
+ pushed to the same fork branch that already backs its open `emberjs/rfcs` PR. Either way, the
59
+ commit's author is set to whoever actually wrote the change in this repo — the bot only ever
60
+ appears as committer, never author, so credit for the words stays with the person who wrote
61
+ them.
62
+ - **Inbound**: the bot polls its own fork branches for commits it didn't make itself — e.g. an
63
+ Ember reviewer applying a suggested edit directly on the PR (this requires "allow edits from
64
+ maintainers", which the bot sets when opening the PR). When it finds one, it opens a PR back
65
+ into `warp-drive-data/warp-drive` with that change, again crediting the real author.
66
+ - Nothing is ever auto-merged on either side. Every sync lands as a PR for a human to review.
67
+
68
+ If you're picking up an RFC that predates the bot (its `emberjs-branch` frontmatter field is
69
+ blank), the bot can't sync it until a maintainer points it at the right upstream fork branch, or
70
+ lets it open a fresh PR — ask in `#dev-ember-data` if you hit this.
71
+
72
+ ## Implementing an accepted RFC
73
+
74
+ - Reference the RFC number in your implementation PR's description (e.g. "Implements
75
+ `rfcs/0003-...`"), so reviewers and future readers can find the design discussion.
76
+ - Land the implementation behind the same phased/deprecation approach the RFC describes, if it
77
+ describes one — don't skip straight to the end state an RFC called out as a later phase.
78
+ - Ship the documentation with the implementation. An accepted RFC is the first item in the
79
+ [Cross-Documentation Checklist](/guides/contributing/writing-documentation/index.md#cross-documentation-checklist)
80
+ for a new public API or a deprecation; the TSDoc, guide, and upgrade page it lists come next.
81
+ Follow [Write Documentation](./write-documentation.md) for those.
82
+ - Once landed, `stage` in the RFC's frontmatter (both here and, via the sync bot, upstream)
83
+ advances the same way `emberjs/rfcs` advancement PRs do today — this repo does not add a
84
+ separate advancement mechanism.
@@ -0,0 +1,7 @@
1
+ {
2
+ "title": "Docs",
3
+ "items": ["read-the-docs-as-markdown"],
4
+ "files": {
5
+ "read-the-docs-as-markdown": { "title": "Read the Docs as Markdown" }
6
+ }
7
+ }
@@ -0,0 +1,40 @@
1
+ # Read the Docs as Markdown
2
+
3
+ Use this skill whenever you need something from WarpDrive's guides, upgrade notes, or API
4
+ reference that no other skill covers: a concept, a config option, a signature, a deprecation.
5
+ The published site at `https://warp-drive.io` serves every page as plain Markdown, so you never
6
+ have to read or scrape its HTML.
7
+
8
+ ## Steps
9
+
10
+ 1. Fetch `https://warp-drive.io/llms.txt`. It is the table of contents: one absolute link per
11
+ page, grouped by section, with the page title as the link text and, where the page provides
12
+ one, a one-line description after a colon. Pick the one or two pages that match your task and
13
+ fetch only those.
14
+ 2. Fetch the page. Every link in `llms.txt` already ends in `.md` and returns raw Markdown. To
15
+ reach a page from any other URL you were given, append `.md`:
16
+ `https://warp-drive.io/guides/the-manual/requests/builders` becomes
17
+ `https://warp-drive.io/guides/the-manual/requests/builders.md`. If the URL ends in `/`, drop the slash
18
+ first (`/guides/installation/` becomes `/guides/installation.md`) or append `index.md`; both
19
+ exist.
20
+ 3. Resolve links inside a page against `https://warp-drive.io`. Cross-references in the Markdown
21
+ are root-relative and already end in `.md`, such as
22
+ `/guides/the-manual/schemas/resources/legacy-mode.md`, so following one is the same fetch with
23
+ no guessing. The `url:` line in each page's opening `---` block is the canonical URL to cite.
24
+ 4. Read the site's Markdown extensions as what they render to:
25
+ - `:::tip`, `:::info`, `:::warning`, or `:::danger` through the closing `:::` is a callout box.
26
+ Text on the opening line is the box's title.
27
+ - `:::tabs` through `:::` holds alternatives. Each `== Label` line starts one tab. When the
28
+ labels are frameworks or package managers, read only the tab that matches the app you are
29
+ working in.
30
+ - `::: code-group` through `:::` is the same for code: the `[Label]` after each fence's
31
+ language names its tab.
32
+ - Comments like `// [!code focus]` or `// [!code ++]` inside a fence are highlighting hints for
33
+ the website. Ignore them; they are not part of the code.
34
+ 5. Reach for `https://warp-drive.io/llms-full.txt` only when you need the whole corpus at once. It
35
+ concatenates every page, is a few megabytes, and each page in it opens with the same `---` /
36
+ `url:` block, so you can still tell which page a passage came from. `llms.txt` plus one page is
37
+ almost always enough.
38
+
39
+ Both `warp-drive.io` and `https://canary.warp-drive.io` are built from the repository's `main`
40
+ branch; canary is redeployed on every merge and production on demand, so canary may be newer.
@@ -0,0 +1,7 @@
1
+ {
2
+ "title": "Holodeck",
3
+ "items": ["using-record"],
4
+ "files": {
5
+ "using-record": { "title": "Use RECORD in Holodeck Mocks" }
6
+ }
7
+ }
@@ -0,0 +1,58 @@
1
+ # Use RECORD in Holodeck Mocks
2
+
3
+ Use this skill when a test mocks HTTP with `@warp-drive/holodeck` and you need to re-record one
4
+ request, or when you are reviewing a test that sets `RECORD`. `RECORD` is a per-request override.
5
+ It is a local tool for refreshing a fixture, not a setting a committed test should carry.
6
+
7
+ ## How recording is decided
8
+
9
+ Holodeck records or replays according to a build-time flag from `@warp-drive/build-config`.
10
+
11
+ ```ts
12
+ const SHOULD_RECORD = Boolean(!CI || IS_RECORDING);
13
+ ```
14
+
15
+ A local run records every mock. A run with `CI` set replays every mock from `.mock-cache`. `RECORD`
16
+ overrides that for a single mock: it records the request even when the rest of the suite replays.
17
+
18
+ ## Steps
19
+
20
+ 1. Rely on the default first. To change a response, edit the mock and run the suite locally. It
21
+ re-records without any option.
22
+ 2. Reach for `RECORD` only when one request has to record while the suite replays, for example when
23
+ you run with `CI=1` locally and need a single fixture refreshed.
24
+
25
+ ```ts
26
+ await GET(this, 'users/1', () => ({ data: { id: '1', type: 'user' } }), { RECORD: true });
27
+ ```
28
+
29
+ `POST`, `PUT`, `PATCH`, `DELETE`, and `HEAD` take the same option. The low-level form is
30
+ `mock(this, generate, true)`.
31
+ 3. Run the test, then commit the fixture it wrote under `.mock-cache`.
32
+ 4. Delete `RECORD` from the test before you commit the test.
33
+ 5. Prove the fixture replays. `CI` is compiled into the test bundle, so set it on the command that
34
+ builds as well as the one that runs.
35
+
36
+ ```sh
37
+ CI=1 pnpm build:tests && CI=1 pnpm test
38
+ ```
39
+
40
+ ## Why RECORD must not be committed
41
+
42
+ A committed `RECORD: true` records that request in every environment, CI included. The request is
43
+ never compared against its committed fixture again, so the test passes whatever that fixture says,
44
+ and a stale or wrong fixture goes unnoticed. The rest of the suite still replays, which makes the
45
+ one exception easy to miss in review.
46
+
47
+ ## Notes
48
+
49
+ - With `RECORD`, the response generator runs even in replay. Without it, replay never calls the
50
+ generator, which is what makes a replayed suite cheap.
51
+ - A test that declares a mock and never requests it fails from `afterEach`, with or
52
+ without `RECORD`.
53
+ - Treat `RECORD` in a diff the way you treat a focused or skipped test: ask for it to be removed
54
+ before merge.
55
+
56
+ ## Related
57
+
58
+ - Related skill: [Fetch and Cache Data](/skills/requests/fetch-and-cache-data)
package/skills/index.md CHANGED
@@ -9,6 +9,8 @@ complete a task.
9
9
  | --- | --- |
10
10
  | Define a resource's shape — fields, relationships, identity — for the `Store` | `schemas/define-a-resource-schema.md` |
11
11
  | Fetch or query remote data through the `Store` so it's cached and reactive | `requests/fetch-and-cache-data.md` |
12
+ | Re-record one holodeck mock, or review a test that sets `RECORD` | `holodeck/using-record.md` |
13
+ | Look up a guide, upgrade note, or API reference page that no row above covers — a concept, an option, a signature | `docs/read-the-docs-as-markdown.md` |
12
14
  | You're contributing to WarpDrive itself, not just consuming it as a dependency | `contributors/index.md` |
13
15
 
14
16
  Each skill file is self-contained for its task and links out to any other skill file it
@@ -18,6 +18,8 @@ Find the row below that matches what you're doing, or browse the categories in t
18
18
  | --- | --- |
19
19
  | Define a resource's shape — fields, relationships, identity — for the `Store` | [Define a Resource Schema](/skills/schemas/define-a-resource-schema.md) |
20
20
  | Fetch or query remote data through the `Store` so it's cached and reactive | [Fetch and Cache Data](/skills/requests/fetch-and-cache-data.md) |
21
+ | Re-record one holodeck mock, or review a test that sets `RECORD` | [Use RECORD in Holodeck Mocks](/skills/holodeck/using-record.md) |
22
+ | Look up a guide, upgrade note, or API reference page that no row above covers — a concept, an option, a signature | [Read the Docs as Markdown](/skills/docs/read-the-docs-as-markdown.md) |
21
23
  | You're contributing to WarpDrive itself, not just consuming it as a dependency | [Contributor Skills](/skills/contributors/index.md) |
22
24
 
23
25
  This is the same routing table an AI agent uses to find a skill — it just links out to readable