From 80c339adaef00daf92a978da00fbc1bafba04ece Mon Sep 17 00:00:00 2001 From: TerminallyLazy Date: Thu, 9 Jul 2026 02:12:38 -0400 Subject: [PATCH 01/12] Plan harness certification matrix --- ...ertification-matrix-implementation-plan.md | 1125 +++++++++++++++++ 1 file changed, 1125 insertions(+) create mode 100644 docs/superpowers/plans/2026-07-09-tree-ring-harness-certification-matrix-implementation-plan.md diff --git a/docs/superpowers/plans/2026-07-09-tree-ring-harness-certification-matrix-implementation-plan.md b/docs/superpowers/plans/2026-07-09-tree-ring-harness-certification-matrix-implementation-plan.md new file mode 100644 index 0000000..a76b64b --- /dev/null +++ b/docs/superpowers/plans/2026-07-09-tree-ring-harness-certification-matrix-implementation-plan.md @@ -0,0 +1,1125 @@ +# Tree Ring Harness Certification Matrix Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Add Phase 2 harness proof records so local compatibility is represented by structured evidence instead of claims. + +**Architecture:** Add a small harness evidence producer in the CLI crate that consumes the existing integration scan, writes `target/tree-ring-certification/harness/*.json`, and merges those records into `evidence-index.json`. Expose it through `tree-ring integrations certify`, run it from the repo certification script, and render per-harness status/path rows in `/evidence`. + +**Tech Stack:** Rust 2021, Clap, serde/serde_json, chrono workspace dependency, Ratatui, POSIX shell certification script, cargo tests. + +## Global Constraints + +- Preserve existing `metrics.json` compatibility while adding richer evidence indexes beside it. +- TUI reads existing evidence by default. +- TUI evidence refresh actions require explicit confirmation. +- Do not add a daemon, background recorder, hidden proof runner, hidden durable memory writer, or background transcript capture. +- Do not change the SQLite schema or public JSONL memory schema. +- Do not make core memory logic depend on Codex, Claude Code, OpenCode, Goose, Pi, Agent Zero, or any other harness. +- Do not replace the current certification metrics format. +- Do not claim compatibility unless a local evidence producer generated a pass, fail, or skip record. +- Do not mutate third-party harness configuration by default. +- Do not implement recall-quality diagnostics in this phase. +- Do not implement `tree-ring integrations link` in this phase. +- Keep Tree Ring framework-agnostic: no Agent Zero core changes, no Codex-only assumptions, and no automatic global harness writes. +- Run `cargo fmt --check`, `cargo test --locked`, `cargo clippy --locked --all-targets`, `git diff --check`, and `sh scripts/certify-tree-ring.sh` before PR handoff. + +--- + +## Scope Check + +This plan implements Evidence Spine Phase 2 only: deterministic non-mutating harness probe evidence for Codex, Claude Code, OpenCode, Goose, Pi, and Agent Zero/A0. It does not implement recall-quality evidence, integration linking, vector search, daemon behavior, background capture, global harness configuration writes, or Agent Zero core changes. + +## File Structure + +- Create `crates/tree-ring-memory-cli/src/harness_evidence.rs`: harness probe records, status rules, record writers, and evidence-index merge logic. +- Modify `crates/tree-ring-memory-cli/src/main.rs`: add `tree-ring integrations certify` and print human/JSON reports. +- Modify `crates/tree-ring-memory-cli/Cargo.toml`: add `chrono.workspace = true` for Rust-side evidence timestamps. +- Modify `scripts/certify-tree-ring.sh`: run the new harness certification producer against temporary markers and merge its records into the repo certification index. +- Modify `crates/tree-ring-memory-cli/src/tui/render.rs`: render per-harness evidence status/path rows from the index. +- Modify `docs/architecture/rust-core-status.md` and `README.md`: document the new proof command and evidence artifacts after implementation. + +--- + +### Task 1: Add Harness Evidence Producer + +**Files:** +- Create: `crates/tree-ring-memory-cli/src/harness_evidence.rs` +- Modify: `crates/tree-ring-memory-cli/src/main.rs` +- Modify: `crates/tree-ring-memory-cli/Cargo.toml` + +**Interfaces:** +- Consumes: `integrations::scan_integrations(root: &Path) -> IntegrationScanReport` +- Consumes: `evidence::EvidenceIndex`, `EvidenceRecordRef`, `EvidenceStatus` +- Produces: `harness_evidence::HarnessCertificationRequest` +- Produces: `harness_evidence::HarnessCertificationReport` +- Produces: `harness_evidence::HarnessProbeRecord` +- Produces: `harness_evidence::certify_harnesses(request: HarnessCertificationRequest) -> Result` +- Produces record files under `/harness/.json` +- Produces or updates `/evidence-index.json` + +- [ ] **Step 1: Add failing harness evidence tests** + +Create `crates/tree-ring-memory-cli/src/harness_evidence.rs` with the module skeleton and these tests: + +```rust +use crate::evidence::{certification_dir_for_project, EvidenceRecordRef, EvidenceStatus}; +use crate::integrations::{scan_integrations, IntegrationMarker, MarkerOrigin}; +use chrono::{SecondsFormat, Utc}; +use serde::{Deserialize, Serialize}; +use std::collections::BTreeMap; +use std::fs; +use std::path::{Path, PathBuf}; + +pub const CERTIFIED_HARNESS_IDS: &[&str] = &[ + "codex", + "claude-code", + "opencode", + "goose", + "pi", + "agent-zero", +]; + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct HarnessCertificationRequest { + pub source_root: PathBuf, + pub evidence_dir: PathBuf, +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct HarnessCertificationReport { + pub generated_at: String, + pub source_root: PathBuf, + pub evidence_dir: PathBuf, + pub index_path: PathBuf, + pub pass_count: usize, + pub fail_count: usize, + pub skip_count: usize, + pub records: Vec, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct HarnessProbeRecord { + pub schema_version: u8, + pub harness_id: String, + pub name: String, + pub status: EvidenceStatus, + pub generated_at: String, + pub source_root: PathBuf, + pub command: String, + pub markers: Vec, + pub guidance: HarnessGuidanceEvidence, + pub summary: String, + pub next_step: String, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct HarnessProbeMarker { + pub path: String, + pub origin: String, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct HarnessGuidanceEvidence { + pub agents_md: Option, + pub skill_md: Option, + pub cli_md: Option, + pub recall_guidance: bool, + pub remember_guidance: bool, +} + +pub fn certify_harnesses( + _request: HarnessCertificationRequest, +) -> Result { + Err("harness certification producer is still in the red phase".to_string()) +} + +#[cfg(test)] +mod tests { + use super::*; + use tempfile::tempdir; + + #[test] + fn harness_certification_skips_absent_project_markers_and_indexes_records() { + let dir = tempdir().unwrap(); + let evidence_dir = certification_dir_for_project(dir.path()); + + let report = certify_harnesses(HarnessCertificationRequest { + source_root: dir.path().to_path_buf(), + evidence_dir: evidence_dir.clone(), + }) + .unwrap(); + + assert_eq!(report.records.len(), CERTIFIED_HARNESS_IDS.len()); + assert_eq!(report.pass_count, 0); + assert_eq!(report.fail_count, 0); + assert_eq!(report.skip_count, CERTIFIED_HARNESS_IDS.len()); + assert!(evidence_dir.join("harness/codex.json").exists()); + let index = std::fs::read_to_string(evidence_dir.join("evidence-index.json")).unwrap(); + assert!(index.contains("\"harness\"")); + assert!(index.contains("\"codex\"")); + assert!(index.contains("\"status\":\"skip\"")); + assert!(!dir.path().join(".codex/generated-by-certify").exists()); + } + + #[test] + fn harness_certification_passes_project_marker_with_generated_guidance() { + let dir = tempdir().unwrap(); + std::fs::create_dir_all(dir.path().join(".codex")).unwrap(); + std::fs::create_dir_all(dir.path().join(".tree-ring")).unwrap(); + std::fs::write( + dir.path().join(".tree-ring/SKILL.md"), + "Use `tree-ring recall` before acting and `tree-ring remember` for durable facts.", + ) + .unwrap(); + std::fs::write( + dir.path().join(".tree-ring/CLI.md"), + "`tree-ring recall` and `tree-ring remember` are the portable command surface.", + ) + .unwrap(); + std::fs::write( + dir.path().join(".tree-ring/AGENTS.md"), + "Project guidance delegates to SKILL.md and CLI.md.", + ) + .unwrap(); + let evidence_dir = certification_dir_for_project(dir.path()); + + let report = certify_harnesses(HarnessCertificationRequest { + source_root: dir.path().to_path_buf(), + evidence_dir: evidence_dir.clone(), + }) + .unwrap(); + + let codex = report + .records + .iter() + .find(|record| record.harness_id == "codex") + .unwrap(); + assert_eq!(codex.status, EvidenceStatus::Pass); + assert!(codex.summary.contains("project marker")); + assert!(codex.guidance.recall_guidance); + assert!(codex.guidance.remember_guidance); + assert!(evidence_dir.join("harness/codex.json").exists()); + } + + #[test] + fn harness_certification_fails_project_marker_without_generated_guidance() { + let dir = tempdir().unwrap(); + std::fs::write(dir.path().join("CLAUDE.md"), "# Claude instructions").unwrap(); + let evidence_dir = certification_dir_for_project(dir.path()); + + let report = certify_harnesses(HarnessCertificationRequest { + source_root: dir.path().to_path_buf(), + evidence_dir, + }) + .unwrap(); + + let claude = report + .records + .iter() + .find(|record| record.harness_id == "claude-code") + .unwrap(); + assert_eq!(claude.status, EvidenceStatus::Fail); + assert!(claude.summary.contains("missing generated Tree Ring guidance")); + assert!(claude.next_step.contains("tree-ring init")); + } + + #[test] + fn harness_certification_preserves_existing_certification_index_entry() { + let dir = tempdir().unwrap(); + std::fs::create_dir_all(dir.path().join(".codex")).unwrap(); + let evidence_dir = certification_dir_for_project(dir.path()); + std::fs::create_dir_all(&evidence_dir).unwrap(); + std::fs::write( + evidence_dir.join("metrics.json"), + r#"{"ok":true,"created_at":"2026-07-09T05:44:48Z"}"#, + ) + .unwrap(); + std::fs::write( + evidence_dir.join("evidence-index.json"), + r#"{ + "generated_at": "2026-07-09T05:44:48Z", + "overall_status": "pass", + "certification": { + "category": "certification", + "status": "pass", + "label": "Local certification", + "path": "metrics.json", + "summary_path": "summary.md", + "generated_at": "2026-07-09T05:44:48Z" + }, + "harness": {}, + "recall_quality": null, + "missing": ["harness", "recall_quality"], + "stale": [] + }"#, + ) + .unwrap(); + + certify_harnesses(HarnessCertificationRequest { + source_root: dir.path().to_path_buf(), + evidence_dir: evidence_dir.clone(), + }) + .unwrap(); + + let index = std::fs::read_to_string(evidence_dir.join("evidence-index.json")).unwrap(); + assert!(index.contains("\"certification\"")); + assert!(index.contains("\"metrics.json\"")); + assert!(index.contains("\"harness/codex.json\"")); + assert!(!index.contains("\"harness\", \"recall_quality\"")); + } +} +``` + +Run: + +```bash +cargo test -p tree-ring-memory-cli harness_certification --locked +``` + +Expected: FAIL because the producer returns the red-phase error and the module is not declared. + +- [ ] **Step 2: Add module declaration and chrono dependency** + +Modify `crates/tree-ring-memory-cli/src/main.rs` module declarations: + +```rust +mod actions; +mod agent_awareness; +mod commands; +mod evidence; +mod harness_evidence; +mod integrations; +mod ring_mark; +mod tui; +mod welcome; +``` + +Modify `crates/tree-ring-memory-cli/Cargo.toml` dependencies: + +```toml +chrono.workspace = true +``` + +- [ ] **Step 3: Implement harness evidence status rules** + +Replace the red-phase `certify_harnesses` implementation with these helper functions and logic: + +```rust +pub fn certify_harnesses( + request: HarnessCertificationRequest, +) -> Result { + let generated_at = Utc::now().to_rfc3339_opts(SecondsFormat::Secs, true); + let report = scan_integrations(&request.source_root); + let guidance = inspect_guidance(&request.source_root); + let harness_dir = request.evidence_dir.join("harness"); + fs::create_dir_all(&harness_dir).map_err(|err| err.to_string())?; + + let mut records = Vec::new(); + for harness_id in CERTIFIED_HARNESS_IDS { + let integration = report + .integrations + .iter() + .find(|integration| integration.id == *harness_id) + .ok_or_else(|| format!("missing integration definition for {harness_id}"))?; + let record = probe_record(integration, &request.source_root, &generated_at, &guidance); + let path = harness_dir.join(format!("{harness_id}.json")); + let json = serde_json::to_string_pretty(&record).map_err(|err| err.to_string())?; + fs::write(&path, json).map_err(|err| err.to_string())?; + records.push(record); + } + + let index_path = merge_harness_index(&request.evidence_dir, &generated_at, &records)?; + let pass_count = records + .iter() + .filter(|record| record.status == EvidenceStatus::Pass) + .count(); + let fail_count = records + .iter() + .filter(|record| record.status == EvidenceStatus::Fail) + .count(); + let skip_count = records + .iter() + .filter(|record| record.status == EvidenceStatus::Skip) + .count(); + + Ok(HarnessCertificationReport { + generated_at, + source_root: request.source_root, + evidence_dir: request.evidence_dir, + index_path, + pass_count, + fail_count, + skip_count, + records, + }) +} + +fn probe_record( + integration: &crate::integrations::AgentIntegration, + source_root: &Path, + generated_at: &str, + guidance: &HarnessGuidanceEvidence, +) -> HarnessProbeRecord { + let project_marker = integration + .markers + .iter() + .any(|marker| marker.origin == MarkerOrigin::Project); + let home_marker = integration + .markers + .iter() + .any(|marker| marker.origin == MarkerOrigin::Home); + let guidance_ready = guidance.recall_guidance && guidance.remember_guidance; + let (status, summary, next_step) = if project_marker && guidance_ready { + ( + EvidenceStatus::Pass, + format!( + "{} has a project marker and generated Tree Ring recall/remember guidance.", + integration.name + ), + integration.next_step.to_string(), + ) + } else if project_marker { + ( + EvidenceStatus::Fail, + format!( + "{} has a project marker but is missing generated Tree Ring guidance.", + integration.name + ), + "Run `tree-ring init`, then reference `.tree-ring/SKILL.md` and `.tree-ring/CLI.md` from the harness project instructions.".to_string(), + ) + } else if home_marker { + ( + EvidenceStatus::Skip, + format!( + "{} only has user-home markers; this project is not certified for that harness.", + integration.name + ), + "Add a project-level harness marker or project instruction file, then rerun `tree-ring integrations certify`.".to_string(), + ) + } else { + ( + EvidenceStatus::Skip, + format!( + "{} was not detected for this project, so no compatibility claim is made.", + integration.name + ), + integration.next_step.to_string(), + ) + }; + + HarnessProbeRecord { + schema_version: 1, + harness_id: integration.id.to_string(), + name: integration.name.to_string(), + status, + generated_at: generated_at.to_string(), + source_root: source_root.to_path_buf(), + command: format!( + "tree-ring integrations certify --source-root {}", + shell_display(source_root) + ), + markers: integration.markers.iter().map(marker_from_scan).collect(), + guidance: guidance.clone(), + summary, + next_step, + } +} + +fn inspect_guidance(source_root: &Path) -> HarnessGuidanceEvidence { + let agents_md = existing_path(source_root.join(".tree-ring/AGENTS.md")); + let skill_md = existing_path(source_root.join(".tree-ring/SKILL.md")); + let cli_md = existing_path(source_root.join(".tree-ring/CLI.md")); + let combined = [agents_md.as_ref(), skill_md.as_ref(), cli_md.as_ref()] + .into_iter() + .flatten() + .filter_map(|path| fs::read_to_string(path).ok()) + .collect::>() + .join("\n"); + HarnessGuidanceEvidence { + agents_md, + skill_md, + cli_md, + recall_guidance: combined.contains("tree-ring recall"), + remember_guidance: combined.contains("tree-ring remember"), + } +} + +fn existing_path(path: PathBuf) -> Option { + path.exists().then_some(path) +} + +fn marker_from_scan(marker: &IntegrationMarker) -> HarnessProbeMarker { + HarnessProbeMarker { + path: marker.path.clone(), + origin: marker.origin.as_str().to_string(), + } +} + +fn shell_display(path: &Path) -> String { + path.display().to_string() +} +``` + +- [ ] **Step 4: Implement evidence-index merge** + +Add this merge logic to `harness_evidence.rs`: + +```rust +fn merge_harness_index( + evidence_dir: &Path, + generated_at: &str, + records: &[HarnessProbeRecord], +) -> Result { + fs::create_dir_all(evidence_dir).map_err(|err| err.to_string())?; + let index_path = evidence_dir.join("evidence-index.json"); + let mut index = read_or_create_index(evidence_dir, generated_at)?; + index.generated_at = generated_at.to_string(); + index.harness = records + .iter() + .map(|record| { + ( + record.harness_id.clone(), + EvidenceRecordRef { + category: "harness".to_string(), + status: record.status, + label: record.name.clone(), + path: PathBuf::from(format!("harness/{}.json", record.harness_id)), + summary_path: None, + generated_at: record.generated_at.clone(), + }, + ) + }) + .collect::>(); + index.missing.retain(|item| item != "harness"); + if index.recall_quality.is_none() && !index.missing.iter().any(|item| item == "recall_quality") { + index.missing.push("recall_quality".to_string()); + } + index.missing.sort(); + index.missing.dedup(); + index.overall_status = rollup_status(&index); + let json = serde_json::to_string_pretty(&index).map_err(|err| err.to_string())?; + fs::write(&index_path, json).map_err(|err| err.to_string())?; + Ok(index_path) +} + +fn read_or_create_index(evidence_dir: &Path, generated_at: &str) -> Result { + let index_path = evidence_dir.join("evidence-index.json"); + if index_path.exists() { + let input = fs::read_to_string(&index_path).map_err(|err| err.to_string())?; + return serde_json::from_str(&input).map_err(|err| err.to_string()); + } + Ok(crate::evidence::EvidenceIndex { + generated_at: generated_at.to_string(), + overall_status: EvidenceStatus::Missing, + certification: certification_record_from_metrics(evidence_dir, generated_at), + harness: BTreeMap::new(), + recall_quality: None, + missing: vec!["recall_quality".to_string()], + stale: Vec::new(), + }) +} + +fn certification_record_from_metrics( + evidence_dir: &Path, + generated_at: &str, +) -> Option { + let metrics_path = evidence_dir.join("metrics.json"); + if !metrics_path.exists() { + return None; + } + let summary_path = evidence_dir.join("summary.md"); + Some(EvidenceRecordRef { + category: "certification".to_string(), + status: EvidenceStatus::Pass, + label: "Local certification".to_string(), + path: PathBuf::from("metrics.json"), + summary_path: summary_path.exists().then_some(PathBuf::from("summary.md")), + generated_at: generated_at.to_string(), + }) +} + +fn rollup_status(index: &crate::evidence::EvidenceIndex) -> EvidenceStatus { + if index.harness.values().any(|record| record.status == EvidenceStatus::Fail) { + return EvidenceStatus::Fail; + } + if index.harness.values().any(|record| record.status == EvidenceStatus::Error) { + return EvidenceStatus::Error; + } + if index.harness.values().any(|record| record.status == EvidenceStatus::Skip) { + return EvidenceStatus::Skip; + } + if let Some(certification) = &index.certification { + return certification.status; + } + if index.harness.is_empty() { + EvidenceStatus::Missing + } else { + EvidenceStatus::Pass + } +} +``` + +Run: + +```bash +cargo test -p tree-ring-memory-cli harness_certification --locked +cargo fmt --check +``` + +Expected: PASS for harness certification tests and formatter. + +- [ ] **Step 5: Commit Task 1** + +Run: + +```bash +git add crates/tree-ring-memory-cli/Cargo.toml crates/tree-ring-memory-cli/src/main.rs crates/tree-ring-memory-cli/src/harness_evidence.rs +git commit -m "Add harness evidence producer" +``` + +--- + +### Task 2: Add `integrations certify` CLI Command + +**Files:** +- Modify: `crates/tree-ring-memory-cli/src/main.rs` + +**Interfaces:** +- Consumes: `harness_evidence::certify_harnesses` +- Produces: `tree-ring integrations certify --source-root [--out-dir ]` +- Produces JSON output shape `{"ok":true,"report":HarnessCertificationReport}` when `--json` is set + +- [ ] **Step 1: Add failing CLI tests** + +Add these tests to the existing `#[cfg(test)] mod tests` in `crates/tree-ring-memory-cli/src/main.rs`: + +```rust +#[test] +fn integrations_certify_writes_harness_evidence_without_memory_store() { + let dir = tempdir().unwrap(); + fs::create_dir_all(dir.path().join(".codex")).unwrap(); + fs::create_dir_all(dir.path().join(".tree-ring")).unwrap(); + fs::write( + dir.path().join(".tree-ring/SKILL.md"), + "Use `tree-ring recall` and `tree-ring remember`.", + ) + .unwrap(); + fs::write( + dir.path().join(".tree-ring/CLI.md"), + "`tree-ring recall` and `tree-ring remember` are available.", + ) + .unwrap(); + let root = dir.path().join(".tree-ring-memory"); + let out_dir = dir.path().join("proof"); + + run(Cli::parse_from([ + "tree-ring", + "--root", + root.to_str().unwrap(), + "--json", + "integrations", + "certify", + "--source-root", + dir.path().to_str().unwrap(), + "--out-dir", + out_dir.to_str().unwrap(), + ])) + .unwrap(); + + assert!(!root.join("memory.sqlite").exists()); + assert!(out_dir.join("harness/codex.json").exists()); + let index = fs::read_to_string(out_dir.join("evidence-index.json")).unwrap(); + assert!(index.contains("\"codex\"")); + assert!(index.contains("\"status\":\"pass\"")); +} + +#[test] +fn integrations_certify_defaults_to_project_certification_dir() { + let dir = tempdir().unwrap(); + + run(Cli::parse_from([ + "tree-ring", + "integrations", + "certify", + "--source-root", + dir.path().to_str().unwrap(), + ])) + .unwrap(); + + assert!(dir + .path() + .join("target/tree-ring-certification/harness/codex.json") + .exists()); +} +``` + +Run: + +```bash +cargo test -p tree-ring-memory-cli integrations_certify --locked +``` + +Expected: FAIL because `IntegrationCommand::Certify` does not exist. + +- [ ] **Step 2: Add the CLI variant** + +Modify `IntegrationCommand` in `main.rs`: + +```rust +#[derive(Debug, Subcommand)] +enum IntegrationCommand { + #[command(about = "scan a project root for known agent-framework markers")] + Scan { + #[arg(long, default_value = ".", help = "project root to scan")] + source_root: PathBuf, + }, + #[command(about = "write non-mutating harness certification evidence")] + Certify { + #[arg(long, default_value = ".", help = "project root to certify")] + source_root: PathBuf, + #[arg( + long, + help = "evidence output directory; defaults to /target/tree-ring-certification" + )] + out_dir: Option, + }, +} +``` + +- [ ] **Step 3: Route `integrations certify` before opening the store** + +Add imports near the existing integration imports: + +```rust +use harness_evidence::{certify_harnesses, HarnessCertificationReport, HarnessCertificationRequest}; +``` + +Add this branch in `run` immediately after the existing `integrations scan` early return: + +```rust +if let Command::Integrations { + command: + IntegrationCommand::Certify { + source_root, + out_dir, + }, +} = &cli.command +{ + let evidence_dir = out_dir + .clone() + .unwrap_or_else(|| evidence::certification_dir_for_project(source_root)); + let report = certify_harnesses(HarnessCertificationRequest { + source_root: source_root.clone(), + evidence_dir, + })?; + print_harness_certification_report(&report, cli.json)?; + return Ok(()); +} +``` + +Add this match arm in the final `match cli.command` unreachable section: + +```rust +Command::Integrations { .. } => { + unreachable!("integrations commands return before opening the scriptable store") +} +``` + +Replace the existing `integrations scan returns before opening the scriptable store` text with the generic text above. + +- [ ] **Step 4: Add report printing** + +Add this helper near `print_integration_report`: + +```rust +fn print_harness_certification_report( + report: &HarnessCertificationReport, + json_output: bool, +) -> Result<(), String> { + if json_output { + println!( + "{}", + json!({ + "ok": true, + "report": report, + }) + ); + } else { + println!( + "Tree Ring Memory harness certification: pass={} fail={} skip={} evidence={}", + report.pass_count, + report.fail_count, + report.skip_count, + report.evidence_dir.display() + ); + for record in &report.records { + println!( + "{} [{}] {}", + record.name, + record.status.as_str(), + record.summary + ); + println!(" next: {}", record.next_step); + } + } + Ok(()) +} +``` + +- [ ] **Step 5: Run focused command tests** + +Run: + +```bash +cargo test -p tree-ring-memory-cli integrations_certify --locked +cargo test -p tree-ring-memory-cli harness_certification --locked +``` + +Expected: PASS. + +- [ ] **Step 6: Commit Task 2** + +Run: + +```bash +git add crates/tree-ring-memory-cli/src/main.rs +git commit -m "Add harness certification CLI" +``` + +--- + +### Task 3: Run Harness Certification From The Repo Certification Script + +**Files:** +- Modify: `scripts/certify-tree-ring.sh` + +**Interfaces:** +- Consumes: `tree-ring integrations certify --source-root "$scan_root" --out-dir "$OUT_DIR"` +- Produces: `target/tree-ring-certification/harness/*.json` +- Updates: `target/tree-ring-certification/evidence-index.json` with harness record refs + +- [ ] **Step 1: Add harness markers and generated guidance to the certification scan root** + +In `scripts/certify-tree-ring.sh`, keep the existing `scan_root` and `scan_home` setup, then add generated guidance files before the existing integration scan: + +```sh +mkdir -p "$scan_root/.tree-ring" +cat > "$scan_root/.tree-ring/SKILL.md" <<'EOF' +Use `tree-ring recall` before acting on project assumptions. +Use `tree-ring remember` only for durable, non-secret project facts. +EOF +cat > "$scan_root/.tree-ring/CLI.md" <<'EOF' +The portable command surface is `tree-ring recall` and `tree-ring remember`. +EOF +cat > "$scan_root/.tree-ring/AGENTS.md" <<'EOF' +Project harnesses should reference SKILL.md and CLI.md for Tree Ring Memory. +EOF +``` + +- [ ] **Step 2: Run the harness certification producer after the initial evidence index is written** + +Move the existing `cat > "$INDEX" < "$OUT_DIR/harness-certification.json" +require_file "$OUT_DIR/harness/codex.json" +require_file "$OUT_DIR/harness/claude-code.json" +require_file "$OUT_DIR/harness/opencode.json" +require_file "$OUT_DIR/harness/goose.json" +require_file "$OUT_DIR/harness/pi.json" +require_file "$OUT_DIR/harness/agent-zero.json" +grep -F '"harness"' "$INDEX" > /dev/null \ + || fail "evidence index did not include harness records" +grep -F '"codex"' "$INDEX" > /dev/null \ + || fail "evidence index did not include Codex harness record" +``` + +Keep this call before `log "certification passed"`. + +- [ ] **Step 3: Print the harness evidence path** + +At the bottom of the script, after: + +```sh +printf 'Evidence index: %s\n' "$INDEX" +``` + +add: + +```sh +printf 'Harness evidence: %s\n' "$OUT_DIR/harness" +``` + +- [ ] **Step 4: Run script checks** + +Run: + +```bash +sh -n scripts/certify-tree-ring.sh +cargo test -p tree-ring-memory-cli harness_certification --locked +sh scripts/certify-tree-ring.sh +test -f target/tree-ring-certification/harness/codex.json +grep -F '"codex"' target/tree-ring-certification/evidence-index.json +``` + +Expected: shell syntax passes, focused tests pass, certification passes, `harness/codex.json` exists, and `evidence-index.json` contains a `codex` harness entry. + +- [ ] **Step 5: Commit Task 3** + +Run: + +```bash +git add scripts/certify-tree-ring.sh +git commit -m "Write harness evidence during certification" +``` + +--- + +### Task 4: Render Harness Evidence In `/evidence` + +**Files:** +- Modify: `crates/tree-ring-memory-cli/src/tui/render.rs` + +**Interfaces:** +- Consumes: `EvidenceSnapshot.index.harness: BTreeMap` +- Renders: per-harness status and relative evidence path + +- [ ] **Step 1: Add failing render test** + +Add this test to `crates/tree-ring-memory-cli/src/tui/render.rs`: + +```rust +#[test] +fn render_evidence_mode_shows_harness_matrix_records() { + let dir = tempdir().unwrap(); + let evidence_dir = dir.path().join("target/tree-ring-certification"); + std::fs::create_dir_all(evidence_dir.join("harness")).unwrap(); + std::fs::write(evidence_dir.join("summary.md"), "# Summary\n").unwrap(); + std::fs::write( + evidence_dir.join("metrics.json"), + r#"{"ok":true,"created_at":"2026-07-09T05:44:48Z"}"#, + ) + .unwrap(); + std::fs::write(evidence_dir.join("harness/codex.json"), "{}").unwrap(); + std::fs::write(evidence_dir.join("harness/claude-code.json"), "{}").unwrap(); + std::fs::write( + evidence_dir.join("evidence-index.json"), + r#"{ + "generated_at": "2026-07-09T05:44:48Z", + "overall_status": "fail", + "certification": { + "category": "certification", + "status": "pass", + "label": "Local certification", + "path": "metrics.json", + "summary_path": "summary.md", + "generated_at": "2026-07-09T05:44:48Z" + }, + "harness": { + "codex": { + "category": "harness", + "status": "pass", + "label": "Codex", + "path": "harness/codex.json", + "summary_path": null, + "generated_at": "2026-07-09T05:44:48Z" + }, + "claude-code": { + "category": "harness", + "status": "fail", + "label": "Claude Code", + "path": "harness/claude-code.json", + "summary_path": null, + "generated_at": "2026-07-09T05:44:48Z" + } + }, + "recall_quality": null, + "missing": ["recall_quality"], + "stale": [] + }"#, + ) + .unwrap(); + let mut app = App::new(dir.path().join(".tree-ring"), None).unwrap(); + app.execute_slash_command("/evidence").unwrap(); + let backend = TestBackend::new(120, 36); + let mut terminal = Terminal::new(backend).unwrap(); + + terminal.draw(|frame| render(frame, &app)).unwrap(); + let output = terminal.backend().to_string(); + + assert!(output.contains("Codex")); + assert!(output.contains("pass")); + assert!(output.contains("Claude Code")); + assert!(output.contains("fail")); + assert!(output.contains("harness/codex.json")); +} +``` + +Run: + +```bash +cargo test -p tree-ring-memory-cli render_evidence_mode_shows_harness_matrix_records --locked +``` + +Expected: FAIL because the current renderer only shows `Harness probes loaded`. + +- [ ] **Step 2: Render per-harness rows in the Evidence list** + +Update `render_evidence_list` so the harness section expands records when `index.harness` is non-empty: + +```rust +if let Some(index) = snapshot.index.as_ref() { + if index.harness.is_empty() { + rows.push(ListItem::new(Line::from(vec![ + Span::styled(" ", theme::dim()), + Span::styled("Harness probes", theme::dim()), + Span::styled(harness_status, theme::dim()), + ]))); + } else { + for record in index.harness.values().take(6) { + rows.push(ListItem::new(Line::from(vec![ + Span::styled(" ", theme::dim()), + Span::styled(format!("{:<18}", record.label), theme::selected()), + Span::styled(format!(" {}", record.status.as_str()), theme::dim()), + ]))); + } + } +} +``` + +Keep the existing recall-quality row. + +- [ ] **Step 3: Render harness paths in the Evidence detail pane** + +In `render_evidence_detail`, after certification metrics/path lines and before the actions line, add: + +```rust +if let Some(index) = snapshot.index.as_ref() { + if !index.harness.is_empty() { + lines.push(Line::from("")); + lines.push(Line::from(Span::styled("Harness matrix", theme::brand()))); + for record in index.harness.values().take(6) { + lines.push(Line::from(format!( + "{} {} {}", + record.label, + record.status.as_str(), + record.path.display() + ))); + } + } +} +``` + +- [ ] **Step 4: Run focused render tests** + +Run: + +```bash +cargo test -p tree-ring-memory-cli render_evidence_mode --locked +``` + +Expected: PASS with the existing evidence render tests and the new harness matrix render test. + +- [ ] **Step 5: Commit Task 4** + +Run: + +```bash +git add crates/tree-ring-memory-cli/src/tui/render.rs +git commit -m "Render harness evidence matrix" +``` + +--- + +### Task 5: Document Harness Certification And Verify + +**Files:** +- Modify: `README.md` +- Modify: `docs/architecture/rust-core-status.md` + +**Interfaces:** +- Consumes: `tree-ring integrations certify` +- Consumes: `target/tree-ring-certification/harness/*.json` +- Produces: PR-ready final verification evidence + +- [ ] **Step 1: Update README command coverage** + +In `README.md`, near the existing `integrations scan` command documentation, add: + +```markdown +tree-ring integrations certify --source-root . +``` + +Add this concise behavior note near the integration-scan explanation: + +```markdown +- `integrations certify` writes non-mutating harness evidence under + `target/tree-ring-certification/harness/` and updates + `target/tree-ring-certification/evidence-index.json`. Pass, fail, and skip + states are evidence records, not broad compatibility claims. +``` + +- [ ] **Step 2: Update architecture status** + +In `docs/architecture/rust-core-status.md`, update the certification/TUI bullets to include: + +```markdown +- `tree-ring integrations certify` turns integration-scan markers into + non-mutating harness evidence records for Codex, Claude Code, OpenCode, + Goose, Pi, and Agent Zero/A0. Records live under + `target/tree-ring-certification/harness/` and are indexed by + `evidence-index.json`; skip states are explicit and are not counted as + compatibility passes. +``` + +- [ ] **Step 3: Run full verification** + +Run: + +```bash +cargo fmt --check +cargo test --locked +cargo clippy --locked --all-targets +git diff --check +sh scripts/certify-tree-ring.sh +``` + +Expected: all pass. + +- [ ] **Step 4: Inspect generated harness evidence** + +Run: + +```bash +test -f target/tree-ring-certification/harness/codex.json +test -f target/tree-ring-certification/harness/claude-code.json +test -f target/tree-ring-certification/harness/opencode.json +test -f target/tree-ring-certification/harness/goose.json +test -f target/tree-ring-certification/harness/pi.json +test -f target/tree-ring-certification/harness/agent-zero.json +grep -F '"codex"' target/tree-ring-certification/evidence-index.json +grep -F '"recall_quality"' target/tree-ring-certification/evidence-index.json +``` + +Expected: all harness evidence files exist, `evidence-index.json` contains harness entries, and `recall_quality` remains present as the missing follow-up category. + +- [ ] **Step 5: Commit Task 5** + +Run: + +```bash +git add README.md docs/architecture/rust-core-status.md +git commit -m "Document harness certification matrix" +``` + +--- + +## Plan Self-Review + +- Spec coverage: Task 1 creates non-mutating harness evidence producers for the Phase 2 harness set. Task 2 exposes the producer as a repeatable command. Task 3 runs it from certification and updates the evidence index. Task 4 surfaces per-harness status/path in `/evidence`. Task 5 documents and verifies the workflow. +- Scope check: Recall-quality diagnostics, integration linking, daemon/background behavior, global harness writes, and Agent Zero core modifications are excluded. +- Type consistency: `HarnessCertificationRequest`, `HarnessCertificationReport`, `HarnessProbeRecord`, `HarnessGuidanceEvidence`, and `certify_harnesses` are defined in Task 1 before CLI, script, TUI, and docs tasks consume them. +- Compatibility check: `metrics.json` remains unchanged; harness proof is added through `harness/*.json` plus `evidence-index.json` harness refs. +- Truthfulness check: skip states are explicit records, failed project markers do not become passes, and home-only markers do not certify the current project. From 02778f23fc0254a03e0ac1dc32ae018a9b85bf0d Mon Sep 17 00:00:00 2001 From: TerminallyLazy Date: Thu, 9 Jul 2026 02:31:29 -0400 Subject: [PATCH 02/12] Add harness evidence producer --- Cargo.lock | 1 + crates/tree-ring-memory-cli/Cargo.toml | 1 + .../src/harness_evidence.rs | 548 ++++++++++++++++++ crates/tree-ring-memory-cli/src/main.rs | 1 + 4 files changed, 551 insertions(+) create mode 100644 crates/tree-ring-memory-cli/src/harness_evidence.rs diff --git a/Cargo.lock b/Cargo.lock index b4c0f62..a5af8e7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1692,6 +1692,7 @@ checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109" name = "tree-ring-memory-cli" version = "0.11.0" dependencies = [ + "chrono", "clap", "ratatui", "serde", diff --git a/crates/tree-ring-memory-cli/Cargo.toml b/crates/tree-ring-memory-cli/Cargo.toml index 5852d97..c5af14a 100644 --- a/crates/tree-ring-memory-cli/Cargo.toml +++ b/crates/tree-ring-memory-cli/Cargo.toml @@ -16,6 +16,7 @@ name = "tree-ring" path = "src/main.rs" [dependencies] +chrono.workspace = true clap.workspace = true ratatui.workspace = true serde.workspace = true diff --git a/crates/tree-ring-memory-cli/src/harness_evidence.rs b/crates/tree-ring-memory-cli/src/harness_evidence.rs new file mode 100644 index 0000000..6e0e0b2 --- /dev/null +++ b/crates/tree-ring-memory-cli/src/harness_evidence.rs @@ -0,0 +1,548 @@ +use crate::evidence::{EvidenceRecordRef, EvidenceStatus}; +use crate::integrations::{scan_integrations, IntegrationMarker, MarkerOrigin}; +use chrono::{SecondsFormat, Utc}; +use serde::{Deserialize, Serialize}; +use std::collections::BTreeMap; +use std::fs; +use std::path::{Path, PathBuf}; + +pub const CERTIFIED_HARNESS_IDS: &[&str] = &[ + "codex", + "claude-code", + "opencode", + "goose", + "pi", + "agent-zero", +]; + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct HarnessCertificationRequest { + pub source_root: PathBuf, + pub evidence_dir: PathBuf, +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct HarnessCertificationReport { + pub generated_at: String, + pub source_root: PathBuf, + pub evidence_dir: PathBuf, + pub index_path: PathBuf, + pub pass_count: usize, + pub fail_count: usize, + pub skip_count: usize, + pub records: Vec, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct HarnessProbeRecord { + pub schema_version: u8, + pub harness_id: String, + pub name: String, + pub status: EvidenceStatus, + pub generated_at: String, + pub source_root: PathBuf, + pub command: String, + pub markers: Vec, + pub guidance: HarnessGuidanceEvidence, + pub summary: String, + pub next_step: String, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct HarnessProbeMarker { + pub path: String, + pub origin: String, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct HarnessGuidanceEvidence { + pub agents_md: Option, + pub skill_md: Option, + pub cli_md: Option, + pub recall_guidance: bool, + pub remember_guidance: bool, +} + +pub fn certify_harnesses( + request: HarnessCertificationRequest, +) -> Result { + let generated_at = Utc::now().to_rfc3339_opts(SecondsFormat::Secs, true); + let report = scan_integrations(&request.source_root); + let guidance = inspect_guidance(&request.source_root); + let harness_dir = request.evidence_dir.join("harness"); + fs::create_dir_all(&harness_dir).map_err(|err| err.to_string())?; + + let mut records = Vec::new(); + for harness_id in CERTIFIED_HARNESS_IDS { + let integration = report + .integrations + .iter() + .find(|integration| integration.id == *harness_id) + .ok_or_else(|| format!("missing integration definition for {harness_id}"))?; + let record = probe_record(integration, &request.source_root, &generated_at, &guidance); + let path = harness_dir.join(format!("{harness_id}.json")); + let json = serde_json::to_string_pretty(&record).map_err(|err| err.to_string())?; + fs::write(&path, json).map_err(|err| err.to_string())?; + records.push(record); + } + + let index_path = merge_harness_index(&request.evidence_dir, &generated_at, &records)?; + let pass_count = records + .iter() + .filter(|record| record.status == EvidenceStatus::Pass) + .count(); + let fail_count = records + .iter() + .filter(|record| record.status == EvidenceStatus::Fail) + .count(); + let skip_count = records + .iter() + .filter(|record| record.status == EvidenceStatus::Skip) + .count(); + + Ok(HarnessCertificationReport { + generated_at, + source_root: request.source_root, + evidence_dir: request.evidence_dir, + index_path, + pass_count, + fail_count, + skip_count, + records, + }) +} + +fn probe_record( + integration: &crate::integrations::AgentIntegration, + source_root: &Path, + generated_at: &str, + guidance: &HarnessGuidanceEvidence, +) -> HarnessProbeRecord { + let project_marker = integration + .markers + .iter() + .any(|marker| marker.origin == MarkerOrigin::Project); + let home_marker = integration + .markers + .iter() + .any(|marker| marker.origin == MarkerOrigin::Home); + let guidance_ready = guidance.recall_guidance && guidance.remember_guidance; + let (status, summary, next_step) = if project_marker && guidance_ready { + ( + EvidenceStatus::Pass, + format!( + "{} has a project marker and generated Tree Ring recall/remember guidance.", + integration.name + ), + integration.next_step.to_string(), + ) + } else if project_marker { + ( + EvidenceStatus::Fail, + format!( + "{} has a project marker but is missing generated Tree Ring guidance.", + integration.name + ), + "Run `tree-ring init`, then reference `.tree-ring/SKILL.md` and `.tree-ring/CLI.md` from the harness project instructions.".to_string(), + ) + } else if home_marker { + ( + EvidenceStatus::Skip, + format!( + "{} only has user-home markers; this project is not certified for that harness.", + integration.name + ), + "Add a project-level harness marker or project instruction file, then rerun `tree-ring integrations certify`.".to_string(), + ) + } else { + ( + EvidenceStatus::Skip, + format!( + "{} was not detected for this project, so no compatibility claim is made.", + integration.name + ), + integration.next_step.to_string(), + ) + }; + + HarnessProbeRecord { + schema_version: 1, + harness_id: integration.id.to_string(), + name: integration.name.to_string(), + status, + generated_at: generated_at.to_string(), + source_root: source_root.to_path_buf(), + command: "tree-ring integrations certify --source-root ".to_string(), + markers: integration.markers.iter().map(marker_from_scan).collect(), + guidance: guidance.clone(), + summary, + next_step, + } +} + +fn inspect_guidance(source_root: &Path) -> HarnessGuidanceEvidence { + let agents_md = existing_path(source_root.join(".tree-ring/AGENTS.md")); + let skill_md = existing_path(source_root.join(".tree-ring/SKILL.md")); + let cli_md = existing_path(source_root.join(".tree-ring/CLI.md")); + let combined = [agents_md.as_ref(), skill_md.as_ref(), cli_md.as_ref()] + .into_iter() + .flatten() + .filter_map(|path| fs::read_to_string(path).ok()) + .collect::>() + .join("\n"); + HarnessGuidanceEvidence { + agents_md, + skill_md, + cli_md, + recall_guidance: combined.contains("tree-ring recall"), + remember_guidance: combined.contains("tree-ring remember"), + } +} + +fn existing_path(path: PathBuf) -> Option { + path.exists().then_some(path) +} + +fn marker_from_scan(marker: &IntegrationMarker) -> HarnessProbeMarker { + HarnessProbeMarker { + path: marker.path.clone(), + origin: marker.origin.as_str().to_string(), + } +} + +fn merge_harness_index( + evidence_dir: &Path, + generated_at: &str, + records: &[HarnessProbeRecord], +) -> Result { + fs::create_dir_all(evidence_dir).map_err(|err| err.to_string())?; + let index_path = evidence_dir.join("evidence-index.json"); + let mut index = read_or_create_index(evidence_dir, generated_at)?; + index.generated_at = generated_at.to_string(); + index.harness = records + .iter() + .map(|record| { + ( + record.harness_id.clone(), + EvidenceRecordRef { + category: "harness".to_string(), + status: record.status, + label: record.name.clone(), + path: PathBuf::from(format!("harness/{}.json", record.harness_id)), + summary_path: None, + generated_at: record.generated_at.clone(), + }, + ) + }) + .collect::>(); + index.missing.retain(|item| item != "harness"); + if index.recall_quality.is_none() && !index.missing.iter().any(|item| item == "recall_quality") + { + index.missing.push("recall_quality".to_string()); + } + index.missing.sort(); + index.missing.dedup(); + index.overall_status = rollup_status(&index); + let json = serde_json::to_string_pretty(&index).map_err(|err| err.to_string())?; + fs::write(&index_path, json).map_err(|err| err.to_string())?; + Ok(index_path) +} + +fn read_or_create_index( + evidence_dir: &Path, + generated_at: &str, +) -> Result { + let index_path = evidence_dir.join("evidence-index.json"); + if index_path.exists() { + let input = fs::read_to_string(&index_path).map_err(|err| err.to_string())?; + return serde_json::from_str(&input).map_err(|err| err.to_string()); + } + Ok(crate::evidence::EvidenceIndex { + generated_at: generated_at.to_string(), + overall_status: EvidenceStatus::Missing, + certification: certification_record_from_metrics(evidence_dir, generated_at), + harness: BTreeMap::new(), + recall_quality: None, + missing: vec!["recall_quality".to_string()], + stale: Vec::new(), + }) +} + +fn certification_record_from_metrics( + evidence_dir: &Path, + generated_at: &str, +) -> Option { + let metrics_path = evidence_dir.join("metrics.json"); + if !metrics_path.exists() { + return None; + } + let summary_path = evidence_dir.join("summary.md"); + Some(EvidenceRecordRef { + category: "certification".to_string(), + status: EvidenceStatus::Pass, + label: "Local certification".to_string(), + path: PathBuf::from("metrics.json"), + summary_path: summary_path.exists().then_some(PathBuf::from("summary.md")), + generated_at: generated_at.to_string(), + }) +} + +fn rollup_status(index: &crate::evidence::EvidenceIndex) -> EvidenceStatus { + if index + .harness + .values() + .any(|record| record.status == EvidenceStatus::Fail) + { + return EvidenceStatus::Fail; + } + if index + .harness + .values() + .any(|record| record.status == EvidenceStatus::Error) + { + return EvidenceStatus::Error; + } + if let Some(certification) = &index.certification { + return certification.status; + } + if index + .harness + .values() + .any(|record| record.status == EvidenceStatus::Skip) + { + return EvidenceStatus::Skip; + } + if index.harness.is_empty() { + EvidenceStatus::Missing + } else { + EvidenceStatus::Pass + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::evidence::certification_dir_for_project; + use tempfile::tempdir; + + #[test] + fn harness_certification_skips_absent_project_markers_and_indexes_records() { + let dir = tempdir().unwrap(); + let evidence_dir = certification_dir_for_project(dir.path()); + + let report = certify_harnesses(HarnessCertificationRequest { + source_root: dir.path().to_path_buf(), + evidence_dir: evidence_dir.clone(), + }) + .unwrap(); + + assert_eq!(report.records.len(), CERTIFIED_HARNESS_IDS.len()); + assert_eq!(report.pass_count, 0); + assert_eq!(report.fail_count, 0); + assert_eq!(report.skip_count, CERTIFIED_HARNESS_IDS.len()); + assert!(evidence_dir.join("harness/codex.json").exists()); + let index: crate::evidence::EvidenceIndex = serde_json::from_str( + &std::fs::read_to_string(evidence_dir.join("evidence-index.json")).unwrap(), + ) + .unwrap(); + assert!(index.harness.contains_key("codex")); + assert_eq!( + index.harness.get("codex").map(|record| record.status), + Some(EvidenceStatus::Skip) + ); + assert!(!dir.path().join(".codex/generated-by-certify").exists()); + } + + #[test] + fn harness_certification_passes_project_marker_with_generated_guidance() { + let dir = tempdir().unwrap(); + std::fs::create_dir_all(dir.path().join(".codex")).unwrap(); + std::fs::create_dir_all(dir.path().join(".tree-ring")).unwrap(); + std::fs::write( + dir.path().join(".tree-ring/SKILL.md"), + "Use `tree-ring recall` before acting and `tree-ring remember` for durable facts.", + ) + .unwrap(); + std::fs::write( + dir.path().join(".tree-ring/CLI.md"), + "`tree-ring recall` and `tree-ring remember` are the portable command surface.", + ) + .unwrap(); + std::fs::write( + dir.path().join(".tree-ring/AGENTS.md"), + "Project guidance delegates to SKILL.md and CLI.md.", + ) + .unwrap(); + let evidence_dir = certification_dir_for_project(dir.path()); + + let report = certify_harnesses(HarnessCertificationRequest { + source_root: dir.path().to_path_buf(), + evidence_dir: evidence_dir.clone(), + }) + .unwrap(); + + let codex = report + .records + .iter() + .find(|record| record.harness_id == "codex") + .unwrap(); + assert_eq!(codex.status, EvidenceStatus::Pass); + assert!(codex.summary.contains("project marker")); + assert!(codex.guidance.recall_guidance); + assert!(codex.guidance.remember_guidance); + assert!(evidence_dir.join("harness/codex.json").exists()); + } + + #[test] + fn harness_certification_fails_project_marker_without_generated_guidance() { + let dir = tempdir().unwrap(); + std::fs::write(dir.path().join("CLAUDE.md"), "# Claude instructions").unwrap(); + let evidence_dir = certification_dir_for_project(dir.path()); + + let report = certify_harnesses(HarnessCertificationRequest { + source_root: dir.path().to_path_buf(), + evidence_dir, + }) + .unwrap(); + + let claude = report + .records + .iter() + .find(|record| record.harness_id == "claude-code") + .unwrap(); + assert_eq!(claude.status, EvidenceStatus::Fail); + assert!(claude + .summary + .contains("missing generated Tree Ring guidance")); + assert!(claude.next_step.contains("tree-ring init")); + } + + #[test] + fn harness_certification_preserves_existing_certification_index_entry() { + let dir = tempdir().unwrap(); + let evidence_dir = certification_dir_for_project(dir.path()); + std::fs::create_dir_all(&evidence_dir).unwrap(); + std::fs::write( + evidence_dir.join("metrics.json"), + r#"{"ok":true,"created_at":"2026-07-09T05:44:48Z"}"#, + ) + .unwrap(); + std::fs::write( + evidence_dir.join("evidence-index.json"), + r#"{ + "generated_at": "2026-07-09T05:44:48Z", + "overall_status": "pass", + "certification": { + "category": "certification", + "status": "pass", + "label": "Local certification", + "path": "metrics.json", + "summary_path": "summary.md", + "generated_at": "2026-07-09T05:44:48Z" + }, + "harness": {}, + "recall_quality": null, + "missing": ["harness", "recall_quality"], + "stale": [] + }"#, + ) + .unwrap(); + + certify_harnesses(HarnessCertificationRequest { + source_root: dir.path().to_path_buf(), + evidence_dir: evidence_dir.clone(), + }) + .unwrap(); + + let index: crate::evidence::EvidenceIndex = serde_json::from_str( + &std::fs::read_to_string(evidence_dir.join("evidence-index.json")).unwrap(), + ) + .unwrap(); + assert!(index.certification.is_some()); + assert_eq!( + index + .certification + .as_ref() + .map(|record| record.path.clone()), + Some(PathBuf::from("metrics.json")) + ); + assert_eq!( + index.harness.get("codex").map(|record| record.path.clone()), + Some(PathBuf::from("harness/codex.json")) + ); + assert_eq!(index.missing, vec!["recall_quality".to_string()]); + assert_eq!(index.overall_status, EvidenceStatus::Pass); + } + + #[test] + fn harness_certification_home_only_marker_produces_skip_record_with_anti_overclaim_guidance() { + let generated_at = "2026-07-09T05:44:48Z"; + let source_root = Path::new("/tmp/example project"); + let guidance = HarnessGuidanceEvidence { + agents_md: None, + skill_md: None, + cli_md: None, + recall_guidance: false, + remember_guidance: false, + }; + let integration = crate::integrations::AgentIntegration { + id: "claude-code", + name: "Claude Code", + status: crate::integrations::IntegrationStatus::Detected, + confidence: 0.7, + markers: vec![IntegrationMarker { + path: "/Users/test/.claude".to_string(), + origin: MarkerOrigin::Home, + }], + next_step: "Reference `.tree-ring/SKILL.md` from `CLAUDE.md` or `.claude` project instructions.", + }; + + let record = probe_record(&integration, source_root, generated_at, &guidance); + + assert_eq!(record.status, EvidenceStatus::Skip); + assert_eq!( + record.summary, + "Claude Code only has user-home markers; this project is not certified for that harness." + ); + assert_eq!( + record.next_step, + "Add a project-level harness marker or project instruction file, then rerun `tree-ring integrations certify`." + ); + assert_eq!( + record.command, + "tree-ring integrations certify --source-root " + ); + } + + #[test] + fn harness_certification_rollup_keeps_certification_status_when_only_skips_are_present() { + let index = crate::evidence::EvidenceIndex { + generated_at: "2026-07-09T05:44:48Z".to_string(), + overall_status: EvidenceStatus::Missing, + certification: Some(EvidenceRecordRef { + category: "certification".to_string(), + status: EvidenceStatus::Pass, + label: "Local certification".to_string(), + path: PathBuf::from("metrics.json"), + summary_path: Some(PathBuf::from("summary.md")), + generated_at: "2026-07-09T05:44:48Z".to_string(), + }), + harness: BTreeMap::from([( + "codex".to_string(), + EvidenceRecordRef { + category: "harness".to_string(), + status: EvidenceStatus::Skip, + label: "Codex".to_string(), + path: PathBuf::from("harness/codex.json"), + summary_path: None, + generated_at: "2026-07-09T05:44:48Z".to_string(), + }, + )]), + recall_quality: None, + missing: vec!["recall_quality".to_string()], + stale: Vec::new(), + }; + + assert_eq!(rollup_status(&index), EvidenceStatus::Pass); + } +} diff --git a/crates/tree-ring-memory-cli/src/main.rs b/crates/tree-ring-memory-cli/src/main.rs index eb1031a..3e0a9c9 100644 --- a/crates/tree-ring-memory-cli/src/main.rs +++ b/crates/tree-ring-memory-cli/src/main.rs @@ -27,6 +27,7 @@ mod actions; mod agent_awareness; mod commands; mod evidence; +mod harness_evidence; mod integrations; mod ring_mark; mod tui; From 22d6a22308f4b52f2b0ccafc5f0dd88babd2ff95 Mon Sep 17 00:00:00 2001 From: TerminallyLazy Date: Thu, 9 Jul 2026 02:37:12 -0400 Subject: [PATCH 03/12] Keep harness-only evidence from passing certification --- .../src/harness_evidence.rs | 34 ++++++++++++++----- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/crates/tree-ring-memory-cli/src/harness_evidence.rs b/crates/tree-ring-memory-cli/src/harness_evidence.rs index 6e0e0b2..7c4915d 100644 --- a/crates/tree-ring-memory-cli/src/harness_evidence.rs +++ b/crates/tree-ring-memory-cli/src/harness_evidence.rs @@ -305,17 +305,10 @@ fn rollup_status(index: &crate::evidence::EvidenceIndex) -> EvidenceStatus { if let Some(certification) = &index.certification { return certification.status; } - if index - .harness - .values() - .any(|record| record.status == EvidenceStatus::Skip) - { - return EvidenceStatus::Skip; - } if index.harness.is_empty() { EvidenceStatus::Missing } else { - EvidenceStatus::Pass + EvidenceStatus::Skip } } @@ -545,4 +538,29 @@ mod tests { assert_eq!(rollup_status(&index), EvidenceStatus::Pass); } + + #[test] + fn harness_certification_rollup_skips_when_only_harness_passes_exist_without_certification() { + let index = crate::evidence::EvidenceIndex { + generated_at: "2026-07-09T05:44:48Z".to_string(), + overall_status: EvidenceStatus::Missing, + certification: None, + harness: BTreeMap::from([( + "codex".to_string(), + EvidenceRecordRef { + category: "harness".to_string(), + status: EvidenceStatus::Pass, + label: "Codex".to_string(), + path: PathBuf::from("harness/codex.json"), + summary_path: None, + generated_at: "2026-07-09T05:44:48Z".to_string(), + }, + )]), + recall_quality: None, + missing: vec!["recall_quality".to_string()], + stale: Vec::new(), + }; + + assert_eq!(rollup_status(&index), EvidenceStatus::Skip); + } } From 794840ca24615a071d654a4667f19f78f61a12ea Mon Sep 17 00:00:00 2001 From: TerminallyLazy Date: Thu, 9 Jul 2026 02:41:54 -0400 Subject: [PATCH 04/12] Add harness certification CLI --- crates/tree-ring-memory-cli/src/main.rs | 126 +++++++++++++++++++++++- 1 file changed, 125 insertions(+), 1 deletion(-) diff --git a/crates/tree-ring-memory-cli/src/main.rs b/crates/tree-ring-memory-cli/src/main.rs index 3e0a9c9..374d1f6 100644 --- a/crates/tree-ring-memory-cli/src/main.rs +++ b/crates/tree-ring-memory-cli/src/main.rs @@ -15,6 +15,9 @@ use actions::export_import::{ ImportActionRequest, }; use actions::integrations::{scan as integration_scan_action, IntegrationScanRequest}; +use harness_evidence::{ + certify_harnesses, HarnessCertificationReport, HarnessCertificationRequest, +}; use actions::lifecycle::{ consolidate, consolidate_dry_run_from_path, maintain, ConsolidateActionRequest, MaintainActionRequest, @@ -254,6 +257,16 @@ enum IntegrationCommand { #[arg(long, default_value = ".", help = "project root to scan")] source_root: PathBuf, }, + #[command(about = "write non-mutating harness certification evidence")] + Certify { + #[arg(long, default_value = ".", help = "project root to certify")] + source_root: PathBuf, + #[arg( + long, + help = "evidence output directory; defaults to /target/tree-ring-certification" + )] + out_dir: Option, + }, } #[derive(Debug, Clone, clap::ValueEnum)] @@ -326,6 +339,25 @@ fn run(cli: Cli) -> Result<(), String> { return Ok(()); } + if let Command::Integrations { + command: + IntegrationCommand::Certify { + source_root, + out_dir, + }, + } = &cli.command + { + let evidence_dir = out_dir + .clone() + .unwrap_or_else(|| evidence::certification_dir_for_project(source_root)); + let report = certify_harnesses(HarnessCertificationRequest { + source_root: source_root.clone(), + evidence_dir, + })?; + print_harness_certification_report(&report, cli.json)?; + return Ok(()); + } + if let Command::Tui { event_stream, tick_ms, @@ -646,7 +678,7 @@ fn run(cli: Cli) -> Result<(), String> { unreachable!("welcome returns before opening the scriptable store") } Command::Integrations { .. } => { - unreachable!("integrations scan returns before opening the scriptable store") + unreachable!("integrations commands return before opening the scriptable store") } Command::Dox { command: @@ -1002,6 +1034,39 @@ fn print_integration_report( Ok(()) } +fn print_harness_certification_report( + report: &HarnessCertificationReport, + json_output: bool, +) -> Result<(), String> { + if json_output { + println!( + "{}", + json!({ + "ok": true, + "report": report, + }) + ); + } else { + println!( + "Tree Ring Memory harness certification: pass={} fail={} skip={} evidence={}", + report.pass_count, + report.fail_count, + report.skip_count, + report.evidence_dir.display() + ); + for record in &report.records { + println!( + "{} [{}] {}", + record.name, + record.status.as_str(), + record.summary + ); + println!(" next: {}", record.next_step); + } + } + Ok(()) +} + fn print_agent_awareness_summary(report: &agent_awareness::AgentAwarenessReport) { if !report.created.is_empty() { println!("Agent awareness files created:"); @@ -1158,6 +1223,65 @@ mod tests { assert!(!root.join("memory.sqlite").exists()); } + #[test] + fn integrations_certify_writes_harness_evidence_without_memory_store() { + let dir = tempdir().unwrap(); + fs::create_dir_all(dir.path().join(".codex")).unwrap(); + fs::create_dir_all(dir.path().join(".tree-ring")).unwrap(); + fs::write( + dir.path().join(".tree-ring/SKILL.md"), + "Use `tree-ring recall` and `tree-ring remember`.", + ) + .unwrap(); + fs::write( + dir.path().join(".tree-ring/CLI.md"), + "`tree-ring recall` and `tree-ring remember` are available.", + ) + .unwrap(); + let root = dir.path().join(".tree-ring-memory"); + let out_dir = dir.path().join("proof"); + + run(Cli::parse_from([ + "tree-ring", + "--root", + root.to_str().unwrap(), + "--json", + "integrations", + "certify", + "--source-root", + dir.path().to_str().unwrap(), + "--out-dir", + out_dir.to_str().unwrap(), + ])) + .unwrap(); + + assert!(!root.join("memory.sqlite").exists()); + assert!(out_dir.join("harness/codex.json").exists()); + let index = fs::read_to_string(out_dir.join("evidence-index.json")).unwrap(); + assert!(index.contains("\"codex\"")); + let parsed: serde_json::Value = serde_json::from_str(&index).unwrap(); + assert_eq!(parsed["harness"]["codex"]["status"], "pass"); + } + + #[test] + fn integrations_certify_defaults_to_project_certification_dir() { + let dir = tempdir().unwrap(); + + run(Cli::parse_from([ + "tree-ring", + "integrations", + "certify", + "--source-root", + dir.path().to_str().unwrap(), + ])) + .unwrap(); + + assert!(dir + .path() + .join("target/tree-ring-certification/harness/codex.json") + .exists()); + } + #[test] fn evidence_promotion_becomes_heartwood_with_evidence_source() { let dir = tempdir().unwrap(); From c6bf2fb38c6aae9438d27c4e6f47cb516435670b Mon Sep 17 00:00:00 2001 From: TerminallyLazy Date: Thu, 9 Jul 2026 02:46:50 -0400 Subject: [PATCH 05/12] Test harness certification CLI output --- crates/tree-ring-memory-cli/src/main.rs | 231 ++++++++++++++++++++++-- 1 file changed, 215 insertions(+), 16 deletions(-) diff --git a/crates/tree-ring-memory-cli/src/main.rs b/crates/tree-ring-memory-cli/src/main.rs index 374d1f6..9fc1576 100644 --- a/crates/tree-ring-memory-cli/src/main.rs +++ b/crates/tree-ring-memory-cli/src/main.rs @@ -15,15 +15,15 @@ use actions::export_import::{ ImportActionRequest, }; use actions::integrations::{scan as integration_scan_action, IntegrationScanRequest}; -use harness_evidence::{ - certify_harnesses, HarnessCertificationReport, HarnessCertificationRequest, -}; use actions::lifecycle::{ consolidate, consolidate_dry_run_from_path, maintain, ConsolidateActionRequest, MaintainActionRequest, }; use actions::recall::{recall as recall_action, RecallRequest}; use actions::remember::{remember as remember_action, RememberRequest}; +use harness_evidence::{ + certify_harnesses, HarnessCertificationReport, HarnessCertificationRequest, +}; use serde_json::json; mod actions; @@ -1038,33 +1038,42 @@ fn print_harness_certification_report( report: &HarnessCertificationReport, json_output: bool, ) -> Result<(), String> { + println!( + "{}", + format_harness_certification_report(report, json_output) + ); + Ok(()) +} + +fn format_harness_certification_report( + report: &HarnessCertificationReport, + json_output: bool, +) -> String { if json_output { - println!( - "{}", - json!({ - "ok": true, - "report": report, - }) - ); + json!({ + "ok": true, + "report": report, + }) + .to_string() } else { - println!( + let mut lines = vec![format!( "Tree Ring Memory harness certification: pass={} fail={} skip={} evidence={}", report.pass_count, report.fail_count, report.skip_count, report.evidence_dir.display() - ); + )]; for record in &report.records { - println!( + lines.push(format!( "{} [{}] {}", record.name, record.status.as_str(), record.summary - ); - println!(" next: {}", record.next_step); + )); + lines.push(format!(" next: {}", record.next_step)); } + lines.join("\n") } - Ok(()) } fn print_agent_awareness_summary(report: &agent_awareness::AgentAwarenessReport) { @@ -1282,6 +1291,196 @@ mod tests { .exists()); } + #[test] + fn harness_certification_json_output_contract() { + let report = HarnessCertificationReport { + generated_at: "2026-07-09T00:00:00Z".to_string(), + source_root: PathBuf::from("/tmp/project"), + evidence_dir: PathBuf::from("/tmp/project/target/tree-ring-certification"), + index_path: PathBuf::from( + "/tmp/project/target/tree-ring-certification/evidence-index.json", + ), + pass_count: 1, + fail_count: 1, + skip_count: 1, + records: vec![ + crate::harness_evidence::HarnessProbeRecord { + schema_version: 1, + harness_id: "codex".to_string(), + name: "Codex".to_string(), + status: crate::evidence::EvidenceStatus::Pass, + generated_at: "2026-07-09T00:00:00Z".to_string(), + source_root: PathBuf::from("/tmp/project"), + command: "tree-ring integrations certify --source-root " + .to_string(), + markers: vec![crate::harness_evidence::HarnessProbeMarker { + path: ".codex".to_string(), + origin: "project".to_string(), + }], + guidance: crate::harness_evidence::HarnessGuidanceEvidence { + agents_md: None, + skill_md: Some(PathBuf::from("/tmp/project/.tree-ring/SKILL.md")), + cli_md: Some(PathBuf::from("/tmp/project/.tree-ring/CLI.md")), + recall_guidance: true, + remember_guidance: true, + }, + summary: "Codex has a project marker and generated Tree Ring recall/remember guidance.".to_string(), + next_step: "Merge the generated Tree Ring guidance into the active Codex instructions.".to_string(), + }, + crate::harness_evidence::HarnessProbeRecord { + schema_version: 1, + harness_id: "goose".to_string(), + name: "Goose".to_string(), + status: crate::evidence::EvidenceStatus::Fail, + generated_at: "2026-07-09T00:00:00Z".to_string(), + source_root: PathBuf::from("/tmp/project"), + command: "tree-ring integrations certify --source-root " + .to_string(), + markers: vec![], + guidance: crate::harness_evidence::HarnessGuidanceEvidence { + agents_md: None, + skill_md: None, + cli_md: None, + recall_guidance: false, + remember_guidance: false, + }, + summary: "Goose has a project marker but is missing generated Tree Ring guidance.".to_string(), + next_step: "Run `tree-ring init`, then reference `.tree-ring/SKILL.md` and `.tree-ring/CLI.md` from the harness project instructions.".to_string(), + }, + crate::harness_evidence::HarnessProbeRecord { + schema_version: 1, + harness_id: "pi".to_string(), + name: "PI".to_string(), + status: crate::evidence::EvidenceStatus::Skip, + generated_at: "2026-07-09T00:00:00Z".to_string(), + source_root: PathBuf::from("/tmp/project"), + command: "tree-ring integrations certify --source-root " + .to_string(), + markers: vec![], + guidance: crate::harness_evidence::HarnessGuidanceEvidence { + agents_md: None, + skill_md: None, + cli_md: None, + recall_guidance: false, + remember_guidance: false, + }, + summary: "PI was not detected for this project, so no compatibility claim is made.".to_string(), + next_step: "Add a project-level harness marker or project instruction file, then rerun `tree-ring integrations certify`.".to_string(), + }, + ], + }; + + let output = format_harness_certification_report(&report, true); + let parsed: serde_json::Value = serde_json::from_str(&output).unwrap(); + + assert_eq!(parsed["ok"], true); + assert_eq!(parsed["report"]["pass_count"], 1); + assert_eq!(parsed["report"]["fail_count"], 1); + assert_eq!(parsed["report"]["skip_count"], 1); + assert_eq!(parsed["report"]["records"][0]["harness_id"], "codex"); + assert_eq!(parsed["report"]["records"][0]["status"], "pass"); + } + + #[test] + fn harness_certification_human_output_contract() { + let evidence_dir = PathBuf::from("/tmp/project/target/tree-ring-certification"); + let report = HarnessCertificationReport { + generated_at: "2026-07-09T00:00:00Z".to_string(), + source_root: PathBuf::from("/tmp/project"), + evidence_dir: evidence_dir.clone(), + index_path: evidence_dir.join("evidence-index.json"), + pass_count: 1, + fail_count: 1, + skip_count: 1, + records: vec![ + crate::harness_evidence::HarnessProbeRecord { + schema_version: 1, + harness_id: "codex".to_string(), + name: "Codex".to_string(), + status: crate::evidence::EvidenceStatus::Pass, + generated_at: "2026-07-09T00:00:00Z".to_string(), + source_root: PathBuf::from("/tmp/project"), + command: "tree-ring integrations certify --source-root " + .to_string(), + markers: vec![], + guidance: crate::harness_evidence::HarnessGuidanceEvidence { + agents_md: None, + skill_md: Some(PathBuf::from("/tmp/project/.tree-ring/SKILL.md")), + cli_md: Some(PathBuf::from("/tmp/project/.tree-ring/CLI.md")), + recall_guidance: true, + remember_guidance: true, + }, + summary: "Codex has a project marker and generated Tree Ring recall/remember guidance.".to_string(), + next_step: "Merge the generated Tree Ring guidance into the active Codex instructions.".to_string(), + }, + crate::harness_evidence::HarnessProbeRecord { + schema_version: 1, + harness_id: "goose".to_string(), + name: "Goose".to_string(), + status: crate::evidence::EvidenceStatus::Fail, + generated_at: "2026-07-09T00:00:00Z".to_string(), + source_root: PathBuf::from("/tmp/project"), + command: "tree-ring integrations certify --source-root " + .to_string(), + markers: vec![], + guidance: crate::harness_evidence::HarnessGuidanceEvidence { + agents_md: None, + skill_md: None, + cli_md: None, + recall_guidance: false, + remember_guidance: false, + }, + summary: "Goose has a project marker but is missing generated Tree Ring guidance.".to_string(), + next_step: "Run `tree-ring init`, then reference `.tree-ring/SKILL.md` and `.tree-ring/CLI.md` from the harness project instructions.".to_string(), + }, + crate::harness_evidence::HarnessProbeRecord { + schema_version: 1, + harness_id: "pi".to_string(), + name: "PI".to_string(), + status: crate::evidence::EvidenceStatus::Skip, + generated_at: "2026-07-09T00:00:00Z".to_string(), + source_root: PathBuf::from("/tmp/project"), + command: "tree-ring integrations certify --source-root " + .to_string(), + markers: vec![], + guidance: crate::harness_evidence::HarnessGuidanceEvidence { + agents_md: None, + skill_md: None, + cli_md: None, + recall_guidance: false, + remember_guidance: false, + }, + summary: "PI was not detected for this project, so no compatibility claim is made.".to_string(), + next_step: "Add a project-level harness marker or project instruction file, then rerun `tree-ring integrations certify`.".to_string(), + }, + ], + }; + + let output = format_harness_certification_report(&report, false); + + assert!(output.contains( + "Tree Ring Memory harness certification: pass=1 fail=1 skip=1 evidence=/tmp/project/target/tree-ring-certification" + )); + assert!(output.contains( + "Codex [pass] Codex has a project marker and generated Tree Ring recall/remember guidance." + )); + assert!(output.contains( + " next: Merge the generated Tree Ring guidance into the active Codex instructions." + )); + assert!(output.contains( + "Goose [fail] Goose has a project marker but is missing generated Tree Ring guidance." + )); + assert!(output.contains( + " next: Run `tree-ring init`, then reference `.tree-ring/SKILL.md` and `.tree-ring/CLI.md` from the harness project instructions." + )); + assert!(output.contains( + "PI [skip] PI was not detected for this project, so no compatibility claim is made." + )); + assert!(output.contains( + " next: Add a project-level harness marker or project instruction file, then rerun `tree-ring integrations certify`." + )); + } + #[test] fn evidence_promotion_becomes_heartwood_with_evidence_source() { let dir = tempdir().unwrap(); From c0de4d0c5b990bb690300c207bdb0179954e0784 Mon Sep 17 00:00:00 2001 From: TerminallyLazy Date: Thu, 9 Jul 2026 02:51:38 -0400 Subject: [PATCH 06/12] Write harness evidence during certification --- scripts/certify-tree-ring.sh | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/scripts/certify-tree-ring.sh b/scripts/certify-tree-ring.sh index c01d00a..5c60de6 100755 --- a/scripts/certify-tree-ring.sh +++ b/scripts/certify-tree-ring.sh @@ -162,6 +162,17 @@ mkdir -p "$scan_root/.codex" "$scan_root/.claude" "$scan_root/usr/plugins" \ "$scan_root/revolve" "$scan_root/.opencode" "$scan_root/.goose" "$scan_home/.claude" printf '# Agent contract\n' > "$scan_root/AGENTS.md" printf '# Claude instructions\n' > "$scan_root/CLAUDE.md" +mkdir -p "$scan_root/.tree-ring" +cat > "$scan_root/.tree-ring/SKILL.md" <<'EOF' +Use `tree-ring recall` before acting on project assumptions. +Use `tree-ring remember` only for durable, non-secret project facts. +EOF +cat > "$scan_root/.tree-ring/CLI.md" <<'EOF' +The portable command surface is `tree-ring recall` and `tree-ring remember`. +EOF +cat > "$scan_root/.tree-ring/AGENTS.md" <<'EOF' +Project harnesses should reference SKILL.md and CLI.md for Tree Ring Memory. +EOF HOME="$scan_home" "$BIN" --json integrations scan --source-root "$scan_root" \ > "$OUT_DIR/integrations-scan.json" grep -F '"origin":"project"' "$OUT_DIR/integrations-scan.json" > /dev/null \ @@ -291,7 +302,21 @@ cat > "$INDEX" < "$OUT_DIR/harness-certification.json" +require_file "$OUT_DIR/harness/codex.json" +require_file "$OUT_DIR/harness/claude-code.json" +require_file "$OUT_DIR/harness/opencode.json" +require_file "$OUT_DIR/harness/goose.json" +require_file "$OUT_DIR/harness/pi.json" +require_file "$OUT_DIR/harness/agent-zero.json" +grep -F '"harness"' "$INDEX" > /dev/null \ + || fail "evidence index did not include harness records" +grep -F '"codex"' "$INDEX" > /dev/null \ + || fail "evidence index did not include Codex harness record" + log "certification passed" printf 'Summary: %s\n' "$SUMMARY" printf 'Metrics: %s\n' "$METRICS" printf 'Evidence index: %s\n' "$INDEX" +printf 'Harness evidence: %s\n' "$OUT_DIR/harness" From 9e37ba61e022166e6df6c30651576a51ba89e2d0 Mon Sep 17 00:00:00 2001 From: TerminallyLazy Date: Thu, 9 Jul 2026 03:01:08 -0400 Subject: [PATCH 07/12] Render harness evidence matrix --- crates/tree-ring-memory-cli/src/tui/render.rs | 173 +++++++++++++++--- 1 file changed, 144 insertions(+), 29 deletions(-) diff --git a/crates/tree-ring-memory-cli/src/tui/render.rs b/crates/tree-ring-memory-cli/src/tui/render.rs index 6badc65..81045f4 100644 --- a/crates/tree-ring-memory-cli/src/tui/render.rs +++ b/crates/tree-ring-memory-cli/src/tui/render.rs @@ -339,11 +339,23 @@ fn render_evidence_list(frame: &mut Frame<'_>, area: Rect, app: &App) { }) .unwrap_or((" missing", " missing")); - rows.push(ListItem::new(Line::from(vec![ - Span::styled(" ", theme::dim()), - Span::styled("Harness probes", theme::dim()), - Span::styled(harness_status, theme::dim()), - ]))); + if let Some(index) = snapshot.index.as_ref() { + if index.harness.is_empty() { + rows.push(ListItem::new(Line::from(vec![ + Span::styled(" ", theme::dim()), + Span::styled("Harness probes", theme::dim()), + Span::styled(harness_status, theme::dim()), + ]))); + } else { + for record in index.harness.values().take(6) { + rows.push(ListItem::new(Line::from(vec![ + Span::styled(" ", theme::dim()), + Span::styled(format!("{:<18}", record.label), theme::selected()), + Span::styled(format!(" {}", record.status.as_str()), theme::dim()), + ]))); + } + } + } rows.push(ListItem::new(Line::from(vec![ Span::styled(" ", theme::dim()), Span::styled("Recall quality", theme::dim()), @@ -526,15 +538,30 @@ fn render_detail(frame: &mut Frame<'_>, area: Rect, app: &App) { fn render_evidence_detail(frame: &mut Frame<'_>, area: Rect, app: &App) { let mut lines = Vec::new(); if let Some(snapshot) = &app.evidence_snapshot { - lines.push(Line::from(vec![ - Span::styled("status ", theme::dim()), - Span::styled(snapshot.status.as_str(), theme::accent()), - ])); + let has_harness_matrix = snapshot + .index + .as_ref() + .map(|index| !index.harness.is_empty()) + .unwrap_or(false); if let Some(certification) = &snapshot.certification { - lines.push(Line::from(vec![ - Span::styled("Local certification ", theme::brand()), - Span::styled(certification.status.as_str(), theme::dim()), - ])); + if has_harness_matrix { + lines.push(Line::from(vec![ + Span::styled("status ", theme::dim()), + Span::styled(snapshot.status.as_str(), theme::accent()), + Span::raw(" "), + Span::styled("Local certification ", theme::brand()), + Span::styled(certification.status.as_str(), theme::dim()), + ])); + } else { + lines.push(Line::from(vec![ + Span::styled("status ", theme::dim()), + Span::styled(snapshot.status.as_str(), theme::accent()), + ])); + lines.push(Line::from(vec![ + Span::styled("Local certification ", theme::brand()), + Span::styled(certification.status.as_str(), theme::dim()), + ])); + } lines.push(Line::from(format!( "generated {}", certification.generated_at @@ -575,22 +602,32 @@ fn render_evidence_detail(frame: &mut Frame<'_>, area: Rect, app: &App) { certification.agent_zero_note.as_deref().unwrap_or("") ))); } - lines.push(Line::from("")); - lines.push(Line::from(vec![ - Span::styled("root ", theme::dim()), - Span::raw(truncate(&snapshot.root.display().to_string(), 56)), - ])); - lines.push(Line::from(vec![ - Span::styled("index ", theme::dim()), - Span::raw(truncate(&snapshot.index_path.display().to_string(), 55)), - ])); - lines.push(Line::from(vec![ - Span::styled("metrics ", theme::dim()), - Span::raw(truncate( - &certification.metrics_path.display().to_string(), - 53, - )), - ])); + if has_harness_matrix { + lines.push(Line::from(vec![ + Span::styled("metrics ", theme::dim()), + Span::raw(truncate( + &certification.metrics_path.display().to_string(), + 53, + )), + ])); + } else { + lines.push(Line::from("")); + lines.push(Line::from(vec![ + Span::styled("root ", theme::dim()), + Span::raw(truncate(&snapshot.root.display().to_string(), 56)), + ])); + lines.push(Line::from(vec![ + Span::styled("index ", theme::dim()), + Span::raw(truncate(&snapshot.index_path.display().to_string(), 55)), + ])); + lines.push(Line::from(vec![ + Span::styled("metrics ", theme::dim()), + Span::raw(truncate( + &certification.metrics_path.display().to_string(), + 53, + )), + ])); + } } else { lines.push(Line::from(snapshot.message.clone())); lines.push(Line::from("Run: sh scripts/certify-tree-ring.sh")); @@ -604,6 +641,19 @@ fn render_evidence_detail(frame: &mut Frame<'_>, area: Rect, app: &App) { Span::raw(truncate(&snapshot.index_path.display().to_string(), 55)), ])); } + if let Some(index) = snapshot.index.as_ref() { + if !index.harness.is_empty() { + lines.push(Line::from(Span::styled("Harness matrix", theme::brand()))); + for record in index.harness.values().take(6) { + lines.push(Line::from(format!( + "{} {} {}", + record.label, + record.status.as_str(), + record.path.display() + ))); + } + } + } lines.push(Line::from("")); lines.push(Line::from("Actions: /evidence refresh | /integrations")); } else { @@ -810,4 +860,69 @@ mod tests { assert!(output.contains("3.729 ms")); assert!(output.contains("Agent Zero")); } + + #[test] + fn render_evidence_mode_shows_harness_matrix_records() { + let dir = tempdir().unwrap(); + let evidence_dir = dir.path().join("target/tree-ring-certification"); + std::fs::create_dir_all(evidence_dir.join("harness")).unwrap(); + std::fs::write(evidence_dir.join("summary.md"), "# Summary\n").unwrap(); + std::fs::write( + evidence_dir.join("metrics.json"), + r#"{"ok":true,"created_at":"2026-07-09T05:44:48Z"}"#, + ) + .unwrap(); + std::fs::write(evidence_dir.join("harness/codex.json"), "{}").unwrap(); + std::fs::write(evidence_dir.join("harness/claude-code.json"), "{}").unwrap(); + std::fs::write( + evidence_dir.join("evidence-index.json"), + r#"{ + "generated_at": "2026-07-09T05:44:48Z", + "overall_status": "fail", + "certification": { + "category": "certification", + "status": "pass", + "label": "Local certification", + "path": "metrics.json", + "summary_path": "summary.md", + "generated_at": "2026-07-09T05:44:48Z" + }, + "harness": { + "codex": { + "category": "harness", + "status": "pass", + "label": "Codex", + "path": "harness/codex.json", + "summary_path": null, + "generated_at": "2026-07-09T05:44:48Z" + }, + "claude-code": { + "category": "harness", + "status": "fail", + "label": "Claude Code", + "path": "harness/claude-code.json", + "summary_path": null, + "generated_at": "2026-07-09T05:44:48Z" + } + }, + "recall_quality": null, + "missing": ["recall_quality"], + "stale": [] + }"#, + ) + .unwrap(); + let mut app = App::new(dir.path().join(".tree-ring"), None).unwrap(); + app.execute_slash_command("/evidence").unwrap(); + let backend = TestBackend::new(120, 36); + let mut terminal = Terminal::new(backend).unwrap(); + + terminal.draw(|frame| render(frame, &app)).unwrap(); + let output = terminal.backend().to_string(); + + assert!(output.contains("Codex")); + assert!(output.contains("pass")); + assert!(output.contains("Claude Code")); + assert!(output.contains("fail")); + assert!(output.contains("harness/codex.json")); + } } From 1a08ed8ef59c03c50a0ccfb3864acd260b0c5fb1 Mon Sep 17 00:00:00 2001 From: TerminallyLazy Date: Thu, 9 Jul 2026 03:06:40 -0400 Subject: [PATCH 08/12] Preserve evidence detail layout for harness matrix --- crates/tree-ring-memory-cli/src/tui/render.rs | 141 ++++++++++-------- 1 file changed, 77 insertions(+), 64 deletions(-) diff --git a/crates/tree-ring-memory-cli/src/tui/render.rs b/crates/tree-ring-memory-cli/src/tui/render.rs index 81045f4..6f5b25c 100644 --- a/crates/tree-ring-memory-cli/src/tui/render.rs +++ b/crates/tree-ring-memory-cli/src/tui/render.rs @@ -126,14 +126,25 @@ fn render_body(frame: &mut Frame<'_>, area: Rect, app: &App) { .direction(Direction::Vertical) .constraints([Constraint::Percentage(64), Constraint::Percentage(36)]) .split(columns[0]); - let right = Layout::default() - .direction(Direction::Vertical) - .constraints([ - Constraint::Length(14), - Constraint::Percentage(45), - Constraint::Percentage(55), - ]) - .split(columns[1]); + let right = if app.mode == AppMode::Evidence { + Layout::default() + .direction(Direction::Vertical) + .constraints([ + Constraint::Length(10), + Constraint::Length(6), + Constraint::Min(12), + ]) + .split(columns[1]) + } else { + Layout::default() + .direction(Direction::Vertical) + .constraints([ + Constraint::Length(14), + Constraint::Percentage(45), + Constraint::Percentage(55), + ]) + .split(columns[1]) + }; if app.mode == AppMode::Exploded { render_exploded(frame, left[0], app); @@ -355,6 +366,12 @@ fn render_evidence_list(frame: &mut Frame<'_>, area: Rect, app: &App) { ]))); } } + } else { + rows.push(ListItem::new(Line::from(vec![ + Span::styled(" ", theme::dim()), + Span::styled("Harness probes", theme::dim()), + Span::styled(harness_status, theme::dim()), + ]))); } rows.push(ListItem::new(Line::from(vec![ Span::styled(" ", theme::dim()), @@ -538,30 +555,15 @@ fn render_detail(frame: &mut Frame<'_>, area: Rect, app: &App) { fn render_evidence_detail(frame: &mut Frame<'_>, area: Rect, app: &App) { let mut lines = Vec::new(); if let Some(snapshot) = &app.evidence_snapshot { - let has_harness_matrix = snapshot - .index - .as_ref() - .map(|index| !index.harness.is_empty()) - .unwrap_or(false); if let Some(certification) = &snapshot.certification { - if has_harness_matrix { - lines.push(Line::from(vec![ - Span::styled("status ", theme::dim()), - Span::styled(snapshot.status.as_str(), theme::accent()), - Span::raw(" "), - Span::styled("Local certification ", theme::brand()), - Span::styled(certification.status.as_str(), theme::dim()), - ])); - } else { - lines.push(Line::from(vec![ - Span::styled("status ", theme::dim()), - Span::styled(snapshot.status.as_str(), theme::accent()), - ])); - lines.push(Line::from(vec![ - Span::styled("Local certification ", theme::brand()), - Span::styled(certification.status.as_str(), theme::dim()), - ])); - } + lines.push(Line::from(vec![ + Span::styled("status ", theme::dim()), + Span::styled(snapshot.status.as_str(), theme::accent()), + ])); + lines.push(Line::from(vec![ + Span::styled("Local certification ", theme::brand()), + Span::styled(certification.status.as_str(), theme::dim()), + ])); lines.push(Line::from(format!( "generated {}", certification.generated_at @@ -602,32 +604,22 @@ fn render_evidence_detail(frame: &mut Frame<'_>, area: Rect, app: &App) { certification.agent_zero_note.as_deref().unwrap_or("") ))); } - if has_harness_matrix { - lines.push(Line::from(vec![ - Span::styled("metrics ", theme::dim()), - Span::raw(truncate( - &certification.metrics_path.display().to_string(), - 53, - )), - ])); - } else { - lines.push(Line::from("")); - lines.push(Line::from(vec![ - Span::styled("root ", theme::dim()), - Span::raw(truncate(&snapshot.root.display().to_string(), 56)), - ])); - lines.push(Line::from(vec![ - Span::styled("index ", theme::dim()), - Span::raw(truncate(&snapshot.index_path.display().to_string(), 55)), - ])); - lines.push(Line::from(vec![ - Span::styled("metrics ", theme::dim()), - Span::raw(truncate( - &certification.metrics_path.display().to_string(), - 53, - )), - ])); - } + lines.push(Line::from("")); + lines.push(Line::from(vec![ + Span::styled("root ", theme::dim()), + Span::raw(truncate(&snapshot.root.display().to_string(), 56)), + ])); + lines.push(Line::from(vec![ + Span::styled("index ", theme::dim()), + Span::raw(truncate(&snapshot.index_path.display().to_string(), 55)), + ])); + lines.push(Line::from(vec![ + Span::styled("metrics ", theme::dim()), + Span::raw(truncate( + &certification.metrics_path.display().to_string(), + 53, + )), + ])); } else { lines.push(Line::from(snapshot.message.clone())); lines.push(Line::from("Run: sh scripts/certify-tree-ring.sh")); @@ -645,12 +637,13 @@ fn render_evidence_detail(frame: &mut Frame<'_>, area: Rect, app: &App) { if !index.harness.is_empty() { lines.push(Line::from(Span::styled("Harness matrix", theme::brand()))); for record in index.harness.values().take(6) { - lines.push(Line::from(format!( - "{} {} {}", - record.label, - record.status.as_str(), - record.path.display() - ))); + lines.push(Line::from(vec![ + Span::styled(truncate(&record.label, 18), theme::selected()), + Span::raw(" "), + Span::styled(record.status.as_str(), theme::dim()), + Span::raw(" "), + Span::raw(truncate(&record.path.display().to_string(), 36)), + ])); } } } @@ -919,10 +912,30 @@ mod tests { terminal.draw(|frame| render(frame, &app)).unwrap(); let output = terminal.backend().to_string(); + assert!(output.contains("status")); + assert!(output.contains("Local certification")); + assert!(output.contains("root")); + assert!(output.contains("index")); + assert!(output.contains("q quit | / command")); assert!(output.contains("Codex")); assert!(output.contains("pass")); assert!(output.contains("Claude Code")); assert!(output.contains("fail")); - assert!(output.contains("harness/codex.json")); + assert!(output.contains("codex.json")); + } + + #[test] + fn render_evidence_mode_keeps_harness_fallback_when_index_missing() { + let dir = tempdir().unwrap(); + let mut app = App::new(dir.path().join(".tree-ring"), None).unwrap(); + app.execute_slash_command("/evidence").unwrap(); + let backend = TestBackend::new(120, 36); + let mut terminal = Terminal::new(backend).unwrap(); + + terminal.draw(|frame| render(frame, &app)).unwrap(); + let output = terminal.backend().to_string(); + + assert!(output.contains("Harness probes")); + assert!(output.contains("missing")); } } From 50d68a48284010db8759fa9344511e4c040bf198 Mon Sep 17 00:00:00 2001 From: TerminallyLazy Date: Thu, 9 Jul 2026 03:09:49 -0400 Subject: [PATCH 09/12] Keep evidence status visible without certification --- crates/tree-ring-memory-cli/src/tui/render.rs | 52 +++++++++++++++++-- 1 file changed, 48 insertions(+), 4 deletions(-) diff --git a/crates/tree-ring-memory-cli/src/tui/render.rs b/crates/tree-ring-memory-cli/src/tui/render.rs index 6f5b25c..856c880 100644 --- a/crates/tree-ring-memory-cli/src/tui/render.rs +++ b/crates/tree-ring-memory-cli/src/tui/render.rs @@ -555,11 +555,11 @@ fn render_detail(frame: &mut Frame<'_>, area: Rect, app: &App) { fn render_evidence_detail(frame: &mut Frame<'_>, area: Rect, app: &App) { let mut lines = Vec::new(); if let Some(snapshot) = &app.evidence_snapshot { + lines.push(Line::from(vec![ + Span::styled("status ", theme::dim()), + Span::styled(snapshot.status.as_str(), theme::accent()), + ])); if let Some(certification) = &snapshot.certification { - lines.push(Line::from(vec![ - Span::styled("status ", theme::dim()), - Span::styled(snapshot.status.as_str(), theme::accent()), - ])); lines.push(Line::from(vec![ Span::styled("Local certification ", theme::brand()), Span::styled(certification.status.as_str(), theme::dim()), @@ -916,6 +916,7 @@ mod tests { assert!(output.contains("Local certification")); assert!(output.contains("root")); assert!(output.contains("index")); + assert!(output.contains("metrics")); assert!(output.contains("q quit | / command")); assert!(output.contains("Codex")); assert!(output.contains("pass")); @@ -924,6 +925,49 @@ mod tests { assert!(output.contains("codex.json")); } + #[test] + fn render_evidence_mode_keeps_status_without_certification() { + let dir = tempdir().unwrap(); + let evidence_dir = dir.path().join("target/tree-ring-certification"); + std::fs::create_dir_all(evidence_dir.join("harness")).unwrap(); + std::fs::write(evidence_dir.join("harness/codex.json"), "{}").unwrap(); + std::fs::write( + evidence_dir.join("evidence-index.json"), + r#"{ + "generated_at": "2026-07-09T05:44:48Z", + "overall_status": "fail", + "certification": null, + "harness": { + "codex": { + "category": "harness", + "status": "pass", + "label": "Codex", + "path": "harness/codex.json", + "summary_path": null, + "generated_at": "2026-07-09T05:44:48Z" + } + }, + "recall_quality": null, + "missing": ["certification", "recall_quality"], + "stale": [] + }"#, + ) + .unwrap(); + let mut app = App::new(dir.path().join(".tree-ring"), None).unwrap(); + app.execute_slash_command("/evidence").unwrap(); + let backend = TestBackend::new(120, 36); + let mut terminal = Terminal::new(backend).unwrap(); + + terminal.draw(|frame| render(frame, &app)).unwrap(); + let output = terminal.backend().to_string(); + + assert!(output.contains("status")); + assert!(output.contains("fail")); + assert!(output.contains("Harness matrix")); + assert!(output.contains("Codex")); + assert!(!output.contains("Local certification")); + } + #[test] fn render_evidence_mode_keeps_harness_fallback_when_index_missing() { let dir = tempdir().unwrap(); From 595b0e83244cd3d79fe4fa923c06e47d6c908875 Mon Sep 17 00:00:00 2001 From: TerminallyLazy Date: Thu, 9 Jul 2026 03:15:01 -0400 Subject: [PATCH 10/12] Document harness certification matrix --- README.md | 6 ++++++ docs/architecture/rust-core-status.md | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/README.md b/README.md index 98a8b22..a805da2 100644 --- a/README.md +++ b/README.md @@ -256,8 +256,14 @@ Framework discovery is read-only: ```bash tree-ring integrations scan --source-root . +tree-ring integrations certify --source-root . ``` +- `integrations certify` writes non-mutating harness evidence under + `target/tree-ring-certification/harness/` and updates + `target/tree-ring-certification/evidence-index.json`. Pass, fail, and skip + states are evidence records, not broad compatibility claims. + It looks for local markers for DOX, Revolve, Codex, Claude Code, Agent Zero/A0, Goose, OpenCode, Hermes, and Pi, then suggests next steps without editing those tools' configuration. JSON output records whether each marker came from the diff --git a/docs/architecture/rust-core-status.md b/docs/architecture/rust-core-status.md index 4743ee4..427645a 100644 --- a/docs/architecture/rust-core-status.md +++ b/docs/architecture/rust-core-status.md @@ -61,6 +61,12 @@ v0.11 Rust-native source adapters plus framework discovery. Revolve, Codex, Claude Code, Agent Zero/A0, Goose, OpenCode, Hermes, and Pi. Integration scan output distinguishes project markers from user-home markers so local harness readiness is explicit. +- `tree-ring integrations certify` turns integration-scan markers into + non-mutating harness evidence records for Codex, Claude Code, OpenCode, + Goose, Pi, and Agent Zero/A0. Records live under + `target/tree-ring-certification/harness/` and are indexed by + `evidence-index.json`; skip states are explicit and are not counted as + compatibility passes. - JSONL import uses batched SQLite writes while preserving dry-run validation, duplicate skipping, explicit replacement, secret blocking, and supersession application. From a7aba54f1a1d9ba5089c776e7e360564659d37cd Mon Sep 17 00:00:00 2001 From: TerminallyLazy Date: Thu, 9 Jul 2026 03:24:40 -0400 Subject: [PATCH 11/12] Make harness certification fixture deterministic --- scripts/certify-tree-ring.sh | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/scripts/certify-tree-ring.sh b/scripts/certify-tree-ring.sh index 5c60de6..86ac2fc 100755 --- a/scripts/certify-tree-ring.sh +++ b/scripts/certify-tree-ring.sh @@ -159,7 +159,8 @@ grep -F 'promoted evidence' "$OUT_DIR/revolve-recall.json" > /dev/null \ scan_root="$TMP_DIR/integration-scan" scan_home="$TMP_DIR/integration-home" mkdir -p "$scan_root/.codex" "$scan_root/.claude" "$scan_root/usr/plugins" \ - "$scan_root/revolve" "$scan_root/.opencode" "$scan_root/.goose" "$scan_home/.claude" + "$scan_root/revolve" "$scan_root/.opencode" "$scan_root/.goose" "$scan_home/.claude" \ + "$scan_home/.pi" printf '# Agent contract\n' > "$scan_root/AGENTS.md" printf '# Claude instructions\n' > "$scan_root/CLAUDE.md" mkdir -p "$scan_root/.tree-ring" @@ -302,7 +303,7 @@ cat > "$INDEX" < "$OUT_DIR/harness-certification.json" require_file "$OUT_DIR/harness/codex.json" require_file "$OUT_DIR/harness/claude-code.json" @@ -310,6 +311,16 @@ require_file "$OUT_DIR/harness/opencode.json" require_file "$OUT_DIR/harness/goose.json" require_file "$OUT_DIR/harness/pi.json" require_file "$OUT_DIR/harness/agent-zero.json" +grep -E '"pass_count"[[:space:]]*:[[:space:]]*5' "$OUT_DIR/harness-certification.json" > /dev/null \ + || fail "harness certification did not report pass_count 5" +grep -E '"fail_count"[[:space:]]*:[[:space:]]*0' "$OUT_DIR/harness-certification.json" > /dev/null \ + || fail "harness certification did not report fail_count 0" +grep -E '"skip_count"[[:space:]]*:[[:space:]]*1' "$OUT_DIR/harness-certification.json" > /dev/null \ + || fail "harness certification did not report skip_count 1" +grep -E '"status"[[:space:]]*:[[:space:]]*"pass"' "$OUT_DIR/harness/codex.json" > /dev/null \ + || fail "codex harness did not report pass status" +grep -E '"status"[[:space:]]*:[[:space:]]*"skip"' "$OUT_DIR/harness/pi.json" > /dev/null \ + || fail "pi harness did not report skip status" grep -F '"harness"' "$INDEX" > /dev/null \ || fail "evidence index did not include harness records" grep -F '"codex"' "$INDEX" > /dev/null \ From 75cb61c5b88e76c2929d5f3444500c39f1fef4cf Mon Sep 17 00:00:00 2001 From: TerminallyLazy Date: Thu, 9 Jul 2026 10:23:01 -0400 Subject: [PATCH 12/12] Address harness certification review feedback --- .../src/harness_evidence.rs | 56 ++++++++++++------- 1 file changed, 35 insertions(+), 21 deletions(-) diff --git a/crates/tree-ring-memory-cli/src/harness_evidence.rs b/crates/tree-ring-memory-cli/src/harness_evidence.rs index 7c4915d..5425c61 100644 --- a/crates/tree-ring-memory-cli/src/harness_evidence.rs +++ b/crates/tree-ring-memory-cli/src/harness_evidence.rs @@ -190,12 +190,13 @@ fn inspect_guidance(source_root: &Path) -> HarnessGuidanceEvidence { .filter_map(|path| fs::read_to_string(path).ok()) .collect::>() .join("\n"); + let combined_lower = combined.to_lowercase(); HarnessGuidanceEvidence { agents_md, skill_md, cli_md, - recall_guidance: combined.contains("tree-ring recall"), - remember_guidance: combined.contains("tree-ring remember"), + recall_guidance: combined_lower.contains("tree-ring recall"), + remember_guidance: combined_lower.contains("tree-ring remember"), } } @@ -219,22 +220,19 @@ fn merge_harness_index( let index_path = evidence_dir.join("evidence-index.json"); let mut index = read_or_create_index(evidence_dir, generated_at)?; index.generated_at = generated_at.to_string(); - index.harness = records - .iter() - .map(|record| { - ( - record.harness_id.clone(), - EvidenceRecordRef { - category: "harness".to_string(), - status: record.status, - label: record.name.clone(), - path: PathBuf::from(format!("harness/{}.json", record.harness_id)), - summary_path: None, - generated_at: record.generated_at.clone(), - }, - ) - }) - .collect::>(); + for record in records { + index.harness.insert( + record.harness_id.clone(), + EvidenceRecordRef { + category: "harness".to_string(), + status: record.status, + label: record.name.clone(), + path: PathBuf::from(format!("harness/{}.json", record.harness_id)), + summary_path: None, + generated_at: record.generated_at.clone(), + }, + ); + } index.missing.retain(|item| item != "harness"); if index.recall_quality.is_none() && !index.missing.iter().any(|item| item == "recall_quality") { @@ -353,12 +351,12 @@ mod tests { std::fs::create_dir_all(dir.path().join(".tree-ring")).unwrap(); std::fs::write( dir.path().join(".tree-ring/SKILL.md"), - "Use `tree-ring recall` before acting and `tree-ring remember` for durable facts.", + "Use `TREE-RING RECALL` before acting and `Tree-Ring Remember` for durable facts.", ) .unwrap(); std::fs::write( dir.path().join(".tree-ring/CLI.md"), - "`tree-ring recall` and `tree-ring remember` are the portable command surface.", + "`Tree-Ring Recall` and `TREE-RING REMEMBER` are the portable command surface.", ) .unwrap(); std::fs::write( @@ -433,7 +431,16 @@ mod tests { "summary_path": "summary.md", "generated_at": "2026-07-09T05:44:48Z" }, - "harness": {}, + "harness": { + "manual-harness": { + "category": "harness", + "status": "skip", + "label": "Manual Harness", + "path": "harness/manual.json", + "summary_path": null, + "generated_at": "2026-07-09T05:44:48Z" + } + }, "recall_quality": null, "missing": ["harness", "recall_quality"], "stale": [] @@ -463,6 +470,13 @@ mod tests { index.harness.get("codex").map(|record| record.path.clone()), Some(PathBuf::from("harness/codex.json")) ); + assert_eq!( + index + .harness + .get("manual-harness") + .map(|record| record.path.clone()), + Some(PathBuf::from("harness/manual.json")) + ); assert_eq!(index.missing, vec!["recall_quality".to_string()]); assert_eq!(index.overall_status, EvidenceStatus::Pass); }