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 .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,9 @@ test-results/
playwright-report/
*.snap.png

# Cladding runtime state — audit log, events log, etc.
.cladding/
# Cladding runtime state — audit log, events log, etc. (config.yaml stays committable)
.cladding/*
!.cladding/config.yaml

# A/B-extended generated React demo projects.
# These are regeneratable on demand via `UPDATE_AB_REPORTS=1 npx vitest run`
Expand Down
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,17 @@ 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).

## [Unreleased]

### Changed

- **The language check now judges the sources on disk, not the build manifest.** The manifest chain reads build orchestration, so a C++ SDK driven by Gradle or a Rust core shipped through npm was mislabelled by construction — measured across realistic repo shapes, the old comparison blocked 12 of 19 normal projects under `--strict`, including labels cladding's own onboarding had just written. `TECH_STACK_MISMATCH` now reads the observed source distribution from one shared vocabulary: a language it does not know, or a tree with under five classified files, produces silence instead of a false alarm; a declared language absent from the sources still warns with the evidence in the message; a declared language present but under 10% is disclosed at info and never blocks. Gate-command selection still uses the manifest chain — "what do we run" and "what is this project" are different questions, and only the second one moved.
- **The module-honesty scan now derives its universe from evidence.** `UNMAPPED_ARTIFACT` picked one file extension from a six-language table; declaring cpp, java, or csharp fell through to `*.ts`, scanned nothing, and passed vacuously on exactly the projects the check exists for. The scan now unites the extensions observed in the tree with the extensions of modules the spec claims under its layer roots — so an unknown language enters the universe the moment a feature claims a file in it — and infers scan roots from the claimed paths themselves (the Kotlin `src/main/kotlin` layout now comes out of inference, not a table). A root must carry at least a quarter of the layer-claimed modules, which keeps directories that merely reuse a layer name from flooding the scan.

### Fixed

- **The gate config can finally be committed.** `clad init` ignored `.cladding/` with the directory form, and git never re-includes under an excluded directory — so `.cladding/config.yaml`, the file that carries every documented gate override, was impossible to commit: fresh clones and CI silently ran a different gate than the author tuned. New projects now get `.cladding/*` plus `!.cladding/config.yaml`. Existing projects are never rewritten; `clad doctor` reports a blocked gate config in text and JSON instead, the same read-only posture as the unpinned-CI report.

## [0.9.4] — Live host health and reproducible verification (2026-08-10)

**In one line:** cladding now proves that its host hooks actually fired, records what stopped or completed a run, pins generated CI to the current release line, and stamps every verified tree with the policy that earned it.
Expand Down
4 changes: 2 additions & 2 deletions README.html
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ <h1>cladding</h1>
<p class="badges">
<a href="https://github.com/qwerfunch/ironclad"><img src="https://img.shields.io/badge/ironclad-L4%20conformant-brightgreen" alt="ironclad"></a>
<a href="https://github.com/qwerfunch/ironclad"><img src="https://img.shields.io/badge/spec-v0.0.23-blue" alt="spec"></a>
<img src="https://img.shields.io/badge/tests-2845%2F2845-brightgreen" alt="tests">
<img src="https://img.shields.io/badge/tests-2953%2F2953-brightgreen" alt="tests">
<img src="https://img.shields.io/badge/detectors-41-brightgreen" alt="detectors">
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-lightgrey" alt="license"></a>
</p>
Expand Down Expand Up @@ -566,7 +566,7 @@ <h2>Status</h2>
</td>
<td style="text-align:center;width:140px;background:#f8fafc;padding:18px 10px;border-radius:8px;border:none">
<div style="font-size:11px;color:#64748b;letter-spacing:1.5px;text-transform:uppercase;font-weight:600">tests</div>
<div style="font-size:24px;font-weight:800;color:#0f172a;margin:8px 0;letter-spacing:-0.5px">2845<span style="font-size:16px;color:#94a3b8">/2845</span></div>
<div style="font-size:24px;font-weight:800;color:#0f172a;margin:8px 0;letter-spacing:-0.5px">2953<span style="font-size:16px;color:#94a3b8">/2953</span></div>
<div style="font-size:11px;color:#64748b">all pass</div>
</td>
<td style="text-align:center;width:140px;background:#f8fafc;padding:18px 10px;border-radius:8px;border:none">
Expand Down
4 changes: 2 additions & 2 deletions README.ja.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<p align="center">
<a href="https://github.com/qwerfunch/ironclad"><img src="https://img.shields.io/badge/ironclad-L4%20conformant-brightgreen" alt="ironclad"/></a>
<a href="https://github.com/qwerfunch/ironclad"><img src="https://img.shields.io/badge/spec-v0.0.23-blue" alt="spec"/></a>
<img src="https://img.shields.io/badge/tests-2845%2F2845-brightgreen" alt="tests"/>
<img src="https://img.shields.io/badge/tests-2953%2F2953-brightgreen" alt="tests"/>
<img src="https://img.shields.io/badge/detectors-41-brightgreen" alt="detectors"/>
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-lightgrey" alt="license"/></a>
</p>
Expand Down Expand Up @@ -347,7 +347,7 @@ clad update # 3. プロジェクト接続と派生状態を更新

| Version | 準拠レベル | Tests | Gate | Features |
|---|---|---|---|---|
| v0.9.4(2026-08) | L4 · [自己申告](https://github.com/qwerfunch/ironclad/blob/main/GOVERNANCE.md) | 2845 / 2845 | 15 段階 · 41 detectors | 277(273 done) |
| v0.9.4(2026-08) | L4 · [自己申告](https://github.com/qwerfunch/ironclad/blob/main/GOVERNANCE.md) | 2953 / 2953 | 15 段階 · 41 detectors | 277(273 done) |

<sub>253 test files · capability 6 個 · カバレッジ低下は COVERAGE_DROP detector がブロック</sub>

Expand Down
4 changes: 2 additions & 2 deletions README.ko.html
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ <h1>cladding</h1>
<p class="badges">
<a href="https://github.com/qwerfunch/ironclad"><img src="https://img.shields.io/badge/ironclad-L4%20conformant-brightgreen" alt="ironclad"></a>
<a href="https://github.com/qwerfunch/ironclad"><img src="https://img.shields.io/badge/spec-v0.0.23-blue" alt="spec"></a>
<img src="https://img.shields.io/badge/tests-2845%2F2845-brightgreen" alt="tests">
<img src="https://img.shields.io/badge/tests-2953%2F2953-brightgreen" alt="tests">
<img src="https://img.shields.io/badge/detectors-41-brightgreen" alt="detectors">
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-lightgrey" alt="license"></a>
</p>
Expand Down Expand Up @@ -600,7 +600,7 @@ <h2>Status</h2>
</td>
<td style="text-align:center;width:140px;background:#f8fafc;padding:18px 10px;border-radius:8px;border:none">
<div style="font-size:11px;color:#64748b;letter-spacing:1.5px;text-transform:uppercase;font-weight:600">tests</div>
<div style="font-size:24px;font-weight:800;color:#0f172a;margin:8px 0;letter-spacing:-0.5px">2845<span style="font-size:16px;color:#94a3b8">/2845</span></div>
<div style="font-size:24px;font-weight:800;color:#0f172a;margin:8px 0;letter-spacing:-0.5px">2953<span style="font-size:16px;color:#94a3b8">/2953</span></div>
<div style="font-size:11px;color:#64748b">all pass</div>
</td>
<td style="text-align:center;width:140px;background:#f8fafc;padding:18px 10px;border-radius:8px;border:none">
Expand Down
4 changes: 2 additions & 2 deletions README.ko.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<p align="center">
<a href="https://github.com/qwerfunch/ironclad"><img src="https://img.shields.io/badge/ironclad-L4%20conformant-brightgreen" alt="ironclad"/></a>
<a href="https://github.com/qwerfunch/ironclad"><img src="https://img.shields.io/badge/spec-v0.0.23-blue" alt="spec"/></a>
<img src="https://img.shields.io/badge/tests-2845%2F2845-brightgreen" alt="tests"/>
<img src="https://img.shields.io/badge/tests-2953%2F2953-brightgreen" alt="tests"/>
<img src="https://img.shields.io/badge/detectors-41-brightgreen" alt="detectors"/>
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-lightgrey" alt="license"/></a>
</p>
Expand Down Expand Up @@ -346,7 +346,7 @@ clad update # 3. 프로젝트 연결과 파생 데이터를 함께

| version | 준수 등급 | tests | gate | features |
|---|---|---|---|---|
| v0.9.4 · 2026-08 | L4 · [L0–L4 중 최고 · 자가 선언](https://github.com/qwerfunch/ironclad/blob/main/GOVERNANCE.md) | 2845 / 2845 · all pass | 15 단계 · 41 detectors | 277 · 273 done · 자기 스펙 |
| v0.9.4 · 2026-08 | L4 · [L0–L4 중 최고 · 자가 선언](https://github.com/qwerfunch/ironclad/blob/main/GOVERNANCE.md) | 2953 / 2953 · all pass | 15 단계 · 41 detectors | 277 · 273 done · 자기 스펙 |

<sub>253 test files · capability 6개 · coverage는 COVERAGE_DROP detector가 하락 차단</sub>

Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<p align="center">
<a href="https://github.com/qwerfunch/ironclad"><img src="https://img.shields.io/badge/ironclad-L4%20conformant-brightgreen" alt="ironclad"/></a>
<a href="https://github.com/qwerfunch/ironclad"><img src="https://img.shields.io/badge/spec-v0.0.23-blue" alt="spec"/></a>
<img src="https://img.shields.io/badge/tests-2845%2F2845-brightgreen" alt="tests"/>
<img src="https://img.shields.io/badge/tests-2953%2F2953-brightgreen" alt="tests"/>
<img src="https://img.shields.io/badge/detectors-41-brightgreen" alt="detectors"/>
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-lightgrey" alt="license"/></a>
</p>
Expand Down Expand Up @@ -360,7 +360,7 @@ Reconcile the drift the update flagged.

| Version | Conformance | Tests | Gate | Features |
|---|---|---|---|---|
| v0.9.4 (2026-08) | L4 · [self-declared](https://github.com/qwerfunch/ironclad/blob/main/GOVERNANCE.md) | 2845 / 2845 | 15 stages · 41 detectors | 277 (273 done) |
| v0.9.4 (2026-08) | L4 · [self-declared](https://github.com/qwerfunch/ironclad/blob/main/GOVERNANCE.md) | 2953 / 2953 | 15 stages · 41 detectors | 277 (273 done) |

<sub>253 test files · 6 capabilities · coverage drop blocked by the COVERAGE_DROP detector</sub>

Expand Down
4 changes: 2 additions & 2 deletions README.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<p align="center">
<a href="https://github.com/qwerfunch/ironclad"><img src="https://img.shields.io/badge/ironclad-L4%20conformant-brightgreen" alt="ironclad"/></a>
<a href="https://github.com/qwerfunch/ironclad"><img src="https://img.shields.io/badge/spec-v0.0.23-blue" alt="spec"/></a>
<img src="https://img.shields.io/badge/tests-2845%2F2845-brightgreen" alt="tests"/>
<img src="https://img.shields.io/badge/tests-2953%2F2953-brightgreen" alt="tests"/>
<img src="https://img.shields.io/badge/detectors-41-brightgreen" alt="detectors"/>
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-lightgrey" alt="license"/></a>
</p>
Expand Down Expand Up @@ -343,7 +343,7 @@ clad update # 3. 刷新项目连接和派生状态

| 版本 | 一致性 | Tests | Gate | Features |
|---|---|---|---|---|
| v0.9.4(2026-08) | L4 · [自我声明](https://github.com/qwerfunch/ironclad/blob/main/GOVERNANCE.md) | 2845 / 2845 | 15 阶段 · 41 检测器 | 277(273 done) |
| v0.9.4(2026-08) | L4 · [自我声明](https://github.com/qwerfunch/ironclad/blob/main/GOVERNANCE.md) | 2953 / 2953 | 15 阶段 · 41 检测器 | 277(273 done) |

<sub>253 个测试文件 · 6 项 capability · 覆盖率下降由 COVERAGE_DROP 检测器拦下</sub>

Expand Down
2 changes: 1 addition & 1 deletion conformance/fixtures.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ fixtures:
- name: F-013_AC-021
stage: documentary
kind: runnable
description: "F-013/AC-021 — When spec.project.language differs from the language resolved by the toolchain manifest chain, the detector shall emit a warn-severity finding."
description: "F-013/AC-021 — When the declared language is absent from the observed sources with at least five classified files, the detector shall emit a warn-severity finding naming the observed distribution (evidence-based since F-9e1279d4; the manifest chain is no longer consulted for identity)."
- name: F-014_AC-022
stage: documentary
kind: runnable
Expand Down
25 changes: 15 additions & 10 deletions conformance/runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -647,22 +647,27 @@ const fixtures: readonly Fixture[] = [
},
{
// F-013/AC-021 — TECH_STACK_MISMATCH warn when spec.project.language
// differs from what the toolchain detection chain returns. The warn
// is absent from the OBSERVED SOURCES (evidence-based since
// F-9e1279d4 — the manifest chain is no longer consulted for
// identity). Five .ts files clear the evidence floor (5), python is
// absent from the observed set, so exactly one warn fires. The warn
// does not fail drift (default severity is warn, not error), so
// pass remains true; the assertion is on the finding shape.
//
// The fixture writes `.secretlintrc.json` because adding package.json
// makes the toolchain pick TypeScript, which makes HARDCODED_SECRET
// try to invoke secretlint via npx — without a config file the
// scanner exits non-zero and emits an error finding that would mask
// the warn we are actually probing for.
// The fixture writes `.secretlintrc.json` because package.json makes
// the toolchain pick TypeScript for GATE COMMANDS, which makes
// HARDCODED_SECRET try to invoke secretlint via npx — without a
// config file the scanner exits non-zero and emits an error finding
// that would mask the warn we are actually probing for.
id: 'F-013_AC-021',
stage: 'stage_1.3',
expectedPass: true,
setup(d) {
mkdirSync(join(d, 'stages'), {recursive: true});
mkdirSync(join(d, 'spec'), {recursive: true});
writeTs(d, 'stages/dummy.ts', '// fixture stub\nexport const ok = true;\n');
for (let i = 1; i <= 5; i++) {
writeTs(d, `stages/dummy${i}.ts`, '// fixture stub\nexport const ok = true;\n');
}
writeFileSync(join(d, 'package.json'), PKG_JSON);
writeFileSync(join(d, '.secretlintrc.json'), SECRETLINTRC);
writeFileSync(
Expand All @@ -672,8 +677,8 @@ const fixtures: readonly Fixture[] = [
properties: {schema: {}, project: {}, features: {}},
}),
);
// spec.project.language = python, but package.json + .ts source
// make the toolchain resolve to typescriptmismatch.
// spec.project.language = python, but five observed .ts sources
// put python absent from the evidencewarn (F-9e1279d4 contract).
writeFileSync(
join(d, 'spec.yaml'),
'schema: "0.1"\n' +
Expand All @@ -682,7 +687,7 @@ const fixtures: readonly Fixture[] = [
' - id: F-001\n' +
' title: t\n' +
' status: done\n' +
' modules: [stages/dummy.ts, spec/schema.json]\n' +
' modules: [stages/dummy1.ts, stages/dummy2.ts, stages/dummy3.ts, stages/dummy4.ts, stages/dummy5.ts, spec/schema.json]\n' +
' acceptance_criteria:\n' +
' - id: AC-001\n' +
' ears: ubiquitous\n' +
Expand Down
2 changes: 1 addition & 1 deletion docs/ab-evaluation-extended/scenarios/dashboard/report.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ Four deterministic drift scenarios injected at feature-30 state. "Caught" = at l

| Scenario | A (Cladding) caught? | A new detectors | B (Vanilla) caught? | B new detectors |
|---|:---:|---|:---:|---|
| DI-1 Stale module reference (rename src/components/Header.tsx → src/components/Header.RENAMED.tsx without spec update) | ✅ | MISSING_IMPLEMENTATION, STATUS_DRIFT | · | — |
| DI-1 Stale module reference (rename src/components/Header.tsx → src/components/Header.RENAMED.tsx without spec update) | ✅ | MISSING_IMPLEMENTATION, UNMAPPED_ARTIFACT, STATUS_DRIFT | · | — |
| DI-2 Architecture violation (src/lib/filter.ts imports ../components/Header) | ✅ | ARCHITECTURE_FROM_SPEC, INFERABLE_DEPENDS_ON | · | — |
| DI-3 Hardcoded secret (add API key constant to src/lib/export-config.ts) | · | — | · | — |
| DI-4 Untested AC (add AC-003 to spec/features/metric-card-2ed463.yaml without test) | ✅ | MISSING_TESTS | N/A | N/A |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ Four deterministic drift scenarios injected at feature-30 state. "Caught" = at l

| Scenario | A (Cladding) caught? | A new detectors | B (Vanilla) caught? | B new detectors |
|---|:---:|---|:---:|---|
| DI-1 Stale module reference (rename src/components/Header.tsx → src/components/Header.RENAMED.tsx without spec update) | ✅ | MISSING_IMPLEMENTATION, STATUS_DRIFT | · | — |
| DI-1 Stale module reference (rename src/components/Header.tsx → src/components/Header.RENAMED.tsx without spec update) | ✅ | MISSING_IMPLEMENTATION, UNMAPPED_ARTIFACT, STATUS_DRIFT | · | — |
| DI-2 Architecture violation (src/lib/filter.ts imports ../components/Header) | ✅ | ARCHITECTURE_FROM_SPEC, INFERABLE_DEPENDS_ON | · | — |
| DI-3 Hardcoded secret (add API key constant to src/lib/export-import.ts) | · | — | · | — |
| DI-4 Untested AC (add AC-003 to spec/features/add-task-3cbf38.yaml without test) | ✅ | MISSING_TESTS | N/A | N/A |
Expand Down
10 changes: 5 additions & 5 deletions docs/ab-evaluation/case-payment-saas.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ no spec, no scenarios, no architecture invariants.
| Forbidden-import rules | 2 | 0 | +2 |
| Detector errors | 0 | 1 | -1 |
| Detector warnings | 1 | 3 | -2 |
| Detector infos | 13 | 28 | -15 |
| Detector infos | 12 | 28 | -16 |
| Tiered doc files | 2 | 0 | +2 |
| Tiered docs (lines) | 61 | 0 | +61 |
| Other doc files | 0 | 1 | -1 |
Expand All @@ -56,7 +56,7 @@ no spec, no scenarios, no architecture invariants.
**Detector outcomes** (META_INTEGRITY + HARDCODED_SECRET excluded — toolchain-only checks):

```
A (Cladding) — errors: 0 warns: 1 infos: 13
A (Cladding) — errors: 0 warns: 1 infos: 12

B (Vanilla) — errors: 1 warns: 3 infos: 28
Sample errors:
Expand All @@ -80,7 +80,7 @@ B (Vanilla) — errors: 1 warns: 3 infos: 28
| Forbidden-import rules | 2 | 0 | +2 |
| Detector errors | 1 | 1 | +0 |
| Detector warnings | 3 | 3 | +0 |
| Detector infos | 15 | 28 | -13 |
| Detector infos | 14 | 28 | -14 |
| Tiered doc files | 2 | 0 | +2 |
| Tiered docs (lines) | 61 | 0 | +61 |
| Other doc files | 0 | 1 | -1 |
Expand All @@ -95,7 +95,7 @@ B (Vanilla) — errors: 1 warns: 3 infos: 28
**Detector outcomes** (META_INTEGRITY + HARDCODED_SECRET excluded — toolchain-only checks):

```
A (Cladding) — errors: 1 warns: 3 infos: 15
A (Cladding) — errors: 1 warns: 3 infos: 14
Sample errors:
- [AC_DRIFT] F-4db939.AC-002 EARS: ears='unwanted' requires condition starting with 'if' — empty

Expand All @@ -109,7 +109,7 @@ B (Vanilla) — errors: 1 warns: 3 infos: 28
- **Structured artifacts**: cladding produces 9 tier-banner-bearing files vs vanilla's 0.
- **Spec ↔ code traceability**: cladding emits 1 feature(s), 2 AC(s), 2 scenario(s), 3 capability(s); vanilla has 0 of each.
- **Architecture enforcement**: cladding declares 3 layer(s) with 2 forbidden-import rule(s); vanilla has 0.
- **Detector behavior**: cladding-managed tree → 1 error(s) / 3 warn(s) / 15 info(s). Vanilla tree → 1 / 3 / 28. The detectors that gate against spec (REFERENCE_INTEGRITY, MISSING_IMPLEMENTATION, ARCHITECTURE_FROM_SPEC, CAPABILITIES_FEATURE_MAPPING) need cladding's artifacts to evaluate — without them they silently pass. The "0 errors on vanilla" therefore is **absence of signal**, not absence of drift.
- **Detector behavior**: cladding-managed tree → 1 error(s) / 3 warn(s) / 14 info(s). Vanilla tree → 1 / 3 / 28. The detectors that gate against spec (REFERENCE_INTEGRITY, MISSING_IMPLEMENTATION, ARCHITECTURE_FROM_SPEC, CAPABILITIES_FEATURE_MAPPING) need cladding's artifacts to evaluate — without them they silently pass. The "0 errors on vanilla" therefore is **absence of signal**, not absence of drift.
- **Token cost**: cladding's cumulative artifact + code consumes ~1943 tokens vs vanilla's ~1399 (heuristic chars/4) — Δ ≈ 544 tokens, the price of structure.
- **Code surface**: vanilla writes 5 source file(s) / 126 LoC + 2 test file(s) / 4 test case(s); cladding writes 1 / 11 + 1 / 1. (Vanilla front-loads code, cladding front-loads spec — both converge by M2.)

Expand Down
Loading
Loading