Skip to content

fix(core): attribute deferred skill plugin failures - #46967

Open
kitlangton wants to merge 1 commit into
v2from
skill-failures
Open

fix(core): attribute deferred skill plugin failures#46967
kitlangton wants to merge 1 commit into
v2from
skill-failures

Conversation

@kitlangton

@kitlangton kitlangton commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Why

A plugin can finish setup successfully and then throw when its skill transform is replayed. Listing skills returns an empty HTTP 500, so clients report UnexpectedStatus without identifying the plugin or failed operation.

What Changes

Before: a deferred callback throws an unattributed defect; GET /api/skill has no declared failure payload.

After: the callback retains its registering plugin ID and operation. The endpoint logs the original exception and returns a declared HTTP 500:

{
  "_tag": "PluginCallbackError",
  "pluginID": "broken-skills",
  "operation": "skill.transform",
  "message": "Plugin \"broken-skills\" failed during skill.transform. Check server logs for details."
}

Both generated Promise and Effect clients preserve that error. The payload contains no exception text, stack, source path, or plugin configuration. Plugin IDs are the existing public inventory identifiers.

The Core callback still fails as a defect. HTTP translates only this recognized boundary failure into its declared error. Unrelated defects remain defects; server interruption retains the HTTP runtime's empty 503 response. Reads continue to fail until the broken registration is explicitly changed—no transform is skipped, disabled, or partially published.

Scope

One reporting slice: deferred skill transforms and skill.list. This does not change plugin inventory health, setup-error reporting, other callback domains, or TUI presentation. In particular it does not infer that a directory is absent or recommend moving it. Pre-model presentation and safe isolation are separate work; this does not overlap the RPC handler changes in #46946 or the location/catalog UI changes in #46961.

Verification

# packages/core
bun typecheck
bun run test test/plugin/skill-failures.test.ts --rerun-each 5
bun run test

# packages/server: isolated HOME/XDG/TMPDIR via the Core wrapper
bun run ../core/script/test.ts test/skill-failures.test.ts test/plugin-activation.test.ts --rerun-each 5
bun run ../core/script/test.ts
bun typecheck

# packages/client
bun run generate
bun run test
bun typecheck

# packages/protocol
bun run generate
bun typecheck
bun run check:generated

# packages/www
bun script/generate-openapi.ts
bun run check:generated
bun typecheck
bun run build

# worktree, normal pre-push hook enabled
git diff --check
git push -u origin skill-failures
  • Red before implementation: two Core attribution cases failed on the raw thrown values. Before adding the HTTP mapping/contract, the real endpoint returned an empty 500 and both client tests failed on UnexpectedStatus/ClientError.
  • Green: Core 4,024 passed, 39 skipped; Server 53 passed, 3 skipped; Client 147 passed. Focused repeats: 15 Core + 30 Server/activation cases passed.
  • The real registry tests cover Error and non-Error throws, successful setup followed by deferred failure, repeat reads, explicit registration removal, and a healthy plugin. Server tests verify that location metadata still succeeds, the original cause reaches the logger, and only the intended public fields reach HTTP.
  • Unrelated-defect and interruption controls pass. An initial test expected client-abort status 499 for a server interruption; inspecting the pinned Effect runtime confirmed its existing 503 behavior, and the corrected control passes repeatedly.
  • Typechecks, generated OpenAPI checks, website build/link validation, and all 33 normal pre-push typecheck tasks passed. The simplify pass found no additional behavior-preserving cleanup worth adding.
  • CI is green: Linux/Windows unit jobs, Linux/Windows end-to-end jobs, and typechecks passed. The first Windows unit attempt passed Server tests but exited 3 when Bun 1.4.0 segfaulted in the TUI suite (panic(main thread): Segmentation fault), with no assertion failure reported. The unchanged rerun passed, including compiled service lifecycle and Node build checks.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant