feat(runner): structured RunnerNotice advisory surface on StoryboardResult / ComplianceResult#1705
Conversation
…esult / ComplianceResult (#1704) Adds `notices: RunnerNotice[]` to StoryboardResult (always-present) and `notices?: RunnerNotice[]` to ComplianceResult (optional, deduped by code). Exposes two spec-grounded day-one notices: request_signing_required_in_4_0 (future_required, scoped to signed_requests storyboards) and legacy_hmac_fallback_removed_in_4_0 (deprecation, scoped to webhook storyboards). CI gates can now key on stable notice codes instead of parsing prose skip.detail strings. https://claude.ai/code/session_01EfP3yr9YftU4Qkj9dwfZbN
…ner-notices # Conflicts: # src/lib/version.ts
…eview Addresses three independent expert reviews on #1705 (code-reviewer, adtech-product-expert, dx-expert). Two blockers + four nits applied. Blockers fixed: 1. NoticeCode is now `string` (with KNOWN_NOTICE_CODES const + KnownNoticeCode union for autocomplete). Every new advisory code would have been a TypeScript breaking change otherwise — adopters narrowing on `code` would see a major bump for each new notice. Matches the issue spec's "code: string" intent (#1704). 2. ComplianceResult.notices is now always-present (default `[]`), mirroring StoryboardResult.notices. Drops the conditional spread at the result return and the `?` on the type. Adopters can iterate `for (const n of result.notices)` at either level without a defensive `?.`. Backfills the field on three early-return paths. Nits fixed: 3. Renamed `effective_adcp_version` -> `effective_version` to align with upstream spec proposal adcp#4418 and #1704. 4. `isWebhookRelatedStoryboard` no longer matches `/webhook/i` storyboard id; relies solely on `WEBHOOK_STEP_TASKS` step-task presence. Eliminates false positives like a hypothetical `webhook_authoring_guide`. 5. `request_signing_required_in_4_0` now populates the previously-dead `requirement: 'request_signer'` field, wiring it to the structured requirement name. Unblocks badge routing. 6. Both notices carry `docs_url` for adopter click-through. 7. Dedup policy commented as "last-occurrence wins" at comply.ts. Deferred to follow-ups: dot-namespaced code naming, CLI default-output surfacing, doc additions (TYPE-SUMMARY/llms.txt/VALIDATE-YOUR-AGENT), AAO Verified dashboard rendering, strict-mode example in changelog. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Review passSpawned three independent expert reviewers (code-reviewer, adtech-product-expert, dx-expert) on the auto-drafted diff. Pushed two commits to address their findings. Blockers fixed (commit
|
| }, | ||
| }; | ||
|
|
||
| const profileWithLegacyHmacAndSigning = { |
… CLI rendering
Applies six design decisions from review discussion:
1. **Closed `NoticeCode` literal union.** Reverts the open-string + KNOWN
constant approach. Adopters who narrow on `code` get exhaustiveness
checks; new codes invite explicit handling instead of silently passing
through. The breaking-change cost is correct — a deprecation or
future-required advisory IS the kind of signal CI gates / dashboards
should explicitly handle.
2. **Dot-namespaced code naming.** Renamed both day-one codes:
- `request_signing_required_in_4_0` -> `request_signing.required`
- `legacy_hmac_fallback_removed_in_4_0` -> `webhook_signing.legacy_hmac_fallback.removed`
The *when* lives in `effective_version`; the code stays stable across
spec versions (no `_in_4_0` / `_in_5_0` proliferation as the spec moves).
3. **Dropped `requirement` field.** Was populated on 1 of 2 day-one
notices; future deprecation notices won't have a structured
`RequirementName` either. Consumers wanting cross-reference can map
by `code` (which is stable). Can re-add as a generic `linked: {...}`
later if real cross-reference needs emerge.
4. **CLI default-output rendering.** New `printNotices(notices)` helper
in bin/adcp.js renders severity-badged one-liners under each
storyboard summary AND under the multi-storyboard rollup. Aggregates
across storyboards with `storyboard_ids` merge. Without this,
adopters who tail the default text output never saw the signal
(was `--json`-only previously).
5. **Storyboard-level `storyboard_ids: string[]` on every notice.** Each
notice carries its source storyboard ids. On `StoryboardResult.notices`
it's a single-element array; on `ComplianceResult.notices` the rollup
merges arrays across storyboards emitting the same code. Auditors get
"how widespread is this deprecation" without re-walking per-storyboard
arrays; dashboards rendering badge counts still see one entry per
unique code.
6. **Comply-level aggregation rewritten** to merge `storyboard_ids` per
code instead of last-write-wins on the whole notice object. Order
preserved across the run's storyboard execution order. Comment names
the chosen first-occurrence-wins policy for the notice body.
Paired AAO-repo issue tracked separately for the dashboard-rendering
side (AAO Verified renders verdicts, not advisory payloads; needs a
dashboard-side change to surface notices).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Design pass shipped (commit `df86a5c3`)All six decisions from review discussion applied:
Paired AAO-repo issueFiled adcontextprotocol/adcp#4436 tracking the AAO Verified dashboard side — surfaces Test results
Remaining deferred follow-ups (separate issues)
Ready for human review / admin merge. |
Closes #1704
Summary
notices: RunnerNotice[]toStoryboardResult(always-present, default[]) andnotices?: RunnerNotice[]toComplianceResult(optional, deduped bycodeacross all storyboard runs)RunnerNotice,NoticeCode(stable union),NoticeSeverity('info' | 'deprecation' | 'future_required')collectCapabilityNotices():request_signing_required_in_4_0(future_required) — onsigned_requestsstoryboards (or storyboards with arequest_signing_probestep) whenrequest_signing.supportedis absent/falselegacy_hmac_fallback_removed_in_4_0(deprecation) — on webhook-related storyboards (id matches/webhook/ior has webhook assertion steps) whenwebhook_signing.legacy_hmac_fallback: truebuildCapabilityUnsupportedResult,buildRequirementUnmetResult,buildRequiredToolsMissingResult,buildDiscoveryFailedResult,buildNotApplicableStoryboardResult,checkAccountDiscoveryGate) carrynotices: []codevalues instead of parsing proseskip.detailstringsDeferred:
signed_requests_specialism_deprecated— pending upstream deprecation of the'signed-requests'specialism value in adcontextprotocol/adcp#4418; the value is still active in the spec.Test plan
test/lib/storyboard-notices.test.js(5 describe blocks,node:testrunner,_profileinjection — no live agent or schema cache needed)noticesalways-present on StoryboardResult including early-return pathsrequest_signing_required_in_4_0fires on signed_requests storyboard and request_signing_probe storyboards; does not fire when signing declared or on unrelated storyboardslegacy_hmac_fallback_removed_in_4_0fires on webhook-scoped storyboards only; does not fire on non-webhook storyboards even when flag is setraw_capabilitiesabsent (standalone runner without pre-fetched profile)tsc --project tsconfig.lib.jsonclean (no errors)Pre-PR review
Two expert panels reviewed the diff before this PR was opened:
Code-reviewer — no blockers; two issues addressed:
buildRequiredToolsMissingResultnow spreadspreflightNotices(was the only early-return path missing it)legacy_hmac_fallback_removed_in_4_0scoped to webhook storyboards viaisWebhookRelatedStoryboardguard (analogous toisSignedRequestsStoryboard)notices.length === 0Protocol expert — one blocker addressed:
legacy_hmac_fallback_removed_in_4_0was firing unconditionally on every storyboard; now gated to webhook-related storyboards only (by id pattern/webhook/ior presence of webhook assertion task steps)https://claude.ai/code/session_01EfP3yr9YftU4Qkj9dwfZbN
Generated by Claude Code