@yagejs-tools/feedback 0.0.0-stage → 0.0.0

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.
Files changed (2) hide show
  1. package/README.md +318 -2
  2. package/package.json +84 -4
package/README.md CHANGED
@@ -1,3 +1,319 @@
1
- # Temporary Holding Version
1
+ # @yagejs-tools/feedback
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Runtime feedback for [YAGE](https://yage.dev) games. Freeze the running game,
4
+ comment on the whole view, on entities, or on an area, and read each comment
5
+ back from a CLI together with its screenshot and inspector snapshot. Made for
6
+ handing observations to a coding agent.
7
+
8
+ `@yagejs-tools` scope, independently versioned — an engine release never forces
9
+ a bump here, and vice versa.
10
+
11
+ ## Install
12
+
13
+ ```bash
14
+ npm install -D @yagejs-tools/feedback
15
+ ```
16
+
17
+ Peers: `@yagejs/core`, `@yagejs/renderer`, `@yagejs/debug`, and `vite`, all of
18
+ which a YAGE game already has. `@yagejs/input` is an optional peer; when the
19
+ game installs `InputPlugin`, feedback clears held input on entry and exit.
20
+ Engine peers are `>=0.11.0 <0.12.0`. The 0.10 packages do not provide the
21
+ inspector clock leases that comment mode uses.
22
+
23
+ The package is a development tool. The Vite plugin serves feedback only from
24
+ the dev server, and a production build contains no feedback routes or
25
+ discovery metadata. Keep `FeedbackPlugin` behind the game's debug flag so a
26
+ release build mounts no UI.
27
+
28
+ ## Usage
29
+
30
+ Add the dev-server plugin to `vite.config.ts` (Vite 8):
31
+
32
+ ```ts
33
+ import { defineConfig } from "vite";
34
+ import { yageFeedback } from "@yagejs-tools/feedback/vite";
35
+
36
+ export default defineConfig({ plugins: [yageFeedback()] });
37
+ ```
38
+
39
+ Install the runtime plugin after `RendererPlugin` and `DebugPlugin`:
40
+
41
+ ```ts
42
+ /// <reference types="vite/client" />
43
+ import { Engine } from "@yagejs/core";
44
+ import { FeedbackPlugin } from "@yagejs-tools/feedback";
45
+
46
+ const debug = import.meta.env.DEV;
47
+ const engine = new Engine({ debug });
48
+ // engine.use(new RendererPlugin(...)); engine.use(new DebugPlugin());
49
+ engine.use(
50
+ new FeedbackPlugin({
51
+ enabled: debug,
52
+ context: () => ({ host: "runtime", level: "forest-1" }),
53
+ }),
54
+ );
55
+ ```
56
+
57
+ Start Vite. Feedback runs on the same port, and the browser plugin discovers
58
+ its API from a `<meta>` tag the Vite plugin injects. An explicit `server`
59
+ option overrides discovery.
60
+
61
+ Open **Feedback gallery** from the game controls, or visit
62
+ `/__yage/feedback/` on the game's origin. The API is at
63
+ `/__yage/feedback/api/`. Both paths include Vite's configured `base` and
64
+ follow its actual port if the preferred port is occupied. Use that full API
65
+ URL in CLI `--server` arguments, including the path.
66
+
67
+ `yageFeedback({ directory: ".yage/feedback", basePath: "/__yage/feedback/" })`
68
+ configures storage relative to Vite's root and routes relative to Vite's base.
69
+ Add `.yage/feedback/` to your project's `.gitignore` if captures should stay local.
70
+ Each running server must own a different storage directory. A second owner
71
+ fails with a lock error; it never creates a different directory silently.
72
+ Restarting Vite preserves comments and releases/reacquires the lock.
73
+
74
+ The integration requires local HTTP. Feedback routes reject nonlocal clients
75
+ even when the game dev server is exposed on the network. Closing Vite stops
76
+ feedback; use the standalone server with the same directory to review saved
77
+ comments afterward.
78
+
79
+ ## Leave a comment
80
+
81
+ 1. Open **Leave feedback** (F8). The game freezes and a captured image appears.
82
+ 2. Choose **Whole view**, **Entities**, or **Area**. Click an entity or use
83
+ the searchable entity dropdown; hold Shift to add another on the image. In Area mode, drag a rectangle.
84
+ 3. Write a comment and save. Add more comments or return to the view.
85
+ 4. Resume and capture another frame to collect more observations in the same
86
+ session.
87
+
88
+ The entity dropdown filters by name, ID, or scene and displays 50 results per
89
+ page. Filtering preserves selected entities; their summary stays visible below
90
+ the dropdown.
91
+
92
+ Screenshots hide the debug HUD during capture and immediately restore its
93
+ previous visibility, including when capture fails.
94
+
95
+ The server saves comments, PNGs, and inspector snapshots in the chosen
96
+ directory. Use one server per directory. Failed uploads keep their draft for
97
+ retry; **Discard unsaved draft** lets you leave without retrying. Discarding
98
+ the local draft does not delete anything already stored on the server.
99
+
100
+ ## Review and hand off comments
101
+
102
+ The gallery defaults to **Pending** (open and ingested). Filter by status,
103
+ search text or entity names, and open **View evidence** for the original image,
104
+ target outlines, inspector snapshot, host context, and status history.
105
+ Cards show 24 comments per page. **Refresh** reloads saved comments and status.
106
+
107
+ Select comments, then choose **Copy for Codex** or **Copy for Claude**.
108
+ The instruction includes the skill invocation, project directory, actual API
109
+ URL, and explicit comment IDs. Paste it into an agent session opened in that
110
+ project. Install the `yage-feedback` skill separately in that agent first.
111
+ If clipboard access fails, a dialog offers selectable text. Reading, selecting,
112
+ and copying do not ingest comments. Changing the filter clears selection;
113
+ changing pages retains it.
114
+
115
+ ## Read the evidence
116
+
117
+ ```sh
118
+ npx yage-feedback list --status open --server http://localhost:5173/__yage/feedback/api/
119
+ npx yage-feedback show COMMENT_ID --server http://localhost:5173/__yage/feedback/api/
120
+ ```
121
+
122
+ Output is JSON. `show` includes the original comment, target, capture
123
+ metadata, full inspector snapshot, and absolute screenshot path. The browser
124
+ can close before the CLI reads the data. Restart the server with the same
125
+ directory to read earlier comments. Use `--server URL` to read another local
126
+ endpoint, including its base path.
127
+
128
+ ## Track agent work
129
+
130
+ Reading leaves status unchanged. Use `ingest` once an agent has read the
131
+ comment and evidence, `address` after applying changes, and `resolve` after
132
+ verification. `reopen` returns any non-open comment to `open`.
133
+
134
+ ```sh
135
+ npx yage-feedback ingest COMMENT_ID \
136
+ --server http://localhost:5173/__yage/feedback/api/ \
137
+ --revision 0 --by codex/session-name \
138
+ --request-id 7582a71c-ffab-4b16-b7d3-145b34fafac5
139
+ ```
140
+
141
+ Use `comment.revision` from `show`. Every new action needs a new request UUID;
142
+ retry an uncertain action with the same UUID and unchanged arguments. A retry
143
+ never adds a second history entry. A stale revision fails so another agent's
144
+ work cannot be overwritten. `--note TEXT` records an optional explanation.
145
+ All transitions retain the original comment, target, screenshot, and snapshot.
146
+ `list --status STATUS` filters open, ingested, addressed, or resolved comments.
147
+
148
+ The server records actor, timestamp, status, revision, and request ID in
149
+ `comment.history`. Comments saved before workflow tracking existed read as
150
+ revision 0 without rewriting their files. Retrying an upload preserves
151
+ existing workflow state.
152
+
153
+ ## Standalone server
154
+
155
+ Without Vite, or to review a directory after the game closed:
156
+
157
+ ```sh
158
+ npx yage-feedback serve --dir .yage/feedback
159
+ ```
160
+
161
+ The standalone server binds `127.0.0.1:5212` and prints its API URL. Set the
162
+ runtime plugin's `server` option to that URL when the game runs without the
163
+ Vite plugin. `--port 0` asks the OS for an available port. `--base-path
164
+ /review/api/` changes its API prefix; its gallery is under
165
+ `/review/api/gallery/`. `--project PATH` sets the project directory used in
166
+ copied instructions; it defaults to the working directory. Cross-origin
167
+ browser requests are allowed from `http://localhost:5173` and
168
+ `http://127.0.0.1:5173`, Vite's default origins. Supply repeatable `--origin
169
+ URL` arguments for another origin; supplying any replaces the defaults. A
170
+ directory lock prevents simultaneous servers. Graceful shutdown releases it.
171
+ After a crash, check the PID recorded in `.server.lock` before removing a
172
+ stale lock.
173
+
174
+ ## Plugin options
175
+
176
+ ```ts yage-group="options" yage-context="engine"
177
+ /// <reference types="vite/client" />
178
+ import { FeedbackPlugin } from "@yagejs-tools/feedback";
179
+
180
+ const debug = import.meta.env.DEV;
181
+ engine.use(
182
+ new FeedbackPlugin({
183
+ enabled: debug, // Same flag passed to new Engine({ debug }).
184
+ server: "http://127.0.0.1:5212",
185
+ context: () => ({ host: "runtime", experiment: "formation" }),
186
+ }),
187
+ );
188
+ ```
189
+
190
+ Set `enabled` to the application’s debug flag. Disabled feedback mounts no UI
191
+ or keyboard listeners. The compact controls become fully visible on hover or
192
+ focus. F8 opens feedback and F9 toggles freeze; `shortcuts: false` disables
193
+ those keys. Shortcuts ignore editable fields and open dialogs.
194
+
195
+ Override keyboard bindings in the runtime plugin:
196
+
197
+ ```ts yage-group="options" yage-context="engine"
198
+ new FeedbackPlugin({
199
+ enabled: debug,
200
+ shortcuts: {
201
+ feedback: { code: "KeyF", shift: true },
202
+ freeze: { code: "KeyP", shift: true },
203
+ stepFrame: { code: "Period" },
204
+ stepTenFrames: { code: "Period", shift: true },
205
+ },
206
+ });
207
+ ```
208
+
209
+ Bindings use physical `KeyboardEvent.code` values, such as `KeyF`, `Space`,
210
+ or `Backquote`. Optional `ctrl`, `alt`, `shift`, and `meta` modifiers must
211
+ match exactly; omitted modifiers are false. Omitted actions keep F8/F9 and F10/Shift+F10.
212
+ Set an action to `false` to disable only its shortcut, or use `shortcuts: false`
213
+ to disable all feedback shortcuts. Buttons remain available and tooltips show each
214
+ configured binding. Duplicate bindings are rejected. Choose combinations that
215
+ your browser and OS do not reserve. Configured step keys stay reserved even
216
+ when stepping is unavailable, except while typing or in a dialog.
217
+
218
+ Once the game is frozen, **+1 frame** and **+10 frames** advance it and leave
219
+ it frozen. Their default keys are F10 and Shift+F10. Stepping uses the
220
+ inspector's configured frame delta, clears held input, and is unavailable
221
+ while a comment dialog is open or another tool owns the clock. Return to the
222
+ game before stepping; saved captures and pending comment evidence stay unchanged.
223
+
224
+ Feedback uses the existing inspector time lease and never advances simulation
225
+ during capture. Context must be finite, acyclic JSON and is copied with the
226
+ capture. The same plugin can be included in a `@yagejs-tools/lab` harness's
227
+ `plugins` array, as shown in [the demo harness](demo/lab/harness.ts).
228
+
229
+ ## Limits
230
+
231
+ - Pause lab playback before opening feedback: lab playback owns the clock.
232
+ - Selection uses rendered bounding boxes. Use the entity dropdown for overlapping
233
+ objects. Masks, displaced pixels, and exact paint order are not resolved.
234
+ - Regions use screenshot pixels. The inspector retains entity world state
235
+ and camera information; feedback does not infer a world region.
236
+ - Capture covers the canvas, not surrounding HTML. Chrome/WebGL was verified.
237
+ - Freezing engine time does not stop external timers, network callbacks, or
238
+ audio. Comments display an immutable captured image.
239
+ - The tool collects evidence and tracks its status; it does not apply fixes or
240
+ run an agent.
241
+
242
+ Uploads can be cancelled with **Cancel save**, **Return to view**, or Escape.
243
+ Requests time out after 30 seconds. A pending draft keeps its original capture,
244
+ text, target, and request identity when you return to the game; reopen feedback
245
+ to retry it. The draft lasts until saved, discarded, or the plugin is destroyed
246
+ (including a page reload). Cancellation cannot undo a completed server write.
247
+
248
+ The server validates PNG checksums and decodes the pixels before saving.
249
+ Screenshots must be non-interlaced and contain at most 16,777,216 pixels. The
250
+ server accepts only loopback Host headers, including CLI requests without an
251
+ Origin header. Object-property order does not affect upload retry identity.
252
+
253
+ ## Contributing
254
+
255
+ Everything below runs inside the YAGE monorepo checkout.
256
+
257
+ Install dependencies and build:
258
+
259
+ ```sh
260
+ npm install
261
+ npx turbo run build --filter=@yagejs-tools/feedback --filter=@yagejs-tools/lab
262
+ ```
263
+
264
+ Run the demo game; its Vite plugin starts feedback automatically:
265
+
266
+ ```sh
267
+ npm run demo --workspace=@yagejs-tools/feedback
268
+ ```
269
+
270
+ Open [the game](http://127.0.0.1:5213). Its data is in
271
+ `packages/tools/feedback/demo/.yage/feedback`.
272
+
273
+ The lab harness uses the standalone server. Start these in separate terminals:
274
+
275
+ ```sh
276
+ node packages/tools/feedback/dist/cli.js serve --dir output/playwright/feedback-data --origin http://127.0.0.1:5214 --origin http://localhost:5214
277
+ npm run lab --workspace=@yagejs-tools/feedback
278
+ ```
279
+
280
+ Open [the lab](http://127.0.0.1:5214). In the lab, press **Pause** before
281
+ **Leave feedback**.
282
+
283
+ The demo also accepts `?shortcuts=custom` to try Shift+K for feedback, Shift+P
284
+ for freeze, and Period/Shift+Period for stepping.
285
+
286
+ Verify:
287
+
288
+ ```sh
289
+ npx turbo run typecheck lint test build --filter=@yagejs-tools/feedback
290
+ ```
291
+
292
+ For CLI lifecycle verification after saving a browser comment:
293
+
294
+ ```sh
295
+ node packages/tools/feedback/checks/cli.mjs http://127.0.0.1:5213/__yage/feedback/api/
296
+ ```
297
+
298
+ This creates one acceptance comment using existing captured evidence and checks
299
+ all transitions, exact retries, stale rejection, and read-only source access.
300
+
301
+ For repeatable browser checks, start the servers above and use Playwright CLI:
302
+
303
+ ```sh
304
+ playwright-cli open http://127.0.0.1:5213
305
+ playwright-cli snapshot
306
+ playwright-cli run-code --filename packages/tools/feedback/checks/runtime.js
307
+ playwright-cli run-code --filename packages/tools/feedback/checks/controls.js
308
+ playwright-cli run-code --filename packages/tools/feedback/checks/shortcuts.js
309
+ playwright-cli goto http://127.0.0.1:5213/__yage/feedback/
310
+ playwright-cli run-code --filename packages/tools/feedback/checks/gallery.js
311
+ playwright-cli goto "http://127.0.0.1:5213/?debug=false"
312
+ playwright-cli run-code --filename packages/tools/feedback/checks/disabled.js
313
+ playwright-cli goto http://127.0.0.1:5214
314
+ playwright-cli snapshot
315
+ playwright-cli run-code --filename packages/tools/feedback/checks/lab.js
316
+ ```
317
+
318
+ The scripts create real comments and save screenshots under
319
+ `output/playwright/`.
package/package.json CHANGED
@@ -1,6 +1,86 @@
1
1
  {
2
2
  "name": "@yagejs-tools/feedback",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.0.0",
4
+ "description": "Runtime feedback for YAGE games — freeze the view, comment on entities or areas, and read the captures from a CLI",
5
+ "keywords": [
6
+ "yage",
7
+ "yage-tool",
8
+ "game-engine",
9
+ "2d",
10
+ "typescript",
11
+ "feedback",
12
+ "annotation",
13
+ "devtools"
14
+ ],
15
+ "license": "MIT",
16
+ "author": "Marco Lepore",
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "git+https://github.com/marco-lepore/yage.git",
20
+ "directory": "packages/tools/feedback"
21
+ },
22
+ "homepage": "https://yage.dev",
23
+ "type": "module",
24
+ "types": "./dist/index.d.ts",
25
+ "bin": {
26
+ "yage-feedback": "dist/cli.js"
27
+ },
28
+ "exports": {
29
+ ".": {
30
+ "types": "./dist/index.d.ts",
31
+ "import": "./dist/index.js"
32
+ },
33
+ "./server": {
34
+ "types": "./dist/server.d.ts",
35
+ "import": "./dist/server.js"
36
+ },
37
+ "./vite": {
38
+ "types": "./dist/vite.d.ts",
39
+ "import": "./dist/vite.js"
40
+ }
41
+ },
42
+ "files": [
43
+ "dist"
44
+ ],
45
+ "publishConfig": {
46
+ "access": "public"
47
+ },
48
+ "scripts": {
49
+ "build": "tsup",
50
+ "dev": "tsup --watch",
51
+ "typecheck": "tsc --noEmit && tsc -p demo/tsconfig.json --noEmit",
52
+ "lint": "eslint src/",
53
+ "test": "vitest run",
54
+ "clean": "rm -rf dist",
55
+ "demo": "vite demo --host 127.0.0.1 --port 5213 --strictPort",
56
+ "lab": "cd demo && yage-lab dev --port 5214 --no-open"
57
+ },
58
+ "dependencies": {
59
+ "pngjs": "^7.0.0"
60
+ },
61
+ "peerDependencies": {
62
+ "@yagejs/core": ">=0.11.0 <0.12.0",
63
+ "@yagejs/debug": ">=0.11.0 <0.12.0",
64
+ "@yagejs/input": ">=0.11.0 <0.12.0",
65
+ "@yagejs/renderer": ">=0.11.0 <0.12.0",
66
+ "vite": "^8.0.0"
67
+ },
68
+ "peerDependenciesMeta": {
69
+ "@yagejs/input": {
70
+ "optional": true
71
+ },
72
+ "vite": {
73
+ "optional": true
74
+ }
75
+ },
76
+ "devDependencies": {
77
+ "@types/node": "^22.0.0",
78
+ "@types/pngjs": "^6.0.5",
79
+ "@yagejs-tools/lab": "^0.2.0",
80
+ "@yagejs/core": ">=0.11.0",
81
+ "@yagejs/debug": ">=0.11.0",
82
+ "@yagejs/input": ">=0.11.0",
83
+ "@yagejs/renderer": ">=0.11.0",
84
+ "vite": "^8.0.0"
85
+ }
86
+ }