{
  "markdown": "# cejel\n\n[![release](https://img.shields.io/github/v/release/BargLabs/cejel)](https://github.com/BargLabs/cejel/releases/latest)\n[![license: AGPL-3.0-only](https://img.shields.io/badge/license-AGPL--3.0--only-blue.svg)](./LICENSE)\n\nCejel (*\"SEH-jel\"*) — a trust certificate for your codebase.\n\nFree, offline, no-signup CLI that scores the engineering signals that tell you whether to\ntrust a repo — tests, secrets, isolation, claim-vs-reality, CI/audit discipline — and prints\na trust certificate + badge. Especially valuable when AI wrote a lot of the code: that's\nexactly when you can't eyeball trust. Built on a deterministic, no-LLM scoring core — the\nfree path makes zero network calls and requires no account.\n\n**Claim boundary:** Cejel scores engineering-trust signals; it does not claim to detect software\ndefects or prove that code is safe. Defect and vulnerability scanners remain evidence producers\nthat Cejel can aggregate into a trust certificate.\n\nCejel is not another point scanner competing with the one you already run — it's the open,\nportable, offline trust certificate that aggregates them. Pipe in SARIF-compatible output\n(MunaTrust, Snyk, Semgrep, CodeQL, Codex) plus OpenSSF Scorecard, and get one shareable\ncertificate + badge over all of them. See \"Aggregate your scanners\" below.\n\n> Dogfooded in production. Cejel is run continuously on Barg Labs' own multi-product\n> monorepo — the ten-product studio it was built inside — which it currently scores\n> 3.3/4.0 on its rubric-native certificate. That transparency snapshot opts into prospective\n> v18; the public CLI default remains calibrated v17. On the comparative board, our code sits\n> outside the ranked population and receives no verdict band. We score ourselves before\n> asking you to score yourself.\n\n### Rubric calibration policy\n\nThe public CLI default is `witan-rubric-v17-2026-07-24`, the last rubric to clear Cejel's\npreregistered 200-repository untouched holdout. Published calibration figures apply only to that\nexact rubric and frozen evaluation population. Later rubrics—including the current v18 through\nv23 prospective series—are available only to explicit evaluation harnesses. Prospective rubrics\ninherit none of v17's calibration figures; a bounded paired repair or corpus-delta result can\nvalidate its stated construction without transferring precision, recall, or false-positive-rate\nclaims. Promoting a prospective rubric to the public default requires a fresh authenticated\nuntouched holdout, every preregistered gate to pass, and a separately recorded promotion decision.\n\n### Measured recall (bounded)\n\n> **Measured recall (bounded).** Cejel publishes no general detection-recall figure. On a frozen,\n> preregistered, in-scope held-out fixture set of 30 named defects, the released public default\n> (v17, tree `a857f0b3`) cited **16/30**, two-sided 95% Wilson interval **[36.1%, 69.8%]**; the\n> prospective v22 detector (commit `8a289ea`, tree `10960a03`) cited **24/30**, two-sided 95%\n> Wilson interval **[62.7%, 90.5%]**. Same fixtures, same partition, same controls in both runs.\n> v22 is prospective and not the shipped default. Full preregistrations and results:\n> `docs/experiments/in-scope-detection-recall-v3-result-2026-08-09.md` and\n> `docs/experiments/in-scope-detection-recall-v4-result-2026-08-11.md`.\n\nThe [defect-class census](docs/defect-class-census.md) publishes the coverage-breadth\nboundary—which defect classes any shipped rule targets—and is explicitly not a recall claim.\n\n## Install\n\nNo account, no key, no signup.\n\n**Single-file binary.** One file. No Node, no npm, no `node_modules`, nothing installed.\n\n```bash\nset -eu\nasset=\"cejel-$(uname -s)-$(uname -m)\"\ncurl -fsSL \"https://github.com/BargLabs/cejel/releases/latest/download/$asset\" -o \"$asset\"\ncurl -fsSL https://github.com/BargLabs/cejel/releases/latest/download/SHA256SUMS -o SHA256SUMS\nchecksum_entry_count=\"$(awk -v asset=\"$asset\" '$2 == asset { count++ } END { print count + 0 }' SHA256SUMS)\"\nif [ \"$checksum_entry_count\" -ne 1 ]; then\n  echo \"Expected exactly one SHA256SUMS entry for $asset; found $checksum_entry_count\" >&2\n  exit 1\nfi\nif command -v sha256sum >/dev/null; then\n  grep \"  $asset$\" SHA256SUMS | sha256sum -c -\nelse\n  grep \"  $asset$\" SHA256SUMS | shasum -a 256 -c -\nfi\nmv \"$asset\" cejel\nchmod +x cejel\n./cejel .\n```\n\n**Windows x86_64 (PowerShell).**\n\n```powershell\n$asset = \"cejel-Windows-x86_64.exe\"\nInvoke-WebRequest \"https://github.com/BargLabs/cejel/releases/latest/download/$asset\" -OutFile $asset\nInvoke-WebRequest \"https://github.com/BargLabs/cejel/releases/latest/download/SHA256SUMS\" -OutFile SHA256SUMS\n$expected = ((Select-String -Path SHA256SUMS -Pattern \"  $([regex]::Escape($asset))$\").Line -split \"\\s+\")[0]\n$actual = (Get-FileHash -Algorithm SHA256 $asset).Hash.ToLowerInvariant()\nif (-not $expected -or $actual -ne $expected.ToLowerInvariant()) {\n  throw \"SHA-256 verification failed for $asset\"\n}\n.\\cejel-Windows-x86_64.exe .\n```\n\n> **Windows signing status:** `cejel-Windows-x86_64.exe` is intentionally unsigned in\n> 0.4.7 and may trigger Microsoft SmartScreen. The release build removes Node's inherited\n> signature before SEA injection and fails unless Windows reports the result as `NotSigned`;\n> it does not ship an invalid signature. Before running it, verify `SHA256SUMS` and the\n> GitHub build-provenance attestation. Each binary also has an attached SPDX SBOM and an\n> own-platform verification receipt covering `--version`, `--help`, a real scan,\n> source/binary parity, and a network-denied scan. If your policy requires Authenticode,\n> use the npm package or the OCI image until a human-approved signing path is available.\n\n**Don't take the offline claim on trust — check it.** Turn your network off, then run the\nbinary. It will score your repository and write you a certificate anyway. That is the whole\nproduct, and you can falsify it in ten seconds:\n\n```bash\n# with Wi-Fi off, or:\ndocker run --rm --network=none -v \"$PWD:/w\" -w /w -v \"$PWD/cejel:/cejel:ro\" debian:stable-slim /cejel .\n```\n\n**npm.**\n\n```bash\nnpx @cejel/cejel@latest .\n```\n\n> **Distribution note:** Cejel `0.4.7` is the coordinated release version for npm,\n> standalone binaries, Docker/OCI, GitHub Action, Homebrew, and MCP Registry.\n\n`npx` can reuse a stale cached package. Force the current npm release with the `@latest`\nspecifier above, and check the version that will run before comparing certificates:\n\n```bash\nnpx @cejel/cejel@latest --version\n```\n\nIf a root `package.json` still carries a template name, override only the certificate display\nname while keeping the repository-derived stable slug:\n\n```bash\nnpx @cejel/cejel@latest . --name \"Customer Portal\"\n```\n\nFrom 0.4.5, use `--product-name` when two checkout directories must emit the\nsame identity fields. The supplied value sets both the display name and its slugified stable ID:\n\n```bash\nnpx @cejel/cejel@latest . --product-name \"Customer Portal\"\n```\n\nProduct identity is caller context, not scored repository evidence, and is excluded from\ncertificate byte-comparison claims.\n\nThe npm package is scoped as `@cejel/cejel`; its executable remains the short command `cejel`.\n\n**GitHub Action** — score every PR and publish the badge:\n\n```yaml\n- uses: BargLabs/cejel/action@v1\n  with:\n    min-score: \"2.5\"   # optional: fail the build below this\n```\n\nFor an executed public example that binds a release artifact to the same commit named by its\nCejel certificate, see [Certified releases with GitHub build provenance](./docs/certified-release-example.md).\n\n**From source** — it is AGPL and it runs offline, so reading it is rather the point:\n\n```bash\ngit clone https://github.com/BargLabs/cejel && cd cejel\npnpm install && pnpm build\nnode dist/index.js .\n```\n\nReleased binaries: `cejel-Darwin-arm64`, `cejel-Darwin-x86_64`, `cejel-Linux-aarch64`,\n`cejel-Linux-x86_64`, and `cejel-Windows-x86_64.exe`. The release also carries\n`SHA256SUMS`, a per-binary SPDX SBOM, and an own-platform verification receipt. Each binary\nis executed against the source build and with networking denied before attachment. Releases\nfrom v0.1.6 also carry a Sigstore bundle containing GitHub's signed build-provenance\nattestation for the release set. Verify a downloaded binary with:\n\n```bash\ngh attestation verify ./cejel-Windows-x86_64.exe -R BargLabs/cejel\n```\n\nThis is cryptographically signed provenance. It is distinct from Apple Developer ID or\nMicrosoft Authenticode code-signing.\n\n**Docker / OCI.** The current container release is `0.4.7`:\n\n```bash\ndocker run --rm -i -v \"$PWD:/workspace:ro\" ghcr.io/barglabs/cejel:0.4.7\n```\n\nThe image defaults to `cejel-mcp` over stdio. To use the CLI instead:\n\n```bash\ndocker run --rm -v \"$PWD:/workspace:ro\" --entrypoint cejel ghcr.io/barglabs/cejel:0.4.7 .\n```\n\nThe OCI image carries an SBOM, maximum-mode build provenance, and a signed registry\nattestation.\n\n## Leaderboard\n\nThis repo ships the [Cejel OSS trust leaderboard](./leaderboard/leaderboard.md): elite OSS\nprojects, the public Cejel repository itself, and one explicitly labeled transparency\nsnapshot from the private studio monorepo where Cejel was built, with a per-repository\nevidence report for every row under [`leaderboard/reports/`](./leaderboard/reports/). The\nboard is also hosted at [cejel.dev](https://cejel.dev). Every score is produced by the same\nsealed public scorer used by `npx @cejel/cejel@latest .`; no private domain collector contributes.\nFor each public-repository row, check out the immutable source commit printed in its report\nand run the public scorer to reproduce the score, verdict, measured coverage, and evidence.\nThe private Alfred snapshot discloses its limitation instead: its source commit and withheld\nlocations are not publicly available, so that row is not independently reproducible and is\nnot presented as a public-repository self-score.\n\n### Redaction policy\n\nA path is published exactly when the reader can check it. Every public repository on the\nboard cites full evidence paths and line numbers, everywhere, in every artifact — a\ncertificate whose evidence you cannot open is not evidence. The private-repository entry\n(the studio monorepo's transparency snapshot) never cites a source path, anywhere, in any\nfield or format — but the finding itself, its\ndimension, status, score, and content hash always survive; only the location is withheld,\nmarked uniformly as \"path withheld — private repository\". Redaction removes a location, never\na fact: a private repository failing its own check still shows up on its certificate, by\nname. The v3 repository scanner marks B1 and B5 not applicable for every repository,\nincluding ours; it does not accept structured substrate evidence for them. They remain\ndefined for other rubric inputs, while the repository ranking excludes them fail-closed.\nNobody is scored on evidence the public scanner cannot collect.\n\n### Known false positives (fixed before publishing)\n\nCalibrating a rubric against real, elite repositories surfaces mistakes; the record is part\nof the trust claim, not something to bury. Two dimensions produced a punitive score for the\n*absence* of a ratable surface rather than a real weakness, and both are fixed:\nDjango was flagged critical on dependency hygiene for using version ranges instead of exact\npins — normal, deliberate practice for a library, not an app; the rubric now scores\ndependency hygiene against archetype-appropriate norms. OSSF Scorecard — Google's own\nsupply-chain security auditing tool — was flagged critical on audit-trail completeness for\npublishing release notes via GitHub Releases instead of a committed `CHANGELOG.md`; a\nrepository with no ratable audit surface now returns \"insufficient data\" (excluded from the\ncomposite) instead of a punitive score. The board also publishes a measured-coverage\nindicator per row: a score reflects only its *measured* dimensions, and a row scored on fewer\nthan half of its applicable dimensions is shown as unranked rather than ordered against\nbetter-evidenced rows.\n\n## Usage\n\n```bash\n./cejel scan .\n```\n\n`scan` scores the current directory with sensible defaults: no signup, fully offline. The\noriginal `./cejel .` form remains supported as a compatibility shorthand.\nPrints a concise terminal certificate and writes to `.cejel/`:\n\n- `report.json` — the full structured report; scored runs carry numeric headline scores and a\n  score-band `verdict`, while abstained runs carry `null` scores and `verdict: \"insufficient_source\"`\n- `attestation.json` — an unsigned in-toto statement binding the report digest, repository\n  revision, rubric, and scored-or-abstained outcome; ready for an external signer\n- `certificate.html` — a self-contained HTML certificate (no external assets)\n- `badge.json` — a [shields.io endpoint](https://shields.io/badges/endpoint-badge) payload\n- `badge.svg` — a static, self-contained trust-score badge\n- `summary.json` — a compact digest (score, verdict, top findings)\n\nThe attestation is deliberately explicit about its assurance level: Cejel creates the\nstatement, but it does not pretend to be an independent signer. Until a customer, reviewer,\nor provenance system signs it, `assurance.status` is `unsigned` and `issuer` is\n`self-generated`. An abstained scan carries only the refusal reason, never a numeric score.\n\nVerify that an emitted report still matches its attestation:\n\n```bash\n./cejel verify .cejel/report.json .cejel/attestation.json\n```\n\nThis verifies the report schema and the report-to-attestation digest, repository, rubric,\ntimestamp, and outcome binding. It does not verify a signature or signer identity; the command\nprints that boundary on every successful verification.\n\n### Flags\n\n- `<path>` — repo to score (default: current directory)\n- `--out <dir>` — where to write report/certificate/badge files (default: `.cejel`;\n  `--out-dir` remains available as a compatibility alias)\n- `--min-score <n>` — exit non-zero if the overall score is below `n` (0–4), or if Cejel\n  abstains and therefore cannot evaluate the threshold; used by the GitHub Action's optional\n  threshold gate\n- `--product-name <name>` — Set both the caller-context\n  display name and slugified product ID so differently named checkouts can emit identical\n  certificates.\n- `--name <display>` — override only the displayed project name while leaving the derived slug\n  unchanged; retained for compatibility\n- `--ingest <file|glob>` — fold another scanner's output into the score (repeatable). Accepts\n  SARIF, OpenSSF Scorecard JSON, or the generic Cejel external-signal shape — format is\n  auto-detected. See \"Aggregate your scanners\" below.\n- `--rubric-pin <version>` — Explicit opt-in only: pin an alternate rubric instead of the\n  calibrated public default. It\n  accepts the calibrated version or any published prospective rubric\n  (`witan-rubric-v18-prospective-*` through `v23`) and fails closed, naming what was accepted, on\n  anything else. `v23` is prospective and uncalibrated, like every rubric after v17: the public\n  default (`WITAN_LAST_CALIBRATED_RUBRIC_VERSION`) is still `witan-rubric-v17-2026-07-24`, and v23\n  inherits none of v17's precision, recall, or false-positive-rate figures. It inherits v22\n  detector/scoring behavior and adds bounded A1 coverage-flag recognition (#276) plus per-signal\n  (rather than per-criterion) abstention for A1's `coverage_percent`/`non_hollow_test_share`\n  metrics (#278); every other criterion still abstains\n  criterion-wide under v23, same as v17/v22. Omit this flag for the calibrated result every\n  default scan produces — a prospective pin carries no precision/recall claim, and the terminal\n  certificate, HTML certificate, and Markdown report all state that plainly whenever one is used.\n- `--run-attempt <n>` — record which CI run attempt produced this certificate, surfaced on the\n  human-readable certificate and as an additive-optional `predicate.githubRunAttempt` field on\n  `attestation.json`. The GitHub Action sets this automatically from `GITHUB_RUN_ATTEMPT`; omit it\n  for a local scan or any other CI — Cejel never fabricates or defaults a run attempt.\n- `--quiet` — suppress the terminal certificate (files are still written)\n- `-h`, `--help` — print usage and exit successfully\n- `-v`, `--version` — print the version derived from the package manifest and exit successfully\n\n## Supported languages\n\nCejel reads a repository's file tree, not its bytecode — it needs to recognise a file's\nsource extension to say anything about it. It does not support every language, and it says so\nhonestly rather than guessing:\n\n- **Deeply modelled** — JS/TS, Python: test detection, coverage, and claim-vs-reality checks\n  are tuned specifically for these ecosystems.\n- **Partially modelled** — Go, Rust, Java, Ruby, PHP, C#, C/C++, Swift, Kotlin, Dart, Elixir,\n  Scala: recognised as source and scored on the language-agnostic dimensions (CI discipline,\n  dependency hygiene, audit trail, secrets), but without ecosystem-specific test-framework\n  tuning.\n- **Recognised but unmodelled** — shell, R, Lua, Julia, Haskell, Terraform, SQL, Perl, OCaml,\n  Clojure, Erlang, Nim, Zig, F#, Groovy, Fortran, CUDA/HIP, Web templates/styles: counted as\n  source so a repo isn't misread as empty, but with the least ecosystem-specific tuning of the\n  three tiers.\n- **Not yet recognised** — other ecosystems, including COBOL and MATLAB. Cejel does\n  not score these as \"source\" at all: a repository with zero\n  recognised-extension files gets the `unrecognised_ecosystem` archetype, an explicit\n  `insufficient_data` criterion status, `null` headline scores, and an explicit machine verdict\n  of `insufficient_source` — never a numeric score-band verdict, and never the word\n  \"Unverified\" for the sole reason that cejel cannot read the language. The certificate states\n  plainly which of the 11 dimensions were and were not measured.\n\nThis list will grow. It will never be \"any codebase\" — that claim is a promise the parser\ncannot keep, and an honest support matrix is worth more than a marketing line the code\ncontradicts on the first unsupported repository someone runs it against.\n\n## Aggregate your scanners\n\nCejel doesn't compete with your AI-code scanner (MunaTrust, Snyk, Semgrep, CodeQL, Codex,\nwhatever runs in CI) — it sits on top of it. Feed a scanner's output in with `--ingest` and\nCejel folds those findings into the same rubric-scored, offline trust certificate, with the\ncontributing tools shown in the certificate and report as provenance:\n\n```bash\n./cejel . --ingest munatrust.sarif --ingest scorecard.json\n```\n\nOr drop files in `.cejel/inputs/` and they're picked up automatically, no flag needed:\n\n```bash\nmkdir -p .cejel/inputs\ncp munatrust-results.sarif .cejel/inputs/\n./cejel .\n```\n\nExternal findings only ever adjust a dimension score *downward*, and by a bounded amount —\nthey augment the native repo scan, they never replace it. Every ingested file is attributed\nby name in `certificate.html`, `report.json` (`consumedSignals`), and the terminal output\n(\"Incorporates findings from: ...\"), so the certificate reads as a visible aggregation, not a\nblack box.\n\nThree ways a scanner's output gets ingested:\n\n1. **SARIF** — any SARIF 2.1.0-emitting tool (Semgrep, CodeQL, most commercial SAST/AI-code\n   scanners) works with zero configuration; `--ingest` auto-detects the `runs` array.\n2. **OpenSSF Scorecard** — `scorecard --repo=... --format=json > scorecard.json`, then\n   `--ingest scorecard.json`; auto-detected by its `checks` array.\n3. **Generic JSON** — for a tool that emits neither, map its output into the minimal shape\n   below (or write a small adapter mirroring\n   [`scorecard-adapter.ts`](../witan/src/scorecard-adapter.ts) if the format needs real\n   parsing):\n\n   ```json\n   {\n     \"version\": \"1.0\",\n     \"tool\": \"my-scanner\",\n     \"signals\": [\n       {\n         \"dimension\": \"A2\",\n         \"weight\": 0.7,\n         \"findings\": [\n           {\n             \"ruleId\": \"hardcoded-secret\",\n             \"severity\": \"critical\",\n             \"message\": \"Hardcoded API key detected.\",\n             \"location\": \"src/config.ts:10\"\n           }\n         ]\n       }\n     ]\n   }\n   ```\n\n   `dimension` is one of the Witan rubric criterion ids (`A1`-`A5`, `B1`-`B6`); `weight`\n   (0–1, default `0.5`) bounds how much this signal can move that dimension; `severity` is\n   `critical` | `warning` | `info`; `location` is optional.\n\n   The version field is required. Cejel rejects unversioned generic documents and unknown major\n   versions rather than guessing. See the [generic ingest contract](docs/ingest-contract.md), its\n   [published JSON Schema](docs/schemas/cejel-ingest-v1.schema.json), and the\n   [synthetic CI heal-log mapping](docs/heal-log-mapping.md). Output-field stability and version\n   routing are documented in [format stability](docs/format-stability.md).\n\n## Displaying the trust badge\n\nEndpoint JSON (host `badge.json` anywhere static — a repo file, a gist, GitHub Pages — and\npoint shields.io at it):\n\n```markdown\n![Cejel trust score](https://img.shields.io/endpoint?url=<url-to-your-hosted-badge.json>)\n```\n\nOr commit/link the static SVG directly:\n\n```markdown\n![Cejel trust score](./.cejel/badge.svg)\n```\n\n## GitHub Action\n\nSee [`action/action.yml`](./action/action.yml) — runs Cejel on `push`/`pull_request`,\nposts the score + top findings to the job summary, and can optionally fail the check below\na configurable `min-score` threshold. The scoring step makes no network calls and needs no\nsecrets.\n\n```yaml\n- uses: BargLabs/cejel/action@v1\n  with:\n    min-score: '2.5' # optional; omit to never fail the check\n```\n\n## MCP server (for agents)\n\nThe same package ships a second bin, `cejel-mcp` — a thin MCP (Model Context Protocol)\nserver over stdio, so any MCP client (Claude Code, Cowork, Cursor, Codex) can request a\ntrust certificate as a tool call. It wraps the exact same scan the CLI runs — same scores,\nsame verdict — and is listed on Smithery via the repo's `smithery.yaml`.\n\nAdd it to an MCP client config:\n\n```json\n{\n  \"mcpServers\": {\n    \"cejel\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"--package=@cejel/cejel@latest\", \"cejel-mcp\"]\n    }\n  }\n}\n```\n\nThe server exposes one tool and two resources:\n\n- `scan` — input `{ path, format? }`; scores the repository at `path` and returns the trust\n  cert as JSON (`format: \"summary\"`, the default, is the compact digest; `format: \"json\"` is\n  the full report, identical to the CLI's `report.json`).\n- `cejel://last-scan/certificate.html` and `cejel://last-scan/badge.svg` — the\n  HTML certificate and SVG badge for the most recent scan (the URI scheme derives from the\n  npm package name).\n\nLike the CLI, scoring over MCP is fully offline: no network calls, no telemetry, no signup,\nand the server writes no files.\n\n## Install via Smithery\n\nCejel is listed on the [Smithery](https://smithery.ai/) MCP registry via the repo's\n`smithery.yaml`. Discovery needs no account:\n\n```bash\nnpx -y @smithery/cli@latest mcp search cejel\n```\n\nConnecting through Smithery's own CLI is a separate step and **requires a Smithery account**:\n`smithery mcp add` prompts to `smithery login` before it will create a connection, for every\ncaller, not just first-time ones.\n\n```bash\nnpx -y @smithery/cli@latest mcp add cejel\n```\n\nIf you'd rather not create a Smithery account, the generic MCP client config above needs no\nlogin and no third-party CLI at all — it talks to the same `cejel-mcp` bin directly.\n\n## Install on OpenClaw\n\nOpenClaw stores outbound MCP servers under `mcp.servers`. Add Cejel with the npm package's\nshipped `cejel-mcp` bin:\n\n```json\n{\n  \"mcp\": {\n    \"servers\": {\n      \"cejel\": {\n        \"command\": \"npx\",\n        \"args\": [\"-y\", \"--package=@cejel/cejel@latest\", \"cejel-mcp\"]\n      }\n    }\n  }\n}\n```\n\nThe equivalent OpenClaw command is:\n\n```bash\nnpx -y openclaw@latest mcp add cejel --command npx --arg -y --arg --package=@cejel/cejel@latest --arg cejel-mcp\nnpx -y openclaw@latest mcp doctor cejel --probe\n```\n\nPin `openclaw@latest` explicitly rather than running bare `openclaw`. The `mcp add`/`mcp\ndoctor` subcommands need OpenClaw ≥`2026.7.1-2`, which itself needs Node ≥22.22.3 (also\n≥24.15 or ≥25.9) — on an older-but-still-supported Node 22 patch, npm's own engines-aware\nresolution silently serves an older OpenClaw release lacking these subcommands, and the\ncommand above fails with `error: unknown option '--command'` instead of a version message.\n\nThe OCI image is an alternative when Docker is the preferred execution boundary. Replace\nthe host path with the repository OpenClaw should allow Cejel to read:\n\n```bash\nnpx -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.4.7\"]}'\nnpx -y openclaw@latest mcp doctor cejel-oci --probe\n```\n\nCejel is active in the Official MCP Registry as `io.github.BargLabs/cejel`. The explicit\nOpenClaw configuration above works independently of catalog indexing.\n\nCejel scans code you point it at. This free adoption surface does **not** watch, intercept,\nor govern an agent's runtime actions. Runtime-action governance is a separate boundary for\nthe future paid Agent Pack.\n\n## What \"offline\" means here\n\nScoring a repo — `cejel scan .` itself, and the Action's scoring step — makes zero network\ncalls: no telemetry, no signup, no model call. The scanner does invoke your local `git`\nbinary through one hardened subprocess chokepoint: fixed argv only (never a shell), an\nexplicit timeout and output bound, prompts and network transports disabled, proxy variables\nremoved, and repository-controlled filesystem monitoring neutralized. A static CI guard\nallows `node:child_process` in that one module only and rejects direct network primitives\neverywhere, while each release binary is also scanned with outbound networking denied.\n\nFetching the `@cejel/cejel` package the first time (like any npm-distributed CLI, including\nthis Action's own dependency install) does need network; that's a one-time install cost, not\npart of the scoring guarantee. If the tracked-file inventory fails unexpectedly, the JSON,\nHTML, and markdown certificates declare that the scanner used its bounded directory fallback\ninstead of silently presenting the two inventories as equivalent.\n\n## Help validate Cejel\n\nCejel does not collect telemetry. External validation is therefore opt-in and inspectable:\n\n- [Report a calibration result](https://github.com/BargLabs/cejel/issues/new?template=calibration.yml)\n  when a score, finding, evidence pointer, or refusal is wrong. The form asks permission before\n  a correction is added to the public error ledger.\n- [Join a pack design-partner pilot](https://github.com/BargLabs/cejel/issues/new?template=pack-interest.yml)\n  for the Quant or Healthcare Pack. Both remain pilot surfaces until their domain-specific\n  calibration gates pass.\n\nSubmit only public or redacted evidence. Never put credentials, proprietary strategy code,\npatient data, or protected health information in a GitHub issue.\n\n## The public leaderboard: what we redact, what we exclude, and where we were wrong\n\nWe publish a trust board scoring a corpus of well-known open-source repositories alongside\nour own. Running a leaderboard on other people's code obliges us to be exact about how it\nworks, so here is all of it.\n\n**What we redact, and on what basis.** One rule: *a path is published exactly when you can\ncheck it.* For a public repository, every evidence path and line number is cited in full — a\ncertificate whose evidence you cannot open is not evidence. For a private repository (ours),\n**no source path is cited anywhere, in any field or format**; an unverifiable path tells you\nnothing you can check while disclosing our file tree for free. Redaction removes a\n**location**, never a **fact**: the finding, its dimension, its status, its score, and its\ncontent hash all survive. Where a path is withheld you will see it said plainly. This is\nenforced structurally — the public artifacts are built from filtered data rather than\nrendered and then scrubbed — and a build that would emit a private path fails rather than\npublishes.\n\n**What we exclude from ranking.** The v5 repository scanner does not evaluate B1 (dispatch\ntrace completeness) or B5 (verified learning trace) for repository inputs, including ours:\nboth are always *not applicable* in a repository certificate. They remain defined in the\nrubric for structured substrate evidence, but that evidence is not accepted by this scanner.\nThe ranking excludes both dimensions fail-closed, including when it reads a legacy or\nseparately produced structured report. We neither score you on evidence the public scanner\ncannot collect nor award ourselves points for evidence you cannot contest.\n\n**Where we were wrong.** Calibrating this rubric against real repositories — and running the\nboard itself like a stranger would — surfaced the errors below in our own tool, every one found\nby us and every one fixed. The list is its own count; we do not keep a tally in this sentence,\nbecause a number typed by hand beside a list that grows is exactly the kind of unchecked claim\nthis tool exists to catch. We publish them because a scoring tool that has never been wrong is a\nscoring tool that has not been checked:\n\n- **Django, scored a false critical on dependency hygiene.** We applied application-shaped\n  expectations to a library. Archetype now gates the dimension.\n- **OpenSSF Scorecard, scored a false critical on audit trail.** We flagged Google's own\n  auditing tool for insufficient auditing. The dimension lacked a \"is there anything here to\n  rate?\" gate before \"how good is it?\"; it has one now.\n- **Twelve of seventeen repositories were silently dropped** from an early build of the\n  board, which nonetheless reported success. The generator could always lose rows without\n  saying so. It now asserts that every repository in the corpus is accounted for — ranked,\n  unranked, or errored — and fails loudly otherwise.\n- **Low-coverage repositories were ranked as though fully measured.** A confidence floor now\n  publishes them without ranking them, rather than implying a precision we did not have.\n- **A1's scheduled-workflow check hardcoded our own internal QA agent's filename** as its\n  definition, instead of the concept it actually measures. It was inert for every external\n  repository by construction — a home-field rule dressed up as a general one. It now detects\n  the *shape* (a cron-scheduled workflow that runs the verification suite, and whether its\n  results are durably published or only handed to an ephemeral CI artifact); our own internal\n  nightly QA workflow is one recognized instance of that shape, not its definition.\n- **Our board and our own certificates disagreed on four repositories' headline scores by\n  0.1** — two coherent bases (the board's fair cross-repo ranking basis, and each\n  certificate's own-dimension basis), one word, \"Overall\", printed on both. We found it on\n  launch day and fixed it: \"Overall\" is now byte-identical everywhere it appears — board,\n  certificate, badge, report, and JSON — and the ranking basis, where it genuinely differs,\n  has its own separate, explicitly labeled column instead of borrowing the same name.\n- **Our own row used a scoring path nobody else could run.** The board generator could add\n  internal collectors after the public scan, so its reassuring collector blacklist was not\n  the invariant it claimed to be. Rubric v3 removes that second path: every corpus row now\n  passes through the same sealed public scorer, every external source is pinned to a commit,\n  and a required guard re-scores every row and compares score, verdict, coverage, and\n  evidence. The honest correction moved Alfred's Code score from 2.5 to 2.4 and A5 from 2.9\n  to 2.4. It is less flattering and more trustworthy.\n- **A tracked symlink could make evidence depend on files outside the checkout.** Repository\n  discovery used a regular-file check that followed symlinks, so a tracked link could escape\n  the immutable source snapshot. Rubric v4 accepts only tracked regular files. On the pinned\n  corpus this removes a duplicate claim source from Zod: A5 moves from 2.2 to 2.0 while its\n  rounded Code score, Overall, verdict, and rank stay unchanged. The full 24-row delta is in\n  the rubric changelog.\n- **A pinned commit could score differently depending on unrelated Git refs in the clone.**\n  History evidence traversed every local and remote-tracking ref, including branches that were\n  not ancestors of the revision being certified. The required clean-clone reproduction job\n  caught the mismatch. Rubric v5 scans only `HEAD` ancestry, so ambient branch state can no\n  longer add evidence or change coverage. The complete v4-to-v5 delta is published in the\n  rubric changelog.\n- **Version 0.1.1 rejected `--help` and `--version` as unknown flags, and read `-h` as a\n  directory path.** Version 0.1.2 handles both aliases before positional-path parsing and\n  derives its printed version from the package manifest.\n- **We reported a timing side-channel in our own test fixtures.** Pointed at its own\n  repository, Cejel's secret-handling dimension flagged a \"non-constant-time secret\n  comparison\" — in string literals inside a test file, the deliberately-insecure example code\n  that exists to prove the detector fires. It read a *file*, not a comparison, and reported a\n  vulnerability in the test written to catch that vulnerability. Two sub-rules of the same\n  dimension held two different private notions of what \"production code\" meant, and the one\n  that had none was the louder. Version 0.1.3 gives every rule one shared, derived answer to\n  that question, and reports the real line of a real match or nothing at all.\n- **We fixed the COBOL false-verdict, shipped it, and it was still broken.** An earlier release\n  corrected a repository written in a language we cannot read being scored anyway. The fixture\n  that proved the fix contained COBOL and nothing else. The first real COBOL repository we\n  pointed it at — AWS's mainframe credit-card demo — carried nine incidental shell scripts\n  among 329 files, and those nine were enough to short-circuit the abstention path entirely:\n  a 99%-COBOL codebase was scored on its deploy scripts and drew a confident `0.0`,\n  \"Unverified\". Every real legacy repository has a deploy script, so the fix that passed every\n  test was unreachable for essentially all of them. Recognised source must now be *dominant*,\n  not merely present. **A fixture cleaner than reality proves nothing.**\n- **Version 0.1.7 missed AVA's root-level `test.js` convention.** A smoke test against\n  `sindresorhus/slugify` reported that a runner was configured but no concrete test files were\n  detected even though `test.js` was present at the repository root. That was a detection gap\n  in Cejel, not evidence about the repository. Rubric v6 recognizes AVA's `test.js` and\n  `test-*.js` conventions; a regression fixture preserves the correction.\n- **Version 0.1.9 claimed Express had no coverage configuration while its package scripts used\n  `nyc`.** The detector looked only for standalone coverage files and framework configuration.\n  Version 0.1.10 also recognizes actual `nyc`, `c8`, and Istanbul commands or configuration in\n  `package.json`. An unused dependency is not treated as coverage evidence. This removes a false\n  finding without changing the measured coverage score.\n- **Metric-only dimension bands told users that “combined metric weighting” was responsible,\n  then stopped.** The underlying metrics were present in the full certificate but absent from\n  the terminal finding, and `info` finding severity could appear beside a `critical` dimension\n  band without naming the two different concepts. Version 0.1.10 prints the two lowest\n  contributing measurements, concrete next actions, `finding severity`, and `dimension band`\n  explicitly. It also explains when a requested scan target is gitignored instead of presenting\n  the target as a generic empty repository.\n\nEvery one was a trust failure produced by *us* — false alarms about other people's code,\nsilent omissions, inconsistent presentation, or a home-only scoring path — and we would\nrather you knew that than discovered it. If you believe the board scores your repository\nwrongly, open an issue — a rubric that cannot be corrected in public has no business being\npublished in public.\n\n**No rubric change re-scores you silently.** Every change to scoring behavior requires a\n`WITAN_RUBRIC_VERSION` bump and a corpus-wide before/after delta published in\n[`docs/leaderboard/RUBRIC_CHANGELOG.md`](../../docs/leaderboard/RUBRIC_CHANGELOG.md) — score,\nverdict, and rank for every repository, \"no repository moved\" stated explicitly when that is\nthe result. A build that changes scoring without both fails; see that file's `v2` entry for\nthe home-field fix above as the first rubric change recorded this way.\n\n## License\n\n`cejel` is free and licensed under [AGPL-3.0-only](./LICENSE), copyleft: any modified\nversion you distribute or run as a network service must also make its source available\nunder the same terms. A commercial license is available for teams that need to use or\nmodify `cejel` without those copyleft obligations.\n",
  "bytes": 37213,
  "sha": "edd4788284c1b173bf15238c9e2de111dc3fad4f5a77f915b58391a57ca172eb",
  "repo_slug": "barglabs/cejel",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_barglabs_cejel_20c31988/readme"
}