diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 99984092..cbb1ced3 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -9,7 +9,7 @@ "name": "claude-code", "source": "./plugins/claude-code", "description": "Reference implementation of the Ironclad standard — multi-agent dev harness for Claude Code.", - "version": "0.9.2", + "version": "0.9.3", "author": { "name": "qwerfunch" }, diff --git a/CHANGELOG.md b/CHANGELOG.md index 01c82a82..4b2041b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,50 @@ All notable changes to Cladding are documented here. Format: [Keep a Changelog 1.1.0](https://keepachangelog.com/en/1.1.0/). Versioning: [Semantic Versioning 2.0](https://semver.org/spec/v2.0.0.html). +## [0.9.3] — The review packet shows how the contract itself moved (2026-08-04) + +**In one line:** a pull request now shows which acceptance criteria were rewritten while the code changed, and the architecture gate stops failing on generated build output. + +### Added + +- **"How the acceptance criteria moved" in `clad report`.** For every feature spec entry the range touched, each criterion is classified new / rewritten / removed / unchanged by matching on its id, alongside the entry's status transition and any EARS pattern shift. Rewriting a requirement to match what you built leaves code and spec agreeing, so no drift check can see it; this is the surface that does. +- **"Declared tests" in `clad report`** — for each criterion, whether the test it names also changed in the range, telling apart a real path that did not change, a concrete path with no file behind it, and a placeholder the harness suggested. It grades nothing: whether a test genuinely verifies its criterion is not mechanically decidable, so the packet shows what was declared and leaves the judgement to the reviewer. The dangling-path case matters because every other existence check in the harness only looks at finished features. +- **The packet names the revision it compared against**, when that is not the commit you named. The range anchors on the merge base of your ref and HEAD, which on a branch that forked earlier is a different commit — an audit artifact that silently compared against something else cannot be reproduced by hand. + +### Fixed + +- **The architecture gate no longer scans generated build output.** A bundler's output legitimately contains mutual imports, so scanning it reported circular dependencies that exist in no hand-written file — and blocked the gate on them. `dist`, `build`, `out`, `coverage`, `target`, `.next`, `.nuxt`, `.output`, `.svelte-kit` and `.vite` are now excluded, matched at the repository root only, so a source directory that merely happens to be named `build/` deeper in the tree is still scanned. `dist`, `coverage` and the framework caches are excluded at any depth, because a monorepo package or a front-end subdirectory keeps its bundle one level down; `build`, `out` and `target` stay anchored at the root, because they name real source directories often enough that excluding them deeper would drop hand-written code from the scan. + + **If your project has its own madge exclusion in force, cladding passes none of its own and your rules are the only ones that apply** — madge replaces its configured exclusions with a command-line flag rather than merging them, so the two cannot coexist. That is decided the way madge decides it: by reading `.madgerc` up the directory tree, plus `$HOME` and `/etc`, and by checking that an exclusion is actually set rather than that a file merely exists. +- **A review range that forked earlier no longer charges the base branch's commits to the range under review.** +- **The packet described itself as four sections when it renders six** — in `clad report --help`, in the module that assembles it, and in the acceptance criterion that enumerates them. The criterion appears as `REWRITTEN` in this release's own packet, which is the correct outcome. +- **A section lead asserted that the code had been changed to match a rewritten criterion.** The population is deliberately status-blind, so the line also sat above entries with no code yet; it is now conditional. +- **A rewritten obligation could pass as unchanged.** The criterion comparison read only the statement, the pattern and the trigger — not `action` and `response`, which state the obligation itself and which four out of five criteria in this project carry. Rewriting one of them classified as no change at all; in this repository's own history that hid 31 rewrites. +- **An instruction the schema rejects.** The `planner` brief asked for an `archive_reason` on a removed acceptance criterion, but that field exists only at feature level and the criterion schema refuses unknown keys — following the instruction failed the sync barrier. +- **A failing scanner said what KIND of problem it found, never which one.** The architecture + stage reported "the code has an import loop" and stopped there, because the code that builds + the message preferred the tool's progress output over its report — madge writes its progress + to one stream and the numbered cycle list to the other — and then cut what survived to two + hundred characters. The gate now shows the list, and the terminal prints the specifics under + the plain sentence instead of replacing them with it. An adopter spent sixteen days on this + and recorded the wrong cause; in a controlled run, three of three agents given the old build + "fixed" it by deleting or rewriting their own build output. +- **Nothing said what language to write a spec entry in.** Four adopter projects diverged on + their own — two reached nearly all Korean titles, two stayed fully English — because the + question was never answered anywhere. The managed AGENTS.md block now answers it: English by + default, but match the entries already in the spec, because those are the project's own voice + and they cannot go stale the way a setting can. Asking for another language covers the title, + the notes and the statement, and carries forward on its own; existing entries are never + rewritten into another language. Only four words are fixed — `when`, `while`, `if`, `where` — + because the gate matches them literally, and only as the FIRST word of a condition, so + `when 앱이 종료될 때` is valid. +- **Nothing shipped to an adopter said how to write an acceptance criterion.** The managed + AGENTS.md block now carries the EARS table — which trigger word each pattern requires, with a + working example per row — and a test asserts every example in it against the real validator, + so the table cannot drift from the rule it teaches. `docs/` is not in the published package, + so agents were reverse-engineering the rules from the minified bundle. +- **Stale and self-contradicting counts across the six READMEs**, where feature and test-file totals disagreed with the spec and, in places, with each other inside the same file. + ## [0.9.2] — Completions record whether anything checked them independently (2026-07-26) **In one line:** every finished feature is now marked `independent` or `self-certified` from the evidence it actually recorded, and cladding stops prescribing how you arrange your agents. diff --git a/README.html b/README.html index d4ec8110..1a91d7f2 100644 --- a/README.html +++ b/README.html @@ -235,7 +235,7 @@
- cladding builds itself with cladding too — 266 of its 270 features cleared this same gate, the first L4 implementation of the Ironclad standard. + cladding builds itself with cladding too — 269 of its 273 features cleared this same gate, the first L4 implementation of the Ironclad standard.
@@ -556,7 +556,7 @@248 test files · 6 capabilities · coverage drop blocked by the COVERAGE_DROP detector
+249 test files · 6 capabilities · coverage drop blocked by the COVERAGE_DROP detector
Road to Ironclad 1.0 — 1.0 locks only when two independent implementations pass the L4 conformance fixtures (GOVERNANCE § 1). cladding is the first.diff --git a/README.ja.md b/README.ja.md index c9f552db..13fb81ce 100644 --- a/README.ja.md +++ b/README.ja.md @@ -12,7 +12,7 @@ @@ -31,7 +31,7 @@ - **たどれる** — **出荷されたものは記録に残る**: 何を検証したかはコミットされた内容に刻まれ、誰がいつやったかはローカルのセッション台帳に、なぜかは spec に残る — だから引き継ぎもレビューも、掘り起こさずに済む。 - **拡張しても揺るがない** — 人と AI が増えれば、普通は衝突と乖離も増える。だが全員が一つの spec を基準に働くので、それらは自動でせき止められる — だから規模を広げても崩れない。 -cladding は **自分自身も cladding で作っている** — 270 個の feature のうち 266 個が同じゲートを通過した、[Ironclad](https://github.com/qwerfunch/ironclad) 標準を L4 で実装した最初の事例だ。 +cladding は **自分自身も cladding で作っている** — 273 個の feature のうち 269 個が同じゲートを通過した、[Ironclad](https://github.com/qwerfunch/ironclad) 標準を L4 で実装した最初の事例だ。 @@ -347,9 +347,9 @@ clad update # 3. プロジェクト接続と派生状態を更新 | Version | 準拠レベル | Tests | Gate | Features | |---|---|---|---|---| -| v0.9.2(2026-07) | L4 · [自己申告](https://github.com/qwerfunch/ironclad/blob/main/GOVERNANCE.md) | 2736 / 2736 | 15 段階 · 41 detectors | 270(266 done) | +| v0.9.3(2026-08) | L4 · [自己申告](https://github.com/qwerfunch/ironclad/blob/main/GOVERNANCE.md) | 2815 / 2815 | 15 段階 · 41 detectors | 273(269 done) | -248 test files · capability 6 個 · カバレッジ低下は COVERAGE_DROP detector がブロック +249 test files · capability 6 個 · カバレッジ低下は COVERAGE_DROP detector がブロック > **Ironclad 1.0 への道** — 1.0 は *独立した二つの実装が L4 準拠フィクスチャを通過してはじめて* 確定する([GOVERNANCE § 1](https://github.com/qwerfunch/ironclad/blob/main/GOVERNANCE.md))。cladding はその一つ目だ。 diff --git a/README.ko.html b/README.ko.html index cec6e50a..a99bc012 100644 --- a/README.ko.html +++ b/README.ko.html @@ -277,7 +277,7 @@
- cladding은 자기 자신도 cladding으로 만든다 — 기능 270개 중 266개가 같은 게이트를 통과했고, Ironclad 표준을 L4로 구현한 첫 사례다. + cladding은 자기 자신도 cladding으로 만든다 — 기능 273개 중 269개가 같은 게이트를 통과했고, Ironclad 표준을 L4로 구현한 첫 사례다.
@@ -590,7 +590,7 @@248 test files · capability 6개 · coverage는 COVERAGE_DROP detector가 하락 차단
+249 test files · capability 6개 · coverage는 COVERAGE_DROP detector가 하락 차단
Ironclad 1.0까지의 길 — 1.0은 독립적인 두 개의 구현이 L4 검증 셋을 통과해야 잠긴다 (GOVERNANCE § 1). cladding이 첫 번째.diff --git a/README.ko.md b/README.ko.md index b21ce565..bbfa7ee1 100644 --- a/README.ko.md +++ b/README.ko.md @@ -12,7 +12,7 @@ @@ -31,7 +31,7 @@ - **추적** — **나간 것은 기록에 남는다**: 무엇을 검증했는지는 커밋된 내용에 새겨지고, 누가·언제는 로컬 세션 로그에, 왜는 스펙에 남아, 인수인계와 리뷰가 파헤치지 않아도 된다. - **확장** — 사람과 AI를 늘리면 보통 충돌과 어긋남도 함께 불어난다. 하지만 모두가 스펙 하나를 기준으로 일하니 그게 자동으로 걸린다 — 그래서 규모를 키워도 무너지지 않는다. -cladding은 **자기 자신도 cladding으로 만든다** — 기능 270개 중 266개가 같은 게이트를 통과했고, [Ironclad](https://github.com/qwerfunch/ironclad) 표준을 L4로 구현한 첫 사례다. +cladding은 **자기 자신도 cladding으로 만든다** — 기능 273개 중 269개가 같은 게이트를 통과했고, [Ironclad](https://github.com/qwerfunch/ironclad) 표준을 L4로 구현한 첫 사례다. @@ -346,9 +346,9 @@ clad update # 3. 프로젝트 연결과 파생 데이터를 함께 | version | 준수 등급 | tests | gate | features | |---|---|---|---|---| -| v0.9.2 · 2026-07 | L4 · [L0–L4 중 최고 · 자가 선언](https://github.com/qwerfunch/ironclad/blob/main/GOVERNANCE.md) | 2736 / 2736 · all pass | 15 단계 · 41 detectors | 270 · 266 done · 자기 스펙 | +| v0.9.3 · 2026-08 | L4 · [L0–L4 중 최고 · 자가 선언](https://github.com/qwerfunch/ironclad/blob/main/GOVERNANCE.md) | 2815 / 2815 · all pass | 15 단계 · 41 detectors | 273 · 269 done · 자기 스펙 | -248 test files · capability 6개 · coverage는 COVERAGE_DROP detector가 하락 차단 +249 test files · capability 6개 · coverage는 COVERAGE_DROP detector가 하락 차단 > **Ironclad 1.0까지의 길** — 1.0은 *독립적인 두 개의 구현이 L4 검증 셋을 통과해야* 잠긴다 ([GOVERNANCE § 1](https://github.com/qwerfunch/ironclad/blob/main/GOVERNANCE.md)). cladding이 첫 번째. diff --git a/README.md b/README.md index 37c5b8d1..48df0442 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ @@ -31,7 +31,7 @@ So you can ship AI-written code held to **the same standard as human-written cod - **Traced** — **What shipped is on the record**: what was verified is stamped into committed content, who and when land in the local session ledger, and the why lives in the spec — so handoff and review skip the archaeology. - **Scales** — adding people and AIs would normally multiply conflicts and drift; because everyone works from one shared spec, those get caught automatically — so you can grow without it breaking down. -cladding builds **itself** with cladding too — 266 of its 270 features cleared this same gate, the first L4 implementation of the [Ironclad](https://github.com/qwerfunch/ironclad) standard. +cladding builds **itself** with cladding too — 269 of its 273 features cleared this same gate, the first L4 implementation of the [Ironclad](https://github.com/qwerfunch/ironclad) standard. @@ -360,9 +360,9 @@ Reconcile the drift the update flagged. | Version | Conformance | Tests | Gate | Features | |---|---|---|---|---| -| v0.9.2 (2026-07) | L4 · [self-declared](https://github.com/qwerfunch/ironclad/blob/main/GOVERNANCE.md) | 2736 / 2736 | 15 stages · 41 detectors | 270 (266 done) | +| v0.9.3 (2026-08) | L4 · [self-declared](https://github.com/qwerfunch/ironclad/blob/main/GOVERNANCE.md) | 2815 / 2815 | 15 stages · 41 detectors | 273 (269 done) | -248 test files · 6 capabilities · coverage drop blocked by the COVERAGE_DROP detector +249 test files · 6 capabilities · coverage drop blocked by the COVERAGE_DROP detector > **Road to Ironclad 1.0** — 1.0 locks only when *two independent implementations pass the L4 conformance fixtures* ([GOVERNANCE § 1](https://github.com/qwerfunch/ironclad/blob/main/GOVERNANCE.md)). cladding is the first. diff --git a/README.zh.md b/README.zh.md index b8533d80..ff68b5df 100644 --- a/README.zh.md +++ b/README.zh.md @@ -12,7 +12,7 @@ @@ -31,7 +31,7 @@ - **可追溯** —— **交付出去的一切都留有记录**:验证了什么,写进已提交的内容;谁、何时,记在本地会话账本;为什么,留在 spec —— 于是交接与评审无需考古,就能追溯每一个决定。 - **可扩展** —— 人和 AI 越多,通常冲突和漂移也越多。但所有人都以同一份 spec 为基准,这些会被自动挡下 —— 所以不断扩张也不会崩。 -cladding 连**自己**也是用 cladding 造的 —— 270 个 feature 里有 266 个通过了同一道门禁,成为 [Ironclad](https://github.com/qwerfunch/ironclad) 标准的首个 L4 实现。 +cladding 连**自己**也是用 cladding 造的 —— 273 个 feature 里有 269 个通过了同一道门禁,成为 [Ironclad](https://github.com/qwerfunch/ironclad) 标准的首个 L4 实现。 @@ -343,9 +343,9 @@ clad update # 3. 刷新项目连接和派生状态 | 版本 | 一致性 | Tests | Gate | Features | |---|---|---|---|---| -| v0.9.2(2026-07) | L4 · [自我声明](https://github.com/qwerfunch/ironclad/blob/main/GOVERNANCE.md) | 2736 / 2736 | 15 阶段 · 41 检测器 | 270(266 done) | +| v0.9.3(2026-08) | L4 · [自我声明](https://github.com/qwerfunch/ironclad/blob/main/GOVERNANCE.md) | 2815 / 2815 | 15 阶段 · 41 检测器 | 273(269 done) | -248 个测试文件 · 6 项 capability · 覆盖率下降由 COVERAGE_DROP 检测器拦下 +249 个测试文件 · 6 项 capability · 覆盖率下降由 COVERAGE_DROP 检测器拦下 > **通往 Ironclad 1.0 之路** —— 只有当*两个独立实现都通过 L4 一致性测试夹具*时,1.0 才会锁定([GOVERNANCE § 1](https://github.com/qwerfunch/ironclad/blob/main/GOVERNANCE.md))。cladding 是第一个。 diff --git a/docs/gate-scope.md b/docs/gate-scope.md index e145ec00..8c347bc3 100644 --- a/docs/gate-scope.md +++ b/docs/gate-scope.md @@ -110,6 +110,21 @@ gate: Precedence, highest first: explicit per-call `cmd` override → `gate.commands` → auto module-scope → repo gate. +## Architecture stage — what it scans in a TS/JS project + +The circular-dependency scan runs from the repository root and **skips generated +build output** — `dist/`, `build/`, `out/`, `coverage/`, `target/`, `.next/`, +`.nuxt/`, `.output/`, `.svelte-kit/`, `.vite/` — matched at the root only, so a +source directory that merely happens to be named `build/` deeper in the tree is +still scanned. A bundler's output legitimately contains mutual imports, and +scanning it reports cycles that exist in no hand-written file. + +**To control this yourself**, declare a `.madgerc` (or a `madge` block in +`package.json`) with your own `excludeRegExp`. When you do, cladding passes no +exclusion of its own and your rules are the only ones in force — madge *replaces* +its configured exclusions with a command-line flag rather than merging them, so +the two cannot coexist. + ## Backward compatibility Non-Gradle languages, modules-less features, and `gate.scope: repo` all run diff --git a/docs/glossary.md b/docs/glossary.md index 91bff1a7..5aca0da2 100644 --- a/docs/glossary.md +++ b/docs/glossary.md @@ -70,7 +70,7 @@ | `graph` | stable (0.7.0) | Render the spec↔code↔doc knowledge graph: `export` → mermaid/dot/json/Obsidian-vault or a self-contained offline `html` viewer (WebGL, three.js bundled); `serve` → the same viewer live on localhost, auto-reloading as spec/docs change; `stats` → counts + hubs. | 지식 그래프 | | `hook` | stable (0.6.0) | Host hook protocol adapter — consumes one host lifecycle event (SessionStart / UserPromptSubmit / PreToolUse / PostToolUse / Stop) as stdin JSON; always exits 0. Honest limit: PreToolUse blocking only sees Edit/Write tool calls — a YAML edit made through Bash bypasses lane one; the Stop hook's post-hoc detectors are lane two. Neither lane alone is the guarantee. | 호스트 훅 프로토콜 어댑터 | | `changelog` | stable (0.6.0) | Render shipped changes since a git ref into human-facing documents — capability-grouped markdown / `--json` manifest / `--audit` verification table / `--catalog` spec listing. Named `changelog` deliberately, NOT `digest` (which means cryptographic hash in this domain — see Naming conventions). | 변경 이력 렌더링 | -| `report` | stable (0.8.0) | Render one deterministic review packet for a git range — spec-shard movement (from `changelog`), changed source files resolved to their owning features via the reverse index, the deduped regression set, and gate + attestation state. `--format md \| sarif \| json`. For PR reviewers/team-leads/auditors: it RENDERS, it gates nothing. | 리뷰 패킷 렌더링 | +| `report` | stable (0.8.0) | Render one deterministic review packet for a git range — spec entry movement (from `changelog`), how each acceptance criterion moved, changed source files resolved to their owning features via the reverse index, the tests those features declare, the deduped regression set, and gate + attestation state. `--format md \| sarif \| json`. For PR reviewers/team-leads/auditors: it RENDERS, it gates nothing. | 리뷰 패킷 렌더링 | | `bundle` | stable (0.8.0) | Write ONE self-contained offline HTML audit bundle (`--out