diff --git a/crates/code-intel-cli/src/providers.rs b/crates/code-intel-cli/src/providers.rs index fdbd3bd..72c4b3c 100644 --- a/crates/code-intel-cli/src/providers.rs +++ b/crates/code-intel-cli/src/providers.rs @@ -1224,7 +1224,89 @@ fn validate_codenexus_integration( } } +/// Resolves the trusted orchestration manifest, refusing the case where the +/// resolved manifest belongs to a different checkout than the one the process +/// is standing in. +/// +/// The refusal exists because the silent version of this is a false PASS, not +/// a false failure. `CODE_INTEL_HOME` is commonly set to a primary checkout; +/// run a validation from a git worktree of the same repository and every +/// provider/route check reads the *primary* checkout's manifest while +/// appearing to validate the worktree. A worktree whose manifest is genuinely +/// broken then reports green as long as the primary checkout is consistent. +/// Naming both roots costs one error message; not naming them costs a +/// verification result that means nothing. +/// +/// `CODE_INTEL_INTEGRATIONS_MANIFEST` is exempt: it is an explicit operator +/// instruction to use one specific file, so there is no ambiguity to resolve. fn orchestration_manifest() -> std::result::Result<(PathBuf, PathBuf), String> { + let explicit = env::var("CODE_INTEL_INTEGRATIONS_MANIFEST").is_ok(); + let (manifest, root) = resolve_orchestration_manifest()?; + if !explicit { + reject_foreign_checkout(&manifest, cwd_manifest_path())?; + } + Ok((manifest, root)) +} + +/// The manifest a cwd-anchored reader would have picked, used only to detect +/// disagreement. This never grants trust — `orchestration_manifest`'s own cwd +/// fallback still gates on [`is_safe_cwd_manifest`]. +fn cwd_manifest_path() -> Option { + let cwd = env::current_dir().ok()?; + cwd.ancestors() + .map(|ancestor| ancestor.join("orchestration").join("integrations.json")) + // `is_safe_cwd_manifest` is what separates the two cases that both + // look like "cwd disagrees with CODE_INTEL_HOME". Standing in an + // unrelated repository that merely happens to have a file at + // orchestration/integrations.json is not ambiguity — the operator + // named a checkout and nothing here rivals it, which is exactly what + // test-integration-orchestration.ps1:243 has always asserted. Only a + // real code-intel registry is a rival, and that is the worktree case + // this guard exists for. + .find(|candidate| candidate.is_file() && is_safe_cwd_manifest(candidate)) +} + +fn reject_foreign_checkout( + resolved: &Path, + local: Option, +) -> std::result::Result<(), String> { + let Some(local) = local else { + return Ok(()); + }; + let canonical = |path: &Path| path.canonicalize().unwrap_or_else(|_| path.to_path_buf()); + if canonical(&local) == canonical(resolved) { + return Ok(()); + } + Err(format!( + "orchestration manifest ambiguity: resolved {} but the current directory belongs to {}. \ +These are different checkouts, so validating one while standing in the other proves nothing. \ +Set CODE_INTEL_HOME to the checkout you mean, or CODE_INTEL_INTEGRATIONS_MANIFEST to one manifest explicitly.", + resolved.display(), + local.display() + )) +} + +// Registry tests must assert against the checkout they were built from, not +// against whatever `CODE_INTEL_HOME` happens to name on the developer's +// machine. Reading the ambient variable is what let a worktree's registry +// look valid while the primary checkout was the thing actually validated. +#[cfg(test)] +fn test_manifest_override() -> Option { + let candidate = Path::new(env!("CARGO_MANIFEST_DIR")) + .join("../..") + .join("orchestration") + .join("integrations.json"); + candidate.is_file().then_some(candidate) +} + +fn resolve_orchestration_manifest() -> std::result::Result<(PathBuf, PathBuf), String> { + #[cfg(test)] + if let Some(path) = test_manifest_override() { + return manifest_candidate(path).ok_or_else(|| { + "built-from checkout has no readable integrations manifest".to_string() + }); + } + if let Ok(explicit) = env::var("CODE_INTEL_INTEGRATIONS_MANIFEST") { let path = PathBuf::from(explicit); let path = if path.is_absolute() { @@ -1670,6 +1752,59 @@ mod tests { ); } + #[test] + fn manifest_from_another_checkout_is_refused_and_names_both_roots() { + // The worktree case: CODE_INTEL_HOME points at the primary checkout + // while the process stands in a worktree of the same repository. + let primary = Path::new(r"D:\projects\code-intel-pipeline\orchestration\integrations.json"); + let worktree = Path::new( + r"D:\projects\code-intel-pipeline\.claude\worktrees\wt\orchestration\integrations.json", + ); + let error = reject_foreign_checkout(primary, Some(worktree.to_path_buf())) + .expect_err("two different checkouts must not validate silently"); + assert!(error.contains("ambiguity"), "{error}"); + assert!(error.contains(&primary.display().to_string()), "{error}"); + assert!(error.contains(&worktree.display().to_string()), "{error}"); + assert!( + error.contains("CODE_INTEL_INTEGRATIONS_MANIFEST"), + "{error}" + ); + } + + #[test] + fn an_unrelated_cwd_manifest_never_rivals_code_intel_home() { + // Regression guard for test-integration-orchestration.ps1:243. A + // directory holding {"policy":{"name":"unrelated"},"integrations":[]} + // is not a code-intel registry, so CODE_INTEL_HOME still wins and + // nothing is ambiguous. + let root = std::env::temp_dir().join(format!( + "code-intel-unrelated-manifest-{}-{}", + std::process::id(), + SystemTime::now() + .duration_since(UNIX_EPOCH) + .expect("clock after epoch") + .as_nanos() + )); + let manifest = root.join("orchestration").join("integrations.json"); + fs::create_dir_all(manifest.parent().expect("orchestration dir")).expect("fixture"); + fs::write( + &manifest, + br#"{"policy":{"name":"unrelated"},"integrations":[]}"#, + ) + .expect("write fixture manifest"); + assert!(!is_safe_cwd_manifest(&manifest)); + fs::remove_dir_all(&root).expect("cleanup"); + } + + #[test] + fn matching_checkout_and_absent_local_manifest_both_pass() { + let same = Path::new(r"D:\repo\orchestration\integrations.json"); + assert!(reject_foreign_checkout(same, Some(same.to_path_buf())).is_ok()); + // Running against an arbitrary directory that has no manifest of its + // own is the normal installed-CLI case, not an ambiguity. + assert!(reject_foreign_checkout(same, None).is_ok()); + } + #[test] fn codenexus_plan_quotes_repo_paths_for_powershell() { let command = render_command( diff --git a/crates/code-intel-cli/tests/graph_adapter.rs b/crates/code-intel-cli/tests/graph_adapter.rs index 4e95409..dbcff41 100644 --- a/crates/code-intel-cli/tests/graph_adapter.rs +++ b/crates/code-intel-cli/tests/graph_adapter.rs @@ -414,8 +414,19 @@ fn public_route_usage_registry_facade_and_schemas_are_real() { assert_eq!(output.status.code(), Some(64)); assert!(output.stdout.is_empty()); + // Name the manifest this test means. Without it the spawned binary + // resolves whatever `CODE_INTEL_HOME` points at, which on a developer + // machine is usually a different checkout than the one being tested — + // the assertion below would then be about someone else's tree. let validation = Command::new(env!("CARGO_BIN_EXE_code-intel")) .args(["provider", "--action", "Validate", "--json"]) + .env( + "CODE_INTEL_INTEGRATIONS_MANIFEST", + Path::new(env!("CARGO_MANIFEST_DIR")) + .join("../..") + .join("orchestration") + .join("integrations.json"), + ) .output() .unwrap(); let validation_json: Value = serde_json::from_slice(&validation.stdout).unwrap(); diff --git a/legacy/install-code-intel-pipeline.ps1 b/legacy/install-code-intel-pipeline.ps1 index 77ba9e4..43f5a3f 100644 --- a/legacy/install-code-intel-pipeline.ps1 +++ b/legacy/install-code-intel-pipeline.ps1 @@ -437,7 +437,11 @@ param( [string[]]`$RemainingArgs ) -`$repoRoot = '$repoRootLiteral' +# CODE_INTEL_REPO_ROOT is honoured here because the error below tells the +# operator to set it. The literal is the install-time location, which goes +# stale the moment the repository is moved or a directory is renamed — the +# override is how you recover without reinstalling. +`$repoRoot = if (-not [string]::IsNullOrWhiteSpace(`$env:CODE_INTEL_REPO_ROOT)) { `$env:CODE_INTEL_REPO_ROOT } else { '$repoRootLiteral' } `$target = Join-Path `$repoRoot '$relativeLiteral' if (-not (Test-Path -LiteralPath `$target -PathType Leaf)) { diff --git a/orchestration/internalization/graph.json b/orchestration/internalization/graph.json index 8e00464..4529490 100644 --- a/orchestration/internalization/graph.json +++ b/orchestration/internalization/graph.json @@ -2,30 +2,30 @@ "schema": "code-intel-internalization-record.v1", "id": "internalization.graph-record", "projectId": "code-intel-pipeline", - "subject": { "name": "architecture graph provider boundary", "kind": "adapted_capability", "source": { "uri": "unverified-upstream:understand-anything; local-adapter=crates/code-intel-cli/src/graph_adapter.rs", "revision": "unverified-upstream; local-adapter-sha256:339536b6756cecd60b706faafb3ee9f53f8c1436ac6d2becb0448d27dc0b0322; local-conformance-sha256:6593d9770665b24e4fa115c2ea5d710e36a3ed679eaaaf605ced616b2b479662" }, "license": { "id": "UNKNOWN-RESEARCH-ONLY", "obligations": ["do not infer external Understand provider ownership, revision, or license from the Pipeline-owned Rust graph implementation", "retain distinct internal and explicit-fallback implementation identities and provenance"] } }, + "subject": { "name": "architecture graph provider boundary", "kind": "adapted_capability", "source": { "uri": "unverified-upstream:understand-anything; local-adapter=crates/code-intel-cli/src/graph_adapter.rs", "revision": "unverified-upstream; local-adapter-sha256:339536b6756cecd60b706faafb3ee9f53f8c1436ac6d2becb0448d27dc0b0322; local-conformance-sha256:1fb78affea75e267dbdd84e797150937a70f3f1c9f80830eee364976ddcf2b34" }, "license": { "id": "UNKNOWN-RESEARCH-ONLY", "obligations": ["do not infer external Understand provider ownership, revision, or license from the Pipeline-owned Rust graph implementation", "retain distinct internal and explicit-fallback implementation identities and provenance"] } }, "adoption": { "rung": "adapt", "ownedBoundary": ["Pipeline-owned B02 architecture-graph port, internal Rust implementation identity, snapshot binding, and A04 route", "external Understand-compatible fallback remains separately owned, explicitly selected, and non-authoritative until adapted; no external implementation is vendored by this record"], "necessityEvidence": { "evidenceIds": ["local:registry:provider.graph-adapt", "local:registry:graph.code-intel-understand", "local:registry:graph.understand-external", "gap:graph:upstream-revision", "gap:graph:license"], "checkedAt": 1783900800, "expiresAt": 1791676800 }, "compatibilityEvidence": { "evidenceIds": ["local:b02:internal-external-identity-separation", "local:b02:explicit-fallback-only", "gap:graph:external-provider-runtime-matrix"], "checkedAt": 1783900800, "expiresAt": 1791676800 }, - "conformanceEvidence": { "evidenceIds": ["local:b02:graph-adapter-conformance:6593d9770665b24e4fa115c2ea5d710e36a3ed679eaaaf605ced616b2b479662", "local:b02:internal-operation-trace", "local:b02:external-fallback-operation-trace", "gap:graph:external-upstream-conformance"], "checkedAt": 1783900800, "expiresAt": 1791676800 } + "conformanceEvidence": { "evidenceIds": ["local:b02:graph-adapter-conformance:1fb78affea75e267dbdd84e797150937a70f3f1c9f80830eee364976ddcf2b34", "local:b02:internal-operation-trace", "local:b02:external-fallback-operation-trace", "gap:graph:external-upstream-conformance"], "checkedAt": 1783900800, "expiresAt": 1791676800 } }, "operationTrace": [ - { "integrationId": "provider.graph-adapt", "operation": "adapt", "command": "target/debug/code-intel.exe provider graph-adapt --request --artifact-root --evaluated-at --max-age-seconds ", "implementationIdentity": { "providerId": "code-intel.graph", "implementationId": "graph-adapter.v1", "activation": "primary" }, "source": { "path": "crates/code-intel-cli/src/graph_adapter.rs", "sha256": "339536b6756cecd60b706faafb3ee9f53f8c1436ac6d2becb0448d27dc0b0322" }, "conformance": { "path": "crates/code-intel-cli/tests/graph_adapter.rs", "sha256": "6593d9770665b24e4fa115c2ea5d710e36a3ed679eaaaf605ced616b2b479662", "testName": "public_route_usage_registry_facade_and_schemas_are_real" } }, - { "integrationId": "provider.graph-adapt", "operation": "facade", "command": "legacy/run-code-intel.ps1 -GraphAdapterRequest -GraphAdapterArtifactRoot -GraphAdapterEvaluatedAt -GraphAdapterMaxAgeSeconds ", "implementationIdentity": { "providerId": "code-intel.graph", "implementationId": "graph-adapter.v1", "activation": "compatibility_facade" }, "source": { "path": "crates/code-intel-cli/src/graph_adapter.rs", "sha256": "339536b6756cecd60b706faafb3ee9f53f8c1436ac6d2becb0448d27dc0b0322" }, "conformance": { "path": "crates/code-intel-cli/tests/graph_adapter.rs", "sha256": "6593d9770665b24e4fa115c2ea5d710e36a3ed679eaaaf605ced616b2b479662", "testName": "public_route_usage_registry_facade_and_schemas_are_real" } }, + { "integrationId": "provider.graph-adapt", "operation": "adapt", "command": "target/debug/code-intel.exe provider graph-adapt --request --artifact-root --evaluated-at --max-age-seconds ", "implementationIdentity": { "providerId": "code-intel.graph", "implementationId": "graph-adapter.v1", "activation": "primary" }, "source": { "path": "crates/code-intel-cli/src/graph_adapter.rs", "sha256": "339536b6756cecd60b706faafb3ee9f53f8c1436ac6d2becb0448d27dc0b0322" }, "conformance": { "path": "crates/code-intel-cli/tests/graph_adapter.rs", "sha256": "1fb78affea75e267dbdd84e797150937a70f3f1c9f80830eee364976ddcf2b34", "testName": "public_route_usage_registry_facade_and_schemas_are_real" } }, + { "integrationId": "provider.graph-adapt", "operation": "facade", "command": "legacy/run-code-intel.ps1 -GraphAdapterRequest -GraphAdapterArtifactRoot -GraphAdapterEvaluatedAt -GraphAdapterMaxAgeSeconds ", "implementationIdentity": { "providerId": "code-intel.graph", "implementationId": "graph-adapter.v1", "activation": "compatibility_facade" }, "source": { "path": "crates/code-intel-cli/src/graph_adapter.rs", "sha256": "339536b6756cecd60b706faafb3ee9f53f8c1436ac6d2becb0448d27dc0b0322" }, "conformance": { "path": "crates/code-intel-cli/tests/graph_adapter.rs", "sha256": "1fb78affea75e267dbdd84e797150937a70f3f1c9f80830eee364976ddcf2b34", "testName": "public_route_usage_registry_facade_and_schemas_are_real" } }, { "integrationId": "provider.graph-adapt", "operation": "capabilityExec", "command": "target/debug/code-intel.exe capability exec provider.graph-adapt --request --out --artifact-root ", "implementationIdentity": { "providerId": "code-intel.graph", "implementationId": "provider.graph-builtin.compat", "activation": "required production capability envelope" }, "source": { "path": "crates/code-intel-cli/src/builtin_provider_evidence.rs", "sha256": "92dcffeeb4226eac01acf1f995cf32ee3c93b4abcd958c9aff461ccdc86bfe9a" }, "conformance": { "path": "crates/code-intel-cli/tests/dag_run.rs", "sha256": "792ffb39dbd46d81e366416ae2e19fcc5eb5f6db688ab593bc22a79fafc8d0f3", "testName": "production_dag_output_commits_and_enters_the_authoritative_index" } }, - { "integrationId": "graph.code-intel-understand", "operation": "refresh", "command": "target/debug/code-intel.exe graph --repo --language zh --write --json", "implementationIdentity": { "providerId": "code-intel.graph", "implementationId": "internal-rust-graph", "activation": "primary" }, "source": { "path": "crates/code-intel-cli/src/graph.rs", "sha256": "6671234c5b00847c7130f535cca5b049030d67f34f6e5341faf45f45b9d01c95" }, "conformance": { "path": "crates/code-intel-cli/tests/graph_adapter.rs", "sha256": "6593d9770665b24e4fa115c2ea5d710e36a3ed679eaaaf605ced616b2b479662", "testName": "internal_and_external_current_outputs_share_one_port_and_provenance_schema" } }, - { "integrationId": "graph.code-intel-understand", "operation": "refreshFull", "command": "target/debug/code-intel.exe graph --repo --language zh --full --write --json", "implementationIdentity": { "providerId": "code-intel.graph", "implementationId": "internal-rust-graph", "activation": "primary" }, "source": { "path": "crates/code-intel-cli/src/graph.rs", "sha256": "6671234c5b00847c7130f535cca5b049030d67f34f6e5341faf45f45b9d01c95" }, "conformance": { "path": "crates/code-intel-cli/tests/graph_adapter.rs", "sha256": "6593d9770665b24e4fa115c2ea5d710e36a3ed679eaaaf605ced616b2b479662", "testName": "internal_and_external_current_outputs_share_one_port_and_provenance_schema" } }, - { "integrationId": "graph.understand-external", "operation": "refresh", "command": "/understand --language zh", "implementationIdentity": { "providerId": "understand-anything", "implementationId": "unverified-upstream", "activation": "explicit_fallback" }, "source": { "path": "docs/graph-provider-adapter.md", "sha256": "9cc96bb7bbd50b6d526dc908be730c90c96f46ed0728cbc51c6abebd7ac94d49" }, "conformance": { "path": "crates/code-intel-cli/tests/graph_adapter.rs", "sha256": "6593d9770665b24e4fa115c2ea5d710e36a3ed679eaaaf605ced616b2b479662", "testName": "fallback_identity_and_payload_identity_cannot_be_relabelled" } }, - { "integrationId": "graph.understand-external", "operation": "refreshFull", "command": "/understand --language zh --full", "implementationIdentity": { "providerId": "understand-anything", "implementationId": "unverified-upstream", "activation": "legacy_rollback" }, "source": { "path": "docs/graph-provider-adapter.md", "sha256": "9cc96bb7bbd50b6d526dc908be730c90c96f46ed0728cbc51c6abebd7ac94d49" }, "conformance": { "path": "crates/code-intel-cli/tests/graph_adapter.rs", "sha256": "6593d9770665b24e4fa115c2ea5d710e36a3ed679eaaaf605ced616b2b479662", "testName": "fallback_identity_and_payload_identity_cannot_be_relabelled" } } + { "integrationId": "graph.code-intel-understand", "operation": "refresh", "command": "target/debug/code-intel.exe graph --repo --language zh --write --json", "implementationIdentity": { "providerId": "code-intel.graph", "implementationId": "internal-rust-graph", "activation": "primary" }, "source": { "path": "crates/code-intel-cli/src/graph.rs", "sha256": "6671234c5b00847c7130f535cca5b049030d67f34f6e5341faf45f45b9d01c95" }, "conformance": { "path": "crates/code-intel-cli/tests/graph_adapter.rs", "sha256": "1fb78affea75e267dbdd84e797150937a70f3f1c9f80830eee364976ddcf2b34", "testName": "internal_and_external_current_outputs_share_one_port_and_provenance_schema" } }, + { "integrationId": "graph.code-intel-understand", "operation": "refreshFull", "command": "target/debug/code-intel.exe graph --repo --language zh --full --write --json", "implementationIdentity": { "providerId": "code-intel.graph", "implementationId": "internal-rust-graph", "activation": "primary" }, "source": { "path": "crates/code-intel-cli/src/graph.rs", "sha256": "6671234c5b00847c7130f535cca5b049030d67f34f6e5341faf45f45b9d01c95" }, "conformance": { "path": "crates/code-intel-cli/tests/graph_adapter.rs", "sha256": "1fb78affea75e267dbdd84e797150937a70f3f1c9f80830eee364976ddcf2b34", "testName": "internal_and_external_current_outputs_share_one_port_and_provenance_schema" } }, + { "integrationId": "graph.understand-external", "operation": "refresh", "command": "/understand --language zh", "implementationIdentity": { "providerId": "understand-anything", "implementationId": "unverified-upstream", "activation": "explicit_fallback" }, "source": { "path": "docs/graph-provider-adapter.md", "sha256": "9cc96bb7bbd50b6d526dc908be730c90c96f46ed0728cbc51c6abebd7ac94d49" }, "conformance": { "path": "crates/code-intel-cli/tests/graph_adapter.rs", "sha256": "1fb78affea75e267dbdd84e797150937a70f3f1c9f80830eee364976ddcf2b34", "testName": "fallback_identity_and_payload_identity_cannot_be_relabelled" } }, + { "integrationId": "graph.understand-external", "operation": "refreshFull", "command": "/understand --language zh --full", "implementationIdentity": { "providerId": "understand-anything", "implementationId": "unverified-upstream", "activation": "legacy_rollback" }, "source": { "path": "docs/graph-provider-adapter.md", "sha256": "9cc96bb7bbd50b6d526dc908be730c90c96f46ed0728cbc51c6abebd7ac94d49" }, "conformance": { "path": "crates/code-intel-cli/tests/graph_adapter.rs", "sha256": "1fb78affea75e267dbdd84e797150937a70f3f1c9f80830eee364976ddcf2b34", "testName": "fallback_identity_and_payload_identity_cannot_be_relabelled" } } ], "economics": { "benefit": { "metric": "B02 implementation identities exercised by swap conformance", "value": 2, "unit": "implementations" }, "cost": { "metric": "registered internal and external implementation lifecycles", "value": 2, "unit": "implementations" }, "benefitEvidence": { "evidenceIds": ["local:b02:internal-external-identity-separation", "gap:graph:representative-utility-measurement"], "checkedAt": 1783900800, "expiresAt": 1791676800 }, "costEvidence": { "evidenceIds": ["local:b02:production-operation-traces", "gap:graph:latency-storage-cost-measurement"], "checkedAt": 1783900800, "expiresAt": 1791676800 } }, "assurance": { "maintenanceEvidence": { "evidenceIds": ["local:b02:replaceable-provider-port", "gap:graph:external-maintenance-status"], "checkedAt": 1783900800, "expiresAt": 1791676800 }, "securityEvidence": { "evidenceIds": ["local:b02:stale-snapshot-rejection", "gap:graph:external-security-review"], "checkedAt": 1783900800, "expiresAt": 1791676800 } }, "update": { "policy": "Before 2026-10-11, independently verify the external provider source, revision, license, maintenance/security status, runtime compatibility, and measured graph utility/cost; never project internal evidence onto the fallback", "nextCheckAt": 1791676800, "evidence": { "evidenceIds": ["gap:graph:update-check"], "checkedAt": 1783900800, "expiresAt": 1791676800 } }, - "ownedModifications": [ { "path": "crates/code-intel-cli/src/graph_adapter.rs", "description": "Pipeline-owned B02 port and adapter with distinct internal/external identities", "evidenceIds": ["local:b02:adapter-source-sha256:339536b6756cecd60b706faafb3ee9f53f8c1436ac6d2becb0448d27dc0b0322", "local:b02:graph-adapter-conformance:6593d9770665b24e4fa115c2ea5d710e36a3ed679eaaaf605ced616b2b479662"] } ], + "ownedModifications": [ { "path": "crates/code-intel-cli/src/graph_adapter.rs", "description": "Pipeline-owned B02 port and adapter with distinct internal/external identities", "evidenceIds": ["local:b02:adapter-source-sha256:339536b6756cecd60b706faafb3ee9f53f8c1436ac6d2becb0448d27dc0b0322", "local:b02:graph-adapter-conformance:1fb78affea75e267dbdd84e797150937a70f3f1c9f80830eee364976ddcf2b34"] } ], "rollback": { "strategy": "select the declared legacy fallback behind provider.graph-adapt or retain the internal Rust provider; direct graph artifacts remain inadmissible", "evidence": { "evidenceIds": ["local:b02:explicit-fallback-only", "local:b02:replaceable-provider-port"], "checkedAt": 1783900800, "expiresAt": 1791676800 } }, "exit": { "strategy": "replace either implementation independently while preserving the B02 port and stale-snapshot rejection", "replacementCriteria": ["replacement has a distinct implementation identity and source provenance", "both internal and fallback conformance fixtures pass without shared claims", "direct artifacts cannot bypass A04"], "evidence": { "evidenceIds": ["local:b02:replaceable-provider-port", "gap:graph:external-exit-drill"], "checkedAt": 1783900800, "expiresAt": 1791676800 } }, "retirement": { "status": "candidate", "triggers": ["external revision or license remains unverifiable", "fallback cannot pass current snapshot and Windows/runtime conformance", "one implementation has no callers and a replacement passes B02"], "evidence": { "evidenceIds": ["local:b02:internal-external-identity-separation", "gap:graph:retirement-proof"], "checkedAt": 1783900800, "expiresAt": 1791676800 } }, - "lifecycle": { "previousStatus": null, "status": "research", "effectiveAt": 1783900800, "replacementRecordId": null, "evidenceIds": ["local:b02:graph-adapter-conformance:6593d9770665b24e4fa115c2ea5d710e36a3ed679eaaaf605ced616b2b479662", "local:b02:internal-operation-trace", "local:b02:external-fallback-operation-trace", "gap:graph:upstream-revision", "gap:graph:license", "gap:graph:representative-utility-measurement"], "authorityEvent": null }, + "lifecycle": { "previousStatus": null, "status": "research", "effectiveAt": 1783900800, "replacementRecordId": null, "evidenceIds": ["local:b02:graph-adapter-conformance:1fb78affea75e267dbdd84e797150937a70f3f1c9f80830eee364976ddcf2b34", "local:b02:internal-operation-trace", "local:b02:external-fallback-operation-trace", "gap:graph:upstream-revision", "gap:graph:license", "gap:graph:representative-utility-measurement"], "authorityEvent": null }, "provenance": { "recordedAt": 1783900800, "recordedBy": "dependency-expert" } }