@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.
- package/CHANGELOG.md +74 -0
- package/README.md +109 -7
- package/dist/application/projectWorkflowService.d.ts +18 -1
- package/dist/application/projectWorkflowService.js +40 -2
- package/dist/application/projectWorkflowService.js.map +1 -1
- package/dist/application/visualAnnotationContractPromotionService.d.ts +41 -0
- package/dist/application/visualAnnotationContractPromotionService.js +143 -0
- package/dist/application/visualAnnotationContractPromotionService.js.map +1 -0
- package/dist/application/visualAnnotationPersistenceService.d.ts +34 -0
- package/dist/application/visualAnnotationPersistenceService.js +68 -0
- package/dist/application/visualAnnotationPersistenceService.js.map +1 -0
- package/dist/application/visualAnnotationReferenceMaterializationService.d.ts +53 -0
- package/dist/application/visualAnnotationReferenceMaterializationService.js +194 -0
- package/dist/application/visualAnnotationReferenceMaterializationService.js.map +1 -0
- package/dist/artifacts/visualAnnotationArtifactReader.d.ts +19 -0
- package/dist/artifacts/visualAnnotationArtifactReader.js +66 -0
- package/dist/artifacts/visualAnnotationArtifactReader.js.map +1 -0
- package/dist/artifacts/visualAnnotationArtifactWriter.d.ts +42 -0
- package/dist/artifacts/visualAnnotationArtifactWriter.js +85 -0
- package/dist/artifacts/visualAnnotationArtifactWriter.js.map +1 -0
- package/dist/cli.js +464 -454
- package/dist/cli.js.map +1 -1
- package/dist/domain/visualAnnotation.d.ts +217 -0
- package/dist/domain/visualAnnotation.js +584 -0
- package/dist/domain/visualAnnotation.js.map +1 -0
- package/dist/domain/visualAnnotationIdentity.d.ts +17 -0
- package/dist/domain/visualAnnotationIdentity.js +47 -0
- package/dist/domain/visualAnnotationIdentity.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/projectWorkflow/projectPaths.d.ts +9 -0
- package/dist/projectWorkflow/projectPaths.js +21 -0
- package/dist/projectWorkflow/projectPaths.js.map +1 -1
- package/dist/viewer/assets/{index-CN_yb9Uf.css → index-BN41MI7m.css} +1 -1
- package/dist/viewer/assets/index-CkKXnlrI.js +9 -0
- package/dist/viewer/index.html +2 -2
- package/dist/viewer/sw.js +1 -1
- package/dist/viewerServer/annotationAuthoring.d.ts +64 -0
- package/dist/viewerServer/annotationAuthoring.js +230 -0
- package/dist/viewerServer/annotationAuthoring.js.map +1 -0
- package/dist/viewerServer/annotationContractPromotion.d.ts +51 -0
- package/dist/viewerServer/annotationContractPromotion.js +105 -0
- package/dist/viewerServer/annotationContractPromotion.js.map +1 -0
- package/dist/viewerServer/annotationReferenceMaterialization.d.ts +40 -0
- package/dist/viewerServer/annotationReferenceMaterialization.js +91 -0
- package/dist/viewerServer/annotationReferenceMaterialization.js.map +1 -0
- package/dist/viewerServer/authoringSecurity.d.ts +59 -0
- package/dist/viewerServer/authoringSecurity.js +112 -0
- package/dist/viewerServer/authoringSecurity.js.map +1 -0
- package/dist/viewerServer/evidence/annotationView.d.ts +28 -0
- package/dist/viewerServer/evidence/annotationView.js +43 -0
- package/dist/viewerServer/evidence/annotationView.js.map +1 -0
- package/dist/viewerServer/evidence/classify.d.ts +3 -1
- package/dist/viewerServer/evidence/classify.js +12 -0
- package/dist/viewerServer/evidence/classify.js.map +1 -1
- package/dist/viewerServer/evidence/discovery.d.ts +2 -0
- package/dist/viewerServer/evidence/discovery.js +6 -0
- package/dist/viewerServer/evidence/discovery.js.map +1 -1
- package/dist/viewerServer/evidence/handles.js +1 -0
- package/dist/viewerServer/evidence/handles.js.map +1 -1
- package/dist/viewerServer/evidence/index.d.ts +29 -0
- package/dist/viewerServer/evidence/index.js +43 -1
- package/dist/viewerServer/evidence/index.js.map +1 -1
- package/dist/viewerServer/evidence/mediaResolver.d.ts +1 -1
- package/dist/viewerServer/evidence/mediaResolver.js +28 -2
- package/dist/viewerServer/evidence/mediaResolver.js.map +1 -1
- package/dist/viewerServer/evidence/projection.d.ts +5 -1
- package/dist/viewerServer/evidence/projection.js +19 -0
- package/dist/viewerServer/evidence/projection.js.map +1 -1
- package/dist/viewerServer/httpServer.d.ts +13 -2
- package/dist/viewerServer/httpServer.js +278 -4
- package/dist/viewerServer/httpServer.js.map +1 -1
- package/dist/viewerServer/viewerService.d.ts +8 -0
- package/dist/viewerServer/viewerService.js +38 -2
- package/dist/viewerServer/viewerService.js.map +1 -1
- package/docs/ARCHITECTURE.md +108 -21
- package/docs/CI_CD.md +78 -1
- package/docs/COMMANDS.md +44 -4
- package/docs/CONTRACTS.md +78 -8
- package/docs/CURRENT_STATE.md +224 -35
- package/docs/DEVELOPMENT.md +38 -3
- package/docs/PROJECT_DESCRIPTION.md +4 -1
- package/docs/PROJECT_MILESTONES.md +32 -0
- package/docs/PROJECT_OVERVIEW.md +58 -17
- package/docs/QUICKSTART.md +52 -39
- package/docs/RELEASE.md +17 -11
- package/docs/ROADMAP.md +458 -66
- package/docs/SECURITY.md +71 -14
- package/docs/WORKFLOWS.md +151 -23
- package/docs/plans/v0.9-implementation-plan.md +1529 -0
- package/docs/plans/v0.9.1-implementation-plan.md +468 -0
- package/docs/reports/v0.9-architecture-retrieval.md +567 -0
- package/docs/reports/v0.9-batch1-visual-annotation-foundation.md +351 -0
- package/docs/reports/v0.9-batch2-viewer-annotation-authoring-boundary.md +438 -0
- package/docs/reports/v0.9-batch3-runtime-screenshot-annotation-authoring.md +412 -0
- package/docs/reports/v0.9-batch4-external-reference-annotation-authoring.md +452 -0
- package/docs/reports/v0.9-batch5-runtime-intent-contract-promotion.md +535 -0
- package/docs/reports/v0.9-batch6-reference-materialization.md +514 -0
- package/docs/reports/v0.9-batch7-integrated-acceptance.md +644 -0
- package/docs/reports/v0.9-demo-foundation.md +589 -0
- package/docs/reports/v0.9-final-pre-release-readiness.md +209 -0
- package/docs/reports/v0.9-final-readiness-corrections.md +530 -0
- package/docs/reports/v0.9-pre-release-readiness.md +170 -0
- package/docs/reports/v0.9-tutorial-end-to-end-acceptance.md +980 -0
- package/docs/reports/v0.9-tutorial-integration.md +731 -0
- package/docs/reports/v0.9.1-batch1-pwa-hard-gate-isolation.md +359 -0
- package/docs/reports/v0.9.1-batch2-hard-gate-validation-integration.md +262 -0
- package/docs/reports/v0.9.1-pre-release-readiness.md +206 -0
- package/package.json +3 -2
- package/dist/viewer/assets/index-D98S1_2d.js +0 -9
|
@@ -0,0 +1,530 @@
|
|
|
1
|
+
# v0.9 Final Readiness Corrections
|
|
2
|
+
|
|
3
|
+
## 1. VERDICT
|
|
4
|
+
|
|
5
|
+
The failed final-readiness workflow run `35527166495` was decomposed into three
|
|
6
|
+
independent defects and corrected. A fourth and a fifth defect, both in the same
|
|
7
|
+
readiness verifier and both in the same family as the second, were found while
|
|
8
|
+
proving the correction locally and are also fixed.
|
|
9
|
+
|
|
10
|
+
No core Observer product regression was established by that run. Final readiness
|
|
11
|
+
exposed:
|
|
12
|
+
|
|
13
|
+
- an Observer tutorial pacing fixture defect,
|
|
14
|
+
- an Observer readiness verifier bug,
|
|
15
|
+
- and a generic my-dev-kit-lab native-select portability gap.
|
|
16
|
+
|
|
17
|
+
The product's own semantics, artifacts and commands were not changed.
|
|
18
|
+
|
|
19
|
+
## 2. Repository identity
|
|
20
|
+
|
|
21
|
+
- Repository: `C:\Users\daile\Projects\my-frontend-observer`
|
|
22
|
+
- Branch: `validation/v0.9-final-readiness`
|
|
23
|
+
- Entry HEAD: `116bf5f45513768d4dfc552545cc02e13265f02f`
|
|
24
|
+
- Package: `@dailephd/my-frontend-observer`
|
|
25
|
+
- Package version: `0.8.1` (unchanged)
|
|
26
|
+
- v0.9: unreleased
|
|
27
|
+
- `master`: not pushed
|
|
28
|
+
- `docs/reports/v0.9-architecture-retrieval.md`: `S` skip-worktree preserved
|
|
29
|
+
|
|
30
|
+
## 3. Failed workflow identity
|
|
31
|
+
|
|
32
|
+
- Run: `35527166495`
|
|
33
|
+
- URL: `https://github.com/dailephd/my-frontend-observer/actions/runs/35527166495`
|
|
34
|
+
- This run is recorded as history. It is not reused as passing evidence for the
|
|
35
|
+
final candidate.
|
|
36
|
+
|
|
37
|
+
## 4. Failure decomposition
|
|
38
|
+
|
|
39
|
+
The earlier compressed summary attributed the whole failure to tutorial
|
|
40
|
+
portability. That was incomplete. The run contained three independent failures.
|
|
41
|
+
|
|
42
|
+
1. Candidate/package job: failed in `npm test` because one scenario pause was
|
|
43
|
+
too short. `02-runtime-intent-contract.json/category-requested` declared
|
|
44
|
+
`pauseAfterMs` of `10900` where the frozen readability rule required
|
|
45
|
+
`11900`. Because the candidate job failed, the exact candidate tarball was
|
|
46
|
+
never built, so the package matrix was `NOT_REACHED`.
|
|
47
|
+
2. Windows tutorial job: the readiness verifier crashed with
|
|
48
|
+
`Cannot read properties of undefined (reading 'contractClass')` because
|
|
49
|
+
contract-reader success results were extracted through the wrong property.
|
|
50
|
+
3. Ubuntu tutorial job: the same readiness verifier crash.
|
|
51
|
+
4. macOS tutorial job: scenario 2 failed while using native-select keyboard
|
|
52
|
+
emulation through click, `ArrowDown` and `Enter` sequences.
|
|
53
|
+
|
|
54
|
+
## 5. my-dev-kit-lab v0.4.9 release identity
|
|
55
|
+
|
|
56
|
+
- Package: `@dailephd/my-dev-kit-lab`
|
|
57
|
+
- Version pinned exactly: `0.4.9`
|
|
58
|
+
- Release commit: `3aca0e2f5969b0a8b414bcd361dec20ba70b8dc6`
|
|
59
|
+
- `npx --yes @dailephd/my-dev-kit-lab@0.4.9 --version` reported `0.4.9`
|
|
60
|
+
- Scenario, target-contract, run-result and manifest schema versions all remain
|
|
61
|
+
`1.0.0`. No Observer scenario schema was migrated.
|
|
62
|
+
- Lab Playwright remains `1.60.0`, so the workflow's exact lab-browser install
|
|
63
|
+
commands were left unchanged. Observer's own `playwright` dependency remains
|
|
64
|
+
`^1.62.1` and was not changed to match the lab.
|
|
65
|
+
- Observer did not add `@dailephd/my-dev-kit-lab` to `dependencies` or
|
|
66
|
+
`devDependencies`. It remains an external tool invoked through `npx`.
|
|
67
|
+
|
|
68
|
+
## 6. select-option contract
|
|
69
|
+
|
|
70
|
+
The released action used is:
|
|
71
|
+
|
|
72
|
+
```json
|
|
73
|
+
{
|
|
74
|
+
"type": "select-option",
|
|
75
|
+
"locator": { "kind": "role", "role": "combobox", "name": "Intent category" },
|
|
76
|
+
"value": "requested"
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
It maps to Playwright's `Locator.selectOption({ value })` and verifies that
|
|
81
|
+
exactly the requested value was selected. v0.4.9 supports `value` only. The
|
|
82
|
+
closed validator rejects `label`, `index`, `values` and multi-select arrays, so
|
|
83
|
+
none of those are used.
|
|
84
|
+
|
|
85
|
+
## 7. Native-select scenario migration inventory
|
|
86
|
+
|
|
87
|
+
Option values were read from the owning viewer source, not guessed from labels:
|
|
88
|
+
|
|
89
|
+
- `viewer/src/annotation/runtimeIntent.ts` for the runtime intent vocabularies.
|
|
90
|
+
- `viewer/src/annotation/referenceIntent.ts` for the reference requirement
|
|
91
|
+
vocabularies.
|
|
92
|
+
- `viewer/src/components/RuntimeAnnotationPanel.tsx` for the relationship select,
|
|
93
|
+
whose option values are `pairwise:<index>`.
|
|
94
|
+
- `viewer/src/components/ReferenceAnnotationPanel.tsx` for the requirement
|
|
95
|
+
selects, whose relationship option values are the relationship index.
|
|
96
|
+
- `examples/v09-demo/references/v09-reference-regions.json` for region ids in
|
|
97
|
+
import order: `header, hero, sidebar, content, cta, asset, footer`.
|
|
98
|
+
|
|
99
|
+
Each migration below replaced a contiguous group of workaround steps with one
|
|
100
|
+
semantic selection step. `01-annotation-basics.json` contains no native select
|
|
101
|
+
interaction and was not modified.
|
|
102
|
+
|
|
103
|
+
### 02-runtime-intent-contract
|
|
104
|
+
|
|
105
|
+
- Runtime intent operation: press "m", press Enter, press Enter, now `select-option` value `move` in step `operation-move`
|
|
106
|
+
- Move direction: click, press ArrowDown, press Enter, now `select-option` value `right` in step `direction-right`
|
|
107
|
+
- Intent category: click, press ArrowDown, press Enter, now `select-option` value `requested` in step `category-requested`
|
|
108
|
+
- Runtime intent operation: press ArrowDown x3, now `select-option` value `resize` in step `operation-resize`
|
|
109
|
+
- Resize direction: press ArrowDown, now `select-option` value `wider` in step `resize-wider`
|
|
110
|
+
- Intent category: press ArrowDown x2, now `select-option` value `expected-dependent` in step `category-expected`
|
|
111
|
+
- Intent expected-dependent mode: press ArrowDown, now `select-option` value `required` in step `mode-required`
|
|
112
|
+
- Runtime intent operation: press ArrowDown x5, now `select-option` value `preserve` in step `operation-preserve`
|
|
113
|
+
- Intent category: press ArrowDown x3, now `select-option` value `protected` in step `category-protected`
|
|
114
|
+
- Preserved property: press ArrowDown x2, now `select-option` value `y` in step `preserve-property`
|
|
115
|
+
- Contract tolerance: press ArrowDown x2, now `select-option` value `absolute-px` in step `tolerance`
|
|
116
|
+
- Canonical relationship to associate: press ArrowDown, now `select-option` value `pairwise:0` in step `relationship-choose`
|
|
117
|
+
- Runtime intent operation: press ArrowDown x5, now `select-option` value `preserve` in step `rel-operation`
|
|
118
|
+
- Intent category: press ArrowDown x4, now `select-option` value `preserved` in step `rel-category`
|
|
119
|
+
- Runtime intent operation: press ArrowDown x4, now `select-option` value `remove` in step `remove-op`
|
|
120
|
+
- Intent category: press ArrowDown, now `select-option` value `requested` in step `remove-category`
|
|
121
|
+
- Runtime intent operation: press ArrowDown, now `select-option` value `inspect` in step `inspect-op`
|
|
122
|
+
|
|
123
|
+
### 03-reference-authoring
|
|
124
|
+
|
|
125
|
+
- Requirement category: press ArrowDown x3, now `select-option` value `protected` in step `property-category`
|
|
126
|
+
- Requirement subject: press ArrowDown, now `select-option` value `region-property` in step `property-subject`
|
|
127
|
+
- Requirement region: press ArrowDown x2, now `select-option` value `hero` in step `property-region`
|
|
128
|
+
- Region property: press ArrowDown x3, now `select-option` value `width` in step `property-prop`
|
|
129
|
+
- Tolerance: press ArrowDown x2, now `select-option` value `absolute-reference-px` in step `property-tolerance`
|
|
130
|
+
- Requirement subject: press ArrowDown, now `select-option` value `region-relationship` in step `relationship-subject`
|
|
131
|
+
- Requirement relationship: press ArrowDown, now `select-option` value `0` in step `relationship-pick`
|
|
132
|
+
- Requirement category: press ArrowDown, now `select-option` value `preserved` in step `measurement-category`
|
|
133
|
+
- Requirement subject: press ArrowDown, now `select-option` value `region-measurement` in step `measurement-subject`
|
|
134
|
+
- Subject region: press ArrowDown x2, now `select-option` value `hero` in step `measurement-subject-region`
|
|
135
|
+
- Related region: press ArrowDown x5, now `select-option` value `cta` in step `measurement-related`
|
|
136
|
+
- Measurement: press ArrowDown, now `select-option` value `vertical-gap` in step `measurement-kind`
|
|
137
|
+
|
|
138
|
+
### 04-reference-materialization
|
|
139
|
+
|
|
140
|
+
- Requirement category: press ArrowDown x3, now `select-option` value `protected` in step `req-a-cat`
|
|
141
|
+
- Requirement subject: press ArrowDown, now `select-option` value `region-property` in step `req-a-subject`
|
|
142
|
+
- Requirement region: press ArrowDown x2, now `select-option` value `hero` in step `req-a-region`
|
|
143
|
+
- Region property: press ArrowDown x3, now `select-option` value `width` in step `req-a-prop`
|
|
144
|
+
- Tolerance: press ArrowDown x2, now `select-option` value `absolute-reference-px` in step `req-a-tol`
|
|
145
|
+
- Requirement category: press ArrowDown, now `select-option` value `preserved` in step `req-b-cat`
|
|
146
|
+
- Requirement region: press ArrowDown x5, now `select-option` value `footer` in step `req-b-region`
|
|
147
|
+
- Region property: press ArrowDown, now `select-option` value `height` in step `req-b-prop`
|
|
148
|
+
|
|
149
|
+
Counts:
|
|
150
|
+
|
|
151
|
+
- `SELECT_OPTION_MIGRATION_COUNT`: 37
|
|
152
|
+
- Collapsed workaround steps: 85 (83 `press`, 2 `click`)
|
|
153
|
+
- `NATIVE_SELECT_KEYBOARD_WORKAROUNDS_BEFORE`: 83
|
|
154
|
+
- `NATIVE_SELECT_KEYBOARD_WORKAROUNDS_REMAINING`: 0
|
|
155
|
+
- Scenario step totals: 258 before, 210 after
|
|
156
|
+
|
|
157
|
+
## 8. Keyboard-workaround removal
|
|
158
|
+
|
|
159
|
+
Narration that described obsolete automation mechanics was removed, for example
|
|
160
|
+
"The first press lands on inspect", "stepped from the top of the list", and the
|
|
161
|
+
single-word stepping lines such as "Move.", "Resize.", "Remove.". Conceptual
|
|
162
|
+
explanation was preserved, including why a category or tolerance is chosen and
|
|
163
|
+
why `unexpected` cannot be authored.
|
|
164
|
+
|
|
165
|
+
`press` remains a legal tutorial action and is still permitted. Only `press`
|
|
166
|
+
acting as a surrogate for `<select>` choice was removed. After migration the
|
|
167
|
+
four scenarios contain no `press` action at all, because every remaining one had
|
|
168
|
+
been a combobox surrogate.
|
|
169
|
+
|
|
170
|
+
Two scenario steps that opened a select with `click` before stepping it were
|
|
171
|
+
part of the same workaround and were collapsed into the semantic selection.
|
|
172
|
+
|
|
173
|
+
No OS-conditional scenario steps were introduced. One canonical scenario set
|
|
174
|
+
remains.
|
|
175
|
+
|
|
176
|
+
Presentation state was preserved rather than dropped while collapsing:
|
|
177
|
+
|
|
178
|
+
- the `direction-right` callout was retained,
|
|
179
|
+
- the `move-form-ready` screenshot, which was attached to the last step of a
|
|
180
|
+
collapsed group, was carried onto the single replacement step.
|
|
181
|
+
|
|
182
|
+
## 9. Pacing correction
|
|
183
|
+
|
|
184
|
+
The frozen rule is unchanged:
|
|
185
|
+
|
|
186
|
+
```
|
|
187
|
+
readingMs = max(1200, ceil((narration.length / 15) * 10) * 100)
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
The rule was not weakened, no test was deleted, and no CI special case was
|
|
191
|
+
added. After all narration edits, every step in all four scenarios was
|
|
192
|
+
re-paced with `pauseAfterMs = max(existing, readingMs)`, which raises any step
|
|
193
|
+
that no longer covers its narration while preserving one deliberately longer
|
|
194
|
+
dwell in `01-annotation-basics.json`.
|
|
195
|
+
|
|
196
|
+
- `CATEGORY_REQUESTED_PACING_FIXED`: true (`10900` to `11900`)
|
|
197
|
+
- `ALL_STEPS_MEET_READING_TIME_RULE`: true, 210 of 210 steps
|
|
198
|
+
- Only the pacing of edited steps changed; `01-annotation-basics.json` is
|
|
199
|
+
byte-identical to its committed version.
|
|
200
|
+
|
|
201
|
+
## 10. Readiness contract-reader root cause
|
|
202
|
+
|
|
203
|
+
`scripts/run-v09-tutorial-readiness.mjs` used one helper for every canonical
|
|
204
|
+
reader:
|
|
205
|
+
|
|
206
|
+
```js
|
|
207
|
+
async function readArtifact(reader, file) {
|
|
208
|
+
const result = await reader(file);
|
|
209
|
+
if (!result?.ok) fail(...);
|
|
210
|
+
return result.artifact;
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
That is correct for `readVisualAnnotationArtifact` and
|
|
215
|
+
`readExternalReferenceArtifact`, whose success result is `{ ok: true, artifact }`.
|
|
216
|
+
|
|
217
|
+
It is wrong for the canonical frontend-contract readers. Their success results
|
|
218
|
+
are:
|
|
219
|
+
|
|
220
|
+
- `readPersistentBaselineContract` returns `{ ok: true, contract }`
|
|
221
|
+
- `readPerChangeContract` returns `{ ok: true, contract }`
|
|
222
|
+
|
|
223
|
+
Neither returns `artifact`. The script therefore pushed `undefined` for every
|
|
224
|
+
valid contract, and the later `item.contractClass` evaluation threw
|
|
225
|
+
`Cannot read properties of undefined (reading 'contractClass')`. This is why the
|
|
226
|
+
Windows and Ubuntu jobs failed after otherwise running the tutorials.
|
|
227
|
+
|
|
228
|
+
Reproduced against the three real contract manifests written by a local
|
|
229
|
+
scenario 2 run:
|
|
230
|
+
|
|
231
|
+
All three returned `undefined` from the old helper, and evaluating
|
|
232
|
+
`contractClass` on that value threw
|
|
233
|
+
`Cannot read properties of undefined (reading 'contractClass')`. The fixed
|
|
234
|
+
reader returned a defined contract for each:
|
|
235
|
+
|
|
236
|
+
1. the per-change contract promoted by the tutorial: `change`
|
|
237
|
+
2. `tutorial-baseline/v09-tutorial-baseline`: `baseline`
|
|
238
|
+
3. `tutorial-initial-change/v09-tutorial-initial-change`: `change`
|
|
239
|
+
|
|
240
|
+
- `CONTRACTCLASS_CRASH_REPRODUCIBLE_BEFORE_FIX`: true
|
|
241
|
+
- `CONTRACTCLASS_CRASH_CLOSED`: true
|
|
242
|
+
|
|
243
|
+
## 11. Contract-reader correction
|
|
244
|
+
|
|
245
|
+
A dedicated canonical contract reader was added. No optional-chaining
|
|
246
|
+
workaround was used, no raw JSON was parsed to choose a reader, and no third
|
|
247
|
+
contract validator was introduced:
|
|
248
|
+
|
|
249
|
+
```js
|
|
250
|
+
async function readContract(file) {
|
|
251
|
+
const baseline = await readPersistentBaselineContract(file);
|
|
252
|
+
if (baseline.ok) return baseline.contract;
|
|
253
|
+
const change = await readPerChangeContract(file);
|
|
254
|
+
if (change.ok) return change.contract;
|
|
255
|
+
fail(`canonical contract readers rejected ${file}: baseline=${baseline.reason}; change=${change.reason}`);
|
|
256
|
+
}
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
Trying each canonical validator is what decides the contract class, so the raw
|
|
260
|
+
`contractClass` dispatch was removed. `jsonFile()` became unused and was
|
|
261
|
+
deleted, along with the now-unused `readFile` import. A later-unused `sha256()`
|
|
262
|
+
helper was also removed. `BASELINE_READER_RESULT_PROPERTY` and
|
|
263
|
+
`CHANGE_READER_RESULT_PROPERTY` are both `contract`.
|
|
264
|
+
|
|
265
|
+
## 12. Two further readiness verifier defects found while proving the fix
|
|
266
|
+
|
|
267
|
+
Once the `contractClass` crash was closed, the local run reached scenario 3 and
|
|
268
|
+
scenario 4 evidence checks for the first time. Both were broken in the same
|
|
269
|
+
family as the contract-reader defect: the script read canonical artifacts
|
|
270
|
+
through a shape that does not exist.
|
|
271
|
+
|
|
272
|
+
### 12.1 Reference lifecycle compared as a string
|
|
273
|
+
|
|
274
|
+
The script used `item.lifecycle === 'approved'` and
|
|
275
|
+
`item.lifecycle === 'imported'`. The canonical contract in
|
|
276
|
+
`src/domain/externalReference.ts` is:
|
|
277
|
+
|
|
278
|
+
```ts
|
|
279
|
+
export interface ImportedExternalReferenceArtifact extends ExternalReferenceArtifactBase {
|
|
280
|
+
lifecycle: { state: 'imported' };
|
|
281
|
+
image: ExternalReferenceImageReference;
|
|
282
|
+
}
|
|
283
|
+
export interface ApprovedExternalReferenceArtifact extends ExternalReferenceArtifactBase {
|
|
284
|
+
lifecycle: { state: 'approved'; approvedAt: string };
|
|
285
|
+
sourceReference: ExternalReferenceSourceReference;
|
|
286
|
+
}
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
`lifecycle` is an object, so both comparisons were always false and scenario 3
|
|
290
|
+
could never pass. Verified against real evidence: both references reported
|
|
291
|
+
`oldStringCompareWorks: false`.
|
|
292
|
+
|
|
293
|
+
This was never reached in run `35527166495` because Windows and Ubuntu crashed
|
|
294
|
+
in scenario 2 and macOS failed in scenario 2.
|
|
295
|
+
|
|
296
|
+
Corrected to use the canonical exported type guards
|
|
297
|
+
`isApprovedExternalReferenceArtifact` and `isImportedExternalReferenceArtifact`
|
|
298
|
+
rather than a locally re-derived check.
|
|
299
|
+
|
|
300
|
+
### 12.2 The materialized image digest comparison never executed
|
|
301
|
+
|
|
302
|
+
The scenario 4 check was:
|
|
303
|
+
|
|
304
|
+
```js
|
|
305
|
+
const imagePath = (reference) => reference.image?.path ? path.join(...) : undefined;
|
|
306
|
+
const sourceImage = imagePath(approved);
|
|
307
|
+
const revisionImage = imagePath(imported[0]);
|
|
308
|
+
if (sourceImage && revisionImage && sha256(...) !== sha256(...)) fail(...);
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
An approved artifact has no top-level `image`; it carries
|
|
312
|
+
`sourceReference.image`. `sourceImage` was therefore always `undefined`, and the
|
|
313
|
+
`sourceImage && revisionImage` guard made the comparison a silent no-op. The
|
|
314
|
+
check reported success while proving nothing, which is exactly the
|
|
315
|
+
absent-evidence-as-PASS failure the evidence-honesty rules forbid. Verified
|
|
316
|
+
against real evidence: the approved artifact reported `hasTopLevelImage: false`.
|
|
317
|
+
|
|
318
|
+
Corrected to compare the canonical identity-bearing digests directly, with no
|
|
319
|
+
file re-hashing and no filesystem path construction:
|
|
320
|
+
|
|
321
|
+
- source: `approved.sourceReference.image.sha256`
|
|
322
|
+
- materialized: the successor's `image.sha256`
|
|
323
|
+
|
|
324
|
+
A missing digest on either side now fails explicitly instead of being skipped.
|
|
325
|
+
|
|
326
|
+
### 12.3 Imported-reference count assumption
|
|
327
|
+
|
|
328
|
+
The scenario 4 check also required exactly one imported reference. Real
|
|
329
|
+
evidence shows a materialization target holds three references: the original
|
|
330
|
+
source import, the approval, and the materialized successor. So
|
|
331
|
+
`imported.length !== 1` would have failed even after the lifecycle fix.
|
|
332
|
+
|
|
333
|
+
The successor is now identified by the property that actually distinguishes it,
|
|
334
|
+
namely that it carries requirements, while the reference the approval came from
|
|
335
|
+
carries none. Observed: `importedCount: 2`, `materializedCount: 1`,
|
|
336
|
+
`digestsMatch: true`.
|
|
337
|
+
|
|
338
|
+
### 12.4 Diagnosability
|
|
339
|
+
|
|
340
|
+
The scenario 3 and scenario 4 checks previously collapsed several distinct
|
|
341
|
+
conditions into one generic message such as
|
|
342
|
+
`reference authoring invariants failed`. Each condition now fails with its own
|
|
343
|
+
message naming the actual cause and the observed counts.
|
|
344
|
+
|
|
345
|
+
## 13. Local four-tutorial proof
|
|
346
|
+
|
|
347
|
+
`npm run build` was run first, because `scripts/run-v09-tutorial-readiness.mjs`
|
|
348
|
+
imports `../dist/index.js`.
|
|
349
|
+
|
|
350
|
+
Before running the tutorials, all four scenarios were validated against the
|
|
351
|
+
released lab:
|
|
352
|
+
|
|
353
|
+
```
|
|
354
|
+
npx --yes @dailephd/my-dev-kit-lab@0.4.9 tutorial validate --scenario <file> --target-contract <generated> --json
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
- `01-annotation-basics`: `status: valid`, `errors: []`
|
|
358
|
+
- `02-runtime-intent-contract`: `status: valid`, `errors: []`
|
|
359
|
+
- `03-reference-authoring`: `status: valid`, `errors: []`
|
|
360
|
+
- `04-reference-materialization`: `status: valid`, `errors: []`
|
|
361
|
+
|
|
362
|
+
This also proves the installed v0.4.9 validator accepts the exact released
|
|
363
|
+
`select-option` shape, because every migrated step uses it.
|
|
364
|
+
|
|
365
|
+
Static workaround audit across all four scenario files:
|
|
366
|
+
|
|
367
|
+
- `COMBOBOX_PRESS_ACTION_COUNT`: 0
|
|
368
|
+
- `select-option` actions: 37
|
|
369
|
+
- Steps satisfying the reading-time rule: 210 of 210
|
|
370
|
+
|
|
371
|
+
Full run, into a clean scratch output outside tracked repository files:
|
|
372
|
+
|
|
373
|
+
```
|
|
374
|
+
node scripts/run-v09-tutorial-readiness.mjs .my-dev-kit-workflow/adhoc/v09-final-readiness/tutorials-run
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
Result: exit 0, with every required condition met.
|
|
378
|
+
|
|
379
|
+
- `observer-v09-annotation-basics`: `passed`, `cleanupErrors: []`
|
|
380
|
+
- `observer-v09-runtime-contract`: `passed`, `cleanupErrors: []`
|
|
381
|
+
- `observer-v09-reference-authoring`: `passed`, `cleanupErrors: []`
|
|
382
|
+
- `observer-v09-reference-materialization`: `passed`, `cleanupErrors: []`
|
|
383
|
+
- `demoSourceImmutable`: true
|
|
384
|
+
- `repositoryUnchanged`: true
|
|
385
|
+
- Tracked demo digest identical before and after: 19 files,
|
|
386
|
+
`3a65f1c822faaddd958d4f4f20ddedcbf415bd4d34de67bf75a34ddc35c32bef`
|
|
387
|
+
|
|
388
|
+
One earlier local attempt failed on the final
|
|
389
|
+
`repository status changed during tutorial readiness` guard. That was caused by
|
|
390
|
+
this report being written while the run was in progress, not by the product or
|
|
391
|
+
the scenarios. The guard behaved correctly. The run above was performed with a
|
|
392
|
+
quiescent worktree.
|
|
393
|
+
|
|
394
|
+
## 14. Canonical Observer evidence proof
|
|
395
|
+
|
|
396
|
+
Every scenario's evidence was read back through the canonical readers.
|
|
397
|
+
|
|
398
|
+
Scenario 2, the contract verifier gate, reached and passed canonical contract
|
|
399
|
+
verification with no `contractClass` crash:
|
|
400
|
+
|
|
401
|
+
- 3 contract manifests read through the canonical readers
|
|
402
|
+
- promoted per-change contract found with exactly 2 clauses
|
|
403
|
+
- no `inspect` clause present
|
|
404
|
+
- no `remove` clause present
|
|
405
|
+
- baseline contract `v09-tutorial-baseline` preserved
|
|
406
|
+
|
|
407
|
+
Scenario 4, the reference verifier gate:
|
|
408
|
+
|
|
409
|
+
- approved source reference exists, carrying 0 requirements
|
|
410
|
+
- 2 imported references exist: the original source import and the successor
|
|
411
|
+
- exactly 1 materialized successor, carrying 1 requirement
|
|
412
|
+
- image digest unchanged and now actually compared:
|
|
413
|
+
`4bdb94db1096532dd886b7b8bd9ea4018f44ff0e3debb24e92cbf6132123538d`
|
|
414
|
+
on both the approved source reference and the materialized successor
|
|
415
|
+
|
|
416
|
+
Scenario 1: 2 annotations with a valid supersession chain and all five mark
|
|
417
|
+
kinds. Scenario 3: one external-reference annotation with exactly 7 items and an
|
|
418
|
+
approved reference carrying 0 requirements.
|
|
419
|
+
|
|
420
|
+
## 15. Full local regression
|
|
421
|
+
|
|
422
|
+
- `npm run typecheck`: PASS
|
|
423
|
+
- `npm run lint`: PASS
|
|
424
|
+
- `npm test`: PASS, 1453 tests in 89 files
|
|
425
|
+
- `npm run test:browser`: PASS, 275 tests in 29 files
|
|
426
|
+
- `npm run test:security`: PASS, 167 tests in 16 files plus 77 tests in 3 files
|
|
427
|
+
- `npm run build`: PASS
|
|
428
|
+
- `npm run check:docs`: PASS, 17 required files
|
|
429
|
+
- `npm pack --dry-run`: PASS, 366 files
|
|
430
|
+
|
|
431
|
+
`tests/unit/v09TutorialScenarios.test.ts` passes, including pacing. The
|
|
432
|
+
candidate-job failure is closed.
|
|
433
|
+
|
|
434
|
+
## 16. Packed smoke results
|
|
435
|
+
|
|
436
|
+
One local candidate tarball was built into the approved workflow root and used
|
|
437
|
+
for all three smokes. Process-local `TEMP`/`TMP` were redirected into that root
|
|
438
|
+
so no consumer install or browser profile was created elsewhere. No user or
|
|
439
|
+
machine environment variable was changed.
|
|
440
|
+
|
|
441
|
+
- Tarball: `dailephd-my-frontend-observer-0.8.1.tgz`
|
|
442
|
+
- SHA-256: `8f8bcd5aab0607df35c9a56fcfa9ece9f286c115910c6e4b50b2384adf4469ad`
|
|
443
|
+
- File count: 366
|
|
444
|
+
|
|
445
|
+
Results:
|
|
446
|
+
|
|
447
|
+
- Packed observation smoke: PASS, `"pass": true`, real Chromium
|
|
448
|
+
`153.0.8010.12`, `targetsFilePathLeaked: false`
|
|
449
|
+
- Packed viewer smoke: PASS
|
|
450
|
+
- Packed v0.9 annotation smoke: PASS
|
|
451
|
+
|
|
452
|
+
This local tarball is local proof only. It is not the final candidate. The
|
|
453
|
+
authoritative exact candidate is the one the workflow builds.
|
|
454
|
+
|
|
455
|
+
## 17. Changed files
|
|
456
|
+
|
|
457
|
+
- `examples/v09-demo/tutorials/02-runtime-intent-contract.json`
|
|
458
|
+
- `examples/v09-demo/tutorials/03-reference-authoring.json`
|
|
459
|
+
- `examples/v09-demo/tutorials/04-reference-materialization.json`
|
|
460
|
+
- `examples/v09-demo/README.md`
|
|
461
|
+
- `examples/v09-demo/scripts/generate-tutorial-target.mjs`
|
|
462
|
+
- `scripts/run-v09-tutorial-readiness.mjs`
|
|
463
|
+
- `tests/unit/v09TutorialScenarios.test.ts`
|
|
464
|
+
- `tests/unit/v09TutorialTargetContract.test.ts`
|
|
465
|
+
- `docs/WORKFLOWS.md`
|
|
466
|
+
- `docs/CURRENT_STATE.md`
|
|
467
|
+
- `docs/PROJECT_OVERVIEW.md`
|
|
468
|
+
- `README.md`
|
|
469
|
+
- `docs/reports/v0.9-final-readiness-corrections.md` (this report)
|
|
470
|
+
|
|
471
|
+
`examples/v09-demo/tutorials/01-annotation-basics.json` was deliberately not
|
|
472
|
+
modified.
|
|
473
|
+
|
|
474
|
+
`.github/workflows/pre-release-readiness.yml` was inspected and needed no
|
|
475
|
+
change. It never pinned the lab version; it delegates to
|
|
476
|
+
`scripts/run-v09-tutorial-readiness.mjs`, where the pin was updated. Its exact
|
|
477
|
+
lab Chromium installation already uses `playwright@1.60.0`, which v0.4.9 still
|
|
478
|
+
declares.
|
|
479
|
+
|
|
480
|
+
## 18. Test changes
|
|
481
|
+
|
|
482
|
+
- `select-option` was added to the released lab action allowlist. All previously
|
|
483
|
+
released actions were kept.
|
|
484
|
+
- A native-select portability regression test was added. It fails if any
|
|
485
|
+
scenario uses `action.type = "press"` against a locator with `kind = "role"`
|
|
486
|
+
and `role = "combobox"`, which freezes the rule that a native `<select>`
|
|
487
|
+
semantic choice must use `select-option`. It does not ban `press` generally.
|
|
488
|
+
- The same test asserts the v0.4.9 value-only contract, so a scenario cannot
|
|
489
|
+
acquire `label`, `index` or `values`.
|
|
490
|
+
- The guard was checked against a synthetic pre-migration step to confirm it is
|
|
491
|
+
not vacuous: it fires on a combobox `press`, and does not fire on a
|
|
492
|
+
`select-option` or on a legitimate non-combobox `press`.
|
|
493
|
+
|
|
494
|
+
## 19. Scope audit
|
|
495
|
+
|
|
496
|
+
- `MY_DEV_KIT_LAB_VERSION`: `0.4.9`, pinned exactly
|
|
497
|
+
- `NATIVE_SELECT_KEYBOARD_WORKAROUNDS_REMAINING`: 0
|
|
498
|
+
- `select-option` used semantically, one canonical scenario set
|
|
499
|
+
- Pacing test passes and was not weakened
|
|
500
|
+
- Contract verifier uses the canonical contract readers correctly
|
|
501
|
+
- No `.artifact` extraction from contract-reader success results
|
|
502
|
+
- No product `<select>` redesign, no custom dropdown, no tutorial-only control
|
|
503
|
+
- No new Observer dependency; `@dailephd/my-dev-kit-lab` is not a dependency
|
|
504
|
+
- Demo still excluded from the npm package: 0 of 365 packaged files match
|
|
505
|
+
`v09-demo`
|
|
506
|
+
- Package version remains `0.8.1`; v0.9 remains unreleased; `master` not pushed
|
|
507
|
+
- No Observer product semantics, artifact schema or command surface changed
|
|
508
|
+
|
|
509
|
+
## 20. Remote readiness continuation
|
|
510
|
+
|
|
511
|
+
Run `35527166495` cannot contribute passing evidence to the final candidate.
|
|
512
|
+
The scenario files changed, the lab version changed, the readiness verifier
|
|
513
|
+
changed and the candidate bytes changed, so rerunning only the failed jobs
|
|
514
|
+
against the stale commit would prove nothing.
|
|
515
|
+
|
|
516
|
+
A new complete workflow execution is required on the correction commit,
|
|
517
|
+
covering:
|
|
518
|
+
|
|
519
|
+
1. the candidate/static job, which must now get past `npm test` and build the
|
|
520
|
+
exact candidate tarball
|
|
521
|
+
2. Windows, Linux and macOS exact-package smokes, which run 35527166495 never
|
|
522
|
+
reached
|
|
523
|
+
3. Windows, Linux and macOS Observer tutorial readiness
|
|
524
|
+
|
|
525
|
+
`RUN_A` is the first complete pass of the full workflow on one exact
|
|
526
|
+
post-correction commit. Only after `RUN_A` exists may
|
|
527
|
+
`docs/reports/v0.9-final-pre-release-readiness.md` be written. Because
|
|
528
|
+
`docs/reports/` is inside the npm package, committing that report changes the
|
|
529
|
+
candidate bytes, so a second full workflow run `RUN_B` is required on the exact
|
|
530
|
+
report-containing commit.
|