原始 JSON 报告 机器可读
{
"data": {
"repo": {
"topics": [],
"is_fork": false,
"size_kb": 569,
"has_wiki": true,
"homepage": "https://achird-labs.github.io/rift-node/",
"languages": {
"Shell": 1875,
"JavaScript": 19897,
"TypeScript": 756619
},
"pushed_at": "2026-07-22T23:34:15Z",
"created_at": "2026-07-09T21:36:42Z",
"owner_type": "Organization",
"updated_at": "2026-07-21T14:03:28Z",
"description": "Official Node.js/TypeScript SDK for Rift — typed mocking DSL, embedded (koffi FFI) + remote + spawn transports, Vitest/Jest testkit",
"is_archived": false,
"is_disabled": false,
"license_spdx": "MIT",
"default_branch": "master",
"license_spdx_raw": "MIT",
"primary_language": "TypeScript",
"significant_languages": [
"TypeScript"
]
},
"owner": {
"blog": null,
"name": null,
"type": "Organization",
"login": "achird-labs",
"company": null,
"location": null,
"followers": 1,
"avatar_url": "https://avatars.githubusercontent.com/u/306492270?v=4",
"created_at": "2026-07-18T12:33:23Z",
"is_verified": null,
"public_repos": 8,
"account_age_days": 11
},
"license": {
"state": "standard",
"spdx_id": "MIT",
"raw_spdx": "MIT",
"file_present": true,
"scorecard_found": true,
"profile_has_license": true
},
"activity": {
"releases": [
{
"tag": "v0.15.0",
"kind": "minor",
"published_at": "2026-07-21T13:13:02Z"
}
],
"recent_commits": [
{
"oid": "38680683f937f89e3dd6b23f4161e9f46cd9a756",
"body": "rift-node had no docs site and a 17-line root README that only described the\nworkspace layout, while the engine and the Java SDK both publish full sites. A\nreader arriving from npm had nowhere to go.\n\nBuild the site the same way the engine repo does (Jekyll + just-the-docs, GitHub's\nown builder, no \n[…]\non someone remembering\nto register a directory. The landing-page hero is embed-checked against\nexamples/hero.ts rather than hand-copied, which is what took the checker from 10\nverified snippets to 11.",
"is_bot": false,
"headline": "docs: publish a documentation site and rewrite the READMEs (#93)",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-21T13:30:10Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "d39a5b223e68aa801a1dce070de922c5702c2586",
"body": "The published `@rift-vs/rift@latest` is 0.14.0, cut from the old EtaCassiopeia/rift\nrepo. This repo's package.json still said 0.12.1, so releasing as-is would have moved\nnpm's `latest` tag *backward* and silently downgraded every consumer onto a different,\nolder codebase. Version both workspaces in \n[…]\nstall-time postinstall download.\n\nVerified: both tarballs stamped 0.15.0 and now carry LICENSE + README (npm publish\n--dry-run), 445/445 unit tests, lint/typecheck/docs:check/typecheck:examples green.",
"is_bot": false,
"headline": "chore(release): prepare the first achird-labs release as 0.15.0 (#92)",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-21T12:57:13Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "05e938853ba0403fe6f490026f7c1c0c20216c34",
"body": "…e affinity-LB pattern (#91)\n\nThe numeric/boolean header 400 (engine rift#754) is fixed in engine v0.15.0\n(rift#757), but stays documented as a version-scoped compat note because\nbinary resolution can still land on an older engine via a PATH install,\nbinaryPath/RIFT_BINARY_PATH, or a pinned version:\n[…]\ned.\n\nAdds the sanctioned multi-instance answer (independent nodes behind a\nsticky/affinity LB keyed on flow id) and drops promissory roadmap language\nabout engine-side distributed support.\n\nCloses #85",
"is_bot": false,
"headline": "docs(migration): version-scope the numeric-header gap and document th…",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-21T12:39:03Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "cb632d22a9af1d541ca1c4f8696b11b2dbc44d88",
"body": "Bumps the rift engine pin from 0.14.0 to 0.15.0 via scripts/bump.sh (the single source of truth for this repo's pin literals).\n\nCo-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>",
"is_bot": false,
"headline": "chore(deps): bump rift engine to 0.15.0 (#90)",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-21T12:08:25Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "176ccc9ff5f0fd9e0c74881b113da57241ef23d7",
"body": "The engine, the sibling SDKs and this repo all now live in the achird-labs\norg. Two of these were already broken rather than merely stale:\n\n- engine-bump.yml was half-migrated - it passed upstream_repo:\n achird-labs/rift while still calling the reusable dep-bump workflow from\n EtaCassiopeia/rift-j\n[…]\nnly via GitHub's redirect. Release-asset redirects are not\n something to depend on for a download path that verifies SHA-256.\n\nThe npm scope (@rift-vs) is unchanged, so nothing changes for consumers.",
"is_bot": false,
"headline": "chore: repoint at achird-labs (#89)",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-20T01:13:15Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "9a93306da20778dab1e6cfb1970a06a82ba83e2e",
"body": "…d) (#88)\n\nThe engine repo EtaCassiopeia/rift was transferred to achird-labs/rift; GitHub\nredirects the old name but the dep-bump release poll should target the canonical\nrepo directly rather than rely on API redirects. Also the target for the new\nimmediate-dispatch trigger added on the engine side.",
"is_bot": false,
"headline": "ci(engine-bump): point upstream_repo at achird-labs/rift (repo rename…",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-19T00:48:19Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "41bfd78ce77c9dc20ce04cf816af55fe9d63aaaa",
"body": "…usl build on Alpine (#84) (#86)\n\n* fix(spawn): version-probe PATH hits and select the musl build on Alpine\n\nTwo binary-resolution robustness gaps found while building a Mountebank->Rift\ncontainer drop-in test.\n\n1. `mb` is in the PATH probe list for migration ergonomics, but Homebrew's\n Mountebank\n[…]\nest hardcoded the PATH name `mb`, but on Windows the\nresolver probes `mb.exe`, so lookupPath never returned the hit and `probed` was\nempty. Match both names, mirroring the existing rift/rift.exe test.",
"is_bot": false,
"headline": "fix(spawn): version-probe PATH hits (no silent Mountebank) + select m…",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-18T12:42:24Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "e83f14845c12d9894c874cf1a2d3b65de9a498eb",
"body": "…dep-bump (#83)\n\nengine-bump.yml -> thin caller of EtaCassiopeia/rift-java/.github/workflows/dep-bump.yml@master; scripts/bump-engine.sh renamed scripts/bump.sh (+ --current). Bumps only DEFAULT_ENGINE_VERSION. Behavior-preserving. Part of rift-java#156.",
"is_bot": false,
"headline": "refactor(ci): convert engine-bump to a caller of the shared reusable …",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-18T02:48:27Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "a405b71001ca30561630c58714dba90864e24988",
"body": "The engine already reports numberOfRequests (journal-backed, counts even with\nrecordRequests off). This adds a regression guard asserting it is present and\nincrements (0 -> 2) on GET /imposters/:port and the list form, so a future\nchange that renames/drops/gates the field is caught before it reaches a\nconsumer's analytics as undefined.\n\nCloses #78",
"is_bot": false,
"headline": "test(compat): pin numberOfRequests on the imposter wire views (#82)",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-18T02:41:11Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "1c434a41180e99a73181ce3f4e26d622d2dcd322",
"body": "…ng (#81)\n\ncreate() previously accepted-and-ignored impostersRepository/redis, silently\nrunning an in-memory single-process server — the \"config silently dropped\"\nanti-pattern. It now throws UnsupportedCreateOptionError before spawning,\nnaming the option and the supported alternatives (datadir for persistence,\nper-imposter flowState() for distributed scenario state).\n\nCloses #76",
"is_bot": false,
"headline": "fix(compat): fail loud on impostersRepository/redis instead of ignori…",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-18T02:34:00Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "ecaa81b897fd19f228b5c72012ef342c05751e9e",
"body": "…#79)\n\nengine-bump.yml (daily poll of EtaCassiopeia/rift -> chore/engine-<ver> PR bumping DEFAULT_ENGINE_VERSION via scripts/bump-engine.sh) + auto-release.yml (workflow_run on green CI -> squash-merge + inline npm publish, package.json versioned in lockstep). First release human-gated; reuses NPM_TOKEN; exactly-once publish.",
"is_bot": false,
"headline": "feat(ci): auto-bump engine and cut an npm patch release on green CI (…",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-18T02:23:17Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "47ebb4de4f107f83d66bc303450092ad2fd06966",
"body": "…arity (#80)\n\ncreate({ datadir }) now maps to the engine's --datadir flag, matching\nmb.create({ datadir }) — imposters created via the admin API persist as\n{port}.json and reload on restart, bringing the compat path to parity with\nrift.spawn({ datadir }). Adds a migration.md \"Persistence & distributed state\"\nsection documenting the path for custom impostersRepository deployments.\n\nCloses #77",
"is_bot": false,
"headline": "feat(compat): expose datadir in create() for Mountebank persistence p…",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-18T02:22:33Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "f37e99e4a8e413b34e5ff0d0968ac7ebd4de810b",
"body": "…-assigns (avoids host port collisions) (#74)\n\nthe mb conformance fixtures pin port 4545; the replay driver bound it verbatim, so any other host process serving 4545 could answer the fetch with a confusing right-status/empty-body mismatch (root cause of a long-standing \"cold-run replay flake\"). repl\n[…]\ne separate DSL-coverage gate. Adds a koffi-free unit gate (port stripped before create) and a deterministic embedded-lane gate (squatter on an ephemeral port; replay must still hit the real imposter).",
"is_bot": false,
"headline": "test(conformance): drop the fixture port in replay so the engine auto…",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-18T00:09:41Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "957cfbfeda56f9b6d5956de526edd603ad857cab",
"body": "…epAlive for standalone servers (#73)\n\nworker was unref'd unconditionally, so a bare script's awaited call could be dropped when the loop drained (Node exit 13, unsettled top-level await). Now #call refs the worker on the 0->1 pending transition and unref happens when the map drains (including error\n[…]\nworker while the engine is open — the standalone Mountebank-style mock-server shape. Gates: 7 fake-worker unit tests + 3 real child-process integration tests in the required embedded lane. Closes #70.",
"is_bot": false,
"headline": "fix(embedded): hold the event loop during in-flight FFI calls; add ke…",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-17T23:51:52Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "75dc0f6345703c9ae8695fc8c8e147bc55a44854",
"body": "…m workspaces) (#71)\n\nConverts the repo to npm workspaces: packages/rift-core (@rift-vs/rift, unchanged publish name) + packages/rift-embedded (@rift-vs/rift-embedded, koffi as a REAL dependency), root is a private shell delegating build/test/lint/docs scripts; core builds first.\n\nCore reaches embed\n[…]\nish.yml stamps+publishes BOTH workspaces in lockstep; ci.yml cdylib cache keys on the embedded manifest; debug-lane patch paths updated. Docs (sdk-api §2/§8.2, READMEs, examples) updated.\n\nCloses #39.",
"is_bot": false,
"headline": "build(embedded): extract src/embedded into @rift-vs/rift-embedded (np…",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-17T23:22:23Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "9c023edb271e2ae5a37fd64d9c17c99576b73e88",
"body": "…te (#69)\n\nThe #53 segfault and subsequent #62/#63/#65 follow-ons are fixed. The\nembedded-conformance lane is green on ubuntu+macos (run 29617312113), so\nwe can drop the job-level continue-on-error flag and make it a required\nM8 gate.\n\nThe fetch-step's continue-on-error (cdylib-404 self-skip) is pre\n[…]\nd.\nThe embedded-conformance-windows experimental job and embedded-segfault-debug\nlane remain unchanged.\n\nUpdated .github/workflows/ci.yml and docs/design/sdk-api.md (removed\n#44 from open-follow-ups).",
"is_bot": false,
"headline": "test(embedded): make the embedded conformance lane the required M8 ga…",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-17T22:30:40Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "119f3ccfa8c5c412682a9e5865f5fb7c1ac6700e",
"body": "… documented signature (#68)\n\nRestores the §5.9 documented `StubBuilder | wire.Stub` signature that was\nregressed by #47. The `.stub()` method now accepts builder-or-raw Stub objects,\nmirrors how `create()`/`toWireStub` accept both forms, and fixes the\n`TypeError: s.build is not a function` error when injecting raw stubs.\n\nFixes: #65\nVerified: typecheck, eslint, full unit suite (480 tests pass, 3 new)",
"is_bot": false,
"headline": "fix(dsl): let imposter().stub() accept raw Stub objects, matching its…",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-17T22:15:11Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "bdcd4f0a4d55f3effc2295bc1bab4afccd25dceb",
"body": "…instead of failing on literal port 0 (#67)\n\nCloses #63",
"is_bot": false,
"headline": "test(embedded): omit port in smoke createImposter so it auto-assigns …",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-17T21:39:52Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "faa2da85f47a83ca8ece1c66b5b1b35a6b3f6e9c",
"body": "…ng works on Node 20/22 (#64)\n\nJest's vm context lacks dispose symbols on Node 20/22, which broke the embedded\nintegration suites once #53 stopped masking them. This adds a setup file to\npolyfill both Symbol.asyncDispose and Symbol.dispose before tests run.",
"is_bot": false,
"headline": "test(embedded): polyfill Symbol.asyncDispose for jest vm so await usi…",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-17T21:30:52Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "71cceef51bdf8d0314cc3df48a424f07e1a2d4ca",
"body": "…-1) (#53) (#61)\n\n`rift.embedded()` hard-crashed (SIGSEGV) on every platform the moment the FFI\nran, at init while decoding rift_build_info. Root cause: `koffi.decode(ptr,\n'string')` on a raw `char*` treats the argument as a pointer-TO-a-string\n(char**) and dereferences once too many — it reads the \n[…]\nst the released v0.12.0 cdylib: the `'string'` form\nSIGSEGVs; `('char', -1)` decodes rift_build_info and a rift_apply_config +\nrift_free cycle (x5) cleanly. koffi.d.ts gains the 3-arg decode overload.",
"is_bot": false,
"headline": "fix(embedded): decode FFI char* results with koffi.decode(ptr,'char',…",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-17T21:03:42Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "0f9e941d096d05be10b89896a5fb8c50b7c027fe",
"body": "The previous run's trace file came up empty even though the crash reproduces\nand worker_threads demonstrably inherit process.env under jest — so the\nfile-only channel wasn't the right signal. Make the diagnostic robust:\n\n- debug-trace.ts: traceFfi now also writes each label to stderr via\n writeSync\n[…]\non macOS cat the symbolicated .ips inline (it holds the caller the koffi\n trampoline hides) and read $x0 as a string.\n\nEnv-gated and inert in production; native-call.ts stays pure. #53 stays blocked.",
"is_bot": false,
"headline": "ci(embedded): robust FFI trace (stderr) + deeper core dump for #53 (#60)",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-17T20:34:23Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "1da164837b0265bf713de21351a103aa5be280ca",
"body": "…nly) (#59)\n\nThe previous run showed the crash lands right as the first embedded engine\ninits — before any call and before rift_build_info/rift_start — so the\nper-call/no-decode traces stayed empty and couldn't name it. Extend the\nenv-gated trace to the koffi binding phase so the trace file's last l\n[…]\nthe crash precedes the first traced point — this pins\nwhether it's koffi.load, a specific symbol bind, or a later call. Env-gated and\ninert in production; native-call.ts stays pure. #53 stays blocked.",
"is_bot": false,
"headline": "ci(embedded): trace koffi bind phase to pin the #53 segfault (debug-o…",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-17T20:13:06Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "ba3276a4b298b2757250bc2d800fb6d57d9012f8",
"body": "…lt debug lane (#53) (#58)\n\nThe first debug-lane run localized the crash to `strlen` on a worker thread at the\nkoffi boundary, and refuted H2 (no-free crashes identically). Extend the lane to\npin the exact symbol and isolate the decode path:\n\n- Per-symbol trace (worker.ts): when RIFT_FFI_DEBUG_TRACE\n[…]\nult-decode\n path; if it persists -> argument marshalling.\n\nBoth hooks are env-gated and inert in production (native-call.ts stays pure).\nTrace file added to the uploaded artifacts. #53 stays blocked.",
"is_bot": false,
"headline": "ci(embedded): add no-decode mode + per-symbol trace to the FFI segfau…",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-17T19:51:55Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "df6b9891940d33ca83aa93569acebf1436461c1d",
"body": "…re (#53) (#57)\n\nThe embedded-conformance lanes only report \"Segmentation fault\" with no frame,\nwhich is not enough to root-cause #53. Add a debug-only job that reproduces the\ncrash under core-dump capture and extracts a native backtrace.\n\n- Opt-in only: runs on workflow_dispatch or a `[ffi-debug]` \n[…]\n test log, node report, macOS .ips crash report, and gzipped core as artifacts.\n\nDoes not change the shipped code or any gating lane; #53 stays blocked until a\ncaptured backtrace identifies the fault.",
"is_bot": false,
"headline": "ci(embedded): add opt-in FFI segfault debug lane with core-dump captu…",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-17T19:24:32Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "93c3ea8e69bb7f12650622a873fbc10fe4430d7a",
"body": "…s (#56)\n\nAdded exported type alias AnyStubBuilder = StubBuilder<Record<string, string>>\nand widened every stub-consuming position to it (imposter().stub(), scenario().when(),\nRequestMatch, ImposterHandle/SpaceHandle addStub/replaceStubs/updateStub, toWireStub),\nenabling param-typed builders from on\n[…]\nand\nremoved the #47 follow-ups row. Added test/unit/dsl-stub-compose.test.ts (runtime smoke).\n\nVerified: typecheck, typecheck:examples, docs:check, eslint (0 errors), unit suite (477 pass).\n\nFixes #47",
"is_bot": false,
"headline": "fix(dsl): let param-typed StubBuilder compose into consuming position…",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-17T18:37:24Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "a2e27646a3f39e02ed6a4022d78d41847072dfe3",
"body": "The committed node_modules symlink was a mode-120000 entry pointing to an\nabsolute local path, causing ELOOP errors and dangling references across\ndifferent environments. Removed via git rm.\n\nUpdated .gitignore from 'node_modules/' to 'node_modules' to ensure that\nany node_modules symlink, directory, or file is properly ignored, allowing\nnpm ci to function without git status conflicts.\n\nVerified: git ls-files node_modules is empty; npm ci leaves clean status.\n\nCloses #48",
"is_bot": false,
"headline": "fix(repo): remove committed node_modules symlink and ignore it (#55)",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-17T18:04:08Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "19a968cce3634908c2ce3c264169b6608e939636",
"body": "…lure pending #53 (#54)\n\njest.embedded.config.js remaps src imports to the built dist so worker_threads resolves the real dist/embedded/worker.js; npm run test:embedded; both embedded CI jobs use it. First genuine FFI execution exposed the cross-platform segfault #53, so the lane stays continue-on-error with the required-gate flip documented for when #53 lands. Refs #44, #53.",
"is_bot": false,
"headline": "test(embedded): conformance lane runs against built dist, allowed-fai…",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-17T03:24:08Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "3d9cdf4344df09e4b3883fe4918c5f1c56ff42b6",
"body": "…#52)\n\nThree conformance fixtures tag stubs with a bare scenarioName (grouping\nonly, no required/new state), which the scenario() FSM builder cannot\nexpress without emitting transitions. Add StubBuilder.inScenario(name)\nfollowing the id()/inSpace() slot pattern, reconstruct\nauthentication-api, featu\n[…]\n raw({ stubs }) workaround), and shrink\nfromJsonOnly to just latency-testing.json (wait:{inject}, fromJson-only\nby #23 design). The canonical API reference's #36 gap notes flip to\nshipped.\n\nCloses #36",
"is_bot": false,
"headline": "feat(dsl): inScenario() — bare scenarioName grouping without an FSM (…",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-17T02:59:04Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "83e7e11e60947c281399a3af2ac1c9189c2960da",
"body": "…JSON bodies (#51)\n\nUnknown request-field names in a predicate (exists: { pathh } or an\noperator FieldMatch) threw nothing and resolved as a silent non-match —\nnow they throw UnsupportedPredicateError naming the field, mirroring how\noperator typos already fail. A jsonpath or object-equals predicate \n[…]\nnote (verdict unchanged,\nfail-closed). Malformed matches/except patterns surfaced as raw\nSyntaxError — regex compilation now rethrows as InvalidDefinition with\nthe original error as cause.\n\nCloses #33",
"is_bot": false,
"headline": "fix(verify): fail loudly on field typos and bad regexes, explain non-…",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-17T02:44:54Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "edf6d2805e0310bc21140bdb910cf92eb0a87c11",
"body": "… host (#50)\n\nThe child's 'error' listener threw inside the emitter, so a spawn failure\n(bad binary path, ENOENT, EACCES) escaped the startup try/catch as an\nuncaught exception and killed the host process. Fold a spawnErrorPromise\ninto the startup race so it rejects catchably, reject promptly on a c\n[…]\nstart so post-startup child errors reach\nserver.on('error') consumers. Spawn and binary resolution are injectable\n(CreateDeps) so the failure paths are unit-testable without a real binary.\n\nCloses #28",
"is_bot": false,
"headline": "fix(compat): reject create() on spawn failure instead of crashing the…",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-17T02:32:55Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "d9de2852d5dd673f943875a63dd92e2cf9f67917",
"body": "…#49)\n\nThe 2026-07-09 design doc's every slice has shipped, so re-frame it as the\nliving reference: describe the shipped single-package layout (koffi\noptionalDependency, ./embedded subpath; split deferred to #39), correct the\nC-ABI count to 26 symbols, document requests() (#26), annotate the honest\n\n[…]\nnto a delivered\nledger with per-issue PRs plus open follow-ups. Wire the doc's runnable\nsnippets into docs:check by scanning docs/design/*.md and backing §0/§9\nwith embed-checked examples.\n\nCloses #20",
"is_bot": false,
"headline": "docs(design): reconcile sdk-api.md into the canonical API reference (…",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-17T02:08:11Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "195a0a7d18e8bd3be87a7c777c5ca9f5e2c9abcb",
"body": "…n notes (#46)\n\nRestructures the README (hero typed-DSL quick-start + verify, per-transport quick\nstarts for embedded/spawn/connect/compat, feature tour, corrected env-var table)\nand adds docs/migration.md (a complete Mountebank-JSON ↔ typed-DSL side-by-side\ncovering every operator/behavior/fault/re\n[…]\nmbed marker\nand enforced by scripts/check-docs-embeds.mjs (new docs CI job runs it +\ntypecheck:examples), so snippets can't rot. The rift-side doc redirect is tracked\nupstream as rift#473.\n\nCloses #14",
"is_bot": false,
"headline": "docs: quick starts + Mountebank migration guide + monorepo deprecatio…",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-17T00:38:52Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "3319dc57d44a2d5e71da7243179f1367acadcd8b",
"body": "…eardown, assertReceived (#45)\n\nAdds test-framework glue over the client API: @rift-vs/rift/testkit/vitest\n(riftTest/createRiftTest fixtures — a worker-scoped engine + per-test imposter\nauto-teardown) and @rift-vs/rift/testkit/jest (setupRift beforeAll/afterEach/\nafterAll helpers). Both re-export as\n[…]\nor via transport. vitest stays an optional\npeer, imported only inside the vitest subpath. Adds a 15-test fake-engine gate\n(with a real jest-lifecycle proof) and a README isolation section.\n\nCloses #12",
"is_bot": false,
"headline": "feat(testkit): Vitest fixtures + Jest helpers — shared engine, auto-t…",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-17T00:14:14Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "acde544ca782f80942dd8fcea5b17139a8dd3969",
"body": "…l windows lane (#43)\n\n* test(conformance): corpus over embedded transport + experimental windows lane\n\nExtends the #7 conformance harness to the embedded transport (the driver is\nalready transport-agnostic) and adds CI topology: an embedded-conformance job\n(ubuntu/macos, cdylib via rift-fetch --lib\n[…]\ned dist; the harness needs to run against the build. Mark the\nlinux/darwin lanes continue-on-error (tracking) like the experimental windows lane\nuntil that follow-up lands, so they never block merges.",
"is_bot": false,
"headline": "test(conformance): corpus green over embedded transport + experimenta…",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-16T23:48:44Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "f118a607b3430aa2a2963e88525a6cf39efa5612",
"body": "…e trust helpers (#42)\n\nAdds engine.intercept(options?) → InterceptHandle: serve/forward/redirectTo\nrules, addRule/rules/clearRules, caPem/caFile, exportTruststore, and env() for\nNode trust. A backend seam (InterceptBackend) is adapted per transport —\nembedded over FFI, remote+spawn over the HTTP ad\n[…]\nnamically imported). Adds wire.InterceptRule, RemoteClient intercept routes, the\nspawn --intercept-port flag, a 37-test fake-backend gate, and a self-skipping\nreal-engine integration lane.\n\nCloses #11",
"is_bot": false,
"headline": "feat(intercept): TLS-MITM surface — serve/forward/redirectTo, CA, Nod…",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-16T23:19:32Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "e4914dc1c5a0e6a5cdd5ad43129146946c63279d",
"body": "Wires rift.embedded(options) to return the same RiftEngine as connect/spawn,\nbacked by the embedded worker binding (#8) with the cdylib resolved via #9.\nRuns a version + feature preflight (versionCheck fail/warn/off, requireFeatures)\nand drives an FFI-first EmbeddedAdmin: imposters/stubs/recorded/fl\n[…]\n per process are independent. The embedded module is\ndynamically imported so core stays zero-dep. Adds a 24-test fake-NativeEngine gate\n+ a RIFT_FFI_LIB-gated quick-start integration test.\n\nCloses #10",
"is_bot": false,
"headline": "feat(embedded): rift.embedded() wiring + engine-version preflight (#41)",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-16T22:47:51Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "bba9e0ea1a2cdb0fbf3cec59a3cecc5d0a21e173",
"body": "… discipline (#40)\n\n* feat(embedded): koffi binding for C-ABI v2 — worker-thread last-error discipline\n\nAdds src/embedded (exposed via the ./embedded subpath): a koffi binding for the\nlibrift_ffi C-ABI v2 (26 symbols) run inside a dedicated worker_threads worker so\nevery call is paired with a same-t\n[…]\nync package-lock.json with koffi optionalDependency\n\nCI npm ci failed 'Missing: koffi from lock file' — regenerate the lock so it\nmatches the koffi optionalDependency added for the embedded transport.",
"is_bot": false,
"headline": "feat(embedded): koffi binding for C-ABI v2 — worker-thread last-error…",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-16T22:18:27Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "9e92ea79d6e88487dadcd1ca1531d55b322bfbb3",
"body": "…a cache, manifest download (#38)\n\nAdds src/natives: resolveCdylib (librift_ffi) mirroring the engine-binary\nresolver — RIFT_FFI_LIB/libPath override → sidecar-validated cache → manifest\ndownload with MANDATORY sha256 (no skip flag) → air-gap error with a\ncopy-pasteable manual-install path pointing \n[…]\npped (resolve.ts untouched). Extends bin/rift-fetch with --bin/--lib/\n--version/--classifier. Adds a 26-test injected-IO gate + a network-gated\nintegration test, and a README env-var table.\n\nCloses #9",
"is_bot": false,
"headline": "build(natives): cdylib resolution — RIFT_FFI_LIB override, version+sh…",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-16T21:44:32Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "27d458bcf7fba6de0f6d6538858019deeaaeae64",
"body": "Adds test/conformance/: a fixture loader (local mb fixtures + the rift#460\nsdk-conformance tarball with sha/air-gap discipline), a replayFixture driver\n(create via fromJson, replay interactions over fetch, strict status/headers/body\nassertions), and a pure DSL-expressibility gate. The gate accounts \n[…]\nonstruction, keeping the gate honest. Failure modes (missing\ncoverage names the fixture; wire mismatch prints a diff) are tested. The replay\nover spawn is binary-gated and self-skips in CI.\n\nCloses #7",
"is_bot": false,
"headline": "test(conformance): corpus replay harness + DSL expressibility gate (#37)",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-16T21:17:49Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "57d0586cee8723640584ecb105aff4b31afb44a2",
"body": "…rator (#35)\n\nAdds ImposterHandle.requests(opts?) → AsyncIterableIterator<RecordedRequest>:\na polling iterator over an imposter's recorded requests with a monotonic\ncursor (no duplicates), cursor reset on clearRecorded(), an optional client-side\nmatch filter (reusing the verify evaluator), and clean\n[…]\nd) completes the iterator.\nSSE upgrade (rift#461) is a future transparent swap; polling ships now. Adds a\ntest:leaks npm script (--detectOpenHandles) and an 8-case gate + integration test.\n\nCloses #26",
"is_bot": false,
"headline": "feat(core): recorded-request async iteration — polling requests() ite…",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-16T20:53:41Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "b9bac15b1dfeb7a33c38fef6395462c88d4f3eb4",
"body": "…times) with readable diffs (#34)\n\nAdds the verification API: typed RecordedRequest, handle.recorded/clearRecorded/\nverify(match, count) with WireMock-style near-miss diffs, count matchers\n(times/atLeast/atMost/between/never, exported from root), a zero-dep client-side\npredicate evaluator mirroring \n[…]\nUnsupported and operator-less\npredicates throw UnsupportedPredicateError rather than matching silently.\nSpaceHandle scopes by flow id. Adds a 56-case gate + a binary-gated integration test.\n\nCloses #6",
"is_bot": false,
"headline": "feat(core): verification API — typed RecordedRequest + verify(match, …",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-16T20:32:31Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "7360da1783ddaf8ba1d82cb63a2550059209dff0",
"body": "…ward, _rift config, scenario fixes (#32)\n\nCompletes the imposter builder (https/mTLS, defaultForward, strictBehaviors,\nserviceName/Info, and the imposter-level _rift config: flowState, metrics,\nscriptEngine, registerScript — all merging across calls), adds stub-level\nid/inSpace/routePattern, and fi\n[…]\nebuild rewrite) and respond() is variadic.\ndefaultResponse throws InvalidDefinition (not a plain Error) on a non-is or\nempty response. Adds a 22-test gate (test/unit/dsl-imposter.test.ts).\n\nCloses #24",
"is_bot": false,
"headline": "feat(dsl): imposter/stub/scenario completion — HTTPS/mTLS, defaultFor…",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-16T20:01:29Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "e4d0f5eb77d746fe7062e304ab57a4f093f93cc8",
"body": "…ipt, full proxy (#31)\n\nCompletes the response side of the fluent DSL: full _behaviors (copy/lookup/\ndecorate/shellTransform/wait variants), binary body + multi-value headers +\ntemplated, typed faults (Fault + withFault merge), a Script builder, and a full\nproxy ProxyBuilder. Fixes the silent-drop b\n[…]\n makes invalid response shapes fail loudly with\nInvalidDefinition instead of dropping data. willReturn now appends (response\ncycling). Adds a 34-test gate (test/unit/dsl-response.test.ts).\n\nCloses #23",
"is_bot": false,
"headline": "feat(dsl): response completion — behaviors, binary, typed faults, Scr…",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-16T19:46:40Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "877261d1b11de874388b312ce38ccc714eb3142c",
"body": "Build expected paths with path.join and the platform binary suffix so the\nextractedBinaryCandidates test passes on Windows CI (path.sep + rift.exe),\nnot just POSIX. Fixes the master CI regression from f3944cf.",
"is_bot": false,
"headline": "test(spawn): make extracted-candidate assertions platform-agnostic",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-16T19:12:42Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "f3944cf48dfbc182ee68cca40caa4aad210d8442",
"body": "- Probe real release-archive layout (rift-<version>-<target>/bin/rift)\n so engine downloads succeed; keep legacy locations as fallbacks.\n- Default host to 127.0.0.1 (IP literal) so spawn() no longer aborts on\n the engine's \"invalid socket address syntax\".\n- Bump DEFAULT_ENGINE_VERSION to v0.14.0; minEngineVersion stays 0.12.0.\n- Name the wire.RecordedRequest _mode?: 'binary' marker (engine >= 0.13.6).",
"is_bot": false,
"headline": "fix(spawn): correct engine download layout and default bind host",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-16T19:07:12Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "8a0570c4098f9e8a7e631ec2e052bb5dc04178a7",
"body": "- Immutable Matcher value objects with equals/deepEquals/contains/startsWith/endsWith/matches/exists/notExists predicates\n- caseSensitive/keyCaseSensitive/except/jsonpath/xpath modifier chains\n- req.{method,path,body,header,query} binders replacing field-first helpers\n- StubBuilder withMethod/withPa\n[…]\nex path predicate\n- Compile-time PathParams<P> type with path parameter extraction\n- and/or/not logical operators for predicate composition\n- injectPredicate for custom predicate functions\n\nCloses #22",
"is_bot": false,
"headline": "feat(dsl): matcher grammar — full predicate coverage (#30)",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-10T03:00:23Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "20e750e4a47aad1e454ab9ab9543b6007aaaf64f",
"body": "…lient API (#29)\n\n* feat(core): RiftEngine facade + ImposterHandle — transport-agnostic client API\n\n- new src/engine.ts with AdminApi interface + Engine facade + ImposterHandle/SpaceHandle/FlowStateHandle implemented once over AdminApi\n- RemoteClient now implements the full admin route table (stub s\n[…]\nbility.\nAlso, toWireImposter now defaults protocol to 'http' when unset, so spawn/remote transports\ncan successfully create imposters without explicit protocol (fixes integration test on real engine).",
"is_bot": false,
"headline": "feat(core): RiftEngine facade + ImposterHandle — transport-agnostic c…",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-10T02:40:45Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "62d39f6eaa946fb2eb826ebd111fd3e17e9edea5",
"body": "…emoval, errors module, exports map, ESM-only (#27)\n\n* chore(core): export hygiene + legacy retirement\n\n- canonical src/errors.ts (full RiftError hierarchy)\n- root exports stripped of legacy weak types (wire model via `wire` namespace)\n- axios removed → zero runtime deps (fetch-based compat poll)\n- \n[…]\nution\n\nThe exports-build test failed on Windows runners with ENOENT when trying\nto spawn 'npm' directly. Using execSync with shell: true allows the\nsystem shell to resolve npm.cmd on Windows properly.",
"is_bot": false,
"headline": "chore(core): export hygiene + legacy retirement — root types, axios r…",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-10T02:00:28Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "850757108d6cffbc9b15060f908d653601232c29",
"body": "…-node#20\n\nSnapshot of the approved API design (engine facade, matcher DSL, verification,\nembedded/intercept/testkit) so the repo carries the reference the M7/M8 issues\nimplement against.",
"is_bot": false,
"headline": "docs(design): complete SDK API surface — canonical reference for rift…",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-10T01:21:47Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "608439c01003bba007b950f78f35f72f586fd399",
"body": "… (#19)\n\n* feat(core): spawn transport rework + Mountebank-compat create() layer\n\nOn-demand binary resolver (RIFT_BINARY_PATH -> PATH -> binaries/ -> version cache -> download) with SHA-256 sidecar verification, mirror (RIFT_DOWNLOAD_URL/RIFT_MIRROR_URL) and air-gap (RIFT_OFFLINE/RIFT_SKIP_BINARY_DO\n[…]\nupPath mock only matched 'rift', but on Windows the code\ntries 'rift.exe', 'rift-http-proxy.exe', etc. Updated the mock to match\nboth Unix and Windows binary names so the test passes on all platforms.",
"is_bot": false,
"headline": "feat(core): spawn transport rework + Mountebank-compat create() layer…",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-10T00:31:48Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "c317e78d436548c8315a31658720ec92140c305b",
"body": "…connect(url) (#18)\n\nZero-dep fetch-based admin API client (rift.connect(url)) covering imposter, scenario-state, space, flow-state, and reload operations, with a typed RiftError hierarchy (InvalidDefinition/EngineUnavailable/CommunicationError/ImposterNotFound/EngineError) mapped from HTTP status and network failure. Supports await using via Symbol.asyncDispose plus close(). Unit-tested via mocked fetch; integration test self-skips without a rift binary.\n\nCloses #4",
"is_bot": false,
"headline": "feat(core): remote transport — admin HTTP client, typed errors, rift.…",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-10T00:03:40Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "808207a2544e36f59c61f78f2374726bb9875a26",
"body": "…cript/proxy builders (#17)\n\nChainable builders that produce the typed wire model: imposter()/onGet()/onPost()/on()/onAny()/stub(), response factories (ok/okJson/created/status/json/text/notFound/noContent), predicate helpers (equals/deepEquals/matches/contains/startsWith/endsWith/exists/and/or/not)\n[…]\nthe exact wire imposter; basic-api and error-testing fixtures are rebuilt byte-exact, the remaining fixtures documented as fromJson-only with accurate capability reasons. Zero runtime deps.\n\nCloses #3",
"is_bot": false,
"headline": "feat(core): fluent DSL — imposter/stub grammar, scenario FSM, fault/s…",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-09T23:43:22Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "f9e286d79778115a1d4319420e761bdfe040f98f",
"body": "… fromJson escape hatch (#16)\n\nAdds a preservation-model wire layer: typed interfaces for the full Mountebank imposter/stub/predicate/response/behaviors grammar plus _rift extensions (exact camelCase wire keys), a fromJson escape hatch that validates structure and returns it verbatim (explicit ports\n[…]\n-safe serialization. Round-trips the rift example fixtures with value identity. Exposed under the wire.* namespace to avoid collisions with the legacy create()-era types. Zero runtime deps.\n\nCloses #2",
"is_bot": false,
"headline": "feat(core): typed wire model — Mountebank grammar + _rift extensions,…",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-09T23:20:32Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "f64f114b7b495ca1eedf358072201c583fa774d5",
"body": "…matrix, npm publishing (#15)\n\nHistory-preserving extraction of rift/packages/rift-node into this standalone repository.\n\nDelivers TypeScript/ESM build system, Node 20/22/24 x Linux/Darwin/Windows CI matrix, snapshot-based npm publish pipeline (dry-run on every push, snapshot dist-tag on master, stable publish gated on release), version target 0.12.1 with Node 20+ minEngineVersion, and CONTRIBUTING conventions doc.\n\nCloses #1",
"is_bot": false,
"headline": "build: repo bootstrap — extract packages/rift-node, TS/ESM build, CI …",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-09T23:01:15Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "f4dbd6e041ebd0d18fa2b5c4e47e710346e7ae50",
"body": "History-preserving extraction of rift/packages/rift-node into this repo. Adds Node 20/22/24 x linux/darwin/windows CI, a snapshot-based npm publish pipeline (dry-run on every push, snapshot dist-tag on master, stable publish gated on release), version target 0.12.1 with minEngineVersion, and a CONTRIBUTING conventions doc.\n\nCloses #1",
"is_bot": false,
"headline": "build: repo bootstrap — TS/ESM build, CI matrix, npm publish pipeline",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-09T22:58:01Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "966718a18c773d779e090a2848c674c110dcfc84",
"body": "# Conflicts:\n#\tREADME.md",
"is_bot": false,
"headline": "Merge branch 'rift-node-extract' into build/rift-1-repo-bootstrap",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-09T22:40:50Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "d6560cfffeee4593c5d5ba28856f315a409aaf08",
"body": null,
"is_bot": false,
"headline": "docs: bootstrap README — SDK scope, planned API, artifacts",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-07-09T21:36:41Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "0283c1a2a90669e82675b17d38ac4b05e6c91adb",
"body": "* fix: use peek_response in get_rift_script_response to avoid double cycling\n\nThe get_rift_script_response function was incorrectly calling\nget_next_response() which advances the cycler. This caused response\ncycling to be off-by-one: the first request would return \"Response 2\"\ninstead of \"Response 1\n[…]\ns to use the sibling format that is compatible\nwith both Mountebank and Rift:\n\n {\"jsonpath\": {\"selector\": \"$.name\"}, \"equals\": {\"body\": \"value\"}}\n\n* test: fix GET / test to check for _links structure",
"is_bot": false,
"headline": "docs: add practical examples and improve quickstart guide (#59) (#60)",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2026-01-02T19:32:41Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "1afcbbc61999de5a4b2c1ebaeae1f1eb41034e32",
"body": "Replace dual configuration approach (Mountebank JSON + native YAML) with\na single Mountebank-compatible JSON format that supports _rift namespace\nfor advanced features.\n\nThe _rift namespace allows advanced features (flow state, fault\ninjection,\nscripting) while maintaining full Mountebank compatibility.",
"is_bot": false,
"headline": "unify configuration to Mountebank format with _rift extensions",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2025-11-30T22:47:49Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "5df9ec19d23964399f5b57fd78240519dcf5c5c3",
"body": null,
"is_bot": false,
"headline": "rename npm package to @rift-vs/rift",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2025-11-28T15:43:02Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "41751748631d3d6827d1296b02b2b6cc11db63cb",
"body": null,
"is_bot": false,
"headline": "add npm package with TypeScript bindings",
"author_name": "Mohsen Zainalpour",
"author_login": "EtaCassiopeia",
"committed_at": "2025-11-15T10:08:26Z",
"body_truncated": false,
"is_coding_agent": false
}
],
"releases_count": 1,
"commits_last_year": 61,
"latest_release_at": "2026-07-21T13:13:02Z",
"latest_release_tag": "v0.15.0",
"releases_from_tags": false,
"days_since_last_push": 6,
"active_weeks_last_year": 5,
"days_since_latest_release": 8,
"mean_days_between_releases": null
},
"community": {
"has_readme": true,
"has_license": true,
"has_description": true,
"has_contributing": true,
"health_percentage": 50,
"has_issue_template": false,
"has_code_of_conduct": false,
"has_pull_request_template": false
},
"ecosystem": {
"packages": [
{
"name": "@rift-vs/rift",
"exists": true,
"license": "MIT",
"keywords": [
"mountebank",
"mock",
"stub",
"test",
"double",
"chaos",
"engineering",
"rift",
"service-virtualization",
"api-mocking"
],
"ecosystem": "npm",
"matches_repo": true,
"registry_url": "https://www.npmjs.com/package/@rift-vs/rift",
"is_deprecated": false,
"latest_version": "0.15.0",
"repository_url": "https://github.com/achird-labs/rift-node",
"versions_count": 42,
"total_downloads": null,
"dependents_count": null,
"deprecation_note": null,
"maintainers_count": 1,
"monthly_downloads": 4813,
"first_published_at": "2025-11-29T04:17:03.102000Z",
"latest_published_at": "2026-07-21T13:13:26.876000Z",
"latest_version_yanked": null,
"days_since_latest_publish": 8
},
{
"name": "@rift-vs/rift-embedded",
"exists": true,
"license": "MIT",
"keywords": [],
"ecosystem": "npm",
"matches_repo": true,
"registry_url": "https://www.npmjs.com/package/@rift-vs/rift-embedded",
"is_deprecated": false,
"latest_version": "0.15.0",
"repository_url": "https://github.com/achird-labs/rift-node",
"versions_count": 6,
"total_downloads": null,
"dependents_count": null,
"deprecation_note": null,
"maintainers_count": 1,
"monthly_downloads": 802,
"first_published_at": "2026-07-19T00:49:39.030000Z",
"latest_published_at": "2026-07-21T13:13:30.526000Z",
"latest_version_yanked": null,
"days_since_latest_publish": 8
}
]
},
"popularity": {
"forks": 0,
"stars": 0,
"watchers": 0,
"fork_history": {
"days": [],
"complete": true,
"collected": 0,
"total_forks": 0
},
"star_history": {
"days": [],
"complete": true,
"collected": 0,
"total_stars": 0,
"collected_at": null
},
"open_issues_and_prs": 3
},
"ai_readiness": {
"has_nix": false,
"example_dirs": [
"examples"
],
"has_llms_txt": false,
"has_dockerfile": false,
"has_mcp_signal": false,
"bootstrap_files": [],
"api_schema_files": [],
"has_devcontainer": false,
"typecheck_configs": [
"packages/rift-core/tsconfig.json",
"packages/rift-embedded/tsconfig.json"
],
"toolchain_manifests": [],
"largest_source_bytes": 42365,
"source_files_sampled": 117,
"oversized_source_files": 0,
"agent_instruction_files": [],
"agent_instruction_max_bytes": null
},
"dependencies": {
"manifests": [
"package.json"
],
"advisories": {
"error": null,
"scope": null,
"source": null,
"findings": [],
"collected": false,
"malicious": [],
"truncated": false,
"by_severity": {},
"advisory_count": 0,
"affected_count": 0,
"assessed_count": 0,
"malicious_count": 0,
"assessed_package": null,
"unassessed_count": 0,
"direct_affected_count": 0
},
"ecosystems": [
"npm"
],
"dependencies": [
{
"name": "koffi",
"manifest": "packages/rift-embedded/package.json",
"ecosystem": "npm",
"version_constraint": "^2.9.0"
}
],
"all_dependencies": {
"error": "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository",
"source": null,
"packages": [],
"collected": false,
"truncated": false,
"total_count": null,
"direct_count": null,
"indirect_count": null
}
},
"maintainership": {
"issues": {
"open_prs": 1,
"merged_prs": 51,
"open_issues": 2,
"closed_ratio": 0.953,
"closed_issues": 41,
"closed_unmerged_prs": 1
},
"bus_factor": 1,
"bot_contributors": 0,
"top_contributors": [
{
"type": "User",
"login": "EtaCassiopeia",
"commits": 61,
"avatar_url": "https://avatars.githubusercontent.com/u/209719?v=4"
}
],
"contributors_sampled": 1,
"top_contributor_share": 1
},
"quality_signals": {
"has_ci": true,
"has_tests": true,
"ci_workflows": [
"auto-release.yml",
"ci.yml",
"docs.yml",
"engine-bump.yml",
"publish.yml"
],
"has_docs_dir": true,
"linter_configs": [
".eslintrc.cjs"
],
"has_editorconfig": false,
"has_linter_config": true,
"has_precommit_config": false
},
"security_signals": {
"lockfiles": [
"package-lock.json"
],
"scorecard": {
"checks": [
{
"name": "Binary-Artifacts",
"score": 10,
"reason": "no binaries found in the repo",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#binary-artifacts"
},
{
"name": "Branch-Protection",
"score": 0,
"reason": "branch protection not enabled on development/release branches",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
},
{
"name": "CI-Tests",
"score": 10,
"reason": "30 out of 30 merged PRs checked by a CI test -- score normalized to 10",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#ci-tests"
},
{
"name": "CII-Best-Practices",
"score": 0,
"reason": "no effort to earn an OpenSSF best practices badge detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#cii-best-practices"
},
{
"name": "Code-Review",
"score": 0,
"reason": "Found 1/30 approved changesets -- score normalized to 0",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
},
{
"name": "Contributors",
"score": 0,
"reason": "project has 0 contributing companies or organizations -- score normalized to 0",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
},
{
"name": "Dangerous-Workflow",
"score": 10,
"reason": "no dangerous workflow patterns detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dangerous-workflow"
},
{
"name": "Dependency-Update-Tool",
"score": 0,
"reason": "no update tool detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dependency-update-tool"
},
{
"name": "Fuzzing",
"score": 0,
"reason": "project is not fuzzed",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#fuzzing"
},
{
"name": "License",
"score": 10,
"reason": "license file detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
},
{
"name": "Maintained",
"score": 0,
"reason": "project was created within the last 90 days. Please review its contents carefully",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#maintained"
},
{
"name": "Packaging",
"score": 10,
"reason": "packaging workflow detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
},
{
"name": "Pinned-Dependencies",
"score": 5,
"reason": "dependency not pinned by hash detected -- score normalized to 5",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
},
{
"name": "SAST",
"score": 0,
"reason": "SAST tool is not run on all commits -- score normalized to 0",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
},
{
"name": "Security-Policy",
"score": 0,
"reason": "security policy file not detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy"
},
{
"name": "Signed-Releases",
"score": null,
"reason": "no releases found",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#signed-releases"
},
{
"name": "Token-Permissions",
"score": 0,
"reason": "detected GitHub workflow tokens with excessive permissions",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
},
{
"name": "Vulnerabilities",
"score": 0,
"reason": "22 existing vulnerabilities detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
}
],
"commit": "38680683f937f89e3dd6b23f4161e9f46cd9a756",
"ran_at": "2026-07-29T23:00:09Z",
"aggregate_score": 3.1,
"scorecard_version": "v5.5.0"
},
"has_codeql_workflow": false,
"has_security_policy": false,
"has_dependabot_config": false
},
"contribution_flow": {
"collected": true,
"ci_last_run_at": "2026-07-29T08:31:07Z",
"oldest_open_prs": [
{
"number": 95,
"created_at": "2026-07-22T23:34:17Z",
"last_comment_at": null,
"last_comment_author": null
}
],
"last_merged_pr_at": "2026-07-21T13:30:10Z",
"ci_last_conclusion": "SUCCESS",
"oldest_open_issues": [
{
"number": 94,
"created_at": "2026-07-21T16:31:53Z",
"last_comment_at": null,
"last_comment_author": null
},
{
"number": 96,
"created_at": "2026-07-26T22:09:03Z",
"last_comment_at": null,
"last_comment_author": null
}
]
}
},
"config": {
"disabled_metrics": [],
"disabled_categories": [],
"disabled_components": {}
},
"source": {
"url": "https://github.com/achird-labs/rift-node",
"host": "github.com",
"name": "rift-node",
"owner": "achird-labs"
},
"metrics": {
"overall": {
"key": "overall",
"band": "moderate",
"name": "Overall health",
"note": null,
"notes": [],
"value": 57,
"inputs": {
"security": 31,
"vitality": 67,
"community": 40,
"governance": 53,
"engineering": 86
},
"components": []
},
"categories": [
{
"key": "vitality",
"band": "moderate",
"name": "Vitality",
"value": 67,
"weight": 0.22,
"metrics": [
{
"key": "development_activity",
"band": "moderate",
"name": "Development activity",
"note": null,
"notes": [],
"value": 56,
"inputs": {
"commits_last_year": 61,
"human_commit_share": 1,
"days_since_last_push": 6,
"active_weeks_last_year": 5
},
"components": [
{
"key": "push_recency",
"name": "Push recency",
"detail": "last push 6 days ago",
"points": 36,
"status": "met",
"details": [
{
"code": "push_recency",
"params": {
"days": 6
}
}
],
"max_points": 36
},
{
"key": "commit_cadence",
"name": "Commit cadence",
"detail": "5/52 weeks with commits",
"points": 3.5,
"status": "partial",
"details": [
{
"code": "commit_cadence_weeks",
"params": {
"weeks": 5
}
}
],
"max_points": 36
},
{
"key": "commit_volume",
"name": "Commit volume",
"detail": "61 commits in the last year",
"points": 16.1,
"status": "partial",
"details": [
{
"code": "commits_last_year",
"params": {
"count": 61
}
}
],
"max_points": 18
},
{
"key": "openssf_scorecard_maintained",
"name": "OpenSSF Scorecard: Maintained",
"detail": "project was created within the last 90 days. Please review its contents carefully",
"points": 0,
"status": "missed",
"details": [],
"max_points": 10
}
]
},
{
"key": "release_discipline",
"band": "good",
"name": "Release discipline",
"note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: Signed-Releases. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"openssf_scorecard_signed_releases"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 84,
"inputs": {
"releases_count": 1,
"latest_release_tag": "v0.15.0",
"releases_from_tags": false,
"days_since_latest_release": 8,
"mean_days_between_releases": null
},
"components": [
{
"key": "ships_releases",
"name": "Ships releases",
"detail": "1 releases published",
"points": 27,
"status": "met",
"details": [
{
"code": "releases_published",
"params": {
"count": 1
}
}
],
"max_points": 27
},
{
"key": "release_recency",
"name": "Release recency",
"detail": "latest release 8 days ago",
"points": 36,
"status": "met",
"details": [
{
"code": "release_recency",
"params": {
"days": 8
}
}
],
"max_points": 36
},
{
"key": "release_cadence",
"name": "Release cadence",
"detail": "cadence unknown (single release)",
"points": 12.6,
"status": "partial",
"details": [
{
"code": "release_cadence_unknown",
"params": {}
}
],
"max_points": 27
},
{
"key": "openssf_scorecard_signed_releases",
"name": "OpenSSF Scorecard: Signed-Releases",
"detail": "no releases found",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_data",
"params": {}
}
],
"max_points": 10
}
]
},
{
"key": "abandonment",
"band": "excellent",
"name": "Abandonment",
"note": null,
"notes": [],
"value": 100,
"inputs": {
"cap": null,
"state": "unverified",
"guards": [],
"signals": [],
"red_flag": false,
"multiplier_pct": 100,
"declared_reason": null,
"unverified_reason": "repository_too_young",
"unanswered_open_prs": null,
"unanswered_open_issues": null,
"days_since_last_merged_pr": null,
"days_since_last_human_commit": null,
"days_since_last_human_commit_is_floor": false
},
"components": [
{
"key": "project_is_still_maintained",
"name": "Project is still maintained",
"detail": "maintenance record not established from the collected data",
"points": 100,
"status": "met",
"details": [
{
"code": "abandonment_unverified",
"params": {}
}
],
"max_points": 100
}
]
}
],
"description": "Is the project alive — is code being written and are releases shipping?"
},
{
"key": "community",
"band": "at_risk",
"name": "Community & Adoption",
"value": 40,
"weight": 0.18,
"metrics": [
{
"key": "popularity",
"band": "critical",
"name": "Popularity & adoption",
"note": null,
"notes": [],
"value": 1,
"inputs": {
"forks": 0,
"stars": 0,
"watchers": 0,
"growth_state": "unverified",
"growth_factor_pct": 100,
"growth_unverified_reason": "no_history"
},
"components": [
{
"key": "stars",
"name": "Stars",
"detail": "0 stars",
"points": 0,
"status": "missed",
"details": [
{
"code": "stars",
"params": {
"count": 0
}
}
],
"max_points": 60
},
{
"key": "forks",
"name": "Forks",
"detail": "0 forks",
"points": 0,
"status": "missed",
"details": [
{
"code": "forks",
"params": {
"count": 0
}
}
],
"max_points": 25
},
{
"key": "watchers",
"name": "Watchers",
"detail": "0 watchers",
"points": 0,
"status": "missed",
"details": [
{
"code": "watchers",
"params": {
"count": 0
}
}
],
"max_points": 15
}
]
},
{
"key": "community_health",
"band": "good",
"name": "Community health",
"note": null,
"notes": [],
"value": 70,
"inputs": {
"has_readme": true,
"has_license": true,
"has_contributing": true,
"has_issue_template": false,
"has_code_of_conduct": false,
"has_pull_request_template": false
},
"components": [
{
"key": "readme",
"name": "README",
"detail": null,
"points": 22.5,
"status": "met",
"details": [],
"max_points": 22.5
},
{
"key": "license",
"name": "License",
"detail": "recognized license (MIT)",
"points": 22.5,
"status": "met",
"details": [
{
"code": "license_standard",
"params": {}
},
{
"code": "license_spdx",
"params": {
"spdx": "MIT"
}
}
],
"max_points": 22.5
},
{
"key": "contributing_guide",
"name": "CONTRIBUTING guide",
"detail": null,
"points": 18,
"status": "met",
"details": [],
"max_points": 18
},
{
"key": "code_of_conduct",
"name": "Code of conduct",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 13.5
},
{
"key": "issue_template",
"name": "Issue template",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.2
},
{
"key": "pr_template",
"name": "PR template",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 6.3
}
]
},
{
"key": "ecosystem_adoption",
"band": "moderate",
"name": "Ecosystem adoption (downloads)",
"note": "Excluded from scoring (no data or not applicable): Registry dependents. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"registry_dependents"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 62,
"inputs": {
"packages": [
"@rift-vs/rift",
"@rift-vs/rift-embedded"
],
"dependents": null,
"ecosystems": "npm",
"total_downloads": null,
"monthly_downloads": 5615
},
"components": [
{
"key": "monthly_downloads",
"name": "Monthly downloads",
"detail": "5,615 downloads/month across npm",
"points": 50,
"status": "partial",
"details": [
{
"code": "downloads_monthly",
"params": {
"count": 5615,
"ecosystems": "npm"
}
}
],
"max_points": 80
},
{
"key": "registry_dependents",
"name": "Registry dependents",
"detail": "not reported by this ecosystem",
"points": 0,
"status": "excluded",
"details": [
{
"code": "not_reported_by_this_ecosystem",
"params": {}
}
],
"max_points": 20
}
]
}
],
"description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
},
{
"key": "governance",
"band": "moderate",
"name": "Sustainability & Governance",
"value": 53,
"weight": 0.24,
"metrics": [
{
"key": "maintainer_resilience",
"band": "critical",
"name": "Maintainer resilience (bus factor)",
"note": null,
"notes": [],
"value": 10,
"inputs": {
"bus_factor": 1,
"contributors_sampled": 1,
"top_contributor_share": 1
},
"components": [
{
"key": "bus_factor",
"name": "Bus factor",
"detail": "1 contributor(s) cover half of all commits",
"points": 9,
"status": "partial",
"details": [
{
"code": "bus_factor",
"params": {
"count": 1
}
}
],
"max_points": 54
},
{
"key": "commit_distribution",
"name": "Commit distribution",
"detail": "top contributor authored 100% of commits",
"points": 0,
"status": "missed",
"details": [
{
"code": "top_contributor_share",
"params": {
"share": 100
}
}
],
"max_points": 22.5
},
{
"key": "contributor_breadth",
"name": "Contributor breadth",
"detail": "1 contributors",
"points": 1.4,
"status": "partial",
"details": [
{
"code": "contributors_sampled",
"params": {
"count": 1
}
}
],
"max_points": 13.5
},
{
"key": "openssf_scorecard_contributors",
"name": "OpenSSF Scorecard: Contributors",
"detail": "project has 0 contributing companies or organizations -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 10
}
]
},
{
"key": "responsiveness",
"band": "good",
"name": "Issue & PR responsiveness",
"note": null,
"notes": [],
"value": 82,
"inputs": {
"merged_prs": 51,
"open_issues": 2,
"closed_issues": 41,
"issue_closed_ratio": 0.953,
"closed_unmerged_prs": 1
},
"components": [
{
"key": "issue_resolution",
"name": "Issue resolution",
"detail": "95% of issues closed",
"points": 44.6,
"status": "partial",
"details": [
{
"code": "issues_closed_share",
"params": {
"share": 95
}
}
],
"max_points": 46.75
},
{
"key": "pr_acceptance",
"name": "PR acceptance",
"detail": "51/52 decided PRs merged",
"points": 37.5,
"status": "partial",
"details": [
{
"code": "decided_prs_merged",
"params": {
"merged": 51,
"decided": 52
}
}
],
"max_points": 38.25
},
{
"key": "openssf_scorecard_code_review",
"name": "OpenSSF Scorecard: Code-Review",
"detail": "Found 1/30 approved changesets -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 15
}
]
},
{
"key": "stewardship",
"band": "at_risk",
"name": "Ownership & stewardship",
"note": null,
"notes": [],
"value": 39,
"inputs": {
"followers": 1,
"owner_type": "Organization",
"is_verified": null,
"owner_login": "achird-labs",
"public_repos": 8,
"account_age_days": 11
},
"components": [
{
"key": "ownership_backing",
"name": "Ownership backing",
"detail": "organization-owned",
"points": 30,
"status": "met",
"details": [
{
"code": "owner_organization",
"params": {}
}
],
"max_points": 30
},
{
"key": "verified_domain",
"name": "Verified domain",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 20
},
{
"key": "owner_reach",
"name": "Owner reach",
"detail": "1 followers of achird-labs",
"points": 2.2,
"status": "partial",
"details": [
{
"code": "owner_followers",
"params": {
"count": 1,
"login": "achird-labs"
}
}
],
"max_points": 25
},
{
"key": "track_record",
"name": "Track record",
"detail": "8 public repos, account ~0 yr old",
"points": 7,
"status": "partial",
"details": [
{
"code": "public_repos",
"params": {
"count": 8
}
},
{
"code": "account_age_years",
"params": {
"years": 0
}
}
],
"max_points": 25
}
]
},
{
"key": "package_maintenance",
"band": "excellent",
"name": "Package maintenance",
"note": null,
"notes": [],
"value": 100,
"inputs": {
"packages": [
"@rift-vs/rift",
"@rift-vs/rift-embedded"
],
"ecosystems": "npm",
"any_deprecated": false,
"min_days_since_publish": 8
},
"components": [
{
"key": "published_resolvable",
"name": "Published & resolvable",
"detail": "2 package(s) on npm",
"points": 25,
"status": "met",
"details": [
{
"code": "packages_published",
"params": {
"count": 2,
"ecosystems": "npm"
}
}
],
"max_points": 25
},
{
"key": "publish_recency",
"name": "Publish recency",
"detail": "latest publish 8 days ago",
"points": 35,
"status": "met",
"details": [
{
"code": "publish_recency",
"params": {
"days": 8
}
}
],
"max_points": 35
},
{
"key": "version_history",
"name": "Version history",
"detail": "42 published versions",
"points": 20,
"status": "met",
"details": [
{
"code": "published_versions",
"params": {
"count": 42
}
}
],
"max_points": 20
},
{
"key": "not_deprecated",
"name": "Not deprecated",
"detail": "active, not deprecated or yanked",
"points": 20,
"status": "met",
"details": [
{
"code": "package_not_deprecated",
"params": {}
}
],
"max_points": 20
}
]
}
],
"description": "Will the project survive its people — bus factor, responsiveness, who backs it, and package upkeep?"
},
{
"key": "engineering",
"band": "excellent",
"name": "Engineering Quality",
"value": 86,
"weight": 0.2,
"metrics": [
{
"key": "engineering_practices",
"band": "good",
"name": "Engineering practices",
"note": null,
"notes": [],
"value": 84,
"inputs": {
"has_ci": true,
"has_tests": true,
"has_editorconfig": false,
"has_linter_config": true,
"has_precommit_config": false
},
"components": [
{
"key": "ci_workflows",
"name": "CI workflows",
"detail": "5 workflow(s)",
"points": 24,
"status": "met",
"details": [
{
"code": "ci_workflows",
"params": {
"count": 5
}
}
],
"max_points": 24
},
{
"key": "tests_present",
"name": "Tests present",
"detail": null,
"points": 24,
"status": "met",
"details": [],
"max_points": 24
},
{
"key": "linter_config",
"name": "Linter config",
"detail": ".eslintrc.cjs",
"points": 16,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": ".eslintrc.cjs"
}
}
],
"max_points": 16
},
{
"key": "pre_commit_hooks",
"name": "Pre-commit hooks",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 9.6
},
{
"key": "editorconfig",
"name": ".editorconfig",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 6.4
},
{
"key": "openssf_scorecard_ci_tests",
"name": "OpenSSF Scorecard: CI-Tests",
"detail": "30 out of 30 merged PRs checked by a CI test -- score normalized to 10",
"points": 20,
"status": "met",
"details": [],
"max_points": 20
}
]
},
{
"key": "documentation",
"band": "excellent",
"name": "Documentation",
"note": null,
"notes": [],
"value": 90,
"inputs": {
"topics": [],
"has_wiki": true,
"homepage": "https://achird-labs.github.io/rift-node/",
"has_readme": true,
"has_docs_dir": true,
"has_description": true
},
"components": [
{
"key": "readme",
"name": "README",
"detail": null,
"points": 30,
"status": "met",
"details": [],
"max_points": 30
},
{
"key": "documentation_directory",
"name": "Documentation directory",
"detail": null,
"points": 25,
"status": "met",
"details": [],
"max_points": 25
},
{
"key": "documentation_homepage_site",
"name": "Documentation / homepage site",
"detail": "https://achird-labs.github.io/rift-node/",
"points": 15,
"status": "met",
"details": [],
"max_points": 15
},
{
"key": "repository_description",
"name": "Repository description",
"detail": null,
"points": 10,
"status": "met",
"details": [],
"max_points": 10
},
{
"key": "topics",
"name": "Topics",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 10
},
{
"key": "wiki",
"name": "Wiki",
"detail": null,
"points": 10,
"status": "met",
"details": [],
"max_points": 10
}
]
}
],
"description": "Are baseline engineering and documentation practices in place?"
},
{
"key": "security",
"band": "at_risk",
"name": "Security",
"value": 31,
"weight": 0.16,
"metrics": [
{
"key": "security_posture",
"band": "at_risk",
"name": "Security posture",
"note": "Excluded from scoring (no data or not applicable): Signed-Releases. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"signed_releases"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 31,
"inputs": {
"source": "openssf_scorecard",
"checks_evaluated": 17,
"scorecard_version": "v5.5.0",
"checks_inconclusive": 1,
"scorecard_aggregate": 3.1
},
"components": [
{
"key": "binary_artifacts",
"name": "Binary-Artifacts",
"detail": "no binaries found in the repo",
"points": 7.5,
"status": "met",
"details": [],
"max_points": 7.5
},
{
"key": "branch_protection",
"name": "Branch-Protection",
"detail": "branch protection not enabled on development/release branches",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "ci_tests",
"name": "CI-Tests",
"detail": "30 out of 30 merged PRs checked by a CI test -- score normalized to 10",
"points": 2.5,
"status": "met",
"details": [],
"max_points": 2.5
},
{
"key": "cii_best_practices",
"name": "CII-Best-Practices",
"detail": "no effort to earn an OpenSSF best practices badge detected",
"points": 0,
"status": "missed",
"details": [],
"max_points": 2.5
},
{
"key": "code_review",
"name": "Code-Review",
"detail": "Found 1/30 approved changesets -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "contributors",
"name": "Contributors",
"detail": "project has 0 contributing companies or organizations -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 2.5
},
{
"key": "dangerous_workflow",
"name": "Dangerous-Workflow",
"detail": "no dangerous workflow patterns detected",
"points": 10,
"status": "met",
"details": [],
"max_points": 10
},
{
"key": "dependency_update_tool",
"name": "Dependency-Update-Tool",
"detail": "no update tool detected",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "fuzzing",
"name": "Fuzzing",
"detail": "project is not fuzzed",
"points": 0,
"status": "missed",
"details": [],
"max_points": 5
},
{
"key": "license",
"name": "License",
"detail": "license file detected",
"points": 2.5,
"status": "met",
"details": [],
"max_points": 2.5
},
{
"key": "maintained",
"name": "Maintained",
"detail": "project was created within the last 90 days. Please review its contents carefully",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "packaging",
"name": "Packaging",
"detail": "packaging workflow detected",
"points": 5,
"status": "met",
"details": [],
"max_points": 5
},
{
"key": "pinned_dependencies",
"name": "Pinned-Dependencies",
"detail": "dependency not pinned by hash detected -- score normalized to 5",
"points": 2.5,
"status": "partial",
"details": [],
"max_points": 5
},
{
"key": "sast",
"name": "SAST",
"detail": "SAST tool is not run on all commits -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 5
},
{
"key": "security_policy",
"name": "Security-Policy",
"detail": "security policy file not detected",
"points": 0,
"status": "missed",
"details": [],
"max_points": 5
},
{
"key": "signed_releases",
"name": "Signed-Releases",
"detail": "no releases found",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_data",
"params": {}
}
],
"max_points": 7.5
},
{
"key": "token_permissions",
"name": "Token-Permissions",
"detail": "detected GitHub workflow tokens with excessive permissions",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "vulnerabilities",
"name": "Vulnerabilities",
"detail": "22 existing vulnerabilities detected",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
}
]
},
{
"key": "high_risk_jurisdiction_exposure",
"band": "excellent",
"name": "High-Risk Jurisdiction Exposure",
"note": "Only high-confidence self-published location evidence affects this multiplier. Ambiguous matches are review-only; country evidence is not proof of nationality, citizenship, legal registration, malicious intent, or sanctions status.",
"notes": [
{
"code": "jurisdiction_evidence_limits",
"params": {}
}
],
"value": 100,
"inputs": {
"meaning": "self-published location evidence; not nationality or citizenship",
"red_flag": false,
"exposures": [],
"policy_countries": [
"Russia",
"Iran",
"North Korea"
],
"review_only_matches": 0,
"assessed_self_published_locations": 1
},
"components": [
{
"key": "policy_exposure_multiplier",
"name": "Policy exposure multiplier",
"detail": "no confirmed policy-scope location match",
"points": 100,
"status": "met",
"details": [
{
"code": "jurisdiction_no_match",
"params": {}
}
],
"max_points": 100
}
]
}
],
"description": "Are visible security and supply-chain practices strong, with no malicious dependency and no unresolved high-risk jurisdiction exposure?"
},
{
"key": "ai_readiness",
"band": "moderate",
"name": "AI Readiness",
"value": 57,
"weight": 0,
"metrics": [
{
"key": "ai_agent_context",
"band": "at_risk",
"name": "Agent context & guidance",
"note": null,
"notes": [],
"value": 40,
"inputs": {
"has_llms_txt": false,
"legible_history_share": 0.951,
"agent_instruction_files": [],
"agent_instruction_max_bytes": null
},
"components": [
{
"key": "agent_instructions",
"name": "Agent instructions",
"detail": "no CLAUDE.md / AGENTS.md / editor rules",
"points": 0,
"status": "missed",
"details": [
{
"code": "no_agent_instructions",
"params": {}
}
],
"max_points": 45
},
{
"key": "machine_readable_docs_llms_txt",
"name": "Machine-readable docs (llms.txt)",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 15
},
{
"key": "legible_commit_history",
"name": "Legible commit history",
"detail": "58 of 61 human commits state their intent (structured subject or explanatory body)",
"points": 40,
"status": "met",
"details": [
{
"code": "legible_history",
"params": {
"legible": 58,
"sampled": 61
}
}
],
"max_points": 40
}
]
},
{
"key": "ai_verify_loop",
"band": "moderate",
"name": "Verify loop (build / test / typecheck)",
"note": null,
"notes": [],
"value": 59,
"inputs": {
"has_nix": false,
"has_tests": true,
"lockfiles": [
"package-lock.json"
],
"has_dockerfile": false,
"typed_language": true,
"bootstrap_files": [],
"has_devcontainer": false,
"has_linter_config": true,
"typecheck_configs": [
"packages/rift-core/tsconfig.json",
"packages/rift-embedded/tsconfig.json"
],
"agent_commit_share": 0,
"toolchain_manifests": [],
"dependency_bot_commit_share": 0
},
"components": [
{
"key": "one_command_bootstrap",
"name": "One-command bootstrap",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 18
},
{
"key": "automated_tests",
"name": "Automated tests",
"detail": null,
"points": 22,
"status": "met",
"details": [],
"max_points": 22
},
{
"key": "lint_format_config",
"name": "Lint / format config",
"detail": ".eslintrc.cjs",
"points": 11,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": ".eslintrc.cjs"
}
}
],
"max_points": 11
},
{
"key": "static_type_checking",
"name": "Static type checking",
"detail": "packages/rift-core/tsconfig.json, packages/rift-embedded/tsconfig.json",
"points": 11,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": "packages/rift-core/tsconfig.json, packages/rift-embedded/tsconfig.json"
}
}
],
"max_points": 11
},
{
"key": "reproducible_environment",
"name": "Reproducible environment",
"detail": "lockfile",
"points": 10,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": "lockfile"
}
}
],
"max_points": 10
},
{
"key": "demonstrated_agent_practice",
"name": "Demonstrated agent practice",
"detail": "no agent-authored commits among the last 61",
"points": 0,
"status": "missed",
"details": [
{
"code": "no_agent_authored_commits",
"params": {
"sampled": 61
}
}
],
"max_points": 10
},
{
"key": "automated_maintenance",
"name": "Automated maintenance",
"detail": "no automated dependency updates observed",
"points": 0,
"status": "missed",
"details": [
{
"code": "no_dependency_automation",
"params": {}
}
],
"max_points": 8
},
{
"key": "openssf_scorecard_pinned_dependencies",
"name": "OpenSSF Scorecard: Pinned-Dependencies",
"detail": "dependency not pinned by hash detected -- score normalized to 5",
"points": 5,
"status": "partial",
"details": [],
"max_points": 10
}
]
},
{
"key": "ai_code_legibility",
"band": "excellent",
"name": "Code legibility for models",
"note": null,
"notes": [],
"value": 100,
"inputs": {
"primary_language": "TypeScript",
"largest_source_bytes": 42365,
"source_files_sampled": 117,
"oversized_source_files": 0
},
"components": [
{
"key": "type_checkable_code",
"name": "Type-checkable code",
"detail": "TypeScript (statically typed)",
"points": 45,
"status": "met",
"details": [
{
"code": "statically_typed_language",
"params": {
"language": "TypeScript"
}
}
],
"max_points": 45
},
{
"key": "manageable_file_sizes",
"name": "Manageable file sizes",
"detail": "0/117 source files over 60KB",
"points": 55,
"status": "met",
"details": [
{
"code": "oversized_source_files",
"params": {
"kb": 60,
"sampled": 117,
"oversized": 0
}
}
],
"max_points": 55
}
]
},
{
"key": "ai_interfaces",
"band": "at_risk",
"name": "Machine-readable interfaces",
"note": null,
"notes": [],
"value": 40,
"inputs": {
"example_dirs": [
"examples"
],
"has_mcp_signal": false,
"api_schema_files": []
},
"components": [
{
"key": "api_schema_openapi_graphql_proto",
"name": "API schema (OpenAPI/GraphQL/proto)",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 40
},
{
"key": "mcp_server",
"name": "MCP server",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 20
},
{
"key": "runnable_examples",
"name": "Runnable examples",
"detail": "examples",
"points": 40,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": "examples"
}
}
],
"max_points": 40
}
]
}
],
"description": "How well is the repo equipped to be developed and maintained with AI coding agents? An independent, experimental badge — weight 0.0, so it is surfaced on its own and does not affect the overall health score."
}
],
"metrics_version": "1.13.0"
},
"warnings": [
"GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository"
],
"report_type": "repository",
"generated_at": "2026-07-29T23:00:28.792654Z",
"schema_version": "0.27.0",
"badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/a/achird-labs/rift-node.svg",
"full_name": "achird-labs/rift-node",
"license_state": "standard",
"license_spdx": "MIT"
}