Звіт у форматі JSON машиночитний
{
"data": {
"repo": {
"topics": [],
"is_fork": false,
"size_kb": 10833,
"has_wiki": true,
"homepage": null,
"languages": {
"Shell": 10106,
"JavaScript": 209589,
"TypeScript": 1907156
},
"pushed_at": "2026-07-22T23:58:57Z",
"created_at": "2026-05-12T20:00:20Z",
"owner_type": "Organization",
"updated_at": "2026-07-22T23:59:02Z",
"description": "Shipeasy Claude Code plugin marketplace",
"is_archived": false,
"is_disabled": false,
"license_spdx": null,
"default_branch": "main",
"license_spdx_raw": null,
"primary_language": "TypeScript",
"significant_languages": [
"TypeScript"
]
},
"owner": {
"blog": "https://shipeasy.ai",
"name": "shipeasy.ai",
"type": "Organization",
"login": "shipeasy-ai",
"company": null,
"location": "United States of America",
"followers": 1,
"avatar_url": "https://avatars.githubusercontent.com/u/279595979?v=4",
"created_at": "2026-04-27T03:38:02Z",
"is_verified": null,
"public_repos": 9,
"account_age_days": 87
},
"license": {
"state": "absent",
"spdx_id": null,
"raw_spdx": null,
"file_present": false,
"scorecard_found": false,
"profile_has_license": false
},
"activity": {
"releases": [],
"recent_commits": [
{
"oid": "0a8071c4432ee583c42927e9cc2371267848d7f1",
"body": "Promote OpsRun/OpsInvestigation `completedAction` from an inline\n`link_pr|notify|status|superseded` string union to a named `OpsRunAction`\nschema (+ `OpsRunActionOrNull`), mirroring `OpsItemStatus`. Codegen now emits\na real TS enum in every generated client, so consumers reference members\n(`OpsRunAction.LINK_PR`) instead of raw strings.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(ops): name the run-action enum in the contract (OpsRunAction)",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-22T23:54:34Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "0fb19934a3cdbcddff1d4f7076813c2db7973e22",
"body": "CreateConfigRequest + UpdateConfigRequest gain optional dev/staging/prod\nobject props. On the CLI/MCP surface they project to --dev/--staging/--prod\n<json> flags (e.g. `release configs update cfg --prod '{\"n\":2}'`), each\npublishing that value to the named env immediately, overriding the flat\n`value` for it. Regenerated openapi client + CLI/MCP surfaces.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(configs): per-env publish keys on create/update",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-22T23:08:52Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "51b458177823dbc6733bacdbf992b30120854589",
"body": "Add operation-level x-cli.hidden; both generators skip it. Keeps the five\nconfig ops (draft, discard-draft, publish, versions, activity) in the API\nspec + reference but drops them from the CLI command tree and MCP tool\nsurface. Regenerated commands.gen/tools.gen; updated tool-catalog + command-\ntree snapshots.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(configs): hide draft/publish/versions/activity ops from CLI+MCP",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-22T22:55:47Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "4ce7f8f02af5c8da815a6ded365bf6f79d59f15a",
"body": "… stringify them\n\nThe `value` property on CreateConfig/UpdateConfig/SaveConfigDraft was declared\nwith no `type`, so the generated MCP inputSchema left it freeform. The Claude\nCode harness (and other MCP hosts) serialise an object argument to a JSON\nstring when the schema doesn't pin it to `type: \"ob\n[…]\ns accurate for both the flat and\nthe `{env: value}` forms. Regenerated the bundle, typed client, zod, MCP tools,\nand CLI commands.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(openapi): type config `value` params as object so MCP hosts don't…",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-22T22:41:33Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "4e241439cabc79167822d439d5e6837b655fc941",
"body": "Add a MetricDisplayUnit schema (nullable string — e.g. ms, %, $) and thread a\n`unit` field through the create/update metric request variants\n(CreateMetricWithQuery[/Ir], UpdateMetricWithQuery[/Ir], UpdateMetricFields).\nRegenerate the openapi bundle, TS/zod types, and the MCP tools from the spec.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(metrics): add optional display unit to metric definitions",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-22T21:09:05Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "1cef9cd8884306637bd15524fc8e9223f67df1fd",
"body": "The queue-work loop now acks each item the moment it's picked up\n(`shipeasy ops ack`), which opens the run that lands finished work in the\nAction-required lane instead of No progress. Agent is auto-detected; no\ntrigger connector required (connector-less run). Replaces the manual\nin_progress status flip.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "docs(ops-work): ack items on pickup to record a run",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-22T19:12:20Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "e70d97ded69ff2114efb64c1684fb94867e56281",
"body": "The metrics_grammar reference listed ratios under NOT SUPPORTED, but the\nruntime parser/IR (packages/query-dsl) has supported the binary ratio(arm,\narm) form end-to-end for a while. Document it: BNF, a RATIO section, the\ncohort-rate-not-id-join semantics, and two examples; narrow NOT SUPPORTED to\nge\n[…]\neral arithmetic. Also fix the stale source-of-truth pointer (the vendored\ncli/src/query-dsl copy lags and is off the create path).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "docs(metrics): document the ratio() DSL form in the grammar",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-22T17:11:33Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "fd037f1f691f4a10966348f5731ccb79e7819da8",
"body": "…itle)\n\nMCP clients (Claude, etc.) bucket tools by the per-tool `annotations`\nobject in tools/list — readOnlyHint / destructiveHint / idempotentHint /\ntitle. We emitted none, so every tool fell into \"other tools\".\n\nDerive them in gen-tools.mjs from the HTTP method + x-cli verb: GET\n(list/get) = read\n[…]\n).\n\nReaches both the stdio server and the hosted mcp-worker unchanged — both\npass the tool objects straight through to tools/list.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(mcp): emit tool annotations (readOnly/destructive/idempotent + t…",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-22T15:53:45Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "e3e51f0d8e351cd040b9f500932d5b7c4f95b878",
"body": "Expose the investigation surface as a proper Ops sub-resource and add an\nin-place update so a delegated agent can write its findings back into the\n`working` run record it was handed:\n\n- New `Investigations` tag (parent Ops) — createOpsInvestigation and\n listOpsInvestigations were silently dropped f\n[…]\ner=, Copilot repo → /tasks/). Never an input.\n\nRegenerated the typed client, CLI commands + snapshot + docs, and MCP tools +\ndocs.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(ops): investigation write-back API + derived run session URL",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-22T02:33:46Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "9409c6a441d7a790ded5434e14b015929eaaaf36",
"body": "admin/ops keys are env-agnostic (server pins them to prod) but the create\nendpoint still requires an env field, so default it to prod and always send.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(cli): always send env on key create (endpoint requires it)",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-21T19:47:42Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "af02dd23459bd6a8cd0b703c26579a7ac6c26c2c",
"body": "…tags\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "chore(mcp): regenerate tools for ops create owner/status/subscribers/…",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-21T19:47:40Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "65695b64fd49435b3eb1afbaa6d4d982f9f6fc30",
"body": "…uest\n\nExtend CreateBugRequest + CreateFeatureRequestRequest with optional\nstatus, assigneeId, subscribers[], and tags[] so a bug / feature request\ncan carry its owner, initial status, Slack subscribers, and tags in the\nsingle POST /api/admin/ops call. Regenerated openapi.{yaml,json} + the\ntyped client/zod validators.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(openapi): accept owner/status/subscribers/tags on ops create req…",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-21T17:05:37Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "1bba46a2619066f04ddf868fa573dad35437d2e2",
"body": "Mirror of @shipeasy/core's buildCopilotAgentFile: the generated\n.github/agents/shipeasy.agent.md now wires the shipeasy MCP server as a remote\n`type: http` endpoint (project-scoped /p/<id>/mcp) authenticated by a\n`Authorization: Bearer ${{ secrets.COPILOT_MCP_SHIPEASY_CLI_TOKEN }}` header\n(a semcp_ \n[…]\ntead of the local `npx @shipeasy/mcp` stdio server.\nNo npm cold-start in the coding-agent sandbox. mcpBaseUrl overridable for e2e.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(cli): Copilot agent file targets remote MCP over Bearer",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-21T03:15:21Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "f49e31329c6d19255e7e9f49dbbce8e03c761594",
"body": "The gate create/update MCP tool input-schemas embed the request-body JSON\nschema; regenerate so they carry the new `whitelist` condition property.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "chore(mcp): regenerate tools.gen for gatekeeper `whitelist` field",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-19T16:50:43Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "ed7ff86d851d447eb7fcea31dda315061e82faa3",
"body": "…on entries\n\nThe gate editor pins an allowlist condition and persists a `whitelist: true`\nmarker on it (round-tripped by every read view — read-gate-view, gate-flow,\nthe stack hovercard — and the editor itself). The condition sub-gate schema\ndeclares `additionalProperties: false` but never listed `w\n[…]\nen\nregenerate. It's a presentational sibling of `locked` — ignored by\nevaluation, which treats the entry as an ordinary condition.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(openapi): allow `whitelist` cosmetic marker on gatekeeper conditi…",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-19T16:49:19Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "1beeb9f82ac7dbe4148c8dfe61ef353afebce295",
"body": "…hanges\n\nThe published @shipeasy/openapi@2.3.0 predates the ops-ack operations\n(ackOpsItem / listOpsAgents) and the errors-series / notifications-feed\nremovals, so publish-openapi idempotent-skipped and publish-cli's pre-publish\ntype-check resolved the stale 2.3.0 (missing ackOpsItem). Bumping the version\npublishes the current surface; cli's `^2.1.0` range then picks it up.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "chore(openapi): bump to 2.4.0 to publish the ops-ack surface + spec c…",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-18T06:05:56Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "c991d2bcdd502f1eb58419cd6a5bcedd8b742456",
"body": "`GET/POST /api/admin/notifications/feed` (the dashboard bell's in-app feed +\nmark-read) is dashboard/mobile-private UI plumbing, read through server\nactions — not a CLI/MCP operation. Removes it from the spec (drops it from\nthe contract fuzz + generated clients; it had no MCP tool). The ops-attentio\n[…]\nT /api/admin/notifications` (createNotification) stays\ncontract-bound. The handlers move to handlers/internal/ in the parent repo.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(spec): move the notifications feed out of the public contract",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-18T05:08:11Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "888dca03b173949a627d066400cb8667881ba2e6",
"body": "`POST /api/admin/errors/series` (getProjectErrorSeries) is a dashboard\nproxy to the Cloudflare Analytics Engine SQL API — it needs the UI\nworker's CF_API_TOKEN secret, which CI has no way to provision, so it can\nonly ever 503 under the contract fuzz. It's a dashboard-only chart feed,\nnot a CLI/MCP o\n[…]\n` stays contract-bound (excluded from\nthe fuzz as a sub-action route). The handler moves to handlers/internal/\nin the parent repo.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(spec): move project-wide error series out of the public contract",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-18T04:48:01Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "4ede981a82e98ff6c8541358719477e6353b6183",
"body": "…as code\n\nA group/tool description authored with a hard-wrapped inline code span\n(`ops ack <handle> --agent\\n<type>`) emitted a `...` span containing a\nnewline. MDX can't parse a single-backtick span across a line break, so it\nread the `<handle>`/`<type>` inside as JSX and the docs build failed with\n[…]\n tag for <handle>\". escapeProse() now collapses internal\nwhitespace within each inline code segment; regenerated mcp-reference.md.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(mcp-docs): keep inline code spans single-line so MDX parses them …",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-18T04:09:56Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "f6891b95ce244562eb1e6739bb4db87c5cd36dcf",
"body": "The skills-contract sdk-compile test bakes SDK snippets from the live\npublished docs and type-checks them against the installed SDK. The docs\nnow use addExtras/clearExtras/runWithExtras (shipped in 7.7.0), so the\nfrozen-lockfile install in ci.yml must resolve 7.7.0 or the snippets fail\nto compile. (skills-contract.yml already forces @latest; this keeps the\nroot `pnpm test` green too.)\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "chore(deps): bump @shipeasy/sdk 7.6.0 → 7.7.0 for the extras API",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-18T01:56:14Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "d50f14b6e09f205a13313ea12593b3fc38fea582",
"body": "openapi-ts writes openapi-ts-error-*.log dumps on a failed/interrupted\ngen run; they're throwaway diagnostics, not artifacts to track.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "chore(openapi): ignore transient openapi-ts codegen error logs",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-18T01:56:13Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "a32a575d2be547d9740af0992562667227a42501",
"body": "Default the acking agent (and session id, when the harness exposes one)\nfor `shipeasy ops ack` / the `ops_ack` MCP tool from the coding-agent\nharness driving the shell — the CLI reads harness env markers, the MCP\nserver reads the client's initialize handshake name with env as fallback.\nAn agent acks\n[…]\nags; a human at a plain terminal stays a\nhuman ack. `SHIPEASY_ACK_AGENT=<type>` forces a type, `=none|human|0`\nforces a human ack.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(cli,mcp): ops ack env-identification layer",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-18T01:55:36Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "b7f0f01d024a7dd74d78eb699e398f8d6b7a592d",
"body": "…se-contract migration\n\nReconcile the hand-authored spec with what the admin handlers actually\nreturn, so every apps/ui handler can annotate its return with a generated\n*Response type (handlers/response-contract):\n\n- Rows gain the dashboard-consumed fields: gates (creatorEmail/updaterEmail/\n versio\n[…]\n surface\nfor all new operations is deliberately NOT wired yet (registry pass\npending; cli/ and mcp/ changes stay uncommitted with that session).\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(spec): document the dashboard's full wire surface for the respon…",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-17T23:57:24Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "2044d371936128712d89b337a9c6fd1c7f37a07b",
"body": "…d URL + release 2.7.0\n\nThe MCP step of `shipeasy upgrade` now resolves the project pin before\nforce-rewriting each agent's entry — the .shipeasy binding wins, else the\npin already in the config (X-Project-Id header or an already-scoped\n/p/<id>/mcp URL) is carried forward via the new existingMcpProj\n[…]\nh also pre-selects\nthe project at OAuth consent).\n\nBump to 2.7.0 so the release carries the scoped-URL setup wiring and this\nmigration together.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(cli): shipeasy upgrade migrates MCP entries to the project-scope…",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-17T03:54:39Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "61064fff68d5c9241d182c0feec2c1711e9cfac9",
"body": "When a bound project is known, the written MCP config now points at\nhttps://mcp.shipeasy.ai/p/<projectId>/mcp instead of the bare /mcp. The\npath pins every tool call to that project (X-Project-Id header kept as the\nexplicit override) and — since OAuth clients echo the configured URL as the\nRFC 8707 \n[…]\nnsent screen pre-selects that\nexact project. Also gives Codex a real project pin: its config carries no\nheaders, so the URL is the only channel.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(cli): project-scoped MCP server URL (/p/<id>/mcp) in setup wiring",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-17T03:40:15Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "726c1bda1eb073cbfd892c9e1bafb73f3e60afe9",
"body": "The killswitch-propagation leg flipped a switch, polled /sdk/evaluate for 24s,\nthen restored. It failed intermittently (\"flip … did NOT propagate, edge still\n<orig>\") — not a prod bug. Verified against prod: the admin write path is\nintact (D1 config_values v46=false→v47=true, and the KV `{pid}:prod:\n[…]\n 96s (> KV's ~60s SLA, with margin) before restoring, polling\nevery 3s; factor the flip/restore polling into one `pollFor` helper.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(prod-probe): hold killswitch flip past KV's 60s edge-cache SLA",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-11T17:00:47Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "2264f4c1c2b82822e664f3258a5561e7bc7f5a19",
"body": "…tract tests)\n\nThe Admin-API contract fuzz failed `response_schema_conformance` on both\n`GET /api/admin/experiments` and `GET /api/admin/experiments/{id}`: the app\nprojects every experiment through one `toExperimentApiRow` allow-list, but the\ntwo response schemas here had drifted apart and both unde\n[…]\nields are optional, so both the enriched list rows and the lean\nby-id detail validate. Regenerated the bundle + hey-api types/zod.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(openapi): experiment API row schema matches the served shape (con…",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-11T16:34:16Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "997645f63544f820c88c6a03549a4683e5cdacaf",
"body": "…h CLI snapshot\n\nThe skills-contract sdk-compile test pins @shipeasy/sdk, but at ^6.2.0 it\nresolved a pre-`universe()` SDK while the shipeasy-experiments skill's baked\n`release/experiments` snippet (fetched from the latest published SDK docs)\ncalls `client.universe(...).assign()` — so the snippet fa\n[…]\no refresh the CLI command-surface snapshot for the new `ops comments`\ngroup (issue-comments feature) so `commands.test.ts` passes.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(ci): type-check skill snippets against @shipeasy/sdk 7.x + refres…",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-11T16:33:26Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "9853c2769f0b34c73423ec1bbe47bcc1c8396d52",
"body": "…erprint docs\n\nErrorRecord gains an optional occurrences array (ErrorOccurrence — the\nminimal per-instance payload: message/stack/url/env/extras + sampleRate\n+ seenAt), returned only by GET /api/admin/errors/{id}, newest first,\ncapped at 100. Detail rows are sampled past 10/100/1000 occurrences\nwhil\n[…]\nn updated: the key is now the issue title (errorType +\nsubject + outcome), not the normalized message. Regenerates the typed\nclient + MCP tools.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(openapi): getError returns sampled occurrences; title-based fing…",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-10T15:42:21Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "d1645112116e6079b296b3893b678a09f026ade0",
"body": "The poll broke as soon as all 20 exposure units were visible, but exposures\nand metric events flush through separate Pipelines sinks — a slower events\nroll left Σy=0 and false-failed the exact-stats assert (observed live:\nΣy=0 at assert time, all 19 metric rows visible minutes later). Hold the\npoll until the expected metric mass has landed as well.",
"is_bot": false,
"headline": "fix(prod-probe): lake-verdict poll must wait for the events sink too",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-10T14:58:53Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "0479371d109265477d1c48fcc8d5de058c6f256b",
"body": "…series\n\nValidates exposure logging end to end: seeds gate-check exposures (6 units,\n2 duplicate rows) alongside the lake-verdict experiment cohort, then runs the\nhourly exposure_recalc cron's exact first-exposure query shape (per-unit\nMIN(ts_ms) → UTC day index) scoped to the run prefixes and asser\n[…]\nic\ncumulative enrollment curve with consistent totals; soft-skips until the\ncrons have produced rows.\n\nVerified green against the live canary (6/6 gate units, 20/20 experiment\nunits, day 20644 exact).",
"is_bot": false,
"headline": "test(prod-probe): exposure-timeline leg — recalc inputs + cumulative …",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-10T14:58:36Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "cd3a0a4ff5218f300d4c38cfc4cb4328ea3686dc",
"body": "openapi 2.3.0 ships the resolveError client op; mcp 2.4.0 ships the\nerrors_resolve tool and pins @shipeasy/openapi to ^2.3.0 so the publish\nworkflow waits for the new openapi on npm before shipping mcp.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
"is_bot": false,
"headline": "chore(release): @shipeasy/openapi 2.3.0, @shipeasy/mcp 2.4.0",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-09T20:46:01Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "c251e87dc76101b793cda8498b8220d45b585f78",
"body": "…rs_resolve\n\nNew single-purpose close-out action: no body, flips one tracked error to\nresolved (PATCH /errors/{id} pinned to { status: \"resolved\" }). Safe by\nconstruction — a resolved error reopens on recurrence — so it's the one\nerror mutation projected to the MCP surface (errors_resolve). The gene\n[…]\ng stay unprojected, and\nthe CLI keeps skipping the Errors tag wholesale.\n\nRegen: bundled spec, typed client, MCP tools.gen + mcp-reference docs.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(openapi,mcp): expose POST /api/admin/errors/{id}/resolve as erro…",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-09T20:38:18Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "2d4f76e9b1a4e45d496e1563d469172656bcb182",
"body": "…elope\n\nField-scoped validation messages (path → message) alongside the existing\n`error`/`code`/`detail`, so a client form can attach each message to its own\ninput instead of collapsing everything into one banner. Regenerated the client\ntypes + zod.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(openapi): add structured per-field `fields` map to the Error env…",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-09T18:11:53Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "f786161b36d768a3547c53a1d7843d0529dd981b",
"body": "Add scale-level checks for the canonical resolution order against live\n/sdk/evaluate on the canary:\n\n- probeGroupSplitSRM: 30/70 fixture over ≤800 deterministic units.\n Step 2 (fully-allocated fast path) → ~100% enrolled; step 6 (group\n hash) → observed split matches 30/70 by df=1 chi-square (SRM \n[…]\new fixtures registered in THROWAWAY_FIXTURES (stopped after each\nrun, reclaimed at start; stays under the Pro=10 running-exp cap).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "test(prod-probe): verify the 7-step resolution chain at scale",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-09T00:55:47Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "3151273858ddd06f22e7ff78729093103eccf82f",
"body": "…lines → R2 SQL\n\nSeeds a deterministic exposure+metric cohort through /collect as the first\nleg, then (as the last leg, after the sink's 300s roll) runs the verdict\nsufficient-stats SQL from experiment-platform/25-pipelines.md against the\nR2 Data Catalog over HTTP and asserts EXACT per-group n/Σy/Σy\n[…]\nnt exposed units at y=0 and exclusion of pre-exposure and never-exposed\npoison metrics. Gated on secrets.SHIPEASY_CATALOG_TOKEN (absent → skip).\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(probe): event-lake verdict leg — exact sufficient stats via Pipe…",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-08T23:55:12Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "ca114cf88be2342297091f0229e5ff65a6e5b434",
"body": "The config-inheritance leg now also guards the two /sdk/evaluate fields the\nuniverse-first SDKs depend on: the per-entry experiments[e].universe tag (so\nuniverse(name).assign() can find the pooled experiment) and the top-level\nuniverses[name].defaults map (so a not-enrolled universe(name).get(field) still\nresolves to the universe default).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "test(prod-probe): assert universe-first edge fields in the config leg",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-08T14:39:42Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "71f1fa0baaef9cdfdc06b20180f743aaecc93730",
"body": "…ures to fit the running cap\n\nThe first §B4-live run showed the rework legs green (config-merge, targeting,\nholdout, append) and mutual exclusion genuinely working — probe_mx_a/b already\nown the universe pool ([0,4000)/[4000,8000)). Two follow-ups so the MX leg\nasserts instead of soft-skipping:\n\n- R\n[…]\nted, and a\n run-start reclaim stops any left over from a prior run. Peak concurrent\n fixtures now ~7, comfortably under the cap.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(prod-probe): reuse the standing pooled MX pair + stop rework fixt…",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-08T12:16:02Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "30a7e1bd2340319e8529b6c9ccd7d79d7d64f6a3",
"body": "…he races, MX pooled-check\n\nThree fixes from the 2026-07-08 run (the new rework legs themselves passed:\nconfig-merge, targeting gate, holdout gate + negative-shape, append-variant):\n\n- mSPRT τ: a weak λ (|λ|≈0.08, far below the significance scale) that stays\n static across τ is thin-signal, not a w\n[…]\nRESH fixture names (probe_mx_pa/pb) so the pair is born pooled\n post-§B4 — a reused pre-§B4 row would stay hashVersion 1 forever.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(prod-probe): green up the first live run — mSPRT weak-λ, blob-cac…",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-08T11:53:02Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "e0881e438a8c34db1d4517c6f9713c1c3e3e50e9",
"body": "…l mutual exclusion\n\nNow that §B4 flips new experiments to pooled assignment, a 100%-allocation\nexperiment claims the WHOLE universe pool — two can't coexist in one\nuniverse. Gave each single-experiment leg (config / targeting / holdout /\nappend) its own universe so their 100% allocations fit, and r\n[…]\nr blob) before the hard assert, so it soft-skips instead of\nfalse-failing during the deploy transition, then lights up on its own.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "test(prod-probe): make the rework legs pooled-safe (§B4) + assert rea…",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-08T03:05:33Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "d28eb94763c72c4e9b0dddad72a979bcf1ea886a",
"body": "Five new eval-time legs assert the features added in the rework, all\ndeterministic off a single /sdk/evaluate response (no /collect, no AE\nsampling — the bucketing is fixed per unit). They build reusable\nthrowaway fixtures, so they gate on SHIPEASY_PROBE_MUTATE:\n\n- probeExperimentConfig — assignment\n[…]\nafter the stats-knob legs; header env docstring updated. No\nworkflow.yml change — MUTATE/SERVER_KEY/CLIENT_KEY are already passed.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "test(prod-probe): cover the Universes→Experiments→Groups rework",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-08T02:51:09Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "93834e530b2a2578aea6b0e71fe672fca3180e0e",
"body": "…m + defaultHoldout\n\n- experiments list response: holdoutGate + reservedHeadroom so the API/CLI/MCP\n can read back what create/update set.\n- projects: defaultHoldout (bp) on update/settings — seeds new universes' holdout.\n\nRegenerated types/zod + CLI commands + MCP tools.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(contract): §C read-back + settings — holdoutGate/reservedHeadroo…",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-08T01:52:32Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "d708d933ffb575b7a1879cc456c7523827203623",
"body": "- universes: param_schema ({name,type,default}[]), recommended_headroom (bp),\n description on create/update/list.\n- experiments: holdout_gate, reserved_headroom (bp) on create/update; group\n params documented as override-only (subset of the universe schema); weights\n sum to 10000 − reserved_headr\n[…]\n\nRegenerated the openapi bundle + hey-api types/zod, and the CLI commands + MCP\ntools that project the registry onto each surface.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(contract): §D universe/experiment/group rework — new fields",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-08T01:41:32Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "cb0da729aa706152cdf68a94eec0e1bfbe76db9e",
"body": "`shipeasy setup` (copilot) now writes `.github/agents/shipeasy.agent.md` — a\nGitHub custom agent whose `mcp-servers.shipeasy` is a local stdio server\n(`npx @shipeasy/mcp`, project id inlined + COPILOT_MCP_SHIPEASY_CLI_TOKEN secret)\nand whose body is the ops-work prompt. The CLI sets that one repo se\n[…]\nnv\nwhen there's no config file, so the coding-agent-spawned stdio server can\nauthenticate from the injected COPILOT_MCP_* secrets.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(triggers): Copilot custom-agent file + env-cred MCP fallback",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-07T04:26:49Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "aa56aa267a372737adf865b32dd1bd556eb0a6f6",
"body": "Cursor-flavored plugin.json mirroring the .claude-plugin/.codex-plugin/.plugin\nmanifests — bundles all 10 skills (./skills/) and the shipeasy MCP server\n(./.mcp.json, hosted HTTP endpoint that Cursor reads under mcpServers).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(marketplace): add Cursor plugin manifest",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-07T04:07:19Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "8aa8d1ff38cbaf65be52ee25f3c460af6852669c",
"body": "The admin error envelope now echoes the expected JSON Schema back when a\nvalue fails schema validation (e.g. a config `value` that doesn't match its\nconfig's saved schema), so a caller can correct the value and retry without\nre-fetching. Makes the `schema` field first-class in the spec's `Error`\nschema (previously `additionalProperties: false` would have rejected it).\nRegenerates the bundle + SDK types/zod.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(openapi): add `schema` to the Error envelope",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-06T23:34:47Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "f35de6299d709ef6b1f3c3bb4162a98269ab0f9d",
"body": "The MCP tool result only renders the thrown message, so the actionable\nguidance core carefully authors on its ApiErrors (`instructions`) never\nreached the calling agent. Fold `instructions` into the surfaced message\nin `unwrap` — e.g. a config value/schema mismatch now returns the expected\nJSON Schema to the agent so it can fix `value` and retry without a second\nround-trip. Adds unwrap unit coverage.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(mcp): surface ApiError `instructions` in the thrown tool error",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-06T23:25:29Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "a517e786e4f87b23a246081a4920e227e1868559",
"body": "Some MCP hosts serialise a structured (object/array) tool argument to a\nJSON string when the tool's JSON Schema doesn't pin the property to\n`type: \"object\"`/`\"array\"` — the known marshalling bug. For freeform\nparams like a config draft `value` (no declared `type`), the admin API\nthen rejected the st\n[…]\narray literal. Scalars, enums, and\nnon-JSON strings pass through untouched, so a plain \"true\"/\"42\"/\"hello\"\nvalue is never coerced.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(mcp): revive over-stringified structured tool args before dispatch",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-06T23:16:27Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "3638834285c5efd703b2984cae08495ddc8242a9",
"body": "…Servers\n\nSwitch the shared .mcp.json from the local `npx @shipeasy/mcp` subprocess\nto the hosted streamable-HTTP server (https://mcp.shipeasy.ai/mcp), mirroring\nthe CLI's canonical serverSpec() incl. the X-Shipeasy-List-Guard header. This\nflips both Claude and Codex (which share ./.mcp.json) to the\n[…]\n`keywords` fields to the Claude plugin.json\nso it matches the Codex and Copilot manifests instead of relying on implicit\ndefaults.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(plugin): claude plugin points at remote MCP + explicit skills/mcp…",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-06T21:20:19Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "43e039221f7357a3fdc6c93b19e304b9c7f833ac",
"body": "…goal\n\n- OpsErrorContext gains `stackTail`: the last 3 frames of the latest\n occurrence's stack, so the ops loop gets an at-a-glance throw locator\n without a second `related.error` fetch. Documented in the errors runbook.\n- OpsMeasurePlanContext gains `goal`: the customer's intent in their own\n w\n[…]\ne, and creates additional metrics/events the goal needs even off\n spec.\n- Regenerated the bundled contract + generated types/zod.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(ops): richer AI ticket context — error stackTail + measure-plan …",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-06T17:23:33Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "cd44623ad44a88947222cf8387bb6ba0356b0c0b",
"body": "Define comments on ops/feedback items in the OpenAPI spec so the whole surface\nis generated like everything else:\n\n- new Comments tag (child of Ops)\n- GET /api/admin/ops/{handle}/comments → listOpsComments (read the thread)\n- POST /api/admin/ops/{handle}/comments → createOpsComment (append; markd\n[…]\nmments list|create`). The\ntools.gen.ts regen also reconciles the pending ciConfidence/allocation drift\nfrom the prior spec commit.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(ops): comment operations (list + create) on queue items",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-06T16:55:40Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "6184b30a76e3c29aac514fb4dd623634752a05b6",
"body": "…ect defaults\n\nUpdateProjectRequest: ciConfidence becomes a free level in [0.5, 0.999]\n(was the 0.95/0.99 literal union) so the dashboard can offer an 'Other…'\ncustom confidence; add defaultAllocationPct (bp), defaultWinsorizePct, and\ndefaultMei — the per-project experiment defaults that seed new experiments\nand metrics. Mirrored on the Project response shape.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(openapi): widen ciConfidence + add allocation/winsorize/MEI proj…",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-06T04:16:59Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "cac1ca78d1c98f2be773aa03bd9a75b4f345b768",
"body": "…n canary)\n\nRan the three stats legs end-to-end against the Eval Probe Canary and fixed\nwhat surfaced:\n\n- Throttle /collect (chunks of 20, 500ms gap). Analytics Engine samples per\n index above ~100 data points/sec, so a 200-event burst lost most of its\n events and signal; pacing recovers a usable \n[…]\nrified: exit 0 on the canary — λ null on fixed ✓, ci_confidence ✓, and CUPED\nvariance reduction fired (238→173) on a clean freeze.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(prod-probe): harden stats legs for live prod AE (verified green o…",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-06T04:13:50Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "ae561c1d95a89ef39ebc96482a64bc8e62e8824d",
"body": "…s them\n\nThe stats legs create their fixtures with an inline goal metric, which registers\nthe backing event as pending:0 but does NOT rebuild the :catalog KV blob the edge\n/collect gate reads (only the events handlers call rebuildCatalog). So seeding a\ncohort 422'd \"Unregistered event names\" forever\n[…]\nt; always rebuilds the catalog), and retry the Unregistered\n422 in collect() to ride out the edge's per-isolate 60s catalog cache.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(prod-probe): approve inline-metric events so the edge catalog see…",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-06T03:20:42Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "b98c171cfc0b15a74a1ba10617378126cca795f5",
"body": "…n knobs absent\n\n`projects current` (getCurrentProject) is not a real route — /api/admin/projects/current\ncollides with /projects/[id] (id=\"current\") and 403s — so probeStatsEffect and the\nthree stats-knob legs could never read the project. Read it by id through the\nwithAdmin GET /api/admin/projects\n[…]\nht up automatically once prod redeploys — so SHIPEASY_PROBE_MUTATE\ncan be enabled ahead of the deploy without reddening the probe.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(prod-probe): read project via admin GET, soft-skip stats legs whe…",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-06T02:50:46Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "416cffe36d625cf6613e878863c260a3cae245b5",
"body": "The generated shipeasy-wiring.md told the agent to init the SDK and bind\na per-user client, but never to populate the identity/attributes bag — so\na straight follow-through left every evaluation seeing an empty context\n(only default rules + 100% rollouts fire, experiments can't bucket).\n\nAdd a per-t\n[…]\nargets feed\nthe same transform through identify(). Gate on the platform auto-inferring\nthe schema (release flags attributes list).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(cli): instruct wiring doc to wire identity + targeting attributes",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-06T02:48:13Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "d866fdce5af70b45700c7a1bd50f767d721de98d",
"body": "…s SKILL.md; sharpen see routing\n\nThe see code-instrumentation cases assert only that shipeasy-see fires and have\nno MCP surface (see() is a pure code primitive the sandbox can't let the agent\nwrite). Headless Haiku consults the skill by READING\n.claude/skills/shipeasy-see/SKILL.md rather than invok\n[…]\n), not console.error. Previously Haiku dove straight into\ngeneric error handling for that phrasing.\n\nshipeasy-see.json 4/4 at K=1.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(skills-eval,shipeasy-see): credit a skill consulted by reading it…",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-05T23:38:44Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "29b1654298e01aae51f8d0aa7980acedc23db6cb",
"body": "…knobs\n\nExtend the scheduled prod eval probe past the two knobs probeStatsEffect\nalready exercises (default_power→realized_mde, srm_threshold→srm_detected)\nto the analysis knobs that can only be tested with purpose-built fixtures:\n\n- probeSequentialTau: a sequential fixture (+ a fixed sibling) prove\n[…]\nwaway fixtures under SHIPEASY_PROBE_STATS_UNIVERSE (default\nprobe_stats; needs a Pro+ plan — soft-skip when create is plan-gated).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(prod-probe): cover mSPRT τ, CUPED gates, and verdict-gate stats …",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-05T23:29:01Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "41d31cee0b10e12e905cf5032403a7147b1ab86d",
"body": "The guard only recognised tools ending in _create, so an agent could file a bug\nvia the ops_bug/ops_feature convenience verbs and skip the mandatory ops_list\ndedup entirely (observed in skills-eval: ops_bug called with no prior list).\nMap both to the 'ops' family so they require the ops_list token l\n[…]\ncription'; the proration/seat\nwording is already asserted in assert_args against the filed content.\n\nshipeasy-ops.json 3/3 at K=1.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(mcp): extend list-before-create guard to ops_bug/ops_feature",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-05T23:04:22Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "2184060702f8b8029d1e8026ddb30faa9ee028aa",
"body": "…teral from fixture\n\nTwo i18n-eval fixes:\n- run.ts: an eval agent escaped the MCP-only lockdown via the Monitor tool\n (runs arbitrary shell) and python/git-committed into the real repo. Disallow\n Monitor + the Task*/Workflow/ScheduleWakeup exec-capable tools alongside Bash.\n- fixture-overlay/app/e\n[…]\nd i18n key; the agent must list-by-value + update via MCP.\n\nshipeasy-i18n.json 4/4 at K=1 (change-existing-copy now routes clean).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(skills-eval): close Monitor exec backdoor; drop 'Welcome back' li…",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-05T22:52:37Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "9206aaeb456a4b43b5c36d753aa93b1f60a47617",
"body": "Replace the round-trip check with an effect test: inject one deterministic,\nimbalanced synthetic cohort and reanalyze while varying a knob to a random\nin-range value, asserting the persisted result moves as the statistics require\n— default_power raises realized_mde monotonically, and a srm_threshold\n[…]\n sequential, CUPED\nneeds baselines, min_sample/min_runtime/ci seed or display) are left to the\nworker unit sims rather than faked.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "test(prod-probe): stats knobs must AFFECT analysis, not just save",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-05T22:37:56Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "ede38841b5a0301c06aafff391f23997518cf0e7",
"body": "Add 10 analysis-pipeline knobs (min sample size/runtime, target power, CI\nlevel, CUPED window/overlap/min-users, mSPRT tau factors, SRM threshold) to\nUpdateProjectRequest + GetCurrentProjectResponse. They flow through the\ngenerated Zod, the CLI `projects update` options and the `projects_update`\nMCP tool. prod-probe round-trips every knob under SHIPEASY_PROBE_MUTATE.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(api): expose per-project statistics knobs on projects update",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-05T22:17:34Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "7c22ce1b5049ff848f5fbe96cacea4295e213f5b",
"body": "…'get started' to setup\n\nOnboarding eval: bare \"set up metrics/alerting\" now confirms the platform is\nready and offers to create the first metric/alert (matching flags/experiments\nphrasing) instead of only interrogating; \"how do I get started with shipeasy in\nthis project\" now routes to shipeasy-setup even when the repo already looks\nShipeasy-shaped. onboarding.json 10/10 at K=1.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(skills): offer to create first metric/alert on bare setup; route …",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-05T22:13:26Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "72e89188220154938fe8d253df6d0f93d6c65fc8",
"body": "BREAKING. Relocate the experiment \"minimum effect\" model to match the\nstatistics (see experiment-platform/06-analysis.md):\n\n- metric `min_detectable_effect` -> `default_min_effect_of_interest`\n (a metric-level DEFAULT judgment, the effect *of interest* — renamed).\n- new per-attachment override `min\n[…]\nectable\n effect given observed variance + n, a read-only output.\n\nRegenerates the openapi types/zod, CLI commands, and MCP tools.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(api)!: split minimum effect of interest from detectable effect",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-05T17:55:35Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "aa6dd60c719772deee72b6fb951478790c30e73c",
"body": "Align the metrics tuning-knob guidance with the actual field name\n(default_min_effect_of_interest, per-experiment override\nmin_effect_of_interest, realized_mde in results) rather than the\nplaceholder minDetectableEffect.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(shipeasy-metrics): correct MDE knob to defaultMinEffectOfInterest",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-05T17:46:18Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "8c145a97e486577adfe8644c5b4ad18a5c546329",
"body": "…s; deterministic exp fixtures\n\nSkill:\n- Distinguish variation POINT (one) from variant ARMS (several): when the user\n didn't pin variants, propose a few candidate arms and let them select which to\n include (multi-select) — control + N treatments, with the traffic-split\n tradeoff.\n- New \"Statisti\n[…]\nchosen name\n (which flaked start between green_checkout_button and checkout_button).\n\nexperiments eval 4/4 at K=1, deterministic.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(shipeasy-experiments): multi-arm variants + all statistical knob…",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-05T17:44:11Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "a1d50beee2c0481c2b95e85764d33e7ccb731b64",
"body": "The list-before-create guard (a fresh *_list must precede each *_create)\nwas stdio-only, toggled by SHIPEASY_MCP_LIST_GUARD env. Make it work on\nthe hosted worker too, carried per-connection by an X-Shipeasy-List-Guard\nheader (env can't be per-connection on a Worker).\n\n- list-guard: setGuardSecret()\n[…]\n DISABLED (off, the hosted\n default) plus a JSON-safe //list-guard note, so it's present, annotated,\n and one edit away from on.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: list-before-create guard on the remote MCP + setup wiring",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-05T17:28:52Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "91c91bb76fc77dbd99084ad5a6d5926540a3eee0",
"body": "- Make the list-before-propose scan (events + metrics + alerts) a hard gate:\n don't propose the plan or create the rule until all three lists return. The\n original run proposed with \"saw [none]\" — no scan at all.\n- Surface, don't silently default, the knobs the user left open — chiefly\n windowHou\n[…]\n windowHours (the prompt gives no\n period, so the skill must land one, not omit it).\n\nalerts eval 4/4 at K=1 (args now verified).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(shipeasy-alerts): surface windowHours options + hard pre-scan gate",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-05T17:18:19Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "13bebb0f907ae9883d7fab073ef70050e4b84b60",
"body": "Every catalogued ErrorCode must be declared on >=1 operation (the spec.test\n'unused ErrorCode' guard). Drop CONFLICT, EXPERIMENT_NOT_FOUND,\nFEATURE_REQUIRES_UPGRADE, INVALID_JSON (dead/redundant — see @shipeasy/core);\ndocument PLAN_LIMIT on the create/start ops that enforce plan quotas\n(checkLimit) \n[…]\n their real ops.\nRegenerate the bundle + client (also picks up the committed tickets:public_create\nscope, fixing cli keys-scopes).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(openapi): reconcile ErrorCode catalogue with operations",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-05T17:14:26Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "b1a39c7b1d6ef668c0a57ce6c3b6c194553d34a9",
"body": "… nudge\n\nRunner (skills-eval):\n- Multi-turn auto-approve: after a turn, an outcome-gated case (expect_state)\n that only listed/proposed is resumed on the SAME session with an approval,\n so the agent carries its recommended default through to the create — the\n transport-level version of the standi\n[…]\nnow mandatory (an un-fired event\n makes the metric read zero), stated in step 3 and Hard rules.\n\nmetrics eval: 1/4 -> 4/4 at K=1.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(skills-eval,mcp): auto-accept consultative pauses + event-wiring…",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-05T17:10:01Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "a82fa381a822ec6dcfae40b9276088275cf1234c",
"body": "`shipeasy setup` and `shipeasy mcp install` now write the bound project\ninto each JSON MCP config (`headers: { \"X-Project-Id\": <uuid> }`), so a\nper-repo .mcp.json targets its own project without relying on the OAuth\nconsent-time pick. The header is not a credential — the remote MCP\nserver still auth\n[…]\ned-in project).\n- Codex HTTP MCP has no header flag, so it stays URL-only and notes that\n the project is chosen at OAuth consent.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(cli): pin project via X-Project-Id header in setup MCP wiring",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-05T17:06:13Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "9d017afdbd5e917b0ab48f3070f74d6cf044cc3e",
"body": "New this release: `shipeasy report-issue` (consent-gated setup-failure bug\nreporting to Shipeasy) with the production report key baked in; `sdk keys\ncreate --name/--scopes` (scopes validated against the spec enum); and the\nrequest helper now surfaces the admin API's field-level validation `detail`.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "chore(cli): release 2.6.0",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-05T16:40:29Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "331968b05a0fea064e912f7bbf1c2aab94049ff8",
"body": "Sets BAKED_REPORT_KEY to Shipeasy's own public client key (minted on the main\nproject, scoped to tickets:public_create only) so `shipeasy report-issue` /\nsetup-failure reporting is live. Client keys are public-by-design — safe to\nembed — and this one can do nothing but file a rate-limited, pending_a\n[…]\nT_KEY` check would have gone false once the constant held the\nreal key). SHIPEASY_REPORT_KEY still overrides for testing/rotation.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(cli): bake in the production report client key",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-05T15:37:13Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "a9a9da3d959df2c1005c2f870aab7f34a26402f5",
"body": "Recreate the app's /cli-auth/success look inline in the loopback page the\nCLI serves after browser auth: the on-brand animated beams backdrop,\ntranslucent card, purple check, \"finish automatically\" row + docs link,\nand a rotating \"Did you know?\" tip. Honours prefers-reduced-motion.\nReplaces the plain light/dark green-check card.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(cli): beams-background CLI auth loopback success/error page",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-05T15:35:50Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "8d513fc94c249177b93b0efac42ddd2f14e86f97",
"body": "…T model\n\nDrive the behavioural skills-eval with the GitHub Copilot CLI as an\nalternative to claude -p, selected via a user argument (--copilot /\n--agent copilot / SHIPEASY_EVAL_AGENT). The copilot runner forces the\ncheapest GPT model (gpt-5-mini, overridable via SHIPEASY_EVAL_COPILOT_MODEL),\nmirror\n[…]\nia ask_user);\n matchSkillToken maps a short plugin token (flags) to shipeasy-flags.\n- README + unit tests for the copilot parser.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(skills-eval): add copilot runner (--copilot), forces cheapest GP…",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-05T10:41:33Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "b3789ced3dea1b1015743fb9a24ad77bad4079d7",
"body": "…amed)\n\nThe TS SDK repo was renamed shipeasy-ai/sdk → shipeasy-ai/sdk-ts to match the\nother SDK repos. Update the docs-fetcher repo map so `docs get/list/skill`\n(and the GitHub Pages base) resolve the renamed repo.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "chore(openapi): point typescript docs at shipeasy-ai/sdk-ts (repo ren…",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-05T04:37:20Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "982a5a6d1006aaa2194daf618368438e2dfa9a0e",
"body": "…d snippets\n\nsdk-compile.test.ts asserted >5 extracted `ts` snippets importing @shipeasy/sdk,\nbut skills are language-neutral: their SDK call sites are {{SDK_SNIPPET:handle}}\nplaceholders baked at install time from the SDK's published docs. Until the SDK's\nGitHub Pages site is live, the bake degrade\n[…]\nting snippets are\nstill compiled by the it.each; baked ones flow in automatically once the docs\nsite publishes real `ts` snippets.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(skills-contract): guard on SDK_SNIPPET placeholders, not extracte…",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-05T04:37:20Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "5244dec18dc0d1e0727572a5ed221c996e7a9114",
"body": "- hero.svg chip now shows `npm install -g @shipeasy/cli && shipeasy setup`\n (was `claude plugin install shipeasy@shipeasy`); widened chip + smaller\n mono font to fit.\n- add hero.gif screencast under the hero, optimized 14.6MB→5.3MB\n (1440x900/401f → 900x563/12fps/96-color) to stay under GitHub's ~10MB\n image-proxy cap so it renders/animates reliably.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "docs(readme): fix hero install command + add optimized hero.gif",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-05T04:34:08Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "56a85ce50efc0a5a7b7f791190223f5679c90b14",
"body": "…te → propose → approve)\n\nReorient the create flows for the shipeasy-experiments, shipeasy-metrics,\nand shipeasy-alerts skills away from fire-and-forget auto-provisioning\ntoward a consultative loop: investigate the scoped surface the ask names\n(required), propose 2-4 variants, then STOP and wait for\n[…]\nthe eval system prompt so\na skill's own propose→provision step auto-approves in the eval, and\nrefresh the three create-case notes.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(skills): make experiments/metrics/alerts consultative (investiga…",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-05T04:19:11Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "5aebe35272b61820c7e59fd003ea5ce59f0c8eb7",
"body": "A 422 from the admin API carries a `detail` string (e.g.\n`scopes.0: Invalid enum value…`) alongside the generic `error: \"Validation\nfailed\"`. The CLI request helper only read `error`, so every validation failure\ncollapsed to \"Validation failed\" with no clue what was wrong. Now the thrown\nApiError message includes `detail` when present.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(cli): surface the admin API's field-level validation detail",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-05T04:05:26Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "6a0a9e562c5f5e744f7174790765eb9067f33c28",
"body": "…rize step\n\nThe list-guard signing secret was generated at module load via randomBytes(32).\nThe Cloudflare Workers runtime (mcp-worker imports @shipeasy/mcp/registry, which\npulls in list-guard) forbids generating random values in global scope, so the\nworker failed to boot with 'Disallowed operation \n[…]\n (MCP_AUTH_INSTRUCTIONS) and, under a coding-agent\nharness, a directive to authorize its own connection before running the wiring.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(mcp): lazy list-guard secret (workerd-safe) + CLI MCP OAuth autho…",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-05T03:56:24Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "c4d2a9d21c66ad0c0f3062fc0f2803d410fb8f47",
"body": "…tHog/Confidence into Shipeasy\n\nOn-demand, intentionally-invoked workflow skill (not an auto-triggering area\nskill). Router SKILL.md + a shared references/conventions.md (target model,\ngate/config/experiment decision, the 16-op targeting vocabulary, plan/execute\nflow, resume) and one references/<pla\n[…]\ndence) skills don't have.\n\nRegisters the skill in EXPECTED_SKILLS and the three host plugin.json\ndescriptions + docs/reference.md.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(skills): add shipeasy-migrate — port Statsig/Eppo/Optimizely/Pos…",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-05T03:41:23Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "8deaf461ed79085a12268918969ae3970dde1807",
"body": "Adds the two flags needed to mint a scoped, named client key (e.g. the CLI's own\n\"CLI main key\" for /cli/report). `--scopes` validates against the OpenAPI\nCreateKeyRequest scope enum read straight off the generated schema, so adding a\nscope to spec/components/schemas/keys.yaml extends the CLI automatically — no\nhardcoded list. Both flags flow into the CreateKeyRequest body (name + scopes\nwere already accepted by the API).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(cli): --name and --scopes on `sdk keys create`",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-05T03:34:02Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "203038774a8c9a9bfcb4397227ae1304b6677750",
"body": "Stage 3 of 3 — the CLI + agent surface for self-reported setup bugs:\n- `shipeasy report-issue` files a pending-approval bug to Shipeasy via the public\n POST /cli/report endpoint, collecting OS/Node/CLI version, project id, language\n and frameworks, plus the failing step + error. `--consent` is a H\n[…]\nelling out the ask-first, consent-required flow.\n- Adds the `tickets:public_create` scope to the OpenAPI key schema (spec source).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(cli): consent-gated setup-failure bug reporting",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-05T03:14:48Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "113bc34097dd2407db4665faec9647592e9dba93",
"body": "…opilot secrets\n\nThe setup command wired the hosted MCP server as the bare origin\n`https://mcp.shipeasy.ai`. The streamable-HTTP transport is served at\n`/mcp`; a bare-origin POST hits `/` and 404s (\"No handler for POST /\"),\nso every agent's MCP entry failed to initialize. Append the `/mcp` path.\n\nTh\n[…]\np, minting the ops key by reusing that token via a direct\nadmin-API call. No session -> the step degrades to a no-op, not a crash.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(cli): point MCP wiring at /mcp path and reuse session token for C…",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-05T00:53:44Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "fb706e0a9c7ff3ced7fc58d52cdef4c4247e10c8",
"body": "Replace the Claude-plugin-install headline CTA with the one-command CLI\npath (`npm install -g @shipeasy/cli` → `shipeasy setup`); demote the\nper-host plugin/skills tiers into a collapsible details block.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "docs: lead README install with global CLI + shipeasy setup",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-05T00:48:13Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "4a62a8646a760fbf3d845717fc7caab9c18caf4a",
"body": "…tice\n\nThe setup install multiselect let the user uncheck targets, but that only\ndeferred the install — de-selected folders still got a section in\nshipeasy-wiring.md, so the reading harness walked projects the user opted\nout of. Track de-selections and exclude them from the per-target loop, the\nbind\n[…]\nefore the shipeasy-mcp tools resolve.\nPer-agent reload commands for claude/cursor/copilot/codex/jules, generic\nfallback otherwise.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(cli): drop de-selected targets from wiring.md + add MCP reload no…",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-05T00:46:22Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "8894c17fc5fc48169b7c5a0a6f115802a9383e81",
"body": "The admin API returns codes from @shipeasy/core's ErrorCode catalogue that\nthe spec enum never picked up (METRIC_NOT_FOUND, METRIC_UNKNOWN_ID, the\nEXPERIMENT_* family, CONFLICT, PLAN_LIMIT, FEATURE_REQUIRES_UPGRADE,\nINVALID_JSON). The contract fuzz caught POST /api/admin/alert-rules returning\n`code:\n[…]\n's\nx-error-codes. Regenerated bundle + SDK types.\n\nAlso folds in the plan-tier enum (free/pro/business/enterprise) example update.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(openapi): sync ErrorCode enum with @shipeasy/core catalogue",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-04T22:18:28Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "12e72fa87797e7f6097057ed8100c1b9bdccf156",
"body": "When the user opts to launch a coding agent on shipeasy-wiring.md, pass that\nagent's skip-permission-prompts flag so it can read the checklist, edit entry\npoints, and write env unattended instead of stalling on an approval prompt for\nevery file op. Per-agent equivalent of Claude's --dangerously-skip\n[…]\n-dangerously-skip-permissions, codex →\n--dangerously-bypass-approvals-and-sandbox, cursor → --force, copilot →\n--allow-all-tools).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(setup): auto-approve the launched wiring agent",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-04T22:10:18Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "a102f304e5e8be46e19e04bf7e1410ce49022c2d",
"body": "…nstalls\n\n- Never add @shipeasy/react to JS/TS installs — it was sunset; the browser\n build ships inside @shipeasy/sdk (the @shipeasy/sdk/client export). Covers\n installArgv, sdkUpdateArgv, and the detect/scan install hints.\n- Map Claude to the `claude-code` skills-CLI name at project scope; bare\n\n[…]\nnvocation per\n agent instead of one process per skill, listing each skill's description so\n the customer can see what it is for.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(setup): drop nonexistent @shipeasy/react; batch + explain skill i…",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-04T22:06:44Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "f92b7e72bb224f7576f409ee6d0779eb7beeec33",
"body": "pnpm forwards the bare `docs` subcommand to `npm docs`, which opens this\npackage's npmjs page (@shipeasy/repo) in a browser instead of running the\n`docs` script (`turbo run docs`). So every commit touching openapi/cli/mcp\npopped open https://www.npmjs.com/package/@shipeasy/repo. Add the missing\n`run` and a note, and fix the same `pnpm docs` footgun in the CLI/MCP READMEs.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(hooks): use `pnpm run docs`, not bare `pnpm docs`, in pre-commit",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-04T21:56:19Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "9e415194ecf0952a1aeda4debde4fed0429266ed",
"body": "Ships the list-token guard (guarded *_create requires a fresh listToken from\nits *_list sibling) and its SHIPEASY_MCP_LIST_GUARD[_WINDOW_MINUTES] env knobs.\nPushing mcp/ to main triggers publish-mcp.yml (npm + MCP registry).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "chore(mcp): release 2.3.0 — env-configurable list-before-create guard",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-04T21:36:54Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "9ea6baddac74f6569daf300fa16488092d025f62",
"body": "Replace the all-or-nothing \"Run the SDK package install in N target(s)?\"\nconfirm with a multiselect (same picker as the agent selection). Each row\nshows the target path and which SDK + install command will run; unpicked\ntargets fall through to the existing deferred/wiring path.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(cli): let setup pick which targets get the SDK install",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-04T21:36:29Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "fe0bb8b671d05370d0690a37ce0bbac6d8fbc1db",
"body": "Expose the guard through env vars, so it configures straight from an\nmcp.json / settings.json `env` block:\n\n SHIPEASY_MCP_LIST_GUARD on|off (default on)\n SHIPEASY_MCP_LIST_GUARD_WINDOW_MINUTES number (default 10)\n\nWhen off, `*_create` tools stop advertising `listToken` and the se\n[…]\ne and memoized (an MCP server's env is fixed for its lifetime),\nkeeping schema advertisement and runtime enforcement in lock-step.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(mcp): make the list-before-create guard configurable via env",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-04T21:34:43Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "727515315e16a0707b4ca6d608c9054f9b93eef6",
"body": "Refuse a guarded `*_create` unless the caller echoes back the short-lived\n`listToken` its sibling `*_list` handed out — a forcing-function so the\nassistant checks for an existing resource before creating a duplicate.\n\n- Per-family: a create is guarded iff it ends in `_create` AND a\n `${family}_list\n[…]\ness\n as model guidance, not a security boundary. `listToken` never reaches the\n wire (generated dispatch reads only named args).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(mcp): guard *_create tools behind a fresh list-token",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-04T21:21:49Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "9ab2b19062dd9e9a2478837527a0716d89063259",
"body": "ok() previously JSON.stringify'd the payload verbatim, so a successful call\nwith no content came back as a bare \"[]\", \"{}\", or — for a void mutation —\nJSON.stringify(undefined), i.e. a non-string `text`. Cheaper models read that\nempty payload as a failure and retry a call that already succeeded.\n\nEm\n[…]\nuilt-in\nreturning a tool_reference block, upstream of our MCP) — it fixes the analogous\nempty-result misread for the tools we own.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(mcp): give tool results an explicit \"success but empty\" envelope",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-04T21:08:31Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "fe9472916894a4e672cbc6d66b5e309e93bd472b",
"body": "The ops_alerts_list dedup step checks for a rule already watching THIS\nmetric+threshold; the list will normally hold other unrelated rules, and\nthat must not block creating a genuinely new alert.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(skills): clarify alerts dedup — list isn't expected to be empty",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-04T20:50:19Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "de4ffe83c92e7596dbea892ca1e081a0477decf2",
"body": "Address skills-eval routing misses under Haiku:\n\n- shipeasy-alerts: state plainly that Shipeasy IS the app's metrics + alerting\n backend, so \"ping me if our error rate climbs above N%\" builds the\n event->metric->rule chain here instead of being punted to Grafana/Sentry/Slack\n or stalling on \"whic\n[…]\n change existing copy, find the backing key with\n i18n_keys_list; don't grep the source for the string (it isn't a code literal).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(skills): sharpen alerts/see/i18n routing for weak-model runs",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-04T20:37:10Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "2a7fc296f2a2e4087b3cdcd951b25e752f4ae0ee",
"body": "Make the eval order-independent and self-contained:\n\n- setupState can now pre-seed alert rules (event -> metric -> alert), so\n mutate-existing alert cases no longer depend on run order or on the\n hardest create-case succeeding first. The seed metric is deliberately\n domain-word-free so its name c\n[…]\new.\n- alerts/error-rate-threshold -> payment domain so the metric it creates can't\n collide with the experiments checkout metric.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "test(skills-eval): seed alert rules + de-overlap metrics/alerts cases",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-04T20:36:57Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "914d18b2f93f8072b1667dd15fbb93e86fa87711",
"body": "`shipeasy upgrade` brings a machine's Shipeasy install up to date in one\nverb: self-updates the CLI (npm/pnpm/yarn/bun), refreshes the coding-agent\nwiring (Claude plugin / MCP registration) and the marketplace how-to skills,\nand offers (never forces) an `@shipeasy/sdk` bump per onboarded target.\n\n`s\n[…]\ned flag to one level and the other's opts\ncome back empty (a --dry-run that silently runs for real). Covered by a\nregression test.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(cli): add `shipeasy upgrade` + `upgrade skills`",
"author_name": "shipeasy-ai",
"author_login": null,
"committed_at": "2026-07-04T20:18:27Z",
"body_truncated": true,
"is_coding_agent": true
}
],
"releases_count": 0,
"commits_last_year": 512,
"latest_release_at": null,
"latest_release_tag": null,
"releases_from_tags": false,
"days_since_last_push": 0,
"active_weeks_last_year": 14,
"days_since_latest_release": null,
"mean_days_between_releases": null
},
"community": {
"has_readme": true,
"has_license": false,
"has_description": true,
"has_contributing": false,
"health_percentage": 37,
"has_issue_template": false,
"has_code_of_conduct": false,
"has_pull_request_template": false
},
"ecosystem": {
"packages": [
{
"name": "@shipeasy/cli",
"exists": true,
"license": "MIT",
"keywords": [],
"ecosystem": "npm",
"matches_repo": true,
"registry_url": "https://www.npmjs.com/package/@shipeasy/cli",
"is_deprecated": false,
"latest_version": "2.7.0",
"repository_url": "https://github.com/shipeasy-ai/shipeasy",
"versions_count": 24,
"total_downloads": null,
"dependents_count": null,
"deprecation_note": null,
"maintainers_count": 1,
"monthly_downloads": 2095,
"first_published_at": "2026-05-12T20:03:29.133000Z",
"latest_published_at": "2026-07-21T03:49:19.696000Z",
"latest_version_yanked": null,
"days_since_latest_publish": 2
},
{
"name": "@shipeasy/mcp",
"exists": true,
"license": "MIT",
"keywords": [
"mcp",
"model-context-protocol",
"mcp-server",
"feature-flags",
"feature-gates",
"feature-management",
"feature-toggles",
"ab-testing",
"split-testing",
"experimentation",
"experiments",
"kill-switch",
"dynamic-config",
"remote-config",
"progressive-delivery",
"feature-rollout",
"canary-release",
"i18n",
"internationalization",
"localization",
"translations",
"shipeasy",
"claude",
"claude-code",
"cursor",
"windsurf",
"ai-agent",
"llm-tools"
],
"ecosystem": "npm",
"matches_repo": true,
"registry_url": "https://www.npmjs.com/package/@shipeasy/mcp",
"is_deprecated": false,
"latest_version": "2.4.0",
"repository_url": "https://github.com/shipeasy-ai/shipeasy",
"versions_count": 14,
"total_downloads": null,
"dependents_count": null,
"deprecation_note": null,
"maintainers_count": 1,
"monthly_downloads": 2087,
"first_published_at": "2026-05-12T20:03:22.874000Z",
"latest_published_at": "2026-07-11T20:17:11.811000Z",
"latest_version_yanked": null,
"days_since_latest_publish": 11
},
{
"name": "@shipeasy/openapi",
"exists": true,
"license": "MIT",
"keywords": [],
"ecosystem": "npm",
"matches_repo": true,
"registry_url": "https://www.npmjs.com/package/@shipeasy/openapi",
"is_deprecated": false,
"latest_version": "2.4.0",
"repository_url": "https://github.com/shipeasy-ai/shipeasy",
"versions_count": 10,
"total_downloads": null,
"dependents_count": null,
"deprecation_note": null,
"maintainers_count": 1,
"monthly_downloads": 2077,
"first_published_at": "2026-05-12T20:03:16.770000Z",
"latest_published_at": "2026-07-18T07:21:47.788000Z",
"latest_version_yanked": null,
"days_since_latest_publish": 5
}
]
},
"popularity": {
"forks": 0,
"stars": 0,
"watchers": 0,
"fork_history": {
"days": [],
"complete": true,
"collected": 0,
"total_forks": 0
},
"star_history": {
"days": [],
"complete": true,
"collected": 0,
"total_stars": 0,
"collected_at": null
},
"open_issues_and_prs": 0
},
"ai_readiness": {
"has_nix": false,
"example_dirs": [],
"has_llms_txt": false,
"has_dockerfile": false,
"has_mcp_signal": true,
"bootstrap_files": [],
"api_schema_files": [
"openapi/openapi.json",
"openapi/openapi.yaml",
"openapi/spec/openapi.yaml"
],
"has_devcontainer": false,
"typecheck_configs": [
"cli/tsconfig.json",
"mcp/tsconfig.json",
"openapi/tsconfig.json",
"skills-contract/tsconfig.json",
"skills-eval/tsconfig.json"
],
"toolchain_manifests": [],
"largest_source_bytes": 176624,
"source_files_sampled": 156,
"oversized_source_files": 2,
"agent_instruction_files": [],
"agent_instruction_max_bytes": null
},
"dependencies": {
"manifests": [
"cli/package.json",
"mcp/package.json",
"openapi/package.json",
"package.json",
"skills-contract/package.json",
"skills-eval/package.json"
],
"advisories": {
"error": null,
"scope": null,
"source": null,
"findings": [],
"collected": false,
"malicious": [],
"truncated": false,
"by_severity": {},
"advisory_count": 0,
"affected_count": 0,
"assessed_count": 0,
"malicious_count": 0,
"assessed_package": null,
"unassessed_count": 0,
"direct_affected_count": 0
},
"ecosystems": [
"npm"
],
"dependencies": [
{
"name": "@babel/parser",
"manifest": "cli/package.json",
"ecosystem": "npm",
"version_constraint": "^7.29.0"
},
{
"name": "@babel/traverse",
"manifest": "cli/package.json",
"ecosystem": "npm",
"version_constraint": "^7.29.0"
},
{
"name": "@babel/types",
"manifest": "cli/package.json",
"ecosystem": "npm",
"version_constraint": "^7.29.0"
},
{
"name": "@shipeasy/openapi",
"manifest": "cli/package.json",
"ecosystem": "npm",
"version_constraint": "workspace:^2.1.0"
},
{
"name": "chalk",
"manifest": "cli/package.json",
"ecosystem": "npm",
"version_constraint": "^5.3.0"
},
{
"name": "cli-table3",
"manifest": "cli/package.json",
"ecosystem": "npm",
"version_constraint": "^0.6.5"
},
{
"name": "commander",
"manifest": "cli/package.json",
"ecosystem": "npm",
"version_constraint": "^12.1.0"
},
{
"name": "conf",
"manifest": "cli/package.json",
"ecosystem": "npm",
"version_constraint": "^13.0.0"
},
{
"name": "open",
"manifest": "cli/package.json",
"ecosystem": "npm",
"version_constraint": "^10.1.0"
},
{
"name": "ora",
"manifest": "cli/package.json",
"ecosystem": "npm",
"version_constraint": "^8.1.0"
},
{
"name": "package-manager-detector",
"manifest": "cli/package.json",
"ecosystem": "npm",
"version_constraint": "^1.6.0"
},
{
"name": "prompts",
"manifest": "cli/package.json",
"ecosystem": "npm",
"version_constraint": "^2.4.2"
},
{
"name": "typescript",
"manifest": "cli/package.json",
"ecosystem": "npm",
"version_constraint": "^5.7.4"
},
{
"name": "zod",
"manifest": "cli/package.json",
"ecosystem": "npm",
"version_constraint": "^4.0.0"
},
{
"name": "@modelcontextprotocol/sdk",
"manifest": "mcp/package.json",
"ecosystem": "npm",
"version_constraint": "^1.29.0"
},
{
"name": "@shipeasy/openapi",
"manifest": "mcp/package.json",
"ecosystem": "npm",
"version_constraint": "workspace:^2.3.0"
},
{
"name": "package-manager-detector",
"manifest": "mcp/package.json",
"ecosystem": "npm",
"version_constraint": "^1.6.0"
},
{
"name": "typescript",
"manifest": "mcp/package.json",
"ecosystem": "npm",
"version_constraint": "^5.7.4"
},
{
"name": "zod",
"manifest": "mcp/package.json",
"ecosystem": "npm",
"version_constraint": "^4.0.0"
},
{
"name": "zod",
"manifest": "openapi/package.json",
"ecosystem": "npm",
"version_constraint": "^4.0.0"
},
{
"name": "@shipeasy/cli",
"manifest": "skills-contract/package.json",
"ecosystem": "npm",
"version_constraint": "workspace:*"
},
{
"name": "@shipeasy/mcp",
"manifest": "skills-contract/package.json",
"ecosystem": "npm",
"version_constraint": "workspace:*"
},
{
"name": "@shipeasy/sdk",
"manifest": "skills-contract/package.json",
"ecosystem": "npm",
"version_constraint": "^7.7.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": 0,
"merged_prs": 0,
"open_issues": 0,
"closed_ratio": null,
"closed_issues": 0,
"closed_unmerged_prs": 0
},
"bus_factor": null,
"bot_contributors": 0,
"top_contributors": [],
"contributors_sampled": null,
"top_contributor_share": null
},
"quality_signals": {
"has_ci": true,
"has_tests": true,
"ci_workflows": [
"ci.yml",
"contract-tests.yml",
"install-claude.yml",
"install-codex.yml",
"install-copilot.yml",
"install-skills-matrix.yml",
"prod-probe.yml",
"publish-cli.yml",
"publish-mcp.yml",
"publish-openapi.yml",
"skills-contract.yml"
],
"has_docs_dir": true,
"linter_configs": [],
"has_editorconfig": false,
"has_linter_config": false,
"has_precommit_config": false
},
"security_signals": {
"lockfiles": [
"pnpm-lock.yaml"
],
"scorecard": {
"checks": [
{
"name": "Binary-Artifacts",
"score": 10,
"reason": "no binaries found in the repo",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#binary-artifacts"
},
{
"name": "Branch-Protection",
"score": 0,
"reason": "branch protection not enabled on development/release branches",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
},
{
"name": "CI-Tests",
"score": null,
"reason": "no pull request found",
"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": 0,
"reason": "no update tool detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dependency-update-tool"
},
{
"name": "Fuzzing",
"score": 0,
"reason": "project is not fuzzed",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#fuzzing"
},
{
"name": "License",
"score": 0,
"reason": "license file not detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
},
{
"name": "Maintained",
"score": 0,
"reason": "project was created within the last 90 days. Please review its contents carefully",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#maintained"
},
{
"name": "Packaging",
"score": 10,
"reason": "packaging workflow detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
},
{
"name": "Pinned-Dependencies",
"score": 0,
"reason": "dependency not pinned by hash detected -- score normalized to 0",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
},
{
"name": "SAST",
"score": 0,
"reason": "no SAST tool detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
},
{
"name": "Security-Policy",
"score": 0,
"reason": "security policy file not detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy"
},
{
"name": "Signed-Releases",
"score": null,
"reason": "no releases found",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#signed-releases"
},
{
"name": "Token-Permissions",
"score": 0,
"reason": "detected GitHub workflow tokens with excessive permissions",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
},
{
"name": "Vulnerabilities",
"score": 0,
"reason": "10 existing vulnerabilities detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
}
],
"commit": "0a8071c4432ee583c42927e9cc2371267848d7f1",
"ran_at": "2026-07-23T15:01:00Z",
"aggregate_score": 2.4,
"scorecard_version": "v5.5.0"
},
"has_codeql_workflow": false,
"has_security_policy": false,
"has_dependabot_config": false
},
"contribution_flow": {
"collected": true,
"ci_last_run_at": "2026-07-23T09:21:41Z",
"oldest_open_prs": [],
"last_merged_pr_at": null,
"ci_last_conclusion": "SUCCESS",
"oldest_open_issues": []
}
},
"config": {
"disabled_metrics": [],
"disabled_categories": [],
"disabled_components": {}
},
"source": {
"url": "https://github.com/shipeasy-ai/shipeasy",
"host": "github.com",
"name": "shipeasy",
"owner": "shipeasy-ai"
},
"metrics": {
"overall": {
"key": "overall",
"band": "at_risk",
"name": "Overall health",
"note": null,
"notes": [],
"value": 40,
"inputs": {
"security": 24,
"vitality": 39,
"community": 25,
"governance": 43,
"engineering": 66
},
"components": []
},
"categories": [
{
"key": "vitality",
"band": "at_risk",
"name": "Vitality",
"value": 39,
"weight": 0.22,
"metrics": [
{
"key": "development_activity",
"band": "moderate",
"name": "Development activity",
"note": null,
"notes": [],
"value": 64,
"inputs": {
"commits_last_year": 512,
"human_commit_share": 1,
"days_since_last_push": 0,
"active_weeks_last_year": 14
},
"components": [
{
"key": "push_recency",
"name": "Push recency",
"detail": "last push 0 days ago",
"points": 36,
"status": "met",
"details": [
{
"code": "push_recency",
"params": {
"days": 0
}
}
],
"max_points": 36
},
{
"key": "commit_cadence",
"name": "Commit cadence",
"detail": "14/52 weeks with commits",
"points": 9.7,
"status": "partial",
"details": [
{
"code": "commit_cadence_weeks",
"params": {
"weeks": 14
}
}
],
"max_points": 36
},
{
"key": "commit_volume",
"name": "Commit volume",
"detail": "512 commits in the last year",
"points": 18,
"status": "met",
"details": [
{
"code": "commits_last_year",
"params": {
"count": 512
}
}
],
"max_points": 18
},
{
"key": "openssf_scorecard_maintained",
"name": "OpenSSF Scorecard: Maintained",
"detail": "project was created within the last 90 days. Please review its contents carefully",
"points": 0,
"status": "missed",
"details": [],
"max_points": 10
}
]
},
{
"key": "release_discipline",
"band": "critical",
"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": 1,
"inputs": {
"releases_count": 0
},
"components": [
{
"key": "ships_releases",
"name": "Ships releases",
"detail": "no releases published",
"points": 0,
"status": "missed",
"details": [
{
"code": "no_releases_published",
"params": {}
}
],
"max_points": 27
},
{
"key": "release_recency",
"name": "Release recency",
"detail": "no releases",
"points": 0,
"status": "missed",
"details": [
{
"code": "no_releases",
"params": {}
}
],
"max_points": 36
},
{
"key": "release_cadence",
"name": "Release cadence",
"detail": "no releases",
"points": 0,
"status": "missed",
"details": [
{
"code": "no_releases",
"params": {}
}
],
"max_points": 27
},
{
"key": "openssf_scorecard_signed_releases",
"name": "OpenSSF Scorecard: Signed-Releases",
"detail": "no releases found",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_data",
"params": {}
}
],
"max_points": 10
}
]
},
{
"key": "abandonment",
"band": "excellent",
"name": "Abandonment",
"note": null,
"notes": [],
"value": 100,
"inputs": {
"cap": null,
"state": "unverified",
"guards": [],
"signals": [],
"red_flag": false,
"multiplier_pct": 100,
"declared_reason": null,
"unverified_reason": "repository_too_young",
"unanswered_open_prs": null,
"unanswered_open_issues": null,
"days_since_last_merged_pr": null,
"days_since_last_human_commit": null,
"days_since_last_human_commit_is_floor": false
},
"components": [
{
"key": "project_is_still_maintained",
"name": "Project is still maintained",
"detail": "maintenance record not established from the collected data",
"points": 100,
"status": "met",
"details": [
{
"code": "abandonment_unverified",
"params": {}
}
],
"max_points": 100
}
]
}
],
"description": "Is the project alive — is code being written and are releases shipping?"
},
{
"key": "community",
"band": "critical",
"name": "Community & Adoption",
"value": 25,
"weight": 0.18,
"metrics": [
{
"key": "popularity",
"band": "critical",
"name": "Popularity & adoption",
"note": null,
"notes": [],
"value": 1,
"inputs": {
"forks": 0,
"stars": 0,
"watchers": 0,
"growth_state": "unverified",
"growth_factor_pct": 100,
"growth_unverified_reason": "no_history"
},
"components": [
{
"key": "stars",
"name": "Stars",
"detail": "0 stars",
"points": 0,
"status": "missed",
"details": [
{
"code": "stars",
"params": {
"count": 0
}
}
],
"max_points": 60
},
{
"key": "forks",
"name": "Forks",
"detail": "0 forks",
"points": 0,
"status": "missed",
"details": [
{
"code": "forks",
"params": {
"count": 0
}
}
],
"max_points": 25
},
{
"key": "watchers",
"name": "Watchers",
"detail": "0 watchers",
"points": 0,
"status": "missed",
"details": [
{
"code": "watchers",
"params": {
"count": 0
}
}
],
"max_points": 15
}
]
},
{
"key": "community_health",
"band": "critical",
"name": "Community health",
"note": null,
"notes": [],
"value": 25,
"inputs": {
"has_readme": true,
"has_license": false,
"has_contributing": false,
"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": "no license file detected",
"points": 0,
"status": "missed",
"details": [
{
"code": "license_absent",
"params": {}
}
],
"max_points": 22.5
},
{
"key": "contributing_guide",
"name": "CONTRIBUTING guide",
"detail": null,
"points": 0,
"status": "missed",
"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": 63,
"inputs": {
"packages": [
"@shipeasy/cli",
"@shipeasy/mcp",
"@shipeasy/openapi"
],
"dependents": null,
"ecosystems": "npm",
"total_downloads": null,
"monthly_downloads": 6259
},
"components": [
{
"key": "monthly_downloads",
"name": "Monthly downloads",
"detail": "6,259 downloads/month across npm",
"points": 50.6,
"status": "partial",
"details": [
{
"code": "downloads_monthly",
"params": {
"count": 6259,
"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": "at_risk",
"name": "Sustainability & Governance",
"value": 43,
"weight": 0.24,
"metrics": [
{
"key": "responsiveness",
"band": "critical",
"name": "Issue & PR responsiveness",
"note": "Excluded from scoring (no data or not applicable): Issue resolution, PR acceptance. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"issue_resolution",
"pr_acceptance"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 1,
"inputs": {
"merged_prs": 0,
"open_issues": 0,
"closed_issues": 0,
"issue_closed_ratio": null,
"closed_unmerged_prs": 0
},
"components": [
{
"key": "issue_resolution",
"name": "Issue resolution",
"detail": "no issues or no data",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_issues_or_data",
"params": {}
}
],
"max_points": 46.75
},
{
"key": "pr_acceptance",
"name": "PR acceptance",
"detail": "no decided pull requests or no data",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_decided_prs_or_data",
"params": {}
}
],
"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": 40,
"inputs": {
"followers": 1,
"owner_type": "Organization",
"is_verified": null,
"owner_login": "shipeasy-ai",
"public_repos": 9,
"account_age_days": 87
},
"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 shipeasy-ai",
"points": 2.2,
"status": "partial",
"details": [
{
"code": "owner_followers",
"params": {
"count": 1,
"login": "shipeasy-ai"
}
}
],
"max_points": 25
},
{
"key": "track_record",
"name": "Track record",
"detail": "9 public repos, account ~0 yr old",
"points": 7.8,
"status": "partial",
"details": [
{
"code": "public_repos",
"params": {
"count": 9
}
},
{
"code": "account_age_years",
"params": {
"years": 0
}
}
],
"max_points": 25
}
]
},
{
"key": "package_maintenance",
"band": "excellent",
"name": "Package maintenance",
"note": null,
"notes": [],
"value": 100,
"inputs": {
"packages": [
"@shipeasy/cli",
"@shipeasy/mcp",
"@shipeasy/openapi"
],
"ecosystems": "npm",
"any_deprecated": false,
"min_days_since_publish": 2
},
"components": [
{
"key": "published_resolvable",
"name": "Published & resolvable",
"detail": "3 package(s) on npm",
"points": 25,
"status": "met",
"details": [
{
"code": "packages_published",
"params": {
"count": 3,
"ecosystems": "npm"
}
}
],
"max_points": 25
},
{
"key": "publish_recency",
"name": "Publish recency",
"detail": "latest publish 2 days ago",
"points": 35,
"status": "met",
"details": [
{
"code": "publish_recency",
"params": {
"days": 2
}
}
],
"max_points": 35
},
{
"key": "version_history",
"name": "Version history",
"detail": "24 published versions",
"points": 20,
"status": "met",
"details": [
{
"code": "published_versions",
"params": {
"count": 24
}
}
],
"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": "moderate",
"name": "Engineering Quality",
"value": 66,
"weight": 0.2,
"metrics": [
{
"key": "engineering_practices",
"band": "moderate",
"name": "Engineering practices",
"note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: CI-Tests. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"openssf_scorecard_ci_tests"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 60,
"inputs": {
"has_ci": true,
"has_tests": true,
"has_editorconfig": false,
"has_linter_config": false,
"has_precommit_config": false
},
"components": [
{
"key": "ci_workflows",
"name": "CI workflows",
"detail": "11 workflow(s)",
"points": 24,
"status": "met",
"details": [
{
"code": "ci_workflows",
"params": {
"count": 11
}
}
],
"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": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 16
},
{
"key": "pre_commit_hooks",
"name": "Pre-commit hooks",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 9.6
},
{
"key": "editorconfig",
"name": ".editorconfig",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 6.4
},
{
"key": "openssf_scorecard_ci_tests",
"name": "OpenSSF Scorecard: CI-Tests",
"detail": "no pull request found",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_data",
"params": {}
}
],
"max_points": 20
}
]
},
{
"key": "documentation",
"band": "good",
"name": "Documentation",
"note": null,
"notes": [],
"value": 75,
"inputs": {
"topics": [],
"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": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 10
},
{
"key": "wiki",
"name": "Wiki",
"detail": null,
"points": 10,
"status": "met",
"details": [],
"max_points": 10
}
]
}
],
"description": "Are baseline engineering and documentation practices in place?"
},
{
"key": "security",
"band": "critical",
"name": "Security",
"value": 24,
"weight": 0.16,
"metrics": [
{
"key": "security_posture",
"band": "critical",
"name": "Security posture",
"note": "Excluded from scoring (no data or not applicable): CI-Tests, Signed-Releases. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"ci_tests",
"signed_releases"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 24,
"inputs": {
"source": "openssf_scorecard",
"checks_evaluated": 16,
"scorecard_version": "v5.5.0",
"checks_inconclusive": 2,
"scorecard_aggregate": 2.4
},
"components": [
{
"key": "binary_artifacts",
"name": "Binary-Artifacts",
"detail": "no binaries found in the repo",
"points": 7.5,
"status": "met",
"details": [],
"max_points": 7.5
},
{
"key": "branch_protection",
"name": "Branch-Protection",
"detail": "branch protection not enabled on development/release branches",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "ci_tests",
"name": "CI-Tests",
"detail": "no pull request found",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_data",
"params": {}
}
],
"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": "no update tool detected",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "fuzzing",
"name": "Fuzzing",
"detail": "project is not fuzzed",
"points": 0,
"status": "missed",
"details": [],
"max_points": 5
},
{
"key": "license",
"name": "License",
"detail": "license file not detected",
"points": 0,
"status": "missed",
"details": [],
"max_points": 2.5
},
{
"key": "maintained",
"name": "Maintained",
"detail": "project was created within the last 90 days. Please review its contents carefully",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "packaging",
"name": "Packaging",
"detail": "packaging workflow detected",
"points": 5,
"status": "met",
"details": [],
"max_points": 5
},
{
"key": "pinned_dependencies",
"name": "Pinned-Dependencies",
"detail": "dependency not pinned by hash detected -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 5
},
{
"key": "sast",
"name": "SAST",
"detail": "no SAST tool detected",
"points": 0,
"status": "missed",
"details": [],
"max_points": 5
},
{
"key": "security_policy",
"name": "Security-Policy",
"detail": "security policy file not detected",
"points": 0,
"status": "missed",
"details": [],
"max_points": 5
},
{
"key": "signed_releases",
"name": "Signed-Releases",
"detail": "no releases found",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_data",
"params": {}
}
],
"max_points": 7.5
},
{
"key": "token_permissions",
"name": "Token-Permissions",
"detail": "detected GitHub workflow tokens with excessive permissions",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "vulnerabilities",
"name": "Vulnerabilities",
"detail": "10 existing vulnerabilities detected",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
}
]
},
{
"key": "high_risk_jurisdiction_exposure",
"band": "excellent",
"name": "High-Risk Jurisdiction Exposure",
"note": "Only high-confidence self-published location evidence affects this multiplier. Ambiguous matches are review-only; country evidence is not proof of nationality, citizenship, legal registration, malicious intent, or sanctions status.",
"notes": [
{
"code": "jurisdiction_evidence_limits",
"params": {}
}
],
"value": 100,
"inputs": {
"meaning": "self-published location evidence; not nationality or citizenship",
"red_flag": false,
"exposures": [],
"policy_countries": [
"Russia",
"Iran",
"North Korea"
],
"review_only_matches": 0,
"assessed_self_published_locations": 1
},
"components": [
{
"key": "policy_exposure_multiplier",
"name": "Policy exposure multiplier",
"detail": "no confirmed policy-scope location match",
"points": 100,
"status": "met",
"details": [
{
"code": "jurisdiction_no_match",
"params": {}
}
],
"max_points": 100
}
]
}
],
"description": "Are visible security and supply-chain practices strong, with no malicious dependency and no unresolved high-risk jurisdiction exposure?"
},
{
"key": "ai_readiness",
"band": "moderate",
"name": "AI Readiness",
"value": 57,
"weight": 0,
"metrics": [
{
"key": "ai_agent_context",
"band": "at_risk",
"name": "Agent context & guidance",
"note": null,
"notes": [],
"value": 40,
"inputs": {
"has_llms_txt": false,
"legible_history_share": 1,
"agent_instruction_files": [],
"agent_instruction_max_bytes": null
},
"components": [
{
"key": "agent_instructions",
"name": "Agent instructions",
"detail": "no CLAUDE.md / AGENTS.md / editor rules",
"points": 0,
"status": "missed",
"details": [
{
"code": "no_agent_instructions",
"params": {}
}
],
"max_points": 45
},
{
"key": "machine_readable_docs_llms_txt",
"name": "Machine-readable docs (llms.txt)",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 15
},
{
"key": "legible_commit_history",
"name": "Legible commit history",
"detail": "100 of 100 human commits state their intent (structured subject or explanatory body)",
"points": 40,
"status": "met",
"details": [
{
"code": "legible_history",
"params": {
"legible": 100,
"sampled": 100
}
}
],
"max_points": 40
}
]
},
{
"key": "ai_verify_loop",
"band": "moderate",
"name": "Verify loop (build / test / typecheck)",
"note": null,
"notes": [],
"value": 53,
"inputs": {
"has_nix": false,
"has_tests": true,
"lockfiles": [
"pnpm-lock.yaml"
],
"has_dockerfile": false,
"typed_language": true,
"bootstrap_files": [],
"has_devcontainer": false,
"has_linter_config": false,
"typecheck_configs": [
"cli/tsconfig.json",
"mcp/tsconfig.json",
"openapi/tsconfig.json",
"skills-contract/tsconfig.json",
"skills-eval/tsconfig.json"
],
"agent_commit_share": 0.98,
"toolchain_manifests": [],
"dependency_bot_commit_share": 0
},
"components": [
{
"key": "one_command_bootstrap",
"name": "One-command bootstrap",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 18
},
{
"key": "automated_tests",
"name": "Automated tests",
"detail": null,
"points": 22,
"status": "met",
"details": [],
"max_points": 22
},
{
"key": "lint_format_config",
"name": "Lint / format config",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 11
},
{
"key": "static_type_checking",
"name": "Static type checking",
"detail": "cli/tsconfig.json, mcp/tsconfig.json, openapi/tsconfig.json, skills-contract/tsconfig.json, skills-eval/tsconfig.json",
"points": 11,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": "cli/tsconfig.json, mcp/tsconfig.json, openapi/tsconfig.json, skills-contract/tsconfig.json, skills-eval/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": "98 of the last 100 commits agent-authored or agent-credited",
"points": 10,
"status": "met",
"details": [
{
"code": "agent_authored_commits",
"params": {
"count": 98,
"sampled": 100
}
}
],
"max_points": 10
},
{
"key": "automated_maintenance",
"name": "Automated maintenance",
"detail": "no automated dependency updates observed",
"points": 0,
"status": "missed",
"details": [
{
"code": "no_dependency_automation",
"params": {}
}
],
"max_points": 8
},
{
"key": "openssf_scorecard_pinned_dependencies",
"name": "OpenSSF Scorecard: Pinned-Dependencies",
"detail": "dependency not pinned by hash detected -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 10
}
]
},
{
"key": "ai_code_legibility",
"band": "excellent",
"name": "Code legibility for models",
"note": null,
"notes": [],
"value": 99,
"inputs": {
"primary_language": "TypeScript",
"largest_source_bytes": 176624,
"source_files_sampled": 156,
"oversized_source_files": 2
},
"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": "2/156 source files over 60KB",
"points": 54.3,
"status": "partial",
"details": [
{
"code": "oversized_source_files",
"params": {
"kb": 60,
"sampled": 156,
"oversized": 2
}
}
],
"max_points": 55
}
]
},
{
"key": "ai_interfaces",
"band": "moderate",
"name": "Machine-readable interfaces",
"note": null,
"notes": [],
"value": 60,
"inputs": {
"example_dirs": [],
"has_mcp_signal": true,
"api_schema_files": [
"openapi/openapi.json",
"openapi/openapi.yaml",
"openapi/spec/openapi.yaml"
]
},
"components": [
{
"key": "api_schema_openapi_graphql_proto",
"name": "API schema (OpenAPI/GraphQL/proto)",
"detail": "openapi/openapi.json, openapi/openapi.yaml, openapi/spec/openapi.yaml",
"points": 40,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": "openapi/openapi.json, openapi/openapi.yaml, openapi/spec/openapi.yaml"
}
}
],
"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": null,
"points": 0,
"status": "missed",
"details": [],
"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": [
"Contributor list unavailable",
"GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository",
"deps.dev does not index npm:@shipeasy/cli@2.7.0; advisories assessed against the repository dependency graph instead"
],
"report_type": "repository",
"generated_at": "2026-07-23T15:01:06.060606Z",
"schema_version": "0.27.0",
"badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/s/shipeasy-ai/shipeasy.svg",
"full_name": "shipeasy-ai/shipeasy",
"license_state": "absent",
"license_spdx": null
}