160 lines
7.9 KiB
Markdown
160 lines
7.9 KiB
Markdown
# Chat External Fact QA Guardrails 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:** Stop chat-mode Feishu Q&A from using internal PMFlow evidence to answer external latest/fact questions, and make factual pushback stay in natural chat instead of falling into AI PMO correction prose.
|
|
|
|
**Architecture:** Keep requirement-plan and draft-confirm chains unchanged. Implement a narrow chat-only policy inside Adaptive RAG that detects external factual chat questions, isolates retrieval from internal project noise, downgrades safely when no live external evidence exists, and keeps follow-up fact challenges in the same chat scene.
|
|
|
|
**Tech Stack:** FastAPI backend, Adaptive RAG mixins, PostgreSQL-backed QA records, control-plane routing, pytest.
|
|
|
|
---
|
|
|
|
### Task 1: Add Chat External-Fact Policy Flags
|
|
|
|
**Files:**
|
|
- Modify: `backend/app/services/adaptive_rag_service/mixin_answer_mainline.py`
|
|
- Modify: `backend/app/services/adaptive_rag_service/mixin_followup_anchor.py`
|
|
- Test: `backend/tests/test_adaptive_rag_mainline_contract.py`
|
|
|
|
- [ ] **Step 1: Write failing tests for chat-only external fact follow-up**
|
|
|
|
Add tests that prove:
|
|
- an external-trend/latest question is marked as chat external fact policy
|
|
- a follow-up like “不对吧,已经有 xxx 了” anchored to a prior `external_trend` / `industry_trend` answer stays in chat QA and does not inherit AI PMO correction behavior
|
|
|
|
- [ ] **Step 2: Resolve anchored prior answer scene from QA record**
|
|
|
|
Read the anchored `QARecord` via existing follow-up resolution and derive the prior prompt variant from `policy_version` so chat logic can tell whether the previous reply was `external_trend` or `industry_trend`.
|
|
|
|
- [ ] **Step 3: Add a narrow chat external-fact policy helper**
|
|
|
|
Implement a helper in `mixin_answer_mainline.py` that derives flags such as:
|
|
- `external_fact_chat`
|
|
- `requires_freshness`
|
|
- `chat_fact_challenge`
|
|
- `allow_internal_refine`
|
|
|
|
These flags must be derived from current scene + question + anchored prior QA record, not from requirement-plan state.
|
|
|
|
- [ ] **Step 4: Thread the policy flags through answer runtime**
|
|
|
|
Pass the new flags into retrieval/execution flow without changing requirement-plan ingress or workflow planner behavior.
|
|
|
|
- [ ] **Step 5: Run focused tests**
|
|
|
|
Run: `pytest backend/tests/test_adaptive_rag_mainline_contract.py -k "external or correction or followup" -v`
|
|
|
|
|
|
### Task 2: Isolate Retrieval for External Latest Questions
|
|
|
|
**Files:**
|
|
- Modify: `backend/app/services/adaptive_rag_service/mixin_multistep_flow.py`
|
|
- Modify: `backend/app/services/adaptive_rag_service/mixin_multistep_core.py`
|
|
- Modify: `backend/app/services/adaptive_rag_service/mixin_answer_retrieval.py`
|
|
- Test: `backend/tests/test_adaptive_rag_mainline_contract.py`
|
|
|
|
- [ ] **Step 1: Write failing tests for retrieval contamination**
|
|
|
|
Add regression tests that prove:
|
|
- `external_trend` / latest questions do not expand into `Project#104`, `#codex-plan*`, module paths, or feature catalog hints
|
|
- second-pass query refinement does not append internal entities/modules for this chat policy
|
|
|
|
- [ ] **Step 2: Disable internal second-pass hint expansion for external fact chat**
|
|
|
|
When `external_fact_chat=true`, skip internal refinement based on manifest, graph entities, project anchors, feature catalog, and symbol hints.
|
|
|
|
- [ ] **Step 3: Restrict evidentiary domains**
|
|
|
|
For external factual latest questions, internal `db / graph / pmflow / feishu / feature_catalog` sources must not be used as grounding for the external fact itself.
|
|
|
|
Allowed behavior:
|
|
- explicit external URL/doc evidence may ground the answer
|
|
- internal PMFlow context may only support “why this matters to your tenant/project”, never “what is the latest external fact”
|
|
|
|
- [ ] **Step 4: Preserve existing internal QA behavior**
|
|
|
|
Make sure non-external chat questions and PMFlow internal feature/status questions still use the current retrieval stack unchanged.
|
|
|
|
- [ ] **Step 5: Run focused tests**
|
|
|
|
Run: `pytest backend/tests/test_adaptive_rag_mainline_contract.py -k "external_trend or industry_trend or retrieval" -v`
|
|
|
|
|
|
### Task 3: Add Freshness Guard and Natural Chat Correction Style
|
|
|
|
**Files:**
|
|
- Modify: `backend/app/services/adaptive_rag_service/mixin_deep_guard_rules.py`
|
|
- Modify: `backend/app/services/adaptive_rag_service/mixin_answer_retrieval.py`
|
|
- Modify: `backend/app/services/adaptive_rag_service/mixin_deep_guard_answer.py`
|
|
- Modify: `backend/app/config/ai_prompts_catalog/part_scenes_06.py`
|
|
- Test: `backend/tests/test_adaptive_rag_mainline_contract.py`
|
|
- Test: `backend/tests/test_draft_confirm_handler.py`
|
|
|
|
- [ ] **Step 1: Write failing tests for unsafe “grounded latest” replies**
|
|
|
|
Cover these cases:
|
|
- no external evidence + question asks “最新/目前/截至现在” => answer must explicitly say no real-time data
|
|
- grounding status must not be `grounded`
|
|
- reply must not inject project IDs, internal routes, or AI config guidance unless user explicitly asked for tenant impact
|
|
|
|
- [ ] **Step 2: Add external freshness guard**
|
|
|
|
Extend guard logic so external factual latest questions are blocked or downgraded when there is no explicit external evidence. Static internal sources must not satisfy freshness requirements.
|
|
|
|
- [ ] **Step 3: Rewrite answer fallback shape**
|
|
|
|
When no live external evidence exists, answer should look like normal chat:
|
|
- first sentence admits lack of real-time data / inability to confirm latest
|
|
- second sentence may give bounded generic context
|
|
- optional final sentence can ask whether to check tenant config separately
|
|
|
|
Forbidden output in this policy:
|
|
- “结论 / 证据链 / 待确认清单” tribunal style
|
|
- treating internal tags or knowledge-graph entities as external market evidence
|
|
|
|
- [ ] **Step 4: Strengthen prompt constraints as secondary guard**
|
|
|
|
Update `PROMPT_EXTERNAL_TREND_QA` / `PROMPT_INDUSTRY_TREND_QA` so they explicitly say:
|
|
- internal PMFlow graph/feature/catalog sources are not external search results
|
|
- if freshness is required and no external evidence is provided, do not claim exact latest version/model status
|
|
|
|
- [ ] **Step 5: Review deep-routing behavior**
|
|
|
|
Do not let this path silently force low-first deep reasoning for fact challenges. If needed, keep the safe downgrade path on low tier now; if quality still falls short, introduce a dedicated external-fact answer function in a separate patch rather than raising all chat traffic.
|
|
|
|
- [ ] **Step 6: Run focused tests**
|
|
|
|
Run:
|
|
- `pytest backend/tests/test_adaptive_rag_mainline_contract.py -k "freshness or external or correction" -v`
|
|
- `pytest backend/tests/test_draft_confirm_handler.py -k "industry_trend or external_trend" -v`
|
|
|
|
|
|
### Task 4: Verify Runtime Safety and Sync Guardrail Docs
|
|
|
|
**Files:**
|
|
- Modify: `docs/architecture/RUNTIME_GUARDRAILS.md`
|
|
- Test: `backend/tests/test_adaptive_rag_mainline_contract.py`
|
|
|
|
- [ ] **Step 1: Add runtime guardrail note**
|
|
|
|
Document that chat-mode external factual latest questions cannot treat PMFlow internal graph/catalog/project evidence as external fact grounding, and anchored factual pushback must stay in chat unless explicitly tied to requirement/draft workflow.
|
|
|
|
- [ ] **Step 2: Run broader regression checks**
|
|
|
|
Run:
|
|
- `python -m py_compile backend/app`
|
|
- `pytest backend/tests/test_adaptive_rag_mainline_contract.py -v`
|
|
|
|
- [ ] **Step 3: Sanity-check that requirement-plan mainline is untouched**
|
|
|
|
Run a narrow requirement-plan regression slice:
|
|
- `pytest backend/tests/test_ai_pmo_ingress_mainline.py -k "requirement_plan or draft" -v`
|
|
|
|
- [ ] **Step 4: Commit**
|
|
|
|
```bash
|
|
git add backend/app/services/adaptive_rag_service backend/app/config/ai_prompts_catalog/part_scenes_06.py backend/tests/test_adaptive_rag_mainline_contract.py backend/tests/test_draft_confirm_handler.py docs/architecture/RUNTIME_GUARDRAILS.md docs/superpowers/plans/2026-04-13-chat-external-fact-qa-guardrails.md
|
|
git commit -m "fix: harden chat external fact QA guardrails"
|
|
```
|