Skip to content

docs: close code origin audit - #2907

Open
Astro-Han wants to merge 6 commits into
mainfrom
docs/code-origin-audit-closeout
Open

docs: close code origin audit#2907
Astro-Han wants to merge 6 commits into
mainfrom
docs/code-origin-audit-closeout

Conversation

@Astro-Han

Copy link
Copy Markdown
Contributor

Summary

  • preserve the reconstructed 25-item SCANOSS evidence and classifications in a permanent audit report
  • record the Astryx and Vercel AI SDK source material in LICENSE after confirming that NOTICE needs no change
  • mark the retained Computer Use Skill origin record as independently reviewed while keeping that review distinct from any legal or ASF release determination
  • narrow the Computer Use provenance wording to the specific binary-recovered facts instead of characterizing the implementation as a whole
  • keep bootstrap tool products, accounts, and governing terms pending contributor confirmation
  • fix the version-pinned Apache notice override so third-party appendices in the root LICENSE cannot leak into a dependency notice

Refs #2669

Verification

  • node --test scripts/generate-third-party-notices.test.mjs
  • npm run check:third-party-notices
  • node scripts/gen-bundled-skill-catalog.mjs --check
  • npx biome check scripts/generate-third-party-notices.mjs scripts/generate-third-party-notices.test.mjs packages/runtime/resources/bundled-skills/provenance.json
  • git diff --check

Repository-wide tests and typecheck were not run because this change is limited to documentation, provenance data, and the focused notice-generator regression.

Review focus and remaining gates

  • The human contributor of record reviews the final diff, all 25 classifications, and the LICENSE/NOTICE conclusion.
  • The bootstrap contributor confirms the exact Raft, Claude, and Codex products or model versions, account/agreement types, governing terms and dates, and any provenance protection used.
  • Before code transfer or release review, obtain an appropriate human legal/ASF determination about retaining the specifically documented facts recovered through static inspection, or independently replace those facts and dependent code.

The second item does not block publishing or reviewing this report. The third item is deliberately narrow: it does not classify the Computer Use implementation as a whole as binary-derived.

AI assistance

OpenAI Codex reconstructed the recovered scanner evidence, compared it with the fixed source snapshot, and drafted the report, attribution changes, and regression fix. The human contributor of record retains responsibility for accuracy, provenance, licensing, and the submission decision.

Checklist

  • Tests cover the generator change and fail without it
  • Lint, format, typecheck and the affected suites pass locally

Does this PR entail a change in behavior?

  • Yes — the generated Apache dependency notice is now scoped to the Apache license text
  • No

@Astro-Han

Copy link
Copy Markdown
Contributor Author

@jackwener, I’m filling in the bootstrap provenance record for this PR. Could you confirm what you remember about the initial repository work around May 19, 2026?

  • Which Raft product or version was used?
  • Which Claude and Codex products or models did it call?
  • Were they accessed through personal, team, enterprise, API, or other accounts? Which terms applied at the time?
  • Were any provenance or training-data protection settings enabled?
  • Did Raft orchestrate both Claude and Codex? Were any third-party source files or artifacts provided as input?

Rough answers are fine. If a detail is unknown or was not recorded, please say so. Please don’t include credentials or account identifiers. We’re documenting the history here, not asking you for a legal or ASF release decision.

中文对照:

@jackwener,我在补充这个 PR 的项目启动阶段来源记录。想请你确认一下对 2026 年 5 月 19 日前后初始仓库工作的记忆:

  • 当时使用的是哪个 Raft 产品或版本?
  • Raft 调用了哪些 Claude 和 Codex 产品或模型?
  • 这些工具是通过个人、团队、企业、API 还是其他类型的账号使用的?当时适用哪些条款?
  • 是否启用了来源保护、训练数据保护或类似设置?
  • 是否可以确认由 Raft 同时编排 Claude 和 Codex?是否向它们提供过第三方源文件或其他制品作为输入?

大致信息即可。不确定或没有留存的信息可以直接注明。请不要提供凭据或账号标识。这里是在记录历史事实,不是请你作出法律或 ASF 发布判断。

Posted via OpenAI Codex for @Astro-Han.
由 OpenAI Codex 代 @Astro-Han 发布。

@likun666661 likun666661 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found two provenance/compliance gaps in the closeout record.

Comment thread docs/code-origin-audit.md Outdated
| 14 | `packages/core/src/user-question.ts:7-19` | [`baochipham942-eng/code-agent`](https://github.com/baochipham942-eng/code-agent) v0.2.4, `src/shared/types.ts:489-501` (MIT) | 50% | Short structural types for questions, IDs, and answers. No distinctive shared expression. No attribution. |
| 15 | `packages/eval/src/__tests__/fixtures/writer-worker.ts:3-22` | [`agent-awareness`](https://www.npmjs.com/package/agent-awareness/v/0.4.5) 0.4.5, `src/commands/codex-hooks.ts:10-29` (MIT) | 86% | Small concurrency-test worker composed of standard file markers, a polling loop, and exit status. Candidate purpose and identifiers differ. No attribution. File is absent from current `main`. |
| 16 | `packages/runtime/src/http-response.ts:9-14` | [`different-ai/openwork`](https://github.com/different-ai/openwork) `alpha-macos-v0.14.1-alpha.982-1aeb1e4`, `apps/server/src/server.ts:869-874` (MIT) | 35% | Necessary Fetch API reconstruction after deleting encoding/length headers. No distinctive expression. No attribution. |
| 17 | `packages/runtime/src/model-protocol.ts:89-106,123-142,211-227,275-290` | [`talkio`](https://www.npmjs.com/package/talkio/v/1.0.0-alpha.1) 1.0.0-alpha.1, `src/types/common.ts:16-33,23-42,72-88,104-119` (Apache-2.0) | 14% | **Real third-party lineage, wrong candidate.** The file declares its adaptation from `@ai-sdk/provider-utils@5.0.25` (Apache-2.0). The fixed AI SDK source is now named in `LICENSE`; desktop notices already carry its exact license. |

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] Add the Apache modification notice to the adapted source file

This says model-protocol.ts already declares its adaptation from @ai-sdk/provider-utils@5.0.25, but the source header currently only says the shapes are “structurally equivalent” and “Maka-owned”; it does not identify the fixed version, the adaptation relationship, or that the file was modified. Since this PR classifies the file as real third-party lineage, adding the component only to the root LICENSE does not satisfy the Apache-2.0 §4(b) requirement for modified files to carry prominent notices stating that they were changed. Please update the model-protocol.ts header with the fixed source and Maka modification notice (or revise this lineage conclusion if adaptation is not what happened).

Comment thread docs/code-origin-audit.md
| Tool | Version | Scope | Data behavior | Preserved result |
|---|---:|---|---|---|
| ScanCode Toolkit | 32.5.0 | 2,542 tracked files; local license, copyright, and package analysis | Local only | The raw result expired; the contemporaneous count and conclusion are retained here |
| SCANOSS JS CLI | 0.40.2 | 2,231 files supported by its winnowing scanner | The public API received winnowing fingerprints with obfuscated file identifiers; it did not receive source files or repository-relative paths | The 2,231-file JSON and WFP were recovered locally and used to reconstruct the table below |

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Record hashes for the recovered scan artifacts

The report depends on the recovered 2,231-file JSON and WFP, but neither artifact is retained here and the report records no SHA-256, byte size, or stable storage location. Because the reproduction section correctly notes that a fresh response can differ as the SCANOSS knowledge base changes, future reviewers cannot verify that this table came from the recovered artifacts described here. Please record at least the SHA-256 and byte size of both files, and preferably their controlled storage location or a retained sanitized copy.

Generated-by: OpenAI Codex
The code origin audit classified `packages/runtime/src/model-protocol.ts` as
real third-party lineage adapted from the Apache-2.0 AI SDK, but the file
header disclosed neither the source nor the adaptation, and the report claimed
a declaration the file did not contain. Recording the component in the root
`LICENSE` alone does not meet the Apache-2.0 section 4(b) requirement that
modified files carry prominent notices stating that they were changed.

Add the source, fixed versions, and modification notice to the file header,
and separate the dependency-boundary claim from the ownership wording that
made the header read as an authorship statement.

Name `@ai-sdk/provider` alongside `@ai-sdk/provider-utils` in `LICENSE`. The
adapted material spans both packages: `JSONValue` and the `SharedV4` provider
option, provider reference, and file data shapes come from `@ai-sdk/provider`.

Pin both components to the versions installed when the adaptation was made
rather than the audit snapshot versions. Every adapted declaration is
byte-identical across the two ranges, so both pinnings identify the same
source material.

Record the verification evidence and its reproduction command in the report so
the lineage conclusion can be re-checked independently of the scanner, which
matched an unrelated candidate at 14%.

Generated-by: Claude Code
@Astro-Han
Astro-Han force-pushed the docs/code-origin-audit-closeout branch from cc70cd5 to 594dcd0 Compare August 20, 2026 03:33
The SCANOSS table covers only source code its winnowing scanner fingerprints.
Two categories of incoming material sit outside it and were previously
unrecorded.

`tool-output.ts` and `edit-replace.ts` state that they are adapted from
opencode, and the adaptation is substantial: the truncation helper follows
upstream line for line down to its local names and asymmetric newline
accounting, and the escape-normalizing regular expression is identical
character for character with its nine branches in upstream order. Upstream is
MIT and requires its notice to travel with the material, but "opencode"
appears in none of the four attribution surfaces.

The models.dev snapshot ships about 27,800 lines derived from an MIT database
with no attribution and no recorded snapshot revision. The entries are facts,
but the selection and arrangement are upstream's.

Both gaps have one cause: the notice generator derives its inventory from npm
production dependency trees, so vendored or adapted source and generated data
are invisible to it by construction. State that blind spot explicitly, since
it will hide the next such source too.

Correct entry 23. The candidate is `MIT + Commons Clause`, not the `MIT` the
scanner reported, which also makes the outcome summary's claim about
source-available candidates wrong as written. Maka's file is byte-identical to
it but demonstrably independent: this repository records it being created as
the shadcn helper and later losing `twMerge` with the Astryx migration.
Replace the weaker "no project-specific expression" reasoning with that
evidence.

Record that the recovered scan artifacts were not retained and cannot be
hashed after the fact, so the table is verifiable through each row's named
candidate rather than against the artifacts themselves.

Generated-by: Claude Code
The scoped Apache override in this branch keeps the root LICENSE third-party
appendices out of dependency notice sections. The committed artifact was
regenerated on main with the unscoped generator, so rebasing reintroduced the
leaked appendices and the check reported the artifact as stale.

Regenerating removes 140 lines of Maka's own third-party appendices from the
`@ai-sdk/provider-utils` section. No dependency entry changes.

Generated-by: Claude Code
The regression test located the provider-utils section by the exact string
`@ai-sdk/provider-utils@5.0.25`, so rebasing onto a main that had bumped the
dependency to 5.0.27 failed the test on a missing section rather than on the
leak it guards.

Match the package prefix instead. Reverting the generator to read the whole
root LICENSE still fails the test on the leaked `THIRD-PARTY COMPONENTS`
appendix, so the guarantee is unchanged.

Generated-by: Claude Code
@Astro-Han

Copy link
Copy Markdown
Contributor Author

@jackwener gentle ping — no rush on the bootstrap tooling question above, just flagging it in case it got buried.

"Don't remember" or "wasn't recorded" is a perfectly good answer — I'll record it as not retained and move on.

简体中文

轻轻提醒一下 —— 上面那条关于项目启动阶段工具来源的问题,不着急,只是怕被沉掉了。

「记不清了」或者「当时没记录」都是完全可以的回答,我会照实写成未留存,不会卡着你。

Posted via Claude Code for @Astro-Han.

The CLI keeps its own generated notice artifact behind
`check:cli-third-party-notices`, and the previous regeneration only covered the
desktop target. CI caught the CLI artifact still carrying the leaked root
LICENSE appendices.

Removes the same 140 lines from the CLI artifact. No dependency entry changes.

Generated-by: Claude Code
@Astro-Han
Astro-Han requested a review from likun666661 August 20, 2026 07:32
@Astro-Han
Astro-Han marked this pull request as ready for review August 20, 2026 07:48
Astro-Han added a commit that referenced this pull request Aug 20, 2026
…tice

`@ai-sdk/provider-utils` ships no license file, so the generator substitutes
the root LICENSE as its Apache-2.0 text. It substituted the whole file. LICENSE
also carries Maka's THIRD-PARTY COMPONENTS section, so 140 lines describing
trycua/cua and the bundled fonts were filed under one npm package in both
release notices — attributing material to a party that has nothing to do with
it, in the artifact whose only job is to attribute correctly.

Cut at the section header instead. The defect scales with LICENSE: every entry
added there lands in that package's notice, which is what surfaced it.

PR #2907 carries the same two-line fix for the same reason. It is repeated here
because this branch adds LICENSE entries, and without it those entries would
ship inside the provider-utils notice. Whichever lands second drops it.

Generated-by: Claude Code
Astro-Han added a commit that referenced this pull request Aug 20, 2026
The code origin audit (#2907) found two pieces of third-party material that
ship in every release and appear in none of Maka's attribution surfaces, both
for the same structural reason: neither is an npm package, and the notice
generator walks npm production dependency trees only.

`tool-output.ts` and `edit-replace.ts` already said in prose that they adapt
opencode, and the adaptation is real — the escape-normalizing replacer's regular
expression and its nine branches are carried over unchanged. Prose is not the
notice MIT requires. Each file now records source, revision, license, and
copyright, and LICENSE carries the permission notice so it travels with the
release. Both files are mixed-origin, so the notice is scoped to the adapted
material and neither file gets a whole-file SPDX identifier; the in-repo
precedent for a wholly-upstream file, `packages/ui/src/astryx-chat-reasoning.tsx`,
is deliberately not followed here.

The generated models.dev modules are a different claim and are worded as one.
Individual model records are facts and are not copyrightable; what comes from
upstream is the selection and arrangement — which providers and fields are
carried, and upstream's normalized structures such as `lifecycle` and
`thinkingOptions.efforts`. The LICENSE entry says that rather than calling it
copied code.

The headers also name the payload. models.dev publishes a rolling document with
no version in its body, so the generator stamps the sync date and the sha256 of
the exact api.json it read. That is provenance, not reproducibility: upstream
serves whatever is current, so the digest tells you whether a file still matches
its stated source, not how to fetch that source again. Re-running the sync
against the snapshot these files were built from reproduces both bodies
byte-for-byte, which is what makes the recorded digest checkable.

Closes the first exit criterion of #3270.

Generated-by: Claude Code
Astro-Han added a commit that referenced this pull request Aug 20, 2026
The generator's inventory is the npm production dependency closure. That is a
complete answer to "which npm packages ship", and a structurally blind one to
"what else ships": vendored, adapted, and generated-from-upstream material is
not a package, so no amount of checking the walk's output can reach it. The
previous commit's LICENSE entries were therefore guarded by nothing — an
attribution header could be dropped in a routine edit and both release notices
would still regenerate clean.

Declare that material instead, in `scripts/non-npm-sources.mjs`, and check each
declaration against the tree it describes: LICENSE must carry the copyright
line, every listed file must exist, and each must still contain its marker. The
marker is pinned to something that should not change silently — the upstream
revision for adapted source, the attribution line for generated data, which a
routine re-sync preserves and a dropped attribution does not. Failing means
failing generation, so `check:third-party-notices` and its CLI twin now gate it
and both notices carry the sections.

Validation takes its content as arguments rather than reading the filesystem,
so the failure paths are exercised in `non-npm-sources.test.mjs` against a stub
instead of by editing tracked source. All three were also falsified end to end
against the real tree before this commit.

Both notice titles drop "npm": they no longer describe only npm.

Two limits worth stating. This is a declared inventory, not a discovery
mechanism — it proves what is declared is still true, not that everything true
is declared; a scan for undeclared upstream markers belongs on top of #2907's
audit, which is the allowlist such a scan needs. And neither notice check runs
on pull requests today; both run only in the ASF source candidate workflow, so
this gate fires at release preparation rather than at review.

Generated-by: Claude Code
Astro-Han added a commit that referenced this pull request Aug 20, 2026
…tice

`@ai-sdk/provider-utils` ships no license file, so the generator substitutes
the root LICENSE as its Apache-2.0 text. It substituted the whole file. LICENSE
also carries Maka's THIRD-PARTY COMPONENTS section, so 140 lines describing
trycua/cua and the bundled fonts were filed under one npm package in both
release notices — attributing material to a party that has nothing to do with
it, in the artifact whose only job is to attribute correctly.

Cut at the section header instead. The defect scales with LICENSE: every entry
added there lands in that package's notice, which is what surfaced it.

PR #2907 carries the same two-line fix for the same reason. It is repeated here
because this branch adds LICENSE entries, and without it those entries would
ship inside the provider-utils notice. Whichever lands second drops it.

Generated-by: Claude Code
Astro-Han added a commit that referenced this pull request Aug 20, 2026
The code origin audit (#2907) found two pieces of third-party material that
ship in every release and appear in none of Maka's attribution surfaces, both
for the same structural reason: neither is an npm package, and the notice
generator walks npm production dependency trees only.

`tool-output.ts` and `edit-replace.ts` already said in prose that they adapt
opencode, and the adaptation is real — the escape-normalizing replacer's regular
expression and its nine branches are carried over unchanged. Prose is not the
notice MIT requires. Each file now records source, revision, license, and
copyright, and LICENSE carries the permission notice so it travels with the
release. Both files are mixed-origin, so the notice is scoped to the adapted
material and neither file gets a whole-file SPDX identifier; the in-repo
precedent for a wholly-upstream file, `packages/ui/src/astryx-chat-reasoning.tsx`,
is deliberately not followed here.

The generated models.dev modules are a different claim and are worded as one.
Individual model records are facts and are not copyrightable; what comes from
upstream is the selection and arrangement — which providers and fields are
carried, and upstream's normalized structures such as `lifecycle` and
`thinkingOptions.efforts`. The LICENSE entry says that rather than calling it
copied code.

The headers also name the payload. models.dev publishes a rolling document with
no version in its body, so the generator stamps the sync date and the sha256 of
the exact api.json it read. That is provenance, not reproducibility: upstream
serves whatever is current, so the digest tells you whether a file still matches
its stated source, not how to fetch that source again. Re-running the sync
against the snapshot these files were built from reproduces both bodies
byte-for-byte, which is what makes the recorded digest checkable.

Closes the first exit criterion of #3270.

Generated-by: Claude Code
Astro-Han added a commit that referenced this pull request Aug 20, 2026
The generator's inventory is the npm production dependency closure. That is a
complete answer to "which npm packages ship", and a structurally blind one to
"what else ships": vendored, adapted, and generated-from-upstream material is
not a package, so no amount of checking the walk's output can reach it. The
previous commit's LICENSE entries were therefore guarded by nothing — an
attribution header could be dropped in a routine edit and both release notices
would still regenerate clean.

Declare that material instead, in `scripts/non-npm-sources.mjs`, and check each
declaration against the tree it describes: LICENSE must carry the copyright
line, every listed file must exist, and each must still contain its marker. The
marker is pinned to something that should not change silently — the upstream
revision for adapted source, the attribution line for generated data, which a
routine re-sync preserves and a dropped attribution does not. Failing means
failing generation, so `check:third-party-notices` and its CLI twin now gate it
and both notices carry the sections.

Validation takes its content as arguments rather than reading the filesystem,
so the failure paths are exercised in `non-npm-sources.test.mjs` against a stub
instead of by editing tracked source. All three were also falsified end to end
against the real tree before this commit.

Both notice titles drop "npm": they no longer describe only npm.

Two limits worth stating. This is a declared inventory, not a discovery
mechanism — it proves what is declared is still true, not that everything true
is declared; a scan for undeclared upstream markers belongs on top of #2907's
audit, which is the allowlist such a scan needs. And neither notice check runs
on pull requests today; both run only in the ASF source candidate workflow, so
this gate fires at release preparation rather than at review.

Generated-by: Claude Code
Astro-Han added a commit that referenced this pull request Aug 20, 2026
…tice

`@ai-sdk/provider-utils` ships no license file, so the generator substitutes
the root LICENSE as its Apache-2.0 text. It substituted the whole file. LICENSE
also carries Maka's THIRD-PARTY COMPONENTS section, so 140 lines describing
trycua/cua and the bundled fonts were filed under one npm package in both
release notices — attributing material to a party that has nothing to do with
it, in the artifact whose only job is to attribute correctly.

Cut at the section header instead. The defect scales with LICENSE: every entry
added there lands in that package's notice, which is what surfaced it.

PR #2907 carries the same two-line fix for the same reason. It is repeated here
because this branch adds LICENSE entries, and without it those entries would
ship inside the provider-utils notice. Whichever lands second drops it.

Generated-by: Claude Code
Astro-Han added a commit that referenced this pull request Aug 20, 2026
The code origin audit (#2907) found two pieces of third-party material that
ship in every release and appear in none of Maka's attribution surfaces, both
for the same structural reason: neither is an npm package, and the notice
generator walks npm production dependency trees only.

`tool-output.ts` and `edit-replace.ts` already said in prose that they adapt
opencode, and the adaptation is real — the escape-normalizing replacer's regular
expression and its nine branches are carried over unchanged. Prose is not the
notice MIT requires. Each file now records source, revision, license, and
copyright, and LICENSE carries the permission notice so it travels with the
release. Both files are mixed-origin, so the notice is scoped to the adapted
material and neither file gets a whole-file SPDX identifier; the in-repo
precedent for a wholly-upstream file, `packages/ui/src/astryx-chat-reasoning.tsx`,
is deliberately not followed here.

The generated models.dev modules are a different claim and are worded as one.
Individual model records are facts and are not copyrightable; what comes from
upstream is the selection and arrangement — which providers and fields are
carried, and upstream's normalized structures such as `lifecycle` and
`thinkingOptions.efforts`. The LICENSE entry says that rather than calling it
copied code.

The headers also name the payload. models.dev publishes a rolling document with
no version in its body, so the generator stamps the sync date and the sha256 of
the exact api.json it read. That is provenance, not reproducibility: upstream
serves whatever is current, so the digest tells you whether a file still matches
its stated source, not how to fetch that source again. Re-running the sync
against the snapshot these files were built from reproduces both bodies
byte-for-byte, which is what makes the recorded digest checkable.

Closes the first exit criterion of #3270.

Generated-by: Claude Code
Astro-Han added a commit that referenced this pull request Aug 20, 2026
The generator's inventory is the npm production dependency closure. That is a
complete answer to "which npm packages ship", and a structurally blind one to
"what else ships": vendored, adapted, and generated-from-upstream material is
not a package, so no amount of checking the walk's output can reach it. The
previous commit's LICENSE entries were therefore guarded by nothing — an
attribution header could be dropped in a routine edit and both release notices
would still regenerate clean.

Declare that material instead, in `scripts/non-npm-sources.mjs`, and check each
declaration against the tree it describes: LICENSE must carry the copyright
line, every listed file must exist, and each must still contain its marker. The
marker is pinned to something that should not change silently — the upstream
revision for adapted source, the attribution line for generated data, which a
routine re-sync preserves and a dropped attribution does not. Failing means
failing generation, so `check:third-party-notices` and its CLI twin now gate it
and both notices carry the sections.

Validation takes its content as arguments rather than reading the filesystem,
so the failure paths are exercised in `non-npm-sources.test.mjs` against a stub
instead of by editing tracked source. All three were also falsified end to end
against the real tree before this commit.

Both notice titles drop "npm": they no longer describe only npm.

Two limits worth stating. This is a declared inventory, not a discovery
mechanism — it proves what is declared is still true, not that everything true
is declared; a scan for undeclared upstream markers belongs on top of #2907's
audit, which is the allowlist such a scan needs. And neither notice check runs
on pull requests today; both run only in the ASF source candidate workflow, so
this gate fires at release preparation rather than at review.

Generated-by: Claude Code
Astro-Han added a commit that referenced this pull request Aug 20, 2026
…tice

`@ai-sdk/provider-utils` ships no license file, so the generator substitutes
the root LICENSE as its Apache-2.0 text. It substituted the whole file. LICENSE
also carries Maka's THIRD-PARTY COMPONENTS section, so 140 lines describing
trycua/cua and the bundled fonts were filed under one npm package in both
release notices — attributing material to a party that has nothing to do with
it, in the artifact whose only job is to attribute correctly.

Cut at the section header instead. The defect scales with LICENSE: every entry
added there lands in that package's notice, which is what surfaced it.

PR #2907 carries the same two-line fix for the same reason. It is repeated here
because this branch adds LICENSE entries, and without it those entries would
ship inside the provider-utils notice. Whichever lands second drops it.

Generated-by: Claude Code
Astro-Han added a commit that referenced this pull request Aug 20, 2026
The code origin audit (#2907) found two pieces of third-party material that
ship in every release and appear in none of Maka's attribution surfaces, both
for the same structural reason: neither is an npm package, and the notice
generator walks npm production dependency trees only.

`tool-output.ts` and `edit-replace.ts` already said in prose that they adapt
opencode, and the adaptation is real — the escape-normalizing replacer's regular
expression and its nine branches are carried over unchanged. Prose is not the
notice MIT requires. Each file now records source, revision, license, and
copyright, and LICENSE carries the permission notice so it travels with the
release. Both files are mixed-origin, so the notice is scoped to the adapted
material and neither file gets a whole-file SPDX identifier; the in-repo
precedent for a wholly-upstream file, `packages/ui/src/astryx-chat-reasoning.tsx`,
is deliberately not followed here.

The generated models.dev modules are a different claim and are worded as one.
Individual model records are facts and are not copyrightable; what comes from
upstream is the selection and arrangement — which providers and fields are
carried, and upstream's normalized structures such as `lifecycle` and
`thinkingOptions.efforts`. The LICENSE entry says that rather than calling it
copied code.

The headers also name the payload. models.dev publishes a rolling document with
no version in its body, so the generator stamps the sync date and the sha256 of
the exact api.json it read. That is provenance, not reproducibility: upstream
serves whatever is current, so the digest tells you whether a file still matches
its stated source, not how to fetch that source again. Re-running the sync
against the snapshot these files were built from reproduces both bodies
byte-for-byte, which is what makes the recorded digest checkable.

Closes the first exit criterion of #3270.

Generated-by: Claude Code
Astro-Han added a commit that referenced this pull request Aug 20, 2026
The generator's inventory is the npm production dependency closure. That is a
complete answer to "which npm packages ship", and a structurally blind one to
"what else ships": vendored, adapted, and generated-from-upstream material is
not a package, so no amount of checking the walk's output can reach it. The
previous commit's LICENSE entries were therefore guarded by nothing — an
attribution header could be dropped in a routine edit and both release notices
would still regenerate clean.

Declare that material instead, in `scripts/non-npm-sources.mjs`, and check each
declaration against the tree it describes: LICENSE must carry the copyright
line, every listed file must exist, and each must still contain its marker. The
marker is pinned to something that should not change silently — the upstream
revision for adapted source, the attribution line for generated data, which a
routine re-sync preserves and a dropped attribution does not. Failing means
failing generation, so `check:third-party-notices` and its CLI twin now gate it
and both notices carry the sections.

Validation takes its content as arguments rather than reading the filesystem,
so the failure paths are exercised in `non-npm-sources.test.mjs` against a stub
instead of by editing tracked source. All three were also falsified end to end
against the real tree before this commit.

Both notice titles drop "npm": they no longer describe only npm.

Two limits worth stating. This is a declared inventory, not a discovery
mechanism — it proves what is declared is still true, not that everything true
is declared; a scan for undeclared upstream markers belongs on top of #2907's
audit, which is the allowlist such a scan needs. And neither notice check runs
on pull requests today; both run only in the ASF source candidate workflow, so
this gate fires at release preparation rather than at review.

Generated-by: Claude Code
Astro-Han added a commit that referenced this pull request Aug 20, 2026
…tice

`@ai-sdk/provider-utils` ships no license file, so the generator substitutes the
root LICENSE as its Apache-2.0 text. It substituted the whole file. LICENSE also
carries Maka's THIRD-PARTY COMPONENTS section, so 140 lines describing
trycua/cua and the bundled fonts were filed under one npm package in both
release notices — attributing material to a party that has nothing to do with
it, in the artifact whose only job is to attribute correctly.

Truncate at the section header. `split` returns the whole string when the
delimiter is absent, which would silently reinstate this exact bug and leave
`--check` demanding that the wrong output be committed, so the delimiter is
required rather than assumed.

The regression test comes from PR #2907, which found this defect and carries the
same fix. It deliberately matches the package without its version, so a routine
dependency bump does not fail it. Both are repeated here because this branch
adds LICENSE entries, and without the fix those entries would ship inside the
provider-utils notice. Whichever lands second drops the duplicate.

The test is wired into `check:release` and into the CI planner's CLI-package
inputs, so it runs on pull requests that touch it rather than only at release
preparation.

Generated-by: Claude Code
Astro-Han added a commit that referenced this pull request Aug 20, 2026
The code origin audit (#2907) found two pieces of third-party material that ship
in every release and appear in none of Maka's attribution surfaces, both for the
same structural reason: neither is an npm package, and the notice generator
walks npm production dependency trees only.

`tool-output.ts` and `edit-replace.ts` already said in prose that they adapt
opencode, and the adaptation is real — the escape-normalizing replacer's regular
expression and its nine branches are carried over unchanged. Prose is not the
notice MIT requires. Each file now records source, revision, license, and
copyright, and LICENSE carries the permission notice so it travels with the
release. Both files are mixed-origin, so the notice is scoped to the adapted
material and neither gets a whole-file SPDX identifier.

The LICENSE entry records the whole upstream chain rather than stopping at the
nearest one. opencode's edit.ts credits cline diff-apply and the gemini-cli
editCorrector; that file is Copyright 2025 Google LLC under Apache-2.0, and its
escape set shares its first eight branches, in order, with the replacer here.
opencode added the ninth and changed the pattern. Whether that shared sequence
carries protected expression is deliberately not adjudicated in LICENSE — it is
recorded so a licensing review can see the chain and decide.

The models.dev entry states what is copied instead of characterising it. The
earlier draft said the individual records were uncopyrightable facts and that
what came from upstream was the selection and arrangement. Both halves were
wrong: `sync-model-metadata.mjs` copies `model.name` and `model.description`
verbatim, and the snapshot carries 1779 upstream-authored descriptions; while
the selection and the ordering are the generator's, not upstream's. The entry
now lists the fields actually carried and leaves the legal conclusion out. The
MIT text was already reproduced in full, so nothing about the obligation
changes — only the accuracy of the sentence next to it.

Upstream copyright lines were checked against the upstream LICENSE files rather
than transcribed: both are `Copyright (c) 2025 opencode` and `Copyright (c) 2025
models.dev` verbatim.

The generated headers name their payload. models.dev serves a rolling document
with no version, so the generator stamps the sha256 of the data it extracted —
not of api.json, which would move whenever any of the ~40 dropped providers
changed and produce header-only diffs that say nothing about the file they sit
in. Hashing after extraction makes the digest describe what ships and keeps the
generator a pure function of its input: the same api.json produces the same
bytes on any day. Verified by running it twice against the pinned payload.

Closes the first exit criterion of #3270.

Generated-by: Claude Code
Astro-Han added a commit that referenced this pull request Aug 20, 2026
…ifact notice

The generator's inventory is the npm production dependency closure. That is a
complete answer to "which npm packages ship" and a structurally blind one to
"what else ships": vendored, adapted, and generated-from-upstream material is
not a package, so no amount of checking the walk's output can reach it. The
previous commit's LICENSE entries were guarded by nothing — an attribution
header could be dropped in a routine edit and both notices would still
regenerate clean.

The obvious move is to declare that material in the generator. The first draft
did, and it was wrong: it restated the repository, revision, copyright, and
license text that LICENSE already holds, creating a second authority that could
disagree with the first while every check passed. Passing a deliberately wrong
repository and revision to that validator was accepted without complaint, and
the notice printed them.

LICENSE is the authority. ASF release policy puts the notice there, it ships
with every artifact, and a human reviews it — and its THIRD-PARTY COMPONENTS
section is already structured. So the generator parses it and reproduces the
entries verbatim into both notices, and this module keeps only the one fact
LICENSE cannot express: which file carries each entry and what text must still
be in it.

That inverts what the check is worth:

- All four entries reach the notices, not the two a hand-written list happened
  to name. Geist is OFL-1.1 and was structurally undeclarable before, because
  the draft could only emit MIT.
- License text is LICENSE's own, not rebuilt from a template around a
  hand-transcribed copyright line.
- The check runs both ways. A LICENSE entry with no carrier decision fails, so
  #2907's Vercel AI SDK and Astryx entries cannot land unanchored; a carrier
  decision with no LICENSE entry fails too.
- `trycua/cua` is now anchored. `palette.ts` calls itself a "faithful 1:1 port"
  — a stronger claim than the opencode adaptation — and nothing had been
  holding it.

The notices' own prose no longer implies more than it delivers: it says the
entries are LICENSE's section reproduced and checked against their carriers,
not that everything vendored has been found. Discovering undeclared material is
a scan whose allowlist is #2907's audit table, and it belongs there.

Validation takes its inputs as arguments, so every failure path is exercised
against fixtures rather than by editing tracked source. `non-npm-sources.mjs`
and both test files are wired into the CI planner's CLI-package inputs, the
Windows release path filter, and `check:release`, so changing the guard runs
the guard.

Generated-by: Claude Code
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants