Skip to content

app-showcase boots with three declared-but-inert wirings: a job with no handler, a capability that never materializes, and a retired retry alias #4888

Closed

Description

@xuyushun441-sys

Context

examples/app-showcase is the reference app — the thing the coverage test keeps
honest and the thing people copy. Three of its declarations are accepted at
authoring time and then quietly do nothing at runtime, each announced by a boot
warning. All three are the "declared, not enforced" shape the repo treats as a
bug class (ADR-0049), so they read as noise but are really dead wiring.

1. Scheduled job whose handler doesn't exist

WARN [AppPlugin] job handler not found in bundle.functions — skipping
  {"appId":"com.example.showcase","job":"showcase_health_sweep","handler":"sweepProjectHealth"}

src/automation/jobs/index.ts:11 declares handler: 'sweepProjectHealth', and
that is the only occurrence of the string in the whole example — no function
of that name is exported into the bundle. So showcase_health_sweep is
registered and never runs.

The showcase is where "scheduled job" is supposed to be demonstrated end-to-end,
so this is a coverage hole as much as a warning: the capability appears exercised
while nothing executes.

2. Capability declared, referenced by a permission set, never materialized

WARN [security] capability has no owning package — not materialized {"name":"showcase.export_data"}

src/security/capabilities.ts:32 declares showcase.export_data, and
src/security/permission-sets.ts:190 puts it in OpsPermissionSet.systemPermissions
alongside the real setup.access.

Because it never materializes, that permission-set entry grants nothing — a
security declaration that reads as enforcement and isn't. Whatever the fix is
(give it an owning package, or drop it and the reference together), it should not
stay in the reference app in a state where copying it produces an inert grant.

3. Retired retry alias in the flow definitions

defineStack: flows[24].nodes[1].config.retry.backoffMs: 'retryDelayMs' → 'backoffMs'
  (converted at load; conversion 'retry-policy-converged', retires in protocol 18).
  Update the source to the canonical shape — the conversion stops running then.

Two sites still use the old spelling:

  • src/automation/flows/index.ts:984 — { maxRetries: 3, retryDelayMs: 1000, backoffMultiplier: 2, maxRetryDelayMs: 10000 }
  • src/automation/flows/index.ts:1176 — { maxRetries: 2, retryDelayMs: 500, backoffMultiplier: 2 }

The conversion carries an explicit retirement deadline (protocol 18), and the
example is the worst place to keep a shape that is about to stop working. This
one is a mechanical rename.

Why file these together

They share a root posture rather than a root cause: each is a declaration the
example makes that the runtime cannot honour, and each is currently "documented"
only by a line in the boot warning block. Happy to split if that suits triage
better.

Found while browser-sweeping showcase + Studio for #4879 (boot warnings on
main @ 0e96e46).

Activity

  1. added
    domain:servicesRetired 2026-10-22, alias of domain:server (services surface); in-flight cards keep it until landed
    on Aug 3, 2026
  2. claude commented on Aug 3, 2026

    @claude
    Contributor

    分诊(收敛):本单与 #4774 的第 1/2/3 条完全同源(job handler 不存在 / capability 无 owning package / retryDelayMs 退役别名)。#4774 已在队并已派发,修复 PR 将同时关闭本单(Fixes 两单)。单一派发入口原则:后续跟进请到 #4774。


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    domain:servicesRetired 2026-10-22, alias of domain:server (services surface); in-flight cards keep it until landed

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions