You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docs(spec): trace 64 frontend methods to their spec, and sync the spec seven tags already pointed at (#471)
gate-16 spec-coverage 64 -> PASS, measured with hydra-gates 651e5c5 at the CI
scope (--scope-to-diff --base origin/beta). gate-46 spec-anchor-existence stays
PASS, so every anchor added here resolves to a heading that exists.
64 changed frontend methods across 24 files carried no @SPEC. Each now names the
requirement it serves — facet views and the facet store to gemma-faceted-search,
the SBOM panel to sbom-import, the suite wizard to suite-wizard, the portfolio
helpers to portfolio-rationalization-time, the view store to view-enrichment-api,
the review modals to catalog-ratings, and so on. No tag was added without
reading the method and the requirement it points at.
openspec/specs/realtime-updates-ui/ is NEW here, and that is the real find.
Change `adopt-live-updates-ui` declares "Affected specs: realtime-updates-ui
(new)" and shipped src/composables/useLiveCollections.js plus its seven
consumers — but the delta was never synced into openspec/specs/. SEVEN @SPEC
tags across six source files have been pointing at a spec that does not exist.
gate-46 never caught it because gate-46 validates ANCHORS (#fragment), not bare
file targets; an audit of every `@spec openspec/specs/<x>/spec.md` in src/ found
this one and only this one dangling. The delta is promoted verbatim — its
requirement, its three scenarios and its author's reason-bearing `@e2e exclude`
are unchanged; the only edits are the title line and the delta's
"## ADDED Requirements" heading becoming "## Requirements", plus a Purpose
recording where it came from. I did not author that exclusion.
I nearly made this worse: the first draft of this change copied the dangling
`@spec openspec/specs/realtime-updates-ui/spec.md` onto useLiveCollections()
itself. Checking the target existed before trusting it is what turned a
propagated broken reference into a fixed one.
Can-fail: reverting the 22 annotated files takes gate-16 from PASS back to 51;
the run before any of this work reported 64 on the same package.
vitest 215/215. gate-46 PASS. No other gate count moved.
Live-update subscription behaviour for Softwarecatalog views that render from the
5
+
`createObjectStore`-based object store. Synced from change `adopt-live-updates-ui`,
6
+
which shipped `src/composables/useLiveCollections.js` and its seven consumers but
7
+
was never synced into `openspec/specs/`.
8
+
9
+
## Requirements
10
+
11
+
### Requirement: Store-rendered views MUST subscribe to live updates for their scope
12
+
13
+
Views that render from Softwarecatalog's `createObjectStore`-based object store MUST subscribe to
14
+
live updates for the data they display: collection-scoped views subscribe to
15
+
`or-collection-{register-slug}-{schema-slug}` per rendered object type, object-scoped views
16
+
subscribe to `or-object-{uuid}`. Subscriptions MUST be re-scoped when the viewed scope
17
+
changes and released when the view is destroyed. Events are refetch HINTS only: views MUST
18
+
refetch through their existing fetch paths and MUST NOT patch rendered state from an event
19
+
payload.
20
+
21
+
@e2e exclude Requires a second concurrent authenticated session plus a notify_push (or poll-tick) round-trip; covered by the shared library's transport tests and manual two-browser verification.
22
+
23
+
#### Scenario: Module view refreshes when a rendered collection changes elsewhere
24
+
25
+
-**GIVEN** a module view (vulnerabilities, compliance matrix, license posture, lifecycle
26
+
roadmap, or organisaties index) is open
27
+
-**WHEN** another user creates, updates or deletes an object of a type the view renders
28
+
-**THEN** the view receives the `or-collection-{register}-{schema}` hint, the plugin
29
+
re-runs `fetchCollection` with the last-used params, and the view's `getCollection`-backed
30
+
computeds re-render the fresh data without a manual refresh
31
+
32
+
#### Scenario: Subscription waits for lazy type registration
33
+
34
+
-**GIVEN** a module view mounts before its `loadData()` has registered its object types
35
+
-**WHEN** the registration lands in the store's `objectTypeRegistry`
36
+
-**THEN** the reactive `enabled` gate flips and the subscription attaches — no subscribe
37
+
call is attempted against an unregistered type
38
+
39
+
#### Scenario: Subscription released on destroy
40
+
41
+
-**GIVEN** live subscriptions are active for a module view
42
+
-**WHEN** the user navigates away and the component scope is disposed
43
+
-**THEN** every subscription is released via the composable's scope-bound lifecycle
0 commit comments