Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,25 @@ 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, cross-platform CI matrix, and canonical repository-root handling aligned.

### Changed

- Project CI now runs the complete release gate on Linux and Windows with Node.js 22 and 24.
- Storage containment checks now compare canonical repository and evidence paths, avoiding false escape reports when a Windows runner exposes the repository through a junction or alias.
- 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
Expand Down
57 changes: 52 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand All @@ -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:
Expand Down Expand Up @@ -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:
Expand All @@ -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.
Expand All @@ -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.

Expand All @@ -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?

Expand All @@ -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?

Expand Down
57 changes: 52 additions & 5 deletions README.zh-TW.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 或更新版本。不必全域安裝:

Expand All @@ -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 或雲端後端:
Expand Down Expand Up @@ -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:
Expand All @@ -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。
Expand All @@ -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 與測試解析。

Expand All @@ -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 嗎?

Expand All @@ -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 產生的程式碼正確嗎?

Expand Down
10 changes: 10 additions & 0 deletions docs/UAT.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 63/63 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,425 packed bytes, 256,600 unpacked bytes, SHA-256 `cc3a95f7637d61cfdcefed76d0dbc7077141a1a3206a52d9a9ffb4049d5aef91`. 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`.
Expand Down
66 changes: 66 additions & 0 deletions docs/ci.md
Original file line number Diff line number Diff line change
@@ -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.
Loading