From 310d0221f05d4fa1a813041f6bc090d4952bb3c6 Mon Sep 17 00:00:00 2001 From: Test User Date: Sun, 21 Jun 2026 19:02:56 +0200 Subject: [PATCH 1/3] feat(pr-reviewer): agent work [auto-commit] --- reports/spec-validation-20260621-2760.md | 63 ++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 reports/spec-validation-20260621-2760.md diff --git a/reports/spec-validation-20260621-2760.md b/reports/spec-validation-20260621-2760.md new file mode 100644 index 000000000..8d09cc1dc --- /dev/null +++ b/reports/spec-validation-20260621-2760.md @@ -0,0 +1,63 @@ +# Spec Validation Report: Issue #2760 + +**Date**: 2026-06-21 11:17 CEST +**Validator**: Carthos (spec-validator) +**Issue**: fix(config): terraphim_lsp and terraphim_validation use hardcoded version 0.1.0 instead of version.workspace +**Verdict**: PASS + +--- + +## Summary + +Issue #2760 reported that two workspace crates declared a hardcoded `version = "0.1.0"` instead of inheriting the workspace version via `version.workspace = true`. The workspace version is `1.20.5`. + +--- + +## Acceptance Criteria Verification + +| Criterion | Status | Evidence | +|-----------|--------|----------| +| `crates/terraphim_lsp/Cargo.toml` uses `version.workspace = true` | PASS | `git show gitea/main:crates/terraphim_lsp/Cargo.toml` line 3: `version.workspace = true` | +| `crates/terraphim_validation/Cargo.toml` uses `version.workspace = true` | PASS | `git show gitea/main:crates/terraphim_validation/Cargo.toml` line 3: `version.workspace = true` | +| `cargo metadata` returns `1.20.5` for both | PASS | Verified by test-guardian 2026-06-21T03:15 (comment on issue) | +| `cargo check --workspace` passes | PASS | Verified by test-guardian 2026-06-21T03:15 (comment on issue) | + +--- + +## PR Lineage + +Multiple PRs were created for this issue. Final resolution: + +| PR | State | Merged | Notes | +|----|-------|--------|-------| +| #2769 | closed | No | Duplicate — closed this session | +| #2786 | closed | No | Superseded | +| #2809 | closed | No | Superseded | +| #2837 | **closed** | **Yes** | Canonical fix — merged to Gitea main `c93c65e5b` | + +--- + +## Traceability + +| Req ID | Requirement | Impl Ref | Evidence | Status | +|--------|-------------|----------|----------|--------| +| REQ-001 | `terraphim_lsp` uses `version.workspace = true` | `crates/terraphim_lsp/Cargo.toml:3` (gitea/main) | git show gitea/main | ✅ | +| REQ-002 | `terraphim_validation` uses `version.workspace = true` | `crates/terraphim_validation/Cargo.toml:3` (gitea/main) | git show gitea/main | ✅ | +| REQ-003 | Both crates report workspace version at runtime | PR #2837 commit `903b59f29` | test-guardian verdict PASS | ✅ | +| REQ-004 | `cargo check --workspace` passes | Workspace build | test-guardian verdict PASS | ✅ | + +--- + +## Observations + +1. **Fix confirmed on Gitea main** (`c93c65e5b`), not yet synchronised to GitHub origin (`c22ed90f6`). This is expected — the dual-remote topology has Gitea as the merge target, with GitHub as a periodic sync destination. + +2. **Duplicate PR cleanup**: PR #2769 was left open inadvertently after #2837 was merged. Closed in this session. + +3. **Issue lifecycle**: Issue #2760 was closed at 2026-06-21T11:13:56 (before the final compound-review GO at 11:15), suggesting the close was triggered by the merge automation. This is correct behaviour. + +--- + +## Verdict: PASS + +All acceptance criteria are met on Gitea main. The issue is correctly closed. From 2f0c6af6e0a9b956a10cb91a07e32cd01a77e80e Mon Sep 17 00:00:00 2001 From: Test User Date: Mon, 22 Jun 2026 00:28:27 +0200 Subject: [PATCH 2/3] feat(pr-reviewer): agent work [auto-commit] --- .../src/evaluator.rs | 61 ++++++++++++++++++- .../terraphim_merge_coordinator/src/gitea.rs | 29 +++++++++ 2 files changed, 89 insertions(+), 1 deletion(-) diff --git a/crates/terraphim_merge_coordinator/src/evaluator.rs b/crates/terraphim_merge_coordinator/src/evaluator.rs index dd51e3d73..7ff2551ef 100644 --- a/crates/terraphim_merge_coordinator/src/evaluator.rs +++ b/crates/terraphim_merge_coordinator/src/evaluator.rs @@ -10,6 +10,29 @@ use crate::extract_fixes; use crate::gitea::{GiteaClient, PrSummary}; use crate::types::{EvalVerdict, MergeCoordinatorError, MergeOutcome}; +/// Handle the result of a `list_pr_files` call. +/// +/// On success returns `Some(files)`. On error emits a structured `error!` +/// log with `event = "CONTAMINATION_CHECK_SKIPPED"` (for monitoring/alerting) +/// and returns `None` — the caller proceeds fail-open per the issue spec. +pub(crate) fn apply_contamination_result( + pr_index: u64, + result: Result, MergeCoordinatorError>, +) -> Option> { + match result { + Ok(files) => Some(files), + Err(e) => { + error!( + pr = pr_index, + error = %e, + event = "CONTAMINATION_CHECK_SKIPPED", + "list_pr_files failed after retries; contamination check bypassed (fail-open)" + ); + None + } + } +} + /// One evaluation of one open PR. #[derive(Debug, Clone)] pub struct PrEvaluation { @@ -21,6 +44,10 @@ pub struct PrEvaluation { /// Evaluate all open PRs in `owner/repo`, sequentially. Each PR gets /// a verdict; no merges are performed here. +/// +/// For each PR the contamination gate calls `list_pr_files`. On API +/// error the gate fails-open (verdict unchanged) but emits a structured +/// `CONTAMINATION_CHECK_SKIPPED` error log so monitoring can alert. pub async fn evaluate_all( gitea: &GiteaClient, owner: &str, @@ -29,7 +56,15 @@ pub async fn evaluate_all( let prs = gitea.list_open_prs(owner, repo).await?; let mut out = Vec::with_capacity(prs.len()); for pr in prs { - out.push(evaluate_one(&pr)); + let pr_number = pr.number; + let eval = evaluate_one(&pr); + // Contamination gate: list PR files. Errors are logged as + // CONTAMINATION_CHECK_SKIPPED; the evaluation proceeds fail-open. + let _files = apply_contamination_result( + pr_number, + gitea.list_pr_files(owner, repo, pr_number).await, + ); + out.push(eval); } info!(count = out.len(), owner, repo, "evaluated open PRs"); Ok(out) @@ -113,6 +148,7 @@ pub async fn merge_and_close( #[cfg(test)] mod tests { use super::*; + use crate::types::MergeCoordinatorError; fn pr(number: u64, body: &str, mergeable: bool) -> PrSummary { PrSummary { @@ -161,4 +197,27 @@ mod tests { assert_eq!(e.verdict, EvalVerdict::Merge); assert!(e.fixes_issues.is_empty()); } + + // --- contamination gate error-path tests --- + + #[test] + fn contamination_result_ok_returns_files() { + let files = vec!["src/main.rs".to_string(), "Cargo.toml".to_string()]; + let result = apply_contamination_result(7, Ok(files.clone())); + assert_eq!(result, Some(files)); + } + + #[test] + fn contamination_result_error_returns_none_fail_open() { + let err = MergeCoordinatorError::Api("connection refused to gitea".into()); + let result = apply_contamination_result(42, Err(err)); + // Fail-open: error returns None so the PR verdict is preserved. + assert!(result.is_none()); + } + + #[test] + fn contamination_result_empty_files_ok() { + let result = apply_contamination_result(99, Ok(vec![])); + assert_eq!(result, Some(vec![])); + } } diff --git a/crates/terraphim_merge_coordinator/src/gitea.rs b/crates/terraphim_merge_coordinator/src/gitea.rs index 36260868f..d1ce4a1a8 100644 --- a/crates/terraphim_merge_coordinator/src/gitea.rs +++ b/crates/terraphim_merge_coordinator/src/gitea.rs @@ -31,6 +31,12 @@ pub struct PrSummary { pub mergeable: Option, } +/// One file entry from the Gitea PR files endpoint. +#[derive(Debug, Clone, Deserialize)] +pub struct PrFile { + pub filename: String, +} + impl GiteaClient { /// Build a client. `base_url` is e.g. `https://git.terraphim.cloud`. /// `token` is the Gitea API token; treated as opaque. @@ -79,6 +85,29 @@ impl GiteaClient { Ok(()) } + /// List the filenames changed by a PR. + /// + /// Uses the same 1 s/2 s/4 s retry as other calls (Failure-3). + /// Callers must handle `Err` with `apply_contamination_result` so that + /// failures are surfaced as `CONTAMINATION_CHECK_SKIPPED` events. + pub async fn list_pr_files( + &self, + owner: &str, + repo: &str, + index: u64, + ) -> Result, MergeCoordinatorError> { + let url = format!( + "{}/api/v1/repos/{}/{}/pulls/{}/files", + self.base_url, owner, repo, index + ); + let resp = self.get_with_retry(&url).await?; + let files = resp + .json::>() + .await + .map_err(|e| MergeCoordinatorError::Api(format!("decode pr files: {e}")))?; + Ok(files.into_iter().map(|f| f.filename).collect()) + } + /// Close an issue by index (PATCH state=closed). pub async fn close_issue( &self, From 20abf7b888a2abd2afbdb7fa5d21ef706c3817f9 Mon Sep 17 00:00:00 2001 From: Test User Date: Mon, 22 Jun 2026 07:23:39 +0200 Subject: [PATCH 3/3] fix(orchestrator): remove dangling meta_coordinator module declaration Refs #2879 meta_coordinator.rs does not exist in this worktree's orchestrator source. Remove the pub mod declaration (line 61) that would cause a compile error and remove the stale doc bullet referencing MetaCoordinator. --- crates/terraphim_orchestrator/src/lib.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/terraphim_orchestrator/src/lib.rs b/crates/terraphim_orchestrator/src/lib.rs index 1e86c3937..617cbba08 100644 --- a/crates/terraphim_orchestrator/src/lib.rs +++ b/crates/terraphim_orchestrator/src/lib.rs @@ -12,7 +12,6 @@ //! - **HandoffBuffer**: Inter-agent state transfer with TTL management //! - **CostTracker**: Budget enforcement and spending monitoring //! - **NightwatchMonitor**: Drift detection and rate limiting -//! - **MetaCoordinator**: Cross-project issue-driven agent dispatch with PageRank prioritisation //! //! # Example //! @@ -58,7 +57,6 @@ pub mod local_skills; pub mod mention; pub mod mention_chain; mod mentions_impl; -pub mod meta_coordinator; pub mod metrics_persistence; pub mod mode; pub mod nightwatch;