@looop-games/cli 0.1.8 → 0.1.10

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/lib/update.mjs CHANGED
@@ -15,6 +15,7 @@ import { reconcileAgentSurface } from './agent-surface.mjs';
15
15
  import { getToken, getApiBase } from './config.mjs';
16
16
  import { login } from './login.mjs';
17
17
  import { DEFAULT_API_BASE } from './llm-shim.mjs';
18
+ import { compareVersions, renderReleases } from './changelog.mjs';
18
19
 
19
20
  // The report is the point. A creator reading this must be able to answer, with
20
21
  // no further digging: what changed, was any of it mine, and what do I do now.
@@ -72,9 +73,28 @@ export async function update({
72
73
  });
73
74
  if (res.status === 401) throw new Error('the platform rejected this machine’s token — run `looop login` again.');
74
75
  if (!res.ok) throw new Error(`could not list engine releases (HTTP ${res.status})`);
75
- const { latest } = await res.json();
76
+ const { latest, releases } = await res.json();
76
77
  if (!latest) throw new Error('the platform has no downloadable engine releases yet.');
77
78
 
79
+ // What the update is about to change UNDER the game (project note azlqm2).
80
+ // Reporting the skill files we rewrote and nothing about the engine was the
81
+ // whole gap: an agent crossed two versions of the shared library blind.
82
+ //
83
+ // A platform too old to serve `releases` must NOT block the update — it just
84
+ // has to be honest that it cannot say what changed. (`looop changelog`, whose
85
+ // only job is to answer that question, refuses outright instead.)
86
+ // Newest first, to match `looop changelog` and — more importantly — to match
87
+ // what renderReleases' own header SAYS. The endpoint returns them ascending;
88
+ // passing that straight through printed 0.1.13 above 0.1.14 under a heading
89
+ // that read "newest first". Caught by reading a real production run.
90
+ const crossed = Array.isArray(releases)
91
+ ? releases
92
+ .filter(
93
+ (r) => compareVersions(r.version, latest) <= 0 && (!from || compareVersions(r.version, from) > 0),
94
+ )
95
+ .sort((a, b) => compareVersions(b.version, a.version))
96
+ : null;
97
+
78
98
  let engineDir = null;
79
99
  let updated = false;
80
100
 
@@ -103,8 +123,15 @@ export async function update({
103
123
  if (!surface.skipped) report(log, surface.engineVersion ?? latest, surface);
104
124
 
105
125
  if (updated) {
126
+ log('');
127
+ if (crossed === null) {
128
+ log(' This Looop platform could not tell us what changed in the engine — no changelog');
129
+ log(' is available for the versions you just crossed.');
130
+ } else if (crossed.length) {
131
+ log(renderReleases(crossed, { pinned: from, latest }));
132
+ }
106
133
  log('');
107
134
  log(' Republish (`npx looop publish`) when you want the live game on it.');
108
135
  }
109
- return { from, to: latest, updated, surface };
136
+ return { from, to: latest, updated, surface, crossed };
110
137
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@looop-games/cli",
3
- "version": "0.1.8",
3
+ "version": "0.1.10",
4
4
  "description": "Looop game development CLI — dev server, login, and publishing for standalone Looop games.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -8,9 +8,9 @@
8
8
  "looop": "bin/looop.mjs"
9
9
  },
10
10
  "files": [
11
+ "CHANGELOG.md",
11
12
  "bin",
12
13
  "lib",
13
- "template",
14
14
  "!lib/**/*.test.mjs"
15
15
  ],
16
16
  "engines": {
@@ -1,266 +0,0 @@
1
- ---
2
- name: build
3
- description: The Looop build loop — the one way game work happens in this repo. Use when the creator wants to make their game, add or change a feature, start something new, or continue where a previous session left off ("let's build", "keep going", "add X", "make it so Y"). Runs from a plan in notes/plans/ — continues the plan if one exists, creates one if not.
4
- ---
5
-
6
- # /build — the loop that builds this game
7
-
8
- You are building for a creator who is probably not a developer. They bring the
9
- vision and the judgment calls; you bring everything else. This skill is the
10
- process — one repo, one game, one loop:
11
-
12
- > **plan → discuss → build in milestones of auto-verified steps → the creator
13
- > playtests → offer publish**
14
-
15
- Two words carry this loop, sized by the words themselves:
16
-
17
- - A **milestone** is a big, vertical increment the creator can actually play —
18
- the loop's unit of *their* attention. **The creator playtests at every
19
- milestone.**
20
- - A **step** is a small build increment inside a milestone. **Every step is
21
- auto-verified by you** — the creator is never asked to approve steps.
22
-
23
- ## When to collapse the ceremony
24
-
25
- A trivial direct request ("make the ball a bit faster") doesn't need the full
26
- loop: make the change, verify it, one line in the plan's log if a plan exists.
27
- The loop is for real increments — new mechanics, features, session-scale work.
28
- The tell: if the creator will want to *play* the result to judge it, it's a
29
- milestone and it runs through the loop.
30
-
31
- **Collapse never applies when there is no plan yet.** Starting something new
32
- runs through the §2 discussion — the plan records the creator's answers, so
33
- it cannot exist before they've answered.
34
-
35
- ## 1. Anchor on the plan
36
-
37
- Every build runs from a **plan** — a file in `notes/plans/`. A build without a
38
- plan doesn't exist; the plan is the loop's spine and the next session's recap.
39
-
40
- - **A plan exists** (look in `notes/plans/`) → CONTINUE it. Read it fully —
41
- vision, decisions, the milestone checklist, the log — and pick up exactly
42
- where it left off. Don't make the creator repeat themselves.
43
- - **No plan** → START one (create `notes/plans/<YYYY-MM-DD-HHMM>-<short-name>.md`
44
- — creation datetime first, always, so plans list in order and the newest is
45
- findable at a glance), through the discussion below. A `/todo` being
46
- promoted becomes a plan the same way.
47
-
48
- Plan shape (keep it lean — decisions and why, never pasted code):
49
-
50
- ```markdown
51
- ---
52
- status: in_progress # in_progress | done | paused | abandoned
53
- created: YYYY-MM-DD
54
- updated: YYYY-MM-DD
55
- ---
56
- # <What we're building>
57
-
58
- ## Vision
59
- What this wants to be at its best, in the creator's words.
60
-
61
- ## Decisions
62
- - **<choice>** — what was decided and why (one entry per real decision).
63
-
64
- ## Out of scope
65
- - **<cut>** — why it's out (one line per cut). As load-bearing as Decisions:
66
- every "we could also…" that got trimmed lands here, so it stays trimmed.
67
-
68
- ## Milestones
69
- ### Milestone 1 — <name> _(playtest: what the creator checks)_
70
- - [x] step
71
- - [ ] step
72
-
73
- ## Log
74
- - YYYY-MM-DD — what happened, in a few lines. Newest first.
75
- ```
76
-
77
- ## 2. Discuss before building
78
-
79
- Before code, get the shape right with the creator — and record it in the plan.
80
-
81
- **Building (§3) runs only from a plan whose decisions are settled — and a
82
- decision is settled by the creator answering, never by you choosing for
83
- them.** A new build request therefore starts as a conversation, one decision
84
- at a time:
85
-
86
- - **One decision per turn.** Pose it, resolve it fully, record it in the
87
- plan, then move to the next. Never a batch of questions — and never a
88
- finished plan (or code, or tests) as your opening move.
89
- - **Explain the problem before the options.** The creator can't choose
90
- between options they don't have the picture for. If they ask "what is X?",
91
- stop and explain X cleanly; the decision waits. If they say "I don't
92
- understand", don't restate the options louder — back up and re-explain the
93
- underlying problem from scratch, with concrete examples.
94
- - **2–3 options with honest pros/cons, and your lean stated** — make it easy
95
- to say "do that" or override you. Don't stack the deck, and don't fake
96
- confidence on a genuine 50/50: phrase the case for the other option clearly
97
- enough that the creator can pick it up if they disagree.
98
- - **Lock it in visibly** — say "Locking in: <choice>" and write it into the
99
- plan's Decisions as it lands, so the record never lags the conversation.
100
-
101
- **Every decision that shapes the game reaches the creator, framed by its
102
- consequences** — the way an engineer briefs a product manager. Not "authority
103
- vs. client prediction?" but "if X, joining mid-game is instant but scores can
104
- briefly disagree; with Y it's the reverse — which matters more here?" Give 2–3
105
- options with honest trade-offs and your lean. The technical detail stays
106
- available underneath for whoever pulls the thread.
107
-
108
- **Silently decide only what is consequence-free for the creator** — naming,
109
- file layout, code structure. The test is *"is the creator the right person to
110
- answer this?"*, not "is this technical?" A technical fork with a consequence
111
- they'd care about (feel, fairness, what can break) goes to them; one with no
112
- creator-visible consequence does not. Never hide a real fork to keep things
113
- simple — there is always a non-confusing way to ask it.
114
-
115
- **The shape decisions are ALWAYS the creator's** — never a default you carry in
116
- on their behalf, and never something you mention in passing as already settled:
117
-
118
- - **Camera and perspective** — top-down, side-on, isometric, first-person, 3D.
119
- There is no house camera; see `/engine`'s render paths.
120
- - **Art direction and look** — the Looop iso kit is *available*, not mandatory.
121
- - **The core verb** — what the player actually does, moment to moment.
122
- - **How conflict works** — combat, avoidance, puzzles, none of the above.
123
- - **Single-player vs. co-op vs. competitive** feel (the *plumbing* is always
124
- multiplayer-first; what the game is *about* is theirs).
125
-
126
- **NEVER invent a platform constraint.** Do not tell the creator "the engine
127
- only does X", "Looop doesn't support Y", or "that would take months" unless you
128
- have just checked and can point at what says so. A Looop game is a web page;
129
- the library is a bag of conveniences, not a fence (`/engine` — "The library is
130
- NOT the limit"). This failure is worse than a silent default: a creator can
131
- argue with "that's a lot of work", but they cannot argue with "the platform
132
- can't", so a fabricated limit kills their idea and looks like physics while
133
- doing it. If a thing is genuinely unbuilt, that is a **cost to price honestly**
134
- and hand them — never a "no" you issue on Looop's behalf.
135
-
136
- Watch for this specifically when scope pressure and a gap in the library point
137
- the same way: **"default to the smallest build" is never a licence to narrow
138
- the creator's vision** — that's the scope-narrowing this skill forbids two
139
- paragraphs down, wearing a technical disguise.
140
-
141
- **Default to the smallest build that meets the creator's ask — never inflate
142
- scope.** Every "we could also…" and every richer-than-asked option is scope
143
- YOU are injecting; the creator can't push back on over-building they didn't
144
- ask for. Surface extras as explicitly optional, record what was ruled out in
145
- the plan (an "Out of scope" line per cut), and when a discussion has stacked
146
- several decisions, recap the accumulated size so the creator can trim.
147
-
148
- Then cut the work into **milestones**: each one vertical, end-to-end, playable
149
- on its own. The FIRST milestone is the thinnest playable thing that proves the
150
- riskiest idea — if the core bet is wrong, the creator learns it after one
151
- milestone, not after the whole build. Write the milestones into the plan, each
152
- with its `_(playtest: …)_` note.
153
-
154
- ## 3. Build a milestone
155
-
156
- Run the steps **autonomously — no approval gates between steps**, just brief
157
- progress notes:
158
-
159
- 1. Consult what's already known before writing new systems: `handbook/`
160
- (this game's locked truths), the engine practices
161
- (`node_modules/@looop-games/engine/shared/practices/`), and `/engine` for
162
- components that already exist — don't reinvent a library.
163
- 2. Where a behaviour has a real contract, write the failing test/smoke first,
164
- then the code.
165
- 3. **After every step, verify it yourself — run `/qa` on what the step
166
- changed.** The steps themselves live in the engine's master QA doc
167
- (`node_modules/@looop-games/engine/shared/practices/qa.md`); `/qa` reads
168
- and runs them — **including the review rows: fresh sub-agent reviewers
169
- (code-quality + test-thoroughness) on the step's diff, findings resolved
170
- red→green before the step counts as done.** Every automated step runs at
171
- step cadence; only the playtest is per-milestone. You are the only tester
172
- inside a milestone — act like it.
173
- 4. **If a fix doesn't land on the first re-test, diagnose — don't
174
- second-guess.** Revert it, add instrumentation, find the actual cause;
175
- never ship a second guess stacked on the first.
176
- 5. **A real fork discovered mid-step goes to the creator**, framed by its
177
- consequences like every other game-shaping decision — never silently
178
- resolved just because the build is rolling.
179
- 6. **Never narrow scope silently.** Build the full milestone that was agreed;
180
- if a constraint forces something smaller, surface it at the gate — don't
181
- quietly ship the lesser version.
182
- 7. Tick the step off in the plan as it lands.
183
-
184
- ## 3½. Close the milestone — before the creator ever sees it
185
-
186
- Every step already passed its own `/qa` — including the per-step review
187
- sub-agents. The milestone close is the whole-greater-than-parts check before
188
- the ONE manual gate: run the full **`npx looop test`** suite (everything, not
189
- just what the last step touched), re-drive the milestone's headline behaviour
190
- end-to-end yourself, and for anything LLM-authored/generative run the
191
- **verdict-mix** row (judged scenarios, never a green check). Anything found
192
- here is fixed **red→green** — the failing test first, then the fix. Only then
193
- hand back.
194
-
195
- ## 4. The playtest gate
196
-
197
- When the milestone's steps are done and verified, hand it to the creator —
198
- this is the one place the loop stops for a human:
199
-
200
- - **The game is already RUNNING when you hand back — you run the server,
201
- never the creator.** If the dev stack isn't up, start it yourself
202
- (`npx looop dev`, backgrounded) and confirm the game URL answers before
203
- handing over; if one is already running, reuse it. The creator gets a
204
- **link to click** — `http://localhost:8000/games/<name>/index.html` (plus
205
- the phone/LAN URL when touch is part of the playtest) — never a command
206
- to paste. Asking them to run a server is asking them to learn infra.
207
- - **A minimal checklist of genuinely human-judgment items** — feel, look,
208
- "does this play the way you imagined". Never hand them a check you could
209
- have run yourself; you already ran those, report the results instead.
210
-
211
- Outcomes:
212
-
213
- - **It lands** → save it (a commit — `milestone: <name>`), check it off in
214
- the plan, update the log, move on. The saves at accepted milestones are the
215
- game's restore points.
216
- - **Close, needs iteration** → adjust within the milestone and hand back.
217
- - **Wrong direction** → offer the revert plainly, no sunk-cost defence:
218
- back to the last save (`git reset --hard` — nothing was saved mid-milestone,
219
- so that's the last accepted state).
220
- - **The playtest caught a defect you missed** → that's a hole in the
221
- verification, not just a bug. Fix it, then run `/handbook` so this
222
- class of defect gets an automated check and never reaches a playtest again.
223
-
224
- ## 5. Offer publish — never publish on your own
225
-
226
- After a milestone lands, offer it: `npx looop publish` puts the game live at
227
- `play.looop.games/g/<name>`. Publishing is **always the creator's explicit
228
- call** — `/build` never runs it unprompted. For a variant the creator wants to
229
- compare against the live game, `npx looop publish --slug <alt>` publishes an
230
- isolated A/B copy (own URL, own room) without touching the real one.
231
-
232
- ## Parallel lanes (advanced)
233
-
234
- A creator can run several `/build` experiments on one game at once. A lane is
235
- just this loop in a git worktree:
236
-
237
- ```bash
238
- # in the main checkout. git worktree needs the repo to have at least one
239
- # commit (on a never-saved repo it silently creates an EMPTY orphan lane) —
240
- # this saves ONLY in that case, and is a no-op otherwise:
241
- git rev-parse HEAD >/dev/null 2>&1 || { git add -A && git commit -m "save: initial"; }
242
-
243
- git worktree add ../<name>-<lane> # one folder per experiment
244
- cd ../<name>-<lane> && npm install # node_modules is gitignored — without
245
- # this, npx falls through to a WRONG
246
- # public 'looop' package and crashes
247
- # with a misleading error
248
- npx looop dev --port 8010 # DISTINCT --port per lane (8010, 8020, …)
249
- ```
250
-
251
- - **The lane serves `/games/<worktree-folder-name>/…`** — the folder name, not
252
- the original game slug. Use the URL the dev banner prints. The folder name
253
- also keys the lane's multiplayer room.
254
- - Every lane needs its own `--port`: the port shifts the whole stack together
255
- — game, multiplayer, services — so lanes are fully isolated (distinct
256
- server processes per lane; `looop test` inside one lane picks its own free
257
- ports and doesn't disturb the others).
258
- - Each lane keeps its own plan progress; save/playtest semantics are
259
- unchanged inside a lane.
260
- - Compare lanes live with `publish --slug <lane>` variants.
261
- - Land the winner: save it in the lane (`git add -A && git commit`), then from
262
- the main checkout `git merge <lane-branch>`, then
263
- `git worktree remove ../<name>-<lane>` and delete the lane branch.
264
- - **If the merge conflicts, stop — never auto-resolve.** Show the creator
265
- what collided (in game terms: "both lanes changed how jumping feels") and
266
- resolve it with them.
@@ -1,100 +0,0 @@
1
- ---
2
- name: engine
3
- description: Discover what the Looop engine already provides before building something from scratch — its component library, craft docs, and how to customize engine behaviour. Read the index rather than assuming what exists. Use when the creator asks "can it do X?", when you're about to write a system a game engine would normally provide, or when tuning game feel.
4
- ---
5
-
6
- # /engine — what Looop already gives you
7
-
8
- The engine is installed at `node_modules/@looop-games/engine` (downloaded by
9
- `looop dev`, pinned in `package.json`'s `looop.engine`). Before writing any
10
- system from scratch — movement, audio, UI, chat, NPCs, scoring — check whether
11
- the engine already has it. Reinventing a library is the most common way a game
12
- gets worse.
13
-
14
- **But the library is a floor, not a ceiling — read the next section before you
15
- ever tell the creator something isn't possible.**
16
-
17
- ## The library is NOT the limit of what the game can be
18
-
19
- A Looop game is **a web page**. Anything the browser can do, the game can do.
20
- The engine saves you work; it does not bound the game. The catalog is what
21
- Looop has *already built for you* — never mistake it for the list of things a
22
- Looop game is allowed to be.
23
-
24
- So there are only ever two answers to "can Looop do X?":
25
-
26
- 1. **The library has it** → use it (don't reinvent it).
27
- 2. **The library doesn't** → **then you build it, in the game folder.** That is
28
- the normal, expected path — it is how the library got its entries in the
29
- first place. Price it honestly and let the creator decide.
30
-
31
- **Never say "the engine doesn't support that" as if it settled the question.**
32
- It is the most damaging sentence you can say to a creator: it retires their
33
- idea without their consent, and it is almost always false. If you catch
34
- yourself about to say it — stop, come back here, and check. What you *may* say
35
- is an honest **cost**: "nothing in the kit does this, so we'd build it; here's
36
- roughly what that means." Price it from what actually exists, never from a
37
- worst case you imagined.
38
-
39
- ## Render paths (the camera is the creator's decision, not yours)
40
-
41
- There is no house camera. Pick with the creator, framed by consequences:
42
-
43
- | path | what it is |
44
- | --- | --- |
45
- | **plain 2D canvas** | `getContext('2d')` — what the scaffold ships with. Top-down, side-on, whatever you draw. Lightest. |
46
- | **iso 2D** (`shared/ui/iso` + `iso-style-looop`) | Isometric 3/4 canvas drawing with the Looop world kit. The best-supported look. Depth is a painter-algorithm sort, so large occluders can glitch. |
47
- | **iso-3d** (`shared/ui/iso-3d`) | Real WebGL/three.js geometry with per-pixel depth-buffer occlusion. Same iso look, no depth-sort bugs. |
48
- | **anything else** | First-person, over-the-shoulder, free 3D camera, 2.5D — all buildable on three.js in the game folder. Less kit support, not less possible. |
49
-
50
- ## Discover
51
-
52
- 1. **Start at the index:**
53
- `node_modules/@looop-games/engine/shared/ui/INDEX.md` — the component
54
- library at a glance, one line per component.
55
- 2. **Read the component's README before using it** —
56
- `node_modules/@looop-games/engine/shared/ui/<component>/README.md`. Each
57
- documents its import, API, and the practices around it.
58
- 3. **Import by absolute path**, e.g.
59
- `import { createRoom } from '/shared/ui/room/client.js'`. In dev and in
60
- production those resolve to the installed engine version — never to files
61
- you can edit.
62
-
63
- ## The craft docs
64
-
65
- `node_modules/@looop-games/engine/shared/practices/` is the engine's
66
- accumulated craft knowledge and applies to every game:
67
-
68
- - `feel.md` — what makes a game feel good; read before tuning anything.
69
- - `architecture.md` — how Looop games are structured.
70
- - `multiplayer.md` — authority, prediction, and the rules of shared state.
71
- - `qa.md` — the master verification list (`/qa` runs it).
72
-
73
- **Game feel specifically:** the `tweaks` library
74
- (`shared/ui/tweaks/` — see its README) is the engine's tuning surface; use it
75
- with `feel.md` rather than scattering magic numbers.
76
-
77
- ## Customize — overrides, never edits
78
-
79
- The engine is read-only; never edit `node_modules`. To change how an engine
80
- file behaves for THIS game:
81
-
82
- 1. Copy it to `overrides/shared/<same path as under shared/>`.
83
- 2. Edit the copy. Dev and publish both serve your override instead of the
84
- official module — game imports stay `/shared/...`, never rewritten.
85
-
86
- An override is a fork: that file stops receiving engine updates until you
87
- re-port it. Prefer game-local code when it can live in the game; override only
88
- when the behaviour truly must change inside the engine module.
89
-
90
- ## When the engine falls short
91
-
92
- - The engine has the component but it's **broken or missing something every
93
- game would want** → that's platform feedback: `/feedback`.
94
- - The need is **specific to this game** → build it game-local (or override),
95
- and note in `handbook/design.md` if it's a pillar.
96
- - The engine has **nothing at all** for something many games would want (a
97
- whole render path, a genre's core system) → do **both**: build it game-local
98
- so the creator is never blocked waiting on Looop, *and* `/feedback` it so
99
- Looop can make it first-class. Never let a gap in the library become a "no"
100
- to the creator.
@@ -1,125 +0,0 @@
1
- ---
2
- name: feedback
3
- description: File feedback to the Looop team when something in Looop ITSELF is broken or missing — the engine, a shared component, the looop CLI, login, publishing, the platform. Use the moment you or the creator think "this looks like a Looop bug, not our game" — AND, just as importantly, whenever you discover your own game breaking a Looop rule, because Looop's own instructions may be what put it there. Offer to file it right away; don't wait to be asked.
4
- ---
5
-
6
- # /feedback — tell Looop when Looop is the problem
7
-
8
- You are often the only witness when the platform misbehaves. The reflex this
9
- skill exists for: the moment something smells like a **Looop** defect — an
10
- engine component behaving wrong, a `looop` command failing strangely, docs
11
- that lied, a missing capability every game would want — **offer to file it**:
12
- "that looks like a Looop bug, want me to send it to the Looop team?"
13
-
14
- This game's own bugs are NOT feedback — they're `/todo`s or just fixes.
15
-
16
- ## The defect you will not notice
17
-
18
- There is one class of Looop bug the reflex above is blind to, and it is the most
19
- valuable class there is: **a defect Looop's own guidance caused.**
20
-
21
- It looks like this. You discover your game violating a Looop rule — it's routing
22
- state the wrong way, using an API it shouldn't. The symptom is in *your* code, so
23
- the conclusion writes itself: *"our bug, not the engine's."* You fix your game and
24
- move on, and Looop never hears about it.
25
-
26
- That inference is locally correct and globally wrong. **Looop's instructions are
27
- not a fixed point — they are a suspect.** They contradict each other sometimes.
28
- The mandatory ones (this repo's `AGENTS.md`, injected into every session) can be
29
- wrong while an opt-in practices doc is right, and you will have followed the
30
- mandatory one without ever noticing there was a choice.
31
-
32
- So, the rule:
33
-
34
- > **When you find your game violating a Looop rule, work out what led you there
35
- > BEFORE you fix it.**
36
-
37
- Retrace it honestly. Did a Looop-authored source — `AGENTS.md`, a
38
- `shared/practices/` doc, a library README, a skill — point you this way? If yes,
39
- **that is a Looop defect and it gets filed**, even though your game is also wrong.
40
- Both are true at the same time; fix your game *and* file the report. If you'd have
41
- made the same mistake with no guidance at all, it's just your bug — fix it and
42
- move on.
43
-
44
- ## What to file
45
-
46
- Write the report to `notes/feedback/<YYYY-MM-DD-HHMM>-<short-slug>.md`
47
- (creation datetime first, like everything under `notes/`). **You are the author,
48
- not the creator — so be maximal.** The Looop team gets nothing but this file;
49
- they can't ask you follow-ups, re-run your session, or see your screen. Every
50
- detail you leave out is a detail they'll have to guess. Include:
51
-
52
- ```markdown
53
- ---
54
- created: YYYY-MM-DD
55
- engine: <the looop.engine pin from package.json>
56
- cli: <@looop-games/cli version from package.json devDependencies>
57
- attachments:
58
- - game.js
59
- - src/net.js
60
- ---
61
- # <One line: what's wrong>
62
-
63
- **What happened:** …
64
- **What was expected:** …
65
-
66
- ## Environment
67
- OS, node version, and anything unusual about the setup (worktree lane,
68
- custom port, offline, …).
69
-
70
- ## Reproduction
71
- The smallest steps/snippet that shows it. Exact commands **with their full
72
- output pasted verbatim** — never summarize an error message.
73
-
74
- ## What led us here (if a Looop source did)
75
- The file and line that pointed you wrong, quoted, and the doc that contradicts
76
- it. This is the section that gets the guidance itself fixed.
77
-
78
- ## Transcript
79
- The conversation that surfaced this, quoted verbatim — from the creator's
80
- request that first hit the problem through your diagnosis: what they asked,
81
- what you ran, what came back, what you ruled out. This is usually the most
82
- valuable section; a reader should be able to replay your session from it.
83
-
84
- ## Workaround used (if any)
85
- e.g. an overrides/shared/ copy, so the team knows what to un-fork once fixed.
86
- ```
87
-
88
- Trim game-specific noise, never evidence: cut what's irrelevant to the
89
- defect, keep everything that shows it. (The intake caps a report at 256 KiB —
90
- if the transcript pushes past that, cut it down to the relevant exchange.)
91
-
92
- ## Attach the files you're talking about
93
-
94
- A report that cites `game.js:56` is only as good as the reader's ability to see
95
- line 56. **List the files your diagnosis rests on in the `attachments:`
96
- frontmatter** — they ship with the report, and the team reads them beside it.
97
-
98
- This applies to **any** report, whatever its reason: a bug, a missing capability,
99
- a rule that led you wrong, a module you had to fork. Whatever your evidence is,
100
- attach it.
101
-
102
- - **You pick the files** — you wrote the diagnosis, so you know what it rests on.
103
- - Paths are **relative to the game folder** and must stay inside it. Anything
104
- pointing outside is refused outright.
105
- - **Text only** (source, logs, config) — up to 20 files, 256 KiB each, 1 MiB total.
106
- - Attach what the report *argues from*: the file with the bug, the module you
107
- worked around, the config that reproduces it. Not the whole game.
108
-
109
- ## Send it
110
-
111
- 1. Run **`npx looop feedback`** — it delivers every unsent report under
112
- `notes/feedback/` to the Looop team (login required; it's the same account
113
- as publishing), attachments included, and stamps each delivered file with
114
- `sent:` + `id:` in its frontmatter so it never ships twice.
115
- 2. If the send fails (offline, not logged in, a bad attachment path), the file
116
- stays unstamped — fix what it says and run `npx looop feedback` again; it
117
- retries everything unsent.
118
-
119
- ## Why bother
120
-
121
- An override that patches an engine bug is a fork that stops receiving updates;
122
- feedback is how the fix lands upstream so the fork can be deleted. A missing
123
- capability filed from a real game is exactly how the engine decides what to build
124
- next. And a rule that led you wrong will lead **every** creator wrong, in every
125
- game, until somebody says so.