Публічний реєстр
Звіт про здоров'я програмного забезпеченнясхема 0.27.0 · метрики 1.13.0 · 2026-07-23 15:01 UTC

shipeasy-ai / shipeasy

Shipeasy Claude Code plugin marketplace

TypeScriptЛіцензію не виявлено★ 0 зірок⑂ 0 форківз трав. 2026 р.Переглянути на GitHub ↗

shipeasy-ai/shipeasy має індекс здоров’я 40 зі 100, що відповідає смузі «У зоні ризику». Найвищий показник — Engineering Quality (66/100), найнижчий — Security (24/100). Останнє оновлення — сьогодні.

40
загалом / 100
У зоні ризику

Індекс здоров'я програмного забезпечення

Метрики згруповано у зважені категорії на шкалі 1–100. Загальна оцінка починається як їхнє середнє; коли публічні дані активують Політику юрисдикцій високого ризику, рейтинг коригується й отримує верхню межу 49 («Під ризиком»). Готовність до ШІ не входить до індексу.

40
Відмінний85-100Зразковий; відповідає практично всім перевіреним критеріям
Добрий70-84Здоровий; незначні прогалини
Помірний50-69Прийнятний, але з помітними прогалинами; рекомендовано перевірку
У зоні ризику30-49Суттєві слабкі місця; впровадження потребує обережності
Критичний1-29Серйозні проблеми (покинутий, єдиний мейнтейнер, без базової гігієни)
ЖиттєздатністьСпільнота тавпровадженняСталість таврядуванняІнженернаякістьБезпекаГотовність доШІ

Профіль оцінок

Кожна вісь — окрема категорія. Форма важить більше, ніж середнє: здоровий об'єкт заповнює всю фігуру, тоді як профіль із піками та провалами означає, що сила в одному вимірі маскує ризик в іншому.

Власність

shipeasy.aiОрганізація
1 підписник9 публічних репозиторіївз квіт. 2026 р.

За цим репозиторієм стоїть організація — спільна, підзвітна опіка, здатна пережити будь-якого окремого мейнтейнера.

Пакетні екосистеми

Метрики за категоріями

Життєздатність

Чи живий проєкт — чи пишеться код і чи виходять релізи?

39У зоні ризику · 22% загального індексу
Як обчислюється оцінка
36/36Свіжість push — останній push 0 дн. тому
9.7/36Ритм комітів — 14/52 тижнів із комітами
18/18Обсяг комітів — 512 комітів за останній рік
0/10OpenSSF Scorecard: Maintained — project was created within the last 90 days. Please review its contents carefully
Використані вхідні дані
commits_last_year512
human_commit_share1
days_since_last_push0
active_weeks_last_year14
Як обчислюється оцінка
0/27Випускає релізи — релізів не опубліковано
0/36Свіжість релізів — релізів немає
0/27Ритм релізів — релізів немає
0/10OpenSSF Scorecard: Signed-Releases — немає даних
Використані вхідні дані
releases_count0
Виключено з оцінювання (немає даних або не застосовно): OpenSSF Scorecard: Signed-Releases. Залишкові ваги перенормовано.

Спільнота та впровадження

Чи має проєкт користувачів, завантаження, увагу та влаштовані умови для контриб’юторів?

25Критичний · 18% загального індексу
Як обчислюється оцінка
0/60Зірки — 0 зірок
0/25Форки — 0 форків
0/15Спостерігачі — 0 спостерігачів
Використані вхідні дані
forks0
stars0
watchers0
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history
Як обчислюється оцінка
22.5/22.5README
0/22.5Ліцензія — файлу ліцензії не виявлено
0/18Настанови CONTRIBUTING
0/13.5Кодекс поведінки
0/7.2Шаблон issue
0/6.3Шаблон PR
Використані вхідні дані
has_readmeтак
has_licenseні
has_contributingні
has_issue_templateні
has_code_of_conductні
has_pull_request_templateні
Як обчислюється оцінка
50.6/80Щомісячні завантаження — 6 259 завантажень/місяць у npm
0/20Залежні пакети в реєстрі — ця екосистема цього не повідомляє
Використані вхідні дані
packages@shipeasy/cli, @shipeasy/mcp, @shipeasy/openapi
dependents
ecosystemsnpm
total_downloads
monthly_downloads6 259
Виключено з оцінювання (немає даних або не застосовно): Залежні пакети в реєстрі. Залишкові ваги перенормовано.

Сталість та врядування

Чи переживе проєкт своїх людей — бас-фактор, реактивність, хто за ним стоїть і як супроводжуються пакети?

43У зоні ризику · 24% загального індексу
Як обчислюється оцінка
0/46.8Вирішення issue — немає issue або даних
0/38.3Прийняття PR — немає вирішених pull request-ів або даних
0/15OpenSSF Scorecard: Code-Review — Found 0/30 approved changesets -- score normalized to 0
Використані вхідні дані
merged_prs0
open_issues0
closed_issues0
issue_closed_ratio
closed_unmerged_prs0
Виключено з оцінювання (немає даних або не застосовно): Вирішення issue, Прийняття PR. Залишкові ваги перенормовано.

Власність та опіка

40У зоні ризику
Як обчислюється оцінка
30/30Підтримка власника — у власності організації
0/20Верифікований домен
2.2/25Охоплення власника — 1 підписників у shipeasy-ai
7.8/25Послужний список — 9 публічних репозиторіїв, вік облікового запису ~0 р.
Використані вхідні дані
followers1
owner_typeOrganization
is_verified
owner_loginshipeasy-ai
public_repos9
account_age_days87

Супровід пакетів

100Відмінний
Як обчислюється оцінка
25/25Опубліковано й доступно — 3 пакет(ів) у npm
35/35Свіжість публікацій — остання публікація 2 дн. тому
20/20Історія версій — 24 опублікованих версій
20/20Не застарілий — активний, не deprecated і не yanked
Використані вхідні дані
packages@shipeasy/cli, @shipeasy/mcp, @shipeasy/openapi
ecosystemsnpm
any_deprecatedні
min_days_since_publish2

Інженерна якість

Чи наявні базові інженерні практики та документація?

66Помірний · 20% загального індексу
Як обчислюється оцінка
24/24Процеси CI — 11 процес(ів) CI
24/24Наявні тести
0/16Конфігурація лінтера
0/9.6Pre-commit-хуки
0/6.4.editorconfig
0/20OpenSSF Scorecard: CI-Tests — немає даних
Використані вхідні дані
has_ciтак
has_testsтак
has_editorconfigні
has_linter_configні
has_precommit_configні
Виключено з оцінювання (немає даних або не застосовно): OpenSSF Scorecard: CI-Tests. Залишкові ваги перенормовано.
Як обчислюється оцінка
30/30README
25/25Каталог документації
0/15Сайт документації / домашня сторінка
10/10Опис репозиторію
0/10Теми
10/10Wiki
Використані вхідні дані
topics
has_wikiтак
homepage
has_readmeтак
has_docs_dirтак
has_descriptionтак

Безпека

Чи міцні видимі практики безпеки й ланцюга постачання, без непослабленої пов’язаності з юрисдикціями високого ризику?

24Критичний · 16% загального індексу

Стан безпеки

24Критичний
Як обчислюється оцінка
7.5/7.5Binary-Artifacts — no binaries found in the repo
0/7.5Branch-Protection — branch protection not enabled on development/release branches
0/2.5CI-Tests — немає даних
0/2.5CII-Best-Practices — no effort to earn an OpenSSF best practices badge detected
0/7.5Code-Review — Found 0/30 approved changesets -- score normalized to 0
0/2.5Contributors — project has 0 contributing companies or organizations -- score normalized to 0
10/10Dangerous-Workflow — no dangerous workflow patterns detected
0/7.5Dependency-Update-Tool — no update tool detected
0/5Fuzzing — project is not fuzzed
0/2.5Ліцензія — license file not detected
0/7.5Maintained — project was created within the last 90 days. Please review its contents carefully
5/5Packaging — packaging workflow detected
0/5Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
0/5SAST — no SAST tool detected
0/5Security-Policy — security policy file not detected
0/7.5Signed-Releases — немає даних
0/7.5Token-Permissions — detected GitHub workflow tokens with excessive permissions
0/7.5Vulnerabilities — 10 existing vulnerabilities detected
Використані вхідні дані
sourceopenssf_scorecard
checks_evaluated16
scorecard_versionv5.5.0
checks_inconclusive2
scorecard_aggregate2,4
Виключено з оцінювання (немає даних або не застосовно): ci_tests, signed_releases. Залишкові ваги перенормовано.

Готовність до ШІ

Наскільки репозиторій оснащений для розробки та супроводу за участі ШІ-агентів? Незалежний, експериментальний бейдж — вага 0.0, тож він подається окремо і не впливає на загальний індекс здоров'я.

57Помірний · 0% загального індексу
Як обчислюється оцінка
0/45Інструкції для агентів — немає CLAUDE.md / AGENTS.md / правил редактора
0/15Машиночитана документація (llms.txt)
40/40Читабельна історія комітів — намір зазначено у 100 з 100 людських комітів (структурований заголовок або пояснювальний текст)
Використані вхідні дані
has_llms_txtні
legible_history_share1
agent_instruction_files
agent_instruction_max_bytes
Як обчислюється оцінка
0/18Розгортання однією командою
22/22Автоматизовані тести
0/11Конфігурація лінтера / форматера
11/11Статична перевірка типів — cli/tsconfig.json, mcp/tsconfig.json, openapi/tsconfig.json, skills-contract/tsconfig.json, skills-eval/tsconfig.json
10/10Відтворюване середовище — lockfile
10/10Підтверджена практика роботи з агентами — 98 з останніх 100 комітів створено агентом або з його зазначенням
0/8Автоматизоване супроводження — автоматичних оновлень залежностей не виявлено
0/10OpenSSF Scorecard: Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
Використані вхідні дані
has_nixні
has_testsтак
lockfilespnpm-lock.yaml
has_dockerfileні
typed_languageтак
bootstrap_files
has_devcontainerні
has_linter_configні
typecheck_configscli/tsconfig.json, mcp/tsconfig.json, openapi/tsconfig.json, skills-contract/tsconfig.json, skills-eval/tsconfig.json
agent_commit_share0,98
toolchain_manifests
dependency_bot_commit_share0
Як обчислюється оцінка
45/45Типізований код — TypeScript (статично типізована)
54.3/55Керовані розміри файлів — 2/156 файлів вихідного коду понад 60 КБ
Використані вхідні дані
primary_languageTypeScript
largest_source_bytes176 624
source_files_sampled156
oversized_source_files2
Як обчислюється оцінка
40/40Схема API (OpenAPI/GraphQL/proto) — openapi/openapi.json, openapi/openapi.yaml, openapi/spec/openapi.yaml
20/20Сервер MCP
0/40Придатні до запуску приклади
Використані вхідні дані
example_dirs
has_mcp_signalтак
api_schema_filesopenapi/openapi.json, openapi/openapi.yaml, openapi/spec/openapi.yaml

Ключові факти

0зірок GitHub
-контриб'юторів
512комітів за останні 12 місяців
0днів від останнього пушу
0релізів
-бас-фактор
0відкритих issue
npmпакетних екосистем

Попередження щодо збору даних

  • 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

Докладніше

OpenSSF Scorecard 2.4 / 10
2.4сукупно

Незалежна, не прив'язана до інструментів оцінка безпеки від відкритого проєкту OpenSSF Scorecard. Кожна перевірка винагороджує практику безпеки, а не інструмент конкретного постачальника. Перевірки, які Scorecard не зміг визначити, позначено н/д і виключено з оцінки безпеки (вони ніколи не зараховуються як нуль).Scorecard v5.5.0 · 2026-07-23 15:01 UTC

10Binary-Artifactsno binaries found in the repo
0Branch-Protectionbranch protection not enabled on development/release branches
н/дCI-Testsno pull request found
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
0Code-ReviewFound 0/30 approved changesets -- score normalized to 0
0Contributorsproject has 0 contributing companies or organizations -- score normalized to 0
10Dangerous-Workflowno dangerous workflow patterns detected
0Dependency-Update-Toolno update tool detected
0Fuzzingproject is not fuzzed
0Licenselicense file not detected
0Maintainedproject was created within the last 90 days. Please review its contents carefully
10Packagingpackaging workflow detected
0Pinned-Dependenciesdependency not pinned by hash detected -- score normalized to 0
0SASTno SAST tool detected
0Security-Policysecurity policy file not detected
н/дSigned-Releasesno releases found
0Token-Permissionsdetected GitHub workflow tokens with excessive permissions
0Vulnerabilities10 existing vulnerabilities detected
Прямі залежності 23
РеєстрПакетОбмеження версіїМаніфест
npm@babel/parser^7.29.0cli/package.json
npm@babel/traverse^7.29.0cli/package.json
npm@babel/types^7.29.0cli/package.json
npm@shipeasy/openapiworkspace:^2.1.0cli/package.json
npmchalk^5.3.0cli/package.json
npmcli-table3^0.6.5cli/package.json
npmcommander^12.1.0cli/package.json
npmconf^13.0.0cli/package.json
npmopen^10.1.0cli/package.json
npmora^8.1.0cli/package.json
npmpackage-manager-detector^1.6.0cli/package.json
npmprompts^2.4.2cli/package.json
npmtypescript^5.7.4cli/package.json
npmzod^4.0.0cli/package.json
npm@modelcontextprotocol/sdk^1.29.0mcp/package.json
npm@shipeasy/openapiworkspace:^2.3.0mcp/package.json
npmpackage-manager-detector^1.6.0mcp/package.json
npmtypescript^5.7.4mcp/package.json
npmzod^4.0.0mcp/package.json
npmzod^4.0.0openapi/package.json
npm@shipeasy/cliworkspace:*skills-contract/package.json
npm@shipeasy/mcpworkspace:*skills-contract/package.json
npm@shipeasy/sdk^7.7.0skills-contract/package.json
Усі залежності не зібрано

Не вдалося зібрати розв'язаний набір залежностей для цього звіту: GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository

Звіт у форматі 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
}

Оцінки — це сигнали, а не гарантії. Вони відображають публічно видимі практики на GitHub — це не аудит коду й не гарантія безпеки.

Відсутні дані виключаються, а ваги перенормовуються — нуль за відсутність ніколи не ставиться. Методологія версіонована й відкрита: метрики v1.13.0, схема v0.27.0 — повна методологія · вікі метрик.

Як окремий результат виглядає на тлі всього реєстру: сукупна статистикаnpm.