Cejel

io.github.BargLabs由 GitHub 帳號 BargLabs 發布v0.6.10更新於 Nov 5, 2026

Offline deterministic engineering-trust certificates for repositories, with no telemetry.

已驗證STDIO僅桌面開發者工具安全與監控

概覽

AI 產生的概覽

Cejel 離線評估儲存庫的工程可信度訊號,並產生綁定到某個提交、可重現的憑證,不使用大型語言模型、無需註冊、無遙測。

可以做什麼
  • 掃描儲存庫目錄樹,輸出附評分與結論的可信度憑證
  • 在輸出目錄寫入報告、證明宣告、HTML 憑證、徽章與摘要檔案
  • 驗證已產生的報告是否仍與其證明宣告的摘要和綁定資訊一致
  • 把其他掃描器的 SARIF 或 OpenSSF Scorecard 輸出併入評分
  • 依最低分數設定門檻,並可指定替代評分規則
適用情境
當你需要一份可分享、他人可重跑的证据,說明儲存庫的測試、已提交的密鑰、CI 把關與宣稱和實際是否一致時適用,特別適合大量程式碼由 AI 撰寫,或要把程式碼庫交給客戶、買方、收購方的情況。
執行需求
以本機程序執行;README 提供單一檔案二進位檔、npm 套件、OCI 映像與 GitHub Action 等方式。無需帳號、金鑰或註冊,免費路徑不發出任何網路請求。依賴歷史的檢查需要完整 git 歷史;淺層複製或沒有 .git 的目錄會被判定為無法評級。
安裝前請注意
它只讀取檔案與歷史,不執行程式碼或測試,也不宣稱能找出缺陷或證明程式碼安全。憑證只描述所固定的那棵目錄樹,存放在別處的证据不會被看到。證明宣告在外部簽署者簽署前是未簽署、自行產生的。Windows 二進位檔未簽署,可能觸發 SmartScreen,執行前應先核對校驗碼與建置來源。

安裝

在 SourceWeft 中

  1. 開啟 儀表板中的 Cejel,將其新增到工作區。
  2. 為需要使用其工具的對話啟用該服務。

Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。

其他 MCP 客戶端

參照 儲存庫 中的啟動說明。

README

cejel

[release] [license: AGPL-3.0-only]

[Cejel logo]

Evidence about a repository that anyone can rerun. Cejel reads a repository's own evidence (tests that really assert something, committed secrets, CI gating) and writes a certificate pinned to one commit. Whoever receives it, a customer, a buyer or an acquirer, can run the same Cejel version on the same commit themselves, offline, and get the same result. No LLM, no signup.

Add it to a workflow; the result is posted to the job summary:

yaml
on: [pull_request]jobs:  cejel:    runs-on: ubuntu-latest    steps:      - uses: actions/checkout@v4        with:          fetch-depth: 0 # full history: A2 and B2 read commit history      - uses: BargLabs/cejel/action@v1

Keep fetch-depth: 0. actions/checkout makes a shallow clone by default, and a shallow clone is "Unrated: shallow clone", with no score and no verdict, under every rubric, the default included, until the full history is checked out. A directory with no .git (an uploaded snapshot or an archive) is "Unrated: no git history" under every rubric.

Or run it once from a shell: npx @cejel/cejel@latest . More on the Action under GitHub Action. To read what comes out, see Reading the result.

Cejel ("SEH-jel") — a trust certificate for your codebase.

Free, offline, no-signup CLI that scores the engineering signals that tell you whether to trust a repo — tests, secrets, isolation, claim-vs-reality, CI/audit discipline — and prints a trust certificate + badge. Especially valuable when AI wrote a lot of the code: that's exactly when you can't eyeball trust. Built on a deterministic, no-LLM scoring core — the free path makes zero network calls and requires no account.

Claim boundary: Cejel scores engineering-trust signals; it does not claim to detect software defects or prove that code is safe. Defect and vulnerability scanners remain evidence producers that Cejel can aggregate into a trust certificate.

Cejel is not another point scanner competing with the one you already run — it's the open, portable, offline trust certificate that aggregates them. Pipe in SARIF-compatible output (MunaTrust, Snyk, Semgrep, CodeQL, Codex) plus OpenSSF Scorecard, and get one shareable certificate + badge over all of them. See "Aggregate your scanners" below.

Cejel is used on Barg Labs’ own code. The public board labels publisher-owned snapshots separately from the ranked public repositories.

Rubric calibration policy

The public CLI default is witan-rubric-v17-2026-07-24, the last rubric to clear Cejel's preregistered 200-repository untouched holdout. Published calibration figures apply only to that exact rubric and frozen evaluation population. Later rubrics—including the current v18 through v23 prospective series—are available only to explicit evaluation harnesses. Prospective rubrics inherit none of v17's calibration figures; a bounded paired repair or corpus-delta result can validate its stated construction without transferring precision, recall, or false-positive-rate claims. Promoting a prospective rubric to the public default requires a fresh authenticated untouched holdout, every preregistered gate to pass, and a separately recorded promotion decision.

Measured recall (bounded)

Measured recall (bounded). Cejel publishes one cohort-level in-scope detection-recall figure, for the prospective v22 rubric, in docs/calibration/v22-detection-recall/; no general figure exists, and the three quantities called recall are set side by side on cejel.dev/methodology. On a frozen, preregistered, in-scope held-out fixture set of 30 named defects, the released public default (v17, tree a857f0b3) cited 16/30, two-sided 95% Wilson interval [36.1%, 69.8%]; the prospective v22 detector (commit 8a289ea, tree 10960a03) cited 24/30, two-sided 95% Wilson interval [62.7%, 90.5%]. Same fixtures, same partition, same controls in both runs. v22 is prospective and not the shipped default. Full preregistrations and results: docs/experiments/in-scope-detection-recall-v3-result-2026-08-09.md and docs/experiments/in-scope-detection-recall-v4-result-2026-08-11.md.

The defect-class census publishes the coverage-breadth boundary—which defect classes any shipped rule targets—and is explicitly not a recall claim.

Reading the result

The first page of certificate.html (and the block printed after the verdict in the terminal) answers four questions in plain words, built only from report.json:

  • What holds: the measured areas the report labels Verified, or Info (one label below, listed as "Partly holds"), each with its score out of 4 and the strongest measurement it saw, for example "Rated Verified, at 1.0 out of 4". Only a score of 4.0 is called the top score. A label and a score are set separately, so a Verified area can have a low score; each area's card in the certificate compares the two. An area Cejel did not examine, or examined with no measurement, is never listed here. When the list is empty, one sentence says why: no overall result, no area labelled Verified or Info, or both.
  • What is wrong: every critical and warning-level finding, most serious first, naming the file or area and what is wrong, and every area labelled Critical or Warning that has no critical or warning finding of its own, with its score ("Scored 2.2 out of 4, with no single finding of its own"). A score made up of several measurements is given with its number and level, for example "give 3.1 out of 4, which Cejel counts as a warning".
  • What is not known: what the report records it could not establish, from these fields: an overall result it withheld, with its reason restated from a fixed table (a reason the table does not know reads "Cejel could not rate the source here; see the certificate below"); areas that do not apply, have no measurement, or have no score while a finding stands; areas Cejel could not fully read (named in the report's skipped-content summary or by a scan or history limitation), listed as "not read" with the cause the report ties to that area: files that could not be read, Git LFS pointers, files left out under Cejel's size limit or rules, a scan limitation, or a shallow clone; each scan and history limitation, reworded into plain words; files it did not read; a label moved by imported evidence; and each limit a check recorded on what it examined. Anything the report does not record is not listed, so an empty list does not mean nothing is unknown.
  • What to check next: one line for each wrong or not-known item, taken from a fixed table of reviewed sentences. The line for an area not read, and for a scan limitation, follows its own cause: git lfs pull for Git LFS pointers, making files readable only where they could not be read, and no fix for a size limit or rule. An item with no table entry points to the section of the certificate that holds it.

The first page also says what the result does not cover: Cejel reads files and history and does not run the code or its tests. Under a prospective rubric such as witan-rubric-v27-prospective-2026-10-19, the first page opens, above the verdict line, with the same notice the certificate's header carries: the rubric is not calibrated, and its results carry no precision or recall claim. Every line links to its source further down; the certificate below the first page holds the evidence, unchanged apart from the anchors those links point to. summary.json carries the same lists under plainSummary.

Install

No account, no key, no signup.

Single-file binary. One file. No Node, no npm, no node_modules, nothing installed.

bash
set -euasset="cejel-$(uname -s)-$(uname -m)"curl -fsSL "https://github.com/BargLabs/cejel/releases/latest/download/$asset" -o "$asset"curl -fsSL https://github.com/BargLabs/cejel/releases/latest/download/SHA256SUMS -o SHA256SUMSchecksum_entry_count="$(awk -v asset="$asset" '$2 == asset { count++ } END { print count + 0 }' SHA256SUMS)"if [ "$checksum_entry_count" -ne 1 ]; then  echo "Expected exactly one SHA256SUMS entry for $asset; found $checksum_entry_count" >&2  exit 1fiif command -v sha256sum >/dev/null; then  grep "  $asset$" SHA256SUMS | sha256sum -c -else  grep "  $asset$" SHA256SUMS | shasum -a 256 -c -fimv "$asset" cejelchmod +x cejel./cejel .

Windows x86_64 (PowerShell).

powershell
$asset = "cejel-Windows-x86_64.exe"Invoke-WebRequest "https://github.com/BargLabs/cejel/releases/latest/download/$asset" -OutFile $assetInvoke-WebRequest "https://github.com/BargLabs/cejel/releases/latest/download/SHA256SUMS" -OutFile SHA256SUMS$expected = ((Select-String -Path SHA256SUMS -Pattern "  $([regex]::Escape($asset))$").Line -split "\s+")[0]$actual = (Get-FileHash -Algorithm SHA256 $asset).Hash.ToLowerInvariant()if (-not $expected -or $actual -ne $expected.ToLowerInvariant()) {  throw "SHA-256 verification failed for $asset"}.\cejel-Windows-x86_64.exe .

Windows signing status: cejel-Windows-x86_64.exe is intentionally unsigned in 0.6.10 and may trigger Microsoft SmartScreen. The release build removes Node's inherited signature before SEA injection and fails unless Windows reports the result as NotSigned; it does not ship an invalid signature. Before running it, verify SHA256SUMS and the GitHub build-provenance attestation. Each binary also has an attached SPDX SBOM (the packages bundled into it, listed from the build, and the Node.js runtime it embeds; from the release after 0.6.0 it is attested to the binary) and an own-platform verification receipt covering --version, --help, a real scan, source/binary parity, and a network-denied scan. If your policy requires Authenticode, use the npm package or the OCI image until a human-approved signing path is available.

Don't take the offline claim on trust — check it. Turn your network off, then run the binary. It will score your repository and write you a certificate anyway. That is the whole product, and you can falsify it in ten seconds:

bash
# with Wi-Fi off, or:docker run --rm --network=none -v "$PWD:/w" -w /w -v "$PWD/cejel:/cejel:ro" debian:stable-slim /cejel .

npm.

bash
npx @cejel/cejel@latest .

Distribution note: Cejel 0.6.10 is the coordinated release version for npm, standalone binaries, Docker/OCI, GitHub Action, Homebrew, and MCP Registry. A GitLab CI template and Code Quality export live in docs/gitlab-ci.md.

npx can reuse a stale cached package. Force the current npm release with the @latest specifier above, and check the version that will run before comparing certificates:

bash
npx @cejel/cejel@latest --version

If a root package.json still carries a template name, override only the certificate display name while keeping the repository-derived stable slug:

bash
npx @cejel/cejel@latest . --name "Customer Portal"

From 0.4.5, use --product-name when two checkout directories must emit the same identity fields. The supplied value sets both the display name and its slugified stable ID:

bash
npx @cejel/cejel@latest . --product-name "Customer Portal"

Product identity is caller context, not scored repository evidence, and is excluded from certificate byte-comparison claims.

The npm package is scoped as @cejel/cejel; its executable remains the short command cejel.

GitHub Action — score every PR and publish the badge:

yaml
- uses: actions/checkout@v4  with:    fetch-depth: 0     # full history: A2 and B2 read commit history- uses: BargLabs/cejel/action@v1  with:    min-score: "2.5"   # optional: fail the build below this

actions/checkout fetches one commit by default, so clone in full with fetch-depth: 0. Under every rubric, the calibrated default included, a shallow clone gets no composite score and no verdict until the full history is checked out. The scan abstains (insufficient_source), still reads and shows each criterion, and says what to do: run git fetch --unshallow (or check out with full history, for example fetch-depth: 0 in actions/checkout), then scan again. The certificate, the badge and the Action's verdict output read "Unrated: shallow clone", and the Action's limited output is true. With --min-score an abstained scan fails the check, as any abstention does, and the message says how to fetch the history. If git cannot report the depth (git is not installed, or cannot open the repository), Cejel reads it from the repository's .git files; if those do not settle it either, the scan abstains the same way as "Unrated: history depth unknown". Among the criteria shown on a shallow clone, A2's scans of earlier commits for .env files and credentials read only the commits it holds, so A2 abstains unless a confirmed critical secret finding stands, including where it would otherwise be marked not applicable, since that decision also rests on earlier commits; B2 withholds its pull-request merge ratio, or abstains where nothing else is left to score it on, saying why in its note. The certificate says so under "History limitations". Until 2 November 2026 this held only under the opt-in prospective v27 rubric (--rubric-pin witan-rubric-v27-prospective-2026-10-19; v17 remains the default), and the default rubric scored a shallow clone, on which A2 could not see a secret committed and later deleted. A complete clone is scored exactly as before.

A directory that is not a git repository gets no composite score and no verdict under every rubric, v27 included: "Unrated: no git history". That covers a directory with no .git, a tarball, an archive export of a commit, and every snapshot uploaded to the HTTP or remote-MCP server. A2 abstains, since no commit history was read, unless a confirmed critical secret finding stands on the files. Scan a git clone with full history; an uploaded snapshot or archive carries no history.

On a clone that is not shallow, A2 abstains under v27 where one of its reads of earlier commits failed: for example on a partial clone made with --filter, which fetch-depth: 0 and no filter avoid, or where a read stops at one of Cejel's own limits: an output limit or the history secret scan's cap of 5,000 historical files, which happen on some large complete histories and which a re-scan of the same repository does not lift (#567), or the 30-second timeout, which a re-scan may lift. It also abstains when it leaves a credential-shaped path in history unread because the path's name contains control characters, and when git itself cannot be run on the scanning host. Each of these abstentions counts as 0 in the composite, so they can lower the v27 score.

For an executed public example that binds a release artifact to the same commit named by its Cejel certificate, see Certified releases with GitHub build provenance.

From source — it is AGPL and it runs offline, so reading it is rather the point:

bash
git clone https://github.com/BargLabs/cejel && cd cejelpnpm install && pnpm buildnode dist/index.js .

Released binaries: cejel-Darwin-arm64, cejel-Darwin-x86_64, cejel-Linux-aarch64, cejel-Linux-x86_64, and cejel-Windows-x86_64.exe. The release also carries SHA256SUMS, a per-binary SPDX SBOM, and an own-platform verification receipt. The SBOM lists the packages bundled into the binary plus its embedded Node.js runtime. The 0.6.0 SBOMs do not: they list only the scanned directory and the binary. See docs/release-process.md. Each binary is executed against the source build and with networking denied before attachment. Releases from v0.1.6 also carry a Sigstore bundle containing GitHub's signed build-provenance attestation for the release set. Verify a downloaded binary with:

bash
gh attestation verify ./cejel-Windows-x86_64.exe -R BargLabs/cejel

This is cryptographically signed provenance. It is distinct from Apple Developer ID or Microsoft Authenticode code-signing.

Docker / OCI. The current container release is 0.6.10:

bash
docker run --rm -i -v "$PWD:/workspace:ro" ghcr.io/barglabs/cejel:0.6.10

The image defaults to cejel-mcp over stdio. To use the CLI instead:

bash
docker run --rm -v "$PWD:/workspace:ro" --entrypoint cejel ghcr.io/barglabs/cejel:0.6.10 .

The OCI image carries an SBOM of its base-image packages, maximum-mode build provenance, and a signed registry attestation. From the release after 0.6.0 it also carries a second SPDX attestation listing the packages Cejel bundles. The 0.6.0 image's SBOM does not list those.

Leaderboard

The Cejel OSS trust leaderboard is hosted on cejel.dev, which is the single current board. This repository no longer distributes a second copy of its scores or certificates. The board records its producing package version, rubric, run date, pinned public revisions, and reproduction instructions for that particular run. The board's row for Barg Labs' own private codebase is a transparency snapshot and is not independently reproducible.

The site's History section preserves the 2026-08-18 withdrawal: the earlier sealed-public-scorer reproducibility claim was false. The stale prospective-rubric copy previously linked here has been removed; it must not be treated as current evidence.

Redaction policy

A path is published exactly when the reader can check it. Every public repository on the board cites full evidence paths and line numbers, everywhere, in every artifact — a certificate whose evidence you cannot open is not evidence. The private-repository entry (the studio monorepo's transparency snapshot) never cites a source path, anywhere, in any field or format — but the finding itself, its dimension, status, score, and content hash always survive; only the location is withheld, marked uniformly as "path withheld — private repository". Redaction removes a location, never a fact: a private repository failing its own check still shows up on its certificate, by name. The v3 repository scanner marks B1 and B5 not applicable for every repository, including ours; it does not accept structured substrate evidence for them. They remain defined for other rubric inputs, while the repository ranking excludes them fail-closed. Nobody is scored on evidence the public scanner cannot collect.

Known false positives (fixed before publishing)

Calibrating a rubric against real, elite repositories surfaces mistakes; the record is part of the trust claim, not something to bury. Two dimensions produced a punitive score for the absence of a ratable surface rather than a real weakness, and both are fixed: Django was flagged critical on dependency hygiene for using version ranges instead of exact pins — normal, deliberate practice for a library, not an app; the rubric now scores dependency hygiene against archetype-appropriate norms. OSSF Scorecard — Google's own supply-chain security auditing tool — was flagged critical on audit-trail completeness for publishing release notes via GitHub Releases instead of a committed CHANGELOG.md; a repository with no ratable audit surface now returns "insufficient data" (excluded from the composite) instead of a punitive score. The board also publishes a measured-coverage indicator per row: a score reflects only its measured dimensions, and a row scored on fewer than half of its applicable dimensions is shown as unranked rather than ordered against better-evidenced rows.

Usage

bash
./cejel scan .

scan scores the current directory with sensible defaults: no signup, fully offline. The original ./cejel . form remains supported as a compatibility shorthand. Prints a concise terminal certificate and writes to .cejel/:

  • report.json — the full structured report; scored runs carry numeric headline scores and a score-band verdict, while abstained runs carry null scores and verdict: "insufficient_source"
  • attestation.json — an unsigned in-toto statement binding the report digest, repository revision, rubric, and scored-or-abstained outcome; ready for an external signer
  • certificate.html — a self-contained HTML certificate (no external assets)
  • badge.json — a shields.io endpoint payload
  • badge.svg — a static, self-contained trust-score badge
  • summary.json — a compact digest (score, verdict, top findings)

The attestation is deliberately explicit about its assurance level: Cejel creates the statement, but it does not pretend to be an independent signer. Until a customer, reviewer, or provenance system signs it, assurance.status is unsigned and issuer is self-generated. An abstained scan carries only the refusal reason, never a numeric score.

Verify that an emitted report still matches its attestation:

bash
./cejel verify .cejel/report.json .cejel/attestation.json

This verifies the report schema and the report-to-attestation digest, repository, rubric, timestamp, and outcome binding. It does not verify a signature or signer identity; the command prints that boundary on every successful verification.

Flags

  • <path> — repo to score (default: current directory)
  • --out <dir> — where to write report/certificate/badge files (default: .cejel; --out-dir remains available as a compatibility alias)
  • --min-score <n> — exit non-zero if the overall score is below n (0–4), if Cejel abstains, or if fewer than half of the applicable dimensions behind any score were measured; used by the GitHub Action's optional threshold gate
  • --product-name <name> — Set both the caller-context display name and slugified product ID so differently named checkouts can emit identical certificates.
  • --name <display> — override only the displayed project name while leaving the derived slug unchanged; retained for compatibility
  • --ingest <file|glob> — fold another scanner's output into the score (repeatable). Accepts SARIF, OpenSSF Scorecard JSON, or the generic Cejel external-signal shape — format is auto-detected. See "Aggregate your scanners" below.
  • --subject-repository <repo> — name the scanned repository (github.com/owner/repo or a clone URL) so an ingested input that declares another repository is recorded as mismatched. Cejel never infers it from clone state.
  • --strict-ingest — refuse, before scoring, an ingested input that declares another repository or commit, was observed before the scanned commit existed, or duplicates another input. Without it, the binding status is recorded and scoring is unchanged. See input binding.
  • --rubric-pin <version> — Explicit opt-in only: pin an alternate rubric instead of the calibrated public default. It accepts the calibrated version or any published prospective rubric (witan-rubric-v18-prospective-* through v27) and fails closed, naming what was accepted, on anything else. The GitHub Action takes the same value as its optional rubric-pin input. v26 (witan-rubric-v26-prospective-2026-10-14) is prospective and uncalibrated: it is the next calibration candidate, inherits v25 complete, inherits neither v23 nor v24, and today scores exactly as v25 does. v25 is prospective and uncalibrated: it inherits v22 and adds only credit for a health or readiness route declared inline in an application file (see "What counts as a health or readiness signal" below). v23 is prospective and uncalibrated, like every rubric after v17: the public default (WITAN_LAST_CALIBRATED_RUBRIC_VERSION) is still witan-rubric-v17-2026-07-24, and v23 inherits none of v17's precision, recall, or false-positive-rate figures. It inherits v22 detector/scoring behavior and adds bounded A1 coverage-flag recognition (#276) plus per-signal (rather than per-criterion) abstention for A1's coverage_percent/non_hollow_test_share metrics (#278); every other criterion still abstains criterion-wide under v23, same as v17/v22. Omit this flag for the calibrated result every default scan produces — a prospective pin carries no precision/recall claim, and the terminal certificate, HTML certificate, and Markdown report all state that plainly whenever one is used.
  • --run-attempt <n> — record which CI run attempt produced this certificate, surfaced on the human-readable certificate and as an additive-optional predicate.githubRunAttempt field on attestation.json. The GitHub Action sets this automatically from GITHUB_RUN_ATTEMPT; omit it for a local scan or any other CI — Cejel never fabricates or defaults a run attempt.
  • --quiet — suppress the terminal certificate (files are still written)
  • -h, --help — print usage and exit successfully
  • -v, --version — print the version derived from the package manifest and exit successfully

Supported languages

Cejel reads a repository's file tree, not its bytecode — it needs to recognise a file's source extension to say anything about it. It does not support every language, and it says so honestly rather than guessing:

  • Deeply modelled — JS/TS, Python: test detection, coverage, and claim-vs-reality checks are tuned specifically for these ecosystems.
  • Partially modelled — Go, Rust, Java, Ruby, PHP, C#, C/C++, Swift, Kotlin, Dart, Elixir, Scala: recognised as source and scored on the language-agnostic dimensions (CI discipline, dependency hygiene, audit trail, secrets), but without ecosystem-specific test-framework tuning.
  • Recognised but unmodelled — shell, R, Lua, Julia, Haskell, Terraform, SQL, Perl, OCaml, Clojure, Erlang, Nim, Zig, F#, Groovy, Fortran, CUDA/HIP, Web templates/styles: counted as source so a repo isn't misread as empty, but with the least ecosystem-specific tuning of the three tiers.
  • Not yet recognised — other ecosystems, including COBOL and MATLAB. Cejel does not score these as "source" at all: a repository with zero recognised-extension files gets the unrecognised_ecosystem archetype, an explicit insufficient_data criterion status, null headline scores, and an explicit machine verdict of insufficient_source — never a numeric score-band verdict, and never the word "Unverified" for the sole reason that cejel cannot read the language. The certificate states plainly which of the 11 dimensions were and were not measured.

This list will grow. It will never be "any codebase" — that claim is a promise the parser cannot keep, and an honest support matrix is worth more than a marketing line the code contradicts on the first unsupported repository someone runs it against.

Aggregate your scanners

Cejel doesn't compete with your AI-code scanner (MunaTrust, Snyk, Semgrep, CodeQL, Codex, whatever runs in CI) — it sits on top of it. Feed a scanner's output in with --ingest and Cejel folds those findings into the same rubric-scored, offline trust certificate, with the contributing tools shown in the certificate and report as provenance:

bash
./cejel . --ingest munatrust.sarif --ingest scorecard.json

Or drop files in .cejel/inputs/ and they're picked up automatically, no flag needed:

bash
mkdir -p .cejel/inputscp munatrust-results.sarif .cejel/inputs/./cejel .

External findings only ever adjust a dimension score downward, and by a bounded amount — they augment the native repo scan, they never replace it. Every ingested file is attributed by name in certificate.html, report.json (consumedSignals), and the terminal output ("Incorporates findings from: ..."), so the certificate reads as a visible aggregation, not a black box.

Three ways a scanner's output gets ingested:

  1. SARIF — any SARIF 2.1.0-emitting tool (Semgrep, CodeQL, most commercial SAST/AI-code scanners) works with zero configuration; --ingest auto-detects the runs array.

  2. OpenSSF Scorecard — scorecard --repo=... --format=json > scorecard.json, then --ingest scorecard.json; auto-detected by its checks array.

  3. Generic JSON — for a tool that emits neither, map its output into the minimal shape below (or write a small adapter mirroring scorecard-adapter.ts if the format needs real parsing):

    json
    {  "version": "1.0",  "tool": "my-scanner",  "signals": [    {      "dimension": "A2",      "weight": 0.7,      "findings": [        {          "ruleId": "hardcoded-secret",          "severity": "critical",          "message": "Hardcoded API key detected.",          "location": "src/config.ts:10"        }      ]    }  ]}

    dimension is one of the rubric criterion ids (A1-A5, B1-B6); weight (0–1, default 0.5) bounds how much this signal can move that dimension; severity is critical | warning | info; location is optional.

    The version field is required. Cejel rejects unversioned generic documents and unknown major versions rather than guessing. See the generic ingest contract, its published JSON Schema, and the synthetic CI heal-log mapping. Output-field stability and version routing are documented in format stability. Contract 1.1 adds optional subject, producer and observedAt fields so the input can be bound to a revision.

Every ingested document is also recorded in report.json under inputBinding: the sha256 of its bytes, the producer and subject its own format declares (Scorecard repo.name/repo.commit/date, SARIF versionControlProvenance and invocations, generic subject/observedAt), and whether that subject is the scanned HEAD (matched, mismatched-repository, mismatched-commit, stale, unbound, unverifiable). By default this is a record, not a gate: it changes no score. --strict-ingest refuses mismatched, stale and duplicate inputs instead. cejel verify ... --input <file> checks a set of input files against the recorded digests, so a swapped input is detected. See input binding, which carries the conformance table the tests run.

Displaying the trust badge

Endpoint JSON (host badge.json anywhere static — a repo file, a gist, GitHub Pages — and point shields.io at it):

markdown
![Cejel trust score](https://img.shields.io/endpoint?url=<url-to-your-hosted-badge.json>)

Or commit/link the static SVG directly:

markdown
![Cejel trust score](./.cejel/badge.svg)

GitHub Action

See action/action.yml — runs Cejel on push/pull_request, posts the score + top findings to the job summary, and can optionally fail the check below a configurable min-score threshold. The scoring step makes no network calls and needs no secrets.

yaml
- uses: actions/checkout@v4  with:    fetch-depth: 0 # full history: A2 and B2 read commit history- uses: BargLabs/cejel/action@v1  with:    min-score: '2.5' # optional; omit to never fail the check

Check out with fetch-depth: 0. The default depth of 1 is a shallow clone, and under every rubric, the default included, a shallow checkout gets no composite score and no verdict: the step summary, the badge and the verdict output read "Unrated: shallow clone", the limited output is true and limitations names the cause, and the scan says to run git fetch --unshallow (or check out with full history, for example fetch-depth: 0 in actions/checkout), then scan again. On a shallow clone A2's scans of earlier commits read only the commits present and B2 withholds its pull-request merge ratio, each with its reason. A repo-path that is not a git repository is "Unrated: no git history" under every rubric. The Action does not pin a rubric, so it scores under the default.

OutputWhat it holds
scoreThe overall score (0.0–4.0), or empty when Cejel abstains.
verdictThe verdict label, or the abstention label (Insufficient source, Insufficient evidence, Unrated: shallow clone, Unrated: history depth unknown, Unrated: no git history).
limitedtrue when scan limitations qualify the result, or when the verdict is Unrated; otherwise false.
limitation-countHow many limitations qualify the certificate, counting an Unrated verdict as one.
limitationsA JSON array of the limitation messages; an Unrated verdict adds one naming its cause.
artifact-dirWhere this run's report artifacts were exported.
InputDefaultWhat it does
repo-paththe checkout ($GITHUB_WORKSPACE)Path to the repository to score.
min-scoreempty: never failFails the step below this overall score (0–4), or when Cejel abstains.
out-dir.cejelEmpty destination for this run's report artifacts.
rubric-pinempty: the calibrated defaultExplicit opt-in only: the same value as the CLI's --rubric-pin. An unknown id fails the step with the CLI's message.

The scoring step is offline whatever the inputs; it never fetches history. To opt in to the prospective v27 rubric, pin it and check out in full with fetch-depth: 0: v27 reads the commit history, so a shallow checkout gets no full v27 result, as under the default. v17 remains the calibrated default.

yaml
- uses: actions/checkout@v4  with:    fetch-depth: 0 # full history: A2 and B2 read commit history- uses: BargLabs/cejel/action@v1  with:    rubric-pin: witan-rubric-v27-prospective-2026-10-19

A prospective pin carries no precision/recall claim, and the certificate states that plainly whenever one is used. Leave rubric-pin empty for the calibrated result every default scan produces: an empty input passes no --rubric-pin, so the scan, the report and the outputs are the same as without the input.

Use with Claude

Cejel ships as a Claude Code plugin in plugins/cejel/. The plugin gives Claude the scan tool below, started through npx and pinned to this release, plus a cejel-scan skill. The skill tells Claude when a scan answers the question and how to read the certificate. It also tells Claude to present a score as evidence for your own judgment, never as an audit or a guarantee.

Install it from this repository's marketplace, inside Claude Code:

text
/plugin marketplace add BargLabs/cejel/plugin install cejel@cejel

From a shell, the same two steps are claude plugin marketplace add BargLabs/cejel and claude plugin install cejel@cejel.

Scanning stays offline: the scan tool makes no network calls and writes no files. The first time the server starts, npx fetches the pinned @cejel/cejel package from npm. When you name a repository that isn't on your machine, Claude asks before cloning it with your git. Neither fetch is part of the scan.

Example prompts that work on a public repository:

Support: GitHub issues. Privacy policy: https://barglabs.ai/privacy. Terms: https://barglabs.ai/terms.

MCP server (for agents)

The same package ships a second bin, cejel-mcp — a thin MCP (Model Context Protocol) server over stdio, so any MCP client (Claude Code, Cowork, Cursor, Codex) can request a trust certificate as a tool call. It wraps the exact same scan the CLI runs — same scores, same verdict — and is listed on Smithery via the repo's smithery.yaml.

Add it to an MCP client config:

json
{  "mcpServers": {    "cejel": {      "command": "npx",      "args": ["-y", "--package=@cejel/cejel@latest", "cejel-mcp"]    }  }}

The server exposes one tool and two resources:

  • scan — input { path, format? }; scores the repository at path and returns the trust cert as JSON (format: "summary", the default, is the compact digest; format: "json" is the full report, identical to the CLI's report.json).
  • cejel://last-scan/certificate.html and cejel://last-scan/badge.svg — the HTML certificate and SVG badge for the most recent scan (the URI scheme derives from the npm package name).

Like the CLI, scoring over MCP is fully offline: no network calls, no telemetry, no signup, and the server writes no files.

Install via Smithery

Cejel is listed on the Smithery MCP registry via the repo's smithery.yaml. Discovery needs no account:

bash
npx -y @smithery/cli@latest mcp search cejel

Connecting through Smithery's own CLI is a separate step and requires a Smithery account: smithery mcp add prompts to smithery login before it will create a connection, for every caller, not just first-time ones.

bash
npx -y @smithery/cli@latest mcp add cejel

If you'd rather not create a Smithery account, the generic MCP client config above needs no login and no third-party CLI at all — it talks to the same cejel-mcp bin directly.

Install on OpenClaw

OpenClaw stores outbound MCP servers under mcp.servers. Add Cejel with the npm package's shipped cejel-mcp bin:

json
{  "mcp": {    "servers": {      "cejel": {        "command": "npx",        "args": ["-y", "--package=@cejel/cejel@latest", "cejel-mcp"]      }    }  }}

The equivalent OpenClaw command is:

bash
npx -y openclaw@latest mcp add cejel --command npx --arg -y --arg --package=@cejel/cejel@latest --arg cejel-mcpnpx -y openclaw@latest mcp doctor cejel --probe

Pin openclaw@latest explicitly rather than running bare openclaw. The mcp add/mcp doctor subcommands need OpenClaw ≥2026.7.1-2, which itself needs Node ≥22.22.3 (also ≥24.15 or ≥25.9) — on an older-but-still-supported Node 22 patch, npm's own engines-aware resolution silently serves an older OpenClaw release lacking these subcommands, and the command above fails with error: unknown option '--command' instead of a version message.

The OCI image is an alternative when Docker is the preferred execution boundary. Replace the host path with the repository OpenClaw should allow Cejel to read:

bash
npx -y openclaw@latest mcp set cejel-oci '{"command":"docker","args":["run","--rm","-i","-v","/absolute/path/to/repo:/workspace:ro","ghcr.io/barglabs/cejel:0.6.10"]}'npx -y openclaw@latest mcp doctor cejel-oci --probe

Cejel is active in the Official MCP Registry as io.github.BargLabs/cejel. The explicit OpenClaw configuration above works independently of catalog indexing.

Cejel scans code you point it at. This free adoption surface does not watch, intercept, or govern an agent's runtime actions. Runtime-action governance is a separate boundary for the future paid Agent Pack.

What "offline" means here

Scoring a repo — cejel scan . itself, and the Action's scoring step — makes zero network calls: no telemetry, no signup, no model call. The scanner does invoke your local git binary through one hardened subprocess chokepoint: fixed argv only (never a shell), an explicit timeout and output bound, prompts and network transports disabled, proxy variables removed, and repository-controlled filesystem monitoring neutralized. A static CI guard allows node:child_process in that one module only and rejects direct network primitives everywhere, while each release binary is also scanned with outbound networking denied.

Fetching the @cejel/cejel package the first time (like any npm-distributed CLI, including this Action's own dependency install) does need network; that's a one-time install cost, not part of the scoring guarantee. If the tracked-file inventory fails unexpectedly, the JSON, HTML, and markdown certificates declare that the scanner used its bounded directory fallback instead of silently presenting the two inventories as equivalent.

What a certificate's scope means

A certificate scores the repository tree at one pinned revision, and only that tree. That boundary is deliberate: a certificate that reached outside the pinned tree could not be reproduced by whoever receives it, and reproducibility is the entire product. Scoring only the pinned tree is correct — the gap was that nothing on the certificate itself told a reader which kind of statement they were holding. A repository whose regression suite lives in a separate repository, checked out and run by its own CI, is correctly reported as having zero test files against its source files. That statement is true about the tree and false about the system, and a reader with no other context cannot tell the difference.

Every certificate now carries a standing scope line, in the "How to read this certificate" section on every surface (HTML, Markdown, terminal), regardless of verdict: the certificate is a statement about the repository tree at the pinned revision, not about the system that tree belongs to, and evidence outside that tree is neither seen nor claimed to be absent. This is additive, not a hedge — a finding that says evidence was not found in this tree stays exactly as stated.

Four specific situations can make the tree's own conclusion misleading about the system it belongs to:

  • A test suite kept in a separate repository. Not detectable from inside the pinned tree — there is no reliable signal that a sibling repository exists. Covered by the standing scope line above, not a conditional disclosure.
  • CI configuration that changes into a different working directory before running its checks. Also not detectable without executing the CI job itself, which the offline scanner does not do. Covered by the standing scope line above.
  • A large implementation file that exceeds the read limit. This one is detectable, and disclosed conditionally when it happens: when a file above the size ceiling is the reason a specific signal has nothing to measure, the certificate's scan-limitations section names it — "declined a large implementation file that exceeded the repository content size limit" — rather than folding it into the generic coverage-limit sentence used for an extension exclusion or a non-regular file. Today this fires for two A3 signals (health/readiness route detection and observability-marker counting); it extends to more signals as they adopt the same per-signal attribution.
  • A recognized-but-nonfunctional package script, such as npm's auto-generated "test": "echo \"Error: no test specified\" && exit 1" placeholder being credited the same as a real test runner. This was a detector defect, not a scope-disclosure gap — Cejel now checks the test script's content against known test-runner invocations rather than crediting it by key presence alone, so no separate disclosure line is needed for it.

What counts as a health or readiness signal

The "health or readiness signal" component of A3's production-readiness checks is filename-based by design under the calibrated rubric (and every prospective rubric before v25). It is credited for exactly these forms:

  • a dedicated health or readiness file, such as health.ts, healthcheck.js, readiness.py (the file must mention health or readiness);
  • a HEALTHCHECK instruction in a root Dockerfile;
  • Kubernetes liveness or readiness probes in a k8s/, kubernetes/ or helm/ manifest.

A route declared inline in an application file does not count under the calibrated rubric, whatever its content: app.get("/health", ...) in server.ts or app.ts earns nothing there, because the component never reads route text. The certificate states this next to the component. Prospective witan-rubric-v25-prospective-2026-10-12, and witan-rubric-v26-prospective-2026-10-14 which inherits it, are the only rubrics that also credit an inline route, in the files the separate info-level "no health or readiness route" finding already reads (under src/, app/, lib/, packages/, functions/, a repo-root server/index/app/main file, or a server/, backend/ or api/ tree), with comments stripped and tests, docs, examples and scripts excluded. Both are explicit opt-in (--rubric-pin), carry no precision or recall claim, and have had no public paired rescore.

Help validate Cejel

Cejel does not collect telemetry. External validation is therefore opt-in and inspectable:

  • Report a calibration result when a score, finding, evidence pointer, or refusal is wrong. The form asks permission before a correction is added to the public error ledger.
  • Join a pack design-partner pilot for the Quant or Healthcare Pack. Both remain pilot surfaces until their domain-specific calibration gates pass.

Submit only public or redacted evidence. Never put credentials, proprietary strategy code, patient data, or protected health information in a GitHub issue.

The public leaderboard: what we redact, what we exclude, and where we were wrong

We publish a trust board scoring a corpus of well-known open-source repositories alongside our own. Running a leaderboard on other people's code obliges us to be exact about how it works, so here is all of it.

What we redact, and on what basis. One rule: a path is published exactly when you can check it. For a public repository, every evidence path and line number is cited in full — a certificate whose evidence you cannot open is not evidence. For a private repository (ours), no source path is cited anywhere, in any field or format; an unverifiable path tells you nothing you can check while disclosing our file tree for free. Redaction removes a location, never a fact: the finding, its dimension, its status, its score, and its content hash all survive. Where a path is withheld you will see it said plainly. This is enforced structurally — the public artifacts are built from filtered data rather than rendered and then scrubbed — and a build that would emit a private path fails rather than publishes.

What we exclude from ranking. The v5 repository scanner does not evaluate B1 (dispatch trace completeness) or B5 (verified learning trace) for repository inputs, including ours: both are always not applicable in a repository certificate. They remain defined in the rubric for structured substrate evidence, but that evidence is not accepted by this scanner. The ranking excludes both dimensions fail-closed, including when it reads a legacy or separately produced structured report. We neither score you on evidence the public scanner cannot collect nor award ourselves points for evidence you cannot contest.

Where we were wrong. Calibrating this rubric against real repositories — and running the board itself like a stranger would — surfaced the errors below in our own tool, every one found by us and every one fixed. The list is its own count; we do not keep a tally in this sentence, because a number typed by hand beside a list that grows is exactly the kind of unchecked claim this tool exists to catch. We publish them because a scoring tool that has never been wrong is a scoring tool that has not been checked:

  • Django, scored a false critical on dependency hygiene. We applied application-shaped expectations to a library. Archetype now gates the dimension.
  • OpenSSF Scorecard, scored a false critical on audit trail. We flagged Google's own auditing tool for insufficient auditing. The dimension lacked a "is there anything here to rate?" gate before "how good is it?"; it has one now.
  • Twelve of seventeen repositories were silently dropped from an early build of the board, which nonetheless reported success. The generator could always lose rows without saying so. It now asserts that every repository in the corpus is accounted for — ranked, unranked, or errored — and fails loudly otherwise.
  • Low-coverage repositories were ranked as though fully measured. A confidence floor now publishes them without ranking them, rather than implying a precision we did not have.
  • A1's scheduled-workflow check hardcoded our own internal QA agent's filename as its definition, instead of the concept it actually measures. It was inert for every external repository by construction — a home-field rule dressed up as a general one. It now detects the shape (a cron-scheduled workflow that runs the verification suite, and whether its results are durably published or only handed to an ephemeral CI artifact); our own internal nightly QA workflow is one recognized instance of that shape, not its definition.
  • Our board and our own certificates disagreed on four repositories' headline scores by 0.1 — two coherent bases (the board's fair cross-repo ranking basis, and each certificate's own-dimension basis), one word, "Overall", printed on both. We found it on launch day and fixed it: "Overall" is now byte-identical everywhere it appears — board, certificate, badge, report, and JSON — and the ranking basis, where it genuinely differs, has its own separate, explicitly labeled column instead of borrowing the same name.
  • Our own row used a scoring path nobody else could run. The board generator could add internal collectors after the public scan, so its reassuring collector blacklist was not the invariant it claimed to be. Rubric v3 removes that second path: every corpus row now passes through the same sealed public scorer, every external source is pinned to a commit, and a required guard re-scores every row and compares score, verdict, coverage, and evidence. The honest correction moved our own private codebase's Code score from 2.5 to 2.4 and A5 from 2.9 to 2.4. It is less flattering and more trustworthy.
  • A tracked symlink could make evidence depend on files outside the checkout. Repository discovery used a regular-file check that followed symlinks, so a tracked link could escape the immutable source snapshot. Rubric v4 accepts only tracked regular files. On the pinned corpus this removes a duplicate claim source from Zod: A5 moves from 2.2 to 2.0 while its rounded Code score, Overall, verdict, and rank stay unchanged. The full 24-row delta is in the rubric changelog.
  • A pinned commit could score differently depending on unrelated Git refs in the clone. History evidence traversed every local and remote-tracking ref, including branches that were not ancestors of the revision being certified. The required clean-clone reproduction job caught the mismatch. Rubric v5 scans only HEAD ancestry, so ambient branch state can no longer add evidence or change coverage. The complete v4-to-v5 delta is published in the rubric changelog.
  • Version 0.1.1 rejected --help and --version as unknown flags, and read -h as a directory path. Version 0.1.2 handles both aliases before positional-path parsing and derives its printed version from the package manifest.
  • We reported a timing side-channel in our own test fixtures. Pointed at its own repository, Cejel's secret-handling dimension flagged a "non-constant-time secret comparison" — in string literals inside a test file, the deliberately-insecure example code that exists to prove the detector fires. It read a file, not a comparison, and reported a vulnerability in the test written to catch that vulnerability. Two sub-rules of the same dimension held two different private notions of what "production code" meant, and the one that had none was the louder. Version 0.1.3 gives every rule one shared, derived answer to that question, and reports the real line of a real match or nothing at all.
  • We fixed the COBOL false-verdict, shipped it, and it was still broken. An earlier release corrected a repository written in a language we cannot read being scored anyway. The fixture that proved the fix contained COBOL and nothing else. The first real COBOL repository we pointed it at — AWS's mainframe credit-card demo — carried nine incidental shell scripts among 329 files, and those nine were enough to short-circuit the abstention path entirely: a 99%-COBOL codebase was scored on its deploy scripts and drew a confident 0.0, "Unverified". Every real legacy repository has a deploy script, so the fix that passed every test was unreachable for essentially all of them. Recognised source must now be dominant, not merely present. A fixture cleaner than reality proves nothing.
  • Version 0.1.7 missed AVA's root-level test.js convention. A smoke test against sindresorhus/slugify reported that a runner was configured but no concrete test files were detected even though test.js was present at the repository root. That was a detection gap in Cejel, not evidence about the repository. Rubric v6 recognizes AVA's test.js and test-*.js conventions; a regression fixture preserves the correction.
  • Version 0.1.9 claimed Express had no coverage configuration while its package scripts used nyc. The detector looked only for standalone coverage files and framework configuration. Version 0.1.10 also recognizes actual nyc, c8, and Istanbul commands or configuration in package.json. An unused dependency is not treated as coverage evidence. This removes a false finding without changing the measured coverage score.
  • Metric-only dimension bands told users that “combined metric weighting” was responsible, then stopped. The underlying metrics were present in the full certificate but absent from the terminal finding, and info finding severity could appear beside a critical dimension band without naming the two different concepts. Version 0.1.10 prints the two lowest contributing measurements, concrete next actions, finding severity, and dimension band explicitly. It also explains when a requested scan target is gitignored instead of presenting the target as a generic empty repository.

Every one was a trust failure produced by us — false alarms about other people's code, silent omissions, inconsistent presentation, or a home-only scoring path — and we would rather you knew that than discovered it. If you believe the board scores your repository wrongly, open an issue — a rubric that cannot be corrected in public has no business being published in public.

No rubric change re-scores you silently. Every change to scoring behavior requires a WITAN_RUBRIC_VERSION bump and a corpus-wide before/after delta published in leaderboard/RUBRIC_CHANGELOG.md — score, verdict, and rank for every repository, "no repository moved" stated explicitly when that is the result. A build that changes scoring without both fails; see that file's v2 entry for the home-field fix above as the first rubric change recorded this way.

License

cejel is free and licensed under AGPL-3.0-only, copyleft: any modified version you distribute or run as a network service must also make its source available under the same terms. A commercial license is available for teams that need to use or modify cejel without those copyleft obligations.

來源:README.md,提交 e3f1a04

工具

0
SourceWeft 曾在隔離沙箱中以無憑證方式啟動該軟體包一次,以列出其工具,但未能完成:該軟體包類型無法在沙箱中執行。

版本歷史

15
  1. v0.6.10最新Nov 5, 2026
  2. v0.6.8Oct 22, 2026
  3. v0.6.7Oct 18, 2026
  4. v0.6.6Oct 16, 2026
  5. v0.6.5Oct 15, 2026
  6. v0.6.4Oct 13, 2026
  7. v0.6.3Oct 10, 2026
  8. v0.6.2Oct 9, 2026
  9. v0.6.1Oct 7, 2026
  10. v0.6.0Oct 3, 2026
  11. v0.5.0Oct 2, 2026
  12. v0.4.11Sep 25, 2026
  13. v0.4.10Sep 17, 2026
  14. v0.4.9Sep 16, 2026
  15. v0.4.8Sep 16, 2026

評分

已滿足適用檢查項的 50%

該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。

  • 近 30 天內可連通25 分

    請保持端點能夠回應 MCP 握手;SourceWeft 每 30 天探測一次。

  • 已宣告認證方式10 分

    請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。

  • 已列出工具15 分

    請讓伺服器在無憑證時回應 tools/list,或發布可在沙箱中無憑證啟動的軟體包。

  • 描述必需15 分
  • 圖示10 分
  • 文件15 分
  • 授權條款10 分