diff --git a/CLAUDE.md b/CLAUDE.md index 13bee34..04ac9eb 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -4,7 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## Project status -`opencmdb` is a self-hosted, single-binary **Rust** network reconciliation engine (IPAM + light app CMDB + topology) for home-lab/SMB. Core thesis: continuously compare the **observed** state (auto-discovered) against the **declared** state (documented); the gap is the product. **Planning is COMPLETE** (product brief, PRD, UX spec, architecture — all in `_bmad-output/planning-artifacts/`, decision register D1–D66). **As of 2026-07-22 the code RUNS**: `v0.1.1` is tagged and published to Docker Hub as `gcorbaz/opencmdb`, and it scans a CIDR and shows a real observed-vs-declared gap on one page. **Epics 1–4 of 23 are done** (the walking skeleton shipped as v0.1). **Epic 4 closed on 2026-07-25**: the fixture corpus, the metrics harness and the trap corpus — all written BEFORE the identity engine — are committed and locked (25 artefacts, 24 traps across nine families, plus the wire-format spec). Its story 4.19 was SPLIT at closure: 4.19a shipped, **4.19b (the mutation generator) moved to Epic 11** — recorded in `epic-4-correct-course-2026-07-25.md` and GitHub issue #34, not silently. **Epic 5 — the identity engine — is IN PROGRESS since 2026-07-27** (**16 stories**: 5.4b was INSERTED 2026-07-29 at story 5.4's contexting, splitting the verdict algebra — a function that must be TOTAL over a table D13 leaves one input class short — and its anti-float `xtask` gate out of 5.4). Its **three inherited debt stories come first and are all `done`** — 5.1, 5.2 and 5.2b, PRs #41, #44 and #46, all merged 2026-07-28. The engine proper starts at **5.3, `done`** — PR #48, merged 2026-07-29 — which ships the identity engine's own abstention vocabulary (`IdentityAbstentionCause`, in the new `crates/opencmdb-core/src/identity/`) and **no engine**: no cascade, no rule, no `Decision`, no join. **5.4 follows and is `done`** — PR #52, squash-merged 2026-07-29 as `da87b62`: it adds the engine's RETURN type in the same file — `Verdict` (D13's five verdicts), `RuleVerdict { rule, verdict, evidence }`, `RulesetVersion`, `Conclusion` and `Decision` — and still **no algebra**: nothing combines a verdict set, no rule produces a verdict, nothing produces a decision. **Next is 5.4b, `ready-for-dev`** (contexted and validated 2026-07-29): `decide(Vec, RulesetVersion) -> Decision` as a TOTAL pure function over D13's six rows plus the one input class the table leaves uncovered (`≥1 Opposes` alone → `Abstained { AbsenceOfProof }`, Guy's arbitration), and the `xtask` gate that refuses a float under `identity/`. _(This sentence named only 5.1 until 2026-07-29 — stale for a day, found by story 5.3's code review, not by the two stories that caused the drift.)_ Live status is `_bmad-output/implementation-artifacts/sprint-status.yaml`; grounding is `docs/project-context.md`. +`opencmdb` is a self-hosted, single-binary **Rust** network reconciliation engine (IPAM + light app CMDB + topology) for home-lab/SMB. Core thesis: continuously compare the **observed** state (auto-discovered) against the **declared** state (documented); the gap is the product. **Planning is COMPLETE** (product brief, PRD, UX spec, architecture — all in `_bmad-output/planning-artifacts/`, decision register D1–D66). **As of 2026-07-22 the code RUNS**: `v0.1.1` is tagged and published to Docker Hub as `gcorbaz/opencmdb`, and it scans a CIDR and shows a real observed-vs-declared gap on one page. **Epics 1–4 of 23 are done** (the walking skeleton shipped as v0.1). **Epic 4 closed on 2026-07-25**: the fixture corpus, the metrics harness and the trap corpus — all written BEFORE the identity engine — are committed and locked (25 artefacts, 24 traps across nine families, plus the wire-format spec). Its story 4.19 was SPLIT at closure: 4.19a shipped, **4.19b (the mutation generator) moved to Epic 11** — recorded in `epic-4-correct-course-2026-07-25.md` and GitHub issue #34, not silently. **Epic 5 — the identity engine — is IN PROGRESS since 2026-07-27** (**16 stories**: 5.4b was INSERTED 2026-07-29 at story 5.4's contexting, splitting the verdict algebra — a function that must be TOTAL over a table D13 leaves one input class short — and its anti-float `xtask` gate out of 5.4). Its **three inherited debt stories come first and are all `done`** — 5.1, 5.2 and 5.2b, PRs #41, #44 and #46, all merged 2026-07-28. The engine proper starts at **5.3, `done`** — PR #48, merged 2026-07-29 — which ships the identity engine's own abstention vocabulary (`IdentityAbstentionCause`, in the new `crates/opencmdb-core/src/identity/`) and **no engine**: no cascade, no rule, no `Decision`, no join. **5.4 follows and is `done`** — PR #52, squash-merged 2026-07-29 as `da87b62`: it adds the engine's RETURN type in the same file — `Verdict` (D13's five verdicts), `RuleVerdict { rule, verdict, evidence }`, `RulesetVersion`, `Conclusion` and `Decision` — and still **no algebra**: nothing combines a verdict set, no rule produces a verdict, nothing produces a decision. **5.4b follows and is in `review`, code-reviewed 2026-07-30** (PR #55 open, CI green, 281 tests): it ships the ALGEBRA — `decide(Vec, RulesetVersion) -> Decision`, a TOTAL pure function over D13's six rows plus the one input class the table leaves uncovered (`≥1 Opposes` alone → `Abstained { AbsenceOfProof }`, Guy's arbitration; the D13 correction itself is **GitHub issue #54**, a milestone act) — and a **sixth `cargo xtask ci` gate, `float-free`**, which reds on a float type or a float literal in code under `identity/`, comments stripped so the architecture may be quoted. The review applied 22 patches and registered 5 deferrals: `decide` now matches on `Option` rather than booleans, so the presence test and the rule selection are one act and no unreachable arm has to be justified; and the gate's matcher is a **numeric-literal tokeniser** rather than a digit-dot-digit search, because the search form was measured to pass `1e-3` and `1.` (both `f64`) while reddening `"192.168.0.1"`, `t.0.1` and any identifier containing `f64` — a shape story 5.5 would have tripped on its first MAC/IP rule. **Still no rule and no producer**: nothing emits a `Verdict`, so nothing calls `decide` outside its own tests (5.5 owns the join). Next is 5.5. _(This sentence named only 5.1 until 2026-07-29 — stale for a day, found by story 5.3's code review, not by the two stories that caused the drift.)_ Live status is `_bmad-output/implementation-artifacts/sprint-status.yaml`; grounding is `docs/project-context.md`. ### Build / lint / test commands (the stack is chosen and building) diff --git a/_bmad-output/implementation-artifacts/5-4b-verdict-algebra-and-float-gate.md b/_bmad-output/implementation-artifacts/5-4b-verdict-algebra-and-float-gate.md index 41810d8..9087ca7 100644 --- a/_bmad-output/implementation-artifacts/5-4b-verdict-algebra-and-float-gate.md +++ b/_bmad-output/implementation-artifacts/5-4b-verdict-algebra-and-float-gate.md @@ -1,6 +1,6 @@ # Story 5.4b: The verdict algebra is a total function, and no float can reach it -Status: ready-for-dev +Status: review