Files
market/scripts
Yige 6c303ef21f feat(invoice-organizer): 声明为可安装并 pin 到已合并 commit / make Invoice Organizer installable (#118)
接 #117。那个 PR 只登记了条目本身(`availability: listing-only`),用户在市场里**看得到、装不了**。
本 PR 补齐可安装所需的证据链。

Follow-up to #117, which only listed the entry (`listing-only`) —
visible in the marketplace but
not installable. This PR supplies the evidence chain required for
installation.

## 改动 / Changes

- `agent.json` 新增 `contentSource`,pin 到 #117 的合并 commit `42a29e9`
- sidecar 的 `provenance.content` 与之**归一化后逐字一致**
(两侧字段名按各自 schema 写:agent.json 侧是 `repoUrl`(`marketPointerSchema`
的必填字段名),
sidecar 侧是 `url`;`normalizeContentSource` 里 `input.url ?? input.repoUrl`
把两者统一成 `url`,
  比对发生在归一化之后,取的是 `{kind, url, path, ref, sha256}` 五元组)
- `governance.compliance.reviewedRef` 绑定同一 commit;`reviewedAt` 与
  `timestamps.reviewedAt` 取同一天
- `governance.availability` 翻成 `installable`
- **移除** sidecar 的 `stewardship: "official"` 与 `branding.relationship:
"official"`

## 为什么移除 `stewardship: official`(这一条值得单独看)

`normalize/sidecar.ts` 只允许 `bundled-builtin` / `system-agent` /
`official-pointer`
三种受信来源自称 official。**inline agent 不在其中**,命中即
`catalog.sidecar-forbidden-provider-claim` —— **整份 sidecar 被丢弃**,
静默回落到 `agent.json` 派生的 legacy 默认值。

在 dev 实例上实测确认(同步到 `42a29e9` 之后):

```
客户端拿到的 governance:
  {"availability":"listing-only","license":{"state":"unknown"},
   "redistribution":"verify-package-terms","listingMaintainer":{...}}
sidecar 里写的却是:
  license: {state:"known", value:"MIT", evidencePath:"LICENSE"},  redistribution: "allowed"
catalogDiagnostics: null
```

也就是说:sidecar 被整份丢弃,而**维护者没有任何反馈**。

`dingtalk-workspace` 也有同样的 `stewardship: "official"`,它的 sidecar
**同样一直在被静默丢弃**
(实测它的客户端 governance 与本条目改之前完全一样)。这条不在本 PR 范围内,
建议单独处理;DesireCore 主仓库那边我另外记了一条「sidecar 被拒的诊断没有透出到任何 API」的缺口。

## 验证 / Verification

直接调用客户端的真实代码路径(不是照着文档推断):

```
hydrateCatalogSidecar                  success=true   diagnostics=[]
compareMarketCatalogConsistency        consistent=true  mismatches=[]
evaluateCatalogAcquisitionEligibility  allowed=true   reasons=[]

legacy  provenance.content: {"kind":"git","url":"https://github.com/desirecore/market.git",
                             "path":"agents/invoice-organizer","ref":"42a29e99a0…"}
sidecar provenance.content: {同上,逐字一致}
```

`compareMarketCatalogConsistency` 对 inline agent 会**逐字比对**
`provenance.content`;
不一致会让整份 sidecar 静默降级回 listing-only,而 Python 校验器对 inline 条目
直接跳过这项比对(`_validate_content_consistency` 对 inline 早退),抓不到。
所以这一项只能靠上面这条客户端侧的验证兜住。

## 校验 / Validation

```
validate_catalog_metadata.py --require-complete   0 error, 129 warning, agents=4, sidecars=74
validate-i18n.py                                  0 error, 129 warning
translate.py --check                              ok
gen-collection-children.py --check                ok
```
129 条 warning 全部来自 `skills/*` 的存量条目,`invoice-organizer` **零命中**。
2026-09-04 09:03:21 -04:00
..