From 8b050312f1f9e0a04d5c75747712e98a8a21d1eb Mon Sep 17 00:00:00 2001 From: BM Cho Date: Mon, 20 Jul 2026 13:23:00 +0800 Subject: [PATCH 1/2] release: prepare Evidrift v0.3.3 --- .github/workflows/ci.yml | 5 +-- CHANGELOG.md | 18 +++++++++++ README.md | 57 +++++++++++++++++++++++++++++++--- README.zh-TW.md | 57 +++++++++++++++++++++++++++++++--- docs/UAT.md | 10 ++++++ docs/ci.md | 66 ++++++++++++++++++++++++++++++++++++++++ docs/index.html | 8 ++--- docs/llms.txt | 1 + docs/zh-TW/faq.html | 4 +-- docs/zh-TW/index.html | 8 ++--- package-lock.json | 4 +-- package.json | 2 +- server.json | 4 +-- src/cli.ts | 2 +- src/types.ts | 2 +- tests/onboarding.test.ts | 2 +- tests/package.test.ts | 16 ++++++++++ tests/seo.test.ts | 24 +++++++++++++++ 18 files changed, 260 insertions(+), 30 deletions(-) create mode 100644 docs/ci.md diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 83fdce8..37a4da7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,12 +10,13 @@ permissions: jobs: verify: - name: Node.js ${{ matrix.node }} - runs-on: ubuntu-latest + name: ${{ matrix.os }} / Node.js ${{ matrix.node }} + runs-on: ${{ matrix.os }} timeout-minutes: 10 strategy: fail-fast: false matrix: + os: [ubuntu-latest, windows-latest] node: [22, 24] steps: - name: Check out repository diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d2ee4f..200b1ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,24 @@ All notable changes are documented here. The project follows [Semantic Versionin No changes yet. +## [0.3.3] - 2026-07-20 + +### Added + +- An inline architecture flow that connects coding-agent assumptions, content-addressed Receipts, Git review, and deterministic CI outcomes. +- A copy-pasteable GitHub Actions adoption guide with read-only permissions, locked npm installation, and commit-pinned Actions. +- Regression tests that keep the public support scope, architecture, CI instructions, and cross-platform CI matrix aligned. + +### Changed + +- Project CI now runs the complete release gate on Linux and Windows with Node.js 22 and 24. +- English and Traditional Chinese first-visit documentation now state the supported and deliberately unsupported surfaces explicitly. +- The demo promise now describes a reproducible one-command path instead of making a network-dependent timing claim. + +### Not included + +- No Receipt schema, verification policy, network access, cloud service, or runtime-correctness claim changed in this release. + ## [0.3.2] - 2026-07-17 ### Added diff --git a/README.md b/README.md index fa73895..26a0096 100644 --- a/README.md +++ b/README.md @@ -16,11 +16,11 @@ It deterministically catches selected TypeScript overload and parameter drift, r ![Evidrift — AI dependency lockfile](https://raw.githubusercontent.com/bm1016bm-svg/evidrift/main/docs/assets/evidrift-hero.png) -[![Real Evidrift CLI demo: a dependency contract passes, its TypeScript signature changes, and Evidrift catches the drift before merge](https://raw.githubusercontent.com/bm1016bm-svg/evidrift/main/docs/assets/evidrift-demo.gif)](#quick-start--try-it-in-10-seconds) +[![Real Evidrift CLI demo: a dependency contract passes, its TypeScript signature changes, and Evidrift catches the drift before merge](https://raw.githubusercontent.com/bm1016bm-svg/evidrift/main/docs/assets/evidrift-demo.gif)](#quick-start--see-drift-in-one-command) The animation is rendered from a [captured CLI transcript](https://github.com/bm1016bm-svg/evidrift/blob/main/docs/assets/evidrift-demo-transcript.txt). The PASS, changed signatures, affected file, and deterministic FAIL come from an actual local `evidrift demo` run; only the scene headings are editorial. -## Quick Start — Try It in 10 Seconds +## Quick Start — See Drift in One Command Requires Node.js 22 or newer. Nothing to install globally: @@ -32,6 +32,15 @@ The command creates a disposable local fixture, records the optional `options` p **If that is a failure you want caught before merge, [star Evidrift on GitHub](https://github.com/bm1016bm-svg/evidrift).** +## Supported Today + +| Surface | Deterministic evidence | Status | +| -------------------------------- | ----------------------------------------------------------------------- | ------------------ | +| Installed TypeScript dependency | Selected call signature, parameter, package version, and declaration | Supported | +| Repository OpenAPI / JSON Schema | Canonical value selected through an RFC 6901 JSON Pointer | Supported for JSON | +| CLI and local STDIO MCP | The same record and revalidation core | Supported | +| YAML, URLs, remote `$ref` | None; Evidrift refuses these inputs instead of making an unsafe promise | Not supported | + ## Installation — Add It to a Repository Initialize the current repository without a global install, account, API key, or cloud backend: @@ -84,6 +93,23 @@ JSON Pointer follows RFC 6901, including `~1` for `/` and `~0` for `~`. Evidrift Coding agents call the same core through `evidrift_record` and `evidrift_record_json_pointer`. Minimal [Codex, Claude Code, and Cursor setup](docs/mcp.md) is included. +## How It Works + +```mermaid +flowchart LR + Author["Coding agent or developer"] --> Record["Record one assumption"] + Record --> Adapter["TypeScript or JSON adapter"] + Adapter --> Receipt["Content-addressed Receipt"] + Receipt --> Review["Git review"] + Review --> Check["evidrift check in CI"] + Check --> Result{"Contract still matches?"} + Result -->|Yes| Pass["PASS"] + Result -->|Source unavailable| Warn["WARNING"] + Result -->|No or tampered| Fail["FAIL"] +``` + +The CLI and MCP server are thin entry points over the same core. The complete component map, check policy, resource bounds, and trust boundary are documented in [Architecture](docs/architecture.md). + ## The Files Evidrift writes one lock and one immutable JSON file per Receipt: @@ -106,6 +132,27 @@ There is no `.evidrift/receipts.json`. `evidence.lock` contains only content-add Each Receipt stores the claim and affected code plus one deterministic contract: an installed TypeScript symbol signature, or a repository JSON path, pointer, canonical value, and hashes. See the [Receipt schema](docs/receipt-schema.md). +## Add It to CI + +Pin Evidrift as a development dependency and expose one stable package script: + +```json +{ + "scripts": { + "evidrift:check": "evidrift check" + } +} +``` + +After `npm ci`, make that script a required CI step: + +```yaml +- name: Revalidate Evidrift receipts + run: npm run evidrift:check +``` + +The complete [GitHub Actions setup](docs/ci.md) uses read-only permissions, locked npm dependencies, and commit-pinned Actions. + ## CI Behavior `evidrift check` does not trust saved `matched` or `verified` flags. It validates the Receipt, reloads the source, and recomputes the selected signature or JSON value. @@ -127,7 +174,7 @@ Receipt ID: sha256:... Action: Do not trust or hand-edit this Receipt. Restore it from version control, or intentionally create a new Receipt with `evidrift record`. ``` -The included GitHub Actions workflow runs the full gate on Node.js 22 and 24. Third-party Actions are pinned to full commit SHAs. +The project workflow runs the full gate on Linux and Windows with Node.js 22 and 24. Third-party Actions are pinned to full commit SHAs. In a human TTY, `check`, `diff`, `explain`, and `demo` use a spinner plus green `✅`, yellow `⚠`, and red `❌` status output. Redirected output, CI, `TERM=dumb`, and `NO_COLOR` stay ANSI-free and keep the stable plain-text format used by agents and tests. @@ -145,7 +192,7 @@ Use all of them if they help. Evidrift covers one gap: the reason code was writt ### What is API drift? -API drift is a change to a dependency or contract after code was written against it. Evidrift v0.3.2 checks two deterministic forms: the TypeScript call signature selected at an affected code location, and a canonical value selected from repository-local OpenAPI JSON or JSON Schema. +API drift is a change to a dependency or contract after code was written against it. Evidrift v0.3.3 checks two deterministic forms: the TypeScript call signature selected at an affected code location, and a canonical value selected from repository-local OpenAPI JSON or JSON Schema. ### Is Evidrift a contract-testing tool? @@ -157,7 +204,7 @@ Yes. They can call the local STDIO MCP server to create Receipts through the sha ### Does Evidrift fetch OpenAPI URLs or execute package code? -No. The v0.3.2 adapters inspect installed TypeScript declarations and repository-local `.json` files. They do not fetch URLs, resolve remote `$ref`, import dependency JavaScript, or execute arbitrary commands. +No. The v0.3.3 adapters inspect installed TypeScript declarations and repository-local `.json` files. They do not fetch URLs, resolve remote `$ref`, import dependency JavaScript, or execute arbitrary commands. ### Does Evidrift prove that AI-generated code is correct? diff --git a/README.zh-TW.md b/README.zh-TW.md index d31b267..df803c3 100644 --- a/README.zh-TW.md +++ b/README.zh-TW.md @@ -16,11 +16,11 @@ Evidrift 能確定性偵測指定的 TypeScript overload/parameter drift、透 ![Evidrift — AI dependency lockfile](https://raw.githubusercontent.com/bm1016bm-svg/evidrift/main/docs/assets/evidrift-hero.png) -[![實際 Evidrift CLI demo:dependency contract 先通過,TypeScript signature 改變後在 merge 前被攔下](https://raw.githubusercontent.com/bm1016bm-svg/evidrift/main/docs/assets/evidrift-demo.gif)](#快速開始--10-秒看到-drift) +[![實際 Evidrift CLI demo:dependency contract 先通過,TypeScript signature 改變後在 merge 前被攔下](https://raw.githubusercontent.com/bm1016bm-svg/evidrift/main/docs/assets/evidrift-demo.gif)](#快速開始--用一個指令看到-drift) 這段動畫由[實際擷取的 CLI transcript](https://github.com/bm1016bm-svg/evidrift/blob/main/docs/assets/evidrift-demo-transcript.txt)產生。`PASS`、改變前後的 signature、affected file 與 deterministic `FAIL` 都來自本機執行的 `evidrift demo`;只有場景標題是後製文字。 -## 快速開始 — 10 秒看到 drift +## 快速開始 — 用一個指令看到 drift 需要 Node.js 22 或更新版本。不必全域安裝: @@ -34,6 +34,15 @@ npx --yes evidrift@latest demo 完整推演請看:[TypeScript 編譯通過,但 dependency signature 已漂移](https://bm1016bm-svg.github.io/evidrift/zh-TW/cases/typescript-signature-drift.html)。 +## 目前支援範圍 + +| Surface | Deterministic evidence | 狀態 | +| -------------------------------- | ------------------------------------------------------------------ | --------- | +| 已安裝的 TypeScript dependency | Selected call signature、parameter、package version 與 declaration | 支援 | +| Repository OpenAPI / JSON Schema | 透過 RFC 6901 JSON Pointer 選取的 canonical value | 支援 JSON | +| CLI 與 local STDIO MCP | 共用相同的 record 與 revalidation core | 支援 | +| YAML、URL、remote `$ref` | 無;Evidrift 會拒絕輸入,不會做出不安全的保證 | 不支援 | + ## 安裝 — 加入現有 Repository 不需要全域安裝、Evidrift 帳號、API key 或雲端後端: @@ -86,6 +95,23 @@ JSON Pointer 遵循 RFC 6901,其中 `~1` 代表 `/`、`~0` 代表 `~`。Evidri Coding Agent 透過 `evidrift_record` 與 `evidrift_record_json_pointer` 呼叫相同核心。Repository 包含 [Codex、Claude Code 與 Cursor 的最小 MCP 設定](docs/mcp.md)。 +## 運作方式 + +```mermaid +flowchart LR + Author["Coding Agent 或開發者"] --> Record["記錄一項 assumption"] + Record --> Adapter["TypeScript 或 JSON adapter"] + Adapter --> Receipt["Content-addressed Receipt"] + Receipt --> Review["Git review"] + Review --> Check["CI 執行 evidrift check"] + Check --> Result{"Contract 仍相同?"} + Result -->|是| Pass["PASS"] + Result -->|Source 無法使用| Warn["WARNING"] + Result -->|否或遭竄改| Fail["FAIL"] +``` + +CLI 與 MCP Server 都是相同 core 的入口。完整 component map、check policy、resource bound 與 trust boundary 請參考英文版 [Architecture](docs/architecture.md)。 + ## 產生的檔案 Evidrift 會寫入一份 lock,以及每張 Receipt 對應的一個 immutable JSON file: @@ -108,6 +134,27 @@ Evidrift 會寫入一份 lock,以及每張 Receipt 對應的一個 immutable J 每張 Receipt 會保存 claim、affected code,以及一項 deterministic contract:已安裝 TypeScript symbol signature,或 repository JSON path、pointer、canonical value 與 hashes。請參考英文版 [Receipt schema](docs/receipt-schema.md)。 +## 加入 CI + +把 Evidrift 固定為 development dependency,並提供穩定的 package script: + +```json +{ + "scripts": { + "evidrift:check": "evidrift check" + } +} +``` + +在 `npm ci` 後把它設為必要 CI step: + +```yaml +- name: Revalidate Evidrift receipts + run: npm run evidrift:check +``` + +完整 [GitHub Actions 設定](docs/ci.md)使用 read-only permission、鎖定的 npm dependency 與固定到 commit 的 Actions。 + ## CI 行為 `evidrift check` 不信任儲存的 `matched` 或 `verified` flag。它會驗證 Receipt、重新載入來源,再計算 selected signature 或 JSON value。 @@ -129,7 +176,7 @@ Receipt ID: sha256:... Action: Do not trust or hand-edit this Receipt. Restore it from version control, or intentionally create a new Receipt with `evidrift record`. ``` -內附的 GitHub Actions workflow 會在 Node.js 22 與 24 執行完整 gate。第三方 Actions 全部固定到完整 commit SHA。 +專案的 GitHub Actions workflow 會在 Linux 與 Windows 使用 Node.js 22、24 執行完整 gate。第三方 Actions 全部固定到完整 commit SHA。 在人類操作的 TTY 中,`check`、`diff`、`explain` 與 `demo` 會顯示 spinner 和綠色 `✅`、黃色 `⚠`、紅色 `❌` 狀態。Redirected output、CI、`TERM=dumb` 與 `NO_COLOR` 會維持無 ANSI 的穩定純文字格式,方便 Coding Agent 與測試解析。 @@ -147,7 +194,7 @@ Action: Do not trust or hand-edit this Receipt. Restore it from version control, ### 什麼是 API drift? -API drift 是 dependency 或 contract 在消費端程式寫完後發生改變。Evidrift v0.3.2 檢查兩種 deterministic evidence:affected code location 實際選到的 TypeScript call signature,以及 repository-local OpenAPI JSON 或 JSON Schema 中選定的 canonical value。 +API drift 是 dependency 或 contract 在消費端程式寫完後發生改變。Evidrift v0.3.3 檢查兩種 deterministic evidence:affected code location 實際選到的 TypeScript call signature,以及 repository-local OpenAPI JSON 或 JSON Schema 中選定的 canonical value。 ### Evidrift 是 contract-testing tool 嗎? @@ -159,7 +206,7 @@ API drift 是 dependency 或 contract 在消費端程式寫完後發生改變。 ### Evidrift 會抓 OpenAPI URL 或執行 package code 嗎? -不會。v0.3.2 adapters 只檢查已安裝的 TypeScript declaration 與 repository-local `.json` file;不會抓 URL、解析 remote `$ref`、import dependency JavaScript 或執行 arbitrary command。 +不會。v0.3.3 adapters 只檢查已安裝的 TypeScript declaration 與 repository-local `.json` file;不會抓 URL、解析 remote `$ref`、import dependency JavaScript 或執行 arbitrary command。 ### Evidrift 能證明 AI 產生的程式碼正確嗎? diff --git a/docs/UAT.md b/docs/UAT.md index 54a7906..accc27c 100644 --- a/docs/UAT.md +++ b/docs/UAT.md @@ -14,6 +14,16 @@ npm run uat `npm run verify` runs formatting, lint, typecheck, all automated tests, the end-to-end smoke test, and a check of this repository's committed Receipt. `npm run uat` isolates the user-facing acceptance cases. +Local v0.3.3 flagship-release checkpoint on 2026-07-20: + +- Platform: Windows, Node.js `v24.13.0`, npm `11.6.2`. +- Automated result: `npm run verify` passed 62/62 tests with 0 failures and 0 skips, then passed the end-to-end smoke test and repository Receipt check. Formatting, lint, typecheck, and release metadata alignment at `v0.3.3` also passed. +- Cross-platform gate: the CI matrix covers `ubuntu-latest` and `windows-latest` with Node.js 22 and 24. The local Windows run passed; GitHub Actions remains the authoritative Linux and clean-checkout result. +- Packed-install result: a fresh isolated consumer installed `evidrift-0.3.3.tgz`; `--version` returned `0.3.3`, bare invocation exposed the one-command demo, `init` created `.evidrift/`, and `demo` reproduced deterministic PASS-to-FAIL drift. +- Package-content result: the tarball contains 64 entries, including both READMEs and the CLI/MCP entrypoints, while excluding `src`, `tests`, and `examples`. +- Pack result: 58,351 packed bytes, 256,275 unpacked bytes, SHA-256 `42b60686bdcb551208653f2b9b8d52ea875275ccd8838b5a5256a6022946dc61`. The counts and sizes come from `npm pack --json`; the hash comes from PowerShell `Get-FileHash` against that exact tarball. +- Dependency advisory result: the isolated consumer's official-registry install audited 113 packages and reported 0 known vulnerabilities. This is registry output, not proof that the code has no vulnerability. + Local v0.3.2 bilingual-release checkpoint on 2026-07-17: - Platform: Windows, Node.js `v24.13.0`, npm `11.6.2`. diff --git a/docs/ci.md b/docs/ci.md new file mode 100644 index 0000000..f8614f2 --- /dev/null +++ b/docs/ci.md @@ -0,0 +1,66 @@ +# GitHub Actions + +Evidrift should run after the repository's locked dependencies are installed. Store `.evidrift/evidence.lock` and `.evidrift/receipts/` in Git so reviewers can see when an assumption is added or replaced. + +## Package script + +Install Evidrift as a development dependency and expose a stable command for local development and CI: + +```bash +npm install --save-dev evidrift +npx evidrift init +``` + +```json +{ + "scripts": { + "evidrift:check": "evidrift check" + } +} +``` + +Commit the resulting package lock, package manifest, and `.evidrift/` files. + +## Complete workflow + +```yaml +name: Evidrift + +on: + pull_request: + push: + branches: [main] + +permissions: + contents: read + +jobs: + check: + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - name: Check out repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Set up Node.js + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + with: + node-version: 22 + package-manager-cache: false + + - name: Install locked dependencies + run: npm ci --ignore-scripts + + - name: Revalidate Evidrift receipts + run: npm run evidrift:check +``` + +The workflow grants read-only repository access. It installs from the committed npm lockfile, does not execute dependency lifecycle scripts, and pins third-party Actions to complete commit SHAs. + +## Result policy + +- Exit `0`: every deterministic contract matches, or a source is visibly unavailable or changed without a selected-contract mismatch. +- Exit `1`: a selected TypeScript signature or JSON value changed or disappeared. +- Exit `2`: the lock or a Receipt is malformed, missing, forged, or hash-invalid. + +Warnings are intentionally non-blocking. Review them in logs; Evidrift only blocks when it has a deterministic mismatch or integrity failure. diff --git a/docs/index.html b/docs/index.html index 9c0c535..2c70d50 100644 --- a/docs/index.html +++ b/docs/index.html @@ -50,7 +50,7 @@ "alternateName": "Evidrift evidence lockfile", "applicationCategory": "DeveloperApplication", "operatingSystem": "Windows, macOS, Linux", - "softwareVersion": "0.3.2", + "softwareVersion": "0.3.3", "description": "A local-first CLI and MCP server that detects TypeScript API and OpenAPI contract drift in AI-generated code by revalidating deterministic evidence in CI.", "url": "https://bm1016bm-svg.github.io/evidrift/", "codeRepository": "https://github.com/bm1016bm-svg/evidrift", @@ -386,7 +386,7 @@

Code compiles.
APIs drift.

rechecks them in CI before the next merge.

- Run the 10-second demo + Run the one-command demo ★ Star on GitHub
Receipt tampering
No signup. No API key. No cloud.
-

Break it in ten seconds.

+

See deterministic drift in one command.

npx --yes evidrift@latest demo
FAQ