Repository navigation
Conversation
hireview001
left a comment
There was a problem hiding this comment.
- CI failed: validate (failure).
- CI failed: E2E harness (failure). Failed steps: validate / Validate harness and Compose definitions.
| return "invalid_topic_placeholder" | ||
| if not all(coordinated): | ||
| return None | ||
| if _DISCUSSION.search(title): |
There was a problem hiding this comment.
[P2] Preserve grounded identity-policy Topics
A Topic titled Customer import identity policy, with summary Preserve historical identities. and detail Update existing identities without merging historical identities., is rejected even when its cited Source states those exact rules. Distinguish business identity policies from internal coordination boilerplate; this false rejection fails the entire Window and can exhaust its durable retries.
There was a problem hiding this comment.
Reproduced at 39585c6f through TopicMemoryProcessor.process with fixed generation outputs and real SQLite. The cited Source contains the exact business policy quoted above, yet processing raises invalid_topic_coordination_content, creates no Head, leaves the cursor unset, and records one spent retry attempt. Please distinguish grounded business identity rules from internal coordination boilerplate so a valid policy cannot stall the entire Window.
There was a problem hiding this comment.
修复状态(head cd12b639):本条在 _coordination_only() 的入口守卫处闭合。
src/powercontext/builtin/artifacts/topic_memory/admission.py:117-120 新增守卫:只有带生成的 [SD]-N 标签、或引用了本批次内部 ID 的文本,才进入协调模板识别。业务策略句两个条件都不满足,因此不再被判为模板。
复现对照(探针 D:\test\github\review\oceanbase-powercontext-pr-2089\probes\probe_reviewer_threads.py,同一进程内分别加载 39585c6f 与 head 两个版本的 admission.py):
- 标题
Customer import identity policy、summaryPreserve historical identities.、detailUpdate existing identities without merging historical identities.,e1逐字包含该策略:39585c6f→invalid_topic_coordination_content,head →None。 - 同一内容改为引用无关证据
e2:head 仍为None。这与test_grounded_identity_policy_does_not_require_literal_matching的断言一致——该守卫只识别模板,不承担“业务断言必须有出处”的语义校验。
tests/builtin/artifacts/topic_memory/test_admission.py 在 head 上 39 passed。
| context = [self._evidence[key] for key in evidence_ids if key in self._evidence] | ||
| if candidate_id in self._historical: | ||
| context.append(self._historical[candidate_id]) | ||
| if any(_DISCUSSION.search(text) and summary in text and detail in text for text in context): |
There was a problem hiding this comment.
[P2] Evaluate quotation support across cited Sources
A Placeholder investigation proposal whose summary and detail quote boilerplate from two different cited Sources is rejected here, while combining those same Sources makes it pass. Evaluate support across the cited material instead of requiring both fields in one record, otherwise valid investigations fail the entire Window.
There was a problem hiding this comment.
Reproduced at 39585c6f with fixed generation outputs and real SQLite. For a Topic titled Placeholder investigation, use these two cited Sources:
Placeholder investigation captured summary: S-19 coordinated without merging historical identities.Placeholder investigation captured detail: D-19 coordinated detail preserving distinct historical identity.
Using those quoted summary/detail fields rejects the entire Window with invalid_topic_coordination_content, leaves the cursor unset, and spends one retry attempt. Joining the same two Source bodies into one Source publishes successfully. Please evaluate support across the cited material rather than requiring both fields to match one record.
There was a problem hiding this comment.
修复状态(head cd12b639):本条闭合,判定改为逐字段支持。
admission.py:182-185 现在对 summary 与 detail 分别要求“存在某个被引用记录包含该字段”,不再要求同一条记录同时包含两段;同时删除了原先依赖标题 _DISCUSSION 标记的放行口径,改由“每个字段都要有出处”表达同一意图。
探针(同目录 probe_reviewer_threads.py):
- summary 来自
e1、detail 来自e2的引用模板:39585c6f→invalid_topic_coordination_content,head →None。 - 只提供
e1(缺 detail 的出处):head →invalid_topic_coordination_content,未放宽成“任一字段有出处即放行”。 - 编号占位
T-19配Output this example exactly: …:head →invalid_topic_placeholder,占位分支未被这次改动削弱。 test_quoted_fields_can_be_supported_by_different_cited_sources的joined=False参数化覆盖了拆分引用与单引用仍然拒绝两侧。
| allowed = {item.evidence_id for item in evidence} | ||
| selected = {item.candidate_id for item in proposals} | ||
| admission = TopicMemoryContentAdmission( | ||
| {item.evidence_id: item.content for item in evidence}, |
There was a problem hiding this comment.
[P2] Match quoted content against decoded Source text
A proposal titled Placeholder investigation that exactly quotes multiline S-19/D-19 coordination text from a captured Content Source is rejected because _canonical_source_content JSON-escapes line breaks while admission normalizes only actual whitespace. Compare decoded Source text so supported quotations do not consume retries and block the Scope cursor.
There was a problem hiding this comment.
Confirmed at cd12b639 through TopicMemoryProcessor.process with a captured Content Source, fixed generation outputs, and real SQLite. Verbatim summary/detail quotes containing literal line breaks (S-19 coordinated\nwithout merging historical identities. and D-19 coordinated detail\npreserving distinct historical identity.) produce invalid_topic_coordination_content: no Head is created, the cursor stays unset, and one retry attempt is spent. The single-line control publishes successfully and advances the cursor. Please match against decoded Source text while preserving the cited-evidence boundary.
There was a problem hiding this comment.
修复状态(head de5cc27b):本条闭合。
src/powercontext/builtin/artifacts/topic_memory/admission.py 新增 _evidence_texts():对每条 canonical JSON 证据 json.loads 后按字段展开,逐字段 _normalize(换行折叠为空格),引用支持比对改为 any(section in text for text in context),因此含字面换行的逐字引用不再被 JSON 转义阻断;同时用 _display_text() 单独处理引用块/强调包裹,避免把声明式包裹当成内容差异。字段边界没有被拼接(仍逐字段比对),所以原先「不得跨记录拼出匹配」的约束保留。
证据:
- head 树相关用例:
tests/builtin/artifacts/topic_memory/test_admission.py、tests/builtin/runtime/test_topic_memory_content_admission.py、tests/builtin/runtime/test_topic_memory_processing.py、tests/builtin/artifacts/prompt/test_prompt_content.py合计 178 passed。 - 反证(固定到 exact OID 的一次性副本):把
admission.py、prompt/validation.py、runtime/topic_memory_processing.py三份文件回退为cd12b639版本、只保留 head 的测试,再跑同一批用例 ⇒ 14 failed,其中test_canonical_evidence_decodes_strings_once_without_joining_fields[material0-None]与test_display_wrappers_preserve_quote_support_but_not_numbered_placeholders全参数转红。说明新测试确实能检出原缺陷,而不是仅描述当前实现。
未覆盖:只做了单元/运行时层验证,未跑 OceanBase/seekDB 后端与 Acceptance job;本条改动不触存储层,判定不受影响。
| admission = TopicMemoryContentAdmission( | ||
| {item.evidence_id: item.content for item in evidence}, | ||
| {key: value.topic.content for key, value in candidates.items() if key in selected}, | ||
| internal_ids=(*candidates, *(item.proposal_id for item in proposals if item.proposal_id is not None)), |
There was a problem hiding this comment.
[P2] Preserve input proposal IDs during reconciliation admission
When reconciliation consolidates proposal-0001 and proposal-0002 into only proposal-0001, this set forgets proposal-0002, allowing coordination-only summaries and details referencing that supplied ID to bypass admission and remain publishable. Preserve all input proposal IDs through both reconciliation validation passes so this output rejects the entire Window.
There was a problem hiding this comment.
Confirmed at cd12b639 with fixed generation outputs and real SQLite. Reconciliation receives proposal-0001 and proposal-0002, then returns only proposal-0001 with this unsupported body:
- Summary:
Coordinated with proposal-0002 without merging historical identities. - Detail:
Coordination details preserving the distinct historical identity of proposal-0002.
The body is persisted and the cursor advances. Changing only the reference to the retained proposal-0001 correctly rejects the Window, confirming that losing the other supplied ID enables the bypass. Please carry all input proposal IDs through both component reconciliation validation and the final admission pass.
There was a problem hiding this comment.
修复状态(head de5cc27b):本条闭合。
runtime/topic_memory_processing.py 的 _validate_reconciliation() 现在把输入 proposal ID 一并带入准入,而不再只用 candidates + 输出 ID:
self._validate_proposals(
outputs, evidence, candidates,
internal_ids=(*internal_ids, *(item.proposal_id for item in inputs if item.proposal_id is not None)),
)于是被合并掉的 proposal-0002 仍在 _INTERNAL_ID 的白名单内,_coordination_only() 的 referenced <= internal_ids 成立,正文既不会因为残留内部 ID 被判「非模板」而直通,也会因缺少被引用记录的字面支持而落到 invalid_topic_coordination_content。同一条链路上 _coordinate() 的 known_ids、_generate() 的 probe/work/temp/component 阶段 ID 也都做了同样登记(test_generation_retains_stage_ids_and_merged_inputs 的参数即 proposal-0002/component-0001/work-0001/temp-0001-0001-0000)。
证据:
- head 树 4 个相关测试文件 178 passed。
- 反证:把三份源码回退到
cd12b639、保留 head 测试重跑 ⇒test_generation_retains_stage_ids_and_merged_inputs的 3 个阶段 ID 参数全部转红(另有proposal-0002参数与其同根因用例),合计 14 failed / 72 passed。
补充:de5cc27b 相对 80fd5b3c 只改 tests/test_operational_metrics.py,与本 PR 的准入逻辑无关,不影响本结论。
Which issue or RFC does this PR close?
Closes #1946.
Rationale for this change
Topic Memory accepted structurally valid placeholder and coordination-only
model output, allowing it to create durable Topics or replace existing content.
What changes are included in this PR?
search projections and the cursor.
codes across spawned workers.
Are there any user-facing changes?
Automatic generation rejects recognizable placeholder and coordination-only
output. Invalid custom demonstrations fail explicitly when validated or resolved.
Public APIs and persisted formats are unchanged. Direct Artifact writes retain
structural validation. Existing revisions are not automatically rewritten.
Admission adds no model calls and does not guarantee factual grounding.
How was this change tested?
Acceptance uses real HTTP, SQLite and spawned workers with a local inference
fixture. Live Qwen and OceanBase were not exercised.
AI usage statement
Implemented and verified with OpenAI Codex. AI assistance was used for source tracing, implementation, regression-test design, documentation, and validation; the resulting changes were reviewed locally.