diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index 4d1fbdea..58c9000f 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "commitlore", "displayName": "CommitLore", - "version": "1.2.0", + "version": "1.2.1", "description": "Recorded decisions from git history, delivered to the agent before it edits. Constraints, alternatives already ruled out, and warnings left by whoever was here last.", "author": { "name": "MongLong0214", diff --git a/.codex-plugin/plugin.json b/.codex-plugin/plugin.json index cb137538..7470e9e7 100644 --- a/.codex-plugin/plugin.json +++ b/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "commitlore", - "version": "1.2.0", + "version": "1.2.1", "description": "Decision memory from Git history, with verified capture for coding sessions.", "author": { "name": "MongLong0214", diff --git a/.github/workflows/canonical-merge.yml b/.github/workflows/canonical-merge.yml index 4714783b..653a82fe 100644 --- a/.github/workflows/canonical-merge.yml +++ b/.github/workflows/canonical-merge.yml @@ -158,7 +158,7 @@ jobs: # ever narrows what job two will accept. echo "${{ steps.fetch.outputs.head }}" > /tmp/canonical.head - - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: canonical-tree path: | @@ -193,7 +193,7 @@ jobs: with: node-version: '22.23.2' - - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: canonical-tree path: /tmp/canonical diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cf1442c3..e2ca6b36 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -101,7 +101,7 @@ jobs: - name: PRD-F2 100k-commit query performance env: COMMITLORE_PERF_LARGE: "1" - run: npx vitest run test/index-perf.test.ts --reporter=basic + run: npx vitest run test/index-perf.test.ts --reporter=default # #392: bench/verify.mjs existed for weeks with no npm script and no step # here, so the result schema drifted five fields behind the runner and a diff --git a/CHANGELOG.md b/CHANGELOG.md index 11794cff..9a816821 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,64 @@ Release notes for 1.0.0, 1.0.1 and 1.0.2 are on the [GitHub releases page](https://github.com/MongLong0214/commitlore/releases); they were not written here. +## 1.2.1 + +A security release, and one line that had been asserting something nobody checked. + +**Seven advisories left the tree, and two of them shipped.** `npm audit --omit=dev` +was failing on `main`, not only on the dependency pull requests that were being +blamed for it: `fast-uri` (high, four GHSAs, reached through `ajv`) and `qs` +(moderate, two, reached through the MCP SDK's `express`) were both in the runtime +tree — the tree that gets bundled into `dist/commitlore.mjs` and installed. They +are fixed at `fast-uri` 3.1.7 and `qs` 6.16.0. Five more, including one rated +critical, were `esbuild <=0.24.2` reachable only through vitest 2's own +dependencies; the vitest 4 upgrade below is what removes them. `npm audit` is now +silent on both surfaces. + +**The push hook no longer reports records that do not exist as unsent.** On a +failed notes mirror the line said "the records for these commits are still only +local" whether or not any record existed — #632 asked "is there a local note +waiting?" and the answer was hard-coded to yes. A repository with no notes ref at +all was told to run `commitlore sync`, and found nothing to send. The hook now +checks, locally, before it claims; when there is nothing waiting it says so. The +check is ref-scoped rather than commit-scoped on purpose: the mirror publishes +`refs/notes/commitlore` whole, so a record written against an already-pushed +commit is still unsent, and a commit-scoped check would call that "nothing +waiting" — wrong in the dangerous direction. + +**`commitlore sync` keeps one row per remote.** An unreachable remote answers with +two lines of git diagnostic, and both went into a column that promises one. The +row broke in half and the trailing `fatal:` read as a bare error standing above +the table rather than as that remote's result. + +**Upgrades.** vitest 2.1.9 → 4.1.11, `@modelcontextprotocol/sdk` 1.29.0 → 1.30.0, +js-yaml 5.2.3 → 5.4.1, `upload-artifact` v4.6.2 → v7.0.1 and `download-artifact` +v4.3.0 → v8.0.1. vitest 4 needed three things with it: `--reporter=basic` no +longer exists, changing `ci.yml` moves the reviewed-workflow lock deliberately, +and the 5s default test timeout no longer fits a runner whose per-file startup +costs more — every failure measured during that upgrade was a timeout, none was +an assertion. + +**Reviewed, with one exception recorded.** 1.2.0 shipped without a cross-provider +review and said so here. This one had them: `gpt-5.6-sol`, read-only and asked to +*disprove* rather than approve, went through the dependency batch (it recomputed +the source digest and all 310 `dist` entries from the commit's git blobs +independently) and the artifact-action upgrade (it read the pinned action sources +and mapped every uploaded path to where the next job reads it). The exception is +the security fix itself, which was merged first and without one, because leaving +two advisories in the runtime tree to wait for a reviewer is the worse trade. Both +reviews recorded their own limits — neither could rerun the Docker build, and +neither dispatched the canonical-merge workflow — and those limits stand. + +**Not changed, deliberately.** The guard's short-alternative false positive +(#858) was measured rather than fixed. At one distinctive token the corroboration +strength is structurally 1.00 whatever the token is, because the corpus weight +that separates a rare `redis` from an ordinary `read` is divided out by its own +denominator. Every rule that removes the false positive also removes +`add a Redis client` → `shared Redis cache`, a documented true positive. Trading +that for an advisory false positive is the wrong direction for a tool that +declares itself advisory; the issue carries the measurements. + ## 1.2.0 > **Recorded as held for want of a reviewer, not as reviewed.** Every change in diff --git a/README.ja.md b/README.ja.md index 8e7af999..54a57d98 100644 --- a/README.ja.md +++ b/README.ja.md @@ -47,18 +47,18 @@

```bash -curl -fsSL https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.0/install.sh | sh -s v1.2.0 +curl -fsSL https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.1/install.sh | sh -s v1.2.1 ```
先にインストーラーを読みたいですか? ```bash -curl -fsSLO https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.0/install.sh -sh install.sh v1.2.0 +curl -fsSLO https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.1/install.sh +sh install.sh v1.2.1 # あるいはスクリプトを使わずに。スクリプトが作るチェックアウトは自分でも作れます。 -git clone --depth 1 --branch v1.2.0 https://github.com/MongLong0214/commitlore +git clone --depth 1 --branch v1.2.1 https://github.com/MongLong0214/commitlore node commitlore/dist/commitlore.mjs --version ``` @@ -107,13 +107,13 @@ CommitLore はその判断をコードのそばに残します。 macOS と Linux: ```bash -curl -fsSL https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.0/install.sh | sh -s v1.2.0 +curl -fsSL https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.1/install.sh | sh -s v1.2.1 ``` Windows: ```powershell -& ([scriptblock]::Create((irm https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.0/install.ps1))) v1.2.0 +& ([scriptblock]::Create((irm https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.1/install.ps1))) v1.2.1 ``` Node.js 22.23.2+ と Git が必要です。スクリプトは何かを書き込む前に両方を確認します。 @@ -232,7 +232,7 @@ superseded な決定は大いに関係があり得ても、現在の指針とし ## 現場報告であって測定ではない -無関係な一つのリポジトリで、初めて v1.2.0 を入れた人の一回の実行です。ここでは何も測定されず、 +無関係な一つのリポジトリで、初めて v1.2.1 を入れた人の一回の実行です。ここでは何も測定されず、 evidence log にもありません。上の段落が表で扱っていない loop を主張しているため、このページにあります。 その人は agent に丸めの不具合を直すよう頼み、decimal library はすでに検討して却下したと付け加え、 diff --git a/README.ko.md b/README.ko.md index e4daa0ba..4a31cdaa 100644 --- a/README.ko.md +++ b/README.ko.md @@ -47,18 +47,18 @@

```bash -curl -fsSL https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.0/install.sh | sh -s v1.2.0 +curl -fsSL https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.1/install.sh | sh -s v1.2.1 ```
먼저 설치기를 읽어 보고 싶나요? ```bash -curl -fsSLO https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.0/install.sh -sh install.sh v1.2.0 +curl -fsSLO https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.1/install.sh +sh install.sh v1.2.1 # 또는 스크립트를 건너뜁니다. 스크립트가 만드는 체크아웃은 직접 만들 수 있습니다. -git clone --depth 1 --branch v1.2.0 https://github.com/MongLong0214/commitlore +git clone --depth 1 --branch v1.2.1 https://github.com/MongLong0214/commitlore node commitlore/dist/commitlore.mjs --version ``` @@ -107,13 +107,13 @@ CommitLore는 그 판단을 코드 곁에 보관합니다. macOS와 Linux: ```bash -curl -fsSL https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.0/install.sh | sh -s v1.2.0 +curl -fsSL https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.1/install.sh | sh -s v1.2.1 ``` Windows: ```powershell -& ([scriptblock]::Create((irm https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.0/install.ps1))) v1.2.0 +& ([scriptblock]::Create((irm https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.1/install.ps1))) v1.2.1 ``` Node.js 22.23.2+와 Git이 필요합니다. 스크립트는 무엇이든 쓰기 전에 둘을 확인합니다. @@ -232,7 +232,7 @@ CommitLore는 이렇게 묻습니다. ## 현장 보고이지 측정은 아닙니다 -관련 없는 한 저장소에서 v1.2.0을 처음 설치한 사람이 한 번 실행한 사례입니다. 여기서는 아무것도 +관련 없는 한 저장소에서 v1.2.1을 처음 설치한 사람이 한 번 실행한 사례입니다. 여기서는 아무것도 측정하지 않았고 evidence log에도 없습니다. 위 문단이 표로 다루지 않는 loop를 주장하기 때문에 이 페이지에 있습니다. diff --git a/README.md b/README.md index 58b53cf7..e3ad22b1 100644 --- a/README.md +++ b/README.md @@ -48,18 +48,18 @@

```bash -curl -fsSL https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.0/install.sh | sh -s v1.2.0 +curl -fsSL https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.1/install.sh | sh -s v1.2.1 ```
Prefer to read the installer first? ```bash -curl -fsSLO https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.0/install.sh -sh install.sh v1.2.0 +curl -fsSLO https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.1/install.sh +sh install.sh v1.2.1 # Or skip the script: the checkout it makes is one you can make yourself. -git clone --depth 1 --branch v1.2.0 https://github.com/MongLong0214/commitlore +git clone --depth 1 --branch v1.2.1 https://github.com/MongLong0214/commitlore node commitlore/dist/commitlore.mjs --version ``` @@ -109,13 +109,13 @@ preserve, not for narrating every change. macOS and Linux: ```bash -curl -fsSL https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.0/install.sh | sh -s v1.2.0 +curl -fsSL https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.1/install.sh | sh -s v1.2.1 ``` Windows: ```powershell -& ([scriptblock]::Create((irm https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.0/install.ps1))) v1.2.0 +& ([scriptblock]::Create((irm https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.1/install.ps1))) v1.2.1 ``` Requires Node.js 22.23.2+ and Git. The script checks both before it writes anything. @@ -242,7 +242,7 @@ per-record user command. ## A field report, not a measurement -One run, on an unrelated repository, by someone installing v1.2.0 for the first +One run, on an unrelated repository, by someone installing v1.2.1 for the first time. Nothing here was measured and none of it is in the evidence logs. It is on this page because the paragraph above asserts a loop that no table here covers. diff --git a/README.zh-CN.md b/README.zh-CN.md index 5e4e2ee1..fb2f22b6 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -47,18 +47,18 @@

```bash -curl -fsSL https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.0/install.sh | sh -s v1.2.0 +curl -fsSL https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.1/install.sh | sh -s v1.2.1 ```
想先阅读安装器吗? ```bash -curl -fsSLO https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.0/install.sh -sh install.sh v1.2.0 +curl -fsSLO https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.1/install.sh +sh install.sh v1.2.1 # 或者跳过脚本:它创建的检出,你自己也能创建。 -git clone --depth 1 --branch v1.2.0 https://github.com/MongLong0214/commitlore +git clone --depth 1 --branch v1.2.1 https://github.com/MongLong0214/commitlore node commitlore/dist/commitlore.mjs --version ``` @@ -105,13 +105,13 @@ CommitLore 把那份判断留在代码旁边。 macOS 和 Linux: ```bash -curl -fsSL https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.0/install.sh | sh -s v1.2.0 +curl -fsSL https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.1/install.sh | sh -s v1.2.1 ``` Windows: ```powershell -& ([scriptblock]::Create((irm https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.0/install.ps1))) v1.2.0 +& ([scriptblock]::Create((irm https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.1/install.ps1))) v1.2.1 ``` 需要 Node.js 22.23.2+ 和 Git。脚本会在写入任何内容前检查两者。 @@ -226,7 +226,7 @@ CommitLore 会问: ## 现场报告,不是测量 -这是某人在一个无关仓库首次安装 v1.2.0 时的一次运行。这里没有测量任何东西,也没有写进 +这是某人在一个无关仓库首次安装 v1.2.1 时的一次运行。这里没有测量任何东西,也没有写进 evidence log。之所以放在这里,是因为上段主张了一种本页表格未覆盖的 loop。 那个人让 agent 修复一个舍入 bug,顺带提到 decimal library 已经考虑过又被否决,最后说“commit it”。 diff --git a/dist/commitlore.mjs b/dist/commitlore.mjs index fdf5d032..d08ae869 100755 --- a/dist/commitlore.mjs +++ b/dist/commitlore.mjs @@ -23017,10 +23017,14 @@ var revParse2 = (ref, opts) => { return result.code === 0 && sha !== "" ? sha : null; }; var isAncestor = (a, b, opts) => execGit(["merge-base", "--is-ancestor", a, b], gitOptions4(opts)).code === 0; +var oneLine = (detail) => detail.replace(/\s+/g, " ").trim(); +var REMOTE_NOT_FOUND = /\brepository\b(?:\s+'[^']*'|\s+"[^"]*")?\s+not found/i; +var TIMED_OUT = /\bETIMEDOUT\b/; +var classifyFailureDetail = (detail) => !TIMED_OUT.test(detail) && REMOTE_NOT_FOUND.test(detail) ? "remote not found" : oneLine(detail); var failure3 = (remote, detail) => ({ remote, outcome: "failed", - detail + detail: classifyFailureDetail(detail) }); var syncRemote = (remote, opts = {}) => { const fetched = execGit( @@ -23135,10 +23139,15 @@ var installPrePushHook = (cwd = process.cwd()) => { ); } }; -var oneLine = (detail) => detail.replace(/\s+/g, " ").trim(); -var saidWhy = (detail) => /\bETIMEDOUT\b/.test(detail) ? `the ${PRE_PUSH_NOTES_SYNC_TIMEOUT_MS / 1e3}s this hook waits for the remote ran out` : oneLine(detail); -var describeSync = (results) => results.filter((result) => result.outcome === "failed" || result.outcome === "diverged").map( - (result) => result.outcome === "diverged" ? `commitlore: notes mirror (${result.remote}) diverged: ${oneLine(result.detail)}. The branch was pushed. Your records and the remote's both exist and neither one fast-forwards, so a later push will not settle it \u2014 run "commitlore sync" to merge them.` : `commitlore: notes mirror (${result.remote}) failed: ${saidWhy(result.detail)}. The branch was pushed; the records for these commits are still only local. The next push retries this automatically, or run "commitlore sync" to send them now.` +var oneLine2 = (detail) => detail.replace(/\s+/g, " ").trim(); +var saidWhy = (detail) => /\bETIMEDOUT\b/.test(detail) ? `the ${PRE_PUSH_NOTES_SYNC_TIMEOUT_MS / 1e3}s this hook waits for the remote ran out` : oneLine2(detail); +var localRecordsExist = () => { + const result = execGit(["rev-parse", "--verify", "--quiet", NOTES_REF]); + if (result.code === 0) return result.stdout.trim() !== ""; + return result.code === 1 ? false : null; +}; +var describeSync = (results, hasLocalRecords = null) => results.filter((result) => result.outcome === "failed" || result.outcome === "diverged").map( + (result) => result.outcome === "diverged" ? `commitlore: notes mirror (${result.remote}) diverged: ${oneLine2(result.detail)}. The branch was pushed. Your records and the remote's both exist and neither one fast-forwards, so a later push will not settle it \u2014 run "commitlore sync" to merge them.` : hasLocalRecords === false ? `commitlore: notes mirror (${result.remote}) failed: ${saidWhy(result.detail)}. The branch was pushed. Nothing is waiting locally, so nothing was lost.` : `commitlore: notes mirror (${result.remote}) failed: ${saidWhy(result.detail)}. The branch was pushed; the records for these commits are still only local. The next push retries this automatically, or run "commitlore sync" to send them now.` ); var nonInteractiveGitEnv = () => ({ ...process.env, @@ -23147,6 +23156,7 @@ var nonInteractiveGitEnv = () => ({ }); var register7 = (program3) => { program3.command(PRE_PUSH_HOOK_NAME).argument("[remote]", "the remote git is pushing to").argument("[url]", "its URL, as git passes it").description("internal hook command: publish the notes mirror alongside a push").action((remote) => { + const hasLocalRecords = localRecordsExist(); try { const results = syncNotes({ ...remote === void 0 || remote === "" ? {} : { remotes: [remote] }, @@ -23155,11 +23165,13 @@ var register7 = (program3) => { timeout: PRE_PUSH_NOTES_SYNC_TIMEOUT_MS } }); - for (const line2 of describeSync(results)) process.stderr.write(`${line2} + for (const line2 of describeSync(results, hasLocalRecords)) process.stderr.write(`${line2} `); } catch (error2) { + const why = saidWhy(error2 instanceof Error ? error2.message : String(error2)); process.stderr.write( - `commitlore: notes mirror failed: ${saidWhy(error2 instanceof Error ? error2.message : String(error2))}. The branch was pushed; the records for these commits are still only local. The next push retries this automatically, or run "commitlore sync" to send them now. + hasLocalRecords === false ? `commitlore: notes mirror failed: ${why}. The branch was pushed. Nothing is waiting locally, so nothing was lost. +` : `commitlore: notes mirror failed: ${why}. The branch was pushed; the records for these commits are still only local. The next push retries this automatically, or run "commitlore sync" to send them now. ` ); } @@ -24922,13 +24934,13 @@ var harvestVerify = (options) => { exitCode: 0 }; }; -var oneLine2 = (text) => text.replace(/\s+/g, " ").trim(); +var oneLine3 = (text) => text.replace(/\s+/g, " ").trim(); var runHarvestVerify = (options) => { try { return harvestVerify(options); } catch (error2) { const detail = error2 instanceof Error ? error2.message : String(error2); - return { stdout: "", stderr: `${PREFIX3} ${oneLine2(detail)} + return { stdout: "", stderr: `${PREFIX3} ${oneLine3(detail)} `, exitCode: BAD_INPUT }; } }; @@ -25478,7 +25490,7 @@ var INVISIBLE_RE2 = /[\u00AD\u180E\u200B-\u200F\u202A-\u202E\u2060-\u2064\uFEFF] var GRADE_TOKEN_RE = /\[(directive|claim|blocked)\]/gi; var MAX_VALUE_CHARS = 400; var TRUNCATION_MARK = " ...[truncated]"; -var oneLine3 = (raw) => { +var oneLine4 = (raw) => { const flattened = raw.replace(ANSI_ESCAPE_RE2, "").replace(CONTROL_RE2, " ").replace(INVISIBLE_RE2, "").replace(GRADE_TOKEN_RE, "\\[$1\\]").replace(/\s+/g, " ").trim(); if (flattened.length <= MAX_VALUE_CHARS) return flattened; return `${flattened.slice(0, MAX_VALUE_CHARS)}${TRUNCATION_MARK}`; @@ -25519,9 +25531,9 @@ var TRUST_TAGS = { blocked: "[blocked] " }; var entryLine = (record2, trailer, trust, tier) => { - const value = oneLine3(trailer.value); - const body = tier === OTHER_TIER ? `${oneLine3(trailer.key)}: ${value}` : value; - return ` ${TRUST_TAGS[trust]} ${oneLine3(record2.recordId ?? "-")} ${shortSha3(record2.sha)} ${body}`; + const value = oneLine4(trailer.value); + const body = tier === OTHER_TIER ? `${oneLine4(trailer.key)}: ${value}` : value; + return ` ${TRUST_TAGS[trust]} ${oneLine4(record2.recordId ?? "-")} ${shortSha3(record2.sha)} ${body}`; }; var byRecency = (a, b) => { if (a.committedTs !== b.committedTs) return b.committedTs - a.committedTs; @@ -25543,7 +25555,7 @@ var project = (records, grades) => { if (grade2.trust === "blocked") { withheldValues += payload.length; withheld.push({ - recordId: record2.recordId !== void 0 && RECORD_ID_RE.test(record2.recordId) ? oneLine3(record2.recordId) : "-", + recordId: record2.recordId !== void 0 && RECORD_ID_RE.test(record2.recordId) ? oneLine4(record2.recordId) : "-", sha: shortSha3(record2.sha), patterns: grade2.matchedPatterns ?? [], keys: grade2.matchedTrailerKeys ?? [], @@ -25574,14 +25586,14 @@ var withheldLine = (withheld) => { if (withheld.length === 0) return []; const collisions = withheld.filter((entry) => entry.reason === "identity-collision"); const injections = withheld.filter((entry) => entry.reason === "injection"); - const collisionNamed = oneLine3( + const collisionNamed = oneLine4( collisions.map((entry) => `${entry.recordId} ${entry.sha}`).join(", ") ); const collisionLine = collisions.length === 0 ? [] : [ `withheld: ${collisions.length} record(s) due to a Record-Id collision; content not shown: ${collisionNamed}.` ]; if (injections.length === 0) return collisionLine; - const named = oneLine3( + const named = oneLine4( injections.map((entry) => `${entry.recordId} ${entry.sha}`).join(", ") ); const patterns = [...new Set(injections.flatMap((entry) => entry.patterns))].sort(); @@ -34485,16 +34497,7 @@ var Server = class extends Protocol { if (!methodSchema) { throw new Error("Schema is missing a method literal"); } - let methodValue; - if (isZ4Schema(methodSchema)) { - const v4Schema = methodSchema; - const v4Def = v4Schema._zod?.def; - methodValue = v4Def?.value ?? v4Schema.value; - } else { - const v3Schema = methodSchema; - const legacyDef = v3Schema._def; - methodValue = legacyDef?.value ?? v3Schema.value; - } + const methodValue = getLiteralValue(methodSchema); if (typeof methodValue !== "string") { throw new Error("Schema method literal must be a string"); } @@ -34803,8 +34806,17 @@ var Server = class extends Protocol { import process4 from "node:process"; // node_modules/@modelcontextprotocol/sdk/dist/esm/shared/stdio.js +var STDIO_DEFAULT_MAX_BUFFER_SIZE = 10 * 1024 * 1024; var ReadBuffer = class { + constructor(options) { + this._maxBufferSize = options?.maxBufferSize ?? STDIO_DEFAULT_MAX_BUFFER_SIZE; + } append(chunk) { + const newSize = (this._buffer?.length ?? 0) + chunk.length; + if (newSize > this._maxBufferSize) { + this.clear(); + throw new Error(`ReadBuffer exceeded maximum size of ${this._maxBufferSize} bytes`); + } this._buffer = this._buffer ? Buffer.concat([this._buffer, chunk]) : chunk; } readMessage() { @@ -34832,18 +34844,24 @@ function serializeMessage(message) { // node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js var StdioServerTransport = class { - constructor(_stdin = process4.stdin, _stdout = process4.stdout) { + constructor(_stdin = process4.stdin, _stdout = process4.stdout, options) { this._stdin = _stdin; this._stdout = _stdout; - this._readBuffer = new ReadBuffer(); this._started = false; this._ondata = (chunk) => { - this._readBuffer.append(chunk); - this.processReadBuffer(); + try { + this._readBuffer.append(chunk); + this.processReadBuffer(); + } catch (error2) { + this.onerror?.(error2); + this.close().catch(() => { + }); + } }; this._onerror = (error2) => { this.onerror?.(error2); }; + this._readBuffer = new ReadBuffer({ maxBufferSize: options?.maxBufferSize }); } /** * Starts listening for messages on stdin. diff --git a/dist/core/sync.d.ts b/dist/core/sync.d.ts index 4695d5b3..d584523f 100644 --- a/dist/core/sync.d.ts +++ b/dist/core/sync.d.ts @@ -65,6 +65,7 @@ export interface SyncOptions extends NotesOptions { /** Limits applied only to network transport children (`git fetch` and `git push`). */ readonly transport?: Pick; } +export declare const classifyFailureDetail: (detail: string) => string; /** * Synchronise one remote. * diff --git a/dist/core/sync.js b/dist/core/sync.js index 332eccd5..27abb2ec 100644 --- a/dist/core/sync.js +++ b/dist/core/sync.js @@ -61,10 +61,43 @@ const revParse = (ref, opts) => { return result.code === 0 && sha !== '' ? sha : null; }; const isAncestor = (a, b, opts) => execGit(['merge-base', '--is-ancestor', a, b], gitOptions(opts)).code === 0; +/** + * `SyncResult.detail` promises one line, and git does not. A fetch against a + * deleted remote answers with two -- `remote: Repository not found.` and + * `fatal: repository '...' not found` -- and putting both in the column split + * the row in half, so the second line read as a bare `fatal:` standing above + * the table rather than as that remote's result (#865). Collapse here, at the + * one place a git diagnostic becomes a detail, so the table, the JSON and the + * hook all inherit the promise. + */ +const oneLine = (detail) => detail.replace(/\s+/g, ' ').trim(); +/** + * A remote that no longer exists is a normal thing to find in a clone that has + * outlived a fork, and the useful report is which remote, not git's two-line + * phrasing of it. + * + * Bounded to git's own two phrasings — `remote: Repository not found.` and + * `fatal: repository '' not found` — rather than "the words repository and + * not found somewhere in the message". The first draft was the loose version, + * and review found it: `repository metadata not found` and + * `repository credentials not found` would both have been relabelled as a + * missing remote. + */ +const REMOTE_NOT_FOUND = /\brepository\b(?:\s+'[^']*'|\s+"[^"]*")?\s+not found/i; +/** + * A timeout outranks the classification. `describeSync` reads `detail` for + * `ETIMEDOUT` to say *why* the mirror failed, and `execGit` appends that to + * whatever partial stderr the child had already written — so a message can + * carry both. Replacing it with `remote not found` would erase the one part the + * hook actually parses, and the operator would be told a fork is missing when + * the remote simply did not answer in time. + */ +const TIMED_OUT = /\bETIMEDOUT\b/; +export const classifyFailureDetail = (detail) => !TIMED_OUT.test(detail) && REMOTE_NOT_FOUND.test(detail) ? 'remote not found' : oneLine(detail); const failure = (remote, detail) => ({ remote, outcome: 'failed', - detail, + detail: classifyFailureDetail(detail), }); /** * Synchronise one remote. diff --git a/dist/core/sync.js.map b/dist/core/sync.js.map index 9f4976f6..84d8d25b 100644 --- a/dist/core/sync.js.map +++ b/dist/core/sync.js.map @@ -1 +1 @@ -{"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/core/sync.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/core/sync.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/hooks/pre-push.d.ts b/dist/hooks/pre-push.d.ts index b833b21c..72ccf66e 100644 --- a/dist/hooks/pre-push.d.ts +++ b/dist/hooks/pre-push.d.ts @@ -44,19 +44,5 @@ export interface PrePushHookResult { */ export declare const prePushStub: () => string; export declare const installPrePushHook: (cwd?: string) => PrePushHookResult; -/** - * One fail-open line per unsuccessful remote. Successful sync stays quiet. - * - * The line has to answer what the operator will actually ask, which is not - * "what went wrong" but "where are my records now, and do I have to do - * something" (#632). It also has to answer it differently for the two - * outcomes, because their answers are opposite: a failed push is transient and - * the next push retries it — `syncNotes` keeps no state and recompares the - * refs every time — while a divergence is two mirrors neither of which - * fast-forwards, and retrying that forever changes nothing. - * - * Saying only "branch push continues" reported the half the operator could - * already see and left the half they were asking about unstated. - */ -export declare const describeSync: (results: readonly SyncResult[]) => string[]; +export declare const describeSync: (results: readonly SyncResult[], hasLocalRecords?: boolean | null) => string[]; export declare const register: (program: Command) => void; diff --git a/dist/hooks/pre-push.js b/dist/hooks/pre-push.js index d2e5da8a..4be3e492 100644 --- a/dist/hooks/pre-push.js +++ b/dist/hooks/pre-push.js @@ -25,6 +25,7 @@ import { randomBytes } from 'node:crypto'; import { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs'; import { resolve } from 'node:path'; import { execGit } from '../core/git.js'; +import { NOTES_REF } from '../core/notes.js'; import { syncNotes } from '../core/sync.js'; import { CHAINED_SUFFIX, HOOK_MODE, captureHookStub } from './commit-msg.js'; export const PRE_PUSH_HOOK_MARKER = '# commitlore:pre-push:v1'; @@ -118,11 +119,39 @@ const saidWhy = (detail) => /\bETIMEDOUT\b/.test(detail) * Saying only "branch push continues" reported the half the operator could * already see and left the half they were asking about unstated. */ -export const describeSync = (results) => results +/** + * Is there anything local the mirror would have sent? + * + * #632 asked exactly this and #656 answered it unconditionally with yes, so a + * push whose repository had no records at all was told its records were "still + * only local" (#865). The remote's contents cannot be known once the remote has + * stopped answering; whether this clone has a notes ref is a local question + * that cannot time out. + * + * Deliberately ref-scoped and not commit-scoped. The mirror publishes + * `refs/notes/commitlore` whole, so a record written against a commit the + * remote already has is still unsent -- and a check that only looked at the + * commits in this push would call that "nothing waiting" and be wrong in the + * more dangerous direction. `test/pre-push-hook.test.ts` fixes that shape. + * + * `null` when git will not answer at all, so the caller keeps the cautious + * sentence rather than inventing a reassuring one from a failure to measure. + */ +const localRecordsExist = () => { + const result = execGit(['rev-parse', '--verify', '--quiet', NOTES_REF]); + if (result.code === 0) + return result.stdout.trim() !== ''; + // `--verify --quiet` exits 1 for "no such ref", which is an answer. Anything + // else -- not a repository, git missing -- is not. + return result.code === 1 ? false : null; +}; +export const describeSync = (results, hasLocalRecords = null) => results .filter((result) => result.outcome === 'failed' || result.outcome === 'diverged') .map((result) => result.outcome === 'diverged' ? `commitlore: notes mirror (${result.remote}) diverged: ${oneLine(result.detail)}. The branch was pushed. Your records and the remote's both exist and neither one fast-forwards, so a later push will not settle it — run "commitlore sync" to merge them.` - : `commitlore: notes mirror (${result.remote}) failed: ${saidWhy(result.detail)}. The branch was pushed; the records for these commits are still only local. The next push retries this automatically, or run "commitlore sync" to send them now.`); + : hasLocalRecords === false + ? `commitlore: notes mirror (${result.remote}) failed: ${saidWhy(result.detail)}. The branch was pushed. Nothing is waiting locally, so nothing was lost.` + : `commitlore: notes mirror (${result.remote}) failed: ${saidWhy(result.detail)}. The branch was pushed; the records for these commits are still only local. The next push retries this automatically, or run "commitlore sync" to send them now.`); /** * Git itself must not prompt, and the default SSH command refuses interactive * authentication. A caller's SSH wrapper is preserved because it may carry @@ -140,6 +169,9 @@ export const register = (program) => { .argument('[url]', 'its URL, as git passes it') .description('internal hook command: publish the notes mirror alongside a push') .action((remote) => { + // Measured before the transport runs, because it must not depend on the + // remote answering: that is the whole distinction #865 turns on. + const hasLocalRecords = localRecordsExist(); try { const results = syncNotes({ ...(remote === undefined || remote === '' ? {} : { remotes: [remote] }), @@ -148,14 +180,17 @@ export const register = (program) => { timeout: PRE_PUSH_NOTES_SYNC_TIMEOUT_MS, }, }); - for (const line of describeSync(results)) + for (const line of describeSync(results, hasLocalRecords)) process.stderr.write(`${line}\n`); } catch (error) { // A push must never fail because the mirror could not be published — // and the line must still say where the records ended up, for the same // reason `describeSync` does (#632). - process.stderr.write(`commitlore: notes mirror failed: ${saidWhy(error instanceof Error ? error.message : String(error))}. The branch was pushed; the records for these commits are still only local. The next push retries this automatically, or run "commitlore sync" to send them now.\n`); + const why = saidWhy(error instanceof Error ? error.message : String(error)); + process.stderr.write(hasLocalRecords === false + ? `commitlore: notes mirror failed: ${why}. The branch was pushed. Nothing is waiting locally, so nothing was lost.\n` + : `commitlore: notes mirror failed: ${why}. The branch was pushed; the records for these commits are still only local. The next push retries this automatically, or run "commitlore sync" to send them now.\n`); } }); }; diff --git a/dist/hooks/pre-push.js.map b/dist/hooks/pre-push.js.map index 6bd6c1ae..ed0b4feb 100644 --- a/dist/hooks/pre-push.js.map +++ b/dist/hooks/pre-push.js.map @@ -1 +1 @@ -{"version":3,"file":"pre-push.js","sourceRoot":"","sources":["../../src/hooks/pre-push.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"pre-push.js","sourceRoot":"","sources":["../../src/hooks/pre-push.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/install.ps1 b/install.ps1 index 821f27c0..30b85c06 100644 --- a/install.ps1 +++ b/install.ps1 @@ -1,8 +1,8 @@ <# Installs commitlore from source on Windows, for any agent that is not Claude Code. - irm https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.0/install.ps1 | iex - & ([scriptblock]::Create((irm https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.0/install.ps1))) v1.2.0 + irm https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.1/install.ps1 | iex + & ([scriptblock]::Create((irm https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.1/install.ps1))) v1.2.1 Claude Code users do not need this script. The repository is itself a plugin marketplace (ADR-0011), so two /plugin commands register the MCP server, the diff --git a/install.sh b/install.sh index 7d793fc8..d279dd53 100755 --- a/install.sh +++ b/install.sh @@ -1,8 +1,8 @@ #!/bin/sh # Installs commitlore from source, for any agent that is not Claude Code. # -# curl -fsSL https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.0/install.sh | sh -# curl -fsSL https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.0/install.sh | sh -s v1.2.0 +# curl -fsSL https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.1/install.sh | sh +# curl -fsSL https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.1/install.sh | sh -s v1.2.1 # # **Claude Code users do not need this script.** The repository is itself a # plugin marketplace (ADR-0011), so two `/plugin` commands register the MCP diff --git a/installer/canonical-artifact.json b/installer/canonical-artifact.json index 306c3851..175e527b 100644 --- a/installer/canonical-artifact.json +++ b/installer/canonical-artifact.json @@ -15,10 +15,10 @@ "tsconfig.json", "src" ], - "sha256": "c939c152715ab8f01eea0888e26f73435db53c82931c4741b28ad162ad73619c" + "sha256": "5af161de2542ca2e07d5566a1a2dbd66ed51e9bf4ad9c9d8c3f64609fd9b1d4a" }, "artifact": { - "sha256": "469d61aa6502ebdbdd9915e5b962144bb718b782a634cd43cf19a53f8fde5a5e", + "sha256": "26e55355619ad81dae04eed5f36be60cb7223378fca290974bcfd16a602616b1", "files": [ { "path": "dist/cli.d.ts", @@ -622,7 +622,7 @@ }, { "path": "dist/commitlore.mjs", - "sha256": "24b845a7ee9b7a65f2b335f0a299a6d623a7131cdb54f8e664ec6a4b838cacde" + "sha256": "9932c059f0d4ce8a4cab17ce674a4089ec74bd099b3cf26dc13bbed557e92f02" }, { "path": "dist/core/agent-configs.d.ts", @@ -1046,15 +1046,15 @@ }, { "path": "dist/core/sync.d.ts", - "sha256": "f42b5512c20636900748d6765eb2fc624848b7d6acbce4cd1d84f09eee8d0897" + "sha256": "64ec1350270d7498a9675adab0b67621dd01cdce9cf192dba74513cb079f7975" }, { "path": "dist/core/sync.js", - "sha256": "4063614b79318a4180cb249f4fea31b171e0b77973b42a56d1b66b9ed1ad416e" + "sha256": "38c81bb0829d4ca97ca30a2606a446d69baf051924d91b5e34f43dd84d011ff0" }, { "path": "dist/core/sync.js.map", - "sha256": "31caa351dedfddf17ee656d1c6f4ac0f480094257e369019173a0f698f78295b" + "sha256": "f87d0eb490fe1a4924761853a8b0ce1c4df0225813e8a356178ebe9622ec55c1" }, { "path": "dist/core/trailers.d.ts", @@ -1178,15 +1178,15 @@ }, { "path": "dist/hooks/pre-push.d.ts", - "sha256": "50a328d14efd52cfa7c5fed03f49eb8a7e9efe805646c09686b3295a0c7e8f25" + "sha256": "bcf44f344dd9852c9e8ed1baa8a20898631fe96a20d78c0a19553c7d3e7e8d20" }, { "path": "dist/hooks/pre-push.js", - "sha256": "dc4d6dc0e6aeb688851bd098ac4fec47297dccf4aa748fb34b2e242b9c658b22" + "sha256": "e5730b7d2aa93b017490b84c18ea1867e40941843ebe7be4d061b462fdc23eb2" }, { "path": "dist/hooks/pre-push.js.map", - "sha256": "a4d1e396c78dd7f172409df90e170c2dd769f50b51e8fe4372e09e28b2b77276" + "sha256": "2a7adc5d162bbe9423726c24f03743d901599b71514d4661734ae2cb33f5ee4c" }, { "path": "dist/hooks/prepare-commit-msg.d.ts", diff --git a/package-lock.json b/package-lock.json index 6f80c690..99a685e8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,15 @@ { "name": "commitlore", - "version": "1.2.0", + "version": "1.2.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "commitlore", - "version": "1.2.0", + "version": "1.2.1", "license": "MIT", "dependencies": { - "@modelcontextprotocol/sdk": "^1.29.0", + "@modelcontextprotocol/sdk": "^1.30.0", "ajv": "^8.20.0", "ajv-formats": "^3.0.1", "commander": "^15.0.0" @@ -18,9 +18,9 @@ "@types/js-yaml": "^4.0.9", "@types/node": "^22.10.0", "esbuild": "^0.28.2", - "js-yaml": "^5.2.3", + "js-yaml": "^5.4.1", "typescript": "^5.7.0", - "vitest": "^2.1.0" + "vitest": "^4.1.11" }, "engines": { "node": ">=22.23.2" @@ -481,19 +481,19 @@ } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.6.0.tgz", + "integrity": "sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==", "dev": true, "license": "MIT" }, "node_modules/@modelcontextprotocol/sdk": { - "version": "1.29.0", - "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.29.0.tgz", - "integrity": "sha512-zo37mZA9hJWpULgkRpowewez1y6ML5GsXJPY8FI0tBBCd77HEvza4jDqRKOXgHNn867PVGCyTdzqpz0izu5ZjQ==", + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.30.0.tgz", + "integrity": "sha512-xKd8OIzlqNzcqcNumGAa6g+PW2kjD5vrpcKOnfldAUPP3j7lnqMPwlTXQm8gF+UwH72z0lqaRbjr9hqGz0eITA==", "license": "MIT", "dependencies": { - "@hono/node-server": "^1.19.9", + "@hono/node-server": "^1.19.9 || ^2.0.5", "ajv": "^8.17.1", "ajv-formats": "^3.0.1", "content-type": "^1.0.5", @@ -527,10 +527,20 @@ } } }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.62.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.62.2.tgz", - "integrity": "sha512-6o7ZLZK+BeenkZCFNDXqpbjw9bD6nuWonvS/lwQJp7NoVVxm6p3qE7qQ5jGuBjiFsgvqjD8mZAU5oWxTmbOeOg==", + "node_modules/@oxc-project/types": { + "version": "0.147.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.147.0.tgz", + "integrity": "sha512-IJ3s6ltHLp45S0bh7phkX+gJO7A1Wuz2EaqpAhb8WjqDwbzMiWKHhyyT42tskaWjEYXtHtVCPpnBJVT9+dcRLg==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Boshen" + } + }, + "node_modules/@rolldown/binding-android-arm-eabi": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm-eabi/-/binding-android-arm-eabi-1.2.6.tgz", + "integrity": "sha512-b+jTcARdTiFLI6jB4a5XjTm0RWd6KcRfQj/I2356fxUZemiho9zQLxo0RtCuMDAyKcLo6cEltkgbQp6d1+sjjQ==", "cpu": [ "arm" ], @@ -539,12 +549,15 @@ "optional": true, "os": [ "android" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.62.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.62.2.tgz", - "integrity": "sha512-BaH7BllCACHoH1LguOU56UItGfUWjujlO65kS9LAodViaN4bwIKd7oeW/ZHJ/4ljr/7MIiENnNy3HJ0zXv8Zkw==", + "node_modules/@rolldown/binding-android-arm64": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.6.tgz", + "integrity": "sha512-lkWU8ZJaRk9q3CIEY1Tc7vIFALp3Xw5NfGJo2hQg5oIqNgxWi1zI+IiDEK3r70BF5Dzol1tcXsnzsRc8NLhG+Q==", "cpu": [ "arm64" ], @@ -553,12 +566,15 @@ "optional": true, "os": [ "android" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.62.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.62.2.tgz", - "integrity": "sha512-v39RCCvj4He82I9sFmk+M1VZ0PLM9sfsLVikjfx2hYBNALhrrOR2D3JjQA6AhlaSOgcR+RzrKY7e1+bT6SUO/A==", + "node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.6.tgz", + "integrity": "sha512-dgR56NYnvAszm7Ob1B2/Vn0e8bUQYZH2UjVaMMtMVOCKFSfjhfLmuA/9+O+F+ajUdG6B/bSssrKW6JJYASa8jA==", "cpu": [ "arm64" ], @@ -567,12 +583,15 @@ "optional": true, "os": [ "darwin" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.62.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.62.2.tgz", - "integrity": "sha512-yl0y2vq3S3lHeuXhEdss6TWfKW8vkujImO12tn4ZkG/4oghr09LvdYm2RElVjokTQiUvDUGXLGsYeLqUMCKpGA==", + "node_modules/@rolldown/binding-darwin-x64": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.6.tgz", + "integrity": "sha512-vpVxFvUCFioJqug7OTvqptkc4yb8UX0AwfDmJpaR/0sWz+BUmqSVAf7c8JkUgnN8YLspb4a/N6NhTyMAmdyQ7Q==", "cpu": [ "x64" ], @@ -581,26 +600,15 @@ "optional": true, "os": [ "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.62.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.62.2.tgz", - "integrity": "sha512-tT4pvt4qXD+vEoezupCWi+a1F0vvDiksiHc+PxRlYTOH1I6/X4id9jPxTP+Fg+545euaFT1jJVs4CEdHZAU1vw==", - "cpu": [ - "arm64" ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.62.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.62.2.tgz", - "integrity": "sha512-6nU5F2wCW+qvCBhTn1pdIU3bzsIoF7EUwsCDRxilWGprQR6yd508YnH9+OKFCwpfS8pjZqDUmnCAr7exax0XCg==", + "node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.6.tgz", + "integrity": "sha512-h1wG6Y6K3JlRswxsI64qQJqBAy4vrLuHgRbc8CZMGSWTOFRY6ghMApM1NKzB2I0n5xV1fjkE18SuVl2QpLeNpA==", "cpu": [ "x64" ], @@ -609,26 +617,15 @@ "optional": true, "os": [ "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.62.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.62.2.tgz", - "integrity": "sha512-n1GJHPOvpIfhi3TmrCeh6S6URt9BFCt0KQE3qvexyGCTAKpR4Lg+eWvNZEqu7epxwus/8ElT3hacYEucm49SZg==", - "cpu": [ - "arm" ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.62.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.62.2.tgz", - "integrity": "sha512-JqgflS8wEB+UXV/vS1RpRbifGBeN4D5lz8D8oOFbFZw4vedvdOgCFAjfBmIMdW3yL10XpQQ0Ambepw6MXrhOnA==", + "node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.6.tgz", + "integrity": "sha512-tbCiqub0q2MVWJKgF5PoAlNWCtQydiOYSLIkd8sByqK/6MMYLJRcSXSYodqYtd0O+Fw7QaVmKKlS4oL94YRZ0w==", "cpu": [ "arm" ], @@ -637,180 +634,135 @@ "optional": true, "os": [ "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.62.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.62.2.tgz", - "integrity": "sha512-wnFJkogWvN4jm/hQRF2UBaeUmk20j5+DmHvoyWii2b8HJDyvz1MF2OU/6ynXt2KR63rbZLWkFpoytpdc/yBuSA==", - "cpu": [ - "arm64" ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.62.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.62.2.tgz", - "integrity": "sha512-HVu2bp0zhvJ8xHEV9+UUs7S90VadmBSY3LcIMvozbPo4AuMGDWlz3ymHLHZPX4hR67TKTt8Qp5PJ5RBg/i+RMQ==", + "node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.6.tgz", + "integrity": "sha512-oxK9+baEBPhZG5HB4URY+uU04zJWeZlH6Tb9rB5DK4DF9XR1uXNLXt5Q5ZsugTKayNCNLhkcwz/ye74hRI98dg==", "cpu": [ "arm64" ], "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.62.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.62.2.tgz", - "integrity": "sha512-mQqqAV8QaoSgr9I2fKDLY2BAVvmKjWoGiu/cSYQonsLvtqwEn1E4QYfnCOcp5zoEqNhsDYin1s6jx/VJmrxlZg==", - "cpu": [ - "loong64" + "libc": [ + "glibc" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.62.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.62.2.tgz", - "integrity": "sha512-IxKLoxCQ2IWi6bT2akyDUBGsOImDKB+sPp4EsTmwFQ/fMwpCKm8uLSSgP/Kx/QYUgKis6SEZ5/Nlhup0DIA0PQ==", - "cpu": [ - "loong64" ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.62.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.62.2.tgz", - "integrity": "sha512-Mk5ha2RQSgyFfmYYLkBpPnUk8D8FriBxesO1u9O75X0mHgXL1UQcH5Itl2lurWL2tj0RxV9b9tJgipac0hRY9A==", + "node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.6.tgz", + "integrity": "sha512-muWCk27FVBEZtv0MsK8gnfSmgczA8KQ0uRVJbTABKhkRfQc38aUrcb7fhi3BNiyseFmgcRsoMfQsSNJ+DbZdSw==", "cpu": [ - "ppc64" + "arm64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ "linux" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.62.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.62.2.tgz", - "integrity": "sha512-CjvEnqJL/0/TQ3TXX3OPIJ/kmBellrWd4heXUmHeJlTnmwjKpSJzoehLaL6Xk0ZnMHBu9dZuFADNOrtjF4v+2w==", + "node_modules/@rolldown/binding-linux-ppc64-gnu": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.6.tgz", + "integrity": "sha512-eWDoSfU7Co2qj3vgB3Dt4lj1mG6CoWbcJQkRMP3XJplyCMtuaq3LHvPFjS9QIPvMGWVadJC04Xiy0IdcVPtnwQ==", "cpu": [ "ppc64" ], "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.62.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.62.2.tgz", - "integrity": "sha512-1SiZbzwdkaDURsew/tSOrooKiYy7EQGT6m8ufavAi9NEyQb/6VuIxFXAL1fqa4iZe3g4NbNk4P7J32z2tw5Mgg==", - "cpu": [ - "riscv64" + "libc": [ + "glibc" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.62.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.62.2.tgz", - "integrity": "sha512-nQts12zJ3NQRoE6uYljOH89v7szzLDvG2JD/vsX+vGXU8w/At1GowTZ5/7qeFQ8m7L55rpR8Okugnuo5bgjy2Q==", - "cpu": [ - "riscv64" ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.62.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.62.2.tgz", - "integrity": "sha512-E9/ll019jhPIJgpzfZoIkBGhcz+kKNgVWYRY0zr9srBdPPFVpvOKW8VaJKUbeK+eZXyQF9ltME+Kk6affeaPgg==", + "node_modules/@rolldown/binding-linux-s390x-gnu": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.6.tgz", + "integrity": "sha512-2bWNjRSIayvupRKxXUY2tWG9fYdoUlTqWywHRvE8Eq3GvuQ+f2HeIkve697fIt+IQs/PV8yFsdWuhp1aJ1PdnA==", "cpu": [ "s390x" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ "linux" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.62.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.62.2.tgz", - "integrity": "sha512-5BqxR/pshjey51iliyzTD5Xi3EN0aLmQ2lZ3lvefVV9c82BvrLo2/6OT55iifpWBufs6kdwWbuOKS841DrmK9A==", + "node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.6.tgz", + "integrity": "sha512-KekI0gS0wLxe1UBSQSjenBVwou/JkcQPDzBPICGZjxUv9k3RteHDPBQaiOicZUFKRIH2wKEimGwVpnJsbPzu7w==", "cpu": [ "x64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ "linux" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.62.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.62.2.tgz", - "integrity": "sha512-uNN83XxQrRAh/w0/pmAfibcwyb6YWt4gP+dpnQKPVJshAloQ785ii8CT8ZCIxkGg9opVsvAlGhFitSm6D1Jjpg==", + "node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.6.tgz", + "integrity": "sha512-TvtPnfVr+HtyGiDmPK4VWmlNm7QhNNAcK5Q9A7aOXsI8545yCyaoMaicXrFZ72JzeYjaUVk7yT243zT0jzjFKQ==", "cpu": [ "x64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ "linux" - ] - }, - "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.62.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.62.2.tgz", - "integrity": "sha512-srjEIxSH3LRnJN6THczDHWQplqEMFiAJrTab0msUryh9kwNpkICf3Ea6q6MN/2cZwRFUNx5w+h6Hpi4QuHS6Zg==", - "cpu": [ - "x64" ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.62.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.62.2.tgz", - "integrity": "sha512-8hOJnxgbyObnCm5AlRA3A931xX19xq80RjVTKgJOvEKWqJruP/Uf12IbAOaDjjEXYRewwHLfmF0YRIdK3OwKWA==", + "node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.6.tgz", + "integrity": "sha512-iOo0VEay2XFhaCcH0sps5XIimkSuOnNaZrf6+ZkoSOQBJPKNU48RkmJv0/lSpipexu5P+ouFgafe5IGr/DiQfg==", "cpu": [ "arm64" ], @@ -819,12 +771,15 @@ "optional": true, "os": [ "openharmony" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.62.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.62.2.tgz", - "integrity": "sha512-mmF4AY1i0hG/bLWUctUq59gtmgaSIRa3cu/A3JFRp/sCNEme2bgDEiDS22P9FbnJB8NJNF4jPJiSP5RHQpUTDg==", + "node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.6.tgz", + "integrity": "sha512-y5NTmmasMS455JlOCO4ZM9krIchv3Mvm1crL1iUPGOPgEzSkves9n0SdC5Sjz6+qWDFhd8/JpfWMH8NSWNHe+A==", "cpu": [ "arm64" ], @@ -833,26 +788,15 @@ "optional": true, "os": [ "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.62.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.62.2.tgz", - "integrity": "sha512-DZgkknc6jhHrk46V25vbAM0zZkyP0nSDkJB8/dRkLTxv470dOmWDqGoEJl/9A0dFfS7yE3REOwNDxpHwSLSt0Q==", - "cpu": [ - "ia32" ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.62.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.62.2.tgz", - "integrity": "sha512-T6xr6ucWSFto+VGajA8YH26LdpHRuP4YLHEKAtCWvJDOlnmWcDZVCI2Jmjr+IFHDlt2zRaTAKE4tfjTaWLgJBg==", + "node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.6.tgz", + "integrity": "sha512-np8iZSLfXlAD4kWhiyq/u0Yt8oZDtRQ8lGhQaCXo2rl37KNjeU0GjJuwr4P3oeZ++ROfofsKNBqR5LTO8aXyWQ==", "cpu": [ "x64" ], @@ -861,21 +805,42 @@ "optional": true, "os": [ "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.62.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.62.2.tgz", - "integrity": "sha512-BfzEnDJOt9T8M989/lA37EcJgat01wLRnoi5dQf3QzOH7jzpqTAzdDbVfRljVr5r+jzKqpbHeyOfAaXxAd0PAA==", - "cpu": [ - "x64" ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz", + "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/chai": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ] + "dependencies": { + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" + } + }, + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true, + "license": "MIT" }, "node_modules/@types/estree": { "version": "1.0.9", @@ -902,38 +867,40 @@ } }, "node_modules/@vitest/expect": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.9.tgz", - "integrity": "sha512-UJCIkTBenHeKT1TTlKMJWy1laZewsRIzYighyYiJKZreqtdxSos/S1t+ktRMQWu2CKqaarrkeszJx1cgC5tGZw==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.11.tgz", + "integrity": "sha512-VX2x5vNJXET47KAFzwERI+KRMtTTCSWTfSMKsW7JsUsXV4psq++e3DvZpuTDOpHcxytiDs6p2nhVb2tVDiiUYw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "2.1.9", - "@vitest/utils": "2.1.9", - "chai": "^5.1.2", - "tinyrainbow": "^1.2.0" + "@standard-schema/spec": "^1.1.0", + "@types/chai": "^5.2.2", + "@vitest/spy": "4.1.11", + "@vitest/utils": "4.1.11", + "chai": "^6.2.2", + "tinyrainbow": "^3.1.0" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/mocker": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.9.tgz", - "integrity": "sha512-tVL6uJgoUdi6icpxmdrn5YNo3g3Dxv+IHJBr0GXHaEdTcw3F+cPKnsXFhli6nO+f/6SDKPHEK1UN+k+TQv0Ehg==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.11.tgz", + "integrity": "sha512-2XJVD55d1o5AZous5CCGKS74g/riOj9odEt2bQpCVZeblHyHdnMeFl4jl0XjU21stf4mbjUkew2eXQZt65g5CQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "2.1.9", + "@vitest/spy": "4.1.11", "estree-walker": "^3.0.3", - "magic-string": "^0.30.12" + "magic-string": "^0.30.21" }, "funding": { "url": "https://opencollective.com/vitest" }, "peerDependencies": { "msw": "^2.4.9", - "vite": "^5.0.0" + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "peerDependenciesMeta": { "msw": { @@ -945,70 +912,68 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.9.tgz", - "integrity": "sha512-KhRIdGV2U9HOUzxfiHmY8IFHTdqtOhIzCpd8WRdJiE7D/HUcZVD0EgQCVjm+Q9gkUXWgBvMmTtZgIG48wq7sOQ==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.11.tgz", + "integrity": "sha512-yiZzPbGTS9Sr/JpFl8zHrcIkAofNbFV6k21vIgQN/cY/oxZeXhJv5sc/MBJ5jFKWmWs+oJHw0UXLZjmf931+Vw==", "dev": true, "license": "MIT", "dependencies": { - "tinyrainbow": "^1.2.0" + "tinyrainbow": "^3.1.0" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/runner": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.9.tgz", - "integrity": "sha512-ZXSSqTFIrzduD63btIfEyOmNcBmQvgOVsPNPe0jYtESiXkhd8u2erDLnMxmGrDCwHCCHE7hxwRDCT3pt0esT4g==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.11.tgz", + "integrity": "sha512-LztvUgdwMNJMIkj3hQnnxiC2Xy1zNxq928W/xhjCLaNCzqTZOudjwbQf6v9IntZGPw132i2Lq2rgTRZHD3JHNw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "2.1.9", - "pathe": "^1.1.2" + "@vitest/utils": "4.1.11", + "pathe": "^2.0.3" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/snapshot": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.9.tgz", - "integrity": "sha512-oBO82rEjsxLNJincVhLhaxxZdEtV0EFHMK5Kmx5sJ6H9L183dHECjiefOAdnqpIgT5eZwT04PoggUnW88vOBNQ==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.11.tgz", + "integrity": "sha512-pN7ikn1ON7h8ee4gIAp4AzyK+zBtJPzVbqOgu5LCEh4VaJVbPQcgYQYJIMGQPXVeJJq1fnfazis7a5pFNPahog==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "2.1.9", - "magic-string": "^0.30.12", - "pathe": "^1.1.2" + "@vitest/pretty-format": "4.1.11", + "@vitest/utils": "4.1.11", + "magic-string": "^0.30.21", + "pathe": "^2.0.3" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/spy": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.9.tgz", - "integrity": "sha512-E1B35FwzXXTs9FHNK6bDszs7mtydNi5MIfUWpceJ8Xbfb1gBMscAnwLbEu+B44ed6W3XjL9/ehLPHR1fkf1KLQ==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.11.tgz", + "integrity": "sha512-apNa/prQy2qCeywhnixOHPRCgGNhvg7T4Dapfl1GahLp/R+uhBm5cPyFoNVyqsNd2h1nJxL6BqqdIjiABL60YA==", "dev": true, "license": "MIT", - "dependencies": { - "tinyspy": "^3.0.2" - }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/utils": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.9.tgz", - "integrity": "sha512-v0psaMSkNJ3A2NMrUEHFRzJtDPFn+/VWZ5WxImB21T9fjucJRmS7xCS3ppEnARb9y11OAzaD+P2Ps+b+BGX5iQ==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.11.tgz", + "integrity": "sha512-zTCVGpyFsGWBhllOyKlTw/vnr6D9qxsfSDyfbyZmTyjHw5N/VuvzHpHoQjm2ZJzn4RJgx5w4r7V0er69CmLgPQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "2.1.9", - "loupe": "^3.1.2", - "tinyrainbow": "^1.2.0" + "@vitest/pretty-format": "4.1.11", + "convert-source-map": "^2.0.0", + "tinyrainbow": "^3.1.0" }, "funding": { "url": "https://opencollective.com/vitest" @@ -1123,16 +1088,6 @@ "node": ">= 0.8" } }, - "node_modules/cac": { - "version": "6.7.14", - "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", - "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/call-bind-apply-helpers": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", @@ -1163,32 +1118,15 @@ } }, "node_modules/chai": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/chai/-/chai-5.3.3.tgz", - "integrity": "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", + "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", "dev": true, "license": "MIT", - "dependencies": { - "assertion-error": "^2.0.1", - "check-error": "^2.1.1", - "deep-eql": "^5.0.1", - "loupe": "^3.1.0", - "pathval": "^2.0.0" - }, "engines": { "node": ">=18" } }, - "node_modules/check-error": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.3.tgz", - "integrity": "sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 16" - } - }, "node_modules/commander": { "version": "15.0.0", "resolved": "https://registry.npmjs.org/commander/-/commander-15.0.0.tgz", @@ -1220,6 +1158,13 @@ "node": ">= 0.6" } }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, "node_modules/cookie": { "version": "0.7.2", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", @@ -1286,16 +1231,6 @@ } } }, - "node_modules/deep-eql": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", - "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -1305,6 +1240,16 @@ "node": ">= 0.8" } }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", @@ -1353,9 +1298,9 @@ } }, "node_modules/es-module-lexer": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", - "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.3.2.tgz", + "integrity": "sha512-poHGpORABojJJucnV9KbOavETW8lBVnphkW77ER5/BQ5Fz7oXSoCNek7IH3vR5nRjdsEz926ibFYX8KtLQmdyw==", "dev": true, "license": "MIT" }, @@ -1553,6 +1498,24 @@ ], "license": "BSD-3-Clause" }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, "node_modules/finalhandler": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz", @@ -1780,9 +1743,9 @@ } }, "node_modules/js-yaml": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-5.2.3.tgz", - "integrity": "sha512-n+mUVyUX5bVv7G/G2zyIHOhdxfuU1dY2NOFzTQUWiMUbFss8b57NFlgCCaggU78wSw5KVS9cllzeLyzyR+n5nw==", + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-5.4.1.tgz", + "integrity": "sha512-28R/k+NAjeuf7+CKlTxWZVExJGwVVLwY06DgEnOMz2gEpfNkDcD7QvyiVPT0xy0XXhU8vHsd4Ot42OOPdJG7dQ==", "dev": true, "funding": [ { @@ -1814,58 +1777,324 @@ "integrity": "sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA==", "license": "BSD-2-Clause" }, - "node_modules/loupe": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz", - "integrity": "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/magic-string": { - "version": "0.30.21", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", - "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "node_modules/lightningcss": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.33.0.tgz", + "integrity": "sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==", "dev": true, - "license": "MIT", + "license": "MPL-2.0", "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.5" - } - }, - "node_modules/math-intrinsics": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", - "license": "MIT", + "detect-libc": "^2.0.3" + }, "engines": { - "node": ">= 0.4" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.33.0", + "lightningcss-darwin-arm64": "1.33.0", + "lightningcss-darwin-x64": "1.33.0", + "lightningcss-freebsd-x64": "1.33.0", + "lightningcss-linux-arm-gnueabihf": "1.33.0", + "lightningcss-linux-arm64-gnu": "1.33.0", + "lightningcss-linux-arm64-musl": "1.33.0", + "lightningcss-linux-x64-gnu": "1.33.0", + "lightningcss-linux-x64-musl": "1.33.0", + "lightningcss-win32-arm64-msvc": "1.33.0", + "lightningcss-win32-x64-msvc": "1.33.0" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.33.0.tgz", + "integrity": "sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/media-typer": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.1.tgz", - "integrity": "sha512-yz3xRaG20c6/BOzvYoDaGtPmGscs7YivItZEEqe6GbwNfHuxu9YNmvnEkMzKldAGY4/80pRcQRZSEnhquk9XuQ==", - "license": "MIT", + "node_modules/lightningcss-darwin-arm64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.33.0.tgz", + "integrity": "sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">= 0.8" + "node": ">= 12.0.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/express" + "url": "https://opencollective.com/parcel" } }, - "node_modules/merge-descriptors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", - "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", - "license": "MIT", + "node_modules/lightningcss-darwin-x64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.33.0.tgz", + "integrity": "sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=18" + "node": ">= 12.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/mime-db": { + "node_modules/lightningcss-freebsd-x64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.33.0.tgz", + "integrity": "sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.33.0.tgz", + "integrity": "sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.33.0.tgz", + "integrity": "sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.33.0.tgz", + "integrity": "sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.33.0.tgz", + "integrity": "sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.33.0.tgz", + "integrity": "sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.33.0.tgz", + "integrity": "sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.33.0.tgz", + "integrity": "sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.1.tgz", + "integrity": "sha512-yz3xRaG20c6/BOzvYoDaGtPmGscs7YivItZEEqe6GbwNfHuxu9YNmvnEkMzKldAGY4/80pRcQRZSEnhquk9XuQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/merge-descriptors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mime-db": { "version": "1.54.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", @@ -1945,6 +2174,20 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/obug": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.4.tgz", + "integrity": "sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==", + "dev": true, + "funding": [ + "https://github.com/sponsors/sxzz", + "https://opencollective.com/debug" + ], + "license": "MIT", + "engines": { + "node": ">=12.20.0" + } + }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -1995,22 +2238,12 @@ } }, "node_modules/pathe": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", - "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", "dev": true, "license": "MIT" }, - "node_modules/pathval": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz", - "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 14.16" - } - }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -2018,6 +2251,19 @@ "dev": true, "license": "ISC" }, + "node_modules/picomatch": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz", + "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/pkce-challenge": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.1.tgz", @@ -2028,9 +2274,9 @@ } }, "node_modules/postcss": { - "version": "8.5.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.23.tgz", - "integrity": "sha512-g50586zr4bZmwFiTlflMu8E0bDTb5I5gertgwAKmsdUlTQIhZtunzUlD1WSzwcVWPoAVpsrA6vlfCD7oXvRwgg==", + "version": "8.5.26", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.26.tgz", + "integrity": "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==", "dev": true, "funding": [ { @@ -2048,7 +2294,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.16", + "nanoid": "^3.3.17", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -2122,49 +2368,38 @@ "node": ">=0.10.0" } }, - "node_modules/rollup": { - "version": "4.62.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.62.2.tgz", - "integrity": "sha512-RFnrW4lhXA3s3eqHDZvN654g8OTjzRfqpIRJYczCGB6HzphckVAi/Qh4tbPUbRuDi7s1Llv8g/NspLkttY3gTA==", + "node_modules/rolldown": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.6.tgz", + "integrity": "sha512-vMM4q3aixf46GiF1Kok8jDPFsEpXgFWGjUHXNkNHNm+Y2adXAG2dbX91jkti3i0ZRsOlcmbuzAz1poObSHCmUA==", "dev": true, "license": "MIT", "dependencies": { - "@types/estree": "1.0.9" + "@oxc-project/types": "=0.147.0", + "@rolldown/pluginutils": "^1.0.0" }, "bin": { - "rollup": "dist/bin/rollup" + "rolldown": "bin/cli.mjs" }, "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" + "node": "^20.19.0 || >=22.12.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.62.2", - "@rollup/rollup-android-arm64": "4.62.2", - "@rollup/rollup-darwin-arm64": "4.62.2", - "@rollup/rollup-darwin-x64": "4.62.2", - "@rollup/rollup-freebsd-arm64": "4.62.2", - "@rollup/rollup-freebsd-x64": "4.62.2", - "@rollup/rollup-linux-arm-gnueabihf": "4.62.2", - "@rollup/rollup-linux-arm-musleabihf": "4.62.2", - "@rollup/rollup-linux-arm64-gnu": "4.62.2", - "@rollup/rollup-linux-arm64-musl": "4.62.2", - "@rollup/rollup-linux-loong64-gnu": "4.62.2", - "@rollup/rollup-linux-loong64-musl": "4.62.2", - "@rollup/rollup-linux-ppc64-gnu": "4.62.2", - "@rollup/rollup-linux-ppc64-musl": "4.62.2", - "@rollup/rollup-linux-riscv64-gnu": "4.62.2", - "@rollup/rollup-linux-riscv64-musl": "4.62.2", - "@rollup/rollup-linux-s390x-gnu": "4.62.2", - "@rollup/rollup-linux-x64-gnu": "4.62.2", - "@rollup/rollup-linux-x64-musl": "4.62.2", - "@rollup/rollup-openbsd-x64": "4.62.2", - "@rollup/rollup-openharmony-arm64": "4.62.2", - "@rollup/rollup-win32-arm64-msvc": "4.62.2", - "@rollup/rollup-win32-ia32-msvc": "4.62.2", - "@rollup/rollup-win32-x64-gnu": "4.62.2", - "@rollup/rollup-win32-x64-msvc": "4.62.2", - "fsevents": "~2.3.2" + "@rolldown/binding-android-arm-eabi": "1.2.6", + "@rolldown/binding-android-arm64": "1.2.6", + "@rolldown/binding-darwin-arm64": "1.2.6", + "@rolldown/binding-darwin-x64": "1.2.6", + "@rolldown/binding-freebsd-x64": "1.2.6", + "@rolldown/binding-linux-arm-gnueabihf": "1.2.6", + "@rolldown/binding-linux-arm64-gnu": "1.2.6", + "@rolldown/binding-linux-arm64-musl": "1.2.6", + "@rolldown/binding-linux-ppc64-gnu": "1.2.6", + "@rolldown/binding-linux-s390x-gnu": "1.2.6", + "@rolldown/binding-linux-x64-gnu": "1.2.6", + "@rolldown/binding-linux-x64-musl": "1.2.6", + "@rolldown/binding-openharmony-arm64": "1.2.6", + "@rolldown/binding-win32-arm64-msvc": "1.2.6", + "@rolldown/binding-win32-x64-msvc": "1.2.6" } }, "node_modules/router": { @@ -2367,9 +2602,9 @@ } }, "node_modules/std-env": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", - "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.2.0.tgz", + "integrity": "sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw==", "dev": true, "license": "MIT" }, @@ -2381,36 +2616,36 @@ "license": "MIT" }, "node_modules/tinyexec": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", - "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", - "dev": true, - "license": "MIT" - }, - "node_modules/tinypool": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz", - "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.3.0.tgz", + "integrity": "sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ==", "dev": true, "license": "MIT", "engines": { - "node": "^18.0.0 || >=20.0.0" + "node": ">=18" } }, - "node_modules/tinyrainbow": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-1.2.0.tgz", - "integrity": "sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==", + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", "dev": true, "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, "engines": { - "node": ">=14.0.0" + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" } }, - "node_modules/tinyspy": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz", - "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==", + "node_modules/tinyrainbow": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.1.tgz", + "integrity": "sha512-yau8yJdTt989Mm0Bd/236QnzEiPf2xLLTqUZRUJOo/3CB078LSwzei343DgtJVmfJKJE3TMINY1u42SQsP6mXw==", "dev": true, "license": "MIT", "engines": { @@ -2497,21 +2732,23 @@ } }, "node_modules/vite": { - "version": "5.4.21", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz", - "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.2.2.tgz", + "integrity": "sha512-cFKLV/PRgAUlIRm5WjMjJ86jrftzpqcgH+Us+DS8mI3CDNiH30Whrz8uHL3+MOLPAgqbMBAqWdAHAphOAM+z/Q==", "dev": true, "license": "MIT", "dependencies": { - "esbuild": "^0.21.3", - "postcss": "^8.4.43", - "rollup": "^4.20.0" + "lightningcss": "^1.33.0", + "picomatch": "^4.0.5", + "postcss": "^8.5.26", + "rolldown": "~1.2.4", + "tinyglobby": "^0.2.17" }, "bin": { "vite": "bin/vite.js" }, "engines": { - "node": "^18.0.0 || >=20.0.0" + "node": "^20.19.0 || >=22.12.0" }, "funding": { "url": "https://github.com/vitejs/vite?sponsor=1" @@ -2520,23 +2757,33 @@ "fsevents": "~2.3.3" }, "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" + "@types/node": "^20.19.0 || >=22.12.0", + "@vitejs/devtools": "^0.4.0 || ^0.5.0", + "esbuild": "^0.27.0 || ^0.28.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" }, "peerDependenciesMeta": { "@types/node": { "optional": true }, - "less": { + "@vitejs/devtools": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "jiti": { "optional": true }, - "lightningcss": { + "less": { "optional": true }, "sass": { @@ -2553,515 +2800,89 @@ }, "terser": { "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true } } }, - "node_modules/vite-node": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.9.tgz", - "integrity": "sha512-AM9aQ/IPrW/6ENLQg3AGY4K1N2TGZdR5e4gu/MmmR2xR3Ll1+dib+nook92g4TV3PXVyeyxdWwtaCAiUL0hMxA==", + "node_modules/vitest": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.11.tgz", + "integrity": "sha512-fhACrNXUidIbGSBr5FlbuBkO7VWC1ZyLl0DO4CU2DrQoAPxX84Ysxs+HeGQpii5lZWV1Q4gBZTTu49mF+A6Edw==", "dev": true, "license": "MIT", "dependencies": { - "cac": "^6.7.14", - "debug": "^4.3.7", - "es-module-lexer": "^1.5.4", - "pathe": "^1.1.2", - "vite": "^5.0.0" + "@vitest/expect": "4.1.11", + "@vitest/mocker": "4.1.11", + "@vitest/pretty-format": "4.1.11", + "@vitest/runner": "4.1.11", + "@vitest/snapshot": "4.1.11", + "@vitest/spy": "4.1.11", + "@vitest/utils": "4.1.11", + "es-module-lexer": "^2.0.0", + "expect-type": "^1.3.0", + "magic-string": "^0.30.21", + "obug": "^2.1.1", + "pathe": "^2.0.3", + "picomatch": "^4.0.3", + "std-env": "^4.0.0-rc.1", + "tinybench": "^2.9.0", + "tinyexec": "^1.0.2", + "tinyglobby": "^0.2.15", + "tinyrainbow": "^3.1.0", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", + "why-is-node-running": "^2.3.0" }, "bin": { - "vite-node": "vite-node.mjs" + "vitest": "vitest.mjs" }, "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/vite/node_modules/@esbuild/aix-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", - "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/android-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", - "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/android-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", - "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/android-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", - "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", - "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/darwin-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", - "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", - "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/freebsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", - "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", - "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", - "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", - "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-loong64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", - "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-mips64el": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", - "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", - "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-riscv64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", - "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-s390x": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", - "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", - "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/netbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", - "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/openbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", - "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/sunos-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", - "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/win32-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", - "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/win32-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", - "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/win32-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", - "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/esbuild": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", - "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.21.5", - "@esbuild/android-arm": "0.21.5", - "@esbuild/android-arm64": "0.21.5", - "@esbuild/android-x64": "0.21.5", - "@esbuild/darwin-arm64": "0.21.5", - "@esbuild/darwin-x64": "0.21.5", - "@esbuild/freebsd-arm64": "0.21.5", - "@esbuild/freebsd-x64": "0.21.5", - "@esbuild/linux-arm": "0.21.5", - "@esbuild/linux-arm64": "0.21.5", - "@esbuild/linux-ia32": "0.21.5", - "@esbuild/linux-loong64": "0.21.5", - "@esbuild/linux-mips64el": "0.21.5", - "@esbuild/linux-ppc64": "0.21.5", - "@esbuild/linux-riscv64": "0.21.5", - "@esbuild/linux-s390x": "0.21.5", - "@esbuild/linux-x64": "0.21.5", - "@esbuild/netbsd-x64": "0.21.5", - "@esbuild/openbsd-x64": "0.21.5", - "@esbuild/sunos-x64": "0.21.5", - "@esbuild/win32-arm64": "0.21.5", - "@esbuild/win32-ia32": "0.21.5", - "@esbuild/win32-x64": "0.21.5" - } - }, - "node_modules/vitest": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.9.tgz", - "integrity": "sha512-MSmPM9REYqDGBI8439mA4mWhV5sKmDlBKWIYbA3lRb2PTHACE0mgKwA8yQ2xq9vxDTuk4iPrECBAEW2aoFXY0Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/expect": "2.1.9", - "@vitest/mocker": "2.1.9", - "@vitest/pretty-format": "^2.1.9", - "@vitest/runner": "2.1.9", - "@vitest/snapshot": "2.1.9", - "@vitest/spy": "2.1.9", - "@vitest/utils": "2.1.9", - "chai": "^5.1.2", - "debug": "^4.3.7", - "expect-type": "^1.1.0", - "magic-string": "^0.30.12", - "pathe": "^1.1.2", - "std-env": "^3.8.0", - "tinybench": "^2.9.0", - "tinyexec": "^0.3.1", - "tinypool": "^1.0.1", - "tinyrainbow": "^1.2.0", - "vite": "^5.0.0", - "vite-node": "2.1.9", - "why-is-node-running": "^2.3.0" - }, - "bin": { - "vitest": "vitest.mjs" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" + "node": "^20.0.0 || ^22.0.0 || >=24.0.0" }, "funding": { "url": "https://opencollective.com/vitest" }, "peerDependencies": { "@edge-runtime/vm": "*", - "@types/node": "^18.0.0 || >=20.0.0", - "@vitest/browser": "2.1.9", - "@vitest/ui": "2.1.9", + "@opentelemetry/api": "^1.9.0", + "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", + "@vitest/browser-playwright": "4.1.11", + "@vitest/browser-preview": "4.1.11", + "@vitest/browser-webdriverio": "4.1.11", + "@vitest/coverage-istanbul": "4.1.11", + "@vitest/coverage-v8": "4.1.11", + "@vitest/ui": "4.1.11", "happy-dom": "*", - "jsdom": "*" + "jsdom": "*", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "peerDependenciesMeta": { "@edge-runtime/vm": { "optional": true }, + "@opentelemetry/api": { + "optional": true + }, "@types/node": { "optional": true }, - "@vitest/browser": { + "@vitest/browser-playwright": { + "optional": true + }, + "@vitest/browser-preview": { + "optional": true + }, + "@vitest/browser-webdriverio": { + "optional": true + }, + "@vitest/coverage-istanbul": { + "optional": true + }, + "@vitest/coverage-v8": { "optional": true }, "@vitest/ui": { @@ -3072,6 +2893,9 @@ }, "jsdom": { "optional": true + }, + "vite": { + "optional": false } } }, diff --git a/package.json b/package.json index 020c8b1f..f5f49075 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "commitlore", - "version": "1.2.0", + "version": "1.2.1", "description": "Git-native, lifecycle-aware decision memory for coding agents", "license": "MIT", "private": true, @@ -49,12 +49,12 @@ "@types/js-yaml": "^4.0.9", "@types/node": "^22.10.0", "esbuild": "^0.28.2", - "js-yaml": "^5.2.3", + "js-yaml": "^5.4.1", "typescript": "^5.7.0", - "vitest": "^2.1.0" + "vitest": "^4.1.11" }, "dependencies": { - "@modelcontextprotocol/sdk": "^1.29.0", + "@modelcontextprotocol/sdk": "^1.30.0", "ajv": "^8.20.0", "ajv-formats": "^3.0.1", "commander": "^15.0.0" diff --git a/scripts/check-exact-head-ci.mjs b/scripts/check-exact-head-ci.mjs index 1db3eb95..6f7e975c 100644 --- a/scripts/check-exact-head-ci.mjs +++ b/scripts/check-exact-head-ci.mjs @@ -40,7 +40,7 @@ const CI_WORKFLOW_FILE_PATH = fileURLToPath(new URL(`../${CI_WORKFLOW_PATH}`, im // shell command; without this lock replacing every job body with `true` would // still look like a real successful run. Update deliberately with the CI // workflow when its reviewed job contract changes. -export const EXPECTED_CI_WORKFLOW_SHA256 = '7e6f6070b2c3230b1fa23682647cf6a49b4b474fce86e22b011f5da3e05868fe'; +export const EXPECTED_CI_WORKFLOW_SHA256 = 'd29daccf3b0722dc96c3c654f41f2f2c27d7acb527aebdee2015476b9b54cc8c'; // Fixed rather than inferred from returned jobs: absence must fail rather // than define itself away. `lint` only runs for pull requests and is therefore diff --git a/scripts/check-release-version.mjs b/scripts/check-release-version.mjs index f51cc299..70102291 100644 --- a/scripts/check-release-version.mjs +++ b/scripts/check-release-version.mjs @@ -99,6 +99,12 @@ const plugin = readManifest('.claude-plugin/plugin.json', ['.version']); // A Codex user would have installed this release and been told it was the // previous one. const codexPlugin = readManifest('.codex-plugin/plugin.json', ['.version']); +// `server.json` is the MCP registry manifest, and it was the fourth one this +// gate did not read. The 1.2.1 review found it still advertising 1.2.0 — +// version, installer command and release URL — while every source below read +// 1.2.1 and the gate passed. Exactly the shape of the Codex note above, one +// file later, and the reason that note says nothing else would have caught it. +const serverManifest = readManifest('server.json', ['.version']); const packageLock = readManifest('package-lock.json', ['.version', '.packages[""].version']); const pkgVersion = requiredVersion(pkg.version, 'package.json .version'); @@ -107,6 +113,7 @@ const codexPluginVersion = requiredVersion( codexPlugin.version, '.codex-plugin/plugin.json .version', ); +const serverVersion = requiredVersion(serverManifest.version, 'server.json .version'); const packageLockVersion = requiredVersion(packageLock.version, 'package-lock.json .version'); const packageLockRootVersion = requiredVersion( packageLock.packages?.['']?.version, @@ -120,6 +127,7 @@ const versionSources = [ ['package.json .version', pkgVersion], ['.claude-plugin/plugin.json .version', pluginVersion], ['.codex-plugin/plugin.json .version', codexPluginVersion], + ['server.json .version', serverVersion], ['package-lock.json .version', packageLockVersion], ['package-lock.json .packages[""].version', packageLockRootVersion], ['dist/commitlore.mjs --version', cliVersion], @@ -137,10 +145,10 @@ if (mismatches.length > 0) { process.exit(1); } +// Built from `versionSources` rather than written out, so the line cannot claim +// to have compared a set the loop above did not. It said "version consistent" +// without naming `server.json` for as long as `server.json` went unchecked. console.log( - `version consistent: tag ${tagArg} == package.json .version ${pkgVersion} == ` + - `.claude-plugin/plugin.json .version ${pluginVersion} == ` + - `.codex-plugin/plugin.json .version ${codexPluginVersion} == package-lock.json .version ` + - `${packageLockVersion} == package-lock.json .packages[""].version ${packageLockRootVersion} == ` + - `dist/commitlore.mjs --version ${cliVersion}`, + `version consistent: tag ${tagArg} == ` + + versionSources.map(([source, version]) => `${source} ${version}`).join(' == '), ); diff --git a/server.json b/server.json index 4f3fa93d..a3bdc2cf 100644 --- a/server.json +++ b/server.json @@ -8,7 +8,7 @@ "source": "github" }, "websiteUrl": "https://github.com/MongLong0214/commitlore#readme", - "version": "1.2.0", + "version": "1.2.1", "_meta": { "io.modelcontextprotocol.registry/publisher-provided": { "registryFit": "Distribution is a tagged git checkout plus a Claude Code plugin marketplace (ADR-0011 registry-free git distribution, ADR-0026 no compiled executables and no uploaded release asset), so no official package type applies and this record relies on websiteUrl plus publisher metadata.", @@ -18,8 +18,8 @@ "/plugin marketplace add MongLong0214/commitlore", "/plugin install commitlore@commitlore" ], - "installer": "curl -fsSL https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.0/install.sh | sh -s v1.2.0", - "release": "https://github.com/MongLong0214/commitlore/releases/tag/v1.2.0" + "installer": "curl -fsSL https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.1/install.sh | sh -s v1.2.1", + "release": "https://github.com/MongLong0214/commitlore/releases/tag/v1.2.1" }, "runtime": { "transport": "stdio", diff --git a/src/core/sync.ts b/src/core/sync.ts index 8127932b..52a08aac 100644 --- a/src/core/sync.ts +++ b/src/core/sync.ts @@ -107,10 +107,48 @@ const revParse = (ref: string, opts: NotesOptions): string | null => { const isAncestor = (a: string, b: string, opts: NotesOptions): boolean => execGit(['merge-base', '--is-ancestor', a, b], gitOptions(opts)).code === 0; +/** + * `SyncResult.detail` promises one line, and git does not. A fetch against a + * deleted remote answers with two -- `remote: Repository not found.` and + * `fatal: repository '...' not found` -- and putting both in the column split + * the row in half, so the second line read as a bare `fatal:` standing above + * the table rather than as that remote's result (#865). Collapse here, at the + * one place a git diagnostic becomes a detail, so the table, the JSON and the + * hook all inherit the promise. + */ +const oneLine = (detail: string): string => detail.replace(/\s+/g, ' ').trim(); + +/** + * A remote that no longer exists is a normal thing to find in a clone that has + * outlived a fork, and the useful report is which remote, not git's two-line + * phrasing of it. + * + * Bounded to git's own two phrasings — `remote: Repository not found.` and + * `fatal: repository '' not found` — rather than "the words repository and + * not found somewhere in the message". The first draft was the loose version, + * and review found it: `repository metadata not found` and + * `repository credentials not found` would both have been relabelled as a + * missing remote. + */ +const REMOTE_NOT_FOUND = /\brepository\b(?:\s+'[^']*'|\s+"[^"]*")?\s+not found/i; + +/** + * A timeout outranks the classification. `describeSync` reads `detail` for + * `ETIMEDOUT` to say *why* the mirror failed, and `execGit` appends that to + * whatever partial stderr the child had already written — so a message can + * carry both. Replacing it with `remote not found` would erase the one part the + * hook actually parses, and the operator would be told a fork is missing when + * the remote simply did not answer in time. + */ +const TIMED_OUT = /\bETIMEDOUT\b/; + +export const classifyFailureDetail = (detail: string): string => + !TIMED_OUT.test(detail) && REMOTE_NOT_FOUND.test(detail) ? 'remote not found' : oneLine(detail); + const failure = (remote: string, detail: string): SyncResult => ({ remote, outcome: 'failed', - detail, + detail: classifyFailureDetail(detail), }); /** diff --git a/src/hooks/pre-push.ts b/src/hooks/pre-push.ts index 7f41a110..e6b73a7c 100644 --- a/src/hooks/pre-push.ts +++ b/src/hooks/pre-push.ts @@ -29,6 +29,7 @@ import { resolve } from 'node:path'; import type { Command } from 'commander'; import { execGit } from '../core/git.js'; +import { NOTES_REF } from '../core/notes.js'; import { syncNotes, type SyncResult } from '../core/sync.js'; import { CHAINED_SUFFIX, HOOK_MODE, captureHookStub } from './commit-msg.js'; @@ -139,13 +140,44 @@ const saidWhy = (detail: string): string => * Saying only "branch push continues" reported the half the operator could * already see and left the half they were asking about unstated. */ -export const describeSync = (results: readonly SyncResult[]): string[] => +/** + * Is there anything local the mirror would have sent? + * + * #632 asked exactly this and #656 answered it unconditionally with yes, so a + * push whose repository had no records at all was told its records were "still + * only local" (#865). The remote's contents cannot be known once the remote has + * stopped answering; whether this clone has a notes ref is a local question + * that cannot time out. + * + * Deliberately ref-scoped and not commit-scoped. The mirror publishes + * `refs/notes/commitlore` whole, so a record written against a commit the + * remote already has is still unsent -- and a check that only looked at the + * commits in this push would call that "nothing waiting" and be wrong in the + * more dangerous direction. `test/pre-push-hook.test.ts` fixes that shape. + * + * `null` when git will not answer at all, so the caller keeps the cautious + * sentence rather than inventing a reassuring one from a failure to measure. + */ +const localRecordsExist = (): boolean | null => { + const result = execGit(['rev-parse', '--verify', '--quiet', NOTES_REF]); + if (result.code === 0) return result.stdout.trim() !== ''; + // `--verify --quiet` exits 1 for "no such ref", which is an answer. Anything + // else -- not a repository, git missing -- is not. + return result.code === 1 ? false : null; +}; + +export const describeSync = ( + results: readonly SyncResult[], + hasLocalRecords: boolean | null = null, +): string[] => results .filter((result) => result.outcome === 'failed' || result.outcome === 'diverged') .map((result) => result.outcome === 'diverged' ? `commitlore: notes mirror (${result.remote}) diverged: ${oneLine(result.detail)}. The branch was pushed. Your records and the remote's both exist and neither one fast-forwards, so a later push will not settle it — run "commitlore sync" to merge them.` - : `commitlore: notes mirror (${result.remote}) failed: ${saidWhy(result.detail)}. The branch was pushed; the records for these commits are still only local. The next push retries this automatically, or run "commitlore sync" to send them now.`, + : hasLocalRecords === false + ? `commitlore: notes mirror (${result.remote}) failed: ${saidWhy(result.detail)}. The branch was pushed. Nothing is waiting locally, so nothing was lost.` + : `commitlore: notes mirror (${result.remote}) failed: ${saidWhy(result.detail)}. The branch was pushed; the records for these commits are still only local. The next push retries this automatically, or run "commitlore sync" to send them now.`, ); /** @@ -166,6 +198,9 @@ export const register = (program: Command): void => { .argument('[url]', 'its URL, as git passes it') .description('internal hook command: publish the notes mirror alongside a push') .action((remote?: string) => { + // Measured before the transport runs, because it must not depend on the + // remote answering: that is the whole distinction #865 turns on. + const hasLocalRecords = localRecordsExist(); try { const results = syncNotes({ ...(remote === undefined || remote === '' ? {} : { remotes: [remote] }), @@ -174,13 +209,16 @@ export const register = (program: Command): void => { timeout: PRE_PUSH_NOTES_SYNC_TIMEOUT_MS, }, }); - for (const line of describeSync(results)) process.stderr.write(`${line}\n`); + for (const line of describeSync(results, hasLocalRecords)) process.stderr.write(`${line}\n`); } catch (error: unknown) { // A push must never fail because the mirror could not be published — // and the line must still say where the records ended up, for the same // reason `describeSync` does (#632). + const why = saidWhy(error instanceof Error ? error.message : String(error)); process.stderr.write( - `commitlore: notes mirror failed: ${saidWhy(error instanceof Error ? error.message : String(error))}. The branch was pushed; the records for these commits are still only local. The next push retries this automatically, or run "commitlore sync" to send them now.\n`, + hasLocalRecords === false + ? `commitlore: notes mirror failed: ${why}. The branch was pushed. Nothing is waiting locally, so nothing was lost.\n` + : `commitlore: notes mirror failed: ${why}. The branch was pushed; the records for these commits are still only local. The next push retries this automatically, or run "commitlore sync" to send them now.\n`, ); } }); diff --git a/test/check-release-version.test.ts b/test/check-release-version.test.ts index 9266d2b7..0f5598cf 100644 --- a/test/check-release-version.test.ts +++ b/test/check-release-version.test.ts @@ -43,11 +43,15 @@ describe('this repository agrees with itself', () => { const codexPlugin = JSON.parse( readFileSync(join(REPO_ROOT, '.codex-plugin', 'plugin.json'), 'utf8'), ) as { version?: unknown }; + const serverManifest = JSON.parse(readFileSync(join(REPO_ROOT, 'server.json'), 'utf8')) as { + version?: unknown; + }; expect(lock.version).toBe(pkg.version); expect(lock.packages?.['']?.version).toBe(pkg.version); expect(claudePlugin.version).toBe(pkg.version); expect(codexPlugin.version).toBe(pkg.version); + expect(serverManifest.version).toBe(pkg.version); }); it('the gate itself accepts this repository at its own version', () => { @@ -75,8 +79,10 @@ interface FixtureVersions { packageLock?: string; packageLockRoot?: string; cli?: string; + server?: string; pluginManifest?: boolean; codexPluginManifest?: boolean; + serverManifest?: boolean; } const fixture = (versions: FixtureVersions = {}): string => { @@ -118,6 +124,12 @@ const fixture = (versions: FixtureVersions = {}): string => { `${JSON.stringify({ name: 'commitlore', version: versions.codexPlugin ?? VERSION }, null, 2)}\n`, ); } + if (versions.serverManifest !== false) { + writeFileSync( + join(root, 'server.json'), + `${JSON.stringify({ name: 'io.github.MongLong0214/commitlore', version: versions.server ?? VERSION }, null, 2)}\n`, + ); + } writeFileSync( join(root, 'dist', 'commitlore.mjs'), `#!/usr/bin/env node\nif (process.argv[2] === '--version') console.log(${JSON.stringify(versions.cli ?? VERSION)});\n`, @@ -146,6 +158,11 @@ describe('#492 check-release-version', () => { // one would have published green and told a Codex user they had installed // the previous release. ['the codex plugin manifest', { codexPlugin: '0.7.0' }, '.codex-plugin/plugin.json .version'], + // Added the same way and for the same reason, one release later. The 1.2.1 + // review found `server.json` still advertising 1.2.0 while every source the + // gate read said 1.2.1, so the gate passed. An MCP registry entry is how a + // stranger finds this, and it was pointing at the previous tag. + ['the server manifest', { server: '0.7.0' }, 'server.json .version'], ['the package-lock root version', { packageLock: '0.7.0' }, 'package-lock.json .version'], [ 'the package-lock root package version', diff --git a/test/guard-insufficiency.test.ts b/test/guard-insufficiency.test.ts index fe4f9ddc..2b3cb129 100644 --- a/test/guard-insufficiency.test.ts +++ b/test/guard-insufficiency.test.ts @@ -86,7 +86,7 @@ describe('ADR-0019: guard signal insufficiency', () => { `(actual recall: ${(point.recall * 100).toFixed(1)}%)`, ).toBeLessThanOrEqual(CURRENT_PRECISION_UPPER); } - }); + }, 300_000); it('49 false negatives from semantic revivals produce zero corroborated signal', () => { // Shape 1 from the analysis: tasks whose FNs all score undefined (zero @@ -136,5 +136,5 @@ describe('ADR-0019: guard signal insufficiency', () => { // The analysis found exactly 49 positives from these tasks produce zero signal. // Assert at least 49 to pin the finding; more would strengthen the claim. expect(zeroSignalPositives).toBeGreaterThanOrEqual(49); - }); + }, 300_000); }); diff --git a/test/pre-push-hook.test.ts b/test/pre-push-hook.test.ts index 3164e7cb..8df250c0 100644 --- a/test/pre-push-hook.test.ts +++ b/test/pre-push-hook.test.ts @@ -25,7 +25,7 @@ import { afterAll, describe, expect, it } from 'vitest'; import { execGit } from '../src/core/git.js'; import { NOTES_REF, writeRecord } from '../src/core/notes.js'; -import { installPrePushHook, PRE_PUSH_NOTES_SYNC_TIMEOUT_MS } from '../src/hooks/pre-push.js'; +import { describeSync, installPrePushHook, PRE_PUSH_NOTES_SYNC_TIMEOUT_MS } from '../src/hooks/pre-push.js'; import { createTestRepo } from './git-fixtures.js'; const REPO_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..'); @@ -249,3 +249,44 @@ describe('the pre-push hook publishes the mirror without re-entering itself', () } }, 60_000); }); + +/** + * #865. The failed-mirror line answers "where are my records now", and it used + * to answer it unconditionally with "still only local" -- without checking. A + * field report on v1.2.0 got that line for a repository with no notes ref at + * all, ran `commitlore sync`, and found nothing to send. + * + * What the remote holds cannot be known once the remote has stopped answering. + * Whether this clone holds anything is local and cannot time out, and the + * mirror publishes the ref whole -- so the ref is the right granularity. A + * commit-scoped check would call a record written against an already-pushed + * commit "nothing waiting", which is the wrong direction to be wrong in. + */ +describe('the failed-mirror line only claims what was measured', () => { + const failed = [{ remote: 'origin', outcome: 'failed' as const, detail: 'ETIMEDOUT' }]; + + it('says nothing was lost when this clone has no records at all', () => { + const [line] = describeSync(failed, false); + expect(line).toContain('Nothing is waiting locally'); + expect(line).toContain('nothing was lost'); + expect(line).not.toContain('still only local'); + }); + + it('keeps the cautious sentence when records exist locally', () => { + const [line] = describeSync(failed, true); + expect(line).toContain('still only local'); + expect(line).toContain('commitlore sync'); + }); + + it('keeps the cautious sentence when the local answer could not be measured', () => { + // "Unknown" must not be reported as "none": the reassuring sentence is only + // safe when the absence was actually observed. + const [line] = describeSync(failed, null); + expect(line).toContain('still only local'); + }); + + it('leaves a divergence alone — its answer does not depend on the local count', () => { + const diverged = [{ remote: 'origin', outcome: 'diverged' as const, detail: 'both moved' }]; + expect(describeSync(diverged, false)[0]).toContain('neither one fast-forwards'); + }); +}); diff --git a/test/sync.test.ts b/test/sync.test.ts index b0f6b5bf..8b7cbc16 100644 --- a/test/sync.test.ts +++ b/test/sync.test.ts @@ -17,7 +17,7 @@ import { afterAll, describe, expect, it } from 'vitest'; import { execGit } from '../src/core/git.js'; import { NOTES_REF, NOTES_REFSPEC, forcesNotes, readRecord, writeRecord } from '../src/core/notes.js'; -import { syncNotes } from '../src/core/sync.js'; +import { classifyFailureDetail, syncNotes } from '../src/core/sync.js'; import { createTestRepo } from './git-fixtures.js'; const scratch: string[] = []; @@ -233,6 +233,41 @@ describe('#416 the notes mirror completes a round trip between two clones', () = expect(forcesNotes('+refs/heads/*:refs/remotes/origin/*')).toBe(false); }); + it('states an unreachable remote in one line, so the table keeps its shape', () => { + // #865: git answers an unreachable remote with more than one line, and both + // used to go into the detail column. The row then broke in half and the + // trailing line read as a bare `fatal:` standing above the next remote's row + // rather than as this remote's result. `SyncResult.detail` promises one line. + const { alice } = team('one-line-detail'); + const sha = git(alice, ['rev-parse', 'HEAD']).trim(); + writeRecord(sha, record('local only'), { cwd: alice }); + git(alice, ['remote', 'set-url', 'origin', join(temp('vanished'), 'nowhere.git')]); + + const results = syncNotes({ cwd: alice }); + + expect(results).toHaveLength(1); + expect(results[0]?.outcome).toBe('failed'); + expect(results[0]?.detail).not.toContain('\n'); + expect(results[0]?.detail.trim()).toBe(results[0]?.detail); + }); + + it('does not relabel a timeout, or a message that merely contains those words', () => { + // Review of #865 found the first draft's classifier too loose: it matched + // "the words repository and not found somewhere in the message", so + // `repository metadata not found` became `remote not found`. Worse, the + // hook reads `detail` for ETIMEDOUT to say *why* the mirror failed, and + // `execGit` appends that to partial stderr — so relabelling could erase the + // one part anything parses and report a missing fork for a slow remote. + expect(classifyFailureDetail("fatal: repository 'https://x/y.git' not found")).toBe( + 'remote not found', + ); + expect(classifyFailureDetail('remote: Repository not found.')).toBe('remote not found'); + expect(classifyFailureDetail('fatal: repository metadata not found')).toContain('metadata'); + expect(classifyFailureDetail('remote: Repository not found.\nETIMEDOUT')).toContain( + 'ETIMEDOUT', + ); + }); + it('leaves the working notes ref intact when it refuses', () => { // A remote that cannot be reached at all: nothing is written either way. const { alice } = team('unreachable'); diff --git a/vitest.config.ts b/vitest.config.ts index dd122d6a..895630b0 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -13,6 +13,30 @@ export default defineConfig({ // caught the original failure, changing it is not part of that migration, // and the cost is only startup time. pool: 'forks', + // vitest 4 runs each file through vite 8's module runner, and the per-file + // startup that buys costs more wall clock than vitest 2's did. This suite is + // unusually exposed to that: most of its tests spawn a real `node`, `git` or + // installer process and then wait on it, so the default 5s covered the work + // plus the old overhead and does not cover the work plus the new one. + // + // Measured on the vitest 4 upgrade, same tree, same machine: + // + // default parallelism 35 failed (12 of them "timed out in 5000ms") + // --maxWorkers=4 7 failed (all 7 "timed out in 5000ms") + // testTimeout 20s see below + // + // Every failure was the timeout; none was an assertion. Lowering parallelism + // only moved the line, which is what a contention-shaped limit does. + // + // This is not a performance budget being relaxed. A timeout here exists to + // stop a hung child process from hanging the run, and 20s still does that — + // the tests that genuinely take longer already carry their own explicit + // timeouts and are unaffected. + testTimeout: 20_000, + // The same change reaches `beforeAll`, which builds fixtures by spawning + // git. `token-ledger`'s hook timed out at the 10s default on vitest 4 and + // not on vitest 2. + hookTimeout: 30_000, // The developer's git config is not an input. Without this, a test that // forgets to set an identity in its temporary repository passes on any // machine that has a global one and fails on a clean CI runner with