@dailephd/my-frontend-observer 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/README.md +17 -7
- package/dist/application/visualChangeAgentHandoffService.d.ts +28 -0
- package/dist/application/visualChangeAgentHandoffService.js +111 -0
- package/dist/application/visualChangeAgentHandoffService.js.map +1 -0
- package/dist/application/visualChangeProjectWorkflowService.d.ts +95 -0
- package/dist/application/visualChangeProjectWorkflowService.js +376 -0
- package/dist/application/visualChangeProjectWorkflowService.js.map +1 -0
- package/dist/application/visualChangeReviewService.d.ts +50 -0
- package/dist/application/visualChangeReviewService.js +69 -0
- package/dist/application/visualChangeReviewService.js.map +1 -0
- package/dist/application/visualChangeWorkflowPersistenceService.d.ts +26 -0
- package/dist/application/visualChangeWorkflowPersistenceService.js +15 -0
- package/dist/application/visualChangeWorkflowPersistenceService.js.map +1 -0
- package/dist/artifacts/visualChangeWorkflowArtifactReader.d.ts +9 -0
- package/dist/artifacts/visualChangeWorkflowArtifactReader.js +47 -0
- package/dist/artifacts/visualChangeWorkflowArtifactReader.js.map +1 -0
- package/dist/artifacts/visualChangeWorkflowArtifactWriter.d.ts +20 -0
- package/dist/artifacts/visualChangeWorkflowArtifactWriter.js +41 -0
- package/dist/artifacts/visualChangeWorkflowArtifactWriter.js.map +1 -0
- package/dist/cli.js +510 -508
- package/dist/cli.js.map +1 -1
- package/dist/domain/visualChangeAgentHandoff.d.ts +82 -0
- package/dist/domain/visualChangeAgentHandoff.js +80 -0
- package/dist/domain/visualChangeAgentHandoff.js.map +1 -0
- package/dist/domain/visualChangeAgentHandoffSerialization.d.ts +2 -0
- package/dist/domain/visualChangeAgentHandoffSerialization.js +11 -0
- package/dist/domain/visualChangeAgentHandoffSerialization.js.map +1 -0
- package/dist/domain/visualChangeCycle.d.ts +8 -0
- package/dist/domain/visualChangeCycle.js +7 -0
- package/dist/domain/visualChangeCycle.js.map +1 -0
- package/dist/domain/visualChangeWorkflow.d.ts +125 -0
- package/dist/domain/visualChangeWorkflow.js +109 -0
- package/dist/domain/visualChangeWorkflow.js.map +1 -0
- package/dist/domain/visualChangeWorkflowIdentity.d.ts +5 -0
- package/dist/domain/visualChangeWorkflowIdentity.js +24 -0
- package/dist/domain/visualChangeWorkflowIdentity.js.map +1 -0
- package/dist/index.d.ts +21 -1
- package/dist/index.js +12 -1
- package/dist/index.js.map +1 -1
- package/dist/projectWorkflow/projectPaths.d.ts +3 -0
- package/dist/projectWorkflow/projectPaths.js +7 -0
- package/dist/projectWorkflow/projectPaths.js.map +1 -1
- package/dist/viewer/assets/index-DglJ6f28.css +1 -0
- package/dist/viewer/assets/index-DsODREY5.js +9 -0
- package/dist/viewer/index.html +2 -2
- package/dist/viewer/sw.js +1 -1
- package/dist/viewerServer/evidence/classify.d.ts +3 -1
- package/dist/viewerServer/evidence/classify.js +10 -0
- package/dist/viewerServer/evidence/classify.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/projection.d.ts +5 -0
- package/dist/viewerServer/evidence/projection.js +19 -0
- package/dist/viewerServer/evidence/projection.js.map +1 -1
- package/dist/viewerServer/evidence/visualChangeWorkflowView.d.ts +31 -0
- package/dist/viewerServer/evidence/visualChangeWorkflowView.js +36 -0
- package/dist/viewerServer/evidence/visualChangeWorkflowView.js.map +1 -0
- package/dist/viewerServer/httpServer.js +323 -1
- package/dist/viewerServer/httpServer.js.map +1 -1
- package/dist/viewerServer/referenceApproval.d.ts +22 -0
- package/dist/viewerServer/referenceApproval.js +42 -0
- package/dist/viewerServer/referenceApproval.js.map +1 -0
- package/dist/viewerServer/referenceVisualChangeAuthoring.d.ts +28 -0
- package/dist/viewerServer/referenceVisualChangeAuthoring.js +134 -0
- package/dist/viewerServer/referenceVisualChangeAuthoring.js.map +1 -0
- package/dist/viewerServer/runtimeVisualChangeAuthoring.d.ts +33 -0
- package/dist/viewerServer/runtimeVisualChangeAuthoring.js +81 -0
- package/dist/viewerServer/runtimeVisualChangeAuthoring.js.map +1 -0
- package/dist/viewerServer/visualChangeAuthoring.d.ts +46 -0
- package/dist/viewerServer/visualChangeAuthoring.js +63 -0
- package/dist/viewerServer/visualChangeAuthoring.js.map +1 -0
- package/dist/viewerServer/visualChangeHandoff.d.ts +23 -0
- package/dist/viewerServer/visualChangeHandoff.js +31 -0
- package/dist/viewerServer/visualChangeHandoff.js.map +1 -0
- package/dist/viewerServer/visualChangeReview.d.ts +30 -0
- package/dist/viewerServer/visualChangeReview.js +46 -0
- package/dist/viewerServer/visualChangeReview.js.map +1 -0
- package/docs/ARCHITECTURE.md +17 -5
- package/docs/CI_CD.md +33 -1
- package/docs/COMMANDS.md +19 -5
- package/docs/CONTRACTS.md +38 -4
- package/docs/CURRENT_STATE.md +92 -11
- package/docs/DEVELOPMENT.md +32 -2
- package/docs/PROJECT_MILESTONES.md +28 -0
- package/docs/PROJECT_OVERVIEW.md +36 -14
- package/docs/QUICKSTART.md +7 -3
- package/docs/RELEASE.md +15 -11
- package/docs/ROADMAP.md +55 -2
- package/docs/SECURITY.md +25 -3
- package/docs/WORKFLOWS.md +29 -3
- package/docs/plans/v0.10-implementation-plan.md +1509 -0
- package/docs/plans/v0.9.1-implementation-plan.md +468 -0
- package/docs/reports/v0.10-batch1-visual-change-workflow-foundation.md +102 -0
- package/docs/reports/v0.10-batch2-project-composition-check-recording.md +103 -0
- package/docs/reports/v0.10-batch3-viewer-visual-change-workspace.md +93 -0
- package/docs/reports/v0.10-batch4-actual-frontend-entry.md +59 -0
- package/docs/reports/v0.10-batch5-reference-driven-entry.md +238 -0
- package/docs/reports/v0.10-batch6-coding-agent-handoff.md +85 -0
- package/docs/reports/v0.10-batch7-correction-review-acceptance.md +145 -0
- package/docs/reports/v0.10-batch8-integrated-acceptance.md +109 -0
- package/docs/reports/v0.10-implementation-completeness-documentation-reconciliation.md +344 -0
- package/docs/reports/v0.10-pre-release-readiness.md +120 -0
- package/docs/reports/v0.10-release-preparation.md +70 -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-BN41MI7m.css +0 -1
- package/dist/viewer/assets/index-CkKXnlrI.js +0 -9
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
# v0.9.1 Batch 2 report: hard-gate validation integration
|
|
2
|
+
|
|
3
|
+
## 1. VERDICT
|
|
4
|
+
|
|
5
|
+
`PASS_V0_9_1_PWA_HARD_GATE_ISOLATION`
|
|
6
|
+
|
|
7
|
+
The isolated PWA hard gate is now a permanent npm command. It is part of
|
|
8
|
+
`npm run test:security`, and through that it is part of pre-release readiness.
|
|
9
|
+
The full regression chain passed. No production file, dependency, or version
|
|
10
|
+
changed. v0.9.1 implementation is complete. v0.9.1 is not released.
|
|
11
|
+
|
|
12
|
+
## 2. Repository identity
|
|
13
|
+
|
|
14
|
+
1. Repository: `C:\Users\daile\Projects\my-frontend-observer`
|
|
15
|
+
2. Branch: `feature/v0.9.1-pwa-hard-gate-isolation`
|
|
16
|
+
3. Starting HEAD: `6874fd4b9690244673bd1b0e39bad0dd01cf397d` (Batch 1 commit)
|
|
17
|
+
4. Package version: `0.9.0` in `package.json`, in `package-lock.json`, and in
|
|
18
|
+
`package-lock.json` `packages[""]`
|
|
19
|
+
5. `docs/reports/v0.9-architecture-retrieval.md` is still marked skip-worktree
|
|
20
|
+
(`git ls-files -v` shows `S`). It was not touched.
|
|
21
|
+
6. Runtime: Node `v24.20.0`, Playwright `1.62.1`, Vitest `4.1.11`, Windows 11
|
|
22
|
+
|
|
23
|
+
## 3. Batch 1 entry gate
|
|
24
|
+
|
|
25
|
+
PASS. Batch 1 ended with `PASS_V0_9_1_BATCH1_PWA_HARD_GATE_ISOLATED` at
|
|
26
|
+
`6874fd4`. At the start of Batch 2 the worktree was clean and HEAD was that
|
|
27
|
+
commit. `tests/browser/pwaHardening.test.ts` still has every Batch 1 element: a
|
|
28
|
+
fresh evidence root, server, temporary persistent profile, and BrowserContext
|
|
29
|
+
for the gate. It also has the separate activation and control proofs, the shell
|
|
30
|
+
precache proof, the `/api/` cache exclusion proof, the live evidence proof, the
|
|
31
|
+
Node-side server-down proof, the offline shell reload, the stale-evidence
|
|
32
|
+
absence checks, and deterministic cleanup. Batch 2 did not change that file.
|
|
33
|
+
|
|
34
|
+
## 4. Root cause carried forward
|
|
35
|
+
|
|
36
|
+
1. `OLD_READINESS_PREDICATE`: `(await navigator.serviceWorker.getRegistration())?.active !== undefined`
|
|
37
|
+
2. `OLD_ACTIVE_VALUE_AT_FAILURE`: `null` (the worker was still installing)
|
|
38
|
+
3. `OLD_CLIENT_CONTROLLER_AT_FAILURE`: `null`
|
|
39
|
+
4. `WHY_OLD_PREDICATE_PASSED`: `null !== undefined` is `true`. The check passed
|
|
40
|
+
as soon as a registration existed, before activation or control. The server
|
|
41
|
+
then closed too early. The precache held only 5 entries, and the reload
|
|
42
|
+
failed with `net::ERR_CONNECTION_REFUSED`.
|
|
43
|
+
5. `CORRECT_ACTIVE_PROOF`: `registration.active !== null`, read from
|
|
44
|
+
`await navigator.serviceWorker.ready`
|
|
45
|
+
6. `CURRENT_CLIENT_CONTROL_PROOF`: `navigator.serviceWorker.controller !== null`
|
|
46
|
+
|
|
47
|
+
Shared state hid the bug in normal order. Earlier tests in the same describe
|
|
48
|
+
block had already activated a controlling worker on the same server origin.
|
|
49
|
+
Selected alone, the server starts on a new random port, so no worker existed yet
|
|
50
|
+
for that origin.
|
|
51
|
+
|
|
52
|
+
Classification remains `TEST_DEFECT`. No product defect was found.
|
|
53
|
+
|
|
54
|
+
## 5. Dedicated isolated command
|
|
55
|
+
|
|
56
|
+
`package.json` now has exactly one new script:
|
|
57
|
+
|
|
58
|
+
`"test:pwa-hard-gate": "vitest run --config vitest.browser.config.ts tests/browser/pwaHardening.test.ts -t \"HARD GATE\""`
|
|
59
|
+
|
|
60
|
+
No alias was added. The command exists because a passing full browser or
|
|
61
|
+
security suite does not prove that the hard gate can run on its own.
|
|
62
|
+
|
|
63
|
+
Direct runs after adding the script:
|
|
64
|
+
|
|
65
|
+
1. `npm run test:pwa-hard-gate` run 1: PASS (1 passed, 6 skipped)
|
|
66
|
+
2. `npm run test:pwa-hard-gate` run 2, straight after: PASS (1 passed,
|
|
67
|
+
6 skipped)
|
|
68
|
+
|
|
69
|
+
## 6. Security-suite integration
|
|
70
|
+
|
|
71
|
+
`test:security` now runs three stages joined with `&&`:
|
|
72
|
+
|
|
73
|
+
1. the existing unit security tests (unchanged)
|
|
74
|
+
2. the existing browser security tests, including the full
|
|
75
|
+
`tests/browser/pwaHardening.test.ts` (unchanged)
|
|
76
|
+
3. `npm run test:pwa-hard-gate` (new)
|
|
77
|
+
|
|
78
|
+
The isolated run is added on top. The full PWA file still runs in stage 2.
|
|
79
|
+
`test:browser` was not changed and still runs every `tests/browser/**/*.test.ts`
|
|
80
|
+
file, including the full PWA file.
|
|
81
|
+
|
|
82
|
+
## 7. Pre-release-readiness integration
|
|
83
|
+
|
|
84
|
+
1. `PRE_RELEASE_WORKFLOW_ALREADY_CALLS_TEST_SECURITY = true`. The `candidate`
|
|
85
|
+
job in `.github/workflows/pre-release-readiness.yml` has the step
|
|
86
|
+
`Security test suite (npm run test:security)`.
|
|
87
|
+
2. `WORKFLOW_YAML_CHANGE_REQUIRED = false`. Candidate readiness now gets the
|
|
88
|
+
isolated gate through the updated npm script. The workflow YAML was not
|
|
89
|
+
modified.
|
|
90
|
+
|
|
91
|
+
## 8. Full PWA file validation
|
|
92
|
+
|
|
93
|
+
`npx vitest run --config vitest.browser.config.ts tests/browser/pwaHardening.test.ts`
|
|
94
|
+
|
|
95
|
+
PASS. 7 passed.
|
|
96
|
+
|
|
97
|
+
## 9. Isolated hard-gate repeated validation
|
|
98
|
+
|
|
99
|
+
1. Direct run 1 (section 5): PASS
|
|
100
|
+
2. Direct run 2 (section 5): PASS
|
|
101
|
+
3. First step of the regression chain: PASS (1 passed, 6 skipped)
|
|
102
|
+
4. Inside `npm run test:security`: PASS (1 passed, 6 skipped)
|
|
103
|
+
5. Last step of the regression chain, after every full suite: PASS
|
|
104
|
+
(1 passed, 6 skipped)
|
|
105
|
+
|
|
106
|
+
Run 5 shows that the full suites did not become a hidden prerequisite again.
|
|
107
|
+
|
|
108
|
+
## 10. Browser-suite validation
|
|
109
|
+
|
|
110
|
+
`npm run test:browser`: PASS. 29 test files, 275 tests passed.
|
|
111
|
+
|
|
112
|
+
## 11. Security-suite validation
|
|
113
|
+
|
|
114
|
+
`npm run test:security`: PASS. The output shows all three stages ran:
|
|
115
|
+
|
|
116
|
+
1. unit security: 16 files, 168 tests passed
|
|
117
|
+
2. browser security: 3 files, 77 tests passed
|
|
118
|
+
3. the npm banner `> @dailephd/my-frontend-observer@0.9.0 test:pwa-hard-gate`,
|
|
119
|
+
then 1 file, 1 test passed, 6 skipped
|
|
120
|
+
|
|
121
|
+
Stage 3 was confirmed from the command output, not only from `package.json`.
|
|
122
|
+
|
|
123
|
+
## 12. Full unit regression
|
|
124
|
+
|
|
125
|
+
`npm test`: PASS. 89 test files, 1454 tests passed.
|
|
126
|
+
|
|
127
|
+
No repository test checks package script strings, so no static script test was
|
|
128
|
+
added. Running `npm run test:pwa-hard-gate` is the primary proof.
|
|
129
|
+
|
|
130
|
+
## 13. Build validation
|
|
131
|
+
|
|
132
|
+
`npm run build`: PASS. The Workbox precache still has 10 entries (7 unique
|
|
133
|
+
URLs). `sw.js` has no runtime caching rules.
|
|
134
|
+
|
|
135
|
+
## 14. Documentation validation
|
|
136
|
+
|
|
137
|
+
`npm run check:docs`: PASS (17 required files). It ran in the regression chain
|
|
138
|
+
after the documentation edits. It was run again after this report was written
|
|
139
|
+
(see section 19).
|
|
140
|
+
|
|
141
|
+
## 15. Package-boundary validation
|
|
142
|
+
|
|
143
|
+
`npm pack --dry-run`: PASS. Candidate filename
|
|
144
|
+
`dailephd-my-frontend-observer-0.9.0.tgz`, 369 files, 1.0 MB packed, 4.0 MB
|
|
145
|
+
unpacked.
|
|
146
|
+
|
|
147
|
+
The file list was searched for `tests/`, `.my-dev-kit-workflow`, `examples/`,
|
|
148
|
+
`pwa-profile`, `hard-gate`, and the agent-control files. The only match was
|
|
149
|
+
`docs/reports/v0.9.1-batch1-pwa-hard-gate-isolation.md`. That is a report
|
|
150
|
+
included by the existing `"files": ["dist", "README.md", "CHANGELOG.md", "docs",
|
|
151
|
+
"LICENSE"]` allowlist, like every other report. No tests, `examples/v09-demo`,
|
|
152
|
+
workflow state, Chromium profiles, or evidence roots are in the package.
|
|
153
|
+
|
|
154
|
+
## 16. Product-code audit
|
|
155
|
+
|
|
156
|
+
`git diff --name-only 6874fd4` shows no path under `src/`, `viewer/`, or
|
|
157
|
+
`.github/`. `viewer/vite.config.ts` and the service-worker caching policy were
|
|
158
|
+
not changed.
|
|
159
|
+
|
|
160
|
+
1. `PRODUCTION_FILES_CHANGED = false`
|
|
161
|
+
2. `PRODUCT_SEMANTICS_CHANGED = false`
|
|
162
|
+
3. `PRODUCT_DEFECT_DISCOVERED = false`
|
|
163
|
+
|
|
164
|
+
## 17. Dependency/version audit
|
|
165
|
+
|
|
166
|
+
1. `dependencies`, `devDependencies`, `peerDependencies`, and
|
|
167
|
+
`optionalDependencies` are the same as at `6874fd4`.
|
|
168
|
+
2. `package-lock.json` did not change.
|
|
169
|
+
3. The version is `0.9.0` in all three places.
|
|
170
|
+
4. No `npm version`, `npm publish`, tag, GitHub Release, or release branch.
|
|
171
|
+
|
|
172
|
+
## 18. Documentation reconciliation
|
|
173
|
+
|
|
174
|
+
1. `docs/CURRENT_STATE.md`: the v0.9.1 section now says implementation complete
|
|
175
|
+
and unreleased. It records the reproduction, the two-part root cause, the
|
|
176
|
+
new ownership and proofs, the command integration, and that production
|
|
177
|
+
behavior is unchanged. The planning background is kept below it.
|
|
178
|
+
2. `docs/ROADMAP.md`: only the v0.9.1 status wording changed, from planned to
|
|
179
|
+
implemented and unreleased. The objective, constraints, exclusions, and
|
|
180
|
+
acceptance are unchanged.
|
|
181
|
+
3. `docs/PROJECT_OVERVIEW.md`: v0.9.1 is complete but unreleased. PWA
|
|
182
|
+
hard/security acceptance no longer depends on prior test order or
|
|
183
|
+
persistent browser state. v0.10 is still future.
|
|
184
|
+
4. `docs/PROJECT_MILESTONES.md`: a status line was added to the existing
|
|
185
|
+
v0.9.1 maintenance note. It says the invariant is implemented and release is
|
|
186
|
+
pending. Milestone 9 semantics are unchanged.
|
|
187
|
+
5. `docs/DEVELOPMENT.md`: the gate-isolation section now gives
|
|
188
|
+
`npm run test:pwa-hard-gate`, says when to run it, and says it must pass on
|
|
189
|
+
its own.
|
|
190
|
+
6. `docs/CI_CD.md`: the v0.9.1 wording is now implemented. It says
|
|
191
|
+
`test:security` runs the isolated gate, that candidate readiness gets it
|
|
192
|
+
automatically, and that the workflow YAML did not change.
|
|
193
|
+
7. `CHANGELOG.md`: one maintenance bullet under `[Unreleased]`. No `0.9.1`
|
|
194
|
+
section was created.
|
|
195
|
+
|
|
196
|
+
`docs/plans/v0.9.1-implementation-plan.md`, the historical `docs/reports/v0.9-*.md`
|
|
197
|
+
reports, and the Batch 1 report were not changed.
|
|
198
|
+
|
|
199
|
+
The durable rule stays in `DEVELOPMENT.md`, `CI_CD.md`, and
|
|
200
|
+
`PROJECT_MILESTONES.md`: tests labeled `HARD GATE`, `SECURITY GATE`, or
|
|
201
|
+
`ACCEPTANCE GATE` must set up their own material prerequisites and pass on
|
|
202
|
+
their own from fresh state. It is now implemented policy.
|
|
203
|
+
|
|
204
|
+
## 19. Changed files
|
|
205
|
+
|
|
206
|
+
1. `package.json`
|
|
207
|
+
2. `CHANGELOG.md`
|
|
208
|
+
3. `docs/CURRENT_STATE.md`
|
|
209
|
+
4. `docs/ROADMAP.md`
|
|
210
|
+
5. `docs/PROJECT_MILESTONES.md`
|
|
211
|
+
6. `docs/PROJECT_OVERVIEW.md`
|
|
212
|
+
7. `docs/DEVELOPMENT.md`
|
|
213
|
+
8. `docs/CI_CD.md`
|
|
214
|
+
9. `docs/reports/v0.9.1-batch2-hard-gate-validation-integration.md`
|
|
215
|
+
|
|
216
|
+
Generated paths:
|
|
217
|
+
|
|
218
|
+
1. Regression logs in the Claude Code session scratchpad `regression\` folder,
|
|
219
|
+
outside the repository and not committed
|
|
220
|
+
2. `dist/` from `npm run build` (ignored build output)
|
|
221
|
+
3. Temporary test directories under the OS temp directory. They were all
|
|
222
|
+
removed. After every run, no `my-frontend-observer-pwa-hard-gate-profile-*`,
|
|
223
|
+
`my-frontend-observer-pwa-hard-gate-evidence-*`, or
|
|
224
|
+
`my-frontend-observer-pwa-profile-*` directories remained.
|
|
225
|
+
4. `npm pack --dry-run` wrote no tarball.
|
|
226
|
+
|
|
227
|
+
Full regression order, all exit 0:
|
|
228
|
+
|
|
229
|
+
1. `npm run test:pwa-hard-gate`
|
|
230
|
+
2. `npm run typecheck`
|
|
231
|
+
3. `npm run lint`
|
|
232
|
+
4. `npm test`
|
|
233
|
+
5. `npm run test:browser`
|
|
234
|
+
6. `npm run test:security`
|
|
235
|
+
7. `npm run build`
|
|
236
|
+
8. `npm run check:docs`
|
|
237
|
+
9. `npm pack --dry-run`
|
|
238
|
+
10. `npm run test:pwa-hard-gate`
|
|
239
|
+
|
|
240
|
+
After this report was written, `npm run check:docs` and `git diff --check`
|
|
241
|
+
were run again before the commit.
|
|
242
|
+
|
|
243
|
+
## 20. Remaining release-readiness work
|
|
244
|
+
|
|
245
|
+
Not done in this batch, and not claimed:
|
|
246
|
+
|
|
247
|
+
1. the v0.9.1 integration PR from this feature branch into `master`, with
|
|
248
|
+
required PR CI
|
|
249
|
+
2. exact-candidate cross-platform pre-release readiness: one tarball, hashed,
|
|
250
|
+
installed on Windows, Linux, and macOS. `test:security` now includes the
|
|
251
|
+
isolated gate on each platform.
|
|
252
|
+
3. release preparation: version bump to `0.9.1`, a `0.9.1` CHANGELOG section,
|
|
253
|
+
and final state documents
|
|
254
|
+
4. user-authorized publication, tag, and GitHub Release
|
|
255
|
+
|
|
256
|
+
Notes carried from Batch 1:
|
|
257
|
+
|
|
258
|
+
1. The focused `/api/` cache test still uses the old weak `?.active !== undefined`
|
|
259
|
+
wait. It is correct in file order because it runs after the registration
|
|
260
|
+
test on the same origin. It is not labeled as a gate.
|
|
261
|
+
2. `.my-dev-kit-workflow/v0.8/batch-08/pwa-profile` still exists on disk. No
|
|
262
|
+
test uses it.
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
# v0.9.1 Pre-release Readiness
|
|
2
|
+
|
|
3
|
+
## 1. VERDICT
|
|
4
|
+
|
|
5
|
+
`PASS_V0_9_1_PR_RUN_A_COMPLETE`
|
|
6
|
+
|
|
7
|
+
This report records the first complete cross-platform readiness proof for the
|
|
8
|
+
v0.9.1 maintenance candidate. It is not final merged-master readiness. A new
|
|
9
|
+
complete PR workflow is required after this report is committed because the
|
|
10
|
+
report changes the candidate package.
|
|
11
|
+
|
|
12
|
+
## 2. Repository identity
|
|
13
|
+
|
|
14
|
+
- Repository: `dailephd/my-frontend-observer`
|
|
15
|
+
- Local repository: `C:\Users\daile\Projects\my-frontend-observer`
|
|
16
|
+
- Branch: `feature/v0.9.1-pwa-hard-gate-isolation`
|
|
17
|
+
- Implementation entry HEAD: `fbc081d6387cdb3aeacd79f5ed82bdcd8812fd93`
|
|
18
|
+
- Base before integration: `985d0ce47a070fd9f84eae478f4098df00d57bd8`
|
|
19
|
+
- Feature contains base: PASS
|
|
20
|
+
|
|
21
|
+
## 3. v0.9.1 maintenance scope
|
|
22
|
+
|
|
23
|
+
v0.9.1 is a test and validation maintenance patch. It makes the PWA server-down
|
|
24
|
+
HARD GATE independently reproducible and adds the permanent command
|
|
25
|
+
`npm run test:pwa-hard-gate`. No production PWA behavior is intentionally
|
|
26
|
+
changed.
|
|
27
|
+
|
|
28
|
+
## 4. v0.9.0 baseline
|
|
29
|
+
|
|
30
|
+
The package baseline remains `0.9.0`. `package.json`, `package-lock.json`, and
|
|
31
|
+
`package-lock.json` `packages[""].version` all remain `0.9.0`.
|
|
32
|
+
|
|
33
|
+
## 5. Batch 1 implementation
|
|
34
|
+
|
|
35
|
+
Batch 1 is recorded in
|
|
36
|
+
`docs/reports/v0.9.1-batch1-pwa-hard-gate-isolation.md`. The implementation
|
|
37
|
+
isolates the server-down PWA test from prior test order, persistent Chromium
|
|
38
|
+
profiles, and prior service-worker cache state.
|
|
39
|
+
|
|
40
|
+
## 6. Batch 2 permanent gate integration
|
|
41
|
+
|
|
42
|
+
Batch 2 is recorded in
|
|
43
|
+
`docs/reports/v0.9.1-batch2-hard-gate-validation-integration.md`. The isolated
|
|
44
|
+
gate is exposed as `npm run test:pwa-hard-gate` and is included in
|
|
45
|
+
`npm run test:security`. No workflow YAML change was required.
|
|
46
|
+
|
|
47
|
+
## 7. Product-change audit
|
|
48
|
+
|
|
49
|
+
The implementation diff changes tests, scripts/package metadata, and
|
|
50
|
+
documentation only. No intended changes occur under `src/`, `viewer/src/`, or
|
|
51
|
+
`viewer/vite.config.ts`.
|
|
52
|
+
|
|
53
|
+
- `PRODUCT_FILES_CHANGED = false`
|
|
54
|
+
- `PRODUCT_SEMANTICS_CHANGED = false`
|
|
55
|
+
- `PRODUCT_DEFECT_DISCOVERED = false`
|
|
56
|
+
- `PRODUCT_CHANGE_REQUIRED = false`
|
|
57
|
+
|
|
58
|
+
## 8. Isolated hard-gate invariant
|
|
59
|
+
|
|
60
|
+
The prior readiness predicate was:
|
|
61
|
+
|
|
62
|
+
```text
|
|
63
|
+
registration?.active !== undefined
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
At failure time, active registration state was `null` and the current page
|
|
67
|
+
controller was `null`. The old predicate falsely passed because `null !==
|
|
68
|
+
undefined`. The corrected proof requires:
|
|
69
|
+
|
|
70
|
+
```text
|
|
71
|
+
registration.active !== null
|
|
72
|
+
navigator.serviceWorker.controller !== null
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
The experiment also proves shell precache, zero `/api/` cache entries, live
|
|
76
|
+
evidence visibility, actual server unavailability, offline shell rendering,
|
|
77
|
+
evidence becoming unavailable, and stale evidence remaining absent.
|
|
78
|
+
|
|
79
|
+
## 9. Local validation
|
|
80
|
+
|
|
81
|
+
All required local commands passed:
|
|
82
|
+
|
|
83
|
+
```text
|
|
84
|
+
npm run test:pwa-hard-gate
|
|
85
|
+
npm run typecheck
|
|
86
|
+
npm run lint
|
|
87
|
+
npm test
|
|
88
|
+
npm run test:browser
|
|
89
|
+
npm run test:security
|
|
90
|
+
npm run build
|
|
91
|
+
npm run check:docs
|
|
92
|
+
npm pack --dry-run
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
The local security chain executed and passed `npm run test:pwa-hard-gate`.
|
|
96
|
+
`LOCAL_SECURITY_CHAIN_ISOLATED_HARD_GATE = PASS`.
|
|
97
|
+
|
|
98
|
+
## 10. PR_RUN_A identity
|
|
99
|
+
|
|
100
|
+
- PR: #16
|
|
101
|
+
- URL: https://github.com/dailephd/my-frontend-observer/pull/16
|
|
102
|
+
- Event: `pull_request`
|
|
103
|
+
- Head branch: `feature/v0.9.1-pwa-hard-gate-isolation`
|
|
104
|
+
- Head SHA: `fbc081d6387cdb3aeacd79f5ed82bdcd8812fd93`
|
|
105
|
+
- Run ID: `35624170324`
|
|
106
|
+
- Run URL: https://github.com/dailephd/my-frontend-observer/actions/runs/35624170324
|
|
107
|
+
- Conclusion: PASS
|
|
108
|
+
|
|
109
|
+
## 11. Candidate package identity
|
|
110
|
+
|
|
111
|
+
- Filename: `dailephd-my-frontend-observer-0.9.0.tgz`
|
|
112
|
+
- SHA-256: `63ba0cee49dc976cd55515ae387c7d1e46b226fd090eb931483c9be3a92bfa5c`
|
|
113
|
+
- File count: `370`
|
|
114
|
+
- Package version: `0.9.0`
|
|
115
|
+
- Candidate head SHA: `fbc081d6387cdb3aeacd79f5ed82bdcd8812fd93`
|
|
116
|
+
|
|
117
|
+
The same exact candidate was verified by the Windows, Linux, and macOS smoke
|
|
118
|
+
jobs.
|
|
119
|
+
|
|
120
|
+
## 12. Candidate Linux security result
|
|
121
|
+
|
|
122
|
+
The candidate job passed its security unit tests, browser security tests, and
|
|
123
|
+
the final isolated gate invocation. Its log includes the exact command
|
|
124
|
+
`npm run test:pwa-hard-gate`, one HARD GATE test passed with six focused tests
|
|
125
|
+
skipped, and no failure.
|
|
126
|
+
|
|
127
|
+
## 13. Windows exact-package result
|
|
128
|
+
|
|
129
|
+
PASS. The Windows smoke job downloaded the candidate artifact, verified the
|
|
130
|
+
candidate SHA-256, and passed packed observation, packed v0.8.1 project/viewer,
|
|
131
|
+
and packed v0.9 annotation smoke.
|
|
132
|
+
|
|
133
|
+
## 14. Linux exact-package result
|
|
134
|
+
|
|
135
|
+
PASS. The Linux smoke job downloaded the candidate artifact, verified the
|
|
136
|
+
candidate SHA-256, and passed packed observation, packed v0.8.1 project/viewer,
|
|
137
|
+
and packed v0.9 annotation smoke.
|
|
138
|
+
|
|
139
|
+
## 15. macOS exact-package result
|
|
140
|
+
|
|
141
|
+
PASS. The macOS smoke job downloaded the candidate artifact, verified the
|
|
142
|
+
candidate SHA-256, and passed packed observation, packed v0.8.1 project/viewer,
|
|
143
|
+
and packed v0.9 annotation smoke.
|
|
144
|
+
|
|
145
|
+
## 16. Windows tutorial result
|
|
146
|
+
|
|
147
|
+
PASS. All four existing v0.9 Observer tutorials passed through
|
|
148
|
+
`@dailephd/my-dev-kit-lab@0.4.9`.
|
|
149
|
+
|
|
150
|
+
## 17. Linux tutorial result
|
|
151
|
+
|
|
152
|
+
PASS. All four existing v0.9 Observer tutorials passed through
|
|
153
|
+
`@dailephd/my-dev-kit-lab@0.4.9`.
|
|
154
|
+
|
|
155
|
+
## 18. macOS tutorial result
|
|
156
|
+
|
|
157
|
+
PASS. All four existing v0.9 Observer tutorials passed through
|
|
158
|
+
`@dailephd/my-dev-kit-lab@0.4.9`.
|
|
159
|
+
|
|
160
|
+
## 19. Package-content audit
|
|
161
|
+
|
|
162
|
+
The npm dry-run and exact candidate contents exclude implementation tests,
|
|
163
|
+
temporary PWA profiles, temporary evidence roots, `.my-dev-kit-workflow/`,
|
|
164
|
+
`examples/v09-demo/`, and generated tutorial artifacts. Normal `dist`, docs,
|
|
165
|
+
license, README, changelog, and package metadata remain present.
|
|
166
|
+
|
|
167
|
+
## 20. Schema/dependency/version audit
|
|
168
|
+
|
|
169
|
+
- Observation schema: `1.2.0`
|
|
170
|
+
- Comparison schema: `1.0.0`
|
|
171
|
+
- Frontend contract schema: `1.0.0`
|
|
172
|
+
- Evaluation schema: `1.0.0`
|
|
173
|
+
- Bounded agent context schema: `1.0.0`
|
|
174
|
+
- External reference schema: `1.0.0`
|
|
175
|
+
- Visual annotation schema: `1.0.0`
|
|
176
|
+
- Viewer protocol: `1.3.0`
|
|
177
|
+
- `DEPENDENCY_CHANGED = false`
|
|
178
|
+
- `PACKAGE_VERSION_CHANGED = false`
|
|
179
|
+
- Package version: `0.9.0`
|
|
180
|
+
|
|
181
|
+
## 21. Readiness-report candidate mutation
|
|
182
|
+
|
|
183
|
+
This tracked report changes the candidate bytes because it is included under
|
|
184
|
+
`docs/`. The report must therefore be committed and pushed, followed by a new
|
|
185
|
+
complete PR workflow against the report-containing head.
|
|
186
|
+
|
|
187
|
+
## 22. PR_RUN_B
|
|
188
|
+
|
|
189
|
+
Not started at report creation. PR_RUN_B is required after the report commit
|
|
190
|
+
and must pass the candidate, all three exact-package smoke jobs, and all three
|
|
191
|
+
tutorial jobs.
|
|
192
|
+
|
|
193
|
+
## 23. Integration handoff
|
|
194
|
+
|
|
195
|
+
Integration is not yet authorized by this report alone. After PR_RUN_B passes,
|
|
196
|
+
merge PR #16 using the repository merge-commit convention. Preserve both the
|
|
197
|
+
implementation branch and the planning branch.
|
|
198
|
+
|
|
199
|
+
## 24. Remaining exact-master validation
|
|
200
|
+
|
|
201
|
+
After the merge, manually dispatch `Pre-release readiness` on the exact merged
|
|
202
|
+
`master` SHA because the workflow does not run automatically on pushes to
|
|
203
|
+
`master`. Require the complete seven-job matrix, verify the isolated hard gate
|
|
204
|
+
again in the Linux candidate job, and leave local `master` at that validated
|
|
205
|
+
merged SHA. Version bumping, tagging, publishing, GitHub Release creation, and
|
|
206
|
+
release-branch creation remain out of scope.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dailephd/my-frontend-observer",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -34,7 +34,8 @@
|
|
|
34
34
|
"lint": "eslint .",
|
|
35
35
|
"test": "vitest run --passWithNoTests",
|
|
36
36
|
"test:browser": "vitest run --config vitest.browser.config.ts --passWithNoTests",
|
|
37
|
-
"test:security": "vitest run tests/unit/policy.test.ts tests/unit/viewerServer.test.ts tests/unit/viewerEvidenceServer.test.ts tests/unit/referenceViewerServer.test.ts tests/unit/contextViewerServer.test.ts tests/unit/paths.test.ts tests/unit/evidenceDiscovery.test.ts tests/unit/projectWorkflow.test.ts tests/unit/projectCheckService.test.ts tests/unit/projectCheckResult.test.ts tests/unit/viewerAuthoringSecurity.test.ts tests/unit/viewerAnnotationAuthoring.test.ts tests/unit/viewerAnnotationEvidence.test.ts tests/unit/viewerAnnotationContractPromotion.test.ts tests/unit/viewerAnnotationReferenceMaterialization.test.ts tests/unit/evidenceDiscoveryTempDirectories.test.ts && vitest run --config vitest.browser.config.ts tests/browser/chromiumAdapter.test.ts tests/browser/pwaHardening.test.ts tests/browser/projectCheckWorkflow.test.ts",
|
|
37
|
+
"test:security": "vitest run tests/unit/policy.test.ts tests/unit/viewerServer.test.ts tests/unit/viewerEvidenceServer.test.ts tests/unit/referenceViewerServer.test.ts tests/unit/contextViewerServer.test.ts tests/unit/paths.test.ts tests/unit/evidenceDiscovery.test.ts tests/unit/projectWorkflow.test.ts tests/unit/projectCheckService.test.ts tests/unit/projectCheckResult.test.ts tests/unit/viewerAuthoringSecurity.test.ts tests/unit/viewerAnnotationAuthoring.test.ts tests/unit/viewerAnnotationEvidence.test.ts tests/unit/viewerAnnotationContractPromotion.test.ts tests/unit/viewerAnnotationReferenceMaterialization.test.ts tests/unit/evidenceDiscoveryTempDirectories.test.ts && vitest run --config vitest.browser.config.ts tests/browser/chromiumAdapter.test.ts tests/browser/pwaHardening.test.ts tests/browser/projectCheckWorkflow.test.ts && npm run test:pwa-hard-gate",
|
|
38
|
+
"test:pwa-hard-gate": "vitest run --config vitest.browser.config.ts tests/browser/pwaHardening.test.ts -t \"HARD GATE\"",
|
|
38
39
|
"check:docs": "node scripts/check-docs.mjs"
|
|
39
40
|
},
|
|
40
41
|
"devDependencies": {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
:root{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light dark;--bg:#0f172a;--panel:#1e293b;--border:#334155;--text:#e2e8f0;--text-dim:#94a3b8;--accent:#38bdf8;--error-bg:#450a0a;--error-border:#dc2626}@media (prefers-color-scheme:dark){:root{--lightningcss-light: ;--lightningcss-dark:initial}}*{box-sizing:border-box}html,body,#root{height:100%;margin:0}body{background:var(--bg);color:var(--text);font-family:system-ui,-apple-system,Segoe UI,sans-serif}.app-shell{flex-direction:column;height:100%;display:flex}.app-shell__header{border-bottom:1px solid var(--border);justify-content:space-between;align-items:center;padding:.75rem 1rem;display:flex}.app-shell__identity{flex-direction:column;line-height:1.2;display:flex}.app-shell__title{font-size:1rem;font-weight:600}.app-shell__subtitle{color:var(--text-dim);font-size:.8rem}.status-banner{border-bottom:1px solid var(--border);justify-content:space-between;gap:1rem;padding:.4rem 1rem;font-size:.8rem;display:flex}.status-banner--loading,.status-banner--ok{color:var(--text-dim)}.status-banner--error{background:var(--error-bg);color:#fecaca;border-bottom-color:var(--error-border)}.app-shell__body{flex:1;grid-template-columns:220px 1fr 280px;min-height:0;display:grid}.app-shell__nav,.app-shell__workspace,.app-shell__details{padding:1rem;overflow:auto}.app-shell__nav{border-right:1px solid var(--border)}.app-shell__details{border-left:1px solid var(--border)}.placeholder-note{color:var(--text-dim);font-size:.85rem;line-height:1.5}.install-affordance{border:1px solid var(--border);border-radius:6px;padding:.35rem .7rem;font-size:.8rem}.install-affordance--available{background:var(--accent);color:#0f172a;border-color:var(--accent);cursor:pointer}.install-affordance--unavailable{color:var(--text-dim)}.evidence-list{flex-direction:column;gap:.4rem;margin:0;padding:0;list-style:none;display:flex}.evidence-list__truncated-note{color:var(--text-dim);font-size:.75rem}.evidence-list__item{text-align:left;background:var(--panel);border:1px solid var(--border);width:100%;color:var(--text);cursor:pointer;border-radius:6px;flex-direction:column;align-items:flex-start;gap:.15rem;padding:.4rem .5rem;font-size:.75rem;display:flex}.evidence-list__item--selected{border-color:var(--accent)}.evidence-list__family{font-weight:600}.evidence-list__id{color:var(--text-dim);font-family:monospace}.evidence-list__state{font-size:.7rem}.evidence-list__state--supported{color:#4ade80}.evidence-list__state--unsupported-version,.evidence-list__state--invalid-structure,.evidence-list__state--malformed-json,.evidence-list__state--unreadable{color:#f87171}.evidence-list__state--unrecognized-kind{color:var(--text-dim)}.evidence-list__error,.artifact-preview__error,.artifact-preview__unsupported{color:#fecaca;font-size:.85rem}.artifact-preview__summary{color:var(--text-dim);font-size:.85rem}.artifact-preview__raw{background:var(--panel);border:1px solid var(--border);white-space:pre-wrap;word-break:break-word;border-radius:6px;max-height:60vh;padding:.75rem;font-size:.7rem;overflow:auto}.evidence-details{font-size:.75rem}.evidence-details dt{color:var(--text-dim);margin-top:.5rem}.evidence-details dd{word-break:break-word;margin:.1rem 0 0}.observation-workspace{flex-direction:column;gap:.5rem;height:100%;font-size:.75rem;display:flex}.observation-workspace__toolbar{border-bottom:1px solid var(--border);gap:1rem;padding-bottom:.4rem;display:flex}.observation-workspace__toolbar label{cursor:pointer;align-items:center;gap:.3rem;display:flex}.observation-workspace__panes{flex:1;grid-template-columns:160px 1fr 260px;gap:.75rem;min-height:0;display:grid}.observation-workspace__targets,.observation-workspace__inspector{overflow:auto}.observation-workspace__visual{border:1px solid var(--border);background:#000;border-radius:6px;justify-content:center;align-items:flex-start;display:flex;overflow:auto}.target-overlay-svg{width:100%;height:auto;display:block}.target-overlay-svg__rect{fill:#38bdf81f;stroke:var(--accent);stroke-width:2px;cursor:pointer;vector-effect:non-scaling-stroke}.target-overlay-svg__rect--selected{fill:#4ade8033;stroke:#4ade80}.target-overlay-svg__rect:focus-visible{outline:2px solid #facc15}.target-overlay-svg__label{fill:#f8fafc;paint-order:stroke;stroke:#0f172a;stroke-width:3px;font-size:12px}.target-overlay-svg__relationship{stroke:#facc15;stroke-width:1.5px;stroke-dasharray:4 3;vector-effect:non-scaling-stroke}.target-list{flex-direction:column;gap:.3rem;margin:0;padding:0;list-style:none;display:flex}.target-list__item{text-align:left;background:var(--panel);border:1px solid var(--border);width:100%;color:var(--text);cursor:pointer;border-radius:6px;flex-direction:column;align-items:flex-start;padding:.3rem .45rem;font-size:.7rem;display:flex}.target-list__item--selected{border-color:#4ade80}.target-list__item--not-found,.target-list__item--ambiguous,.target-list__item--unavailable{opacity:.75}.target-list__name{font-family:monospace;font-weight:600}.target-list__status{color:var(--text-dim)}.inspector h3,.inspector h4{margin:.4rem 0 .3rem;font-size:.8rem}.inspector__fields{margin:0}.evidence-field{margin-bottom:.4rem}.evidence-field dt{color:var(--text-dim);font-size:.68rem}.evidence-field dd{word-break:break-word;margin:0}.evidence-field__source{color:var(--text-dim);font-size:.65rem}.evidence-field--unavailable dd,.evidence-field--not-applicable dd{color:var(--text-dim);font-style:italic}.relationships-section__note{color:var(--text-dim);font-size:.68rem}.relationships-section__list{margin:.3rem 0;padding:0;list-style:none}.relationships-section__unresolved{color:var(--text-dim);font-size:.68rem}.inspector__error{color:#fecaca}.target-overlay-svg__rect--highlighted{stroke:#facc15;fill:#facc1526}.comparison-workspace,.evaluation-workspace{flex-direction:column;gap:.6rem;height:100%;font-size:.75rem;display:flex;overflow:auto}.comparability-banner{border:1px solid var(--border);border-radius:6px;padding:.4rem .6rem}.comparability-banner--comparable{border-color:#4ade80}.comparability-banner--comparable-with-warnings{border-color:#facc15}.comparability-banner--incomparable{background:var(--error-bg);border-color:#f87171}.comparability-banner ul{margin:.3rem 0 0;padding-left:1rem}.comparability-reason--blocking{color:#fecaca}.comparability-reason--warning{color:#fde68a}.comparability-reason--unassessed{color:var(--text-dim)}.comparison-workspace__truncated{color:#fde68a;border:1px solid #facc15;border-radius:6px;padding:.4rem .6rem}.comparison-workspace__panes{grid-template-columns:1fr 1fr;gap:.75rem;min-height:260px;display:grid}.comparison-pane{border:1px solid var(--border);background:#000;border-radius:6px;padding:.4rem;overflow:auto}.comparison-pane__label{color:var(--text-dim);text-transform:uppercase;margin:0 0 .3rem;font-size:.7rem}.comparison-workspace__details,.evaluation-workspace__details{flex-direction:column;gap:.6rem;display:flex}.comparison-workspace__details section,.evaluation-workspace__details section{border-top:1px solid var(--border);padding-top:.4rem}.comparison-workspace__details h4,.evaluation-workspace__details h4{margin:0 0 .3rem;font-size:.75rem}.comparison-list{flex-direction:column;gap:.25rem;margin:0;padding:0;list-style:none;display:flex}.comparison-list__item{text-align:left;background:var(--panel);border:1px solid var(--border);width:100%;color:var(--text);cursor:pointer;border-radius:6px;padding:.3rem .45rem;font-size:.7rem}.comparison-list__item:disabled{cursor:default;opacity:.7}.comparison-list__meta{color:var(--text-dim);font-size:.65rem;display:block}.overall-verdict{text-align:center;border:2px solid var(--border);border-radius:8px;padding:.6rem .8rem;font-size:1rem}.overall-verdict--PASS{color:#4ade80;border-color:#4ade80}.overall-verdict--FAIL{color:#f87171;background:var(--error-bg);border-color:#f87171}.clause-list{flex-direction:column;gap:.3rem;margin:0;padding:0;list-style:none;display:flex}.clause-row{border:1px solid var(--border);border-radius:6px;padding:.3rem .45rem}.clause-row--fail{border-color:#f87171}.clause-row--pass{border-color:#4ade80}.clause-row--conflict{border-color:#fb923c}.clause-row--unavailable{border-color:var(--text-dim)}.clause-row__button{color:var(--text);text-align:left;cursor:pointer;background:0 0;border:none;flex-wrap:wrap;align-items:center;gap:.4rem;width:100%;font-size:.7rem;display:flex}.clause-row__button:disabled{cursor:default}.clause-row__id{font-family:monospace;font-weight:600}.clause-row__badge{border:1px solid var(--border);border-radius:4px;padding:.05rem .3rem;font-size:.6rem}.clause-row__badge--active{color:#4ade80;border-color:#4ade80}.clause-row__badge--superseded{color:var(--text-dim)}.clause-row__category{color:var(--text-dim);text-transform:uppercase;font-size:.6rem}.clause-row__status{margin-left:auto}.clause-row__unresolved{color:#fde68a;margin:.2rem 0 0;font-size:.65rem}.clause-row__primitive{color:var(--text-dim);word-break:break-word;margin:.2rem 0 0;font-family:monospace;font-size:.62rem}.reference-region-overlay-svg__rect--has-requirement{stroke-dasharray:4 2}.reference-workspace{flex-direction:column;gap:.6rem;height:100%;font-size:.75rem;display:flex;overflow:auto}.reference-workspace__panes{grid-template-columns:1fr 1fr;gap:.75rem;min-height:260px;display:grid}.reference-pane{border:1px solid var(--border);border-radius:6px;padding:.4rem;overflow:auto}.reference-workspace__candidate-select,.reference-workspace__evaluation-select{flex-direction:column;gap:.2rem;margin-bottom:.4rem;font-size:.7rem;display:flex}.reference-workspace__candidate-select select,.reference-workspace__evaluation-select select{background:var(--panel);color:var(--text);border:1px solid var(--border);border-radius:4px;padding:.2rem}.reference-workspace__details{flex-direction:column;gap:.6rem;display:flex}.reference-adequacy{border:1px solid var(--border);border-radius:6px;padding:.3rem .5rem;font-size:.7rem}.reference-adequacy--adequate{border-color:#4ade80}.reference-adequacy--partial{border-color:#facc15}.reference-adequacy--inadequate{border-color:#f87171}.target-overlay-svg--pannable{cursor:grab}.target-overlay-svg--pannable:active{cursor:grabbing}.zoom-controls{align-items:center;gap:.3rem;margin-bottom:.3rem;font-size:.68rem;display:flex}.zoom-controls button{background:var(--panel);color:var(--text);border:1px solid var(--border);cursor:pointer;border-radius:4px;padding:.1rem .4rem}.zoom-controls__scale{color:var(--text-dim);text-align:center;min-width:3rem}.reference-workspace__lock{align-items:center;gap:.4rem;margin-bottom:.4rem;font-size:.68rem;display:flex}.reference-workspace__lock button{background:var(--panel);color:var(--text);border:1px solid var(--border);cursor:pointer;border-radius:4px;padding:.15rem .5rem}.reference-workspace__lock button[aria-pressed=true]{color:#4ade80;border-color:#4ade80}.reference-workspace__lock button:disabled{cursor:default;opacity:.6}.reference-fidelity-panel{flex-direction:column;gap:.4rem;display:flex}.reference-fidelity-panel__toolbar button{background:var(--panel);color:var(--text);border:1px solid var(--border);cursor:pointer;border-radius:4px;padding:.25rem .6rem}.reference-fidelity-panel__toolbar button:disabled{cursor:default;opacity:.7}.reference-fidelity-panel__units{color:var(--text-dim);font-size:.62rem}.reference-fidelity-state{border:2px solid var(--border);border-radius:6px;padding:.4rem .6rem;font-size:.85rem}.reference-fidelity-state--pass{color:#4ade80;border-color:#4ade80}.reference-fidelity-state--fail{color:#f87171;background:var(--error-bg);border-color:#f87171}.reference-fidelity-state--not-evaluated{border-color:var(--text-dim);color:var(--text-dim)}.reference-workspace__independence-note{color:#fde68a;border-top:1px solid var(--border);padding-top:.3rem;font-size:.7rem}.app-shell__mode-toggle{gap:.3rem;margin-left:auto;margin-right:.5rem;display:flex}.app-shell__mode-toggle button{background:var(--panel);color:var(--text);border:1px solid var(--border);cursor:pointer;border-radius:4px;padding:.2rem .6rem;font-size:.75rem}.app-shell__mode-toggle button[aria-pressed=true]{border-color:var(--accent);color:var(--accent)}.app-shell__body--context{display:block}.app-shell__workspace--context{height:100%;padding:.75rem;overflow:auto}.context-workspace{flex-direction:column;gap:.8rem;font-size:.78rem;display:flex}.context-workspace section{border-top:1px solid var(--border);padding-top:.5rem}.context-summary-grid{grid-template-columns:max-content 1fr;gap:.2rem .8rem;font-size:.8rem;display:grid}.context-summary-grid dt{color:var(--text-dim)}.context-adequacy-badge{border:1px solid var(--border);border-radius:4px;padding:.05rem .4rem;font-weight:600;display:inline-block}.context-adequacy-badge--adequate{color:#4ade80;border-color:#4ade80}.context-adequacy-badge--partial{color:#facc15;border-color:#facc15}.context-adequacy-badge--inadequate{color:#f87171;border-color:#f87171}.context-sources{flex-direction:column;gap:.4rem;display:flex}.context-source-row{border:1px solid var(--border);border-radius:6px;flex-wrap:wrap;align-items:center;gap:.5rem;padding:.3rem .5rem;display:flex}.context-source-row__label{font-family:monospace}.context-source-row__status{border:1px solid var(--border);border-radius:4px;padding:.05rem .35rem;font-size:.7rem}.context-source-row__status--resolved{color:#4ade80;border-color:#4ade80}.context-source-row__status--ambiguous{color:#fb923c;border-color:#fb923c}.context-source-row__status--missing{border-color:var(--text-dim);color:var(--text-dim)}.context-target-source-list{margin:.3rem 0 0;padding-left:1rem;font-size:.7rem}.context-correlation-heading{color:var(--text-dim);margin:.2rem 0;font-size:.68rem}.context-correlation-row--selected{outline:1px solid var(--accent)}.context-required-loss{background:var(--error-bg);color:#fecaca;border:1px solid #f87171;border-radius:6px;padding:.4rem .6rem}.raw-evidence-viewer button{background:var(--panel);color:var(--text);border:1px solid var(--border);cursor:pointer;border-radius:4px;padding:.15rem .5rem;font-size:.68rem}.annotation-toolbar{border-bottom:1px solid var(--border);flex-wrap:wrap;align-items:center;gap:.75rem;padding-bottom:.4rem;display:flex}.annotation-toolbar .zoom-controls{margin-bottom:0}.annotation-toolbar__modes{gap:.25rem;display:flex}.annotation-toolbar__mode,.annotation-panel__actions button,.annotation-panel__association-actions button,.annotation-panel__saved-item{background:var(--panel);color:var(--text);border:1px solid var(--border);font:inherit;cursor:pointer;border-radius:4px;padding:.15rem .5rem}.annotation-toolbar__mode--active{border-color:var(--accent);background:#38bdf833}.annotation-panel__actions button:disabled,.annotation-panel__association-actions button:disabled{opacity:.5;cursor:not-allowed}.annotation-toolbar__note{align-items:center;gap:.3rem;display:flex}.annotation-toolbar__note input{width:12rem;font:inherit}.annotation-toolbar__read-only,.annotation-panel__read-only{color:var(--text-dim);font-style:italic}.annotation-panel{border-bottom:1px solid var(--border);flex-direction:column;gap:.4rem;margin-bottom:.6rem;padding-bottom:.6rem;display:flex}.annotation-panel h3,.annotation-panel h4{margin:.2rem 0}.annotation-panel__saved-list{flex-direction:column;gap:.25rem;margin:0;padding:0;list-style:none;display:flex}.annotation-panel__saved-item{text-align:left;flex-direction:column;width:100%;display:flex}.annotation-panel__saved-item--active{border-color:#4ade80}.annotation-panel__saved-id{word-break:break-all;font-family:ui-monospace,monospace}.annotation-panel__saved-meta,.annotation-panel__parent,.annotation-panel__interpretation{color:var(--text-dim);word-break:break-all;margin:0}.annotation-panel__actions,.annotation-panel__association-actions{flex-wrap:wrap;gap:.3rem;display:flex}.annotation-panel__association-actions label,.annotation-panel__note-editor{flex-direction:column;gap:.2rem;width:100%;display:flex}.annotation-panel__note-editor textarea{min-height:3rem;font:inherit}.annotation-panel__status--success{color:#4ade80}.annotation-panel__error{color:#fca5a5;margin:0}.target-overlay-svg__rect--inert{pointer-events:none}.target-overlay-svg--mode-point,.target-overlay-svg--mode-rectangle,.target-overlay-svg--mode-line,.target-overlay-svg--mode-arrow,.target-overlay-svg--mode-note{cursor:crosshair;touch-action:none}.target-overlay-svg--mode-pan{touch-action:none}.annotation-layer .annotation-layer__mark{pointer-events:none}.annotation-layer--selectable .annotation-layer__mark{pointer-events:visiblePainted;cursor:move}.annotation-layer__mark:focus-visible{outline:2px solid #facc15}.annotation-layer__shape{fill:none;stroke:#f472b6;stroke-width:3px;vector-effect:non-scaling-stroke}.annotation-layer__shape--area{fill:#f472b61f}.annotation-layer__shape--filled{fill:#f472b6}.annotation-layer__note-text{fill:#fdf2f8;paint-order:stroke;stroke:#500724;stroke-width:3px;font-size:14px}.annotation-layer__mark--selected .annotation-layer__shape{stroke:#facc15}.annotation-layer__mark--selected .annotation-layer__shape--filled{fill:#facc15}.annotation-layer__mark--preview .annotation-layer__shape{stroke-dasharray:6 4;opacity:.8}.reference-workspace>*{flex-shrink:0}.reference-pane .annotation-toolbar{margin-bottom:.3rem}.annotation-panel__group{border:1px solid var(--border);border-radius:4px;margin:0;padding:.3rem .4rem}.annotation-panel__group legend{color:var(--text-dim);padding:0 .2rem}.annotation-panel__requirement-form{flex-wrap:wrap;align-items:flex-end;gap:.3rem;display:flex}.annotation-panel__requirement-form label,.annotation-panel__association-actions label{flex-direction:column;gap:.15rem;display:flex}.annotation-panel__requirement-form button{background:var(--panel);color:var(--text);border:1px solid var(--border);font:inherit;cursor:pointer;border-radius:4px;padding:.15rem .5rem}.annotation-panel__requirement-form button:disabled{opacity:.5;cursor:not-allowed}.annotation-panel__hint{color:var(--text-dim);font-style:italic}.annotation-panel__intent{background:var(--panel);border:1px solid var(--border);white-space:pre-wrap;word-break:break-all;border-radius:4px;margin:0;padding:.3rem}.annotation-panel__proposal-list{word-break:break-all;margin:0;padding-left:1rem}.candidate-region-preview{pointer-events:none}.candidate-region-preview__rect{fill:none;stroke-width:2px;vector-effect:non-scaling-stroke}.candidate-region-preview__rect--create{stroke:#34d399;stroke-dasharray:8 4;fill:#34d3991a}.candidate-region-preview__rect--refine-original{stroke:#94a3b8;stroke-dasharray:2 3}.candidate-region-preview__rect--refine-candidate{stroke:#fb923c;stroke-dasharray:8 4;fill:#fb923c1a}.candidate-region-preview__label{fill:#ecfdf5;paint-order:stroke;stroke:#022c22;stroke-width:3px;font-size:11px}.annotation-panel__promotion{border-top:1px solid var(--border);flex-direction:column;gap:.3rem;padding-top:.4rem;display:flex}.annotation-panel__promotion button,.annotation-panel__group>button{background:var(--panel);color:var(--text);border:1px solid var(--border);font:inherit;cursor:pointer;border-radius:4px;align-self:flex-start;padding:.15rem .5rem}.annotation-panel__promotion button:disabled,.annotation-panel__group>button:disabled{opacity:.5;cursor:not-allowed}.annotation-panel__promotion-status{color:var(--text-dim);margin:.3rem 0}.annotation-panel__materialization .annotation-panel__status p{margin:0}
|