@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 +66 -6
- package/package.json +1 -1
- package/skills/_meta.json +1 -1
- package/skills/contributors/_meta.json +17 -2
- package/skills/contributors/extract-test-setup-into-functions.md +56 -0
- package/skills/contributors/fix-at-the-source.md +4 -0
- package/skills/contributors/index.md +13 -2
- package/skills/contributors/keep-commits-human-authored.md +40 -0
- package/skills/contributors/overview.md +6 -0
- package/skills/contributors/start-in-a-fresh-worktree.md +31 -19
- package/skills/contributors/submit-a-pr.md +104 -0
- package/skills/contributors/use-ci-as-the-source-of-truth.md +39 -0
- package/skills/contributors/write-documentation.md +116 -0
- package/skills/contributors/writing-and-implementing-rfcs.md +84 -0
- package/skills/docs/_meta.json +7 -0
- package/skills/docs/read-the-docs-as-markdown.md +40 -0
- package/skills/holodeck/_meta.json +7 -0
- package/skills/holodeck/using-record.md +58 -0
- package/skills/index.md +2 -0
- package/skills/overview.md +2 -0
package/README.md
CHANGED
|
@@ -8,13 +8,11 @@
|
|
|
8
8
|
/>
|
|
9
9
|
</p>
|
|
10
10
|
|
|
11
|
-

|
|
12
|
+

|
|
13
13
|

|
|
14
|
-
[](https://discord.gg/zT3asNS
|
|
15
|
-
)
|
|
16
|
-
[](https://discord.gg/PHBbnWJx5S
|
|
17
|
-
)
|
|
14
|
+
[](https://discord.gg/zT3asNS)
|
|
15
|
+
[](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.
|
|
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,10 +1,25 @@
|
|
|
1
1
|
{
|
|
2
2
|
"title": "Contributors",
|
|
3
|
-
"items": [
|
|
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
|
-
"
|
|
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
|
|
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
|
|
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
|
|
26
|
-
nested inside it. This is not a tidiness preference — Node's resolution
|
|
27
|
-
*upward* for `node_modules`, so a worktree at `<repo>/anything/my-worktree`
|
|
28
|
-
any dependency or `bin` its own install hasn't provided from
|
|
29
|
-
primary checkout's tree. Three properties of this repo turn that
|
|
30
|
-
than an error: `pnpm-workspace.yaml` sets `hoist: false` and uses
|
|
31
|
-
specifically to keep each test app's dep tree isolated, `pnpm
|
|
32
|
-
into consumers' `node_modules`, and the packages lean on
|
|
33
|
-
gets the other checkout's `dist`, mismatched versions,
|
|
34
|
-
private-brand type errors that point nowhere near the
|
|
35
|
-
holding a `node_modules`, so resolution can't cross
|
|
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"
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
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
|
|
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
|
|
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,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,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
|
package/skills/overview.md
CHANGED
|
@@ -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
|