From 9f1c9d8b910ce787d10587e5ab530b4a41220c17 Mon Sep 17 00:00:00 2001 From: Yvette Carlisle Date: Fri, 3 Jul 2026 01:35:46 -0400 Subject: [PATCH] {"schema":"decodex/commit/1","summary":"Guard Knowledge Workspace memory candidates as review proposals","authority":"XY-1153"} --- docs/log.md | 3 +++ docs/spec/system_knowledge_pages_v1.md | 9 +++++++++ .../elf-service/src/knowledge/tests_helpers.rs | 8 ++++++++ packages/elf-service/src/knowledge/tests_memory.rs | 13 +++++++++++++ .../src/knowledge/watch/candidates/proposal.rs | 14 ++++++++++++++ 5 files changed, 47 insertions(+) diff --git a/docs/log.md b/docs/log.md index 1d398c4f..df953b68 100644 --- a/docs/log.md +++ b/docs/log.md @@ -170,3 +170,6 @@ logs. - Preserved historical benchmark evidence rows that recorded the former singular check command, and constrained docs task validation to allow only those exact legacy evidence references. +- Added the XY-1153 Knowledge Workspace authority-boundary marker for changed-source + memory candidates so derived page deltas remain reviewable consolidation proposals + and cannot directly mutate Memory Authority or source evidence. diff --git a/docs/spec/system_knowledge_pages_v1.md b/docs/spec/system_knowledge_pages_v1.md index 93749b59..e507b862 100644 --- a/docs/spec/system_knowledge_pages_v1.md +++ b/docs/spec/system_knowledge_pages_v1.md @@ -176,6 +176,15 @@ nested source refs. - `allowed_variance` - `previous_version_diff` +Knowledge delta memory candidates produced by changed-source watch/rebuild are +review proposals only. Their proposed payload and diff must carry +`elf.knowledge_delta.authority_boundary/v1` with +`authority = "derived_non_authoritative"`, +`review_surface = "consolidation_proposals"`, +`promotion_required_for_memory_authority = true`, +`direct_memory_ledger_mutation_allowed = false`, and +`source_mutation_allowed = false`. + `previous_version_diff` must use schema `elf.knowledge_page.version_diff/v1`. Initial rebuilds must set `available = false` and explain that no previous version exists. Later rebuilds must set `available = true` and include previous and new diff --git a/packages/elf-service/src/knowledge/tests_helpers.rs b/packages/elf-service/src/knowledge/tests_helpers.rs index 4cd39bcb..c11083a0 100644 --- a/packages/elf-service/src/knowledge/tests_helpers.rs +++ b/packages/elf-service/src/knowledge/tests_helpers.rs @@ -165,6 +165,14 @@ pub(super) fn assert_candidate_is_reviewable(candidate: &KnowledgeDeltaMemoryCan assert_eq!(candidate.source_refs[0].kind.as_str(), "note"); assert_eq!(candidate.source_snapshot["source_mutation_allowed"], false); assert_eq!(candidate.diff.after["reason"], "changed_claim"); + assert_eq!( + candidate.diff.after["authority_boundary"]["review_surface"], + "consolidation_proposals" + ); assert_eq!(candidate.proposed_payload["type"], "plan"); + assert_eq!( + candidate.proposed_payload["authority_boundary"]["authority"], + "derived_non_authoritative" + ); assert_eq!(candidate.proposed_payload["source_ref"]["schema"], "elf.knowledge_delta/v1"); } diff --git a/packages/elf-service/src/knowledge/tests_memory.rs b/packages/elf-service/src/knowledge/tests_memory.rs index 82d3fea1..0cc4388d 100644 --- a/packages/elf-service/src/knowledge/tests_memory.rs +++ b/packages/elf-service/src/knowledge/tests_memory.rs @@ -25,7 +25,20 @@ fn memory_candidate_uses_reviewable_consolidation_proposal_contract() { assert_eq!(proposal.apply_intent, ConsolidationApplyIntent::CreateDerivedNote); assert_eq!(proposal.source_refs.len(), 1); + assert_eq!(proposal.diff.after["authority_boundary"]["authority"], "derived_non_authoritative"); + assert_eq!( + proposal.diff.after["authority_boundary"]["direct_memory_ledger_mutation_allowed"], + false + ); assert_eq!(proposal.proposed_payload["source_ref"]["source_mutation_allowed"], false); + assert_eq!( + proposal.proposed_payload["authority_boundary"]["review_surface"], + "consolidation_proposals" + ); + assert_eq!( + proposal.proposed_payload["authority_boundary"]["promotion_required_for_memory_authority"], + true + ); assert_eq!(proposal.proposed_payload["source_ref"]["reason"], "changed_claim"); assert!(!proposal.markers.staleness.is_empty()); } diff --git a/packages/elf-service/src/knowledge/watch/candidates/proposal.rs b/packages/elf-service/src/knowledge/watch/candidates/proposal.rs index b0db3907..b13ccf2a 100644 --- a/packages/elf-service/src/knowledge/watch/candidates/proposal.rs +++ b/packages/elf-service/src/knowledge/watch/candidates/proposal.rs @@ -48,6 +48,7 @@ pub(in crate::knowledge::watch::candidates) fn candidate_diff( "page_id": page.page.page_id, "section_id": section.section_id, "section_key": section.section_key, + "authority_boundary": knowledge_delta_authority_boundary(), }), } } @@ -77,6 +78,7 @@ pub(in crate::knowledge::watch::candidates) fn candidate_proposed_payload( "scope": "project_shared", "importance": 0.65, "confidence": 0.72, + "authority_boundary": knowledge_delta_authority_boundary(), "source_ref": { "schema": "elf.knowledge_delta/v1", "reason": reason, @@ -89,6 +91,18 @@ pub(in crate::knowledge::watch::candidates) fn candidate_proposed_payload( }) } +fn knowledge_delta_authority_boundary() -> Value { + serde_json::json!({ + "schema": "elf.knowledge_delta.authority_boundary/v1", + "origin_layer": "knowledge_workspace", + "authority": "derived_non_authoritative", + "review_surface": "consolidation_proposals", + "promotion_required_for_memory_authority": true, + "direct_memory_ledger_mutation_allowed": false, + "source_mutation_allowed": false, + }) +} + fn candidate_markers(candidate: &KnowledgeDeltaMemoryCandidate) -> ConsolidationMarkers { let marker = ConsolidationMarker { severity: ConsolidationMarkerSeverity::Medium,