Back to home@ZZZjf13960

dsh-onfail

DSH plugin: poll GitHub Actions, surface failed checks as cards, open a fix session with log context.

Stars
1
Language
JavaScript
Created
Aug 28, 2026
Updated
Aug 28, 2026
GitHub repo

Introduction

dsh-onfail

CI failed. Stay in DSH. Click the card, start the fix. CI 挂了也别离开 DSH:侧栏一张失败卡,点一下带 log 开修。

DeepSeek Harness plugin: poll one GitHub repository's Actions, surface failed checks as sidebar cards (job name, SHA, log tail), and open a repair session preloaded with that failure context.

v0 is polling only. No webhooks.

Install

Requires a DSH web profile. From any directory:

dsh plugin --profile web add github:ZZZjf13960/dsh-onfail

This package ships committed JavaScript (dsh/index.js + dsh/client.js) on main, so the GitHub specifier is loadable without a prepare build or pnpm allowBuilds gate.

Then start (or restart) the web UI:

dsh --profile web

The plugin mounts as package name dsh-onfail via cordis.patch.yml. Settings, then Plugins, should show an Onfail (GitHub Actions) card. A CI control appears in the sidebar footer; failed checks also render as overlay cards.

Remove

Either form drops the profile dependency and the bundle layer:

dsh plugin --profile web remove github:ZZZjf13960/dsh-onfail
dsh plugin --profile web remove dsh-onfail

Restart the web UI so the host process unloads the routes and the browser half.

Configure

FieldDefaultWhere
repoemptyPlugin settings card, or config.repo on the dsh-onfail loader row (owner/name)
tokenemptyPlugin settings card (never echoed back). Also DSH_ONFAIL_TOKEN then GITHUB_TOKEN
pollIntervalMs60000Settings card or loader config (~60s)
fixturefalseSettings checkbox, loader config, or DSH_ONFAIL_FIXTURE=1
logTailChars4000Loader config

Token resolution order: plugin config, then DSH_ONFAIL_TOKEN, then GITHUB_TOKEN. Nothing is hardcoded. A teammate supplies a live token and CI later.

A classic repo PAT (or GitHub App installation token) needs Actions read on that repository. Fine-grained PATs need Actions: Read.

Loader override example ($DSH_HOME/profiles/web/cordis.patch.yml):

- id: dsh-onfail
  config:
    repo: your-org/your-repo
    pollIntervalMs: 60000
    fixture: false

Polling

Every pollIntervalMs the host half calls:

  1. GET /repos/{owner}/{repo}/actions/runs?status=completed
  2. For failed / timed-out runs, GET .../actions/runs/{id}/jobs
  3. For failed jobs, GET .../actions/jobs/{id}/logs (log tail cached per job id)

There are no webhooks. The browser half polls GET /dsh-onfail/state every few seconds and renders cards.

Fixture mode

Tests and a live UI walkthrough can produce a card without a GitHub token:

  • Settings, Onfail, enable Fixture mode, or
  • DSH_ONFAIL_FIXTURE=1, or
  • loader config.fixture: true

This loads fixtures/failed-run.json (acme/widget, job unit-tests, SHA aaaabbb, a failing test log tail).

node --test

Acceptance checks

  1. Install from GitHub on main. Manifest tests assert dsh.bundle.patch points at cordis.patch.yml that inserts package dsh-onfail, plus exports["./client"] and dsh.client. JS is committed on main. Verifier still runs dsh plugin --profile web add github:ZZZjf13960/dsh-onfail.

  2. Failed Actions checks become sidebar cards (job, SHA, log tail). Fixture and the poll mapper produce that card shape. The client registers sidebar.footer.action and shell.overlay. Verifier still confirms the CI footer / overlay cards in DSH Web.

  3. Clicking a card opens a repair session with repo, job, SHA, and log tail. The click path is sessions.createsessions.opensession.prompt(..., 'queue'). A rejected prompt or failed create shows a role=status error on the card. Composer paste is not a session. Verifier still clicks a card in the live UI.

  4. Missing token: readable error, harness does not crash or hang. apply() with no token sets error and still registers routes; it never throws. Verifier still opens the plugin UI with empty token/repo.

  5. Remove drops the profile entry. Documented; dsh plugin remove reconciles bundles by installed state. Verifier still runs remove and checks dsh.profile.bundles.

Layout

dsh-onfail/
  package.json           # dsh.bundle + dsh.client + exports
  cordis.patch.yml       # insert id/name: dsh-onfail
  fixtures/failed-run.json
  dsh/index.js           # host apply (imports @deepseek-ai/cordis + schemastery)
  dsh/plugin.js          # poll loop + /dsh-onfail/* routes
  dsh/client.js          # lazy CJS browser half
  dsh/config.js poll.js cards.js http.js
  test/*.test.js

License

MIT