# The OpenPWA Evidence Layers: support, capability and behaviour as separate claims about web platform features

**Version 1.0, 2026-10-20** · OpenPWA Editorial Team · Licence: CC BY 4.0 ·
Condensed edition: https://openpwa.net/about/evidence/ · Frozen version:
https://openpwa.net/about/evidence/v1.0/ · Chinese edition: https://openpwa.net/zh/about/evidence/v1.0/paper/

Status: position paper, not peer reviewed. Drafted by AI agent sessions for the OpenPWA Editorial Team
from the team's own study materials; no per-entry human sign-off, as on the rest of openpwa.net. The
worked example rests on device steps that an OpenPWA operator performed on a real iPhone.

## Abstract

Compatibility tables answer one question well: is a feature supported in a given browser, and since which
version. Developers who build installable web apps also need answers to two further questions that a
support table is not designed to answer: what can the feature actually do (show me), and how does it
behave on a real device, in a specific OS build and launch context, when two settings conflict or a default applies. We
propose the **OpenPWA Evidence Layers**, a framework that treats these as three layers of claim: **Support**,
**Capability** and **Behaviour**. Each layer has a native evidence class (**documented**, **demonstrated**,
**measured**), and every published claim carries both its layer and the class of evidence actually behind
it. Behaviour claims are versioned by OS build and context, dated, reproducible from a published protocol
and harness, and backed by raw data with hashes. Behaviour results flow back to the support layer as dated
conditions attached to a support row (agrees, adds a condition, differs) without silently overwriting the
upstream source. None of the ingredients is new on its own: compatibility data has notes and partial
support, conformance suites run tests, demo sites show capabilities, and practitioners publish device notes.
What the framework formalises and names is their separation into layers with explicit per-claim evidence
grading, the treatment of installed-app and device context as a first-class layer with its own evidence
class, the back-filling of support data with dated device conditions, and same-device before-and-after
studies across OS upgrades. We define the layers and a decision procedure for assigning claims, set out
twelve principles, and apply the framework claim by claim to a single-device study of Home Screen web apps
on iOS 18.6.2.

## 1. The problem: "is it supported?" is not the question developers end up asking

A support table compresses a feature into a cell: yes, no, partial, a version number, sometimes a note.
That compression is the table's strength. It is also the reason a "yes" or a "no" can mislead someone who
ships a web app to a phone. The 2026-10-20 OpenPWA study on an iPhone 16 Pro running iOS 18.6.2 (build
22G100) gives five concrete cases. Notebook entries are cited as N01 to N66 [S1].

**A "no" that fires.** MDN browser-compat-data (BCD) records
`api.ServiceWorkerGlobalScope.notificationclick_event` as `version_added: false` for Safari on iOS [R1]. A
BCD issue opened in April 2024 reports that the event does fire [R2]. On 18.6.2, in a web app added to the
Home Screen, `notificationclick` fired on six of six taps, through both `addEventListener` and the
`onnotificationclick` property, and `focus()` on the existing window succeeded (N35 to N40). Every tap had a live window; taps with
no live page, which comment 35 on WebKit bug 268797 reports as failing, were not tested [R9]. The property check that a BCD contributor says the collector runs [R2], `'onnotificationclick' in self`, was true in a
worker controlled by the Home Screen app and false in the same worker controlled by a Safari tab (N03, N18,
N34). One explanation, not established by the study, is that the collector read the check in a tab
context. The support cell states one value for Safari on iOS as a whole, with no note that
separates the two contexts.

**Two "yes" cells that collide.** BCD lists both `<meta name="theme-color">` and the manifest
`theme_color` member as supported in Safari on iOS since 15 [R3, R4]. Neither entry says what happens when a
page sets one colour and its manifest another. On 18.6.2 the status-bar strip of a Home Screen app took the
page's `theme-color` meta over a different manifest `theme_color`, also inside an existing installed app,
and took the manifest value only when the page had no meta (three purpose-built apps, N64 to N65-a).
Precedence is a property of behaviour, not of support.

**A transition with a moment.** WebKit described in Safari 17.2 that cookies are copied from Safari into a
web app when it is added to the Home Screen [R5]. On 18.6.2 a first-party cookie set in Safari appeared in
a newly added app once and was independent afterwards, while localStorage and IndexedDB were never copied
in either direction (N13, N16 to N22). A support table can say "partitioned storage: yes". A bare support value does
not say that one store is copied at one moment and the others are not.

**A default that depends on the OS build.** A page with no manifest and no icon, added to the Home Screen on
18.6.2, opened in Safari, with Safari's process, storage and service worker, `navigator.standalone` false
and `display-mode: browser` (N23, N63). WebKit's Safari 26.0 notes say that from iOS 26 every site added to
the Home Screen opens as a web app by default [R6]. The same page and the same tap are therefore
documented to behave differently across OS builds; our iOS 26-or-later run is still to come. A version
number in a support row for "manifest" does not capture this; a dated, build-stamped observation does.

**A lifecycle nobody tabulates.** After the user swiped the app away in the app switcher, the document from
the previous launch was still alive about six seconds later, `clients.matchAll()` found it, and the web-app
process id survived a swipe in an earlier step (N16, N38, N40). Whether this is a guarantee, a race or an
artefact of the debugging connection is a question for more runs. It is the kind of fact that decides
whether a notification handler should call `focus()` or `openWindow()`, and none of the compatibility
sources we read records it.

The pattern across the five cases: the support layer is mostly right about what it claims, and the risk
comes from reading it as a claim about behaviour. The fix is not a bigger table. It is to keep the
two kinds of claim apart, label each with the evidence behind it, and connect them explicitly.

## 2. The three layers

A **claim** is a single statement about a web platform feature that a reader could act on. Each claim
belongs to exactly one layer, decided by the question it answers, and carries one evidence class,
decided by what actually backs it (section 3).

| | Layer 1, Support | Layer 2, Capability | Layer 3, Behaviour |
|---|---|---|---|
| Question | Is it supported, and since which version? | What can it do? Show me. | What exactly happens on this device, OS build and context? |
| Typical form | "Safari on iOS 16.4+ supports the Push API in Home Screen web apps." | "This page requests notification permission and shows a notification. Try it." | "On iOS 18.6.2 (22G100) a Home Screen app's status-bar strip takes the page's `theme-color` meta over the manifest `theme_color`." |
| Allowed evidence classes | documented | demonstrated | measured (native) or documented |
| Native sources | Specifications, vendor documentation and release notes, BCD | A runnable demo that exercises the feature | A dated run of a published protocol on a named device |
| Unit | feature × browser × version range | feature × demo | behaviour × device × OS build × context × date |

### 2.1 Layer 1, Support

Claims of presence, absence, partial presence, flag status or removal of a feature in a named browser and
version range, **as stated by a source**. Availability conditions that the source states ("Home Screen web
apps only", "requires user activation") are part of the layer 1 claim, because they bound where the "yes"
applies. Layer 1 is documented by definition: OpenPWA does not author support statements, it relays and
cross-checks them. When an OpenPWA measurement bears on a support statement, the measurement stays a
layer 3 record and is attached to the support row as a relation (section 4).

### 2.2 Layer 2, Capability

Claims that a feature can accomplish a task, backed by a runnable page that attempts it: requesting
permission, setting a badge, sharing a file, receiving a push. The claim is about possibility. Whatever
the demo does on a given device is the observation of whoever ran it. A demo run recorded by OpenPWA under
the protocol produces a layer 3 record, not a stronger layer 2 claim.

### 2.3 Layer 3, Behaviour

Claims about what a feature does under stated conditions:

- **precedence** when inputs conflict (page meta over manifest);
- **defaults** when an input is missing (a letter tile when there is no icon);
- **context differences** (Home Screen app versus Safari tab; a worker controlled by an app versus by a
  tab);
- **timing and lifecycle** (cookie copy at add; a page alive after swipe-away; a permission promise
  pending until answered);
- **geometry and rendering** (viewport 402 × 812, top inset 62 px, strip `#161616`);
- **pitfalls** (a subpath-scoped worker's push subscription not returned by `window.pushManager`).

A measured layer 3 claim always names a device, an OS version and build, a context and a date; a
documented one carries whatever conditions its source states, often only a version. It is **measured**
when OpenPWA ran it, and **documented** when a source describes it (WebKit's Safari 17.2
description of the cookie copy is a documented layer 3 claim until someone measures it).

### 2.4 Boundary cases

- **Feature detection.** A presence check such as `'onnotificationclick' in self` reported by a source
  without context is layer 1. The same check run by OpenPWA in a stated context is a layer 3 record; here
  its result depended on context (true in the app's worker, false in the tab's), and that is exactly what
  the support row lacked.
- **A version number from a run** ("works on 18.6.2") is a layer 3 claim about one build. It does not
  establish `version_added`, which needs a source or a run on the earlier build.
- **Limits and performance** (quota sizes, timing budgets): layer 1 when a vendor publishes the limit,
  layer 3 when measured.
- **A demo that fails on the reader's device** is the reader's observation. It becomes an OpenPWA claim
  only when reproduced under the protocol.
- **Mixed statements** ("supported since 16.4, and fires only in Home Screen apps") are split into one
  claim per layer.

### 2.5 Decision procedure

Apply in order; the first "yes" decides.

1. Does the claim say what happens when the feature is used, or how its result depends on device, OS
   build, launch context or state: values, precedence, defaults, timing, lifecycle, rendering, prompts?
   **Layer 3.** Then: did OpenPWA run it under the protocol (measured), or does a source state it
   (documented)?
2. Does it say that the feature can do a task and point to a runnable page, with no recorded run?
   **Layer 2**, demonstrated.
3. Does it say whether, where or since when the feature is available (presence, version, flag, partial,
   a source-stated availability condition)? **Layer 1**, documented. If the claim came from an OpenPWA run
   rather than a source, go back to step 1: it is a layer 3 record attached to the row.
4. Otherwise it is not a platform claim (advice, history, opinion). Label it as such or remove it.

## 3. Evidence classes and grading

This section defines what can back a claim and how measured results are graded.

### 3.1 The three classes

**Documented.** A source outside OpenPWA states the claim: a specification, vendor documentation, release
notes, a vendor engineering post, a vendor bug tracker, or BCD. Shown with the source and the date it was
checked. BCD rows are documented even where BCD's own data came from automated collection, because
OpenPWA did not observe them. Third-party notes (practitioner blogs, forums) are documented with lower
confidence, under the site's existing high, medium and low rule [S2]. A documented layer 3 claim is shown
as `Documented by <source>; not measured by OpenPWA`, so it is never read as a measurement.

**Demonstrated.** A runnable OpenPWA demo exercises the capability. Shown with the demo link and wording
that invites the reader to try it on their own device ("Try it"). A demonstrated label asserts that the
demo exists and is designed to exercise the feature. It never asserts that the feature works on any
particular device.

**Measured.** An OpenPWA run of a published protocol on a named real device recorded the result. To
qualify, a run needs all of the following:

- **Environment block**: device marketing name and model identifier, OS version and build, release channel,
  browser version, language and region, non-default feature flags, content blockers or VPN state, and
  the inspecting host if one was used.
- **Date and time** with time zone, for the run and for each read.
- **Context**: tab, Home Screen app, or both; fresh state or not; first launch or relaunch.
- **Protocol and harness**: the test id, the published steps, and the harness version with a SHA-256 hash
  for each file the run loaded.
- **Expectation in advance**: the expected result and its source, recorded before the step (in a
  checklist or the notebook; not in a public registry).
- **Raw data**: the instrumented reads as files, screenshots and recordings, each listed with a hash.
- **Verdict**: as-expected, differs, inconclusive or could-not-run.
- **Confidence label** (3.2).

These are the requirements for v1.0. The 18.6.2 study ran before they were written and does not
meet all of them. Its gaps [S1]: raw reads carry tool-hash sidecars only from N15 onwards; run-time
snapshots of the served harness exist for `lab.js`, `sw.js` and the T7 files but not for every page, so
the other files are identified by their repository version at the deployed revision; and the environment
record lacks feature flags, VPN and iCloud Private Relay state, the identity of an installed Safari Web
Extension, and the Settings language and region.

### 3.2 Confidence labels within measured

| Label | Meaning | Published as measured? |
|---|---|---|
| **A**, instrumented read (agent-measured) | An instrumented read of page state: a published probe script's output, captured over a debugging protocol (for example the WebKit remote inspector) and stored verbatim as JSON. "Agent" names who ran the probe; the value is the probe's output, not a model's interpretation | Yes |
| **S**, screenshot or recording | A capture analysed afterwards (pixel values, video frames, capture times) | Yes |
| **O**, observer report | The operator's verbal report only | No. Kept in the notebook; may support an A or S result, never stand alone |

Labels combine: "A+S" means an instrumented read and a capture agree; "S+O" means a capture with the
operator's report as context. A result is published with its weakest essential component named; for
example, the 18.6.2 status-bar colour source is S+O, because the pixel evidence is S and the
identification of which app was on screen rests partly on the operator.

### 3.3 Dating and reproducibility

A measured claim is true of one build on one device on one date. It is never generalised across builds by
wording ("iOS 18 does X"). It is reproducible when another person with the same device class and OS build
can follow the protocol, load the same harness bytes (checked by hash), and compare against the raw data.
Same-device reruns after an OS upgrade compare like with like: same hardware, same installed apps, same
harness files, with the upgrade as the intervention.

Reproduction has a limit: the study's report notes that once the test phone is upgraded to iOS 27, its
iOS 18.6.2 results can be re-measured only on another device still on that build.
This is why the raw data matters more than the prose. When nobody can repeat the run, the published reads,
captures and hashes are the only way to audit it.

## 4. How the layers relate

The layers stay separate and are linked by explicit relations.

### 4.1 Layer 3 conditions layer 1

A behaviour result is attached to the support row it bears on, with one of three relations:

- **agrees**: the measurement matches the row (badge shown on the Home Screen icon after `setAppBadge(3)`;
  BCD says Badging is supported).
- **adds-condition**: the row holds under a condition the source does not state (Declarative Web Push:
  `window.pushManager` also exists in a Safari tab, and in two Home Screen apps whose subpath-scoped
  worker held a push subscription, `window.pushManager.getSubscription()` returned null).
- **differs**: the measurement contradicts the source (`notificationclick` fires in Home Screen apps where
  BCD says unsupported).

The row keeps its source, status, version and confidence. The relation and its condition are shown in the
row, dated and linked to the run. This is what "back-filling" means in this framework: support data gains
dated device conditions; it is not rewritten by them.

### 4.2 Resolving and displaying conflicts

A `differs` relation is a finding, not an error to be hidden. It is shown in the row as `Differs from <source>`, with the condition and the run date. It goes on a discrepancy list, where it becomes a candidate
for an upstream report (a BCD issue, a WebKit bug). The row's status
changes only if an upstream source changes, or if OpenPWA publishes a rule under which a measurement may
set status (not in v1.0; see P8). When a later run differs from an earlier one, both stay visible, each
with its build; the newer run does not erase the older.

### 4.3 Layer 2 connects the other two

A demo is where a reader can turn a support claim into a personal check, and where a behaviour test often
starts. It does not settle either. The framework keeps it in its own layer so that "it ran on my phone"
is never mistaken for "OpenPWA measured it" or "the vendor supports it".

## 5. Principles

**P1. Every claim has a layer and an evidence class.** Readers can see both, in text, not only by colour.

**P2. Classes are never upgraded by wording.** "Tested", "verified on device", "in practice" and their
Chinese equivalents are reserved for published measured runs.

**P3. Behaviour is versioned per OS build and context.** A behaviour claim names device, OS version and
build, context and date. Different builds give different rows.

**P4. Measurements are dated, reproducible and come with raw data.** Protocol, harness version and file
hashes, environment block, raw reads and captures, all published in sanitised form.

**P5. Expectations are written before the step.** The expected result and its source are recorded first.
"Differs from expected" is a finding.

**P6. Records beat reports.** When an operator's report conflicts with a read or a capture, the record is
preferred and the conflict is logged as an anomaly. Observer-only results are never published as measured.

**P7. Corrections are append-only.** A wrong entry is corrected by a new dated entry that cites the old
one. Retracted readings are listed as "do not cite" next to the result they were retracted from.

**P8. Layer 3 conditions layer 1; it does not silently overwrite it.** In v1.0 a measurement never changes a
support row's status, version or confidence. Any future rule that lets it do so is published as a new
version of this framework before it is applied.

**P9. Scope is stated.** Sample size (devices, builds, runs), what was not tested and known threats to
validity are part of every result.

**P10. Novelty is checked, replication is labelled.** A result that confirms a published description is
labelled a replication and cites the description. Only results with no prior description found are called
new, and the search is described.

**P11. The observer protocol protects the record.** When a person operates the device and an instrument
reads it, the protocol rules are part of the method. Define every term before using it (for example, "the
status bar" means the strip with the time and battery). Ask one question per message. Confirm a step was
done before asking for its result. Leave the screen untouched for 20 to 30 seconds while an instrumented read runs. Do not
write test markers through browser automation: in the 18.6.2 study the safaridriver automation window had
its own website data, separate from the owner's Safari profile, so a marker written there would not be
where the test looks (N06).

**P12. Harness bytes and installed apps are frozen between comparable runs.** A harness version is never
moved, redirected or edited once a run has used it, except to fix a privacy or security defect, which is
published as a dated erratum with the old and new hashes; new versions get new, non-overlapping scopes. The test
apps installed for a before-and-after study keep their scope and start URL until the after run is done.

## 6. Application to openpwa.net

The framework is being built into the structure of the site's evidence. The definition page, its frozen
version pages and change history, the Device Lab with its behaviour pages, and the study with its data
package [S1] are published with v1.0. The compatibility-table badges and the reference-page evidence strip
are planned; each will be listed in the site changelog when it ships.

- **Definition page.** `/about/evidence/` (and `/zh/about/evidence/`) publishes this framework in site
  voice, with frozen version pages and a change history.
- **Compatibility tables (planned).** The matrix keeps its shape. Rows with measured evidence will carry a "Device-tested"
  badge and a numbered, dated footnote with the relation ("Measured 2026-10-20, iPhone 16 Pro, iOS 18.6.2
  (22G100): fires in Home Screen apps through both registration paths. Differs from BCD."). The caption
  will carry a legend naming the three layers and their classes.
- **Reference pages (planned).** An evidence strip under the availability banner: Documented (sources and last
  verified date) · Demonstrated (demo link) · Measured (latest run). Each item appears only when it exists.
- **Behaviour reference pages.** One page per behaviour topic (`/lab/behaviour/<topic>/`) with the
  question, the steps, per-build results with anchors, what the documentation says, the data, what it
  backs and its limits.
- **The Device Lab.** The public section that produces layer 3: protocol index, run guides, harness
  versions and hashes, a test roadmap, methodology and threats to validity, and the studies.
- **Studies.** Dated papers with data packages, such as the iOS 18.6.2 study [S1], each stating which
  layer its conclusions belong to.

## 7. Worked example: the iOS 18.6.2 study, claim by claim

Study: OpenPWA device test, 2026-10-20, iPhone 16 Pro, iOS 18.6.2 (22G100) [S1]. Every row is a layer 3
claim except where marked. "L1 relation" is the relation the result would carry on the matching support
row. "Prior" says whether a published description existed (P10).

| # | Claim (18.6.2, Home Screen app unless stated) | Layer | Class, label | Notebook | L1 relation | Prior |
|---|---|---|---|---|---|---|
| 1 | A page with no manifest and no icon, added to the Home Screen, opens in Safari with Safari's storage and worker; `display-mode: browser` | 3 | measured, A+S | N23, N63 | adds-condition (before iOS 26, standalone launch needs the `apple-mobile-web-app-capable` meta tag or a manifest `display` value) | documented (WebKit 16.4 [R38]; WebKit 26.0 for the change [R6]) |
| 2 | A manifest app opens standalone in a 402 × 812 viewport; only `display-mode: standalone` matches | 3 | measured, A+S | N13 | agrees (`display` standalone) | documented (confirmation; values added) |
| 3 | Icon precedence: 180 px apple-touch-icon over manifest icons; manifest `any` 192 otherwise; letter tile without icons | 3 | measured, S | N11, N63 | adds-condition (manifest `icons`) | documented (firt.dev [R8]) |
| 4 | localStorage and IndexedDB are never copied between Safari and the app, in either direction | 3 | measured, A | N13, N16 to N20 | adds-condition (storage partitioning) | documented (WebKit 17.2) |
| 5 | A first-party cookie is copied once into the new app, then independent; each app has its own cookie store | 3 | measured, A (copy timing moderate) | N18 to N22 | adds-condition | replication of WebKit 17.2 [R5] |
| 6 | `notificationclick` fires through both registration paths, 6 of 6 taps, each with a live window; `focus()` succeeds. No-window case not tested | 3 | measured, A | N35 to N40 | **differs** (BCD `version_added: false`) | developer reports in BCD issue #22959 [R2]; confirmation with new detail |
| 7 | `'onnotificationclick' in self` true in an app-controlled worker, false in a tab-controlled worker | 3 | measured, A | N03, N18, N34 | adds-condition; explains the collector result | **new** as far as we found |
| 8 | The permission prompt appears after a tap; `requestPermission()` stays pending until answered (2068 ms) | 3 | measured, A+S | N53, N54, N58, N59 | agrees | documented |
| 9 | One grant covers both push managers; with a subpath-scoped worker, `window.pushManager.getSubscription()` returns null. Root-scoped worker not tested | 3 | measured, A | N32, N33, N41 | adds-condition (DWP row) | consistent with WebKit's DWP post [R7] |
| 9b | `window.pushManager` exists in a plain Safari tab, where `PushManager` and `Notification` do not (exposure only) | 3 | measured, A | N03, N41 | adds-condition | **new** as far as we found |
| 10 | Default status-bar style: viewport starts 62 px below the top, strip solid `#161616`, no blur; `viewport-fit=cover` adds only a 34 px bottom inset | 3 | measured, A (geometry) + S (pixels) | N25 to N29, N62 | adds-condition | behaviour documented; no public 18.x values found |
| 10c | Strip colour: page `theme-color` meta over manifest `theme_color`; manifest as fallback | 3 | measured, S+O | N64 to N65-a | adds-condition (both theme rows) | precedence not stated in the sources we read; not claimed as new |
| 11 | `black-translucent` + `viewport-fit=cover` puts the page under the status bar: viewport 402 × 874, inset 62 px | 3 | measured, A (+O appearance) | N55 | agrees | documented |
| 12 | `setAppBadge(3)` shows "3" on the icon; clearing reported only by the operator | 3 | measured, S (clear: O, not published) | N60 | agrees | documented |
| 13 | After a swipe-away, the previous document was alive about 6 s later and found by `clients.matchAll()` | 3 | measured, A | N16, N38, N40 | none (no support row) | not checked; needs more runs before any general claim |
| 14 | `BeforeInstallPromptEvent` and `navigator.install` are absent on this build | 3 | measured, A | study report §T9 | agrees (BCD: not supported) | documented |
| 15 | BCD: Safari iOS `notificationclick_event` unsupported | 1 | documented (BCD) | n/a | (row source) | n/a |
| 15b | WebKit: cookies are copied into a web app when it is added (Safari 17.2) | 3 | documented (WebKit [R5]) | n/a | n/a | n/a |
| 16 | Push permission demo on `/demo/push/` | 2 | demonstrated | n/a | n/a | n/a |
| X1 | "The status bar was blue / followed the page's top colour" | n/a | **retracted** (N46) | N46 | do not cite | n/a |
| X2 | "theme-color has no effect" and "the app uses the manifest `theme_color`" | n/a | **refuted** (N65, N65-a) | N65 | do not cite | n/a |

Three things the table shows. First, every result of the study is a layer 3 record, and only two of them
are new as far as we found (7 and 9b). The value of the rest is
that they are dated, measured on a named build and reusable as conditions on support rows. Second, the
retractions are part of the record: the colour-source question went through two wrong readings before the
three-app test settled it, and the framework keeps those readings visible as "do not cite" instead of
deleting them. Third, the same feature can sit in all three layers at once (rows 6, 15 and 16), and the
same behaviour can be both documented and measured (rows 5 and 15b), each labelled for what it is.

## 8. Research agenda

- **Per-release measurement.** Rerun the core tests on each iOS and Safari point release, about one hour
  per release, and add a dated row per behaviour. Bug-fix releases rerun only tests whose subject the
  release notes mention.
- **iOS 27 same-device rerun.** The second study: the same iPhone, upgraded from 18.6.2, with the same
  installed Home Screen apps and the same harness v1 bytes. Each behaviour gets a before-and-after
  comparison across one intervention, the upgrade (time and other device state also change, and the
  study will record what it can of them). Questions it can settle that a fresh device cannot: whether
  existing apps keep their storage, cookies, permission and push subscription across the upgrade; whether
  the manifest-less launch default changes for an icon added before the upgrade; whether the status-bar
  precedence holds.
- **Gaps from 18.6.2.** The `clients.openWindow()` path when no window exists; cookie copy timing (at add
  versus at first launch); badge clearing (O only in the 18.6.2 study); Declarative Web Push with a root-scoped worker,
  which needs a separate origin.
- **Other platforms.** Android Chrome and Samsung Internet (install prompts, `navigator.install`, share
  target), desktop Chromium (file handling, launch handler), Firefox where Mozilla documents install
  surfaces, iPadOS (multitasking windows, add sheet).
- **Independent replication.** A results format that lets other people submit runs, labelled as community
  results and kept apart from operator runs.
- **Framework evaluation.** Measure how often support rows gain `adds-condition` or `differs` relations
  over a year, and how often a later build reverses an earlier measurement. If the relations stay rare, the
  framework is overhead; if they are common, the support layer alone is misleading at that rate.

## 9. Relationship to existing work

Every ingredient of this framework already exists somewhere. Sources were read on 2026-10-20; where a
page renders only with JavaScript, its repository or data files were read instead.

### 9.1 Prior work by area

**Compatibility data.** caniuse gives each browser version one value (`y`, `a` for partial, `n`, `u`,
`p`, `x`, `d`) with numbered notes and known bugs; its contribution guide lists a link to test cases among the marks of a good new-feature pull request [R10], and
its test suite checks "basic support", warning that a "test may pass but support is actually buggy"
[R11]. BCD support statements carry `version_added` (a version, `false`, `"preview"` or a ranged `"≤"`
value), `flags`, `prefix`, `partial_implementation` and `notes` [R12, R13]. BCD also allows behavioural
subfeatures for "a contextual support condition that is not readily feature detectable", and it already
records installed-context differences: Screen Wake Lock on Safari iOS is `partial_implementation` from
16.4 up to, not including, 18.4 with the note "Does not work in standalone Home Screen Web Apps" [R14]. BCD updates are
assisted by mdn-bcd-collector, which generates feature-detection tests from Web IDL and CSS definitions
and runs them as pages in browsers, optionally through Selenium on cloud browser services [R15]. The support layer therefore already carries context, as notes and
subfeatures on a version range. It does not carry a test date, an OS build, a device, raw data or a
re-test schedule for those notes.

**Conformance and interoperability testing.** web-platform-tests and wpt.fyi run specification test
suites in the major desktop browsers, and Interop scores selected focus areas each year; in Interop 2026,
mobile testing is an investigation area, not a scored one, and Mozilla's announcement notes that a browser
can score well "while having inconsistent behavior" [R16, R17]. None of these descriptions covers Home
Screen launch, the status bar, icons or permission prompts. The testing literature draws the same line. ISO/IEC
9646 defines conformance testing against a standard's requirements [R31]; ETSI separates it from
interoperability testing and notes that "items passing conformance testing may still not interoperate"
[R32]. The W3C QA Framework names the reason a third kind of evidence is needed: specifications contain
"discretionary items", behaviour left to the user agent [R33]. Most of what layer 3 records on iOS
(status-bar colour, icon choice, cookie copy, launch default) is of that kind.

**Summaries and launch tracking.** Baseline (W3C WebDX Community Group, web-features) labels features
Limited, Newly or Widely available from BCD, excluding partial implementations [R18]. webstatus.dev
combines BCD, WPT and web-features [R19]. Chrome Platform Status tracks Blink launches [R20]. WebKit's
feature status page is retired; Safari release notes remain the vendor record and have "Home Screen Web
Apps" sections [R21]. All are layer 1 sources here.

**Demonstrations and practitioner notes.** whatpwacando.today offers over 40 live demos and shows what the
visitor's device supports [R22]; it is the clearest layer 2 resource and publishes no dated results.
Maximiliano Firtman's iOS PWA notes are the closest content analog to layer 3: they separate installed
apps from Safari tabs per feature and record precedence rules such as "`apple-touch-icon` overrides
manifest icons" [R8]. Their evidence is the author's private testing; methods, devices and raw data are
not published.

**Context and dated real-client tests.** caniwebview (W3C WebView Community Group) adds WebView as a
compatibility context, from BCD and hand-written quirk notes [R34]. Steiner (2018) compared PWA feature
exposure in WebViews and browsers [R28]. caniemail is the strongest methodological precedent: each
feature records a `last_test_date`, a `test_url` and a `test_results_url`, with support split per client
and platform, each entry keyed by a client version (Apple Mail 12.4) or a test month (Gmail 2019-02) [R35]. It tests email clients, not browsers, and in the files we read
it does not record OS builds or hashes.

**Research and measurement at scale.** WebDiff, CrossCheck and X-PERT detect rendering and behaviour
differences between desktop browsers [R25, R27, R26], as does the work of Mesbah and Prasad [R24]. Early PWA papers
assessed the approach for cross-platform development [R29, R30]; the Web Almanac measures how sites use
PWA features [R23]; studies of feature use on the web exist [R39]. We found no published empirical study of
Home Screen web-app behaviour on iOS with released data. Grading claims by evidence strength is standard
elsewhere, as GRADE in medicine [R36] and in software-engineering reviews [R37]; we adapt the idea.

### 9.2 What is new, and what is not

| Element | Closest prior art | Our assessment |
|---|---|---|
| Recording that support differs by context (installed app vs tab, WebView vs browser) | BCD notes and contextual subfeatures [R13, R14]; caniuse notes; caniwebview [R34]; firt.dev [R8]; Steiner [R28] | **Exists.** Not claimed. |
| (a) Installed-app and device-context behaviour as a first-class layer with its own evidence class, rather than a note on a support statement | The same sources, where behaviour appears as notes, subfeatures or unaudited tables | **Partly new.** The content exists; making it a separate layer with its own evidence requirements is, as far as we found, new. |
| (b) An explicit documented / demonstrated / measured grade on every claim | GRADE [R36]; SE evidence grading [R37]; caniuse `u` and test links [R10] | **New in web compatibility, adapted from other fields.** |
| (c) Back-filling support rows with dated, OS-build-level, hashed device results as relations (agrees, adds-condition, differs) | caniemail dated tests [R35]; mdn-bcd-results raw collector output [R15]; BCD notes linking bugs | **Partly new.** Dated real-client testing exists in caniemail; build-level resolution, device and install context, hashed raw data and the three relations on a browser support table did not appear in the sources we read. |
| (d) Same-device before-and-after studies across OS upgrades | Pre/post repeated measures and regression testing generally; scattered forum reports of upgrade regressions | **Partly new.** The design is textbook; a published, reproducible before-and-after dataset for web-app behaviour was not found. "First published, to our knowledge", not a new method. |
| Separating conformance from behaviour in context | ISO/IEC 9646 [R31], ETSI [R32], W3C QA Framework discretionary items [R33] | **Exists.** We rely on it. |

In short, OpenPWA formalises and names a structure that the field already uses informally.
The contribution is that the structure is explicit, graded per claim, context-aware at OS-build level,
and auditable from published data. We would welcome a pointer to any earlier source that does all four,
and will cite it in the next version.

## 10. How to adopt and cite

**Licence.** This text is published under Creative Commons Attribution 4.0 International (CC BY 4.0):
anyone may copy, translate, adapt or extend it, including commercially, with attribution. Using the
framework as a method needs no licence at all; we ask that adopters cite it.

**Citation.**

> OpenPWA Editorial Team. *The OpenPWA Evidence Layers: support, capability and behaviour as separate
> claims about web platform features.* Version 1.0, 2026-10-20. openpwa.net.
> https://openpwa.net/about/evidence/v1.0/

Short form in running text: "OpenPWA Evidence Layers v1.0". When citing a single definition, add the
fragment (for example `#p8` or `#decision-procedure`).

**Adopting it.** A site or dataset adopts the framework by labelling each claim with its layer and
evidence class, publishing the requirements for "measured" that it applies (at least those of 3.1), and
naming the version it follows. It need not use OpenPWA's labels, data model or harness.

**Version policy.** Major versions change or remove a layer, an evidence class or a principle. Minor
versions add principles, boundary cases or display rules. Patch versions fix wording. Every published
version keeps a frozen URL (`/about/evidence/v<major>.<minor>/`), and the change history is append-only.

## 11. Glossary

- **Claim**: one statement about a web platform feature that a reader could act on.
- **Layer**: the kind of question a claim answers: Support (1), Capability (2), Behaviour (3).
- **Evidence class**: what backs a claim: documented, demonstrated or measured.
- **Context**: the conditions of a behaviour claim: device, OS build, launch context (tab, Home Screen app),
  state (fresh, after add, after relaunch, after swipe-away).
- **Run**: one execution of a protocol on one device and build, on one date.
- **Harness**: the set of test pages and apps a run loads, versioned and hashed.
- **Protocol**: the published steps, recording fields and environment block for a test.
- **Confidence label**: A (instrumented read), S (screenshot or recording), O (observer report).
- **Relation**: how a measured result bears on a support row: agrees, adds-condition, differs.
- **Back-fill**: attaching a dated measured result to a support row as a relation and condition.
- **Replication**: a measured result that confirms a published description.
- **Same-device study**: a before-and-after comparison on one physical device across an OS upgrade, with
  the same installed apps and harness bytes.

## References

All URLs accessed 2026-10-20. "Repository read" means the page renders with JavaScript and its source data
was read instead.

**Study and site**

- [S1] OpenPWA Editorial Team. "Home Screen web apps on iOS 18.6.2: an instrumented single-device study of
  display mode, storage, status bar and notification behaviour." Version 1, 2026-10-20. Data:
  https://openpwa.net/research/2026-10-ios18-home-screen-web-apps/data/ . Citation string: OpenPWA device
  test, 2026-10-20, iPhone 16 Pro, iOS 18.6.2 (22G100).
- [S2] OpenPWA. "Methodology." https://openpwa.net/about/methodology/

**Vendor documentation and compatibility data**

- [R1] mdn/browser-compat-data. `api/ServiceWorkerGlobalScope.json`, `notificationclick_event`.
  https://github.com/mdn/browser-compat-data/blob/main/api/ServiceWorkerGlobalScope.json
- [R2] mdn/browser-compat-data issue #22959, "api.ServiceWorkerGlobalScope.notificationclick_event - It
  looks like the events are actually fired on iOS Safari - please verify." Opened 2024-04-29.
  https://github.com/mdn/browser-compat-data/issues/22959
- [R3] mdn/browser-compat-data. `html/elements/meta.json`, `name.theme-color`.
  https://github.com/mdn/browser-compat-data/blob/main/html/elements/meta.json
- [R4] mdn/browser-compat-data. `manifests/webapp/theme_color.json`.
  https://github.com/mdn/browser-compat-data/blob/main/manifests/webapp/theme_color.json
- [R5] WebKit. "WebKit Features in Safari 17.2." 2023-12-11. https://webkit.org/blog/14787/webkit-features-in-safari-17-2/
- [R6] WebKit. "WebKit Features in Safari 26.0." 2025-09-15. https://webkit.org/blog/17333/webkit-features-in-safari-26-0/
- [R7] WebKit. "Meet Declarative Web Push." 2025-03-27. https://webkit.org/blog/16535/meet-declarative-web-push/
- [R8] M. Firtman. "iOS PWA Compatibility." firt.dev, updated 2026-10-13. https://firt.dev/notes/pwa-ios/
- [R9] WebKit Bugzilla. Bug 268797, "notificationclick events in serviceworkers not firing."
  https://bugs.webkit.org/show_bug.cgi?id=268797
- [R10] caniuse. https://caniuse.com ; data format and contribution rules:
  https://github.com/Fyrd/caniuse/blob/main/CONTRIBUTING.md
- [R11] caniuse tests. https://tests.caniuse.com/
- [R12] mdn/browser-compat-data. Data guidelines.
  https://github.com/mdn/browser-compat-data/blob/main/docs/data-guidelines/README.md
- [R13] mdn/browser-compat-data. Compat data schema.
  https://github.com/mdn/browser-compat-data/blob/main/schemas/compat-data-schema.md
- [R14] mdn/browser-compat-data. `api/WakeLock.json` (Safari iOS 16.4 to 18.4 partial, note "Does not work
  in standalone Home Screen Web Apps"). https://github.com/mdn/browser-compat-data/blob/main/api/WakeLock.json
- [R15] Open Web Docs. mdn-bcd-collector. https://github.com/openwebdocs/mdn-bcd-collector ; results:
  https://github.com/openwebdocs/mdn-bcd-results
- [R16] web-platform-tests. "About wpt.fyi." https://wpt.fyi/about
- [R17] Interop 2026 dashboard, https://wpt.fyi/interop-2026 (repository read:
  https://github.com/web-platform-tests/interop); Mozilla Hacks, "Launching Interop 2026," 2026-02-12,
  https://hacks.mozilla.org/2026/02/launching-interop-2026/
- [R18] W3C WebDX Community Group. web-features, Baseline definition.
  https://github.com/web-platform-dx/web-features/blob/main/docs/baseline.md ; https://web.dev/baseline
- [R19] webstatus.dev. https://webstatus.dev (repository read: https://github.com/GoogleChrome/webstatus.dev)
- [R20] Chrome Platform Status. https://chromestatus.com (repository read:
  https://github.com/GoogleChrome/chromium-dashboard)
- [R21] WebKit Feature Status (retired). https://webkit.org/status/ ; Apple, Safari release notes,
  https://developer.apple.com/documentation/safari-release-notes
- [R22] whatpwacando.today. https://whatpwacando.today/
- [R23] HTTP Archive. Web Almanac 2025, chapter "PWA." https://almanac.httparchive.org/en/2025/pwa
- [R34] W3C WebView Community Group. caniwebview. https://caniwebview.com/
- [R35] caniemail. https://www.caniemail.com/ ; feature data: https://github.com/hteumeuleu/caniemail
- [R38] WebKit. "WebKit Features in Safari 16.4." 2023-03-27. https://webkit.org/blog/13966/webkit-features-in-safari-16-4/

**Research and standards**

- [R24] A. Mesbah, M. R. Prasad. "Automated cross-browser compatibility testing." ICSE 2011.
  https://doi.org/10.1145/1985793.1985870
- [R25] S. Roy Choudhary, H. Versee, A. Orso. "WEBDIFF: Automated identification of cross-browser issues in
  web applications." ICSM 2010. https://doi.org/10.1109/ICSM.2010.5609723
- [R26] S. Roy Choudhary, M. R. Prasad, A. Orso. "X-PERT: Accurate identification of cross-browser issues in
  web applications." ICSE 2013. https://doi.org/10.1109/ICSE.2013.6606616
- [R27] S. Roy Choudhary, M. R. Prasad, A. Orso. "CrossCheck: Combining crawling and differencing to better
  detect cross-browser incompatibilities in web applications." ICST 2012. https://doi.org/10.1109/ICST.2012.97
- [R28] T. Steiner. "What is in a Web View? An Analysis of Progressive Web App Features When the Means of
  Web Access is not a Web Browser." WWW '18 Companion. https://doi.org/10.1145/3184558.3188742
- [R29] A. Biørn-Hansen, T. A. Majchrzak, T.-M. Grønli. "Progressive Web Apps: The Possible Web-native
  Unifier for Mobile Development." WEBIST 2017. https://doi.org/10.5220/0006353703440351
- [R30] T. A. Majchrzak, A. Biørn-Hansen, T.-M. Grønli. "Progressive Web Apps: the Definite Approach to
  Cross-Platform Development?" HICSS 2018. https://doi.org/10.24251/HICSS.2018.718
- [R31] ISO/IEC 9646-1:1994. "OSI conformance testing methodology and framework, Part 1: General
  concepts." https://www.iso.org/standard/17473.html (page not readable by our client; definition taken from
  ETSI's citation of it, [R32])
- [R32] ETSI. "Conformance and interoperability testing: a comparison."
  https://docbox.etsi.org/MTS/MTS/10-PromotionalMaterial/MBS-20111118/Testing/Comparison/comparison.htm
- [R33] W3C. "QA Framework: Specification Guidelines." W3C Recommendation, 2005-08-17.
  https://www.w3.org/TR/qaframe-spec/
- [R36] G. H. Guyatt et al. "GRADE: an emerging consensus on rating quality of evidence and strength of
  recommendations." BMJ 2008. https://doi.org/10.1136/bmj.39489.470347.AD
- [R37] T. Dybå, T. Dingsøyr. "Strength of evidence in systematic reviews in software engineering." ESEM
  2008. https://doi.org/10.1145/1414004.1414034
- [R39] P. Snyder, L. Ansari, C. Taylor, C. Kanich. "Browser Feature Usage on the Modern Web." IMC 2016.
  https://doi.org/10.1145/2987443.2987466

## Appendix: naming

Three candidate names were checked on 2026-10-20 by web search for the phrase with web, browser and PWA
context.

| Candidate | Collision check | Verdict |
|---|---|---|
| **OpenPWA Three-Layer Model** | No use in web compatibility found. "Three-layer" and "three-tier" are standard names for the presentation / application / data architecture, so the bare phrase is generic and hard to search. | Usable descriptively ("the three-layer model"), weak as a name |
| **Support–Capability–Behaviour (SCB) model** | No exact use of the phrase in either spelling. Nearby wording: Australia's NDIS "Positive Behaviour Support Capability Framework" and the COM-B behaviour-change model. The acronym SCB is heavily taken: Siam Commercial Bank, Standard Chartered Bank, Statistics Sweden, a privileged-access product ("Shell Control Box") and an IEEE paper titled "Secure Cloud Browser". | Keep the three words as the subtitle; never use the bare acronym |
| **OpenPWA Evidence Layers** | No use found. "Evidence layers" appears in a 2026 safety-assurance blog post about design, implementation and performance evidence, which is an analogous idea in another field rather than a conflict. | **Recommended** |

**Recommendation: "OpenPWA Evidence Layers", subtitle "Support, Capability, Behaviour".** It carries the
platform name, so it is attributable and searchable. It names what the framework is about (evidence)
rather than a count, so a later version can change the number of layers without renaming. It matches the
`/about/evidence/` URL.
"The three-layer model" stays available as an informal description in prose.

Short labels:

| Element | EN | ZH |
|---|---|---|
| Framework | OpenPWA Evidence Layers | OpenPWA 证据分层 |
| Layer 1 | Support | 支持 |
| Layer 2 | Capability | 能力 |
| Layer 3 | Behaviour | 行为 |
| Class | documented | 文档记载 |
| Class | demonstrated | 演示可见 |
| Class | measured | 真机实测 |
| Row badge | Device-tested | 真机实测 |
| Confidence | A instrumented read · S screenshot or recording · O observer report | A 仪器读数 · S 截图或录屏 · O 观察者口述 |
| Relation | agrees · adds a condition · differs | 一致 · 补充条件 · 不符 |
