Operator Briefing
Unified daily operator briefing report. A workflow-scope report over the
daily-briefing workflow that loops the run's step executions, dispatches
each step by modelType to a per-source normalizer, and flattens everything
into two projections: a prioritized four-tier review queue and a set of ops
signals. It renders a consistent markdown briefing plus a STABLE JSON
contract that downstream renderers (a live HTML view, executive R/vellum
reports) consume — observe once, render many.
Sources (today)
@webframp/gitlab— cross-project review queue (MRs + todos), tiered per the daily-briefing design: waiting on you / awaiting your merge / mentions / your open MRs. Dedups onreference, folds assigned∩authored into your-MRs, and drops items you have already approved.@webframp/anthropic/analytics— seats (DAU/WAU/MAU), adoption, cost window. Acollected: falsefetch is rendered "unavailable", never as a zero.@webframp/anthropic/compliance— effective-settings count and recent activity volume.@webframp/aws/service-quotas— per-service quota utilization over threshold and pending increase requests, withfailedProfilesdegradation (including thesso-login-requiredre-auth hint).
Adding a source is one workflow step plus one normalizer plus one registry line; the render / tiering / freshness core does not change.
Accuracy
Freshness is judged from each source's own fetchedAt (stale > 24h for ops,
7d for queue items). Unknown modelType / missing normalizer / parse failure are skipped and counted. The report degrades — it never throws.
Reports
@webframp/operator-briefing(workflow scope) — the full daily briefing: GitLab review queue plus ops signals, rendered after adaily-briefingworkflow run completes.@webframp/operator-briefing/review-queue(method scope) — a fast path that renders just the four GitLab review tiers LIVE on everylist_my_merge_requestsrun, reusing the same normalizer and renderer so its output matches the briefing's GitLab section (no ops section).
Models
@webframp/operator-briefing/metrics— a durable append-only time-series accumulator. Point-in-time briefing data is re-observable, but a time series is not: once a versioned snapshot is GC'd that historical point is gone. Itsappend_metricsmethod upserts one day's metrics (spend, DAU/WAU/MAU, seats, AWS quota counts, …) by date into a singleseriesresource whose latest version holds the entire history, so trend charts survive garbage collection. It merges fields for a shared date, never throws, and never overwrites a longer history with a shorter one.
Usage
Require the workflow report on the daily-briefing workflow; it renders after
the run completes. Require the method report on the @webframp/gitlab model's
list_my_merge_requests method for a live queue between briefings. Read the
results with:
swamp data get report-@webframp/operator-briefing --markdown
swamp data get report-@webframp/operator-briefing-json --json
swamp data get "report-@webframp/operator-briefing/review-queue" --markdown2026.07.18.2
Added: An upgrades array entry (no-op) to metrics.ts for proper typeVersion tracking on existing instances. No schema or behavior changes.
2026.07.18.1
Changed: Pinned the zod import specifier in the metrics model to
npm:zod@4.4.3 (was npm:zod@^4.3.6) for hermetic dependency resolution. No
runtime behavior change.
2026.07.13.5
Fixed: The daily briefing falsely reported degraded: true whenever the
metrics_append step ran in the daily-briefing workflow.
The workflow-scope report loops every step execution and dispatches by
modelType. The durable metrics accumulator
(@webframp/operator-briefing/metrics) runs as a step but is not a briefing
source — it has no normalizer by design — so it was skipped-and-counted like
an unknown source, which set sourceErrors.skippedSteps and flipped the whole
briefing to degraded: true with a spurious "No normalizer …" note.
The report now recognizes a set of non-source model types
(nonSourceModelTypes in the normalizer registry; today just the metrics
accumulator) and skips them silently — no skipped-source count, no note, no
degraded flag. A missing normalizer for any other modelType is still a real
gap and is skipped-and-counted as before.
2026.07.13.4
Added a dashboard renderer to the metrics model — the metrics series (and, optionally, the daily briefing) becomes a self-contained HTML page. Observe once, render many.
- New
render_dashboardmethod (@webframp/operator-briefing/metrics). Reads the model's own append-onlyseries(trend history) and takes an optionalreportargument — the operator-briefing JSON contract (review queue + ops signals), wired in by the workflow; it is never cross-read from storage. Renders ONE self-contained HTML document — inline SVG sparklines, stat tiles, tier counts, and an ops table, theme-aware, with no external JS/CDN (CSP-safe; renders in a browser or a claude.ai Artifact). Reads only its own data, never fetches, and degrades rather than throwing (empty series → trends-empty page; a malformed ornull-bearing report is filtered, not fatal). - New
dashboardfile resource (text/html, lifetime30d,garbageCollection10). A regenerated downstream projection, so short retention is right. Written viacreateFileWriter().writeText(). redact: trueshareable mode. Produces a variant that shows only aggregate tier counts, ops severities/labels, and non-identifying numeric trends — every reference, author, title, opsdetail, anddegradedReasonis stripped, so no internal URL, username, or account name reaches the page (CLAUDE.md forbids exposing internal identifiers). The default (redact: false) is the operator-local full-detail view.
Additive: append_metrics, the series resource, and the existing reports and
JSON contract are all unchanged.
2026.07.13.3
Added a durable time-series accumulator — the package's first model — so trends (spend, DAU burndown, adoption growth) survive version garbage collection.
- New
metricsmodel (@webframp/operator-briefing/metrics). Point-in-time briefing data is always re-observable, so GC-ing its snapshots is harmless. A time series is not: once a versioned snapshot is GC'd, that historical point is gone forever. So the series is stored as first-class data in a single append-onlyseriesresource whose LATEST version holds the entire history (an array of dated rows). Version-GC then only drops old partial states; the latest always has everything, so keeping a handful of versions is safe. append_metricsmethod. Upserts one day's metrics onto the series by date. It reads the latest series, MERGES fields for a shared date (a run that carries only spend never wipes that day's dau), sorts ascending by date, and writes the whole series back under the stable name "metrics" so it versions in place. A one-timebackfillarray seeds prior dates (incoming wins on a shared date, still field-merged).- Never throws, and never clobbers. The cardinal rule of an append-only
accumulator is that a shorter series must never overwrite a longer one. So a
write happens only when the prior history is KNOWN: a genuinely absent (null)
series is treated as empty and written fresh, but a prior series that can't be
READ (a thrown read — transient I/O, not proof of absence) or is MALFORMED
(
rowsnot an array, or a non-empty array with zero parseable rows) SKIPS the write rather than truncate real history. A degrade AFTER the read — a failingwriteResourceas the payload grows, a throwing logger — likewise leaves the stored series untouched (no fallback empty write). A wrong-shaped or non-finite metric is skipped rather than fatal, and a metric value of0is preserved as real data (0 is a number, not "absent"). Dates are validated as zero-paddedYYYY-MM-DD, which also guarantees the lexicographic
| Argument | Type | Description |
|---|---|---|
| date | string | The row date in zero-padded YYYY-MM-DD form (required). |
| spendUsd? | number | Spend in USD for the day. |
| dau? | number | Daily active users. |
| wau? | number | Weekly active users. |
| mau? | number | Monthly active users. |
| activeSeats? | number | Active seats. |
| totalSeats? | number | Total provisioned seats. |
| projects? | number | Project count. |
| skills? | number | Skill count. |
| connectors? | number | Connector count. |
| quotaOverCount? | number | Count of AWS quotas over threshold. |
| pendingCount? | number | Count of pending quota-increase requests. |
| backfill? | array | Optional prior rows to seed once. Applied before the current run's row; incoming values win on a shared date. |
| Argument | Type | Description |
|---|---|---|
| redact? | boolean | Produce a shareable, redacted dashboard: aggregate counts + numeric trends only, with every reference / author / ops detail stripped. Default false (operator-local, full detail). |
| title? | string | Dashboard title. Defaults to 'Operator Briefing'. |
| report? | record | Optional operator-briefing report JSON (the BriefingJson contract: tiers, ops, generatedAt, degraded). When present, the dashboard adds a review-queue and ops-signals section; when absent it renders trends only. |
Resources
Files
Unified daily operator briefing: GitLab review queue (four tiers) plus ops signals (analytics, compliance, AWS quotas), normalized into a consistent markdown briefing and a stable JSON contract.
Fast-path GitLab review queue (four tiers) rendered live on every `list_my_merge_requests` run. Reuses the daily briefing's shared normalizer and renderer so its output matches the briefing's GitLab section; emits the same stable JSON contract restricted to the queue tiers (no ops).
2026.07.18.1
Changed: Pinned the zod import specifier in the metrics model to
npm:zod@4.4.3 (was npm:zod@^4.3.6) for hermetic dependency resolution. No
runtime behavior change.
2026.07.13.5
Fixed: The daily briefing falsely reported degraded: true whenever the
metrics_append step ran in the daily-briefing workflow.
The workflow-scope report loops every step execution and dispatches by
modelType. The durable metrics accumulator
(@webframp/operator-briefing/metrics) runs as a step but is not a briefing
source — it has no normalizer by design — so it was skipped-and-counted like
an unknown source, which set sourceErrors.skippedSteps and flipped the whole
briefing to degraded: true with a spurious "No normalizer …" note.
The report now recognizes a set of non-source model types
(nonSourceModelTypes in the normalizer registry; today just the metrics
accumulator) and skips them silently — no skipped-source count, no note, no
degraded flag. A missing normalizer for any other modelType is still a real
gap and is skipped-and-counted as before.
2026.07.13.4
Added a dashboard renderer to the metrics model — the metrics series (and, optionally, the daily briefing) becomes a self-contained HTML page. Observe once, render many.
- New
render_dashboardmethod (@webframp/operator-briefing/metrics). Reads the model's own append-onlyseries(trend history) and takes an optionalreportargument — the operator-briefing JSON contract (review queue + ops signals), wired in by the workflow; it is never cross-read from storage. Renders ONE self-contained HTML document — inline SVG sparklines, stat tiles, tier counts, and an ops table, theme-aware, with no external JS/CDN (CSP-safe; renders in a browser or a claude.ai Artifact). Reads only its own data, never fetches, and degrades rather than throwing (empty series → trends-empty page; a malformed ornull-bearing report is filtered, not fatal). - New
dashboardfile resource (text/html, lifetime30d,garbageCollection10). A regenerated downstream projection, so short retention is right. Written viacreateFileWriter().writeText(). redact: trueshareable mode. Produces a variant that shows only aggregate tier counts, ops severities/labels, and non-identifying numeric trends — every reference, author, title, opsdetail, anddegradedReasonis stripped, so no internal URL, username, or account name reaches the page (CLAUDE.md forbids exposing internal identifiers). The default (redact: false) is the operator-local full-detail view.
Additive: append_metrics, the series resource, and the existing reports and
JSON contract are all unchanged.
2026.07.13.3
Added a durable time-series accumulator — the package's first model — so trends (spend, DAU burndown, adoption growth) survive version garbage collection.
- New
metricsmodel (@webframp/operator-briefing/metrics). Point-in-time briefing data is always re-observable, so GC-ing its snapshots is harmless. A time series is not: once a versioned snapshot is GC'd, that historical point is gone forever. So the series is stored as first-class data in a single append-onlyseriesresource whose LATEST version holds the entire history (an array of dated rows). Version-GC then only drops old partial states; the latest always has everything, so keeping a handful of versions is safe. append_metricsmethod. Upserts one day's metrics onto the series by date. It reads the latest series, MERGES fields for a shared date (a run that carries only spend never wipes that day's dau), sorts ascending by date, and writes the whole series back under the stable name "metrics" so it versions in place. A one-timebackfillarray seeds prior dates (incoming wins on a shared date, still field-merged).- Never throws, and never clobbers. The cardinal rule of an append-only
accumulator is that a shorter series must never overwrite a longer one. So a
write happens only when the prior history is KNOWN: a genuinely absent (null)
series is treated as empty and written fresh, but a prior series that can't be
READ (a thrown read — transient I/O, not proof of absence) or is MALFORMED
(
rowsnot an array, or a non-empty array with zero parseable rows) SKIPS the write rather than truncate real history. A degrade AFTER the read — a failingwriteResourceas the payload grows, a throwing logger — likewise leaves the stored series untouched (no fallback empty write). A wrong-shaped or non-finite metric is skipped rather than fatal, and a metric value of0is preserved as real data (0 is a number, not "absent"). Dates are validated as zero-paddedYYYY-MM-DD, which also guarantees the lexicographic sort is chronological.
Additive: the existing reports and the stable JSON contract are unchanged.
2026.07.13.2
**Enriched the stable JSON contract so downstrea
Modified 1 models
2026.07.13.3
Added a durable time-series accumulator — the package's first model — so trends (spend, DAU burndown, adoption growth) survive version garbage collection.
- New
metricsmodel (@webframp/operator-briefing/metrics). Point-in-time briefing data is always re-observable, so GC-ing its snapshots is harmless. A time series is not: once a versioned snapshot is GC'd, that historical point is gone forever. So the series is stored as first-class data in a single append-onlyseriesresource whose LATEST version holds the entire history (an array of dated rows). Version-GC then only drops old partial states; the latest always has everything, so keeping a handful of versions is safe. append_metricsmethod. Upserts one day's metrics onto the series by date. It reads the latest series, MERGES fields for a shared date (a run that carries only spend never wipes that day's dau), sorts ascending by date, and writes the whole series back under the stable name "metrics" so it versions in place. A one-timebackfillarray seeds prior dates (incoming wins on a shared date, still field-merged).- Never throws, and never clobbers. The cardinal rule of an append-only
accumulator is that a shorter series must never overwrite a longer one. So a
write happens only when the prior history is KNOWN: a genuinely absent (null)
series is treated as empty and written fresh, but a prior series that can't be
READ (a thrown read — transient I/O, not proof of absence) or is MALFORMED
(
rowsnot an array, or a non-empty array with zero parseable rows) SKIPS the write rather than truncate real history. A degrade AFTER the read — a failingwriteResourceas the payload grows, a throwing logger — likewise leaves the stored series untouched (no fallback empty write). A wrong-shaped or non-finite metric is skipped rather than fatal, and a metric value of0is preserved as real data (0 is a number, not "absent"). Dates are validated as zero-paddedYYYY-MM-DD, which also guarantees the lexicographic sort is chronological.
Additive: the existing reports and the stable JSON contract are unchanged.
2026.07.13.2
Enriched the stable JSON contract so downstream renderers get clickable links and chartable AWS data directly from the contract — no reaching around to raw data resources.
QueueItem.url. Every queue item now carries an optional deep link — an MR'swebUrlor a todo'stargetUrl— so a renderer can make the reference clickable. This also covers issue-todos that have no derivablereferencebut do have atargetUrl; they now get aurltoo. Left undefined when the source carries no URL — never fabricated.- Structured, account-redacted AWS
entrieson theOpsSignal. A utilization signal (ec2/vpc/eks) now carries its over-threshold quotas as{ quotaName, utilizationPct, usageValue, value, adjustable }, and the pending signal carries{ quotaName, serviceCode, desiredValue, status }per request — chartable quota facts without parsing the detail string. The entries NEVER include an account identifier (profile,accountId,requestId,caseId, or any bare account number); CLAUDE.md forbids exposing internal account IDs. A degraded fetch that observed nothing leavesentriesabsent and keeps the honest "not checked" phrasing unchanged.
Both additions are additive to the JSON contract; the markdown projection is unchanged.
Hardening from a second adversarial review:
- Account-number redaction now catches embedded digit runs. Redaction
previously masked a profile segment only when it was ENTIRELY digits, so an
account number embedded in a longer name (
prod-123456789012) leaked intodetail. It now masks ANY 6+ digit run (prod-123456789012->prod-****) while leaving the all-digits case asaccount ****and never touching legitimate large quota values. - Null-safe entry mapping. The AWS entry mappers now filter to real objects
before mapping, so a
nullelement in a resource'sentriesno longer throws (which would have dropped the whole aws-quotas section and marked the report degraded); the valid entries still surface. kinddiscriminant on AWS entries. Each entry now carrieskind: "utilization" | "pending"so a consumer iterating entries without the parent signal's label cannot misread a pending row's absentutilizationPctas0.
2026.07.13.1
Added: @webframp/operator-briefing/review-queue — a new method-scope
report attached to the @webframp/gitlab model. It fires after a single
list_my_merge_requests execution and renders the four GitLab review tiers LIVE
(waiting on you / awaiting your merge / mentions / your open MRs) — a fast path
between full daily briefings, with no ops section.
It reuses the SAME shared _lib the workflow briefing uses — the gitlab
normalizer and a shared renderQueueSection in _lib/render.ts — s
Added 1 models
2026.07.13.2
Enriched the stable JSON contract so downstream renderers get clickable links and chartable AWS data directly from the contract — no reaching around to raw data resources.
QueueItem.url. Every queue item now carries an optional deep link — an MR'swebUrlor a todo'stargetUrl— so a renderer can make the reference clickable. This also covers issue-todos that have no derivablereferencebut do have atargetUrl; they now get aurltoo. Left undefined when the source carries no URL — never fabricated.- Structured, account-redacted AWS
entrieson theOpsSignal. A utilization signal (ec2/vpc/eks) now carries its over-threshold quotas as{ quotaName, utilizationPct, usageValue, value, adjustable }, and the pending signal carries{ quotaName, serviceCode, desiredValue, status }per request — chartable quota facts without parsing the detail string. The entries NEVER include an account identifier (profile,accountId,requestId,caseId, or any bare account number); CLAUDE.md forbids exposing internal account IDs. A degraded fetch that observed nothing leavesentriesabsent and keeps the honest "not checked" phrasing unchanged.
Both additions are additive to the JSON contract; the markdown projection is unchanged.
Hardening from a second adversarial review:
- Account-number redaction now catches embedded digit runs. Redaction
previously masked a profile segment only when it was ENTIRELY digits, so an
account number embedded in a longer name (
prod-123456789012) leaked intodetail. It now masks ANY 6+ digit run (prod-123456789012->prod-****) while leaving the all-digits case asaccount ****and never touching legitimate large quota values. - Null-safe entry mapping. The AWS entry mappers now filter to real objects
before mapping, so a
nullelement in a resource'sentriesno longer throws (which would have dropped the whole aws-quotas section and marked the report degraded); the valid entries still surface. kinddiscriminant on AWS entries. Each entry now carrieskind: "utilization" | "pending"so a consumer iterating entries without the parent signal's label cannot misread a pending row's absentutilizationPctas0.
2026.07.13.1
Added: @webframp/operator-briefing/review-queue — a new method-scope
report attached to the @webframp/gitlab model. It fires after a single
list_my_merge_requests execution and renders the four GitLab review tiers LIVE
(waiting on you / awaiting your merge / mentions / your open MRs) — a fast path
between full daily briefings, with no ops section.
It reuses the SAME shared _lib the workflow briefing uses — the gitlab
normalizer and a shared renderQueueSection in _lib/render.ts — so the two
reports render their GitLab tiers through one code path and can never diverge in
tiering, shape, or format. The method report emits the same stable JSON contract
restricted to the queue tiers (ops: []), and degrades rather than throwing (an
unreadable handle is counted, a missing dashboard yields a valid empty queue).
The data-handle reader is now shared in _lib/read.ts across both reports.
Changed (both reports benefit):
- Long table cells are truncated.
_lib/render.tsnow caps a free-text cell (an MR title or a todo body) to ~80 visible characters with an ellipsis before escaping, so a long mention body no longer dumps a wall of text into a table cell. The full text is preserved untouched in the JSON contract. - Honest degraded-ops phrasing. When an AWS quota signal is degraded (e.g. a
non-empty
failedProfilesfrom an expired SSO session) and returned no entries, its detail now reads "ec2: not checked" instead of the dishonest "ec2: all quotas below threshold" — the quotas were never observed. ThedegradedReasonstill carries the actionable hint (re-rungranted sso login). A non-empty result is still reported as the real value it is.
2026.07.12.1
Added: @webframp/operator-briefing — the initial release of the unified
daily operator briefing report (workflow scope).
The report loops a workflow run's step executions, dispatches each step by
modelType to a per-source normalizer via a registry, reads that step's data
handles, and flattens the results into two projections held in a shared _lib/:
- a four-tier review queue (
QueueItem[]) — waiting on you / awaiting your merge / mentions / your open MRs — from@webframp/gitlabdashboard data, with the accuracy rules the oldreview_dashboardignored: dedup onreference, fold assigned∩authored into your-MRs, and drop items already approved by the operator (approvedByMe/myReviewState === "approved"); - a set of ops signals (
OpsSignal[]) from@webframp/anthropic/analytics(seats, adoption, cost — acollected: falsefetch renders "unavailable", not zero),@webframp/anthropic/compliance(effectiv
2026.07.13.1
Added: @webframp/operator-briefing/review-queue — a new method-scope
report attached to the @webframp/gitlab model. It fires after a single
list_my_merge_requests execution and renders the four GitLab review tiers
LIVE (waiting on you / awaiting your merge / mentions / your open MRs) — a fast
path between full daily briefings, with no ops section.
It reuses the SAME shared _lib the workflow briefing uses — the gitlab
normalizer and a shared renderQueueSection in _lib/render.ts — so the two
reports render their GitLab tiers through one code path and can never diverge in
tiering, shape, or format. The method report emits the same stable JSON contract
restricted to the queue tiers (ops: []), and degrades rather than throwing (an
unreadable handle is counted, a missing dashboard yields a valid empty queue).
The data-handle reader is now shared in _lib/read.ts across both reports.
Changed (both reports benefit):
- Long table cells are truncated.
_lib/render.tsnow caps a free-text cell (an MR title or a todo body) to ~80 visible characters with an ellipsis before escaping, so a long mention body no longer dumps a wall of text into a table cell. The full text is preserved untouched in the JSON contract. - Honest degraded-ops phrasing. When an AWS quota signal is degraded (e.g. a
non-empty
failedProfilesfrom an expired SSO session) and returned no entries, its detail now reads "ec2: not checked" instead of the dishonest "ec2: all quotas below threshold" — the quotas were never observed. ThedegradedReasonstill carries the actionable hint (re-rungranted sso login). A non-empty result is still reported as the real value it is.
2026.07.12.1
Added: @webframp/operator-briefing — the initial release of the unified
daily operator briefing report (workflow scope).
The report loops a workflow run's step executions, dispatches each step by
modelType to a per-source normalizer via a registry, reads that step's data
handles, and flattens the results into two projections held in a shared
_lib/:
- a four-tier review queue (
QueueItem[]) — waiting on you / awaiting your merge / mentions / your open MRs — from@webframp/gitlabdashboard data, with the accuracy rules the oldreview_dashboardignored: dedup onreference, fold assigned∩authored into your-MRs, and drop items already approved by the operator (approvedByMe/myReviewState === "approved"); - a set of ops signals (
OpsSignal[]) from@webframp/anthropic/analytics(seats, adoption, cost — acollected: falsefetch renders "unavailable", not zero),@webframp/anthropic/compliance(effective-settings count, recent activity), and@webframp/aws/service-quotas(per-service quota utilization over threshold, pending increases, withfailedProfilesdegradation and thesso-login-requiredre-auth hint).
Freshness is judged from each source's own fetchedAt (stale > 24h for ops,
7d for queue items) and
truncatedbecomes a note. The report degrades, never throws: unknown modelType / missing normalizer / parse failure are skipped and counted, and any unexpected error returns a valid{ markdown, json }withdegraded: true.
Output is a consistent markdown briefing plus a stable JSON contract
({ generatedAt, tiers, queue, ops, degraded, notes }) designed as the durable
interface downstream renderers consume.
Added 1 reports
2026.07.12.1
Added: @webframp/operator-briefing — the initial release of the unified
daily operator briefing report (workflow scope).
The report loops a workflow run's step executions, dispatches each step by
modelType to a per-source normalizer via a registry, reads that step's data
handles, and flattens the results into two projections held in a shared
_lib/:
- a four-tier review queue (
QueueItem[]) — waiting on you / awaiting your merge / mentions / your open MRs — from@webframp/gitlabdashboard data, with the accuracy rules the oldreview_dashboardignored: dedup onreference, fold assigned∩authored into your-MRs, and drop items already approved by the operator (approvedByMe/myReviewState === "approved"); - a set of ops signals (
OpsSignal[]) from@webframp/anthropic/analytics(seats, adoption, cost — acollected: falsefetch renders "unavailable", not zero),@webframp/anthropic/compliance(effective-settings count, recent activity), and@webframp/aws/service-quotas(per-service quota utilization over threshold, pending increases, withfailedProfilesdegradation and thesso-login-requiredre-auth hint).
Freshness is judged from each source's own fetchedAt (stale > 24h for ops,
7d for queue items) and
truncatedbecomes a note. The report degrades, never throws: unknown modelType / missing normalizer / parse failure are skipped and counted, and any unexpected error returns a valid{ markdown, json }withdegraded: true.
Output is a consistent markdown briefing plus a stable JSON contract
({ generatedAt, tiers, queue, ops, degraded, notes }) designed as the durable
interface downstream renderers consume.
- Has README or module doc2/2earned
- README has a code example1/1earned
- README is substantive1/1earned
- Most symbols documented1/1earned
- No slow types (deprecated)1/1earned
- Dependencies pass trust audit2/2earned
- Has description1/1earned
- Platform support declared (or universal)2/2earned
- License declared1/1earned
- Verified public repository2/2earned