build(workspace): [ENG-PM-01] use pinned Yarn with frozen installs

This commit is contained in:
Harvey Zhao committed 2026-09-10 19:09:26 +08:00
1 parent 9d1d5fda3d
commit 9a6cfe5c6b
17 files changed
+8888 -17372

No files matched your search

-2
View File
@@ -3,7 +3,5 @@
.DS_Store
node_modules
**/package-lock.json
!/package-lock.json
lerna-debug.log
yarn.lock
refactor/.cache/
+3
View File
@@ -17,6 +17,9 @@ The user requires one separate local Git commit for each completed refactor task
Include the task ID in the commit subject and include its implementation, tests, documentation,
and status updates together. Verify the commit before starting the next task. Do not bundle
multiple newly completed tasks or include unrelated work. This does not authorize pushing or publishing.
Use Yarn Classic 1.22.22 as packageManager and maintain only the root yarn.lock.
Use Node from .node-version; frozen Yarn installs and strict toolchain checks are required.
Bun remains an isolated evaluation and must not replace Yarn without a new user decision.
The user also authorizes installing needed dependencies and adding or improving reasonable
project scripts for the refactor without asking again for routine tooling choices.
Record their purpose and versions, use the appropriate workspace/dependency category, update
-17318
View File
File diff suppressed because it is too large. Load diff
+4 -1
View File
@@ -45,6 +45,8 @@
"browserslist": "last 1 Chrome version",
"devDependencies": {
"@antfu/eslint-config": "5.4.1",
"@vue/compiler-sfc": "3.5.28",
"@yarnpkg/lockfile": "1.1.0",
"cpy": "13.2.3",
"cross-env": "10.1.0",
"cross-spawn": "7.0.6",
@@ -59,7 +61,8 @@
"servor": "4.0.2",
"svgo": "4.1.0",
"terser": "5.51.2",
"typescript": "5.9.3",
"vite": "7.3.6"
},
"packageManager": "npm@11.19.0"
"packageManager": "yarn@1.22.22"
}
+1 -1
View File
@@ -26,7 +26,7 @@
| [docs 页面与编辑器测试](docs-browser-testing.md) | 复用已有 HTML、加载版本、隔离状态和补强文档 smoke |
| [多轮复盘与 npm 准入](release-reviews.md) | Chrome 验证分工、三轮全局复盘、问题闭环和候选发布门槛 |
| [工具链与发布](toolchain-release.md) | TypeScript、Bun、构建、版本管理和发布回退 |
| [已实现的开发环境](toolchain-setup.md) | Node/npm 固定版本、锁文件、安装命令和实际验证范围 |
| [已实现的开发环境](toolchain-setup.md) | Node/Yarn 固定版本、锁文件、安装命令和实际验证范围 |
| [全包大版本策略](version-policy.md) | 每包分别升级一个 major 的目标清单、兼容要求和版本落地步骤 |
| [GitHub CI/CD](github-ci-cd.md) | PR/兼容矩阵、构建报告、Pages、npm 发布及远端准入验证 |
| [AI 协作流程](ai-workflow.md) | AI 接续工作、任务边界、验证、记录和交接模板 |
+643
View File
@@ -0,0 +1,643 @@
{
"task": "ENG-PM-01",
"date": "2026-09-10",
"sourceCommit": "9d1d5fda",
"node": "24.21.0",
"packageManager": "yarn@1.22.22",
"platform": "win32-x64",
"yarnArchive": {
"url": "https://registry.npmjs.org/yarn/-/yarn-1.22.22.tgz",
"integrity": "sha512-prL3kGtyG7o9Z9Sv8IPfBNrWTDmXB4Qbes8A9rEzt6wkJV8mUvoirjU0Mp3GGAU06Y0XQyA3/2/RQFVuK7MTfg=="
},
"rootManifestSha256": "629a959414cb878b617e4410877d024fdd39cba9279dc20cdd6f5495052809c5",
"lockSha256": "5921f159477b65161b48d4b768f462cb05a537b6a257e62732ec9dfaf4d69e7e",
"lockSelectors": 1335,
"retainedSelectorVersionChanges": [],
"rootTools": [
{
"name": "@antfu/eslint-config",
"version": "5.4.1"
},
{
"name": "@vue/compiler-sfc",
"version": "3.5.28"
},
{
"name": "@yarnpkg/lockfile",
"version": "1.1.0"
},
{
"name": "cpy",
"version": "13.2.3"
},
{
"name": "cross-env",
"version": "10.1.0"
},
{
"name": "cross-spawn",
"version": "7.0.6"
},
{
"name": "dotenv",
"version": "17.2.4"
},
{
"name": "esbuild",
"version": "0.27.7"
},
{
"name": "eslint",
"version": "9.39.2"
},
{
"name": "eslint-plugin-format",
"version": "2.0.1"
},
{
"name": "glob",
"version": "13.0.6"
},
{
"name": "lerna",
"version": "8.2.4"
},
{
"name": "less",
"version": "4.5.1"
},
{
"name": "prompts",
"version": "2.4.2"
},
{
"name": "servor",
"version": "4.0.2"
},
{
"name": "svgo",
"version": "4.1.0"
},
{
"name": "terser",
"version": "5.51.2"
},
{
"name": "typescript",
"version": "5.9.3"
},
{
"name": "vite",
"version": "7.3.6"
}
],
"workspaceDependencies": [
{
"workspace": "artplayer",
"name": "option-validator",
"range": "^2.0.6",
"version": "2.0.6",
"matchesNpmBaseline": true
},
{
"workspace": "artplayer-plugin-danmuku-mask",
"name": "@mediapipe/selfie_segmentation",
"range": "^0.1.1675465747",
"version": "0.1.1675465747",
"matchesNpmBaseline": true
},
{
"workspace": "artplayer-plugin-danmuku-mask",
"name": "@tensorflow-models/body-segmentation",
"range": "^1.0.2",
"version": "1.0.2",
"matchesNpmBaseline": true
},
{
"workspace": "artplayer-plugin-danmuku-mask",
"name": "@tensorflow/tfjs-backend-cpu",
"range": "^4.21.0",
"version": "4.22.0",
"matchesNpmBaseline": true
},
{
"workspace": "artplayer-plugin-danmuku-mask",
"name": "@tensorflow/tfjs-backend-webgl",
"range": "^4.21.0",
"version": "4.22.0",
"matchesNpmBaseline": true
},
{
"workspace": "artplayer-plugin-danmuku-mask",
"name": "@tensorflow/tfjs-converter",
"range": "^4.21.0",
"version": "4.22.0",
"matchesNpmBaseline": true
},
{
"workspace": "artplayer-plugin-danmuku-mask",
"name": "@tensorflow/tfjs-core",
"range": "^4.21.0",
"version": "4.22.0",
"matchesNpmBaseline": true
},
{
"workspace": "artplayer-plugin-vast",
"name": "@glomex/vast-ima-player",
"range": "^1.21.2",
"version": "1.21.2",
"matchesNpmBaseline": true
},
{
"workspace": "artplayer-proxy-mediabunny",
"name": "mediabunny",
"range": "^1.43.1",
"version": "1.56.1",
"matchesNpmBaseline": true
}
],
"cleanInstall": {
"command": "yarn install --frozen-lockfile --non-interactive",
"freshNodeModules": true,
"lifecycleScriptsEnabled": true,
"lockUnchanged": true,
"seconds": 26.8
},
"strictToolchainPassed": true,
"tests": {
"passed": 20,
"failed": 0,
"scope": "19 existing Node tests plus toolchain guard integration test with 4 rejection cases",
"workspaceIncludingBaselineTests": 22
},
"lint": {
"command": "eslint scripts/check-toolchain.mjs test/toolchain.test.js --no-fix",
"passed": true
},
"libraryBuild": {
"command": "yarn build all",
"packages": 21,
"artifacts": [
{
"package": "artplayer",
"file": "artplayer.js",
"bytes": 134939,
"sha256": "9ad044a601dafc24f449b690403fb1c343b40e99ffb31043272189fc3c1e7bfa",
"matchesNpmBaseline": true
},
{
"package": "artplayer",
"file": "artplayer.legacy.js",
"bytes": 136659,
"sha256": "71eebcca3192000c58e20f2e3cb76e86c05e33b5a1fab0add20436a5933a3e87",
"matchesNpmBaseline": true
},
{
"package": "artplayer",
"file": "artplayer.mjs",
"bytes": 210198,
"sha256": "ac72f41624383ba853474161affb72b5887644449bf7cb18f6d18edeb2f6f997",
"matchesNpmBaseline": true
},
{
"package": "artplayer-plugin-ads",
"file": "artplayer-plugin-ads.js",
"bytes": 5620,
"sha256": "ceb2d8a23a6735c161b31a4a427d8a757679aaf8a5a106ef40a6f047061f1df8",
"matchesNpmBaseline": true
},
{
"package": "artplayer-plugin-ads",
"file": "artplayer-plugin-ads.legacy.js",
"bytes": 5951,
"sha256": "1e10c3a6b51de18e54cd02dd342ab4010fc466de6257659cf1d2e087642aa9a3",
"matchesNpmBaseline": true
},
{
"package": "artplayer-plugin-ads",
"file": "artplayer-plugin-ads.mjs",
"bytes": 9326,
"sha256": "0919678423424047b28d9d803835d9ebc98f4477e04e58d497e8ed8c48b95008",
"matchesNpmBaseline": true
},
{
"package": "artplayer-plugin-ambilight",
"file": "artplayer-plugin-ambilight.js",
"bytes": 1844,
"sha256": "8f32290c65a13b0a3026dee0045fef4125a9c9ac788ecb1675aef05f79172693",
"matchesNpmBaseline": true
},
{
"package": "artplayer-plugin-ambilight",
"file": "artplayer-plugin-ambilight.legacy.js",
"bytes": 1844,
"sha256": "8f32290c65a13b0a3026dee0045fef4125a9c9ac788ecb1675aef05f79172693",
"matchesNpmBaseline": true
},
{
"package": "artplayer-plugin-ambilight",
"file": "artplayer-plugin-ambilight.mjs",
"bytes": 3329,
"sha256": "77486db6d24f50420c952de5b37d226e404089730c7c1c6be226c836f4e85f9c",
"matchesNpmBaseline": true
},
{
"package": "artplayer-plugin-asr",
"file": "artplayer-plugin-asr.js",
"bytes": 5064,
"sha256": "7f975b131a9ea207f88a157aafec778bc4906230500db9b30f5bbfbf327b251d",
"matchesNpmBaseline": true
},
{
"package": "artplayer-plugin-asr",
"file": "artplayer-plugin-asr.legacy.js",
"bytes": 5468,
"sha256": "8b9f07ce97a8ce2e4f29e41e79257be530fd7a76558369d34c3d7497ea606c33",
"matchesNpmBaseline": true
},
{
"package": "artplayer-plugin-asr",
"file": "artplayer-plugin-asr.mjs",
"bytes": 9057,
"sha256": "f1c4274541e86544b65936ff470413cfc7001999ebc193969f95c123be48cd61",
"matchesNpmBaseline": true
},
{
"package": "artplayer-plugin-audio-track",
"file": "artplayer-plugin-audio-track.js",
"bytes": 1471,
"sha256": "473f39f1d750f0722cca7e857c12c3c978ebe3c3b2352e325f1248318e508683",
"matchesNpmBaseline": true
},
{
"package": "artplayer-plugin-audio-track",
"file": "artplayer-plugin-audio-track.legacy.js",
"bytes": 1497,
"sha256": "d8dc74bce76112d7430c98e3165605e32fde5d3c603be4b496eac58f574576cb",
"matchesNpmBaseline": true
},
{
"package": "artplayer-plugin-audio-track",
"file": "artplayer-plugin-audio-track.mjs",
"bytes": 2238,
"sha256": "4ac599bc5a1a6ecb0cb1942d4269528bfb2cd9d047f988de61fe671a77ad14cd",
"matchesNpmBaseline": true
},
{
"package": "artplayer-plugin-auto-thumbnail",
"file": "artplayer-plugin-auto-thumbnail.js",
"bytes": 1299,
"sha256": "ce1f1472bf02b836dd85b92eadf2f00786c02cde11a20ac2801136a0f675d12a",
"matchesNpmBaseline": true
},
{
"package": "artplayer-plugin-auto-thumbnail",
"file": "artplayer-plugin-auto-thumbnail.legacy.js",
"bytes": 1949,
"sha256": "3561e51e0a5f294b56641bf0884a24a4a9e326582d2e99416a04f9526c7d0cc0",
"matchesNpmBaseline": true
},
{
"package": "artplayer-plugin-auto-thumbnail",
"file": "artplayer-plugin-auto-thumbnail.mjs",
"bytes": 1831,
"sha256": "99da4748422bad54663c669d78963589a64c7cb02102e3544439fec7570a7f8b",
"matchesNpmBaseline": true
},
{
"package": "artplayer-plugin-chapter",
"file": "artplayer-plugin-chapter.js",
"bytes": 4973,
"sha256": "c2aaee11bf1db765433b01d9f8dd3978e41fa4d39655db00ebd03fc0be3e35e0",
"matchesNpmBaseline": true
},
{
"package": "artplayer-plugin-chapter",
"file": "artplayer-plugin-chapter.legacy.js",
"bytes": 4973,
"sha256": "c2aaee11bf1db765433b01d9f8dd3978e41fa4d39655db00ebd03fc0be3e35e0",
"matchesNpmBaseline": true
},
{
"package": "artplayer-plugin-chapter",
"file": "artplayer-plugin-chapter.mjs",
"bytes": 7721,
"sha256": "61342a069b84e0731d44a2464d0dfe637d1514d0037c740371fc866c516d2209",
"matchesNpmBaseline": true
},
{
"package": "artplayer-plugin-chromecast",
"file": "artplayer-plugin-chromecast.js",
"bytes": 3934,
"sha256": "4959661fc7f22eee3d32363bb0392a486c44499ec4a9c608ccfea55de29aaac6",
"matchesNpmBaseline": true
},
{
"package": "artplayer-plugin-chromecast",
"file": "artplayer-plugin-chromecast.legacy.js",
"bytes": 4472,
"sha256": "e2ba7aebec099884bb806f3caf77f9ff739ff9f236aefdfd0a4e69a8295c9d01",
"matchesNpmBaseline": true
},
{
"package": "artplayer-plugin-chromecast",
"file": "artplayer-plugin-chromecast.mjs",
"bytes": 6533,
"sha256": "b6d4e445a78f00fae53a35d239e62cc4a1448086d76058d69d8f9634a5754768",
"matchesNpmBaseline": true
},
{
"package": "artplayer-plugin-danmuku",
"file": "artplayer-plugin-danmuku.js",
"bytes": 52390,
"sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f",
"matchesNpmBaseline": true
},
{
"package": "artplayer-plugin-danmuku",
"file": "artplayer-plugin-danmuku.legacy.js",
"bytes": 53263,
"sha256": "62db96685c48b8573f0480cead6ac934b1d0382b9fdd0046d17d15d2549c56dc",
"matchesNpmBaseline": true
},
{
"package": "artplayer-plugin-danmuku",
"file": "artplayer-plugin-danmuku.mjs",
"bytes": 75696,
"sha256": "083d7de2f9a0314955dc83cdeedbc46c36728f7c9a0943ada8c3229edf9264ce",
"matchesNpmBaseline": true
},
{
"package": "artplayer-plugin-danmuku-mask",
"file": "artplayer-plugin-danmuku-mask.js",
"bytes": 904243,
"sha256": "07cebbfbf77f8ec4b2df6a77d7d7300345b86f2993e220ff14e1aae530e4fb31",
"matchesNpmBaseline": true
},
{
"package": "artplayer-plugin-danmuku-mask",
"file": "artplayer-plugin-danmuku-mask.legacy.js",
"bytes": 907166,
"sha256": "a678a3c0f6d3920bee3b66af9943b3612935028bff61c96677b8eaf8ef7cc8f0",
"matchesNpmBaseline": true
},
{
"package": "artplayer-plugin-danmuku-mask",
"file": "artplayer-plugin-danmuku-mask.mjs",
"bytes": 1728250,
"sha256": "48f7a449dc9555ab4060a578902b5431701f81b2f093a7cb0526042a8c417400",
"matchesNpmBaseline": true
},
{
"package": "artplayer-plugin-dash-control",
"file": "artplayer-plugin-dash-control.js",
"bytes": 3450,
"sha256": "248aa1162ffb2480965f8e12d766ba6b7d2abfc2d80e65e8a6e8db6bdfa750c5",
"matchesNpmBaseline": true
},
{
"package": "artplayer-plugin-dash-control",
"file": "artplayer-plugin-dash-control.legacy.js",
"bytes": 3450,
"sha256": "248aa1162ffb2480965f8e12d766ba6b7d2abfc2d80e65e8a6e8db6bdfa750c5",
"matchesNpmBaseline": true
},
{
"package": "artplayer-plugin-dash-control",
"file": "artplayer-plugin-dash-control.mjs",
"bytes": 5905,
"sha256": "2cc039698627a6baaa5da1cc50cc5db5230ae5d31152b1217dda62e38c67aa3e",
"matchesNpmBaseline": true
},
{
"package": "artplayer-plugin-document-pip",
"file": "artplayer-plugin-document-pip.js",
"bytes": 4624,
"sha256": "261d4ae84579c569ade1b1e7e91d51e3bd00c6efbea8c51a48b8283e0f4f3496",
"matchesNpmBaseline": true
},
{
"package": "artplayer-plugin-document-pip",
"file": "artplayer-plugin-document-pip.legacy.js",
"bytes": 5356,
"sha256": "8e36b658196dece391add21c249b735f3abfe4082fc968d3dbbbb1ae58a77b31",
"matchesNpmBaseline": true
},
{
"package": "artplayer-plugin-document-pip",
"file": "artplayer-plugin-document-pip.mjs",
"bytes": 6912,
"sha256": "22b432b5fc958f6f838b83fdfcc7e5ab7144137111b1f8cf081eb2e21afd8382",
"matchesNpmBaseline": true
},
{
"package": "artplayer-plugin-hls-control",
"file": "artplayer-plugin-hls-control.js",
"bytes": 3156,
"sha256": "7a6ce18a0b16f61f6149e0ea77efbb6e0503f997d39afe84271b59e366759e6d",
"matchesNpmBaseline": true
},
{
"package": "artplayer-plugin-hls-control",
"file": "artplayer-plugin-hls-control.legacy.js",
"bytes": 3182,
"sha256": "893a3de27f9ed02b4b61f03732aec03bfcaf50d02c9beb15cc8a5767ef9121a0",
"matchesNpmBaseline": true
},
{
"package": "artplayer-plugin-hls-control",
"file": "artplayer-plugin-hls-control.mjs",
"bytes": 5015,
"sha256": "85c4de4940e031d835b4de3ccf68af449d10aec4f630c89ecaf62f5503348931",
"matchesNpmBaseline": true
},
{
"package": "artplayer-plugin-jassub",
"file": "artplayer-plugin-jassub.js",
"bytes": 16231,
"sha256": "271d5284e5246fbd04575526510b3e381e5e60d414c030acecce92fcf2e9b10a",
"matchesNpmBaseline": true
},
{
"package": "artplayer-plugin-jassub",
"file": "artplayer-plugin-jassub.legacy.js",
"bytes": 16947,
"sha256": "0726c96bf0df2aab2662ac8973bb7676a0ca7f8e4cb806aa44cb3ec9de296e64",
"matchesNpmBaseline": true
},
{
"package": "artplayer-plugin-jassub",
"file": "artplayer-plugin-jassub.mjs",
"bytes": 33771,
"sha256": "31e4be88838ddd786f1f2180d2662792ac3b2bcce00b7ccac977b59b9d659716",
"matchesNpmBaseline": true
},
{
"package": "artplayer-plugin-multiple-subtitles",
"file": "artplayer-plugin-multiple-subtitles.js",
"bytes": 13433,
"sha256": "c1cb0b511da88347165cc855185de9450a44835bb34bb802281ccdb854ef603c",
"matchesNpmBaseline": true
},
{
"package": "artplayer-plugin-multiple-subtitles",
"file": "artplayer-plugin-multiple-subtitles.legacy.js",
"bytes": 14099,
"sha256": "0b17644827e5b199afe8293093c44bfda571821014ff5b087c7c918c630dcc18",
"matchesNpmBaseline": true
},
{
"package": "artplayer-plugin-multiple-subtitles",
"file": "artplayer-plugin-multiple-subtitles.mjs",
"bytes": 26832,
"sha256": "e867c64303299a53d2bf6af62cc1e59044f1c7355aeb55e45b15ab2703448cb0",
"matchesNpmBaseline": true
},
{
"package": "artplayer-plugin-vast",
"file": "artplayer-plugin-vast.js",
"bytes": 23307,
"sha256": "72842ae0b4a44e44a080f88783c0c9bcd0b572fa0e946d817b2c36d960a08bfe",
"matchesNpmBaseline": true
},
{
"package": "artplayer-plugin-vast",
"file": "artplayer-plugin-vast.legacy.js",
"bytes": 23571,
"sha256": "4b88cec8d12844d639cc7703f88703136a4fe586781d9939bf2e3a0c93b42b60",
"matchesNpmBaseline": true
},
{
"package": "artplayer-plugin-vast",
"file": "artplayer-plugin-vast.mjs",
"bytes": 30891,
"sha256": "91fbe929a9d8d780f1656b53697fb0fe400b9375db79370866ec2f4c5313e727",
"matchesNpmBaseline": true
},
{
"package": "artplayer-plugin-vtt-thumbnail",
"file": "artplayer-plugin-vtt-thumbnail.js",
"bytes": 2325,
"sha256": "2d8e22cbd191bdac5a6c711b641590c2f8a90ba1aae185dd0e02a00baf000f8d",
"matchesNpmBaseline": true
},
{
"package": "artplayer-plugin-vtt-thumbnail",
"file": "artplayer-plugin-vtt-thumbnail.legacy.js",
"bytes": 2594,
"sha256": "ecbd0abe12c537687fb058de552c328c71ced71d911e454d0e37887192e9a291",
"matchesNpmBaseline": true
},
{
"package": "artplayer-plugin-vtt-thumbnail",
"file": "artplayer-plugin-vtt-thumbnail.mjs",
"bytes": 4284,
"sha256": "413af5e4f28d47c659521332042a8347da357b17af39cf08c89ce3347897c618",
"matchesNpmBaseline": true
},
{
"package": "artplayer-proxy-canvas",
"file": "artplayer-proxy-canvas.js",
"bytes": 1927,
"sha256": "ef489570e13f402f1a60eb256ce3900a0021a3d05699c2ba15adfaaeff184d4c",
"matchesNpmBaseline": true
},
{
"package": "artplayer-proxy-canvas",
"file": "artplayer-proxy-canvas.legacy.js",
"bytes": 2210,
"sha256": "7d25f21170c06d067aeaa1c8e79b15f2c0130a27cff1b410532d6c4ef4d2d45f",
"matchesNpmBaseline": true
},
{
"package": "artplayer-proxy-canvas",
"file": "artplayer-proxy-canvas.mjs",
"bytes": 3849,
"sha256": "4bb4a881787770093652a3262fc214a2529a1c514ef49affaf152b8abf0f4dc6",
"matchesNpmBaseline": true
},
{
"package": "artplayer-proxy-mediabunny",
"file": "artplayer-proxy-mediabunny.js",
"bytes": 418518,
"sha256": "376a0fffbac289e71717795532d6fce9f3531f87cc025dfd7694952d44479037",
"matchesNpmBaseline": true
},
{
"package": "artplayer-proxy-mediabunny",
"file": "artplayer-proxy-mediabunny.legacy.js",
"bytes": 440601,
"sha256": "8a91401e634fa4fe75ea68d6dd17e0793948584a67bcfab8edfe0c574920b0e7",
"matchesNpmBaseline": true
},
{
"package": "artplayer-proxy-mediabunny",
"file": "artplayer-proxy-mediabunny.mjs",
"bytes": 904277,
"sha256": "5b151b82b4054706d3c7c5c610ffd8ce9f39ef56d8393867b524891331fef8c0",
"matchesNpmBaseline": true
},
{
"package": "artplayer-tool-iframe",
"file": "artplayer-tool-iframe.js",
"bytes": 2878,
"sha256": "2ec257c8055a9448d12af3fecf1fae8ba58c06f47e85072d02c386cd258b0c86",
"matchesNpmBaseline": true
},
{
"package": "artplayer-tool-iframe",
"file": "artplayer-tool-iframe.legacy.js",
"bytes": 3108,
"sha256": "c0755d79f316cda71f045da86749648f95faf47c09180d525fb04bb753576d5f",
"matchesNpmBaseline": true
},
{
"package": "artplayer-tool-iframe",
"file": "artplayer-tool-iframe.mjs",
"bytes": 4094,
"sha256": "cbcdb0516dd5f17ca2572a6b3e363ea63b0cfd9733f3e47689c02088f23f29b9",
"matchesNpmBaseline": true
},
{
"package": "artplayer-tool-thumbnail",
"file": "artplayer-tool-thumbnail.js",
"bytes": 5984,
"sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98",
"matchesNpmBaseline": true
},
{
"package": "artplayer-tool-thumbnail",
"file": "artplayer-tool-thumbnail.legacy.js",
"bytes": 5984,
"sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98",
"matchesNpmBaseline": true
},
{
"package": "artplayer-tool-thumbnail",
"file": "artplayer-tool-thumbnail.mjs",
"bytes": 9029,
"sha256": "4d46df8cccdc92d18efc6f12abedf85e8881737023f4ead28697c8b1e85eead1",
"matchesNpmBaseline": true
}
]
},
"docsBuild": {
"command": "yarn workspace artplayer-vitepress build",
"passed": true
},
"remainingWarnings": [
{
"owner": "SITE-05",
"detail": "Existing flexsearch/search plugin peer mismatch and Algolia/search-insights peer warnings; docs build passed, search behavior still requires browser validation."
},
{
"owner": "MOD-02",
"detail": "Existing npx/Lerna postinstall emits npm environment warnings; Yarn Classic emits url.parse deprecation on Node 24."
}
],
"unverified": [
"Other OS and minimum Node matrix",
"Public runtime/types compatibility and device validation",
"Remote CI and npm publication"
]
}
@@ -0,0 +1,32 @@
# ENG-PM-01:按用户选择维护 Yarn
日期:2026-09-10;分支:codex/compatible-modernization;起点:9d1d5fda。
## 改动与兼容
用户明确要求 packageManager 使用 Yarn。根 manifest 改为 yarn@1.22.22,沿用 Yarn Classic v1 锁格式;提交唯一 yarn.lock,停止维护 package-lock.json。Node 24.21.0、原 16 个构建工具和各发布包的版本/依赖范围均保持。Lerna 原有 npmClient 已是 yarn,无需变更。
新增三个显式开发依赖:@yarnpkg/lockfile 1.1.0 用于官方锁解析;typescript 5.9.3 与 @vue/compiler-sfc 3.5.28 满足 ESLint 工具 peer 要求。三者均为先前已安装的版本,后两者不再依赖其他包偶然提升到根目录。没有迁移生产 TypeScript 或改变浏览器运行依赖。
旧本地锁的 p-map/esbuild 两个条目缺少完整下载信息,首次 Yarn 解析曾选取新版本。最终通过官方锁解析/序列化器保留原版本并补齐 registry tarball/integrity,然后重新从空 node_modules 冻结安装;未将试验升级带入交付。Yarn 自动清除旧锁里的机器绝对路径和非安装 peer 条目,补齐跨平台 optional 包。
check:toolchain 改为核对 Yarn 声明、根精确工具版本、全部 workspace 依赖及传递锁图、下载完整性字段和实际 Node/Yarn。新增集成测试验证遗漏根工具、workspace 依赖未锁、竞争 npm 锁、错误包管理器均被拒绝,恢复合法输入后通过。Yarn 的 peer 安装语义不等同 npm,锁检查不代替消费者测试。
## 验证
使用校验过的 Yarn 1.22.22 归档与 Node 24.21.0,在独立空依赖目录执行最终冻结安装,安装脚本正常运行,26.80 秒完成,锁文件字节不变。
- 严格工具检查:22 workspace、19 个直接工具、1335 个依赖选择器。
- 保留下来的旧锁选择器版本变化为零;9 个 workspace runtime 依赖解析版本与 ENG-01 一致。
- 独立环境原 19 项 Node 测试与新增工具检查集成测试共 20 项通过;工作区加发布归档与 HTTP 基线共 22 项通过。改动脚本/测试只读 lint 通过。
- 21 个库包构建通过,63 个输出与 ENG-01 npm 构建的 SHA-256 全部相同。
- VitePress 文档站构建通过;全部生成文件保留于忽略的隔离目录。
- 报告:[yarn-validation.json](../baselines/yarn-validation.json)。Windows 本地结果不代表其他系统、远端 CI 或发布已通过。
文档搜索仍有原 flexsearch peer 范围冲突及 Algolia/search-insights peer 警告,交由 SITE-05 核对实际搜索行为;本轮没有以降低/升级搜索依赖来隐藏问题。旧 npx/Lerna hook 的 npm 环境警告与 Yarn Classic url.parse 弃用提示交 MOD-02 评估,安装/构建退出成功。
## 文档与后续
AGENTS、toolchain-setup、工具链规范、路线、决策及任务依赖同步维护;Bun 仅作隔离比较,未经用户后续新决定不得替换 Yarn。ENG-01 npm 报告保留为历史事实。
本地独立提交主题包含 ENG-PM-01。原 Yarn 和 npm 锁都已备份于忽略缓存,历史 Git 提交亦保留 npm 锁;回退本提交可恢复 ENG-01 工具配置。未推送、未发布。下一步 ENG-02 将冻结 Yarn 安装和只读检查接入 PR/主线 CI;BASE-02 可使用已验证可连接的内置浏览器继续。
+4 -1
View File
@@ -7,7 +7,7 @@
| ADR-001 | 采用方向 | 保留公共 Artplayer 门面、渐进替换内部 | 大量旧用户及插件;属性/事件/分发均是契约 |
| ADR-002 | 采用方向 | 自有核心、插件、proxy、工具逐步 TS 化 | 消除实现/声明漂移;JS/TS 过渡,公开类型兼容 |
| ADR-003 | 采用方向 | 先测试、生命周期,再大范围模块调整 | 已有销毁与切源风险;不能仅靠改写语言获得可靠性 |
| ADR-004 | 待验证 | Bun 先用于依赖管理和脚本入口 | 需要固定版本、干净安装和完整包验证;不替换 Node 测试语义 |
| ADR-004 | 已替代 | Bun 仅作隔离评估,默认包管理器使用 Yarn | 用户明确指定 Yarn,见 ADR-021;保留 Node 测试语义 |
| ADR-005 | 采用方向 | 保留 Vite/Rollup 的既有分发能力 | UMD/AMD/legacy、Less/SVG/worker 兼容成本明确 |
| ADR-006 | 采用方向 | 每包独立任务和版本,公共共享依赖谨慎增加 | 支持旧核心配新插件;不强制生态同步升级 |
| ADR-007 | 采用方向 | 机器任务表 + 可读生成表 + 每次变更记录 | 支持 AI 接续、依赖检查和证据追溯 |
@@ -25,6 +25,9 @@
| ADR-019 | 采用方向 | 候选产物内容绑定测试证据 | 来源 SHA、锁文件/工具和 tarball integrity 可追溯,内容变化后重新验证,避免测一份发布另一份 |
| ADR-020 | 采用方向 | 全部 workspace 包各自升级到下一个 major,minor/patch 归零 | 2026-09-10 用户明确要求;替代旧“不自动提升全部 major”策略,保留 independent、旧 API 及跨版本插件兼容;目标见 version-policy.md |
| ADR-021 | 采用方向 | 用户指定 Yarn,固定 Classic 1.22.22 和唯一 yarn.lock | 与原 v1 锁格式一致;保留 Node 24.21.0 和既有依赖版本,ENG-PM-01 验证;替代 ENG-01 的 npm 默认工具选择 |
| ADR-022 | 采用方向 | Chrome 不可用时使用 Codex 内置浏览器 | 用户明确授权;记录实际环境和能力范围,必要设备测试仍独立验收 |
## 开始实现前需补齐的决定
1. 支持的历史核心/插件版本、TS 最低版本与浏览器能力矩阵,由 BASE-01/ENG-01 登记证据。
+7 -5
View File
@@ -2,9 +2,9 @@
> 由 tasks.json 生成。请修改数据后运行 `node refactor/scripts/plan.mjs --write`,不要手改本表。
基线:`40fcda6a37d0049d42e49c1e64e70d4fd9ba5f7f`。总任务 213 项,范围 22 个包及工作区/示例。
基线:`40fcda6a37d0049d42e49c1e64e70d4fd9ba5f7f`。总任务 214 项,范围 22 个包及工作区/示例。
状态:todo 197 / doing 0 / blocked 0 / done 16 / deferred 0。风险 L/M/H 表示兼容风险,不表示工期。
状态:todo 197 / doing 0 / blocked 0 / done 17 / deferred 0。风险 L/M/H 表示兼容风险,不表示工期。
前置依赖是启动条件;验收是完成条件。任务可以继续拆分,但不能复用或悄悄删除旧 ID。
@@ -74,7 +74,8 @@
| ID | 范围 / 步骤 | 前置依赖 | 交付物 | 验收条件 | 风险 | 状态 |
| --- | --- | --- | --- | --- | --- | --- |
| ENG-01 | workspace<br>固定 Node、包管理器与依赖 | BASE-01 | 版本 pin、唯一锁文件、安装说明 | 干净环境可复现,最低 Node 与构建依赖一致,未夹带全量升级 | M | done |
| ENG-02 | workspace<br>拆分只读检查并建立 PR CI | ENG-01 | lint/lint:fix、PR 与主线检查、独立部署任务;遵循 github-ci-cd.md,PR/重构分支触发、最小权限及 workflow 静态检查 | 仓库内检查可执行且不改源码、不发布;required checks 的外部设置状态列入发布台账,不阻塞本地框架建设 | M | todo |
| ENG-PM-01 | workspace<br>按用户选择切换固定 Yarn 包管理器 | ENG-01 | Yarn 固定版本、唯一 yarn.lock、工具检查与安装维护文档 | 干净冻结安装、Node 测试和全部构建通过;记录解析差异和依赖用途,独立提交 | M | done |
| ENG-02 | workspace<br>拆分只读检查并建立 PR CI | ENG-01, ENG-PM-01 | lint/lint:fix、PR 与主线检查、独立部署任务;遵循 github-ci-cd.md,PR/重构分支触发、最小权限及 workflow 静态检查 | 仓库内检查可执行且不改源码、不发布;required checks 的外部设置状态列入发布台账,不阻塞本地框架建设 | M | todo |
| ENG-03 | workspace<br>建立公共行为与单元测试入口 | ENG-02, BASE-03 | 保留现有 node:test,测试目录/夹具/统一入口 | 已有 19 项回归保留,旧版与候选可用同一夹具运行 | M | todo |
| ENG-04 | workspace<br>建立类型测试基础 | ENG-02, BASE-05 | 根与分包 tsconfig、显式 TS 依赖、正反例测试 | 核心/试点与迁移模块严格检查,未迁移第三方/包历史问题独立台账;明确最低/当前 TS 和各环境类型 | M | todo |
| ENG-05 | workspace<br>建立真实浏览器测试服务 | ENG-03, BASE-04, BASE-08 | Playwright projects、本地 Range/失败媒体服务;复用 docs 页面/样本的状态隔离、错误采集与候选资源映射 | Chromium/Firefox/WebKit 的基础播放 smoke 和报告可执行;以媒体状态断言判定通过,区分轻量用例与真实编辑器交互 | M | todo |
@@ -362,7 +363,7 @@
| SITE-02 | artplayer-vitepress<br>整理声明与示例生成器 | SITE-01, ENG-04, ENG-06 | build-ts/build-test 生成链的可验证 TS 脚本 | 不靠字符串拼接掩盖声明错误,生成示例有真实断言或仅标 smoke;替换固定 100ms 成功判定,明确异步错误、清理和生成覆盖限制 | M | todo |
| SITE-03 | artplayer-vitepress<br>整理 i18n/文档/LLM 生成流程 | SITE-02 | build-i18n/build-docs/build-llm/trans-docs 的任务边界和错误处理 | 原命令兼容、生成可复现,翻译步骤不隐式运行远程服务 | M | todo |
| SITE-04 | artplayer-vitepress<br>交叉核对逐包持续维护的文档 | CORE-21, SITE-03, PKG-CHAPTER-04, PKG-AMBILIGHT-04, PKG-AUDIO-04, PKG-AUTO-THUMB-04, PKG-VTT-THUMB-04, PKG-HLS-04, PKG-DASH-04, PKG-MULTI-SUB-04, PKG-JASSUB-04, PKG-MASK-04, PKG-ASR-04, PKG-ADS-04, PKG-VAST-04, PKG-CAST-04, PKG-DPIP-04, PKG-CANVAS-04, PKG-IFRAME-04, PKG-TOOL-THUMB-04, PKG-DANMUKU-06, PKG-MB-08 | 已随实现更新的中文/英文 API、包内实现地图、旧 JS 示例及已知能力限制的全包核对 | 未把缺环境的能力写成已验证,静态核对不等待设备任务;最终 demo 仍由 EX-03 验收 | M | todo |
| SITE-05 | artplayer-vitepress<br>构建文档站和验证链接/示例 | SITE-04, EX-01, EX-02 | VitePress 构建、链接与嵌入 demo 检查 | 文档构建、链接、嵌入路径与声明注入通过;真实完整 demo 保留 EX-03 独立门槛 | M | todo |
| SITE-05 | artplayer-vitepress<br>构建文档站和验证链接/示例 | SITE-04, EX-01, EX-02 | VitePress 构建、链接与嵌入 demo 检查 | 文档构建、链接、嵌入路径与声明注入通过;真实完整 demo 保留 EX-03 独立门槛;核对 ENG-PM-01 登记的搜索 peer 范围和真实搜索行为 | M | todo |
| SITE-06 | artplayer-vitepress<br>文档站交付验收 | SITE-05 | 维护指南和站点变更记录 | 未手改 generated 目录,旧 URL 可用、部署与检查分离 | M | todo |
| EX-01 | example/react.js<br>验证 React 消费者与 TS | CORE-22, ENG-07 | React 挂载/卸载/重挂载、引用和插件样例 | 真实 tarball + TS 消费通过,保留既有 React 集成 API | M | todo |
| EX-02 | example/vue.js<br>验证 Vue 消费者与更新卸载 | CORE-22, ENG-07 | Vue 实例/ref、参数更新、卸载及插件样例 | 旧 JS 组件用法无需修改,重复挂载不泄漏 | M | todo |
@@ -372,7 +373,7 @@
| ID | 范围 / 步骤 | 前置依赖 | 交付物 | 验收条件 | 风险 | 状态 |
| --- | --- | --- | --- | --- | --- | --- |
| MOD-01 | workspace<br>Bun 固定版本干净安装试点 | ENG-09 | 独立目录的 Bun 锁文件、lifecycle/peer/workspace 与全部构建对比 | Node 测试仍通过;安装与资源一致才决定采用;不改 bundler | H | todo |
| MOD-01 | workspace<br>Bun 固定版本干净安装试点 | ENG-09 | 独立目录的 Bun 安装与 Yarn 冻结基线对比,默认仍为用户选定的 Yarn | Node 测试仍通过;安装与资源一致才决定采用;不改 bundler;不自动替换默认 packageManager 或维护锁文件 | H | todo |
| MOD-02 | workspace<br>整理剩余开发/构建脚本与插件模板 | ENG-06, SITE-03 | dev/build/utils/create-plugin 的 TS 与可测 CLI,模板同时提供旧 API | 旧脚本入口保留、新插件类型/测试/示例齐全,Lerna 改动单独取证 | M | todo |
| MOD-03 | workspace<br>测量并优化核心热路径 | CORE-22, ENG-08 | DOM 读写、进度更新、持久化、初始化的测量与改进 | 相同设备媒体多次比较,契约不变,收益及无效尝试记录 | M | todo |
| MOD-04 | workspace<br>测量并优化重型插件/proxy | PKG-DANMUKU-09, PKG-MASK-06, PKG-MB-10, ENG-08 | 帧/队列/推理/音画同步与资源长期运行比较 | 不改默认算法/阈值,性能改善有证据;无收益则保留旧实现 | M | todo |
@@ -418,3 +419,4 @@
- BASE-01: [记录](changes/2026-09-10-BASE-01-published-baseline.md) [记录](baselines/releases.json)
- BASE-HARNESS-01: [记录](changes/2026-09-10-BASE-HARNESS-01-browser-fixture.md)
- ENG-01: [记录](changes/2026-09-10-ENG-01-reproducible-toolchain.md) [记录](baselines/toolchain-validation.json)
- ENG-PM-01: [记录](changes/2026-09-10-ENG-PM-01-yarn-toolchain.md) [记录](baselines/yarn-validation.json)
+6
View File
@@ -1,5 +1,11 @@
# 进度与证据
## 当前实施:ENG-PM-01 已完成 Yarn 切换
标准工具链为 Node 24.21.0 / Yarn Classic 1.22.22,唯一维护 yarn.lock。最终干净冻结安装、20 项 Node 测试、只读工具检查、21 库包及文档站构建通过,63 个库产物与 npm 基线 SHA-256 全同。详见 [ENG-PM-01](changes/2026-09-10-ENG-PM-01-yarn-toolchain.md)。既有搜索 peer 警告交 SITE-05 验证。
DOC-13 已提交 9d1d5fda;内置浏览器的 9 项基础 API 检查通过,BASE-02 可继续完整快照。当前 214 项任务,17 完成、197 待办。下一项 ENG-02,接入 Yarn 冻结安装和只读 PR CI;随后继续浏览器基线。没有生产 TS 迁移、推送或发布。
## 当前实施:Yarn 选择与浏览器回退
用户指定 packageManager 使用 Yarn,正在准备 ENG-PM-01 替换 ENG-01 的 npm 默认工具选择。ENG-02 暂回待办,待 Yarn 锁定验证后接续。用户同时授权 Chrome 不可用时使用内置浏览器;9 项发布包基础 API 检查已通过,BASE-02 连接阻塞解除,完整快照任务仍待完成。详见 [DOC-13](changes/2026-09-10-DOC-13-browser-fallback.md)。历史 npm 和 Chrome 失败记录保留为当时事实。
+1 -1
View File
@@ -22,7 +22,7 @@
3. 播放、设置、字幕和媒体接口分别稳定后,再推进相应插件;不要求等整个核心完成才开始所有生态任务。
4. danmuku、MediaBunny、跨文档 PiP、ASR、外部 SDK 插件各自分批,不能与基础播放改造混在同一补丁中。
5. 所有包的最终集成/分发验收依赖 CORE-22;早期试点通过不能代替最终核心上的重新验证。文档静态核对和本地候选包准备可以先做,设备缺口保留在相关验证任务。
6. Bun 替换默认包管理器需要干净安装试点证据;不要求迁移所有插件后才试验,但最终采用决策在发布前完成。
6. 默认包管理器已由用户指定为 Yarn;Bun 可以进行隔离安装对比,未经后续用户新决定不得替换 Yarn。
7. 生命周期缺陷修复、TS 迁移、目录移动、依赖升级、行为增强应形成不同变更记录。单个小步骤确实不可分时记录原因。
## 里程碑
+24 -4
View File
@@ -409,6 +409,25 @@
"baselines/toolchain-validation.json"
]
},
{
"id": "ENG-PM-01",
"phase": "2 工程保障",
"title": "按用户选择切换固定 Yarn 包管理器",
"scope": [
"workspace"
],
"dependsOn": [
"ENG-01"
],
"status": "done",
"risk": "M",
"deliverable": "Yarn 固定版本、唯一 yarn.lock、工具检查与安装维护文档",
"acceptance": "干净冻结安装、Node 测试和全部构建通过;记录解析差异和依赖用途,独立提交",
"evidence": [
"changes/2026-09-10-ENG-PM-01-yarn-toolchain.md",
"baselines/yarn-validation.json"
]
},
{
"id": "ENG-02",
"phase": "2 工程保障",
@@ -417,7 +436,8 @@
"workspace"
],
"dependsOn": [
"ENG-01"
"ENG-01",
"ENG-PM-01"
],
"status": "todo",
"risk": "M",
@@ -3376,7 +3396,7 @@
"status": "todo",
"risk": "M",
"deliverable": "VitePress 构建、链接与嵌入 demo 检查",
"acceptance": "文档构建、链接、嵌入路径与声明注入通过;真实完整 demo 保留 EX-03 独立门槛",
"acceptance": "文档构建、链接、嵌入路径与声明注入通过;真实完整 demo 保留 EX-03 独立门槛;核对 ENG-PM-01 登记的搜索 peer 范围和真实搜索行为",
"evidence": []
},
{
@@ -3478,8 +3498,8 @@
],
"status": "todo",
"risk": "H",
"deliverable": "独立目录的 Bun 锁文件、lifecycle/peer/workspace 与全部构建对比",
"acceptance": "Node 测试仍通过;安装与资源一致才决定采用;不改 bundler",
"deliverable": "独立目录的 Bun 安装与 Yarn 冻结基线对比,默认仍为用户选定的 Yarn",
"acceptance": "Node 测试仍通过;安装与资源一致才决定采用;不改 bundler;不自动替换默认 packageManager 或维护锁文件",
"evidence": []
},
{
+3 -3
View File
@@ -2,9 +2,9 @@
## 目标组合
TypeScript 用于自有源码、检查与声明生成;Vite/Rollup 保留现有产物能力;Node 继续运行现有测试和必要脚本;Bun 先作为包管理器及脚本入口试点。浏览器消费者不依赖 Bun。
TypeScript 用于自有源码、检查与声明生成;Vite/Rollup 保留现有产物能力;Node 继续运行现有测试和必要脚本;用户已指定 Yarn 为默认包管理器,Bun 仅作隔离试点评估。浏览器消费者不依赖 Bun。
这是项目方向,不是已完成的切换。工具版本必须在 ENG-01 / MOD-01 通过干净环境试点后固定,不能沿用开发机器上偶然存在的传递依赖。
实际固定版本与命令见 toolchain-setup.md,Yarn 切换由 ENG-PM-01 验证。新增工具必须显式声明并通过干净环境检查,不能沿用开发机器上偶然存在的传递依赖。
## 新依赖与脚本的自主选择
@@ -39,7 +39,7 @@ TypeScript 用于自有源码、检查与声明生成;Vite/Rollup 保留现有
| 命令对比 | `bun run` 只是脚本入口;脚本中的 node 仍由 Node 执行,不能声称已经换运行时 |
| 构建对比 | 相同版本和源码下构建全部包、文档、worker/WASM,比较包内容与消费者行为 |
| Node 回归 | npm/Node 消费发布包仍通过;现有 node:test 不因包管理器变化被替换 |
| 采用或保留 | 证据充分才改默认文档/CI/锁文件;否则保留 Node 工具链,登记试点结论 |
| 采用或保留 | 记录对 Yarn 的对比结论;用户已选择 Yarn,未经后续新决定不得改默认文档/CI/锁文件 |
评估时本机 Bun 1.3.14 直接运行现有测试遇到 node:test mock.fn 不兼容;这是具体版本的观察,未来升级应重测。Bun bundler 不作为本轮替换目标,因为需要保留 UMD、legacy 语法降级和现有资源处理。参考:[Bun bundler](https://bun.com/docs/bundler)、[workspaces](https://bun.com/docs/pm/workspaces)、[lifecycle](https://bun.com/docs/pm/lifecycle)、[TS allowJs](https://www.typescriptlang.org/tsconfig/allowJs.html)。执行时重新核对官方文档。
+18 -22
View File
@@ -1,33 +1,29 @@
# 可重跑的开发环境
ENG-01 固定开发工具,消费者 API 和各包版本尚未修改。规范运行时是根 .node-version 的 Node 24.21.0,配套 npm 11.19.0;官方二进制已核对 SHA-256。开发依赖版本固定为本机改造前已经解析的版本,package-lock.json 是唯一提交和维护的依赖锁文件。
用户指定 packageManager 使用 Yarn。标准组合为 Node 24.21.0(根 .node-version)和 Yarn Classic 1.22.22(根 package.json),唯一维护的安装锁文件为 yarn.lock。Yarn 版本沿用仓库原有 v1 锁格式;播放器消费者 API、包版本和浏览器构建目标不受该选择影响。
## 使用
1. 安装/切换到 .node-version 指定版本,确认 `node --version` 和 `npm --version`。实施时采用的 [Node 官方发行索引](https://nodejs.org/dist/index.json) 给出 24.21.0 LTS 与 npm 11.19.0;固定后不能每次 CI 自动取 latest。
2. 从干净 checkout 运行 `npm ci`。它会删除当前 node_modules 并按锁文件安装,不更新锁;在本轮验证中使用独立目录,未删除用户原有依赖。规则参见 [npm ci](https://docs.npmjs.com/cli/commands/npm-ci/)。
3. 执行 `npm run check:toolchain -- --strict`,核对实际 Node/npm、16 个根开发工具及 22 workspace 的锁定声明。无 --strict 时允许满足工具最低要求的 Node,并打印与标准版本的差异。
4. 现有 `npm run test:playback`、`npm run test:dash-control`、`npm run build -- all`、`npm --workspace artplayer-vitepress run build` 继续可用。CI 和只读 lint 的拆分由 ENG-02 接续;当前 lint 仍有 --fix,不当作只读验证。
1. 切换到 .node-version 指定的 Node,安装 Yarn 1.22.22;例如 `npm install --global yarn@1.22.22`,然后确认 `node --version` 和 `yarn --version`。npm 仅可用于安装 Yarn 工具及消费者兼容检查,不用于维护本仓库依赖锁。
2. 干净 checkout 执行 `yarn install --frozen-lockfile --non-interactive`,禁止 CI 自动更新锁或忽略安装脚本/engines。参见 [Yarn Classic install](https://classic.yarnpkg.com/en/docs/cli/install/)。
3. 执行 `yarn check:toolchain --strict`,核对实际 Node/Yarn、19 个固定开发工具和 22 个 workspace 的声明及传递依赖锁条目。普通检查允许满足最低工具要求的 Node,同时打印标准版本。
4. 执行 `yarn test:playback`、`yarn test:dash-control`、`yarn build all` 和 `yarn workspace artplayer-vitepress build`。只读 lint 和 PR CI 的拆分由 ENG-02 完成;旧 lint 当前仍有 --fix。
私有根包的最低工具 Node 改为 ^20.19.0 || >=22.12.0,与已使用 Vite 7 的 engines 一致;这不是改变已发布播放器的 Node/browser 支持声明。本轮实际验证 Node 24.21.0,其他版本矩阵由 CI-01 执行,不能声称已经跑过全部最低环境。
私有根包最低 Node 为 ^20.19.0 || >=22.12.0,与原本使用的 Vite 7 一致。本轮验证 Node 24.21.0,其他版本矩阵由 CI-01 接续,不能宣称所有最低环境已经通过。
## 安装与锁文件维护
## 锁文件和依赖维护
- 原根 dependencies 全部是开发/构建工具,已移入 devDependencies 并固定精确版本;各发布包的 runtime dependencies/peer 范围保持原样。
- 初始锁从现有安装及锁信息生成,确认已有解析路径、直接工具和 workspace runtime 版本没有升级;补齐跨平台可选包供后续 CI 使用。
- 旧本地 yarn.lock 被忽略,留存以免删除用户文件;不作为维护锁或 CI 来源。不要混用 Yarn/Bun 改写依赖。MOD-01 另做 Bun 固定安装对比,结果通过再变更标准工具。
- 新依赖仍按任务需要自主添加,并固定开发依赖版本;将 manifest 和 package-lock.json 同次提交。更新 runtime 范围需独立兼容证据。
- 当前根 postinstall 执行已安装的 Lerna 8.2.4 run prepare;本轮 22 包无 prepare 脚本,输出 No packages found。是否删除空 hook 在 MOD-02 清理,不在初次固定锁时重写所有旧命令。
- npm 11.19.0 本轮报告 esbuild(两个版本)、less、nx 安装脚本尚未列入 allowScripts 策略;未用 ignore-scripts 绕过干净安装。实际安装、构建和 Node 测试成功;后续 CI/Bun 脚本策略需按真实包版本审查,不把警告写成运行失败或自动批准任意脚本。
- 根构建工具固定精确版本并放在 devDependencies;发布包的 dependencies/peer 范围保持原样。
- 添加根开发依赖使用 `yarn add --dev --exact --ignore-workspace-root-check <name>@<version>`,包级依赖使用 `yarn workspace <name> add ...`;运行依赖升级需要独立兼容证据。
- manifest 和 yarn.lock 同次提交;不提交 package-lock.json、bun.lock 或第二份安装锁。旧 npm 锁及验证报告保留于 ENG-01 Git 历史,原本地 Yarn 锁也已在忽略缓存中备份。
- 新增 @yarnpkg/lockfile 1.1.0 为显式开发依赖,供检查器使用 Yarn 官方锁解析器;不依赖 Lerna 偶然安装的传递依赖。只验证 registry 依赖图及完整性字段,实际下载完整性由 Yarn 安装验证;peer 兼容仍由消费者测试和安装报告验证。
- 另将原已解析的 TypeScript 5.9.3 和 @vue/compiler-sfc 3.5.28 显式声明为根开发依赖,满足 ESLint 工具链 peer 要求,防止依赖偶然提升到根目录;不在本任务迁移生产 TS 或更新公开声明。
- packageManager 字段只是声明,严格检查核对实际执行工具。Yarn 不像 npm lock 一样存储 workspace manifest 副本,workspace 名称/版本的发布基线仍由 refactor 清单和版本任务维护。
- 用户已选 Yarn;MOD-01 可在独立目录评估 Bun,但不能凭试点结果自行替换默认包管理器。
- 现有 npx/npm 脚本入口仍可用,脚本整理由 MOD-02 接续;新增脚本采用本地依赖。当前 postinstall 的 Lerna prepare 在 22 包均无 prepare 时为空操作。
## 已完成证据
## 验证记录
[toolchain-validation.json](baselines/toolchain-validation.json) 保存官方运行时归档 SHA、依赖锁及输入标识、安装计数、测试与构建文件摘要。
ENG-01 的 [npm 验证报告](baselines/toolchain-validation.json) 是切换前历史证据,不代表 Yarn 已验证。[Yarn 验证报告](baselines/yarn-validation.json) 记录最终干净冻结安装、20 项 Node 测试、21 库包 63 产物及文档站构建全部通过;63 产物 SHA-256 与 ENG-01 完全相同。保留的旧锁条目版本变化为零,9 个 workspace runtime 依赖解析与 npm 基线一致。搜索 peer 警告由 SITE-05 接续验证。
- Windows 独立空依赖目录:npm ci 安装 1141 个包,锁文件字节不变;无已有解析版本升级。
- 独立 Node 24.21.0/npm 11.19.0 严格工具检查通过;原 19 项 Node 测试通过。
- 21 个库包的正常构建全部通过(63 个 UMD/legacy/ESM 输出),VitePress 文档站构建通过;输出均在忽略的隔离目录。
- 工具检查器能拒绝 manifest/lock 不一致。已有完整性/HTTP 服务测试加原测试共 21 项通过。
- 计划校验器跳过 .cache/node_modules/.git,不再误扫工具下载和干净安装副本里的第三方文档。
这些结果说明固定工具链能安装并构建原项目,不代表运行时、类型、真实浏览器或 npm 发布验收已完成。Chrome 连接阻塞继续由 BASE-02 登记。
构建通过不代表运行时、类型、真实浏览器或 npm 发布验收已完成。Chrome 不可用时按 release-reviews.md 使用内置浏览器并注明实际环境。
+30 -14
View File
@@ -1,36 +1,52 @@
import assert from 'node:assert/strict'
import fs from 'node:fs'
import path from 'node:path'
import process from 'node:process'
import { fileURLToPath } from 'node:url'
import lockfile from '@yarnpkg/lockfile'
const root = fileURLToPath(new URL('../', import.meta.url))
const read = name => JSON.parse(fs.readFileSync(path.join(root, name), 'utf8'))
const manifest = read('package.json')
const lock = read('package-lock.json')
const parsed = lockfile.parse(fs.readFileSync(path.join(root, 'yarn.lock'), 'utf8'))
assert.equal(parsed.type, 'success', 'Yarn lock must parse without conflicts')
assert(!fs.existsSync(path.join(root, 'package-lock.json')), 'Maintain yarn.lock only')
assert.equal(manifest.packageManager, 'yarn@1.22.22', 'Use the agreed Yarn Classic version')
const lock = parsed.object
const nodeVersion = fs.readFileSync(path.join(root, '.node-version'), 'utf8').trim()
const [major, minor] = process.versions.node.split('.').map(Number)
assert((major === 20 && minor >= 19) || (major === 22 && minor >= 12) || major >= 23, 'Build tooling requires Node ^20.19.0 || >=22.12.0')
assert.equal(lock.lockfileVersion, 3)
assert.deepEqual(lock.packages[''].devDependencies, manifest.devDependencies, 'Root dependencies differ from lock')
for (const [name, version] of Object.entries(manifest.devDependencies)) {
assert(/^\d+\.\d+\.\d+(?:-[\w.-]+)?$/.test(version), `Unpinned development dependency: ${name}`)
assert.equal(lock.packages[`node_modules/${name}`]?.version, version, `Lock resolution differs: ${name}`)
assert.equal(lock[`${name}@${version}`]?.version, version, `Lock resolution differs: ${name}`)
}
const checked = new Set()
function checkDependencies(pkg) {
for (const field of ['dependencies', 'devDependencies', 'optionalDependencies']) {
for (const [name, range] of Object.entries(pkg[field] || {})) {
const selector = `${name}@${range}`
assert(lock[selector], `Dependency missing from Yarn lock: ${selector}`)
if (checked.has(selector))
continue
checked.add(selector)
assert(lock[selector].resolved && lock[selector].integrity, `Missing registry integrity: ${selector}`)
checkDependencies(lock[selector])
}
}
}
checkDependencies(manifest)
let packages = 0
for (const dir of fs.readdirSync(path.join(root, 'packages'))) {
const filename = `packages/${dir}/package.json`
if (!fs.existsSync(path.join(root, filename))) continue
const workspace = read(filename)
const locked = lock.packages[`packages/${dir}`]
assert(locked, `Workspace missing from lock: ${dir}`)
for (const field of ['version', 'dependencies', 'devDependencies', 'peerDependencies', 'optionalDependencies']) {
assert.deepEqual(locked[field], workspace[field], `Workspace lock differs: ${dir}.${field}`)
}
if (!fs.existsSync(path.join(root, filename)))
continue
checkDependencies(read(filename))
packages += 1
}
if (process.argv.includes('--strict')) {
assert.equal(process.versions.node, nodeVersion, 'Use the pinned .node-version runtime')
const actualNpm = process.env.npm_config_user_agent?.split(' ')[0]
assert.equal(actualNpm, manifest.packageManager.replace('@', '/'), 'Run with the pinned npm through npm run check:toolchain -- --strict')
const actualManager = process.env.npm_config_user_agent?.split(' ')[0]
assert.equal(actualManager, manifest.packageManager.replace('@', '/'), 'Run yarn check:toolchain --strict with the pinned Yarn')
}
console.log(`Toolchain verified: ${packages} workspaces, ${Object.keys(manifest.devDependencies).length} pinned tools; Node ${process.versions.node} (canonical ${nodeVersion}), ${manifest.packageManager}`)
console.log(`Toolchain verified: ${packages} workspaces, ${Object.keys(manifest.devDependencies).length} pinned tools, ${checked.size} dependency selectors; Node ${process.versions.node} (canonical ${nodeVersion}), ${manifest.packageManager}`)
+51
View File
@@ -0,0 +1,51 @@
import assert from 'node:assert/strict'
import { spawnSync } from 'node:child_process'
import fs from 'node:fs'
import path from 'node:path'
import process from 'node:process'
// eslint-disable-next-line test/no-import-node-test -- Exercise the real toolchain guard with isolated manifests.
import { test } from 'node:test'
import { fileURLToPath } from 'node:url'
const root = fileURLToPath(new URL('../', import.meta.url))
test('toolchain guard rejects unlocked dependencies, competing locks and the wrong package manager', () => {
const cache = path.join(root, 'refactor/.cache')
fs.mkdirSync(cache, { recursive: true })
const fixture = fs.mkdtempSync(path.join(cache, 'toolchain-check-'))
const manifest = JSON.parse(fs.readFileSync(path.join(root, 'package.json'), 'utf8'))
const writeManifest = value => fs.writeFileSync(path.join(fixture, 'package.json'), JSON.stringify(value))
const run = (args = [], userAgent = 'yarn/1.22.22') => spawnSync(process.execPath, [path.join(fixture, 'scripts/check-toolchain.mjs'), ...args], {
encoding: 'utf8',
env: { ...process.env, npm_config_user_agent: userAgent },
})
try {
fs.mkdirSync(path.join(fixture, 'scripts'))
fs.mkdirSync(path.join(fixture, 'packages/example'), { recursive: true })
fs.symlinkSync(path.join(root, 'node_modules'), path.join(fixture, 'node_modules'), 'junction')
for (const file of ['yarn.lock', 'scripts/check-toolchain.mjs'])
fs.copyFileSync(path.join(root, file), path.join(fixture, file))
fs.writeFileSync(path.join(fixture, '.node-version'), process.versions.node)
fs.writeFileSync(path.join(fixture, 'packages/example/package.json'), JSON.stringify({ name: 'example', dependencies: { 'option-validator': '^2.0.6' } }))
writeManifest(manifest)
assert.equal(run(['--strict']).status, 0)
writeManifest({ ...manifest, devDependencies: { ...manifest.devDependencies, 'unlocked-tool': '1.0.0' } })
assert.match(run().stderr, /Lock resolution differs: unlocked-tool/)
writeManifest(manifest)
fs.writeFileSync(path.join(fixture, 'packages/example/package.json'), JSON.stringify({ name: 'example', dependencies: { 'option-validator': '^99.0.0' } }))
assert.match(run().stderr, /Dependency missing from Yarn lock: option-validator/)
fs.writeFileSync(path.join(fixture, 'packages/example/package.json'), JSON.stringify({ name: 'example' }))
fs.writeFileSync(path.join(fixture, 'package-lock.json'), '{}')
assert.match(run().stderr, /Maintain yarn.lock only/)
fs.unlinkSync(path.join(fixture, 'package-lock.json'))
assert.match(run(['--strict'], 'npm/11.19.0').stderr, /Run yarn check:toolchain/)
assert.equal(run(['--strict']).status, 0)
}
finally {
const relative = path.relative(cache, fixture)
assert(relative.startsWith('toolchain-check-') && !relative.includes(path.sep))
fs.rmSync(fixture, { recursive: true, force: true })
}
})
+8061
View File
File diff suppressed because it is too large. Load diff