coderoasted/Sift — structural CI-log diff
Diffs this run's logs against the last green run on the base branch; posts one sticky PR comment + an advisory gate.
View on GitHubTrust Signals
- Scorecard Score
- not yet scored
- Maintenance Recency
- Activelast commit Jul 10, 2026
- License
- MIT
Pinned Snippet
uses: coderoasted/sift-action@1613207535da1eff7cef8849012581d98015dd64 # engine-v1.7.7tags can be moved; commit SHAs can't. why a SHA?
Inputs
| name | description | required | default |
|---|---|---|---|
| target-job | Zero-plumbing log sourcing: the NAME of a finished job in this run whose log Sift diffs — no tee/capture shell needed in the build job. Run Sift in a separate job that `needs:` the target (the API serves logs for completed jobs only; the target's own conclusion then also gives you `changed-outcome` for free). The runner's per-line timestamps are stripped; `capture` selects marked sections. Mutually exclusive with `log` (target-job wins). | no | "" |
| capture | With `target-job`: which part of the job log to diff. `auto` (default) — if the log contains SIFT_CAPTURE sections use them all, else the whole job log. `off` — the whole job log always. `<name>` — only the sections opened with `SIFT_CAPTURE <name>` (absent ⇒ the run fails: config error). Sections are plain echoed lines: `echo "SIFT_CAPTURE ci"` … `echo "SIFT_CAPTURE_END"`. | no | auto |
| log | Path to the current run's captured log to diff (the build/CI log). Required for mode comment|render unless `target-job` is set; unused for mode post. | no | — |
| sift-binary | Override path to a `sift` binary. Default: download + verify the version-pinned linux-x64 release asset. | no | sift |
| fail-on | Advisory gate: exit non-zero when the condition holds. One of none | significant | regression. | no | none |
| baseline | Baseline SELECTION — you are King of the baseline. One of: `auto` (default) — the last green run of this workflow on the PR's base branch (push: the pushed branch; tag: the repo default branch), pulling its `baseline-name` artifact — the turnkey zero-config path. `branch=<name>` — same resolver, explicit branch. `artifact=<name>` — the newest non-expired artifact with that exact name, repo-wide: NAMED baselines (a main-seeded `sift-baseline-main-build`, a per-PR `sift-baseline-build-pr-123`) resolve from ANY event — tags and PRs included, no need for this workflow to have run on that branch. `path=<file>` — a local file (self-hosted / bring-your-own). `none` — forced cold start (seed-only runs). A malformed value fails the run (config error), never falls back silently. | no | auto |
| baseline-name | The artifact name this run PUBLISHES its ingested log under (the `create_baseline` half), and the artifact name the `auto`/`branch=` resolvers look for on the resolved run. Compose per-job / per-PR names with expressions, e.g. `sift-baseline-build-pr-123`. | no | sift-baseline-log |
| publish-baseline | When this run publishes `baseline-name`: `auto` (default — PRs always seed; pushes/tags are green-gated: a red build never overwrites the last-green baseline) | `always` | `never`. | no | auto |
| comment-tag | Optional namespace for the sticky PR comment (appended to the hidden marker and the title), so two sift invocations in one job — e.g. vs-main and vs-previous-run — each keep their own comment. Leave unset for the single-comment default. | no | "" |
| explain | Opt-in AI narrative header (false default | true). When true, the Action provisions a pinned, checksum-verified LOCAL model + inference server (no credential, fork-safe — nothing leaves the runner) and asks sift for a short plain-English story over the deterministic report. Adds a ~2.4 GB model download (cache it across runs with a one-line `actions/cache` step on `~/.cache/coderoast` — see the README explain example) + a few seconds of CPU inference; the deterministic report is ALWAYS produced regardless (the narrative is advisory and fail-soft — never blocks or changes the gate). Cloud BYO is CLI-only and never via the Action. | no | false |
| explain-model | Advanced: override the pinned recommended model name passed to `sift --explain`. Leave unset for the default (the only model the Action auto-provisions). | no | "" |
| changed-outcome | The current run's NATIVE CI verdict token, forwarded VERBATIM to the engine (`--changed-outcome`), which maps it four-class-aware (SUCCESS | FAILURE | UNSTABLE | ABORTED) through its dialect vocabulary — this drives the verdict headline, the outcome-regression check, and the verdict-gated baseline re-seed. `auto` (default): the target job's own API conclusion when `target-job` is set — zero plumbing; without `target-job` set it explicitly from a needs.<job>.result expression, else the engine falls back to the log's console tail / no verdict. | no | auto |
| pr-comment | PR runs: post the sticky comment when the verdict is at least this level — never | regression (only a flagged regression) | significant (drift OR regression) | always (every state, incl. the green "no change" reassurance). Default `always`. The job summary + outputs are written regardless. | no | always |
| commit-comment | Push runs (no PR — e.g. trunk commits to main): ALSO post a comment on the pushed commit when the verdict is at least this level — never (default; job summary only) | regression | significant (drift OR regression) | always. NEVER fires below the level (a clean run stays quiet), upserts per-commit (re-runs don't duplicate). Needs `contents: write`; degrades to a warning without it. | no | never |
| annotations | Inline check-run annotations: emit a `::error|warning|notice::` workflow command for each significant row when the verdict is at least this level — never | regression (regressions only) | significant (drift OR regression) | always. They surface in the Checks tab / PR checks strip, fire on a GREEN build (where GitHub's failure-explain is silent), and need NO write token, so a fork PR's unprivileged build (mode=render) annotates fork-safely. Polarity drives the level: regression → error, recovery → notice, other significant → warning. Default `significant` (a clean run has no significant rows, so it stays quiet). | no | significant |
| github-token | Token for the runs/artifacts API, the sticky comment, and artifact upload. | no | ${{ github.token }} |
| mode | comment (default) — render + post the sticky comment inline (same-repo PRs, the proven path). render — render the escaped comment body to $RUNNER_TEMP/sift-comment/ WITHOUT posting (the unprivileged fork build job; the workflow uploads it as the `sift-comment` artifact). post — run no engine; download that artifact off the triggering run and post the comment (the privileged workflow_run job). See examples/fork-safe/. Leave unset (comment) unless you have wired the fork-comment topology. | no | comment |
| run-id | mode=post only: the triggering run id whose `sift-comment` artifact to post — the workflow_run event's run id (see examples/fork-safe). | no | "" |
| build-workflow | mode=post only (optional): the expected build workflow (file name or display name) to double-check the triggering run against. The workflow_run trigger filter is the primary guard. | no | "" |
Outputs
| name | description |
|---|---|
| state | Verdict: cold-start | clean | drift | regression. |
| total-changes | Total observed deltas (the "of N" number, before significance suppression). |
| significant-changes | Deltas that cleared the significance floor. |
| regression | true when a regression was flagged (a regression row OR a run-verdict regression), else false. |
| baseline-outcome | The baseline run's engine-resolved verdict: SUCCESS | FAILURE | UNSTABLE | ABORTED | UNKNOWN. |
| changed-outcome | This run's engine-resolved verdict: SUCCESS | FAILURE | UNSTABLE | ABORTED | UNKNOWN. |
| outcome-regressed | true when the run verdict got strictly worse (Success < Unstable < Failure; Aborted/Unknown excluded). |
| report-path | Filesystem path to this run's deterministic report.json on a stable, cross-step location ($RUNNER_TEMP/sift-report.json). Empty on cold start (no baseline ⇒ no report). A later step on the SAME runner can narrate it with `sift explain --report <path>` — the same content already in the comment/summary; no credential (contract § 3.6). |