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).@webframp/aws/securityhub-findings— Security Hub severity summary across the AWS Organization (CRITICAL/HIGH/MEDIUM/LOW counts, 24h window).@webframp/aws/cost-explorer— consolidated AWS cost trend (7-day window) from the payer account with direction indicator.@webframp/redmine— open issues assigned to the operator across all projects (equivalent to /my/page), surfaced as tier-1 queue items.
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.08.28.1
Changed: Normalized the extension license to Apache-2.0 and corrected the copyright holder to "Sean Escriva". Extensions that previously shipped an MIT LICENSE.md are now Apache-2.0, consistent with the repository root and every other extension. No code or behavioral changes.
Upgrade note: License text only. No API, schema, or runtime behavior changed.
2026.08.26.3
Fixed: Restored inline npm:zod@4.4.3 import specifiers so the registry
quality scorer can resolve dependencies and score the extension. An earlier
release used a bare "zod" import-map specifier, which published but scored as
unscored.
Changed: Retained explicit compilerOptions.strict in deno.json. No
behavioral or schema changes.
| 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. |
| redmineIssueCount? | number | Count of open Redmine issues assigned to the operator. |
| criticalFindingCount? | number | Count of CRITICAL Security Hub findings (24h window). |
| highFindingCount? | number | Count of HIGH Security Hub findings (24h window). |
| awsCostTotal7d? | number | Total AWS cost (USD) for the trailing 7-day window. |
| 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.08.26.3
Fixed: Restored inline npm:zod@4.4.3 import specifiers so the registry
quality scorer can resolve dependencies and score the extension. An earlier
release used a bare "zod" import-map specifier, which published but scored as
unscored.
Changed: Retained explicit compilerOptions.strict in deno.json. No
behavioral or schema changes.
2026.08.26.1
Fixed: Added missing description field to upgrade entry for version
2026.08.24.2. The omission caused swamp extension pull to fail with a catalog
validation error ("upgrades.N.description: Invalid input: expected string,
received undefined").
2026.08.24.3
Added: Output metadata attributes for observability.
durationMs: Method execution duration in milliseconds.collectedBy: Extension name that produced the data.fetchedAt: ISO 8601 timestamp when data was fetched (added to resources that previously lacked it).
2026.08.24.2
Added Troubleshooting section documenting per-source degradation, append_metrics skip-write safety, dashboard empty-trend rendering, incomplete README sources table, and implicit configuration model.
2026.08.21.1
Changed: Added .describe() to every field on the metrics model's Row
and Series resource schemas, mirroring the descriptions that already
existed on the corresponding append_metrics method arguments. No
behavioral change.
2026.08.10.1
Added: Three new briefing sources and four new metrics fields.
Sources:
@webframp/aws/securityhub-findings— Security Hub severity summary (CRITICAL/HIGH/MEDIUM/LOW counts) as an ops signal.@webframp/aws/cost-explorer— consolidated AWS cost trend (7-day total + direction) as an ops signal.@webframp/redmine— open issues assigned to the operator across all projects, surfaced as tier-1 queue items plus an ops signal with the total count.
Metrics (append_metrics schema):
redmineIssueCount— open Redmine issues assigned to the operator.criticalFindingCount— CRITICAL Security Hub findings (24h).highFindingCount— HIGH Security Hub findings (24h).awsCostTotal7d— total AWS cost (USD) for the trailing 7-day window.
All new fields are optional and merge non-destructively with existing rows. Existing model instances upgrade via identity function (no data migration).
2026.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 on
2026.08.10.1
Added: Three new briefing sources and four new metrics fields.
Sources:
@webframp/aws/securityhub-findings— Security Hub severity summary (CRITICAL/HIGH/MEDIUM/LOW counts) as an ops signal.@webframp/aws/cost-explorer— consolidated AWS cost trend (7-day total + direction) as an ops signal.@webframp/redmine— open issues assigned to the operator across all projects, surfaced as tier-1 queue items plus an ops signal with the total count.
Metrics (append_metrics schema):
redmineIssueCount— open Redmine issues assigned to the operator.criticalFindingCount— CRITICAL Security Hub findings (24h).highFindingCount— HIGH Security Hub findings (24h).awsCostTotal7d— total AWS cost (USD) for the trailing 7-day window.
All new fields are optional and merge non-destructively with existing rows. Existing model instances upgrade via identity function (no data migration).
2026.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-me
2026.08.10.1
Added: Three new briefing sources and four new metrics fields.
Sources:
@webframp/aws/securityhub-findings— Security Hub severity summary (CRITICAL/HIGH/MEDIUM/LOW counts) as an ops signal.@webframp/aws/cost-explorer— consolidated AWS cost trend (7-day total + direction) as an ops signal.@webframp/redmine— open issues assigned to the operator across all projects, surfaced as tier-1 queue items plus an ops signal with the total count.
Metrics (append_metrics schema):
redmineIssueCount— open Redmine issues assigned to the operator.criticalFindingCount— CRITICAL Security Hub findings (24h).highFindingCount— HIGH Security Hub findings (24h).awsCostTotal7d— total AWS cost (USD) for the trailing 7-day window.
All new fields are optional and merge non-destructively with existing rows. Existing model instances upgrade via identity function (no data migration).
2026.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-me
2026.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
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