原始 JSON 报告 机器可读
{
"data": {
"repo": {
"topics": [
"automation",
"cli",
"ferry",
"github-actions",
"jira"
],
"is_fork": false,
"size_kb": 15102,
"has_wiki": true,
"homepage": null,
"languages": {
"HTML": 4222,
"Shell": 6681,
"JavaScript": 950508,
"TypeScript": 2019175
},
"pushed_at": "2026-07-28T19:03:31Z",
"created_at": "2026-04-27T18:19:11Z",
"owner_type": "Organization",
"updated_at": "2026-07-21T16:28:37Z",
"description": "GitHub Actions–native agent pipeline that turns Jira column moves into reviewed draft PRs — no server, no daemon.",
"is_archived": false,
"is_disabled": false,
"license_spdx": "MIT",
"default_branch": "main",
"license_spdx_raw": "MIT",
"primary_language": "TypeScript",
"significant_languages": [
"TypeScript",
"JavaScript"
]
},
"owner": {
"blog": "https://big-emotion.com/",
"name": "BIG EMOTION",
"type": "Organization",
"login": "big-emotion",
"company": null,
"location": "France",
"followers": 1,
"avatar_url": "https://avatars.githubusercontent.com/u/205988443?v=4",
"created_at": "2025-04-02T20:28:05Z",
"is_verified": null,
"public_repos": 6,
"account_age_days": 483
},
"license": {
"state": "standard",
"spdx_id": "MIT",
"raw_spdx": "MIT",
"file_present": true,
"scorecard_found": true,
"profile_has_license": true
},
"activity": {
"releases": [
{
"tag": "v1.2.0",
"kind": "minor",
"published_at": "2026-07-21T16:16:33Z"
},
{
"tag": "v1.1.2",
"kind": "patch",
"published_at": "2026-07-18T22:55:35Z"
},
{
"tag": "v1.1.1",
"kind": "patch",
"published_at": "2026-07-18T22:06:19Z"
},
{
"tag": "v1.1.0",
"kind": "minor",
"published_at": "2026-07-18T21:46:15Z"
},
{
"tag": "v1.0.3",
"kind": "patch",
"published_at": "2026-07-18T20:54:00Z"
},
{
"tag": "v1.0.2",
"kind": "patch",
"published_at": "2026-07-18T14:21:47Z"
},
{
"tag": "v1.0.1",
"kind": "patch",
"published_at": "2026-07-18T11:31:44Z"
},
{
"tag": "v1.0.0",
"kind": "major",
"published_at": "2026-07-18T10:33:39Z"
},
{
"tag": "v0.19.0",
"kind": "minor",
"published_at": "2026-07-18T09:27:40Z"
},
{
"tag": "v0.18.2",
"kind": "patch",
"published_at": "2026-07-18T09:04:09Z"
},
{
"tag": "v0.18.1",
"kind": "patch",
"published_at": "2026-07-18T08:03:59Z"
},
{
"tag": "v0.18.0",
"kind": "minor",
"published_at": "2026-07-18T07:34:46Z"
},
{
"tag": "v0.17.0",
"kind": "minor",
"published_at": "2026-06-07T12:05:03Z"
},
{
"tag": "v0.16.0",
"kind": "minor",
"published_at": "2026-05-25T10:39:29Z"
},
{
"tag": "v0.15.1",
"kind": "patch",
"published_at": "2026-05-21T19:07:50Z"
},
{
"tag": "v0.15.0",
"kind": "minor",
"published_at": "2026-05-21T16:04:29Z"
},
{
"tag": "v0.14.0",
"kind": "minor",
"published_at": "2026-05-21T14:06:04Z"
},
{
"tag": "v0.13.2",
"kind": "patch",
"published_at": "2026-05-21T11:38:40Z"
},
{
"tag": "v0.13.1",
"kind": "patch",
"published_at": "2026-05-20T23:52:35Z"
},
{
"tag": "v0.13.0",
"kind": "minor",
"published_at": "2026-05-20T21:46:12Z"
},
{
"tag": "v0.12.0",
"kind": "minor",
"published_at": "2026-05-20T00:33:11Z"
},
{
"tag": "v0.10.3",
"kind": "patch",
"published_at": "2026-05-05T18:47:50Z"
},
{
"tag": "v0.10.2",
"kind": "patch",
"published_at": "2026-05-05T17:33:56Z"
},
{
"tag": "v0.10.1",
"kind": "patch",
"published_at": "2026-05-05T16:47:52Z"
},
{
"tag": "v0.10.0",
"kind": "minor",
"published_at": "2026-05-05T16:20:39Z"
},
{
"tag": "v0.9.0",
"kind": "minor",
"published_at": "2026-05-05T15:23:11Z"
},
{
"tag": "v0.8.2",
"kind": "patch",
"published_at": "2026-05-05T14:55:22Z"
},
{
"tag": "v0.8.1",
"kind": "patch",
"published_at": "2026-05-05T14:35:21Z"
},
{
"tag": "v0.8.0",
"kind": "minor",
"published_at": "2026-05-05T13:24:32Z"
},
{
"tag": "v0.7.0",
"kind": "minor",
"published_at": "2026-05-04T21:18:52Z"
},
{
"tag": "v0.6.0",
"kind": "minor",
"published_at": "2026-05-04T18:10:40Z"
},
{
"tag": "v0.5.3",
"kind": "patch",
"published_at": "2026-05-02T22:05:16Z"
},
{
"tag": "v0.5.2",
"kind": "patch",
"published_at": "2026-05-02T21:27:25Z"
},
{
"tag": "v0.5.1",
"kind": "patch",
"published_at": "2026-05-02T20:40:30Z"
},
{
"tag": "v0.5.0",
"kind": "minor",
"published_at": "2026-05-02T17:52:14Z"
},
{
"tag": "v0.4.0",
"kind": "minor",
"published_at": "2026-05-02T11:28:41Z"
},
{
"tag": "v0.3.0",
"kind": "minor",
"published_at": "2026-05-01T15:32:15Z"
}
],
"recent_commits": [
{
"oid": "c1138acb2407c1846fbc25544e6967a208a9655f",
"body": "Re-audits the post-1.0.0 line at the v1.2.0 tip. Score holds at 8.9/10\nwith no P0 blockers. Coverage is now measured (87.3% statements /\n80.8% branches) rather than asserted, and the release-tag consistency\ntable is clean at @v1.2.0.\n\nRecords that a locally stale floating v1 tag is a fetch artifact, not a\nsupply-chain defect — verify it via git ls-remote, never git rev-parse.\n\nAdds a P2 note that Jira merge-column permissions became a security\nboundary under ADR-0005 rev. 2.",
"is_bot": false,
"headline": "docs: refresh production-readiness audit for v1.2.0",
"author_name": "jean-noe",
"author_login": "kooljo",
"committed_at": "2026-07-21T16:27:13Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "39a42f9f5607d22c38f453bb33212c0c94750486",
"body": null,
"is_bot": false,
"headline": "release: v1.2.0",
"author_name": "jean-noe",
"author_login": "kooljo",
"committed_at": "2026-07-21T16:08:55Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "da35314c28135e80c540bcfc62181d6177e33d2e",
"body": "…431)\n\nFive behaviors that consumers previously had to hand-write as\nprompts/<agent>.<path>.local.md overlays are now Ferry defaults on both\ndirect-action paths, so a fresh install behaves like a tuned one:\n\n- a `**Confidence (self-critique):** N/10` line on every audit comment\n- a PR label protocol\n[…]\nsrc/lib/prompts/agent-defaults.test.ts asserts these behaviors against the\nshipped prompt files so a later edit cannot silently demote one to opt-in.\n\nCo-authored-by: jean-noe <kollojeannoe@gmail.com>",
"is_bot": false,
"headline": "feat(agents): ship field-proven agent behavior as bundled defaults (#…",
"author_name": "jean-noe",
"author_login": "jean-noe",
"committed_at": "2026-07-21T13:52:28Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "12fed42ed3aa4fcf7b39637b89d81bb92965d5f2",
"body": "Correct drift in CLAUDE.md against the current codebase:\n- document the build:cli bundle (dist/cli/) alongside build:ferry\n- add the Merger agent entrypoint\n- list the ferry-run-merger and ferry-run-claude-agent composites\n- describe all three execution paths (bundled script, claude-code, codex-cli)\n- expand the CLI bin inventory and point to docs/CLI.md\n- cover both shipped build artifacts in the Deployment section",
"is_bot": false,
"headline": "docs(claude-md): sync with current build, agents, and execution paths",
"author_name": "jean-noe",
"author_login": "kooljo",
"committed_at": "2026-07-19T15:33:36Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "010f15147572106521d72577a8d9b1a6485d9597",
"body": null,
"is_bot": false,
"headline": "release: v1.1.2",
"author_name": "jean-noe",
"author_login": "kooljo",
"committed_at": "2026-07-18T22:51:05Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "eb5c5fc260d78ab4176afe654a95fafcf3f4c135",
"body": "Default Refiner, Reviewer, and Merger to claude-opus-4-8; Developer and\nIterator to claude-sonnet-5. Previously every agent fell back to\nclaude-sonnet-4-6 (and the script-path Developer default was\nclaude-opus-4-5).\n\n- config.ts: DEFAULT_FERRY_CONFIG.models per-agent defaults\n- ferry-init templates \n[…]\nte for Sonnet 5\n- reconcile.ts: Anthropic invoice name mappings for the two models\n- docs/CONFIGURATION.md and tests updated; .ferry/ bundles rebuilt\n\nCo-authored-by: jean-noe <kollojeannoe@gmail.com>",
"is_bot": false,
"headline": "chore(config): set per-agent model tiers (Opus 4.8 + Sonnet 5) (#429)",
"author_name": "jean-noe",
"author_login": "jean-noe",
"committed_at": "2026-07-18T22:38:00Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "125ad0610026a6a9a5d932c761ffdb7d8229c5fa",
"body": null,
"is_bot": false,
"headline": "release: v1.1.1",
"author_name": "jean-noe",
"author_login": "kooljo",
"committed_at": "2026-07-18T22:03:07Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "eae8df9f3ddbb469a51ac991429393436c4c11d1",
"body": "Six source files load yaml at runtime via createRequire (config loading,\ndoctor checks, ferry-update's ferry.local.yml overrides). esbuild cannot\nbundle a dynamic require, so the module must resolve from the installed\npackage's node_modules — but yaml was declared in devDependencies, which\nnpx does \n[…]\ned in v1.0.1.\n\nVerified end-to-end: npm pack, install the tarball in a scratch project,\ncreateRequire('yaml') from the installed dist/cli/update/index.js\nresolves and parses a ferry.local.yml snippet.",
"is_bot": false,
"headline": "fix(packaging): declare yaml as a runtime dependency",
"author_name": "jean-noe",
"author_login": "kooljo",
"committed_at": "2026-07-18T22:00:15Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "f21cd43087461384920669d77c01278a94e8ad23",
"body": null,
"is_bot": false,
"headline": "release: v1.1.0",
"author_name": "jean-noe",
"author_login": "kooljo",
"committed_at": "2026-07-18T21:37:11Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "ee60dbc49630bb3883accf953e75d2b21ab6dd68",
"body": "Moving a ticket into workflow.agents.merger.trigger_column (default\n\"Ready to Merge\") now routes the generic ferry-transition event to the\nMerger, exactly like the four other agents' trigger columns. A column\nmove into the merge column is an explicit human merge order.\n\n- config: MergerWorkflowAgent\n[…]\nions bundles rebuilt\n\nThe Reviewer-emitted ferry-merge dispatch on approve is unchanged; the\ncolumn is an additional trigger path. The gh-pr-merge deny-list for the\nfour non-merger roles is untouched.",
"is_bot": false,
"headline": "feat(router): column-triggered Merger — ADR-0005 rev. 2",
"author_name": "jean-noe",
"author_login": "kooljo",
"committed_at": "2026-07-18T21:31:20Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "4aa7b5c655a7b7b39fb92cadf52037de6c1d69aa",
"body": null,
"is_bot": false,
"headline": "release: v1.0.3",
"author_name": "jean-noe",
"author_login": "kooljo",
"committed_at": "2026-07-18T20:49:32Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "e5fa869a5f00f31a2bb50de917a8e2d94d1a73ec",
"body": "The claude-code-action App installation token carries no Actions scope,\nso every gh run list / gh run view --log-failed call made by an agent\nreturns 403 (observed on the CHANSUP dry-run: the Developer labeled the\nPR ci-failing because CI was unreadable, and the Merger cannot verify\nthe green state \n[…]\nper FR32/ADR-0005).\n\nRequest actions:read via additional_permissions; the calling job must\ngrant the matching ceiling, which ferry-router.yml's run-agent job\nalready does (permissions: actions: read).",
"is_bot": false,
"headline": "fix(cc-agent): request actions:read so agents can read CI state (#428)",
"author_name": "jean-noe",
"author_login": "jean-noe",
"committed_at": "2026-07-18T20:35:18Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "b370abfbe78ec1ae8052ee46ce7d6990e2587a3a",
"body": null,
"is_bot": false,
"headline": "release: v1.0.2",
"author_name": "jean-noe",
"author_login": "kooljo",
"committed_at": "2026-07-18T14:18:23Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "735b5aff2a5c77944d35a8e6375f979be785b5c1",
"body": "…427)\n\nThe Merger is reached only by the ferry-merge event the Reviewer\ndispatches on approval (ADR-0005), so the merge run's actor is Ferry's\nClaude GitHub App (claude[bot]), never a human. anthropics/claude-code-action's\nhuman-actor gate rejects any bot actor unless it is in allowed_bots\n(default \n[…]\node-action step, allow-listing\nFerry's own bot only (not '*'; the action lower-cases and strips the\n[bot] suffix). Human-triggered roles are unaffected — allowed_bots is\nconsulted only for bot actors.",
"is_bot": false,
"headline": "fix(claude-code): allow-list Ferry's own bot so the Merger can run (#…",
"author_name": "jean-noe",
"author_login": "jean-noe",
"committed_at": "2026-07-18T14:07:45Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "f95af326bbdd163043fff198a524cbb7967be4e7",
"body": null,
"is_bot": false,
"headline": "release: v1.0.1",
"author_name": "jean-noe",
"author_login": "kooljo",
"committed_at": "2026-07-18T11:28:25Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "ac6d5054b869cfa82a6536bc3349fc5870c61adb",
"body": "…package\n\nscripts/build-cli.mjs hardcodes the esbuild entrypoint list and never\nincluded resolve-transition, local, or codex-config, so their dist/cli/\nbundles were never emitted despite being declared in package.json bin.\nOn the claude-code path this crashed the Developer/Reviewer/Iterator\nagents w\n[…]\n) with their mkdir/chmod, and record the fix under CHANGELOG\n[Unreleased].\n\nVerified: npm run build:cli emits all three; each binary runs (no 127);\nnpm pack --dry-run ships all three (total files 18).",
"is_bot": false,
"headline": "fix(build): bundle the three CLI binaries missing from the published …",
"author_name": "jean-noe",
"author_login": "kooljo",
"committed_at": "2026-07-18T11:17:19Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "d5399c393421dfe0efa9cb87a0d5995848244f2c",
"body": null,
"is_bot": false,
"headline": "release: v1.0.0",
"author_name": "jean-noe",
"author_login": "kooljo",
"committed_at": "2026-07-18T10:26:10Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "2e2b3fe4c4208767892e34ceae4c3511541ef6a2",
"body": null,
"is_bot": false,
"headline": "docs: refresh production-readiness audit for v0.19.0 (cleared for 1.0.0)",
"author_name": "jean-noe",
"author_login": "kooljo",
"committed_at": "2026-07-18T10:19:31Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "226ee8e756f48b6ccf62f51e0cb43cd06587fb5a",
"body": null,
"is_bot": false,
"headline": "release: v0.19.0",
"author_name": "jean-noe",
"author_login": "kooljo",
"committed_at": "2026-07-18T09:21:58Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "6e986a95cabaed89e3a9b8ba425bebe59b1e4360",
"body": "… list (FER-27)\n\nEvery ferry-router.yml run showed the same anonymous \"Ferry — Router\" title, so\nthree concurrent dispatches for different tickets were indistinguishable in the\nActions list. The agent role is only known after the route job, but the dispatch\nevent type, ticket key, and target status \n[…]\ne consumer example stub, and the repo's own dogfood\nworkflow (effective immediately — run-name lives in the workflow file, not the\ncomposite, so no release is needed for the dogfood board to show it).",
"is_bot": false,
"headline": "feat(router): add run-name identifying each router run in the Actions…",
"author_name": "jean-noe",
"author_login": "kooljo",
"committed_at": "2026-07-18T09:12:19Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "a82a0f06ea62c6abb64060f7a0eae773acd47b85",
"body": null,
"is_bot": false,
"headline": "release: v0.18.2",
"author_name": "jean-noe",
"author_login": "kooljo",
"committed_at": "2026-07-18T08:57:09Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "9a5b57cacfd885127d2cb648c5cd23bcab1cc691",
"body": "…ublished package (FER-26)\n\nWhen Ferry dogfoods itself, the ferry-run-claude-agent composite runs in a\ncheckout of big-emotion/ferry — so `npx -p @big-emotion/ferry@<ver> <bin>`\nresolves the LOCAL package (whose dist/ is not built) and every bin comes back\n\"command not found\", killing the agent befo\n[…]\nackage from a neutral dir. The CLIs still read prompts/config from the repo\ncwd (--repo-root unchanged), so consumer prompt resolution is intact.\n\nGuarded by structural tests in install-guide.test.ts.",
"is_bot": false,
"headline": "fix(composite): isolate npx via --prefix so dogfooding resolves the p…",
"author_name": "jean-noe",
"author_login": "kooljo",
"committed_at": "2026-07-18T08:51:38Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "afbba32ed97d1ee8a126e48c1f14fc86d6e92055",
"body": null,
"is_bot": false,
"headline": "release: v0.18.1",
"author_name": "jean-noe",
"author_login": "kooljo",
"committed_at": "2026-07-18T07:58:43Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "cf9733ded084e44e68711bd4227cf5c6d3cbefe0",
"body": "…es to .claude-code.local.md\n\nThe claude-code prompt resolver only appended prompts/<agent>.<path>.local.md\nwhen NO full prompts/<agent>.<path>.md override existed — so a repo that ships\nits bundled prompt SOURCE at prompts/<agent>.claude-code.md (Ferry dogfooding\nitself) silently shadowed its own .\n[…]\nonsumers (npm files = dist/cli only), so this stays\ndogfooding-local with no consumer impact. Takes effect for Ferry's own\ndogfooding once a release carrying this resolver ships and the pin is bumped.",
"is_bot": false,
"headline": "fix(prompts): always apply the .local.md overlay; move dogfooding rul…",
"author_name": "jean-noe",
"author_login": "kooljo",
"committed_at": "2026-07-18T07:48:01Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "0c70cd78e4217d35f40991b0610edd9beb91c245",
"body": "…ER-1) (#426)\n\n- Delete .github/workflows/ferry-{refine,dev,review,iterate,merge}.yml (legacy\n @v0.17.0 install from #424): the router subscribes to the same event types,\n so keeping both would double-fire every dispatch, including ferry-merge.\n- Install .github/workflows/ferry-router.yml from the\n[…]\n swap would otherwise invalidate.\n- Give ferry-release an explicit pin policy for the installed dogfood router\n (release-coupled, staged in Step 8).\n\nCo-authored-by: jean-noe <kollojeannoe@gmail.com>",
"is_bot": false,
"headline": "feat(dogfooding): swap the 5 legacy workflows for the router model (F…",
"author_name": "jean-noe",
"author_login": "jean-noe",
"committed_at": "2026-07-18T07:37:01Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "38da2fc63ac7e2053143eccb8ec33e3a4546bc7f",
"body": null,
"is_bot": false,
"headline": "release: v0.18.0",
"author_name": "jean-noe",
"author_login": "kooljo",
"committed_at": "2026-07-18T07:30:18Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "997be840c837cd1c4b000ecd29f538bc89497c7b",
"body": "CI (npm Audit supply-chain gate) went red on newly-published high-severity\nadvisories against already-present transitive deps — ws and protobufjs (via\n@google/genai) and hono (via @modelcontextprotocol/sdk). `npm audit fix`\npatches all three within the existing semver ranges: package.json is\nunchanged, only the lockfile moves. Rebuilt .ferry/ + composite bundles so\nthe vendored SDK code matches. `npm run audit:ci` is clean (0 blocking).",
"is_bot": false,
"headline": "fix(deps): patch ws, protobufjs and hono transitive advisories",
"author_name": "jean-noe",
"author_login": "kooljo",
"committed_at": "2026-07-18T07:20:59Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "9cf35adc0b6478f5f95b5af338f0b92532aa28a7",
"body": "Completes the thin-install migration surface. ferry-doctor, ferry-update and\nferry-uninstall now understand both install models; docs and guard tests\ndescribe the router model accurately. Hardened by an adversarial review pass\n(14 findings, all addressed):\n\ndoctor\n- secrets: transition-id secrets ar\n[…]\ns\n Done/Closed; auto_transition_done + FERRY_MERGE_DONE_TRANSITION_ID are\n script-path); MIGRATIONS.md v0.17.x -> v0.18.0 router migration entry;\n install-guide guards updated to pin the new claims",
"is_bot": false,
"headline": "feat(cli): align doctor/update/uninstall and docs with the router model",
"author_name": "jean-noe",
"author_login": "kooljo",
"committed_at": "2026-07-18T00:40:06Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "2372a19279b59a16eccb7c0ca12c0e331ab5b746",
"body": "…ngle Jira rule\n\nThe claude-code install collapses to: ONE router workflow (ferry-router.yml)\n+ ONE any-column Jira rule + ferry.config as the single source of truth.\n\n- new shared composite .github/actions/ferry-run-claude-agent: one\n role-parameterized action absorbing branch resolution (ferry/<k\n[…]\nRRY_INTEGRATION_BRANCH from the repo default branch, updates banner\n and next-steps; script/codex paths keep the per-agent stubs\n- legacy 5-stub generator untouched — existing installs stay supported",
"is_bot": false,
"headline": "feat(router): thin router workflow, shared claude-agent composite, si…",
"author_name": "jean-noe",
"author_login": "kooljo",
"committed_at": "2026-07-17T23:58:38Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "caf6c671f2312895e164dcb74c3f8b504c43bbce",
"body": "…o-resolve\n\nBackward-compatible groundwork for the thin-install model (one any-column\nJira rule -> one router workflow -> config as single source of truth). All\nof it ships dormant: existing 5-event installs behave identically.\n\n- event schema v1: add optional `to_status` and the `transition` phase \n[…]\n ferry_merge_done_transition_id input/env (the stub-level FR32 gap)\n- ferry-resolve-transition: support `--agent merge --kind done`\n- rebuild .ferry/ and composite-action bundles (schema vendored 4x)",
"is_bot": false,
"headline": "feat(router): foundations for the single-rule router model + FR32 aut…",
"author_name": "jean-noe",
"author_login": "kooljo",
"committed_at": "2026-07-17T23:49:11Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "1cc0fbcd59756b2d00219d03e6dae7b1b511e790",
"body": "…s on the claude-code path\n\nThe claude-code path still injects numeric Jira transition ids into the\nagent prompt from FERRY_*_TRANSITION_ID secrets. This CLI is the bridge that\nlets a workflow drop those secrets: it reads ferry.config.json, maps the\n(agent, kind) pair to the configured auto_transiti\n[…]\naccess\n- writes the id to $GITHUB_OUTPUT (or stdout)\n\nThe composite action (thick-composite slice) and the router workflow will\ncall this to remove the transition-ID secrets from the claude-code path.",
"is_bot": false,
"headline": "feat(cli): add ferry-resolve-transition to auto-resolve transition id…",
"author_name": "jean-noe",
"author_login": "kooljo",
"committed_at": "2026-07-17T23:22:06Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "a96ef54aba90cfe44490584c0f9373d42e060371",
"body": "…ames\n\nConsumers no longer have to look up numeric Jira transition ids by hand.\nThe Developer, Reviewer and Iterator agents now resolve the transition id\nat runtime from the configured target status name\n(workflow.agents.*.auto_transition*), matching on the transition's target\nstatus (transition.to.\n[…]\nsite-action bundles\n\nFirst slice of the install-simplification initiative (auto-resolve\ntransitions). Merger auto-resolve and the claude-code resolve step follow\nin later slices; both reuse this core.",
"is_bot": false,
"headline": "feat(jira): auto-resolve workflow transition ids from config status n…",
"author_name": "jean-noe",
"author_login": "kooljo",
"committed_at": "2026-07-17T23:10:20Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "4728dac8d484086188bfa0e0c6fd2d2d05504228",
"body": "…plate (#422)\n\n- .claude/skills: migrate ferry-release and ferry-audit from user level,\n refreshed against the current repo (package name, released workflow\n surface, v0.17.0 reference map, FR32 Merger); add ferry-spec and\n ferry-ticket, adapted from the Grande Chancellerie consumer skills\n- docs\n[…]\n- docs/templates: self-sufficient Jira ticket template for FER\n- .gitignore: version only the four ferry-* skills; local skill packs\n stay untracked\n\nCo-authored-by: jean-noe <kollojeannoe@gmail.com>",
"is_bot": false,
"headline": "feat(skills): add project skills, spec bootstrap, and Jira ticket tem…",
"author_name": "jean-noe",
"author_login": "jean-noe",
"committed_at": "2026-07-17T22:22:38Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "ab83b3ee750d79fdd8a6c5a813b1f9d47d70a9bb",
"body": "After createPR, the Developer looks up the open PR for its working\nbranch and adds the ferry:reviewing label, surfacing pipeline status\nfrom the GitHub PR list. Best-effort by design: any lookup or labeling\nerror is logged as a warning and never fails the run or the FR18\ntransition.\n\n- src/agents/de\n[…]\nbest-effort call after createPR\n- .ferry/ and action bundles rebuilt in lock-step\n- .gitignore: ignore autogenerated .codex/ local environment config\n\nCo-authored-by: jean-noe <kollojeannoe@gmail.com>",
"is_bot": false,
"headline": "feat(developer): label opened PRs with ferry:reviewing (#423)",
"author_name": "jean-noe",
"author_login": "jean-noe",
"committed_at": "2026-07-17T22:22:25Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "2b51a2e1bc9cf6886dcc83a9bd3e3d63092622dc",
"body": "… (#424)\n\nWire big-emotion/ferry as a consumer of its own pipeline:\n\n- .github/workflows/ferry-{refine,dev,review,iterate,merge}.yml: the five\n agent dispatch workflows, copied verbatim from the consumer stubs and\n pinned to @v0.17.0 (only the copy-instruction header lines replaced;\n ferry-merge'\n[…]\n awareness) — bundled defaults\n untouched\n\nRemaining before first run (human): FER-5 secrets/variables, FER-6 board\ncolumns + Jira Automation rules.\n\nCo-authored-by: jean-noe <kollojeannoe@gmail.com>",
"is_bot": false,
"headline": "feat(dogfooding): install Ferry on its own repo (FER-3, FER-4, FER-7)…",
"author_name": "jean-noe",
"author_login": "jean-noe",
"committed_at": "2026-07-17T22:22:13Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "94188899feffee7d3834eef2da507a06397ab8de",
"body": "Add operator-local Ferry runner CLI with poll and serve entrypoints, local idempotency persistence, per-ticket worktrees, package wiring, tests, and documentation.",
"is_bot": false,
"headline": "[codex] feat(local-runner): add operator-local CLI (#411)",
"author_name": "jean-noe",
"author_login": "jean-noe",
"committed_at": "2026-06-13T02:12:00Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "8d4d4b59315ae410c101f26381481a9dedbed18d",
"body": "Co-authored-by: jean-noe <kollojeannoe@gmail.com>",
"is_bot": false,
"headline": "Preserve local workflow and prompt overrides (#412)",
"author_name": "jean-noe",
"author_login": "jean-noe",
"committed_at": "2026-06-13T00:35:28Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "d2893b8927cde26253215db7cc40c4611b9ad897",
"body": "* add codex-cli workflow path\n\n* fix codex doctor typecheck\n\n---------\n\nCo-authored-by: jean-noe <kollojeannoe@gmail.com>",
"is_bot": false,
"headline": "[codex] complete codex-cli execution path (#409)",
"author_name": "jean-noe",
"author_login": "jean-noe",
"committed_at": "2026-06-12T23:57:39Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "da06698adc90b584044172bdab2acbc8a2111201",
"body": "Co-authored-by: jean-noe <kollojeannoe@gmail.com>",
"is_bot": false,
"headline": "docs(gitlab): add step-by-step install path (#407)",
"author_name": "jean-noe",
"author_login": "jean-noe",
"committed_at": "2026-06-12T23:41:33Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "fe7d111085ab03d462131dacd1bbf05342bac9b7",
"body": "…de-code workflows (#397)\n\nCI-driving agents (Developer, Iterator, Merger) call `gh pr checks`,\n`gh run view --log-failed`, and the GraphQL statusCheckRollup to gate\ntransitions. Without `checks: read` and `actions: read`, GitHub returns\nHTTP 403 on all check-status endpoints, causing the agent to t\n[…]\nests so this\ncontract cannot silently drift again.\n\nFixes #395\n\nCo-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>\nCo-authored-by: jean-noe <jean-noe@users.noreply.github.com>",
"is_bot": false,
"headline": "fix(init): add checks: read + actions: read to dev/iterate/merge clau…",
"author_name": "jean-noe",
"author_login": "jean-noe",
"committed_at": "2026-06-10T21:04:55Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "6f27868c781c6d92cfb0143afd5d00f35109b8ba",
"body": "Bumps [lint-staged](https://github.com/lint-staged/lint-staged) from 17.0.5 to 17.0.7.\n- [Release notes](https://github.com/lint-staged/lint-staged/releases)\n- [Changelog](https://github.com/lint-staged/lint-staged/blob/main/CHANGELOG.md)\n- [Commits](https://github.com/lint-staged/lint-staged/compar\n[…]\nrect:development\n update-type: version-update:semver-patch\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>",
"is_bot": true,
"headline": "chore(deps): bump lint-staged from 17.0.5 to 17.0.7 (#399)",
"author_name": "dependabot[bot]",
"author_login": "dependabot[bot]",
"committed_at": "2026-06-09T06:00:33Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "03206012ee7afa0edf96bf9a63471b2d8d74184e",
"body": "Bumps [@google/genai](https://github.com/googleapis/js-genai) from 2.6.0 to 2.8.0.\n- [Release notes](https://github.com/googleapis/js-genai/releases)\n- [Changelog](https://github.com/googleapis/js-genai/blob/main/CHANGELOG.md)\n- [Commits](https://github.com/googleapis/js-genai/compare/v2.6.0...v2.8.\n[…]\nirect:production\n update-type: version-update:semver-minor\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>",
"is_bot": true,
"headline": "chore(deps): bump @google/genai from 2.6.0 to 2.8.0 (#401)",
"author_name": "dependabot[bot]",
"author_login": "dependabot[bot]",
"committed_at": "2026-06-09T06:00:09Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "e0742749375300e183be4cbe143f4225a511c664",
"body": "Bumps the typescript-toolchain group with 3 updates: [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node), [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) and [@typescript-eslint/parser](htt\n[…]\npdate:semver-minor\n dependency-group: typescript-toolchain\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>",
"is_bot": true,
"headline": "chore(deps): bump the typescript-toolchain group with 3 updates (#398)",
"author_name": "dependabot[bot]",
"author_login": "dependabot[bot]",
"committed_at": "2026-06-09T05:59:49Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "7265278223aa92e5fd55b36117c762794fc2b2e7",
"body": "Bumps [openai](https://github.com/openai/openai-node) from 6.39.0 to 6.42.0.\n- [Release notes](https://github.com/openai/openai-node/releases)\n- [Changelog](https://github.com/openai/openai-node/blob/main/CHANGELOG.md)\n- [Commits](https://github.com/openai/openai-node/compare/v6.39.0...v6.42.0)\n\n---\n[…]\nirect:production\n update-type: version-update:semver-minor\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>",
"is_bot": true,
"headline": "chore(deps): bump openai from 6.39.0 to 6.42.0 (#402)",
"author_name": "dependabot[bot]",
"author_login": "dependabot[bot]",
"committed_at": "2026-06-09T05:58:54Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "db75a86fbf17c8cea4431a705f7daf4b7dde6b4d",
"body": "…ion in agent jobs (#403)\n\nOn the claude-code path, dev/iterate/merge run-agent-claude-code jobs were\nmissing checks: read and actions: read, so every call to gh pr checks,\ngh run view, and the statusCheckRollup GraphQL endpoint returned HTTP 403.\nThe agent resolved CI as unknown and never transitio\n[…]\nterate script path already used\nfetch-depth: 0).\n\nCloses #396.\n\nCo-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>\nCo-authored-by: jean-noe <jean-noe@users.noreply.github.com>",
"is_bot": false,
"headline": "fix(claude-code): grant CI-read permissions and check out target vers…",
"author_name": "jean-noe",
"author_login": "jean-noe",
"committed_at": "2026-06-09T05:57:48Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "8d5fcce14c839bad2e41c73840f13d39788c5016",
"body": null,
"is_bot": false,
"headline": "release: v0.17.0",
"author_name": "jean-noe",
"author_login": "kooljo",
"committed_at": "2026-06-07T11:59:36Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "f040805709f5cae5925b302916b249870854fcdf",
"body": "…gn merge docs (FR32)\n\nThe example consumer reviewer workflow (examples/consumer-setup/workflows/ferry-review.yml)\ngranted the script-path job only `contents: read`, so the FR32 `ferry-merge`\nrepository_dispatch on approve failed silently (the dispatch is best-effort, wrapped in\ntry/catch). ferry-in\n[…]\nated auto-transition) without\n rewriting the historical decision\n- install-guide.test.ts: the test pinned the stale \"Ferry never merges\" string in\n INSTALL.md; re-point it at the gated-merge wording",
"is_bot": false,
"headline": "fix(fr32): grant reviewer script-path contents:write in example + ali…",
"author_name": "jean-noe",
"author_login": "kooljo",
"committed_at": "2026-06-07T11:31:24Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "5c26acf361e33ceb726f045c88355d0ef88f75af",
"body": "…t (#393)\n\n* feat(merger): implement src/agents/merger + merger role in ferry-agent\n\n- Add `merger` to `AgentRole` (run-agent.ts) and `AgentOutputRole` (cc-wrappers/routing.ts)\n- Add `merger` to `providerForRole` switch (always returns 'anthropic'; merger is script-only)\n- Add `mergePR(prRef, strate\n[…]\ned-by: jean-noe <jean-noe@users.noreply.github.com>\n\n---------\n\nCo-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>\nCo-authored-by: jean-noe <jean-noe@users.noreply.github.com>",
"is_bot": false,
"headline": "feat(merger): implement src/agents/merger + merger role in ferry-agen…",
"author_name": "jean-noe",
"author_login": "jean-noe",
"committed_at": "2026-06-07T10:49:51Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "1d82d6313596568dc469ed1f5f48301ba5bfcf34",
"body": "…390)\n\n- Add prompts/merge.claude-code.md and prompts/merge.codex-cli.md for\n the direct-action execution paths (FR32 Merger)\n- Add prompts/merge.md for the script-path execution path\n- Extend CcAgent type, CC_AGENTS, and CC_PROMPT_TOKENS with 'merge'\n (tokens: TICKET_KEY, RUN_ID — matches the fer\n[…]\nundled-default substitution and consumer override\n\nCloses #385\n\nCo-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>\nCo-authored-by: jean-noe <jean-noe@users.noreply.github.com>",
"is_bot": false,
"headline": "feat(cc-prompt): add merge prompts + ferry-cc-prompt --agent merge (#…",
"author_name": "jean-noe",
"author_login": "jean-noe",
"committed_at": "2026-06-07T10:49:21Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "b736451326870bf1cf288bdcb7ad1bad0a792920",
"body": "* feat(refiner): MCP Phase 3 — migrate Refiner to agent-loop (issue #323)\n\nReplace single-shot createLlmCall with createAgentLoop + MCP plumbing.\nAdd FINISH_REFINE_TOOL (done) as the loop terminator, add runRefinerLoop()\nalongside the preserved runRefiner() for backward compatibility.\n\nCo-authored-b\n[…]\ned-by: jean-noe <jean-noe@users.noreply.github.com>\n\n---------\n\nCo-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>\nCo-authored-by: jean-noe <jean-noe@users.noreply.github.com>",
"is_bot": false,
"headline": "feat(refiner): MCP Phase 3 — migrate Refiner to agent-loop #323 (#394)",
"author_name": "jean-noe",
"author_login": "jean-noe",
"committed_at": "2026-06-07T10:49:10Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "0db471bd3150c881ade51102c6a1431d8452d5fe",
"body": "… (#391)\n\nRemove Bash(gh pr merge) and Bash(gh pr merge:*) from the Merger\nclaude-code path --disallowedTools, keeping Bash(gh pr close) blocked.\nAll four other roles (refiner, developer, reviewer, iterator) retain the\nfull ban. Mirrors the fix in examples/consumer-setup/workflows/ferry-merge.yml\nan\n[…]\ncaveat (label approval ≠ GitHub review approval).\n\nCloses #386\n\nCo-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>\nCo-authored-by: jean-noe <jean-noe@users.noreply.github.com>",
"is_bot": false,
"headline": "feat(merger): allow gh pr merge for Merger role only (FR32, ADR-0005)…",
"author_name": "jean-noe",
"author_login": "jean-noe",
"committed_at": "2026-06-07T10:39:38Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "d6be89583433e3b24d907b812a1baae01c607049",
"body": "…g (#389)\n\n- Add .github/actions/ferry-run-merger/action.yml mirroring the other\n ferry-run-* composites (inputs: payload, jira_*, *_api_key, github_token,\n github_repo, ferry_merger_model; outputs: input_tokens, output_tokens,\n cost_eur, model, cache_read_tokens, cache_write_tokens)\n- Wire merge\n[…]\n\n- Add merger to ROLES in scripts/smoke-bundle.sh\n\nCloses #384\n\nCo-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>\nCo-authored-by: jean-noe <jean-noe@users.noreply.github.com>",
"is_bot": false,
"headline": "feat(actions): commit ferry-run-merger composite action + build wirin…",
"author_name": "jean-noe",
"author_login": "jean-noe",
"committed_at": "2026-06-07T10:39:22Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "943044e091108cc014c19dc7785040094fb30deb",
"body": "Corrects documentation drift between described and actual Merger behaviour:\n\n- CHANGELOG [Unreleased]: trigger is `repository_dispatch: [ferry-merge]`\n dispatched by the Reviewer, not the `ferry:approved` label; rename\n FERRY_MERGE_MODEL/PROVIDER → FERRY_MERGER_MODEL/PROVIDER; fix\n branch-protect\n[…]\nthe `ferry-merge` dispatch rather than the label.\n\nCloses #387\n\nCo-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>\nCo-authored-by: jean-noe <jean-noe@users.noreply.github.com>",
"is_bot": false,
"headline": "docs(fr32): align Merger docs with ferry-merge dispatch trigger (#392)",
"author_name": "jean-noe",
"author_login": "jean-noe",
"committed_at": "2026-06-07T10:39:11Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "37a4614e32e976f06178e77e47f953dd3e04c6ac",
"body": "…t-loop (#381)\n\n* feat(reviewer): migrate from createToolCallLoop to createAgentLoop (MCP Phase 2, #322)\n\nReviewer now uses createAgentLoop so it inherits MCP wiring alongside\nDev and Iterator (part of #319).\n\nKey changes:\n- review-loop.ts: swap ToolCallLoop → AgentLoop; replace finish_review\n with\n[…]\ned-by: jean-noe <jean-noe@users.noreply.github.com>\n\n---------\n\nCo-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>\nCo-authored-by: jean-noe <jean-noe@users.noreply.github.com>",
"is_bot": false,
"headline": "feat(reviewer): MCP Phase 2 — migrate Reviewer from tool-loop to agen…",
"author_name": "jean-noe",
"author_login": "jean-noe",
"committed_at": "2026-06-07T09:53:38Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "18e155909da82328b192cc6da8cc07abe922bb03",
"body": "…NFIGURATION (#377)\n\n* docs(fr32): document Merger agent — MIGRATIONS, CHANGELOG, README, CONFIGURATION\n\nAdd consumer-facing documentation for the new Merger agent (FR32):\n\n- MIGRATIONS.md: v0.16.x → v0.17.0 entry covering ferry-merge.yml,\n the optional FERRY_MERGE_DONE_TRANSITION_ID secret, and th\n[…]\ned-by: jean-noe <jean-noe@users.noreply.github.com>\n\n---------\n\nCo-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>\nCo-authored-by: jean-noe <jean-noe@users.noreply.github.com>",
"is_bot": false,
"headline": "docs(fr32): document Merger agent — MIGRATIONS, CHANGELOG, README, CO…",
"author_name": "jean-noe",
"author_login": "jean-noe",
"committed_at": "2026-06-07T09:52:48Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "901488074211dd1a378be315c4910cea34a9eb2d",
"body": "* feat(fr32): dispatch ferry-merge from cc-path reviewer on approve\n\nOn the claude-code execution path the reviewer now emits a\n`ferry-merge` repository_dispatch event whenever the verdict is\nApproved (FR32). This fixes the gap where cc-path consumers could\napprove a PR but the Merger agent never tr\n[…]\ned-by: jean-noe <jean-noe@users.noreply.github.com>\n\n---------\n\nCo-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>\nCo-authored-by: jean-noe <jean-noe@users.noreply.github.com>",
"is_bot": false,
"headline": "feat(fr32): dispatch ferry-merge from cc-path reviewer on approve (#378)",
"author_name": "jean-noe",
"author_login": "jean-noe",
"committed_at": "2026-06-07T09:52:04Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "d9d76697815726e76ba9963392790c41bb73df94",
"body": "…ry-merge dispatch (#379)\n\n* fix(FR32): reviewer script-path gets contents:write + best-effort ferry-merge dispatch\n\n- Add `merge` to EventPhase, event schema enum, and PHASE_TO_WORKFLOW routing\n- Fix ferry-review.yml run-agent permissions: contents:read → contents:write\n (repository_dispatch requi\n[…]\ned-by: jean-noe <jean-noe@users.noreply.github.com>\n\n---------\n\nCo-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>\nCo-authored-by: jean-noe <jean-noe@users.noreply.github.com>",
"is_bot": false,
"headline": "fix(FR32): reviewer script-path gets contents:write + best-effort fer…",
"author_name": "jean-noe",
"author_login": "jean-noe",
"committed_at": "2026-06-07T09:49:19Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "98d2701a2e6ada915fbec215ffbdb97d4b2cbe33",
"body": "Adds a `ferry.local.yml` file that consumers can place at their repo root\nto declare workflow overrides that survive `ferry-update`. The file is\nread during regeneration so the resulting workflow files are deterministic\nfrom `(ferry version, ferry.local.yml)` — making `--dry-run` diffs\nmeaningful ag\n[…]\n/CONFIGURATION.md`: new \"Local overrides\" section\n\nCloses #371\n\nCo-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>\nCo-authored-by: jean-noe <jean-noe@users.noreply.github.com>",
"is_bot": false,
"headline": "feat(update): introduce ferry.local.yml consumer-side overlay (#380)",
"author_name": "jean-noe",
"author_login": "jean-noe",
"committed_at": "2026-06-07T09:49:08Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "9efbee7362d7b01a7db0ddbb7869cddf2cb8f305",
"body": "Bumps [@google/genai](https://github.com/googleapis/js-genai) from 2.4.0 to 2.6.0.\n- [Release notes](https://github.com/googleapis/js-genai/releases)\n- [Changelog](https://github.com/googleapis/js-genai/blob/main/CHANGELOG.md)\n- [Commits](https://github.com/googleapis/js-genai/compare/v2.4.0...v2.6.\n[…]\nirect:production\n update-type: version-update:semver-minor\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>",
"is_bot": true,
"headline": "chore(deps): bump @google/genai from 2.4.0 to 2.6.0 (#368)",
"author_name": "dependabot[bot]",
"author_login": "dependabot[bot]",
"committed_at": "2026-06-06T09:58:27Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "607278824b6a4faf82d5604eeb52b0ff4fa2d173",
"body": "Bumps [openai](https://github.com/openai/openai-node) from 6.38.0 to 6.39.0.\n- [Release notes](https://github.com/openai/openai-node/releases)\n- [Changelog](https://github.com/openai/openai-node/blob/master/CHANGELOG.md)\n- [Commits](https://github.com/openai/openai-node/compare/v6.38.0...v6.39.0)\n\n-\n[…]\nirect:production\n update-type: version-update:semver-minor\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>",
"is_bot": true,
"headline": "chore(deps): bump openai from 6.38.0 to 6.39.0 (#370)",
"author_name": "dependabot[bot]",
"author_login": "dependabot[bot]",
"committed_at": "2026-06-06T09:58:18Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "4a78627f2e478fe4313e4738419864d2770429b3",
"body": "…ith 6 updates (#373)\n\nBumps the typescript-toolchain group with 5 updates in the / directory:\n\n| Package | From | To |\n| --- | --- | --- |\n| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `25.9.0` | `25.9.1` |\n| [@typescript-eslint/eslint-plugin](https://gi\n[…]\npdate:semver-patch\n dependency-group: typescript-toolchain\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>",
"is_bot": true,
"headline": "chore(deps): bump the typescript-toolchain group across 1 directory w…",
"author_name": "dependabot[bot]",
"author_login": "dependabot[bot]",
"committed_at": "2026-06-06T09:58:07Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "83534c9ff28776ef97fe976043fa89a1ff4d6290",
"body": "…bels, prompts and CLI support (#372)\n\n* feat(codex): add codex-cli routing and prompts\n\n* fix(codex-cli): apply codex-cli execution path changes to ferry-run-* action bundles\n\nThe ferry-run-{developer,iterator,refiner,reviewer} agent.js bundles were\nmissed in the previous commit — they still rejected codex-cli as a valid\nexecution_path and lacked the executionPath override plumbing.\n\n---------\n\nCo-authored-by: jean-noe <kollojeannoe@gmail.com>",
"is_bot": false,
"headline": "Add 'codex-cli' execution path (openai/codex-action) with routing, la…",
"author_name": "jean-noe",
"author_login": "jean-noe",
"committed_at": "2026-06-06T09:57:47Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "b5238ccfeb8545dd346e7fbff5fc84305e18fa03",
"body": null,
"is_bot": false,
"headline": "release: v0.16.0",
"author_name": "jean-noe",
"author_login": "kooljo",
"committed_at": "2026-05-25T10:36:29Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "85737814003c1d45550f3218a33216e417a4959d",
"body": "…l (#365)\n\nReplace hardcoded `runs-on: ubuntu-latest` across all four agent workflow\ntemplates with `${{ fromJSON(vars.FERRY_RUNNER || '\"ubuntu-latest\"') }}`.\nConsumers on self-hosted runners set FERRY_RUNNER to a JSON string (e.g.\n'\"ubuntu-latest\"') or array (e.g. '[\"self-hosted\",\"Linux\",\"X64\"]') a\n[…]\nd documents the new variable in CONFIGURATION.md.\n\nCloses #364\n\nCo-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>\nCo-authored-by: jean-noe <jean-noe@users.noreply.github.com>",
"is_bot": false,
"headline": "feat(init): support FERRY_RUNNER variable for self-hosted runner labe…",
"author_name": "jean-noe",
"author_login": "jean-noe",
"committed_at": "2026-05-25T10:15:03Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "c55e466910f2baa7857896f5a347f95ef5ebb9ea",
"body": "* feat(claude-code): resolve agent prompts via ferry-cc-prompt\n\nAdd ferry-cc-prompt, a bin that resolves the claude-code-path system prompt for each agent: the consumer's prompts/<agent>.claude-code.md override when present, otherwise Ferry's bundled default, with runtime token substitution. The fou\n[…]\n>\n\n---------\n\nCo-authored-by: jean-noe <kollojeannoe@gmail.com>\nCo-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>\nCo-authored-by: jean-noe <jean-noe@users.noreply.github.com>",
"is_bot": false,
"headline": "feat(claude-code): resolve agent prompts via ferry-cc-prompt (#363)",
"author_name": "jean-noe",
"author_login": "jean-noe",
"committed_at": "2026-05-22T20:51:27Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "c72179c747f1d4cd704f2a246a127579554987ac",
"body": null,
"is_bot": false,
"headline": "release: v0.15.1",
"author_name": "jean-noe",
"author_login": "kooljo",
"committed_at": "2026-05-21T19:05:07Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "596a4be8008c103b6453466d044f8d7e93028724",
"body": "The four claude-code agent workflows were scaffolded with\n--permission-mode acceptEdits, which only auto-approves file edits. In a\nnon-interactive (SDK) run there is no human to grant permission, so every\nJira MCP tool call (and Bash/git/gh) is denied — the agent finishes with\npermission denials and\n[…]\nose`, so\nFerry's \"never merges\" guardrail is preserved.\n\nUpdate templates.test.ts to assert bypassPermissions and reject a\nregression to acceptEdits.\n\nCo-authored-by: jean-noe <kollojeannoe@gmail.com>",
"is_bot": false,
"headline": "fix(init): scaffold claude-code workflows with bypassPermissions (#362)",
"author_name": "jean-noe",
"author_login": "jean-noe",
"committed_at": "2026-05-21T18:48:23Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "85e9e4eb4057a933d793be8de11c6f7520b2dbf4",
"body": "…versions",
"is_bot": false,
"headline": "fix(deps): bump brace-expansion, fast-uri, protobufjs, ws to patched …",
"author_name": "jean-noe",
"author_login": "kooljo",
"committed_at": "2026-05-21T16:08:03Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "95ceb32ca41037b6a8347d0fcb6157873392fe7a",
"body": null,
"is_bot": false,
"headline": "release: v0.15.0",
"author_name": "jean-noe",
"author_login": "kooljo",
"committed_at": "2026-05-21T16:01:51Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "78c9fcf64a446f9b3bd60060fe24189c0793707c",
"body": "…n call (#361)\n\n* feat(claude-code): replace cc wrapper with a direct claude-code-action call\n\nFor `ferry:claude-code` tickets, each agent now runs as one direct\nanthropics/claude-code-action call instead of the\nferry-cc-prepare -> claude-code-action -> ferry-cc-apply wrapper. The\nagent does its own\n[…]\n failed\ntransition stays non-fatal but now emits a workflow warning annotation\nand a job-summary line instead of being silently swallowed.\n\n---------\n\nCo-authored-by: jean-noe <kollojeannoe@gmail.com>",
"is_bot": false,
"headline": "feat(claude-code): replace cc wrapper with a direct claude-code-actio…",
"author_name": "jean-noe",
"author_login": "jean-noe",
"committed_at": "2026-05-21T15:48:58Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "71e791bc61bd491dffc1c7f3ae38467bc276912b",
"body": null,
"is_bot": false,
"headline": "release: v0.14.0",
"author_name": "jean-noe",
"author_login": "kooljo",
"committed_at": "2026-05-21T14:03:04Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "9fe550d662b1db88b8c967abf598a35fb06c3e92",
"body": "…sks (#360)\n\nThe claude-code execution path for the refiner was broken end-to-end:\nclaude-code-action terminated successfully without writing\n.ferry/cc-output.json, so ferry-cc-apply failed with ENOENT — and even\nwith the artifact present, three refiner schemas disagreed and nothing\ncreated the Jira\n[…]\ntOutput variant (schema, types, contract,\n FERRY_SUBTASK_COUNT plumbing) — the refiner no longer flows through\n validateAgentOutput/decideContract.\n\nCo-authored-by: jean-noe <kollojeannoe@gmail.com>",
"is_bot": false,
"headline": "fix(cc-refiner): make the claude-code-path refiner create Jira sub-ta…",
"author_name": "jean-noe",
"author_login": "jean-noe",
"committed_at": "2026-05-21T13:40:27Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "38ce5dcf647fff5c72f60fbeebfe2074d6731b55",
"body": "…(#359)\n\n* feat(templates): expose claude-code session logs via upload-artifact\n\nAdds an observability bracket around the Run claude-code-action step in\nall four consumer workflow templates (refiner, developer, reviewer,\niterator). Each now:\n\n- Assigns id: cc-run so execution_file output is referenc\n[…]\n>\n\n---------\n\nCo-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>\nCo-authored-by: jean-noe <jean-noe@users.noreply.github.com>\nCo-authored-by: jean-noe <kollojeannoe@gmail.com>",
"is_bot": false,
"headline": "feat(templates): expose claude-code session logs via upload-artifact …",
"author_name": "jean-noe",
"author_login": "jean-noe",
"committed_at": "2026-05-21T13:01:25Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "be6fe658694913bf6c9884d83ac5906aeb0262cb",
"body": "The .ferry/ directory is gitignored wholesale; the six built action\nbundles are force-added so GitHub Actions can execute them on checkout.\nroute-action.js was the only bundle never added — its byte-identical\ndeployed copy lives at .github/actions/ferry-route/route-action.js.\nForce-add it for consistency with its six tracked siblings.",
"is_bot": false,
"headline": "build: commit the .ferry/route-action.js bundle",
"author_name": "jean-noe",
"author_login": "kooljo",
"committed_at": "2026-05-21T11:42:23Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "79ce655fd99e99475b5af496e9023d48a3bece6a",
"body": null,
"is_bot": false,
"headline": "release: v0.13.2",
"author_name": "jean-noe",
"author_login": "kooljo",
"committed_at": "2026-05-21T11:35:57Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "98ddc0d6685b91e5ab4333928e26837a62059f19",
"body": "…tem prompt via prompt input (#354)\n\ncc-prepare emitted claude_args as a JSON array, but claude-code-action@v1\nword-splits that input with shell-quote. A JSON array is mis-tokenized, so\nevery flag — including the Write(.ferry/cc-output.json) grant — was silently\ndropped. The refiner could not write \n[…]\nm(<role>). The system prompt is now folded into the action's\n verbatim prompt: input, ahead of the initial prompt.\n- Amend ADR-0006 §2 and decisions/0002 for the prompt-delivery change.\n\nCloses #354.",
"is_bot": false,
"headline": "fix(cc-prepare): serialize claude_args as a shell string; deliver sys…",
"author_name": "jean-noe",
"author_login": "kooljo",
"committed_at": "2026-05-21T11:26:49Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "496b9e26674adcd3a4038ae501af78f1c1dae041",
"body": null,
"is_bot": false,
"headline": "release: v0.13.1",
"author_name": "jean-noe",
"author_login": "kooljo",
"committed_at": "2026-05-20T23:49:20Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "5042742647f2bb263bc715b7b721e377261740f5",
"body": "* fix: add id-token: write to run-agent-claude-code jobs in all four templates\n\nanthropics/claude-code-action@v1 unconditionally calls core.getIDToken()\nduring setupGitHubToken. When a job has an explicit permissions: block that\nomits id-token, GitHub Actions denies the OIDC fetch and every consumer\n[…]\ns\n\n---------\n\nCo-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>\nCo-authored-by: jean-noe <jean-noe@users.noreply.github.com>\nCo-authored-by: jean-noe <kollojeannoe@gmail.com>",
"is_bot": false,
"headline": "fix: add id-token: write to claude-code workflow templates (#353) (#357)",
"author_name": "jean-noe",
"author_login": "jean-noe",
"committed_at": "2026-05-20T23:35:11Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "ab33a5ef44d73fafe169b9c3cb9019e23a7453da",
"body": "…ED_PROMPTS_DIR (#356)\n\n* fix(cc-prepare): ship bundled prompts with action and set FERRY_BUNDLED_PROMPTS_DIR\n\nThe ferry-cc-prepare action claimed to be \"self-contained; no .ferry/ needed\"\nbut failed with ENOENT on the bundled prompt files because:\n\n1. build-ferry-actions.mjs copied prompts to ferry\n[…]\ned-by: jean-noe <jean-noe@users.noreply.github.com>\n\n---------\n\nCo-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>\nCo-authored-by: jean-noe <jean-noe@users.noreply.github.com>",
"is_bot": false,
"headline": "fix(cc-prepare): ship bundled prompts with action and set FERRY_BUNDL…",
"author_name": "jean-noe",
"author_login": "jean-noe",
"committed_at": "2026-05-20T23:16:35Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "2eb98f09f4ef2834ce1ef783ec8757e547518146",
"body": "…s on claude-code path (#358)\n\n* fix(cc-prepare): add narrow Write(.ferry/cc-output.json) grant for read-only roles\n\nRefiner and reviewer agents on the claude-code path need to write their\nstructured result to .ferry/cc-output.json, but ROLE_ACCESS='read-only'\npreviously restricted --allowedTools to\n[…]\ned-by: jean-noe <jean-noe@users.noreply.github.com>\n\n---------\n\nCo-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>\nCo-authored-by: jean-noe <jean-noe@users.noreply.github.com>",
"is_bot": false,
"headline": "fix: add narrow Write(.ferry/cc-output.json) grant for read-only role…",
"author_name": "jean-noe",
"author_login": "jean-noe",
"committed_at": "2026-05-20T22:58:06Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "314f8e9a821efdcd39232151013aeb9209d6c45f",
"body": "…4/10)\n\nRefreshes docs/PRODUCTION-READINESS-AUDIT.md to reflect the v0.8.2 → v0.13.0\nwindow (8 releases). Overall score moves 8.2 → 8.4 (net +0.2).\n\nMovement:\n- Tests +0.5 (1200 → 2232 tests across 100 → 152 files)\n- CI/CD +0.5 (CodeQL fail-on-high/critical gate, gitlab-adapter job)\n- Consumer docs \n[…]\n finding tracked: SHA-pin the two repo-development helper workflows\nto match the project standard. Carry-overs unchanged (harden-runner egress\nallowlist, action 0d drift gate, e2e idempotency replay).",
"is_bot": false,
"headline": "docs(audit): refresh production-readiness audit for v0.13.0 (score 8.…",
"author_name": "jean-noe",
"author_login": "kooljo",
"committed_at": "2026-05-20T22:17:52Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "9f8c564a778a233972018542266df252b581df50",
"body": null,
"is_bot": false,
"headline": "release: v0.13.0",
"author_name": "jean-noe",
"author_login": "kooljo",
"committed_at": "2026-05-20T21:43:51Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "d881a439445978ec452396ccee88dbef68901563",
"body": "…er/reviewer/iterator (closes #350) (#351)\n\n* feat(cc-prepare): complete role coverage for developer/reviewer/iterator (closes #350)\n\nThe ferry-cc-prepare composite entrypoint now dispatches into a per-role\nupstream-resolver for all four agents. Previously only the refiner role\nran end-to-end; the o\n[…]\ns soft-fail divergence) and 351-6 (test\nmock-architecture refactor) deferred — surfaced as needs-decision\nin the fix-train status comment.\n\n---------\n\nCo-authored-by: jean-noe <kollojeannoe@gmail.com>",
"is_bot": false,
"headline": "feat(cc-prepare): complete ferry-cc-prepare role coverage for develop…",
"author_name": "jean-noe",
"author_login": "jean-noe",
"committed_at": "2026-05-20T21:22:25Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "e2366d49943d285c022acfb653b90a7fa51181b6",
"body": "…dev/review/iterate fail-loud scaffold (refs #333) (#348)\n\n* feat(cc-wiring): wire claude-code-action four-step chain in workflows + templates (closes #333)\n\nReplace the fail-loud placeholder in every run-agent-claude-code job with the\nreal chain: checkout → ferry-cc-prepare → anthropics/claude-code\n[…]\n✅\n\n---------\n\nCo-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>\nCo-authored-by: jean-noe <jean-noe@users.noreply.github.com>\nCo-authored-by: jean-noe <kollojeannoe@gmail.com>",
"is_bot": false,
"headline": "feat(cc-wiring): wire claude-code-action chain — refiner end-to-end, …",
"author_name": "jean-noe",
"author_login": "jean-noe",
"committed_at": "2026-05-20T17:28:13Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "e555a27fc3fad831f988d41272ea4e9e3d494fdf",
"body": "…s (#303) (#349)\n\nWire the three no-auto-merge hardening primitives that previously had zero\ncallers into the claude-code execution path (ADR-0002 §accepted-divergences\npoints 3 & 4, ADR-0006 §5, #303).\n\n**tool-policy** (`claude-args.ts`):\n- Import `assertToolPolicyEnforcesNoAutoMerge` + `NO_AUTO_ME\n[…]\nrmissions checks; new §6 and §7 describe blocks.\n\nCloses #335.\n\nCo-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>\nCo-authored-by: jean-noe <jean-noe@users.noreply.github.com>",
"is_bot": false,
"headline": "feat(hardening): wire secret-scan-gate + tool-policy + job-permission…",
"author_name": "jean-noe",
"author_login": "jean-noe",
"committed_at": "2026-05-20T14:06:45Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "99ccd97efe045d0c167c929848c3645ff39db982",
"body": "… closes #331) (#347)\n\n* feat(cc-prepare): add ferry-cc-prepare composite action (ADR-0006 §2, #331)\n\nFront-half loader for the claude-code execution path. Runs BEFORE\n`anthropics/claude-code-action@v1` in the consumer workflow: reads the\nenvelope + ferry config + Jira issue, calls the per-role prep\n[…]\nL2: strict-proxy InMemoryTracker so non-getIssue calls throw\n- L3: refusal tests for developer/reviewer/iterator roles asserting #333 hint\n\n---------\n\nCo-authored-by: jean-noe <kollojeannoe@gmail.com>",
"is_bot": false,
"headline": "feat(cc-prepare): add ferry-cc-prepare composite action (ADR-0006 §2,…",
"author_name": "jean-noe",
"author_login": "jean-noe",
"committed_at": "2026-05-20T13:26:35Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "e715f75ebbf4f731964b04a6013882005bc8ea71",
"body": "…#328) (#346)\n\nREADME.md is reduced from 548 → 79 lines / ~30KB → 2.2KB, matching the\nclaude-code brevity standard. All removed content is preserved in new docs:\n\n- docs/INSTALL.md — full install walkthrough (steps 1–4, SHA pinning, smoke\n test, ops setup, checklist)\n- docs/OVER\n[…]\nor all install-guide acceptance criteria. All 2088 tests pass.\n\nCo-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>\nCo-authored-by: jean-noe <jean-noe@users.noreply.github.com>",
"is_bot": false,
"headline": "docs(readme): trim README to 79 lines, move content to docs/ (closes …",
"author_name": "jean-noe",
"author_login": "jean-noe",
"committed_at": "2026-05-20T12:35:33Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "d4df635381bf08d801e991ef3192eaf0c3206ce2",
"body": "…secret flow (#343)\n\n* feat(uninstall): remove new composite dirs and add interactive OAuth secret flow\n\n- Add `FERRY_COMPOSITE_DIRS` constant and `detectCompositeActions` / `removeCompositeActions`\n to detect and delete `.github/actions/ferry-route/`, `ferry-cc-prepare/`, `ferry-cc-apply/`\n as pa\n[…]\n.\n\n---------\n\nCo-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>\nCo-authored-by: jean-noe <jean-noe@users.noreply.github.com>\nCo-authored-by: jean-noe <kollojeannoe@gmail.com>",
"is_bot": false,
"headline": "feat(uninstall): remove new composite dirs and add interactive OAuth …",
"author_name": "jean-noe",
"author_login": "jean-noe",
"committed_at": "2026-05-20T11:18:17Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "e7e5eda99983f7e0c34957e7f948f98c1f92265b",
"body": "…2) (#344)\n\n* feat(cc-apply): add ferry-cc-apply composite action (ADR-0006 §2, #332)\n\nImplements the deterministic post-step for the claude-code execution path.\nReads .ferry/cc-output.json, validates fail-closed via AJV (NFR-S1), then\napplies Jira-side audit + transition writes (FR18/FR24/FR28) via\n[…]\n.\n\n---------\n\nCo-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>\nCo-authored-by: jean-noe <jean-noe@users.noreply.github.com>\nCo-authored-by: jean-noe <kollojeannoe@gmail.com>",
"is_bot": false,
"headline": "feat(cc-apply): add ferry-cc-apply composite action (ADR-0006 §2, #33…",
"author_name": "jean-noe",
"author_login": "jean-noe",
"committed_at": "2026-05-20T11:18:03Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "e5e8b1c39296c6d0bff6fe17d177104a202f4397",
"body": "… functions (closes #330) (#345)\n\n* refactor(agent-runtime): extract per-role pre-loop setup into prepare functions (closes #330)\n\nEach agent today executes 60-100+ lines of stateful setup before\n`createAgentLoop`/`runReviewLoop`: Jira fetch, `buildSystem(<role>)`,\n`initialPrompt` builder, MCP capab\n[…]\nn tests in\n iterator-prepare.test.ts and developer-prepare.test.ts covering the\n hasLabelsConfig=true branch (the filtered subset path).\n\n---------\n\nCo-authored-by: jean-noe <kollojeannoe@gmail.com>",
"is_bot": false,
"headline": "refactor(agent-runtime): extract per-role pre-loop setup into prepare…",
"author_name": "jean-noe",
"author_login": "jean-noe",
"committed_at": "2026-05-20T11:17:43Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "897cbdbea321bcbcda3dd3bd37d084d335893db2",
"body": "…ider gate, workflow shape (#342)\n\nImplements three new `ferry-doctor` checks in `claude-code-path.ts` for\nconsumers using `execution_path: claude-code` (issue #336):\n\n- **CC path: token exclusivity** — red when `CLAUDE_CODE_OAUTH_TOKEN` is\n absent as a repo secret; yellow when `ANTHROPIC_API_KEY` \n[…]\ne-positive behaviour for v0.12.x repos (acceptance criterion).\n\nCo-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>\nCo-authored-by: jean-noe <jean-noe@users.noreply.github.com>",
"is_bot": false,
"headline": "feat(doctor): add claude-code path checks for token exclusivity, prov…",
"author_name": "jean-noe",
"author_login": "jean-noe",
"committed_at": "2026-05-20T09:46:32Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "f68ff7798da9a61c5b967f809be5bb5bd9ad64fc",
"body": "…ses #329) (#341)\n\n* feat(routing): enforce anthropicOnly as hard gate in resolveExecutionPath (issue #329)\n\nAdd a provider gate (step 2 in resolution order) that returns\n{ path: 'script', reason: 'provider-gate' } when anthropicOnly === false,\nbefore the per-ticket label override is consulted. This\n[…]\ned-by: jean-noe <jean-noe@users.noreply.github.com>\n\n---------\n\nCo-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>\nCo-authored-by: jean-noe <jean-noe@users.noreply.github.com>",
"is_bot": false,
"headline": "feat: enforce anthropicOnly as hard gate in resolveExecutionPath (clo…",
"author_name": "jean-noe",
"author_login": "jean-noe",
"committed_at": "2026-05-20T09:46:10Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "03e38810ec092a9ed67ec68ccede2b72358b8f3f",
"body": "….12.x → v0.13.0 (#340)\n\nActivates the credential gate for the v0.12.x → v0.13.0 transition:\n- `ferry-update --dry-run` now reports the missing secret when running\n from any v0.12.x base\n- Interactive `ferry-update` prompts for the token and sets it on the\n repo; non-interactive stays on the scrip\n[…]\nt-out\n\nCloses #334. Refs ADR-0006 §7, decisions/0002 §G, #316.\n\nCo-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>\nCo-authored-by: jean-noe <jean-noe@users.noreply.github.com>",
"is_bot": false,
"headline": "feat(migrations): add requires-secrets: CLAUDE_CODE_OAUTH_TOKEN to v0…",
"author_name": "jean-noe",
"author_login": "jean-noe",
"committed_at": "2026-05-20T09:45:50Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "c61049f9a2c93c58f46071a378edf582126327ce",
"body": "…ADR-0006 §3) (#327)\n\nAdds the routing decision step that the existing claude-code-path foundation\n(closed #300, #301, #302) was missing a workflow hook into. Until now, the\npure `resolveExecutionPath` resolver and `buildClaudeCodeJob` library had no\ncaller — no workflow ran them, so the path stayed\n[…]\nually flowing into a\nrunning workflow rather than living only in a unit-tested library.\n\nRefs ADR-0006 §3, ADR-0002 §wiring, closed #300, #301, #302.\n\nCo-authored-by: jean-noe <kollojeannoe@gmail.com>",
"is_bot": false,
"headline": "feat(routing): wire execution-path decision into consumer workflows (…",
"author_name": "jean-noe",
"author_login": "jean-noe",
"committed_at": "2026-05-20T01:07:59Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "be788b24986e12be228c4da5fa2a5703011e0e9a",
"body": null,
"is_bot": false,
"headline": "release: v0.12.0",
"author_name": "jean-noe",
"author_login": "kooljo",
"committed_at": "2026-05-20T00:22:11Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "c2ebaa07815773bb4e430b02978125022cd98aed",
"body": "…of #319) (#326)\n\n* docs(mcp): add Phase 0 reconnaissance for GitHub, Atlassian, Figma, Prismic MCP servers\n\nRead-only research output for epic #319 Phase 0 (#320). Documents per-server\nfindings on remote HTTP/SSE endpoint availability, headless authentication\nviability for GitHub Actions runners, a\n[…]\n cross-reference pointer to advertise the\n Atlassian example (not the removed Figma one).\n\nAddresses the review-train blocker on this PR.\n\n---------\n\nCo-authored-by: jean-noe <kollojeannoe@gmail.com>",
"is_bot": false,
"headline": "docs(mcp): document GitHub, Atlassian, Prismic; defer Figma (Phase 1 …",
"author_name": "jean-noe",
"author_login": "jean-noe",
"committed_at": "2026-05-20T00:12:15Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "e13249857519dd7b33e3caa5d46698cf1fad178b",
"body": "…ping (closes #302) (#314)\n\n* feat(claude-code): action job + prompt reuse + per-agent tool/MCP mapping (closes #302)\n\nStandalone, fully unit-tested mapping library for the claude-code-action\nexecution path (ADR-0006 / decisions/0002 §C). Pure and deterministic;\nconsumed later by the contract wrappe\n[…]\ntes cost_estimate against the strict RefinerCostEstimate shape so the\nclaude-code path cannot silently accept payloads the script path rejects.\n\n---------\n\nCo-authored-by: jnk <kollojeannoe@gmail.com>",
"is_bot": false,
"headline": "feat(claude-code): action job + prompt reuse + per-agent tool/MCP map…",
"author_name": "jean-noe",
"author_login": "jean-noe",
"committed_at": "2026-05-20T00:05:33Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "c71a3a41fe18bc903e8d7315da77252d8685b339",
"body": "…code contract decision (#301) (#313)\n\nAdds three explanatory comment blocks to `src/lib/cc-wrappers/contract.ts`\ncodifying the path divergences from the bundled-script implementation:\n\n- developer case (L141): the script's force/type-override `overrideNote`\n suffix (`dev-action.ts:526-534`) is int\n[…]\nation (validator, decision\nfunction, idempotency-gated apply, schema) shipped in #315; this PR\ncontributes only the inline documentation that makes those accepted\ndivergences auditable in code review.",
"is_bot": false,
"headline": "docs(cc-wrappers): document accepted-divergence invariants in claude-…",
"author_name": "jean-noe",
"author_login": "jean-noe",
"committed_at": "2026-05-20T00:05:15Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "fd449f93074336cbfebfd6f27ecb798e7dba902d",
"body": "* chore(deps): bump @anthropic-ai/sdk from 0.95.2 to 0.97.0\n\nBumps [@anthropic-ai/sdk](https://github.com/anthropics/anthropic-sdk-typescript) from 0.95.2 to 0.97.0.\n- [Release notes](https://github.com/anthropics/anthropic-sdk-typescript/releases)\n- [Changelog](https://github.com/anthropics/anthrop\n[…]\ngithub.com>\nCo-authored-by: jnk <jeannoe.kollo@big-emotion.com>\nCo-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>\nCo-authored-by: jean-noe <jean-noe@users.noreply.github.com>",
"is_bot": true,
"headline": "chore(deps): bump @anthropic-ai/sdk from 0.95.2 to 0.97.0 (#296)",
"author_name": "dependabot[bot]",
"author_login": "dependabot[bot]",
"committed_at": "2026-05-19T23:08:25Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "6dd63ed2043a679a3a581dff92ba4060cb1354a5",
"body": "Bumps [@google/genai](https://github.com/googleapis/js-genai) from 2.0.1 to 2.4.0.\n- [Release notes](https://github.com/googleapis/js-genai/releases)\n- [Changelog](https://github.com/googleapis/js-genai/blob/main/CHANGELOG.md)\n- [Commits](https://github.com/googleapis/js-genai/compare/v2.0.1...v2.4.\n[…]\nirect:production\n update-type: version-update:semver-minor\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>",
"is_bot": true,
"headline": "chore(deps): bump @google/genai from 2.0.1 to 2.4.0 (#295)",
"author_name": "dependabot[bot]",
"author_login": "dependabot[bot]",
"committed_at": "2026-05-19T23:08:05Z",
"body_truncated": true,
"is_coding_agent": false
}
],
"releases_count": 37,
"commits_last_year": 587,
"latest_release_at": "2026-07-21T16:16:33Z",
"latest_release_tag": "v1.2.0",
"releases_from_tags": false,
"days_since_last_push": 1,
"active_weeks_last_year": 8,
"days_since_latest_release": 8,
"mean_days_between_releases": 0.4
},
"community": {
"has_readme": true,
"has_license": true,
"has_description": true,
"has_contributing": true,
"health_percentage": 62,
"has_issue_template": false,
"has_code_of_conduct": false,
"has_pull_request_template": false
},
"ecosystem": {
"packages": [
{
"name": "@big-emotion/ferry",
"exists": true,
"license": "MIT",
"keywords": [
"ferry",
"github-actions",
"jira",
"cli",
"automation"
],
"ecosystem": "npm",
"matches_repo": true,
"registry_url": "https://www.npmjs.com/package/@big-emotion/ferry",
"is_deprecated": false,
"latest_version": "1.2.0",
"repository_url": "https://github.com/big-emotion/ferry",
"versions_count": 37,
"total_downloads": null,
"dependents_count": null,
"deprecation_note": null,
"maintainers_count": 1,
"monthly_downloads": 2473,
"first_published_at": "2026-05-01T15:32:13.782000Z",
"latest_published_at": "2026-07-21T16:16:32.331000Z",
"latest_version_yanked": null,
"days_since_latest_publish": 8
}
]
},
"popularity": {
"forks": 1,
"stars": 3,
"watchers": 0,
"fork_history": {
"days": [
{
"date": "2026-04-27",
"count": 1
}
],
"complete": true,
"collected": 1,
"total_forks": 1
},
"star_history": null,
"open_issues_and_prs": 16
},
"ai_readiness": {
"has_nix": false,
"example_dirs": [
"example",
"examples"
],
"has_llms_txt": false,
"has_dockerfile": false,
"has_mcp_signal": true,
"bootstrap_files": [],
"api_schema_files": [
".ferry/node_modules/protobufjs/google/api/annotations.proto",
".ferry/node_modules/protobufjs/google/api/http.proto",
".ferry/node_modules/protobufjs/google/protobuf/api.proto",
".ferry/node_modules/protobufjs/google/protobuf/descriptor.proto",
".ferry/node_modules/protobufjs/google/protobuf/source_context.proto",
".ferry/node_modules/protobufjs/google/protobuf/type.proto",
".github/actions/ferry-run-developer/node_modules/protobufjs/google/api/annotations.proto",
".github/actions/ferry-run-developer/node_modules/protobufjs/google/api/http.proto",
".github/actions/ferry-run-developer/node_modules/protobufjs/google/protobuf/api.proto",
".github/actions/ferry-run-developer/node_modules/protobufjs/google/protobuf/descriptor.proto",
".github/actions/ferry-run-developer/node_modules/protobufjs/google/protobuf/source_context.proto",
".github/actions/ferry-run-developer/node_modules/protobufjs/google/protobuf/type.proto",
".github/actions/ferry-run-iterator/node_modules/protobufjs/google/api/annotations.proto",
".github/actions/ferry-run-iterator/node_modules/protobufjs/google/api/http.proto",
".github/actions/ferry-run-iterator/node_modules/protobufjs/google/protobuf/api.proto",
".github/actions/ferry-run-iterator/node_modules/protobufjs/google/protobuf/descriptor.proto",
".github/actions/ferry-run-iterator/node_modules/protobufjs/google/protobuf/source_context.proto",
".github/actions/ferry-run-iterator/node_modules/protobufjs/google/protobuf/type.proto",
".github/actions/ferry-run-merger/node_modules/protobufjs/google/api/annotations.proto",
".github/actions/ferry-run-merger/node_modules/protobufjs/google/api/http.proto",
".github/actions/ferry-run-merger/node_modules/protobufjs/google/protobuf/api.proto",
".github/actions/ferry-run-merger/node_modules/protobufjs/google/protobuf/descriptor.proto",
".github/actions/ferry-run-merger/node_modules/protobufjs/google/protobuf/source_context.proto",
".github/actions/ferry-run-merger/node_modules/protobufjs/google/protobuf/type.proto",
".github/actions/ferry-run-refiner/node_modules/protobufjs/google/api/annotations.proto",
".github/actions/ferry-run-refiner/node_modules/protobufjs/google/api/http.proto",
".github/actions/ferry-run-refiner/node_modules/protobufjs/google/protobuf/api.proto",
".github/actions/ferry-run-refiner/node_modules/protobufjs/google/protobuf/descriptor.proto",
".github/actions/ferry-run-refiner/node_modules/protobufjs/google/protobuf/source_context.proto",
".github/actions/ferry-run-refiner/node_modules/protobufjs/google/protobuf/type.proto",
".github/actions/ferry-run-reviewer/node_modules/protobufjs/google/api/annotations.proto",
".github/actions/ferry-run-reviewer/node_modules/protobufjs/google/api/http.proto",
".github/actions/ferry-run-reviewer/node_modules/protobufjs/google/protobuf/api.proto",
".github/actions/ferry-run-reviewer/node_modules/protobufjs/google/protobuf/descriptor.proto",
".github/actions/ferry-run-reviewer/node_modules/protobufjs/google/protobuf/source_context.proto",
".github/actions/ferry-run-reviewer/node_modules/protobufjs/google/protobuf/type.proto"
],
"has_devcontainer": false,
"typecheck_configs": [
".ferry/node_modules/@anthropic-ai/sdk/src/tsconfig.json",
".ferry/node_modules/@stablelib/base64/tsconfig.json",
".ferry/node_modules/fast-uri/tsconfig.json",
".ferry/node_modules/json-with-bigint/tsconfig.json",
".ferry/node_modules/openai/src/tsconfig.json",
".ferry/node_modules/protobufjs/tsconfig.json",
".github/actions/ferry-emit-audit/node_modules/json-with-bigint/tsconfig.json",
".github/actions/ferry-envelope-validate/node_modules/fast-uri/tsconfig.json",
".github/actions/ferry-run-developer/node_modules/@anthropic-ai/sdk/src/tsconfig.json",
".github/actions/ferry-run-developer/node_modules/@stablelib/base64/tsconfig.json",
".github/actions/ferry-run-developer/node_modules/fast-uri/tsconfig.json",
".github/actions/ferry-run-developer/node_modules/openai/src/tsconfig.json",
".github/actions/ferry-run-developer/node_modules/protobufjs/tsconfig.json",
".github/actions/ferry-run-iterator/node_modules/@anthropic-ai/sdk/src/tsconfig.json",
".github/actions/ferry-run-iterator/node_modules/@stablelib/base64/tsconfig.json",
".github/actions/ferry-run-iterator/node_modules/fast-uri/tsconfig.json",
".github/actions/ferry-run-iterator/node_modules/openai/src/tsconfig.json",
".github/actions/ferry-run-iterator/node_modules/protobufjs/tsconfig.json",
".github/actions/ferry-run-merger/node_modules/@anthropic-ai/sdk/src/tsconfig.json",
".github/actions/ferry-run-merger/node_modules/@stablelib/base64/tsconfig.json",
".github/actions/ferry-run-merger/node_modules/fast-uri/tsconfig.json",
".github/actions/ferry-run-merger/node_modules/openai/src/tsconfig.json",
".github/actions/ferry-run-merger/node_modules/protobufjs/tsconfig.json",
".github/actions/ferry-run-refiner/node_modules/@anthropic-ai/sdk/src/tsconfig.json",
".github/actions/ferry-run-refiner/node_modules/@stablelib/base64/tsconfig.json",
".github/actions/ferry-run-refiner/node_modules/fast-uri/tsconfig.json",
".github/actions/ferry-run-refiner/node_modules/openai/src/tsconfig.json",
".github/actions/ferry-run-refiner/node_modules/protobufjs/tsconfig.json",
".github/actions/ferry-run-reviewer/node_modules/@anthropic-ai/sdk/src/tsconfig.json",
".github/actions/ferry-run-reviewer/node_modules/@stablelib/base64/tsconfig.json",
".github/actions/ferry-run-reviewer/node_modules/fast-uri/tsconfig.json",
".github/actions/ferry-run-reviewer/node_modules/openai/src/tsconfig.json",
".github/actions/ferry-run-reviewer/node_modules/protobufjs/tsconfig.json",
"tsconfig.json"
],
"toolchain_manifests": [],
"largest_source_bytes": 406037,
"source_files_sampled": 404,
"oversized_source_files": 14,
"agent_instruction_files": [
".claude-pr/CLAUDE.md",
".github/copilot-instructions.md",
"CLAUDE.md"
],
"agent_instruction_max_bytes": 12620
},
"dependencies": {
"manifests": [
".ferry/package.json",
"package.json"
],
"advisories": {
"error": null,
"scope": "published_package",
"source": "osv",
"findings": [],
"collected": true,
"malicious": [],
"truncated": false,
"by_severity": {},
"advisory_count": 0,
"affected_count": 0,
"assessed_count": 159,
"malicious_count": 0,
"assessed_package": "npm:@big-emotion/ferry@1.2.0",
"unassessed_count": 0,
"direct_affected_count": 0
},
"ecosystems": [
"npm"
],
"dependencies": [
{
"name": "ajv",
"manifest": ".ferry/package.json",
"ecosystem": "npm",
"version_constraint": "^8.0.0"
},
{
"name": "ajv-formats",
"manifest": ".ferry/package.json",
"ecosystem": "npm",
"version_constraint": "^3.0.1"
},
{
"name": "@octokit/rest",
"manifest": ".ferry/package.json",
"ecosystem": "npm",
"version_constraint": "^22.0.1"
},
{
"name": "@anthropic-ai/sdk",
"manifest": ".ferry/package.json",
"ecosystem": "npm",
"version_constraint": "^0.97.0"
},
{
"name": "@google/genai",
"manifest": ".ferry/package.json",
"ecosystem": "npm",
"version_constraint": "^2.0.1"
},
{
"name": "openai",
"manifest": ".ferry/package.json",
"ecosystem": "npm",
"version_constraint": "^6.34.0"
},
{
"name": "yaml",
"manifest": ".ferry/package.json",
"ecosystem": "npm",
"version_constraint": "^2.6.0"
},
{
"name": "@anthropic-ai/sdk",
"manifest": "package.json",
"ecosystem": "npm",
"version_constraint": "^0.97.0"
},
{
"name": "@google/genai",
"manifest": "package.json",
"ecosystem": "npm",
"version_constraint": "^2.0.1"
},
{
"name": "@modelcontextprotocol/sdk",
"manifest": "package.json",
"ecosystem": "npm",
"version_constraint": "^1.29.0"
},
{
"name": "@octokit/rest",
"manifest": "package.json",
"ecosystem": "npm",
"version_constraint": "^22.0.1"
},
{
"name": "ajv",
"manifest": "package.json",
"ecosystem": "npm",
"version_constraint": "^8.0.0"
},
{
"name": "ajv-formats",
"manifest": "package.json",
"ecosystem": "npm",
"version_constraint": "^3.0.1"
},
{
"name": "openai",
"manifest": "package.json",
"ecosystem": "npm",
"version_constraint": "^6.34.0"
},
{
"name": "ulid",
"manifest": "package.json",
"ecosystem": "npm",
"version_constraint": "^3.0.2"
},
{
"name": "yaml",
"manifest": "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": 10,
"merged_prs": 223,
"open_issues": 6,
"closed_ratio": 0.968,
"closed_issues": 179,
"closed_unmerged_prs": 16
},
"bus_factor": 1,
"bot_contributors": 2,
"top_contributors": [
{
"type": "User",
"login": "jean-noe",
"commits": 259,
"avatar_url": "https://avatars.githubusercontent.com/u/206253650?v=4"
},
{
"type": "User",
"login": "kooljo",
"commits": 221,
"avatar_url": "https://avatars.githubusercontent.com/u/17022476?v=4"
}
],
"contributors_sampled": 2,
"top_contributor_share": 0.54
},
"quality_signals": {
"has_ci": true,
"has_tests": true,
"ci_workflows": [
"claude-code-review.yml",
"claude.yml",
"codeql.yml",
"ferry-ci.yml",
"ferry-router.yml",
"release.yml"
],
"has_docs_dir": true,
"linter_configs": [
".eslintrc",
".eslintrc.js",
".eslintrc.yml",
"eslint.config.js"
],
"has_editorconfig": true,
"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": 5,
"reason": "branch protection is not maximal on development and all release branches",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
},
{
"name": "CI-Tests",
"score": 10,
"reason": "5 out of 5 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 0/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": 10,
"reason": "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": 10,
"reason": "30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10",
"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": 6,
"reason": "dependency not pinned by hash detected -- score normalized to 6",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
},
{
"name": "SAST",
"score": 10,
"reason": "SAST tool is run on all commits",
"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": 7,
"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": "15 existing vulnerabilities detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
}
],
"commit": "c1138acb2407c1846fbc25544e6967a208a9655f",
"ran_at": "2026-07-30T05:54:56Z",
"aggregate_score": 6.1,
"scorecard_version": "v5.5.0"
},
"has_codeql_workflow": true,
"has_security_policy": false,
"has_dependabot_config": true
},
"contribution_flow": {
"collected": true,
"ci_last_run_at": "2026-07-28T19:06:41Z",
"oldest_open_prs": [
{
"number": 414,
"created_at": "2026-06-15T22:36:31Z",
"last_comment_at": null,
"last_comment_author": null
},
{
"number": 416,
"created_at": "2026-06-15T22:36:49Z",
"last_comment_at": null,
"last_comment_author": null
},
{
"number": 417,
"created_at": "2026-06-22T22:34:52Z",
"last_comment_at": null,
"last_comment_author": null
},
{
"number": 418,
"created_at": "2026-06-22T22:35:16Z",
"last_comment_at": null,
"last_comment_author": null
},
{
"number": 419,
"created_at": "2026-06-22T22:35:37Z",
"last_comment_at": null,
"last_comment_author": null
},
{
"number": 421,
"created_at": "2026-07-13T22:36:18Z",
"last_comment_at": null,
"last_comment_author": null
},
{
"number": 430,
"created_at": "2026-07-20T22:35:21Z",
"last_comment_at": null,
"last_comment_author": null
},
{
"number": 432,
"created_at": "2026-07-22T14:59:43Z",
"last_comment_at": null,
"last_comment_author": null
},
{
"number": 433,
"created_at": "2026-07-22T15:26:20Z",
"last_comment_at": null,
"last_comment_author": null
},
{
"number": 434,
"created_at": "2026-07-28T19:03:47Z",
"last_comment_at": null,
"last_comment_author": null
}
],
"last_merged_pr_at": "2026-05-13T20:44:41Z",
"ci_last_conclusion": "SUCCESS",
"oldest_open_issues": [
{
"number": 293,
"created_at": "2026-05-15T21:08:18Z",
"last_comment_at": null,
"last_comment_author": null
},
{
"number": 324,
"created_at": "2026-05-19T23:23:05Z",
"last_comment_at": "2026-06-07T10:50:49Z",
"last_comment_author": "claude"
},
{
"number": 325,
"created_at": "2026-05-19T23:35:25Z",
"last_comment_at": null,
"last_comment_author": null
},
{
"number": 404,
"created_at": "2026-06-12T23:20:46Z",
"last_comment_at": "2026-06-12T23:42:41Z",
"last_comment_author": "jean-noe"
},
{
"number": 405,
"created_at": "2026-06-12T23:22:53Z",
"last_comment_at": "2026-06-12T23:40:43Z",
"last_comment_author": "jean-noe"
},
{
"number": 425,
"created_at": "2026-07-18T06:56:15Z",
"last_comment_at": "2026-07-28T18:49:15Z",
"last_comment_author": "github-actions"
}
]
}
},
"config": {
"disabled_metrics": [],
"disabled_categories": [],
"disabled_components": {}
},
"source": {
"url": "https://github.com/big-emotion/ferry",
"host": "github.com",
"name": "ferry",
"owner": "big-emotion"
},
"metrics": {
"overall": {
"key": "overall",
"band": "moderate",
"name": "Overall health",
"note": null,
"notes": [],
"value": 68,
"inputs": {
"security": 69,
"vitality": 82,
"community": 40,
"governance": 57,
"engineering": 88
},
"components": []
},
"categories": [
{
"key": "vitality",
"band": "good",
"name": "Vitality",
"value": 82,
"weight": 0.22,
"metrics": [
{
"key": "development_activity",
"band": "good",
"name": "Development activity",
"note": null,
"notes": [],
"value": 70,
"inputs": {
"commits_last_year": 587,
"human_commit_share": 0.91,
"days_since_last_push": 1,
"active_weeks_last_year": 8
},
"components": [
{
"key": "push_recency",
"name": "Push recency",
"detail": "last push 1 days ago",
"points": 36,
"status": "met",
"details": [
{
"code": "push_recency",
"params": {
"days": 1
}
}
],
"max_points": 36
},
{
"key": "commit_cadence",
"name": "Commit cadence",
"detail": "8/52 weeks with commits",
"points": 5.5,
"status": "partial",
"details": [
{
"code": "commit_cadence_weeks",
"params": {
"weeks": 8
}
}
],
"max_points": 36
},
{
"key": "commit_volume",
"name": "Commit volume",
"detail": "587 commits in the last year",
"points": 18,
"status": "met",
"details": [
{
"code": "commits_last_year",
"params": {
"count": 587
}
}
],
"max_points": 18
},
{
"key": "openssf_scorecard_maintained",
"name": "OpenSSF Scorecard: Maintained",
"detail": "30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10",
"points": 10,
"status": "met",
"details": [],
"max_points": 10
}
]
},
{
"key": "release_discipline",
"band": "excellent",
"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": 100,
"inputs": {
"releases_count": 37,
"latest_release_tag": "v1.2.0",
"releases_from_tags": false,
"days_since_latest_release": 8,
"mean_days_between_releases": 0.4
},
"components": [
{
"key": "ships_releases",
"name": "Ships releases",
"detail": "37 releases published",
"points": 27,
"status": "met",
"details": [
{
"code": "releases_published",
"params": {
"count": 37
}
}
],
"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": "a release every ~0.4 days",
"points": 27,
"status": "met",
"details": [
{
"code": "release_cadence",
"params": {
"gap": 0.4
}
}
],
"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": 5,
"inputs": {
"forks": 1,
"stars": 3,
"watchers": 0,
"growth_state": "unverified",
"growth_factor_pct": 100,
"growth_unverified_reason": "no_history"
},
"components": [
{
"key": "stars",
"name": "Stars",
"detail": "3 stars",
"points": 4.9,
"status": "partial",
"details": [
{
"code": "stars",
"params": {
"count": 3
}
}
],
"max_points": 60
},
{
"key": "forks",
"name": "Forks",
"detail": "1 forks",
"points": 0,
"status": "missed",
"details": [
{
"code": "forks",
"params": {
"count": 1
}
}
],
"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": 56,
"inputs": {
"packages": [
"@big-emotion/ferry"
],
"dependents": null,
"ecosystems": "npm",
"total_downloads": null,
"monthly_downloads": 2473
},
"components": [
{
"key": "monthly_downloads",
"name": "Monthly downloads",
"detail": "2,473 downloads/month across npm",
"points": 45.2,
"status": "partial",
"details": [
{
"code": "downloads_monthly",
"params": {
"count": 2473,
"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": 57,
"weight": 0.24,
"metrics": [
{
"key": "maintainer_resilience",
"band": "critical",
"name": "Maintainer resilience (bus factor)",
"note": null,
"notes": [],
"value": 22,
"inputs": {
"bus_factor": 1,
"contributors_sampled": 2,
"top_contributor_share": 0.54
},
"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 54% of commits",
"points": 10.3,
"status": "partial",
"details": [
{
"code": "top_contributor_share",
"params": {
"share": 54
}
}
],
"max_points": 22.5
},
{
"key": "contributor_breadth",
"name": "Contributor breadth",
"detail": "2 contributors",
"points": 2.7,
"status": "partial",
"details": [
{
"code": "contributors_sampled",
"params": {
"count": 2
}
}
],
"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": 81,
"inputs": {
"merged_prs": 223,
"open_issues": 6,
"closed_issues": 179,
"issue_closed_ratio": 0.968,
"closed_unmerged_prs": 16
},
"components": [
{
"key": "issue_resolution",
"name": "Issue resolution",
"detail": "97% of issues closed",
"points": 45.3,
"status": "partial",
"details": [
{
"code": "issues_closed_share",
"params": {
"share": 97
}
}
],
"max_points": 46.75
},
{
"key": "pr_acceptance",
"name": "PR acceptance",
"detail": "223/239 decided PRs merged",
"points": 35.7,
"status": "partial",
"details": [
{
"code": "decided_prs_merged",
"params": {
"merged": 223,
"decided": 239
}
}
],
"max_points": 38.25
},
{
"key": "openssf_scorecard_code_review",
"name": "OpenSSF Scorecard: Code-Review",
"detail": "Found 0/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": 41,
"inputs": {
"followers": 1,
"owner_type": "Organization",
"is_verified": null,
"owner_login": "big-emotion",
"public_repos": 6,
"account_age_days": 483
},
"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 big-emotion",
"points": 2.2,
"status": "partial",
"details": [
{
"code": "owner_followers",
"params": {
"count": 1,
"login": "big-emotion"
}
}
],
"max_points": 25
},
{
"key": "track_record",
"name": "Track record",
"detail": "6 public repos, account ~1 yr old",
"points": 8.8,
"status": "partial",
"details": [
{
"code": "public_repos",
"params": {
"count": 6
}
},
{
"code": "account_age_years",
"params": {
"years": 1
}
}
],
"max_points": 25
}
]
},
{
"key": "package_maintenance",
"band": "excellent",
"name": "Package maintenance",
"note": null,
"notes": [],
"value": 100,
"inputs": {
"packages": [
"@big-emotion/ferry"
],
"ecosystems": "npm",
"any_deprecated": false,
"min_days_since_publish": 8
},
"components": [
{
"key": "published_resolvable",
"name": "Published & resolvable",
"detail": "1 package(s) on npm",
"points": 25,
"status": "met",
"details": [
{
"code": "packages_published",
"params": {
"count": 1,
"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": "37 published versions",
"points": 20,
"status": "met",
"details": [
{
"code": "published_versions",
"params": {
"count": 37
}
}
],
"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": 88,
"weight": 0.2,
"metrics": [
{
"key": "engineering_practices",
"band": "excellent",
"name": "Engineering practices",
"note": null,
"notes": [],
"value": 90,
"inputs": {
"has_ci": true,
"has_tests": true,
"has_editorconfig": true,
"has_linter_config": true,
"has_precommit_config": false
},
"components": [
{
"key": "ci_workflows",
"name": "CI workflows",
"detail": "6 workflow(s)",
"points": 24,
"status": "met",
"details": [
{
"code": "ci_workflows",
"params": {
"count": 6
}
}
],
"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, .eslintrc.js, .eslintrc.yml, eslint.config.js",
"points": 16,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": ".eslintrc, .eslintrc.js, .eslintrc.yml, eslint.config.js"
}
}
],
"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": 6.4,
"status": "met",
"details": [],
"max_points": 6.4
},
{
"key": "openssf_scorecard_ci_tests",
"name": "OpenSSF Scorecard: CI-Tests",
"detail": "5 out of 5 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": 85,
"inputs": {
"topics": [
"automation",
"cli",
"ferry",
"github-actions",
"jira"
],
"has_wiki": true,
"homepage": null,
"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": null,
"points": 0,
"status": "missed",
"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": "5 topics",
"points": 10,
"status": "met",
"details": [
{
"code": "topics_count",
"params": {
"count": 5
}
}
],
"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": "moderate",
"name": "Security",
"value": 69,
"weight": 0.16,
"metrics": [
{
"key": "security_posture",
"band": "moderate",
"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": 61,
"inputs": {
"source": "openssf_scorecard",
"checks_evaluated": 17,
"scorecard_version": "v5.5.0",
"checks_inconclusive": 1,
"scorecard_aggregate": 6.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 is not maximal on development and all release branches",
"points": 3.8,
"status": "partial",
"details": [],
"max_points": 7.5
},
{
"key": "ci_tests",
"name": "CI-Tests",
"detail": "5 out of 5 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 0/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": "update tool detected",
"points": 7.5,
"status": "met",
"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": "30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10",
"points": 7.5,
"status": "met",
"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 6",
"points": 3,
"status": "partial",
"details": [],
"max_points": 5
},
{
"key": "sast",
"name": "SAST",
"detail": "SAST tool is run on all commits",
"points": 5,
"status": "met",
"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": 5.2,
"status": "partial",
"details": [],
"max_points": 7.5
},
{
"key": "vulnerabilities",
"name": "Vulnerabilities",
"detail": "15 existing vulnerabilities detected",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
}
]
},
{
"key": "dependency_advisories",
"band": "excellent",
"name": "Dependency advisories",
"note": "Excluded from scoring (no data or not applicable): No advisories left outstanding. Remaining weights renormalized. Matched the npm:@big-emotion/ferry@1.2.0 runtime dependency closure — what installing the published package pulls in — 159 packages. Reachability is not analyzed.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"no_advisories_left_outstanding"
]
}
},
{
"code": "weights_renormalized",
"params": {}
},
{
"code": "advisories_scope_published",
"params": {
"package": "npm:@big-emotion/ferry@1.2.0",
"assessed": 159
}
},
{
"code": "advisories_reachability",
"params": {}
}
],
"value": 100,
"inputs": {
"source": "osv",
"advisories": 0,
"affected_packages": 0,
"assessed_packages": 159,
"unassessed_packages": 0,
"affected_by_severity": "none",
"direct_affected_packages": 0
},
"components": [
{
"key": "direct_dependencies_free_of_known_advisories",
"name": "Direct dependencies free of known advisories",
"detail": "no direct dependency carries a known advisory",
"points": 35,
"status": "met",
"details": [
{
"code": "no_direct_advisories",
"params": {}
}
],
"max_points": 35
},
{
"key": "indirect_dependencies_free_of_known_advisories",
"name": "Indirect dependencies free of known advisories",
"detail": "no indirect dependency carries a known advisory",
"points": 25,
"status": "met",
"details": [
{
"code": "no_indirect_advisories",
"params": {}
}
],
"max_points": 25
},
{
"key": "no_advisories_left_outstanding",
"name": "No advisories left outstanding",
"detail": "no advisory carries a publication date",
"points": 0,
"status": "excluded",
"details": [
{
"code": "advisories_no_publication_date",
"params": {}
}
],
"max_points": 40
}
]
},
{
"key": "malicious_dependencies",
"band": "excellent",
"name": "Malicious dependencies",
"note": null,
"notes": [],
"value": 100,
"inputs": {
"source": "osv",
"meaning": "reported as a malicious package by the OpenSSF corpus; the remedy is removal or moving off the compromised name, never an upgrade of the same artifact. Versions the registry has since pulled are listed but not scored",
"packages": [],
"red_flag": false,
"assessed_packages": 159,
"malicious_packages": 0,
"direct_malicious_packages": 0,
"withdrawn_malicious_packages": 0,
"installable_malicious_packages": 0
},
"components": [
{
"key": "no_dependency_reported_as_a_malicious_package",
"name": "No dependency reported as a malicious package",
"detail": "no dependency is reported as a malicious package",
"points": 100,
"status": "met",
"details": [
{
"code": "no_malicious_dependencies",
"params": {}
}
],
"max_points": 100
}
]
},
{
"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": 2
},
"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": "excellent",
"name": "AI Readiness",
"value": 86,
"weight": 0,
"metrics": [
{
"key": "ai_agent_context",
"band": "excellent",
"name": "Agent context & guidance",
"note": null,
"notes": [],
"value": 85,
"inputs": {
"has_llms_txt": false,
"legible_history_share": 1,
"agent_instruction_files": [
".claude-pr/CLAUDE.md",
".github/copilot-instructions.md",
"CLAUDE.md"
],
"agent_instruction_max_bytes": 12620
},
"components": [
{
"key": "agent_instructions",
"name": "Agent instructions",
"detail": ".claude-pr/CLAUDE.md, .github/copilot-instructions.md, CLAUDE.md",
"points": 45,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": ".claude-pr/CLAUDE.md, .github/copilot-instructions.md, CLAUDE.md"
}
}
],
"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": "91 of 91 human commits state their intent (structured subject or explanatory body)",
"points": 40,
"status": "met",
"details": [
{
"code": "legible_history",
"params": {
"legible": 91,
"sampled": 91
}
}
],
"max_points": 40
}
]
},
{
"key": "ai_verify_loop",
"band": "good",
"name": "Verify loop (build / test / typecheck)",
"note": null,
"notes": [],
"value": 78,
"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": [
".ferry/node_modules/@anthropic-ai/sdk/src/tsconfig.json",
".ferry/node_modules/@stablelib/base64/tsconfig.json",
".ferry/node_modules/fast-uri/tsconfig.json",
".ferry/node_modules/json-with-bigint/tsconfig.json",
".ferry/node_modules/openai/src/tsconfig.json",
".ferry/node_modules/protobufjs/tsconfig.json",
".github/actions/ferry-emit-audit/node_modules/json-with-bigint/tsconfig.json",
".github/actions/ferry-envelope-validate/node_modules/fast-uri/tsconfig.json",
".github/actions/ferry-run-developer/node_modules/@anthropic-ai/sdk/src/tsconfig.json",
".github/actions/ferry-run-developer/node_modules/@stablelib/base64/tsconfig.json",
".github/actions/ferry-run-developer/node_modules/fast-uri/tsconfig.json",
".github/actions/ferry-run-developer/node_modules/openai/src/tsconfig.json",
".github/actions/ferry-run-developer/node_modules/protobufjs/tsconfig.json",
".github/actions/ferry-run-iterator/node_modules/@anthropic-ai/sdk/src/tsconfig.json",
".github/actions/ferry-run-iterator/node_modules/@stablelib/base64/tsconfig.json",
".github/actions/ferry-run-iterator/node_modules/fast-uri/tsconfig.json",
".github/actions/ferry-run-iterator/node_modules/openai/src/tsconfig.json",
".github/actions/ferry-run-iterator/node_modules/protobufjs/tsconfig.json",
".github/actions/ferry-run-merger/node_modules/@anthropic-ai/sdk/src/tsconfig.json",
".github/actions/ferry-run-merger/node_modules/@stablelib/base64/tsconfig.json",
".github/actions/ferry-run-merger/node_modules/fast-uri/tsconfig.json",
".github/actions/ferry-run-merger/node_modules/openai/src/tsconfig.json",
".github/actions/ferry-run-merger/node_modules/protobufjs/tsconfig.json",
".github/actions/ferry-run-refiner/node_modules/@anthropic-ai/sdk/src/tsconfig.json",
".github/actions/ferry-run-refiner/node_modules/@stablelib/base64/tsconfig.json",
".github/actions/ferry-run-refiner/node_modules/fast-uri/tsconfig.json",
".github/actions/ferry-run-refiner/node_modules/openai/src/tsconfig.json",
".github/actions/ferry-run-refiner/node_modules/protobufjs/tsconfig.json",
".github/actions/ferry-run-reviewer/node_modules/@anthropic-ai/sdk/src/tsconfig.json",
".github/actions/ferry-run-reviewer/node_modules/@stablelib/base64/tsconfig.json",
".github/actions/ferry-run-reviewer/node_modules/fast-uri/tsconfig.json",
".github/actions/ferry-run-reviewer/node_modules/openai/src/tsconfig.json",
".github/actions/ferry-run-reviewer/node_modules/protobufjs/tsconfig.json",
"tsconfig.json"
],
"agent_commit_share": 0.28,
"toolchain_manifests": [],
"dependency_bot_commit_share": 0.09
},
"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, .eslintrc.js, .eslintrc.yml, eslint.config.js",
"points": 11,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": ".eslintrc, .eslintrc.js, .eslintrc.yml, eslint.config.js"
}
}
],
"max_points": 11
},
{
"key": "static_type_checking",
"name": "Static type checking",
"detail": ".ferry/node_modules/@anthropic-ai/sdk/src/tsconfig.json, .ferry/node_modules/@stablelib/base64/tsconfig.json, .ferry/node_modules/fast-uri/tsconfig.json, .ferry/node_modules/json-with-bigint/tsconfig.json, .ferry/node_modules/openai/src/tsconfig.json, .ferry/node_modules/protobufjs/tsconfig.json, .github/actions/ferry-emit-audit/node_modules/json-with-bigint/tsconfig.json, .github/actions/ferry-envelope-validate/node_modules/fast-uri/tsconfig.json, .github/actions/ferry-run-developer/node_modules/@anthropic-ai/sdk/src/tsconfig.json, .github/actions/ferry-run-developer/node_modules/@stablelib/base64/tsconfig.json, .github/actions/ferry-run-developer/node_modules/fast-uri/tsconfig.json, .github/actions/ferry-run-developer/node_modules/openai/src/tsconfig.json, .github/actions/ferry-run-developer/node_modules/protobufjs/tsconfig.json, .github/actions/ferry-run-iterator/node_modules/@anthropic-ai/sdk/src/tsconfig.json, .github/actions/ferry-run-iterator/node_modules/@stablelib/base64/tsconfig.json, .github/actions/ferry-run-iterator/node_modules/fast-uri/tsconfig.json, .github/actions/ferry-run-iterator/node_modules/openai/src/tsconfig.json, .github/actions/ferry-run-iterator/node_modules/protobufjs/tsconfig.json, .github/actions/ferry-run-merger/node_modules/@anthropic-ai/sdk/src/tsconfig.json, .github/actions/ferry-run-merger/node_modules/@stablelib/base64/tsconfig.json, .github/actions/ferry-run-merger/node_modules/fast-uri/tsconfig.json, .github/actions/ferry-run-merger/node_modules/openai/src/tsconfig.json, .github/actions/ferry-run-merger/node_modules/protobufjs/tsconfig.json, .github/actions/ferry-run-refiner/node_modules/@anthropic-ai/sdk/src/tsconfig.json, .github/actions/ferry-run-refiner/node_modules/@stablelib/base64/tsconfig.json, .github/actions/ferry-run-refiner/node_modules/fast-uri/tsconfig.json, .github/actions/ferry-run-refiner/node_modules/openai/src/tsconfig.json, .github/actions/ferry-run-refiner/node_modules/protobufjs/tsconfig.json, .github/actions/ferry-run-reviewer/node_modules/@anthropic-ai/sdk/src/tsconfig.json, .github/actions/ferry-run-reviewer/node_modules/@stablelib/base64/tsconfig.json, .github/actions/ferry-run-reviewer/node_modules/fast-uri/tsconfig.json, .github/actions/ferry-run-reviewer/node_modules/openai/src/tsconfig.json, .github/actions/ferry-run-reviewer/node_modules/protobufjs/tsconfig.json, tsconfig.json",
"points": 11,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": ".ferry/node_modules/@anthropic-ai/sdk/src/tsconfig.json, .ferry/node_modules/@stablelib/base64/tsconfig.json, .ferry/node_modules/fast-uri/tsconfig.json, .ferry/node_modules/json-with-bigint/tsconfig.json, .ferry/node_modules/openai/src/tsconfig.json, .ferry/node_modules/protobufjs/tsconfig.json, .github/actions/ferry-emit-audit/node_modules/json-with-bigint/tsconfig.json, .github/actions/ferry-envelope-validate/node_modules/fast-uri/tsconfig.json, .github/actions/ferry-run-developer/node_modules/@anthropic-ai/sdk/src/tsconfig.json, .github/actions/ferry-run-developer/node_modules/@stablelib/base64/tsconfig.json, .github/actions/ferry-run-developer/node_modules/fast-uri/tsconfig.json, .github/actions/ferry-run-developer/node_modules/openai/src/tsconfig.json, .github/actions/ferry-run-developer/node_modules/protobufjs/tsconfig.json, .github/actions/ferry-run-iterator/node_modules/@anthropic-ai/sdk/src/tsconfig.json, .github/actions/ferry-run-iterator/node_modules/@stablelib/base64/tsconfig.json, .github/actions/ferry-run-iterator/node_modules/fast-uri/tsconfig.json, .github/actions/ferry-run-iterator/node_modules/openai/src/tsconfig.json, .github/actions/ferry-run-iterator/node_modules/protobufjs/tsconfig.json, .github/actions/ferry-run-merger/node_modules/@anthropic-ai/sdk/src/tsconfig.json, .github/actions/ferry-run-merger/node_modules/@stablelib/base64/tsconfig.json, .github/actions/ferry-run-merger/node_modules/fast-uri/tsconfig.json, .github/actions/ferry-run-merger/node_modules/openai/src/tsconfig.json, .github/actions/ferry-run-merger/node_modules/protobufjs/tsconfig.json, .github/actions/ferry-run-refiner/node_modules/@anthropic-ai/sdk/src/tsconfig.json, .github/actions/ferry-run-refiner/node_modules/@stablelib/base64/tsconfig.json, .github/actions/ferry-run-refiner/node_modules/fast-uri/tsconfig.json, .github/actions/ferry-run-refiner/node_modules/openai/src/tsconfig.json, .github/actions/ferry-run-refiner/node_modules/protobufjs/tsconfig.json, .github/actions/ferry-run-reviewer/node_modules/@anthropic-ai/sdk/src/tsconfig.json, .github/actions/ferry-run-reviewer/node_modules/@stablelib/base64/tsconfig.json, .github/actions/ferry-run-reviewer/node_modules/fast-uri/tsconfig.json, .github/actions/ferry-run-reviewer/node_modules/openai/src/tsconfig.json, .github/actions/ferry-run-reviewer/node_modules/protobufjs/tsconfig.json, 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": "28 of the last 100 commits agent-authored or agent-credited",
"points": 10,
"status": "met",
"details": [
{
"code": "agent_authored_commits",
"params": {
"count": 28,
"sampled": 100
}
}
],
"max_points": 10
},
{
"key": "automated_maintenance",
"name": "Automated maintenance",
"detail": "9 of the last 100 commits are automated dependency updates",
"points": 8,
"status": "met",
"details": [
{
"code": "dependency_bot_commits",
"params": {
"count": 9,
"sampled": 100
}
}
],
"max_points": 8
},
{
"key": "openssf_scorecard_pinned_dependencies",
"name": "OpenSSF Scorecard: Pinned-Dependencies",
"detail": "dependency not pinned by hash detected -- score normalized to 6",
"points": 6,
"status": "partial",
"details": [],
"max_points": 10
}
]
},
{
"key": "ai_code_legibility",
"band": "excellent",
"name": "Code legibility for models",
"note": null,
"notes": [],
"value": 98,
"inputs": {
"primary_language": "TypeScript",
"largest_source_bytes": 406037,
"source_files_sampled": 404,
"oversized_source_files": 14
},
"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": "14/404 source files over 60KB",
"points": 53.1,
"status": "partial",
"details": [
{
"code": "oversized_source_files",
"params": {
"kb": 60,
"sampled": 404,
"oversized": 14
}
}
],
"max_points": 55
}
]
},
{
"key": "ai_interfaces",
"band": "excellent",
"name": "Machine-readable interfaces",
"note": null,
"notes": [],
"value": 100,
"inputs": {
"example_dirs": [
"example",
"examples"
],
"has_mcp_signal": true,
"api_schema_files": [
".ferry/node_modules/protobufjs/google/api/annotations.proto",
".ferry/node_modules/protobufjs/google/api/http.proto",
".ferry/node_modules/protobufjs/google/protobuf/api.proto",
".ferry/node_modules/protobufjs/google/protobuf/descriptor.proto",
".ferry/node_modules/protobufjs/google/protobuf/source_context.proto",
".ferry/node_modules/protobufjs/google/protobuf/type.proto",
".github/actions/ferry-run-developer/node_modules/protobufjs/google/api/annotations.proto",
".github/actions/ferry-run-developer/node_modules/protobufjs/google/api/http.proto",
".github/actions/ferry-run-developer/node_modules/protobufjs/google/protobuf/api.proto",
".github/actions/ferry-run-developer/node_modules/protobufjs/google/protobuf/descriptor.proto",
".github/actions/ferry-run-developer/node_modules/protobufjs/google/protobuf/source_context.proto",
".github/actions/ferry-run-developer/node_modules/protobufjs/google/protobuf/type.proto",
".github/actions/ferry-run-iterator/node_modules/protobufjs/google/api/annotations.proto",
".github/actions/ferry-run-iterator/node_modules/protobufjs/google/api/http.proto",
".github/actions/ferry-run-iterator/node_modules/protobufjs/google/protobuf/api.proto",
".github/actions/ferry-run-iterator/node_modules/protobufjs/google/protobuf/descriptor.proto",
".github/actions/ferry-run-iterator/node_modules/protobufjs/google/protobuf/source_context.proto",
".github/actions/ferry-run-iterator/node_modules/protobufjs/google/protobuf/type.proto",
".github/actions/ferry-run-merger/node_modules/protobufjs/google/api/annotations.proto",
".github/actions/ferry-run-merger/node_modules/protobufjs/google/api/http.proto",
".github/actions/ferry-run-merger/node_modules/protobufjs/google/protobuf/api.proto",
".github/actions/ferry-run-merger/node_modules/protobufjs/google/protobuf/descriptor.proto",
".github/actions/ferry-run-merger/node_modules/protobufjs/google/protobuf/source_context.proto",
".github/actions/ferry-run-merger/node_modules/protobufjs/google/protobuf/type.proto",
".github/actions/ferry-run-refiner/node_modules/protobufjs/google/api/annotations.proto",
".github/actions/ferry-run-refiner/node_modules/protobufjs/google/api/http.proto",
".github/actions/ferry-run-refiner/node_modules/protobufjs/google/protobuf/api.proto",
".github/actions/ferry-run-refiner/node_modules/protobufjs/google/protobuf/descriptor.proto",
".github/actions/ferry-run-refiner/node_modules/protobufjs/google/protobuf/source_context.proto",
".github/actions/ferry-run-refiner/node_modules/protobufjs/google/protobuf/type.proto",
".github/actions/ferry-run-reviewer/node_modules/protobufjs/google/api/annotations.proto",
".github/actions/ferry-run-reviewer/node_modules/protobufjs/google/api/http.proto",
".github/actions/ferry-run-reviewer/node_modules/protobufjs/google/protobuf/api.proto",
".github/actions/ferry-run-reviewer/node_modules/protobufjs/google/protobuf/descriptor.proto",
".github/actions/ferry-run-reviewer/node_modules/protobufjs/google/protobuf/source_context.proto",
".github/actions/ferry-run-reviewer/node_modules/protobufjs/google/protobuf/type.proto"
]
},
"components": [
{
"key": "api_schema_openapi_graphql_proto",
"name": "API schema (OpenAPI/GraphQL/proto)",
"detail": ".ferry/node_modules/protobufjs/google/api/annotations.proto, .ferry/node_modules/protobufjs/google/api/http.proto, .ferry/node_modules/protobufjs/google/protobuf/api.proto, .ferry/node_modules/protobufjs/google/protobuf/descriptor.proto, .ferry/node_modules/protobufjs/google/protobuf/source_context.proto, .ferry/node_modules/protobufjs/google/protobuf/type.proto, .github/actions/ferry-run-developer/node_modules/protobufjs/google/api/annotations.proto, .github/actions/ferry-run-developer/node_modules/protobufjs/google/api/http.proto, .github/actions/ferry-run-developer/node_modules/protobufjs/google/protobuf/api.proto, .github/actions/ferry-run-developer/node_modules/protobufjs/google/protobuf/descriptor.proto, .github/actions/ferry-run-developer/node_modules/protobufjs/google/protobuf/source_context.proto, .github/actions/ferry-run-developer/node_modules/protobufjs/google/protobuf/type.proto, .github/actions/ferry-run-iterator/node_modules/protobufjs/google/api/annotations.proto, .github/actions/ferry-run-iterator/node_modules/protobufjs/google/api/http.proto, .github/actions/ferry-run-iterator/node_modules/protobufjs/google/protobuf/api.proto, .github/actions/ferry-run-iterator/node_modules/protobufjs/google/protobuf/descriptor.proto, .github/actions/ferry-run-iterator/node_modules/protobufjs/google/protobuf/source_context.proto, .github/actions/ferry-run-iterator/node_modules/protobufjs/google/protobuf/type.proto, .github/actions/ferry-run-merger/node_modules/protobufjs/google/api/annotations.proto, .github/actions/ferry-run-merger/node_modules/protobufjs/google/api/http.proto, .github/actions/ferry-run-merger/node_modules/protobufjs/google/protobuf/api.proto, .github/actions/ferry-run-merger/node_modules/protobufjs/google/protobuf/descriptor.proto, .github/actions/ferry-run-merger/node_modules/protobufjs/google/protobuf/source_context.proto, .github/actions/ferry-run-merger/node_modules/protobufjs/google/protobuf/type.proto, .github/actions/ferry-run-refiner/node_modules/protobufjs/google/api/annotations.proto, .github/actions/ferry-run-refiner/node_modules/protobufjs/google/api/http.proto, .github/actions/ferry-run-refiner/node_modules/protobufjs/google/protobuf/api.proto, .github/actions/ferry-run-refiner/node_modules/protobufjs/google/protobuf/descriptor.proto, .github/actions/ferry-run-refiner/node_modules/protobufjs/google/protobuf/source_context.proto, .github/actions/ferry-run-refiner/node_modules/protobufjs/google/protobuf/type.proto, .github/actions/ferry-run-reviewer/node_modules/protobufjs/google/api/annotations.proto, .github/actions/ferry-run-reviewer/node_modules/protobufjs/google/api/http.proto, .github/actions/ferry-run-reviewer/node_modules/protobufjs/google/protobuf/api.proto, .github/actions/ferry-run-reviewer/node_modules/protobufjs/google/protobuf/descriptor.proto, .github/actions/ferry-run-reviewer/node_modules/protobufjs/google/protobuf/source_context.proto, .github/actions/ferry-run-reviewer/node_modules/protobufjs/google/protobuf/type.proto",
"points": 40,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": ".ferry/node_modules/protobufjs/google/api/annotations.proto, .ferry/node_modules/protobufjs/google/api/http.proto, .ferry/node_modules/protobufjs/google/protobuf/api.proto, .ferry/node_modules/protobufjs/google/protobuf/descriptor.proto, .ferry/node_modules/protobufjs/google/protobuf/source_context.proto, .ferry/node_modules/protobufjs/google/protobuf/type.proto, .github/actions/ferry-run-developer/node_modules/protobufjs/google/api/annotations.proto, .github/actions/ferry-run-developer/node_modules/protobufjs/google/api/http.proto, .github/actions/ferry-run-developer/node_modules/protobufjs/google/protobuf/api.proto, .github/actions/ferry-run-developer/node_modules/protobufjs/google/protobuf/descriptor.proto, .github/actions/ferry-run-developer/node_modules/protobufjs/google/protobuf/source_context.proto, .github/actions/ferry-run-developer/node_modules/protobufjs/google/protobuf/type.proto, .github/actions/ferry-run-iterator/node_modules/protobufjs/google/api/annotations.proto, .github/actions/ferry-run-iterator/node_modules/protobufjs/google/api/http.proto, .github/actions/ferry-run-iterator/node_modules/protobufjs/google/protobuf/api.proto, .github/actions/ferry-run-iterator/node_modules/protobufjs/google/protobuf/descriptor.proto, .github/actions/ferry-run-iterator/node_modules/protobufjs/google/protobuf/source_context.proto, .github/actions/ferry-run-iterator/node_modules/protobufjs/google/protobuf/type.proto, .github/actions/ferry-run-merger/node_modules/protobufjs/google/api/annotations.proto, .github/actions/ferry-run-merger/node_modules/protobufjs/google/api/http.proto, .github/actions/ferry-run-merger/node_modules/protobufjs/google/protobuf/api.proto, .github/actions/ferry-run-merger/node_modules/protobufjs/google/protobuf/descriptor.proto, .github/actions/ferry-run-merger/node_modules/protobufjs/google/protobuf/source_context.proto, .github/actions/ferry-run-merger/node_modules/protobufjs/google/protobuf/type.proto, .github/actions/ferry-run-refiner/node_modules/protobufjs/google/api/annotations.proto, .github/actions/ferry-run-refiner/node_modules/protobufjs/google/api/http.proto, .github/actions/ferry-run-refiner/node_modules/protobufjs/google/protobuf/api.proto, .github/actions/ferry-run-refiner/node_modules/protobufjs/google/protobuf/descriptor.proto, .github/actions/ferry-run-refiner/node_modules/protobufjs/google/protobuf/source_context.proto, .github/actions/ferry-run-refiner/node_modules/protobufjs/google/protobuf/type.proto, .github/actions/ferry-run-reviewer/node_modules/protobufjs/google/api/annotations.proto, .github/actions/ferry-run-reviewer/node_modules/protobufjs/google/api/http.proto, .github/actions/ferry-run-reviewer/node_modules/protobufjs/google/protobuf/api.proto, .github/actions/ferry-run-reviewer/node_modules/protobufjs/google/protobuf/descriptor.proto, .github/actions/ferry-run-reviewer/node_modules/protobufjs/google/protobuf/source_context.proto, .github/actions/ferry-run-reviewer/node_modules/protobufjs/google/protobuf/type.proto"
}
}
],
"max_points": 40
},
{
"key": "mcp_server",
"name": "MCP server",
"detail": null,
"points": 20,
"status": "met",
"details": [],
"max_points": 20
},
{
"key": "runnable_examples",
"name": "Runnable examples",
"detail": "example, examples",
"points": 40,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": "example, 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": [
"Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token",
"GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository"
],
"report_type": "repository",
"generated_at": "2026-07-30T05:55:25.722928Z",
"schema_version": "0.27.0",
"badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/b/big-emotion/ferry.svg",
"full_name": "big-emotion/ferry",
"license_state": "standard",
"license_spdx": "MIT"
}