@dailephd/my-frontend-observer 0.8.1 → 0.9.1

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 (111) hide show
  1. package/CHANGELOG.md +74 -0
  2. package/README.md +109 -7
  3. package/dist/application/projectWorkflowService.d.ts +18 -1
  4. package/dist/application/projectWorkflowService.js +40 -2
  5. package/dist/application/projectWorkflowService.js.map +1 -1
  6. package/dist/application/visualAnnotationContractPromotionService.d.ts +41 -0
  7. package/dist/application/visualAnnotationContractPromotionService.js +143 -0
  8. package/dist/application/visualAnnotationContractPromotionService.js.map +1 -0
  9. package/dist/application/visualAnnotationPersistenceService.d.ts +34 -0
  10. package/dist/application/visualAnnotationPersistenceService.js +68 -0
  11. package/dist/application/visualAnnotationPersistenceService.js.map +1 -0
  12. package/dist/application/visualAnnotationReferenceMaterializationService.d.ts +53 -0
  13. package/dist/application/visualAnnotationReferenceMaterializationService.js +194 -0
  14. package/dist/application/visualAnnotationReferenceMaterializationService.js.map +1 -0
  15. package/dist/artifacts/visualAnnotationArtifactReader.d.ts +19 -0
  16. package/dist/artifacts/visualAnnotationArtifactReader.js +66 -0
  17. package/dist/artifacts/visualAnnotationArtifactReader.js.map +1 -0
  18. package/dist/artifacts/visualAnnotationArtifactWriter.d.ts +42 -0
  19. package/dist/artifacts/visualAnnotationArtifactWriter.js +85 -0
  20. package/dist/artifacts/visualAnnotationArtifactWriter.js.map +1 -0
  21. package/dist/cli.js +464 -454
  22. package/dist/cli.js.map +1 -1
  23. package/dist/domain/visualAnnotation.d.ts +217 -0
  24. package/dist/domain/visualAnnotation.js +584 -0
  25. package/dist/domain/visualAnnotation.js.map +1 -0
  26. package/dist/domain/visualAnnotationIdentity.d.ts +17 -0
  27. package/dist/domain/visualAnnotationIdentity.js +47 -0
  28. package/dist/domain/visualAnnotationIdentity.js.map +1 -0
  29. package/dist/index.d.ts +11 -0
  30. package/dist/index.js +6 -0
  31. package/dist/index.js.map +1 -1
  32. package/dist/projectWorkflow/projectPaths.d.ts +9 -0
  33. package/dist/projectWorkflow/projectPaths.js +21 -0
  34. package/dist/projectWorkflow/projectPaths.js.map +1 -1
  35. package/dist/viewer/assets/{index-CN_yb9Uf.css → index-BN41MI7m.css} +1 -1
  36. package/dist/viewer/assets/index-CkKXnlrI.js +9 -0
  37. package/dist/viewer/index.html +2 -2
  38. package/dist/viewer/sw.js +1 -1
  39. package/dist/viewerServer/annotationAuthoring.d.ts +64 -0
  40. package/dist/viewerServer/annotationAuthoring.js +230 -0
  41. package/dist/viewerServer/annotationAuthoring.js.map +1 -0
  42. package/dist/viewerServer/annotationContractPromotion.d.ts +51 -0
  43. package/dist/viewerServer/annotationContractPromotion.js +105 -0
  44. package/dist/viewerServer/annotationContractPromotion.js.map +1 -0
  45. package/dist/viewerServer/annotationReferenceMaterialization.d.ts +40 -0
  46. package/dist/viewerServer/annotationReferenceMaterialization.js +91 -0
  47. package/dist/viewerServer/annotationReferenceMaterialization.js.map +1 -0
  48. package/dist/viewerServer/authoringSecurity.d.ts +59 -0
  49. package/dist/viewerServer/authoringSecurity.js +112 -0
  50. package/dist/viewerServer/authoringSecurity.js.map +1 -0
  51. package/dist/viewerServer/evidence/annotationView.d.ts +28 -0
  52. package/dist/viewerServer/evidence/annotationView.js +43 -0
  53. package/dist/viewerServer/evidence/annotationView.js.map +1 -0
  54. package/dist/viewerServer/evidence/classify.d.ts +3 -1
  55. package/dist/viewerServer/evidence/classify.js +12 -0
  56. package/dist/viewerServer/evidence/classify.js.map +1 -1
  57. package/dist/viewerServer/evidence/discovery.d.ts +2 -0
  58. package/dist/viewerServer/evidence/discovery.js +6 -0
  59. package/dist/viewerServer/evidence/discovery.js.map +1 -1
  60. package/dist/viewerServer/evidence/handles.js +1 -0
  61. package/dist/viewerServer/evidence/handles.js.map +1 -1
  62. package/dist/viewerServer/evidence/index.d.ts +29 -0
  63. package/dist/viewerServer/evidence/index.js +43 -1
  64. package/dist/viewerServer/evidence/index.js.map +1 -1
  65. package/dist/viewerServer/evidence/mediaResolver.d.ts +1 -1
  66. package/dist/viewerServer/evidence/mediaResolver.js +28 -2
  67. package/dist/viewerServer/evidence/mediaResolver.js.map +1 -1
  68. package/dist/viewerServer/evidence/projection.d.ts +5 -1
  69. package/dist/viewerServer/evidence/projection.js +19 -0
  70. package/dist/viewerServer/evidence/projection.js.map +1 -1
  71. package/dist/viewerServer/httpServer.d.ts +13 -2
  72. package/dist/viewerServer/httpServer.js +278 -4
  73. package/dist/viewerServer/httpServer.js.map +1 -1
  74. package/dist/viewerServer/viewerService.d.ts +8 -0
  75. package/dist/viewerServer/viewerService.js +38 -2
  76. package/dist/viewerServer/viewerService.js.map +1 -1
  77. package/docs/ARCHITECTURE.md +108 -21
  78. package/docs/CI_CD.md +78 -1
  79. package/docs/COMMANDS.md +44 -4
  80. package/docs/CONTRACTS.md +78 -8
  81. package/docs/CURRENT_STATE.md +224 -35
  82. package/docs/DEVELOPMENT.md +38 -3
  83. package/docs/PROJECT_DESCRIPTION.md +4 -1
  84. package/docs/PROJECT_MILESTONES.md +32 -0
  85. package/docs/PROJECT_OVERVIEW.md +58 -17
  86. package/docs/QUICKSTART.md +52 -39
  87. package/docs/RELEASE.md +17 -11
  88. package/docs/ROADMAP.md +458 -66
  89. package/docs/SECURITY.md +71 -14
  90. package/docs/WORKFLOWS.md +151 -23
  91. package/docs/plans/v0.9-implementation-plan.md +1529 -0
  92. package/docs/plans/v0.9.1-implementation-plan.md +468 -0
  93. package/docs/reports/v0.9-architecture-retrieval.md +567 -0
  94. package/docs/reports/v0.9-batch1-visual-annotation-foundation.md +351 -0
  95. package/docs/reports/v0.9-batch2-viewer-annotation-authoring-boundary.md +438 -0
  96. package/docs/reports/v0.9-batch3-runtime-screenshot-annotation-authoring.md +412 -0
  97. package/docs/reports/v0.9-batch4-external-reference-annotation-authoring.md +452 -0
  98. package/docs/reports/v0.9-batch5-runtime-intent-contract-promotion.md +535 -0
  99. package/docs/reports/v0.9-batch6-reference-materialization.md +514 -0
  100. package/docs/reports/v0.9-batch7-integrated-acceptance.md +644 -0
  101. package/docs/reports/v0.9-demo-foundation.md +589 -0
  102. package/docs/reports/v0.9-final-pre-release-readiness.md +209 -0
  103. package/docs/reports/v0.9-final-readiness-corrections.md +530 -0
  104. package/docs/reports/v0.9-pre-release-readiness.md +170 -0
  105. package/docs/reports/v0.9-tutorial-end-to-end-acceptance.md +980 -0
  106. package/docs/reports/v0.9-tutorial-integration.md +731 -0
  107. package/docs/reports/v0.9.1-batch1-pwa-hard-gate-isolation.md +359 -0
  108. package/docs/reports/v0.9.1-batch2-hard-gate-validation-integration.md +262 -0
  109. package/docs/reports/v0.9.1-pre-release-readiness.md +206 -0
  110. package/package.json +3 -2
  111. package/dist/viewer/assets/index-D98S1_2d.js +0 -9
@@ -0,0 +1,980 @@
1
+ # v0.9 Tutorial End-to-End Acceptance
2
+
3
+ ## 1. VERDICT
4
+
5
+ `PASS_V0_9_TUTORIAL_ACCEPTANCE_READY_FOR_HUMAN_REVIEW`
6
+
7
+ ```text
8
+ FINAL_RUNS_PASSED 4 of 4
9
+ CLEANUP_ERRORS empty for every run
10
+ STRUCTURAL_ARTIFACT_ACCEPTANCE PASS (144 checks)
11
+ CANONICAL_OBSERVER_EVIDENCE PASS (44 checks)
12
+ SCENARIO_CONTENT_QUALITY PASS (after the corrections in section 8)
13
+ DEMO_SOURCE_IMMUTABILITY PASS
14
+ DEMO_IN_NPM_PACKAGE false
15
+ FULL_LOCAL_REGRESSION PASS
16
+ LOCAL_PACKED_SMOKES PASS
17
+ HUMAN_VISUAL_REVIEW PENDING_USER
18
+ ```
19
+
20
+ All four tutorials were regenerated from clean targets with the released
21
+ `@dailephd/my-dev-kit-lab@0.4.8` against the current local unreleased v0.9
22
+ build. Every run passed with no cleanup error, and every outcome was then
23
+ checked by reading the canonical Observer evidence the run actually wrote.
24
+
25
+ This stage corrected six real tutorial-quality defects, one of which was a
26
+ narration that did not match the evidence the tutorial produced. See
27
+ section 8.
28
+
29
+ Observer gained no tutorial runtime, no dependency and no product-semantics
30
+ change. The package stays at `0.8.1` and v0.9 stays unreleased. A coding agent
31
+ cannot judge how a video looks, so human visual review is honestly recorded as
32
+ pending.
33
+
34
+ ## 2. Repository identity
35
+
36
+ - Repository: `C:\Users\daile\Projects\my-frontend-observer`
37
+ - Branch: `master`
38
+ - Starting HEAD: `6895b303d618fe705252e3cbdbfcd665a656c407`
39
+ - Ending HEAD: recorded in the terminal summary for this stage
40
+ - Package: `@dailephd/my-frontend-observer`
41
+ - Package version: `0.8.1` (unchanged)
42
+ - Viewer protocol: `1.3.0`
43
+ - Visual annotation schema: `1.0.0`
44
+ - v0.9: unreleased
45
+
46
+ ## 3. Entry gate
47
+
48
+ Preflight matched every required value:
49
+
50
+ ```text
51
+ branch master
52
+ HEAD 6895b303d618fe705252e3cbdbfcd665a656c407
53
+ tracked worktree clean
54
+ package version 0.8.1
55
+ docs/reports/v0.9-architecture-retrieval.md S (skip-worktree preserved)
56
+ ```
57
+
58
+ No `pull`, `reset`, `rebase`, `clean` or `stash` was run at any point.
59
+
60
+ The Prompt 2 entry verdict `PASS_V0_9_TUTORIAL_INTEGRATION` was present, and
61
+ its implementation was preserved. The four defect corrections Prompt 2 made
62
+ were not reverted.
63
+
64
+ ## 4. Final tutorial review bundle
65
+
66
+ `Z:` is not available on this machine, so the documented fallback root was
67
+ used and is recorded here exactly:
68
+
69
+ ```text
70
+ C:\Users\daile\AppData\Local\Temp\my-frontend-observer-tutorial-review\v0.9
71
+ ```
72
+
73
+ The exact review root was removed and recreated before the final runs. Only
74
+ that path was removed, after checking that its last two segments were
75
+ `my-frontend-observer-tutorial-review\v0.9`, that it was inside `%TEMP%`, and
76
+ that it was not inside the repository. No parent directory was touched.
77
+
78
+ Structure:
79
+
80
+ ```text
81
+ <reviewRoot>/
82
+ 01-annotation-basics/ lab run root (target, artifacts, screenshots, logs, temporary)
83
+ 02-runtime-intent-contract/ lab run root
84
+ 03-reference-authoring/ lab run root
85
+ 04-reference-materialization/ lab run root
86
+ _contracts/ the four generated target contracts
87
+ _run-results/ run results, validations, verification.json
88
+ REVIEW_INDEX.md
89
+ ```
90
+
91
+ Lab-owned run contents were not reorganized. `_contracts/` is the location the
92
+ task prefers for generated contracts; `_run-results/` holds the captured
93
+ `TutorialRunResultV1` documents and the acceptance verification output so the
94
+ evidence behind this report can be re-read.
95
+
96
+ Absolute review paths are listed in section 26.
97
+
98
+ ## 5. my-dev-kit-lab identity
99
+
100
+ ```text
101
+ npx --yes @dailephd/my-dev-kit-lab@0.4.8 --version 0.4.8
102
+ ```
103
+
104
+ Exact `0.4.8` was used for every validation and every final run. The lab was
105
+ not modified. It is not an Observer dependency and appears in neither
106
+ `dependencies` nor `devDependencies`; it is invoked only through `npx`.
107
+
108
+ Observed limits of the released lab, unchanged and not worked around:
109
+
110
+ 1. There is no select-option action, so native `<select>` controls are driven
111
+ with `ArrowDown` presses. See section 13.
112
+ 2. The tutorial manifest carries no artifact record for itself. This is the
113
+ known limitation and is not reported as a defect.
114
+
115
+ ## 6. Scenario inventory
116
+
117
+ ```text
118
+ id file steps screenshots
119
+ observer-v09-annotation-basics 01-annotation-basics.json 33 11
120
+ observer-v09-runtime-contract 02-runtime-intent-contract.json 106 14
121
+ observer-v09-reference-authoring 03-reference-authoring.json 64 10
122
+ observer-v09-reference-materialization 04-reference-materialization.json 50 7
123
+ ```
124
+
125
+ Each scenario was validated by the released lab against a freshly generated
126
+ target contract immediately before its run:
127
+
128
+ ```text
129
+ scenario validation targetId match run
130
+ observer-v09-annotation-basics valid yes passed
131
+ observer-v09-runtime-contract valid yes passed
132
+ observer-v09-reference-authoring valid yes passed
133
+ observer-v09-reference-materialization valid yes passed
134
+ ```
135
+
136
+ Each run received its own clean run root and its own freshly prepared target
137
+ root, with two distinct dynamic loopback ports. No run reused another run's
138
+ state.
139
+
140
+ ## 7. Structural artifact acceptance
141
+
142
+ The returned `TutorialRunResultV1` is the authority for cleanup:
143
+
144
+ ```text
145
+ scenario result.status result.cleanupErrors manifest.run.status
146
+ observer-v09-annotation-basics passed [] passed
147
+ observer-v09-runtime-contract passed [] passed
148
+ observer-v09-reference-authoring passed [] passed
149
+ observer-v09-reference-materialization passed [] passed
150
+ ```
151
+
152
+ Every result reported schema `1.0.0`. No run reported `cleanup-failed`,
153
+ `artifact-failed`, `step-failed` or `video-finalization-failed`.
154
+
155
+ Artifact inventory, all regular non-empty files:
156
+
157
+ ```text
158
+ scenario webm srt vtt md manifest screenshots
159
+ observer-v09-annotation-basics 27.9 MB 6.5 kB 6.4 kB 7.1 kB 29.8 kB 11 of 11
160
+ observer-v09-runtime-contract 49.3 MB 12.3 kB 12.0 kB 13.0 kB 68.0 kB 14 of 14
161
+ observer-v09-reference-authoring 34.3 MB 8.0 kB 7.8 kB 8.7 kB 44.5 kB 10 of 10
162
+ observer-v09-reference-materialization 19.6 MB 4.9 kB 4.8 kB 5.2 kB 33.6 kB 7 of 7
163
+ ```
164
+
165
+ Checks that passed for every scenario (144 structural checks in total, zero
166
+ failures; the 44 canonical evidence checks are in section 17):
167
+
168
+ 1. WebM: EBML signature `1A 45 DF A3`, `webm` DocType in the EBML header,
169
+ non-empty and plausibly sized. No FFmpeg or ffprobe was added and nothing
170
+ was transcoded.
171
+ 2. Manifest: `schemaVersion 1.0.0`, `run.status passed`, `cleanupErrors` empty,
172
+ `warnings` empty, every executed step present in scenario order, every step
173
+ `passed`, every requested screenshot represented with path
174
+ `screenshots/<id>.png` and status `written`, and every artifact path
175
+ run-root-relative with no drive letter, no leading separator and no `..`.
176
+ 3. Every manifest artifact record exists on disk. The two process `stderr`
177
+ logs are correctly recorded as written and are empty, because neither the
178
+ demo server nor the viewer wrote to stderr.
179
+ 4. Screenshots: valid PNG signature and IHDR, non-empty, all 1440x900. No
180
+ unrequested screenshot was produced. No pixel-diff acceptance was done.
181
+ 5. SRT and VTT: one cue per executed step, cue order equal to step order, cue
182
+ text byte-equal to the scenario narration, timestamps monotonic and
183
+ non-overlapping, and every cue boundary equal to the manifest timeline for
184
+ that step. Subtitle wording was never edited separately; the scenario
185
+ remains the single narration source.
186
+ 6. Markdown: correct title, every executed step present in order, narration
187
+ preserved verbatim, requested screenshots referenced as
188
+ `../screenshots/<id>.png` and each reference resolves to a real file, no
189
+ machine-specific absolute path, and no line of prose beyond the scenario's
190
+ own title, description, step headings, narration and image references.
191
+
192
+ ## 8. Scenario content-quality audit
193
+
194
+ Every step was read and judged against the questions the task sets: whether
195
+ the narration explains why an operation exists, whether it draws the
196
+ distinction that matters, whether the step does real product work, and whether
197
+ it is materially more useful than naming the control being clicked.
198
+
199
+ The audit found six genuine defects. All six were corrected in this stage and
200
+ all four scenarios were then rerun from clean targets. The corrections
201
+ stayed inside scenario narration, pauses, screenshot requests, callouts and
202
+ scenario step sequence. No product behavior was changed.
203
+
204
+ ### 8.1 Narration that contradicted the evidence (scenario 4)
205
+
206
+ The second requirement in `04-reference-materialization` was narrated as being
207
+ about the footer, and the tutorial's whole point is that the unselected
208
+ requirement is a real, confirmed, correct requirement left out of the
209
+ revision. The saved evidence from the Prompt 2 run says otherwise:
210
+
211
+ ```text
212
+ {"category":"preserved","subject":{"kind":"region-property","region":"promo-band","property":"height"}}
213
+ ```
214
+
215
+ The requirement-region select keeps its previous value, `hero`, and the region
216
+ list is the reference's own regions in import order followed by the regions
217
+ the draft proposes. Six `ArrowDown` presses from `hero` therefore pass
218
+ `sidebar, content, cta, asset, footer` and land on the draft's own
219
+ `promo-band`. One press too many selected a different but equally valid
220
+ region, so nothing failed and the run passed with narration that was untrue.
221
+
222
+ Correction: the press count is now five, which lands on `footer`. The step
223
+ `req-b-region-6` was removed and the five remaining presses now name the value
224
+ each one lands on. The scenario now also asserts the resulting structured
225
+ requirement immediately:
226
+
227
+ ```json
228
+ { "type": "text-contains", "expected": "\"region\": \"footer\"" }
229
+ { "type": "text-contains", "expected": "\"property\": \"height\"" }
230
+ ```
231
+
232
+ That assertion is the regression guard: the same defect would now fail the run
233
+ instead of producing a confident false statement. The final run confirms the
234
+ unselected requirement is `preserved footer.height`, and that it did not
235
+ materialize.
236
+
237
+ Note for the record: section 21 of `docs/reports/v0.9-tutorial-integration.md`
238
+ describes this item as "the unselected footer requirement". That statement was
239
+ inaccurate for the Prompt 2 candidate. It is accurate for the current one.
240
+
241
+ ### 8.2 Narration that was too fast to read (all four scenarios)
242
+
243
+ No step declared a pause, so each step lasted only as long as its action. In
244
+ the Prompt 2 run, `01-annotation-basics` played 4301 characters of narration
245
+ in 20.7 seconds, and its opening 40-word subtitle cue was on screen for 256
246
+ milliseconds. The structure was valid and the content was good, but nobody
247
+ could read it. That is the "near-zero instructional visibility" the timing
248
+ audit asks about.
249
+
250
+ Correction: every step now carries a `pauseAfterMs` sized from its own
251
+ narration at 15 characters per second, never below 1.2 seconds. The pause runs
252
+ after the action and after any callout is drawn, so it extends both the
253
+ subtitle cue and the time a callout stays readable, and it is inside the
254
+ step's timeline, so subtitles and manifest stay consistent.
255
+ `tests/unit/v09TutorialScenarios.test.ts` now enforces that floor, so
256
+ lengthening a narration without lengthening its pause fails a unit test.
257
+
258
+ ### 8.3 A claim the tutorial never demonstrated (scenario 1)
259
+
260
+ `01-annotation-basics` told the viewer that saving again writes a new
261
+ annotation recording which one it revises, and that the original stays
262
+ untouched. It then stopped at the revision draft without saving, so the
263
+ strongest claim in the tutorial was the one thing it never showed, and there
264
+ was no supersession chain in the evidence to verify.
265
+
266
+ Correction: five steps were added. In the revision draft the point mark, which
267
+ was saved with no association, is explicitly associated with `card1` and the
268
+ revision is saved. The canonical check in section 17 now verifies a real
269
+ two-artifact chain.
270
+
271
+ ### 8.4 View state that made the revision unreadable (scenario 1)
272
+
273
+ After the reload, the relationship overlay returns, because a view toggle is
274
+ page state rather than evidence. The final revision screenshots were covered
275
+ in dashed relationship lines.
276
+
277
+ Correction: one step switches the overlay off again, and its narration uses
278
+ the moment to make the point that the annotation came back from disk while the
279
+ toggle did not.
280
+
281
+ ### 8.5 Mechanical narration on keyboard steps
282
+
283
+ Several keypress steps read only "Stepping down." Individually harmless, but a
284
+ recording that says "Stepping down" eleven times teaches nothing and makes the
285
+ keyboard-driven select changes hard to follow, which is exactly what review
286
+ question 8 asks about.
287
+
288
+ Correction: each press in a run now names the value it lands on, for example
289
+ "Inspect.", "Move.", "Resize.", "Remove.", "Preserve.", and the first press of
290
+ each run explains what is being chosen and why. The vocabulary order is now
291
+ visible in the recording instead of implied.
292
+
293
+ ### 8.6 Narration that did not name what was chosen
294
+
295
+ Two steps described a mark's position rather than the association actually
296
+ made. In scenario 2 a line is drawn across the call-to-action band and then
297
+ bound to the first derived relationship, which is `header` horizontally
298
+ overlapping `navigation`. In scenario 3 the narration said the header "sits
299
+ above" the hero while the requirement protects `horizontally-overlapping`.
300
+
301
+ Correction: both now name the relationship, and scenario 2 turns the mismatch
302
+ into the lesson: where a mark is drawn never decides what it is about. Both
303
+ scenarios now assert the relationship they narrate.
304
+
305
+ ### 8.7 Judgement on the rest
306
+
307
+ The remaining narration passes. Short lines such as "Confirmed." appear only
308
+ on steps whose meaning was explained immediately before, and the substantive
309
+ steps explain purpose rather than naming controls. No step's substance is only
310
+ "Click Rectangle" or "Press Confirm".
311
+
312
+ ## 9. Annotation basics review
313
+
314
+ `observer-v09-annotation-basics`, 33 steps, 6 min 24 s.
315
+
316
+ Content gate:
317
+
318
+ ```text
319
+ marks are evidence, not requirements PASS (steps point-mode, point-place, five-marks)
320
+ visual overlap is not association PASS (explain-no-association, with callout)
321
+ Select, Pan and drawing modes differ PASS (explain-select-mode, explain-pan-mode)
322
+ association is explicit PASS (select-hero-target, associate-hero)
323
+ saving creates immutable evidence PASS (save-annotation, confirm-saved)
324
+ revision does not rewrite history PASS (explain-revision, and now save-revision)
325
+ ```
326
+
327
+ The tutorial creates all five mark kinds, associates exactly one of them on
328
+ purpose, saves, reloads from disk, reopens the saved annotation as a revision,
329
+ changes one association, and saves the revision. The claim about revisions is
330
+ now demonstrated and then verified in the evidence.
331
+
332
+ ## 10. Runtime intent and contract review
333
+
334
+ `observer-v09-runtime-contract`, 106 steps, 10 min 48 s.
335
+
336
+ Content gate:
337
+
338
+ ```text
339
+ drawing does not determine intent PASS
340
+ arrow geometry does not determine move direction PASS (drawn left, direction right, asserted)
341
+ candidate != confirmed PASS
342
+ confirmed can become candidate again after editing PASS (retarget hero -> content, asserted)
343
+ Inspect is informational and non-promotable PASS (asserted "informational")
344
+ Remove is confirmable but unsupported for promotion PASS (asserted "no target-absent primitive")
345
+ confirmed != selected for this contract PASS (4 confirmed, 2 selected)
346
+ promotion != activation PASS (separate explicit checkbox)
347
+ ```
348
+
349
+ The structured mappings are shown as real product output, not narrated:
350
+ `property-increases hero.x`, `property-increases sidebar.width`,
351
+ `property-unchanged-within-tolerance footer.y`, and `relationship-unchanged`.
352
+ The promotion result is asserted to report `2 clauses` and
353
+ `Activation: activated`.
354
+
355
+ ## 11. Reference authoring review
356
+
357
+ `observer-v09-reference-authoring`, 64 steps, 7 min 11 s.
358
+
359
+ Content gate:
360
+
361
+ ```text
362
+ reference-image pixels != runtime CSS pixels PASS (aria-label asserted exactly)
363
+ drawing a region != binding it PASS (callout plus explicit refine)
364
+ visible detail != requirement PASS
365
+ property != relationship != measurement PASS (all three authored and asserted)
366
+ asset-sensitive/informational != executable requirement PASS
367
+ ```
368
+
369
+ The relationship requirement is chosen from the list Observer derived from the
370
+ reference's own geometry, so a requirement the image does not contain cannot
371
+ be authored. The final run recorded `header`/`hero` `horizontally-overlapping`
372
+ protected, `hero.width` protected within 4 reference pixels, and a
373
+ `vertical-gap` from `hero` to `cta` preserved within 6 reference pixels.
374
+
375
+ ## 12. Reference materialization review
376
+
377
+ `observer-v09-reference-materialization`, 50 steps, 4 min 11 s.
378
+
379
+ Content gate:
380
+
381
+ ```text
382
+ confirmed != materialized PASS (blocked until saved, asserted)
383
+ only selected confirmed items enter this revision PASS (3 of 4 selected)
384
+ source reference remains immutable PASS (verified in evidence)
385
+ annotation marks are not baked into the image PASS (digest equality, section 18)
386
+ new revision is imported PASS (asserted "Lifecycle: imported")
387
+ imported != approved PASS (asserted "Approval required: yes")
388
+ materialization != approval PASS (no approved successor exists)
389
+ ```
390
+
391
+ The tutorial also shows that the viewer does not switch to the new revision,
392
+ and explains why quietly adopting an unapproved reference would make approval
393
+ meaningless.
394
+
395
+ ## 13. ArrowDown and native-select dependency audit
396
+
397
+ Every `<select>` renders an empty `Choose…` option first, so from an empty
398
+ form the first press lands on the first vocabulary entry. The runtime intent
399
+ form resets for every mark; the reference requirement form does not. Counts
400
+ that are wrong by one select a different valid value rather than failing,
401
+ which is why each authored result is asserted.
402
+
403
+ Scenario 2, `observer-v09-runtime-contract`. Every form starts empty:
404
+
405
+ ```text
406
+ steps field presses result frozen vocabulary
407
+ operation-move..-2 Runtime intent operation 2 move RUNTIME_OPERATIONS: inspect, move, resize, remove, preserve
408
+ direction-right Move direction 1 right MOVE_DIRECTIONS: right, left, down, up
409
+ category-requested Intent category 1 requested RUNTIME_AUTHORED_CATEGORIES: requested, expected-dependent, protected, preserved
410
+ operation-resize-1..3 Runtime intent operation 3 resize RUNTIME_OPERATIONS
411
+ resize-wider Resize direction 1 wider RESIZE_DIRECTIONS: wider, narrower, taller, shorter
412
+ category-expected-1..2 Intent category 2 expected-dependent RUNTIME_AUTHORED_CATEGORIES
413
+ mode-required Intent expected-dependent mode 1 required RUNTIME_EXPECTED_DEPENDENT_MODES: required, permitted
414
+ operation-preserve..-5 Runtime intent operation 5 preserve RUNTIME_OPERATIONS
415
+ category-protected-1..3 Intent category 3 protected RUNTIME_AUTHORED_CATEGORIES
416
+ preserve-property-1..2 Preserved property 2 y PRESERVE_PROPERTIES: x, y, width, height
417
+ tolerance-1..2 Contract tolerance 2 absolute-px CONTRACT_TOLERANCE_KINDS: exact, absolute-px, percent
418
+ relationship-choose Canonical relationship to associate 1 header/navigation server relationship graph order (see below)
419
+ rel-operation-1..5 Runtime intent operation 5 preserve RUNTIME_OPERATIONS
420
+ rel-category-1..4 Intent category 4 preserved RUNTIME_AUTHORED_CATEGORIES
421
+ remove-op-1..4 Runtime intent operation 4 remove RUNTIME_OPERATIONS
422
+ remove-category Intent category 1 requested RUNTIME_AUTHORED_CATEGORIES
423
+ inspect-op Runtime intent operation 1 inspect RUNTIME_OPERATIONS
424
+ ```
425
+
426
+ Scenario 3, `observer-v09-reference-authoring`:
427
+
428
+ ```text
429
+ steps field starting value presses result vocabulary
430
+ property-category-1..3 Requirement category empty 3 protected REQUIREMENT_CATEGORIES: requested, expected-dependent, protected, preserved
431
+ property-subject Requirement subject empty 1 region-property region-property, region-relationship, region-measurement
432
+ property-region-1..2 Requirement region empty 2 hero region list (see below)
433
+ property-prop-1..3 Region property empty 3 width REGION_PROPERTIES: x, y, width, height, right, bottom, centerX, centerY
434
+ property-tolerance-1..2 Tolerance empty 2 absolute-reference-px TOLERANCE_KINDS: exact, absolute-reference-px, percent
435
+ relationship-subject-1 Requirement subject region-property (kept) 1 region-relationship subject kinds
436
+ relationship-pick Requirement relationship empty 1 header/hero overlap derived reference relationships
437
+ measurement-category-1 Requirement category protected (kept) 1 preserved REQUIREMENT_CATEGORIES
438
+ measurement-subject-1 Requirement subject region-relationship (kept) 1 region-measurement subject kinds
439
+ measurement-subject-region-1..2 Subject region empty (never set) 2 hero region list
440
+ measurement-related-1..5 Related region empty 5 cta region list
441
+ measurement-kind Measurement empty 1 vertical-gap REGION_MEASUREMENTS: vertical-gap, horizontal-gap, center-x-delta, center-y-delta, left-edge-delta, right-edge-delta
442
+ ```
443
+
444
+ Scenario 4, `observer-v09-reference-materialization`:
445
+
446
+ ```text
447
+ steps field starting value presses result vocabulary
448
+ req-a-cat-1..3 Requirement category empty 3 protected REQUIREMENT_CATEGORIES
449
+ req-a-subject Requirement subject empty 1 region-property subject kinds
450
+ req-a-region-1..2 Requirement region empty 2 hero region list
451
+ req-a-prop-1..3 Region property empty 3 width REGION_PROPERTIES
452
+ req-a-tol-1..2 Tolerance empty 2 absolute-reference-px TOLERANCE_KINDS
453
+ req-b-cat Requirement category protected (kept) 1 preserved REQUIREMENT_CATEGORIES
454
+ req-b-region-1..5 Requirement region hero (kept) 5 footer region list, corrected from 6 in section 8.1
455
+ req-b-prop Region property width (kept) 1 height REGION_PROPERTIES
456
+ ```
457
+
458
+ The region list is `requirementRegionIds`: the reference's own regions in
459
+ import order, `header, hero, sidebar, content, cta, asset, footer`, followed
460
+ by region ids the draft proposes, which adds `promo-band` once the create
461
+ intent exists.
462
+
463
+ Two of these lists are not frozen vocabularies and deserve to be called out.
464
+ The relationship options come from the canonical relationship graph the server
465
+ derives, in its order. They are deterministic here only because the demo's
466
+ geometry is deterministic, and both scenarios now assert the relationship they
467
+ select, so a change in derivation order fails the run rather than silently
468
+ recording a different requirement.
469
+
470
+ Maintenance coupling: adding a member to any of these vocabularies, or a
471
+ region to the demo reference, shifts the press counts. The demo README records
472
+ this, and the in-scenario assertions turn a shifted count into a run failure.
473
+
474
+ ## 14. Reference-form retained-value audit
475
+
476
+ The reference requirement form keeps its values when another mark is selected.
477
+ The runtime intent form resets. Neither behavior was changed.
478
+
479
+ Scenario 3:
480
+
481
+ ```text
482
+ field previous value next expected value how the scenario handles it
483
+ Requirement category protected protected no press; reused for the relationship requirement
484
+ Requirement subject region-property region-relationship one press
485
+ Requirement category protected preserved one press
486
+ Requirement subject region-relationship region-measurement one press
487
+ Tolerance kind absolute-reference-px absolute-reference-px no press; only the amount is refilled, 4 then 6
488
+ ```
489
+
490
+ Scenario 4:
491
+
492
+ ```text
493
+ field previous value next expected value how the scenario handles it
494
+ Requirement category protected preserved one press
495
+ Requirement subject region-property region-property no press; reused
496
+ Requirement region hero footer five presses
497
+ Region property width height one press
498
+ Tolerance kind absolute-reference-px absolute-reference-px no press; amount refilled to 8
499
+ ```
500
+
501
+ This stays deterministic because each run starts from a fresh target and a
502
+ freshly loaded page, the form starts from `EMPTY_REQUIREMENT_FORM`, every
503
+ later value is reached by a fixed number of presses from a known previous
504
+ value, and the resulting structured requirement is asserted before the run
505
+ continues.
506
+
507
+ ## 15. Tutorial timing audit
508
+
509
+ ```text
510
+ scenario total steps longest step shortest step
511
+ observer-v09-annotation-basics 6 min 24 s 33 arrow-draw 21.4 s revise-select-point 5.0 s
512
+ observer-v09-runtime-contract 10 min 48 s 106 show-arrow-non-inference 23.8 s preserve-property-2 1.5 s
513
+ observer-v09-reference-authoring 7 min 11 s 64 explain-coordinates 23.6 s property-category-3 1.5 s
514
+ observer-v09-reference-materialization 4 min 11 s 50 inspect-result 23.8 s req-b-region-2 1.5 s
515
+ ```
516
+
517
+ Flags, using the audit's own three questions:
518
+
519
+ 1. Accidental dead time: none. No step spent more than 5 seconds beyond its
520
+ declared reading pause. Longest steps are the deliberate explanation steps,
521
+ and their duration is the reading pause plus an action of about 50 ms.
522
+ 2. Near-zero instructional visibility: none. The shortest step is 1.5 seconds
523
+ for a single keypress whose narration is one word. This was the defect
524
+ described in section 8.2 and it is closed.
525
+ 3. Timeout-like delay: none. No step approaches an assertion timeout, and no
526
+ run reported a warning.
527
+
528
+ Duration was not optimized. Total runtime grew from about 2.5 minutes to about
529
+ 28.5 minutes across the four tutorials because the narration is now readable,
530
+ which the task explicitly prefers over speed.
531
+
532
+ ## 16. Screenshot, callout and highlight coverage
533
+
534
+ ```text
535
+ scenario screenshots conceptual states captured
536
+ observer-v09-annotation-basics 11 viewer open, observation ready, rectangle drawn,
537
+ arrow as evidence, five marks, no association,
538
+ association made, saved, reloaded from disk,
539
+ revision draft, revision saved
540
+ observer-v09-runtime-contract 14 start, arrow drawn left, candidate set, structured
541
+ intent, confirmation withdrawn, resize confirmed,
542
+ preserve confirmed, relationship associated,
543
+ relationship confirmed, remove not promotable,
544
+ inspect informational, promotion list, selected
545
+ subset, promoted and activated
546
+ observer-v09-reference-authoring 10 reference open, coordinate distinction, region
547
+ created, drawn but not bound, region refined,
548
+ property requirement, relationship requirement,
549
+ measurement requirement, asset-sensitive, saved
550
+ observer-v09-reference-materialization 7 source reference, four confirmed, confirmed but not
551
+ materialized, materialization list, three of four
552
+ selected, materialized result, source still open
553
+ ```
554
+
555
+ Five screenshots were added in this stage because important conceptual
556
+ transitions had a callout but no still image: `arrow-is-evidence`,
557
+ `relationship-associated`, `reference-coordinates`, `drawn-not-bound` and
558
+ `confirmed-not-materialized`. Trivial steps such as individual keypresses
559
+ deliberately have none.
560
+
561
+ Callouts: 6, 5, 3 and 3 across the four scenarios, 17 in total. Every one
562
+ carries a distinction rather than repeating the narration, for example "The
563
+ arrow points left. The requested direction is right.", "Confirmed is not the
564
+ same as included." and "Imported is not approved. Materializing is not
565
+ approving." No callout repeats its narration verbatim and no step highlights
566
+ every click. The scenarios declare no `highlight`.
567
+
568
+ Callout occlusion was inspected on the captured screenshots. The callout in
569
+ `explain-no-association` sits over the lower part of the observation image and
570
+ away from the target list the next step clicks; the callout in `save-revision`
571
+ sits at the bottom of the image area. A callout can cover part of the
572
+ screenshot being discussed, which is a judgement only a human watching the
573
+ video can finally make. It is question 3 of the review checklist.
574
+
575
+ ## 17. Canonical Observer evidence verification
576
+
577
+ These checks were rerun against the final review runs. Prompt 2's results were
578
+ not reused. Evidence was read from each disposable target root with Observer's
579
+ own exported readers (`readVisualAnnotationArtifact`,
580
+ `readExternalReferenceArtifact`, `readPersistentBaselineContract`,
581
+ `readPerChangeContract`), so a structurally invalid artifact would fail here.
582
+
583
+ Scenario 1, `01-annotation-basics`:
584
+
585
+ ```text
586
+ two annotation artifacts, original and revision PASS
587
+ canonical reader accepts both, schema 1.0.0 PASS
588
+ both sources are the prepared baseline observation PASS
589
+ all five mark kinds present in both PASS
590
+ revision.supersedesAnnotationId == original.annotationId PASS
591
+ chain has one root and no dangling parent PASS
592
+ original: rectangle -> hero is the only association PASS
593
+ revision: point -> card1 added, rectangle -> hero kept PASS
594
+ original written first and not rewritten PASS
595
+ ```
596
+
597
+ Scenario 2, `02-runtime-intent-contract`:
598
+
599
+ ```text
600
+ project acceptance baselineArtifact unchanged PASS (tutorial-baseline/v09-tutorial-baseline)
601
+ baseline contract still readable and untouched PASS
602
+ changeArtifact moved off the prepared initial contract PASS
603
+ active change contract is a normal PerChangeContract PASS
604
+ exactly two clauses PASS
605
+ requested:property-increases:hero.x
606
+ expected-dependent(required):property-increases:sidebar.width
607
+ Remove absent from clauses PASS
608
+ Inspect absent from clauses PASS
609
+ clauses cite the saved annotation as supporting evidence PASS
610
+ annotation still holds six confirmed items, incl. remove
611
+ and inspect PASS
612
+ relationship intent is header/navigation
613
+ horizontally-overlapping PASS
614
+ ```
615
+
616
+ Scenario 3, `03-reference-authoring`:
617
+
618
+ ```text
619
+ annotation source is the approved reference PASS
620
+ seven items, all confirmed PASS
621
+ reference-region intent: create promo-band, refine sidebar PASS
622
+ region-property requirement hero.width protected 4px PASS
623
+ region-relationship requirement header/hero
624
+ horizontally-overlapping protected PASS
625
+ region-measurement requirement hero -> cta vertical-gap
626
+ preserved 6px PASS
627
+ informational and asset-sensitive intent recorded PASS
628
+ neither materialized: approved source still has zero
629
+ requirements and no new revision exists PASS
630
+ ```
631
+
632
+ Scenario 4, `04-reference-materialization`:
633
+
634
+ ```text
635
+ exactly one new reference revision PASS
636
+ lifecycle = imported PASS
637
+ supersedes the approved source reference PASS
638
+ selected create materialized (promo-band) PASS
639
+ selected refine materialized (sidebar rectangle differs) PASS
640
+ selected requirement materialized (protected hero.width) PASS
641
+ unselected requirement absent (preserved footer.height) PASS
642
+ source approved reference unchanged: approved, 7 regions,
643
+ 0 requirements PASS
644
+ no approved successor automatically created PASS
645
+ ```
646
+
647
+ ## 18. Reference image digest verification
648
+
649
+ ```text
650
+ source reference image SHA-256 4bdb94db1096532dd886b7b8bd9ea4018f44ff0e3debb24e92cbf6132123538d
651
+ materialized revision image SHA-256 4bdb94db1096532dd886b7b8bd9ea4018f44ff0e3debb24e92cbf6132123538d
652
+ committed examples/v09-demo PNG 4bdb94db1096532dd886b7b8bd9ea4018f44ff0e3debb24e92cbf6132123538d
653
+ digest recorded by the approved source manifest 4bdb94db...538d
654
+ digest recorded by the new revision manifest 4bdb94db...538d
655
+ ```
656
+
657
+ All five are equal, computed from the actual file bytes rather than trusted
658
+ from the manifests. The new revision reuses the source image exactly, so the
659
+ annotation graphics were not baked into it.
660
+
661
+ ## 19. Demo and source immutability
662
+
663
+ A SHA-256 digest of all 19 tracked files under `examples/v09-demo/` was taken
664
+ immediately before the four final runs and recomputed immediately after:
665
+
666
+ ```text
667
+ tracked files 19
668
+ digest before 6c845bac0964dd97146306b8789bdb4918fd26ee3af8744ad9b55e1f4f687edb
669
+ digest after 6c845bac0964dd97146306b8789bdb4918fd26ee3af8744ad9b55e1f4f687edb
670
+ demoSourceImmutable true
671
+ ```
672
+
673
+ `git status --short` was captured before the runs and recompared after. It was
674
+ byte-identical, so no tutorial runtime output appeared in the repository, as
675
+ tracked or untracked content. Every generated artifact lives under the
676
+ external review root.
677
+
678
+ For honesty about method: an earlier complete set of four runs was executed
679
+ while this stage was still editing scenario narration and documentation, so
680
+ its immutability and status comparison were meaningless and it was discarded
681
+ as a trial. The final runs reported here were executed with no tracked file
682
+ being edited during them, and the report itself was written afterwards.
683
+
684
+ ## 20. npm package inclusion decision
685
+
686
+ Frozen as specified: for v0.9.0, `examples/v09-demo/` and its tutorial and
687
+ reference assets remain repository-owned development, documentation and
688
+ demonstration source, and are not shipped in the npm package.
689
+
690
+ The decision needed no package-boundary change. `package.json#files` is
691
+ `dist`, `README.md`, `CHANGELOG.md`, `docs`, `LICENSE`, so the demo was never
692
+ included:
693
+
694
+ ```text
695
+ npm pack --dry-run 0.8.1, no entry under examples/
696
+ ```
697
+
698
+ Regression protection was added to the canonical package-content gate rather
699
+ than to a new framework. `scripts/ci/runPackedV09AnnotationSmoke.mjs` already
700
+ asserts that the installed package contains every compiled v0.9 owner and does
701
+ not contain `scripts/`; it now also fails if an `examples/` directory is
702
+ present in the installed package. That gate runs locally in section 22 and in
703
+ the pre-release readiness matrix on all three platforms.
704
+
705
+ ## 21. Documentation reconciliation
706
+
707
+ ```text
708
+ README.md new "Demo and tutorials" section: why the demo
709
+ exists, where it lives, that
710
+ my-dev-kit-lab@0.4.8 records the tutorials, how
711
+ a contributor validates and runs one, that
712
+ output goes to a caller-chosen external
713
+ directory, and that none of it ships in the npm
714
+ package
715
+ docs/PROJECT_OVERVIEW.md v0.9 product implementation complete, demo and
716
+ tutorial integration complete, release pending a
717
+ fresh exact-candidate readiness run
718
+ docs/CURRENT_STATE.md new bounded "v0.9 demo and tutorials" section:
719
+ implementation status, the demo-foundation and
720
+ tutorial-integration commits, the lab 0.4.8 tool
721
+ relationship, the four scenarios, the canonical
722
+ evidence proofs, unreleased state, and the next
723
+ required readiness step; the stale claim that
724
+ readiness "has not yet run" was corrected to
725
+ record the historical run and why it is not
726
+ authoritative now
727
+ docs/ROADMAP.md concise status note only; v0.9 product design
728
+ untouched
729
+ docs/WORKFLOWS.md new "Developer tutorial-generation workflow"
730
+ section with the pipeline diagram, the ownership
731
+ boundary and runnable commands
732
+ docs/PROJECT_DESCRIPTION.md the durable "Future capability - Human visual
733
+ annotation" heading was relabelled as implemented
734
+ in v0.9 and not yet released, following the
735
+ document's existing convention; the capability
736
+ intent text is unchanged
737
+ examples/v09-demo/README.md exact lab version, review-output guidance, run
738
+ root layout, pacing rules, and the select and
739
+ retained-value maintenance notes
740
+ docs/COMMANDS.md unchanged; Observer gained no tutorial command
741
+ and the commands the tutorials use are already
742
+ documented
743
+ docs/PROJECT_MILESTONES.md unchanged; Milestone 9 already states
744
+ "implemented in the current unreleased
745
+ development state"
746
+ ```
747
+
748
+ Terms are used exactly: implemented, validated locally, tutorial integration
749
+ complete, unreleased, cross-platform readiness pending rerun. No document says
750
+ released, published, `v0.9.0` available, or that a final candidate passed
751
+ cross-platform validation.
752
+
753
+ ## 22. Local release-candidate regression
754
+
755
+ Run after all documentation and tutorial-quality corrections:
756
+
757
+ ```text
758
+ npm run typecheck PASS
759
+ npm run lint PASS
760
+ npm test PASS (89 files, 1452 tests)
761
+ npm run test:browser PASS (29 files, 275 tests)
762
+ npm run test:security PASS (16 files / 167 tests, then 3 files / 77 tests)
763
+ npm run build PASS
764
+ npm run check:docs PASS (17 required files)
765
+ npm pack --dry-run PASS (0.8.1, 365 files, 0 examples/ entries)
766
+ ```
767
+
768
+ The unit count is one higher than Prompt 2's 1451 because of the new
769
+ reading-time floor test in `tests/unit/v09TutorialScenarios.test.ts`. No test
770
+ was skipped, deleted, weakened or made permissive, and no `.skip`, `.only`,
771
+ `continue-on-error` or `|| true` was introduced.
772
+
773
+ ## 23. Local packed-package and smoke verification
774
+
775
+ The existing local packed gates were rerun against one exact candidate
776
+ tarball, not a weaker substitute. The tarball, its hash, the consumer installs
777
+ and all temporary state were kept beneath the git-ignored repository-local
778
+ workflow root `.my-dev-kit-workflow/v0.9/tutorial-acceptance/`, with `TEMP` and
779
+ `TMP` redirected there for the smoke processes.
780
+
781
+ ```text
782
+ candidate tarball .my-dev-kit-workflow/v0.9/tutorial-acceptance/package/dailephd-my-frontend-observer-0.8.1.tgz
783
+ SHA-256 d4fb780120e8b6707946d194f3ce57389b270e36ffaf8e263351377a5154e225
784
+
785
+ node scripts/ci/runPackedObservationSmoke.mjs <tarball> PASS
786
+ node scripts/ci/runPackedViewerSmoke.mjs <tarball> PASS
787
+ node scripts/ci/runPackedV09AnnotationSmoke.mjs <tarball> PASS
788
+ ```
789
+
790
+ The observation smoke reported aggregate `pass: true`, including every
791
+ installed v0.1 to v0.7 assertion, `packedNoRepoRootLeak` and source
792
+ immutability. The protected and preserved failure values inside its summary
793
+ are the intentional negative-case contract evaluation, not a smoke failure.
794
+
795
+ The viewer smoke reported `PACKED VIEWER SMOKE: PASS` with viewer protocol
796
+ `1.3.0`, the installed project workflow producing `REVIEW_REQUIRED`, then
797
+ `FAIL`, then `PASS`, alias correctness, traversal rejected, overlay and
798
+ reference views rendered, the service worker registered, `/api/` never cached,
799
+ and the server-down stale-evidence gate holding.
800
+
801
+ The v0.9 annotation smoke reported `PACKED V0.9 ANNOTATION SMOKE: PASS` with
802
+ `tarballSha256` equal to the candidate hash above and every summary flag true:
803
+ `packageContentsPass`, `publicExportsPass`, `consumerPurityPass`,
804
+ `projectWorkflowPass`, `authoringSessionEnabled`, `runtimeAnnotationPass`,
805
+ `runtimePromotionPass`, `contractInspectionPass`, `referenceAnnotationPass`,
806
+ `referenceMaterializationPass`, `newReferenceInspectionPass` and
807
+ `readOnlyBoundaryPass`. `packageContentsPass` now also covers the new
808
+ packaged-`examples/` assertion.
809
+
810
+ Package boundary proof from the installed candidate: every required compiled
811
+ v0.9 owner is present, and `examples/` is absent.
812
+
813
+ ## 24. Prior readiness staleness
814
+
815
+ The prior v0.9 pre-release readiness run
816
+ (`docs/reports/v0.9-pre-release-readiness.md`) passed on Windows, Linux and
817
+ macOS for commit `a78a058`. That candidate did not contain:
818
+
819
+ ```text
820
+ 59ae009d deterministic demo foundation
821
+ 6895b303 tutorial integration
822
+ this stage's scenario, test, package-gate and documentation changes
823
+ ```
824
+
825
+ Therefore:
826
+
827
+ ```text
828
+ prior cross-platform readiness != final-candidate readiness
829
+ PRIOR_CROSS_PLATFORM_READINESS_STILL_AUTHORITATIVE false
830
+ ```
831
+
832
+ This stage ran local validation only. No Windows, Linux or macOS readiness
833
+ claim is made for the current candidate. Cross-platform readiness must be
834
+ rerun on the exact final commit.
835
+
836
+ ## 25. Human visual review status
837
+
838
+ ```text
839
+ HUMAN_VISUAL_REVIEW: PENDING_USER
840
+ ```
841
+
842
+ Automated acceptance verified structure, timing, manifests, subtitles,
843
+ Markdown, screenshots, scenario content and canonical evidence. It cannot
844
+ judge how the recording looks: whether the synthetic cursor reads clearly,
845
+ whether gestures make visual sense, whether callouts are readable and
846
+ well-placed, and whether each tutorial feels like one lesson. That judgement
847
+ belongs to the user, and `REVIEW_INDEX.md` carries the twelve-question
848
+ checklist.
849
+
850
+ One practical note for the reviewer: the viewer header displays the local
851
+ evidence root, so every video and screenshot contains a path under the user
852
+ profile. That is correct viewer behavior, but it matters before the media is
853
+ shared.
854
+
855
+ ## 26. Review paths
856
+
857
+ Review root:
858
+
859
+ ```text
860
+ C:\Users\daile\AppData\Local\Temp\my-frontend-observer-tutorial-review\v0.9
861
+ ```
862
+
863
+ Review index:
864
+
865
+ ```text
866
+ C:\Users\daile\AppData\Local\Temp\my-frontend-observer-tutorial-review\v0.9\REVIEW_INDEX.md
867
+ ```
868
+
869
+ Videos:
870
+
871
+ ```text
872
+ ...\v0.9\01-annotation-basics\artifacts\tutorial.webm
873
+ ...\v0.9\02-runtime-intent-contract\artifacts\tutorial.webm
874
+ ...\v0.9\03-reference-authoring\artifacts\tutorial.webm
875
+ ...\v0.9\04-reference-materialization\artifacts\tutorial.webm
876
+ ```
877
+
878
+ Generated Markdown tutorials:
879
+
880
+ ```text
881
+ ...\v0.9\01-annotation-basics\artifacts\tutorial.md
882
+ ...\v0.9\02-runtime-intent-contract\artifacts\tutorial.md
883
+ ...\v0.9\03-reference-authoring\artifacts\tutorial.md
884
+ ...\v0.9\04-reference-materialization\artifacts\tutorial.md
885
+ ```
886
+
887
+ Manifests:
888
+
889
+ ```text
890
+ ...\v0.9\01-annotation-basics\artifacts\tutorial-manifest.json
891
+ ...\v0.9\02-runtime-intent-contract\artifacts\tutorial-manifest.json
892
+ ...\v0.9\03-reference-authoring\artifacts\tutorial-manifest.json
893
+ ...\v0.9\04-reference-materialization\artifacts\tutorial-manifest.json
894
+ ```
895
+
896
+ Screenshot directories:
897
+
898
+ ```text
899
+ ...\v0.9\01-annotation-basics\screenshots
900
+ ...\v0.9\02-runtime-intent-contract\screenshots
901
+ ...\v0.9\03-reference-authoring\screenshots
902
+ ...\v0.9\04-reference-materialization\screenshots
903
+ ```
904
+
905
+ Each `...` is the review root above. Subtitles sit beside each video as
906
+ `tutorial.srt` and `tutorial.vtt`. Nothing in this bundle is committed.
907
+
908
+ ## 27. Scope audit
909
+
910
+ All of the following are `false`:
911
+
912
+ ```text
913
+ Observer tutorial runtime implemented false
914
+ Observer Playwright recorder added false
915
+ Observer subtitle writer added false
916
+ Observer tutorial-manifest schema added false
917
+ Observer cursor implementation added false
918
+ Observer callout implementation added false
919
+ annotation semantics changed false
920
+ contract semantics changed false
921
+ reference semantics changed false
922
+ approval semantics changed false
923
+ project acceptance semantics changed false
924
+ my-dev-kit-lab modified false
925
+ new dependency added false
926
+ package version changed false
927
+ v0.9 marked released false
928
+ generated tutorial media committed false
929
+ examples/v09-demo included in npm package false
930
+ old cross-platform readiness represented as current false
931
+ ```
932
+
933
+ `src/` and `viewer/src/` are untouched by this stage. `package.json` and
934
+ `package-lock.json` are unchanged, so `DEPENDENCY_CHANGED` is false. The
935
+ intentional `skip-worktree` flag on
936
+ `docs/reports/v0.9-architecture-retrieval.md` is preserved.
937
+
938
+ ## 28. Changed files
939
+
940
+ ```text
941
+ examples/v09-demo/tutorials/01-annotation-basics.json pauses, narration, revision steps, screenshot
942
+ examples/v09-demo/tutorials/02-runtime-intent-contract.json pauses, narration, relationship assertion, screenshot
943
+ examples/v09-demo/tutorials/03-reference-authoring.json pauses, narration, relationship assertion, screenshots
944
+ examples/v09-demo/tutorials/04-reference-materialization.json pauses, narration, footer correction and assertions, screenshot
945
+ examples/v09-demo/README.md exact lab version, review guidance, pacing, select notes
946
+ tests/unit/v09TutorialScenarios.test.ts reading-time floor regression test
947
+ scripts/ci/runPackedV09AnnotationSmoke.mjs packaged-examples regression assertion
948
+ README.md Demo and tutorials section
949
+ docs/PROJECT_OVERVIEW.md v0.9 demo/tutorial status
950
+ docs/CURRENT_STATE.md v0.9 demo and tutorials section, readiness correction
951
+ docs/ROADMAP.md v0.9 status note
952
+ docs/WORKFLOWS.md developer tutorial-generation workflow
953
+ docs/PROJECT_DESCRIPTION.md annotation capability relabelled as implemented
954
+ docs/reports/v0.9-tutorial-end-to-end-acceptance.md this report
955
+ ```
956
+
957
+ Generated paths, all outside the repository or git-ignored:
958
+
959
+ ```text
960
+ C:\Users\daile\AppData\Local\Temp\my-frontend-observer-tutorial-review\v0.9\ review bundle
961
+ .my-dev-kit-workflow/v0.9/tutorial-acceptance/ packed candidate, consumers, temp
962
+ ```
963
+
964
+ ## 29. Exact next step
965
+
966
+ Do not release. In order:
967
+
968
+ 1. The user watches the four WebM tutorials using `REVIEW_INDEX.md` and
969
+ answers its twelve questions.
970
+ 2. If the user approves, rerun the exact-candidate Windows, Linux and macOS
971
+ v0.9 pre-release readiness workflow on the new final commit. The prior run
972
+ is not a substitute.
973
+ 3. If that readiness passes, begin controlled v0.9.0 release preparation as a
974
+ separate stage.
975
+ 4. Only after release preparation passes, publish, tag and release through the
976
+ existing controlled release workflow.
977
+
978
+ If review finds only presentation issues, correct narration, timing, callouts
979
+ or screenshots within the tutorial-quality boundary and regenerate the review
980
+ bundle. Do not reopen v0.9 product semantics.