Status: active Scope: diagnosis input ownership, schema ownership, ai-runs ownership, local/crossdomain cognition boundaries See also:
DESIGN.md,DESIGN_SCHEMA.md,DESIGN_GOLDEN.md,APP_MIGRATION_HANDBOOK.mdTracking:dakoolfrank/nexrur#140版本: v1.1 所属: nexrur 底座
状态: 核心设计文档(系统级)
定位: program-first LLM agent 的统一诊断中枢设计
目录
- 一句话定位
- 为什么 Diagnosis 是核心中的核心
- Diagnosis 在系统中的位置
- 核心原则
- Diagnosis 的五桶 evidence 输入体系
- Diagnosis 的输出体系
- 底座与应用层边界
- Consumer Diagnosis Asset Pack 标准
- Diagnosis 与 ToolLoop / Campaign / Orchestrator 的关系
- 与 core / memory 的关系
- 标准数据流
- 文件归属与目录设计
- 为什么不能让 app 继续长 diagnosis engine
- 与 Cross-Domain / Cognition 的统一关系
- Diagnosis Input Ownership
- Diagnosis And Multi-App Execution
- ai-runs Ownership Model
- Future runroot Refactor Constraints
- 迁移路线
- 完成定义
- 反模式与禁止事项
- 一句话总结
1. 一句话定位
Diagnosis 是 nexrur 的统一诊断中枢:它是 program-first agent 的“眼睛与大脑”,统一消费五桶 evidence 与 consumer diagnosis assets,并向 campaign 提供可执行路由前的解释与建议。
它不是普通 helper,不是 campaign 的附属品,也不是某个 consumer 的局部技巧模块。它是:
- nexrur 的核心智能解释器
- fail-to-pivot 的核心判断器
- diagnosis_result 的统一产生器
- 证据链的最大消费者
2. 为什么 Diagnosis 是核心中的核心
很多系统会先拥有:
- Orchestrator
- Campaign
- ToolLoop
- Evidence
- 显式 memory / cognition / cross-domain 输入
- Memory
但如果 Diagnosis 没有真正站在这些资产的中心消费它们,就会出现一个典型问题:
四肢很强,但大脑失明
也就是:
- orchestrator 在排步骤
- campaign 在跑循环
- toolloop 在做局部工具探索
- evidence 在积累事实
- memory 在积累经验
但是最核心的 LLM 判断层没有统一消费这些依据,导致:
- 路由建议不稳定
- fail-to-pivot 缺乏统一解释器
- route hint 变成局部 patch,而不是全证据链判断
- cross-domain lesson 无法真正进入主脑
- cognition(brief/validation)无法变成可计算的上游依据
所以 Diagnosis 的意义不只是“多一个诊断模块”,而是:
把 program-first 架构辛苦积累的全证据链真正交给大脑去解释。
3. Diagnosis 在系统中的位置
┌──────────────────────────────────────────┐
│ Consumer Apps / Domain Skills │
│ WQ-YI / AGV / AUDIT / others │
└──────────────────────┬───────────────────┘
│
│ 提供标准化 diagnosis assets
▼
┌──────────────────────────────────────────┐
│ Consumer Diagnosis Asset Pack │
│ evidence / catalog / golden │
│ cases / counterexamples / patterns │
└──────────────────────┬───────────────────┘
│
│ consumer semantics
▼
┌────────────────────────────────────────────────────────────────────────────┐
│ nexrur Diagnosis Substrate │
│ │
│ core -> app run ledger / manifest / outcome / audit refs │
│ engines -> orchestrator / campaign / toolloop bounded execution facts │
│ aiskills -> app active business artifacts / schema / diagnosis projections │
│ memory -> contentstore / vectorstore historical recall units │
│ golden -> approved diagnosis positive cases / counterexamples / patterns │
│ │
│ context.py │
│ select / normalize / deduplicate / bound material -> DiagnosisInput │
│ diagnosis.py │
│ DiagnosisInput -> diagnosis_result │
│ result_code / confidence / evidence_refs / explanation │
└──────────────────────────────┬─────────────────────────────────────────────┘
│
│ validated diagnosis result only
▼
┌──────────────────────────────────────────┐
│ campaign.py │
│ continue / continue_with_repair │
│ restart / reroute / halt / budget │
│ restart target subagent from phase 1 │
└──────────────────────────────────────────┘
最关键的一点:
- Diagnosis 解释
- Campaign / Orchestrator 裁决与执行
这正是 program-first 的核心分工。
4. 核心原则
4.1 Program-first,不是 LLM-governed
Diagnosis 再强,也只能:
- 解释证据
- 归纳根因
- 输出独立
diagnosis_result.result_code - 说明 why_not_others
Diagnosis 不能直接:
- 改 checkpoint
- 改 budget
- reset/replay
- halt campaign
- 强行改 final route
这些必须由:
campaign.pyorchestrator.py- 未来的 controller 层
来决定。
4.2 Diagnosis 是统一解释层,不是业务真身
底座 Diagnosis 负责:
- “怎么诊断”
- “怎么合并证据”
- “怎么做 flash/pro review”
- “怎么输出 suggestion”
consumer 负责:
- “在这个业务域里,什么信号意味着什么”
- “哪些 Diagnosis result code 存在”
- “diagnosis result_code -> target_step 如何映射”
- “重复失败如何升级”
4.3 底座统一,应用收窄
Diagnosis 的未来不是每个 app 都各写一套 toolloop_diagnosis.py。
Diagnosis 的未来是:
- 底座只有一个 engine
- app 只提供标准化资产包
就像 Claude Code:
- skill 可以不同
- knowledge 可以不同
- 但 agent 大脑不应该每个 app 自己重写一份
4.4 Product 结果所有权与 Diagnosis 命名空间
Production 拥有本轮 Product 结果的唯一定义权:
production_result.status
production_result.reason
production_result.reason_code
这三个字段是当前 cycle 的业务事实。Evidence、Schema、Step6、 Diagnosis、Campaign 和 Orchestrator 都只能读取、记录和原样转运, 不得覆盖、补全、canonicalize、压缩或重新选择它们。
Diagnosis 回答的是“Diagnosis 如何解释这个 Product 结果”, 必须使用独立命名空间:
diagnosis_result.result_code
diagnosis_result.explanation
diagnosis_result 中禁止再出现 reason_code,也不保留兼容别名或
双写。result_code 是诊断分类,不是 Product reason;它可以与
production_result.reason_code 文本相同,但字段所有权和语义仍然分离。
Diagnosis 不输出 Product-like pass / partial / stop、governance_class
或 recommended_disposition。Campaign 可以读取
diagnosis_result.result_code 决定后续 cycle 的 continue / rerun / halt,
但不得因此改写当前 cycle 的 Product 结果。只有后续 cycle
重新运行 Production,才可能产生新的 Product status/reason。
Step6 只组合 Diagnosis 与 Campaign 的独立结果,不得把
diagnosis_result.result_code 提升为 Step6、child graph 或 parent graph 的
Product reason_code。若 Production 未返回有效结果而是突然崩溃,底座
可以另行记录 runtime incident,但不得冒充 Product reason。
5. Diagnosis 的五桶 evidence 输入体系
Diagnosis 必须统一消费五桶 evidence,而不是只看某个 step 的局部日志,也不是把 memory / cognition / cross-domain 当成绕过 evidence bundle 的独立判断层。
| Bucket | Diagnosis 中的作用 | 典型来源 |
|---|---|---|
core | 当前 app trace/cycle 的运行账本与 artifact refs | .core manifest / outcome / audit / evidence refs |
engines | 底座执行事实的 deterministic index | orchestrator checkpoint index、campaign state、toolloop events index |
aiskills | app 业务真值与 active projection | production / schema / diagnosis / envelopes / digest refs |
memory | 历史经验与 recall,不是当前事实 | contentstore / vectorstore bounded retrieved units |
golden | 已审核 diagnosis 案例 grounding | positivecases / counterexamples / patterns |
五桶共同回答:
- 发生了什么事实?
- 哪一步失败或降级?
- failure signal 来自 production、schema/validation、engines runtime,还是 app 业务约束?
- 是否有 memory/cognition/crossdomain 经验支持某个解释?
- 这个解释能否追溯到 artifact/evidence refs?
硬约束:
- Diagnosis 不接受一句话 error 作为充分输入。
- Memory/cognition/crossdomain 只能作为
memorybucket 证据,不能直接触发 route / halt。 - Golden 只能作为 approved case grounding;selector result 不是 diagnosis verdict。
- App 的 source truth 必须来自 app-owned manifest / asset pack;底座只解释和读取。
evidence_refs与artifact_refs必须可审计。
5.1 Evidence Context And Diagnosis Evidence Share One Evidence Contract
Consumer apps may use evidence.py or equivalent adapters to build Step 1/2/3
context, but the generic source truth must be an app-owned evidence manifest.
For WQ-YI this manifest is:
.gemini/skills/_shared/engines/evidence/evidence.yml
The substrate diagnosis/evidence line owns the generic mechanism:
evidence.yml
-> five-bucket readers: core / engines / aiskills / memory / golden
-> evidence bundle
-> evidence digest
-> pre-LLM selector digest
-> obligations
-> current_scope / upstream_feedback
The substrate prompt asset for this pre-LLM evidence line is
src/nexrur/prompts/evidence.md. It owns two sections:
evidence.md::evidence_digest
-> consumed only by build_evidence_digest
evidence.md::pre_llm_selector
-> consumed only by build_evidence_digest selector builder
-> writes selector trace into golden digest for later handoff
The old standalone digest.md prompt has been renamed into
evidence.md::evidence_digest and must not remain as a separate active prompt
truth. Legacy pre-LLM selector text that used to live in app selector.md
files or diagnosis prompt preambles belongs in evidence.md::pre_llm_selector;
app-owned selector profiles may still supply owner/module goals and forbidden
scope.
The five-bucket readers remain the same across first evidence, Step 6
diagnosis preparation, and campaign restart. The substrate builder, not the
reader, selects the assembly contract through evidence_assembly_mode:
facts_evidence -> first phase-1 evidence for Production
step6_evidence -> bounded Step 6 handoff with diagnosis_evidence_packet
restart_evidence -> campaign restart feedback projected into phase-1 evidence
production_evidence and step6_evidence are active total handoff envelopes, not
selector-only traces. build_obligations.py may copy existing digest manifest /
bucket refs / selector trace into them, but it must not run digest or selector
LLM. Both must embed the evidence core: facts summary, obligations,
current_scope, upstream_feedback, missing/degraded/fallback facts, and
evidence/artifact refs. A evidence_ref may be present for debug/lineage, but it
is not sufficient as the active LLM handoff.
step6_evidence additionally contains validation facts, not full schema truth;
runtime failure facts, not a full runtime dump; production/schema refs; and a
canonical diagnosis_evidence_packet. That packet is the fail2pivot input. It
must expose requires_diagnosis, trigger_signals, failure_kind, bounded
validation/schema/production/runtime/phase facts, refs, and the diagnosis-mode
pre_llm_selector / Prompt A result when golden cognition is enabled. The
selector result is not the diagnosis verdict: it only chooses approved positive
cases, counterexamples, or patterns for Diagnosis Prompt B/C.
step6_evidence may also carry an explicitly prepared memory_recall bucket.
Diagnosis does not open a RAG/vector client or perform runtime retrieval. That bucket is
historical_auxiliary_recall_not_current_truth: Prompt A/B/C may read it as
similar-case context, but it must not replace current evidence, prove a fact,
raise schema confidence, or choose a campaign route. Campaign route, halt,
restart, and Diagnosis result_code stay out of step6_evidence. The original
Production reason_code may appear only inside the canonical Production facts
and must remain an exact copy of the producer-owned value.
step6_evidence_packet is not the canonical diagnosis input; if present, it is
legacy/index-only. An envelope with diagnosis_ready: true but no
diagnosis_evidence_packet is invalid for fail2pivot.
Fail2pivot accepts one strict transport envelope. The caller must provide
app_root, an explicit projection_identity, and exactly one of inline
step6_evidence or step6_evidence_ref. The inline value must be a canonical
step6_evidence_envelope; the referenced file must be named
step6_evidence.json, remain below app_root, stay within 256 KiB, and contain
the same projection_identity. Generic top-level evidence, phase-result
scanning, artifact-ref discovery, and identity aliases such as top-level
product / asset_id / trace_id / cycle_no, workspace, or
canonical_id are not fallback sources and must fail closed.
projection_identity.scope=asset requires asset_id and writes StepSix under
<product>/<asset_id>/<trace_id>/<cycle>/; scope=trace forbids asset_id,
requires the Product projection contract to allow unbound traces, and writes
under <product>/<trace_id>/<cycle>/. Fail2pivot must not invent a placeholder
asset, infer identity from a directory, or silently skip Projection. A failed
Projection changes the StepSix result to failed.
restart_evidence requires diagnosis_result and campaign_control, then
mechanically projects them into canonical upstream_feedback and
current_scope before the target subagent reruns from phase 1.
Step 2 digest is the substrate build_evidence_digest contract. It reads only
the evidence.md::evidence_digest section. It is LLM-assisted but
program-validated: each read content unit from the five-bucket bundle must have
a compact JSON representation and source ref. Digest failure is a
diagnosis-ready failure, not a deterministic fallback success. Step 3
obligations may only assemble a schema-gated envelope from app-owned
declarations, this digest, and evidence refs. The same obligation surface may
then run evidence.md::pre_llm_selector in mode=production or
mode=diagnosis and write production_evidence.json or step6_evidence.json.
Those files must carry the evidence core inline before adding selector results
or failure facts.
Digest, Memory selector/arbitrator and pre-LLM selector profiles must be supplied
explicitly by the App execution envelope. Evidence has no provider or model
default. Digest and selector profiles remain separate contracts.
This evidence context is shared by production and diagnosis. Diagnosis must not
require consumer owners to re-parse source-specific artifacts at Step 6, and
production must not maintain private upstream scanners. If a downstream restart
needs failure context, campaign/diagnosis facts must be represented as generic
upstream_feedback in the evidence context through the restart_evidence
assembly contract.
Substrate code must stay app-neutral. It interprets manifest declarations and normalizes evidence mechanics; it must not hardcode WQ diagnosis result codes, WQ artifact names, or app-specific route semantics. Consumer apps own the business source declarations, diagnosis/catalog semantics, production prompt context, campaign assets, and schema truth.
The allowed adapter role is narrow: app evidence wrappers may project the
substrate evidence/digest/obligation envelope into their local production shape,
but they must not define a second source truth, scan historical app directories
independently, or introduce private feedback channels such as
evaluate_feedback, field_updater_feedback, or previous_evaluate_outcome.
5.2 Evidence Payload JSON-Safe Contract
Five-bucket evidence payloads are runtime contracts, not Python object transport. Any value that crosses the ToolLoop, evidence reader, audit/evidence stream, checkpoint, orchestrator step result, or diagnosis bundle boundary must be JSON-safe.
Allowed payload values:
null, string, number, boolean;- arrays and objects composed only of JSON-safe values;
- path refs as normalized strings, preferably POSIX-style relative paths;
assets_input,artifact_refs,current_scope,upstream_feedback, andmemory_backend_statusrepresented as JSON-safe objects.
Forbidden at those boundaries:
- raw
AssetRefor app-specific runtime objects; Path,datetime,Enum, dataclass, namedtuple, or custom class instances;- open file handles, client/session objects, callables, or other live runtime handles.
Callers must convert runtime objects to JSON-safe values before entering the
Evidence boundary. Evidence itself only compiles the explicit identity envelope
through compile_current_scope(...), which validates:
artifact_refs
current_scope
current_artifact_refs
memory_backend_status
trace/run/step identifiers
AssetRef-like runtime objects should become standard evidence refs, for
example:
{
"kind": "abbreviation",
"id": "ALTI",
"path": "docs/ai-skills/evidence-papers/pending/ALTI",
"metadata": {
"source_type": "academic"
}
}
When richer context is available, apps may include run_id, trace_id,
artifact_kind, source_step, business_path, or nested artifact_refs, but
the resulting object must still pass json.dumps(...).
This contract is substrate-owned and app-neutral. Apps must not patch around
serialization failures by calling str(asset_ref) in local skill code, because
that loses refs and leaves dataset/evaluate/other consumers exposed to the same
boundary bug.
6. Diagnosis 的输入与输出体系
Diagnosis 的输出不是执行动作,而是给 campaign 消费的解释与建议。
6.1 Step 6 最小输入 envelope
每个 app 的 Step 6 diagnosis 输入必须先由底座 Step6 evidence handoff 规整成
diagnosis_evidence_packet:
{
"kind": "diagnosis_evidence_packet",
"version": 1,
"status": "ready",
"subject_id": "...",
"source_subagent": "...",
"source_phase": "...",
"requires_diagnosis": true,
"trigger_signals": [],
"failure_kind": "...",
"validation_facts": {},
"schema_errors": [],
"production_failure_facts": {},
"runtime_failure_facts": {},
"phase_issue_facts": [],
"phase_failure_facts": {},
"diagnosis_facts": {},
"evidence_refs": [],
"artifact_refs": []
}
Fail2pivot 的外层调用不是上述 packet 本身,而是:
{
"app_root": "<explicit app root>",
"projection_identity": {
"product": "<declared product>",
"scope": "asset | trace",
"asset_id": "<required only for asset scope>",
"trace_id": "trace-...",
"cycle_no": 1
},
"step6_evidence": {
"kind": "step6_evidence_envelope",
"step": "step6_evidence",
"phase": "step6_evidence",
"diagnosis_ready": true,
"projection_identity": {},
"diagnosis_evidence_packet": {}
}
}
step6_evidence 可替换为唯一的 step6_evidence_ref,但二者不能同时出现。
需要实际 Diagnosis 时还必须显式提供 current_step、diagnosis_assets_root 和
campaign_contract_path;requires_diagnosis=false 也必须携带完整 canonical packet,
不得以缺 packet 表示“不需要诊断”。两个合同路径按 app_root 解析且必须留在
该 root 内,不能借外部 contract 授予 Candidate 权限。未知输入字段和旧别名必须
fail closed。
说明:
validation_facts对应 Step 5 Validation (schema-driven) 的机械事实。production_failure_facts对应 Step 4 输出里的 failure / degradation signal。runtime_failure_facts来自 engines bounded index,不是 full checkpoint/events。phase_issue_facts按执行顺序保留所有 Production / Schema / runtime 的原始partial / degraded / failed / blocked问题;它是完整诊断输入,不含 route verdict。phase_failure_facts只保留实际阻断当前 graph 的主故障兼容投影,不得替代phase_issue_facts。diagnosis_facts是 app-owned opaque mapping。唯一传输链是 leafresult.control_envelope.diagnosis.facts-> Orchestratorphase_failure_facts.diagnosis_facts-> Step6diagnosis_evidence_packet.diagnosis_facts->DiagnosisInput.evidence。 底座只做类型、深度、条目数和字节上限检查,不枚举 role、不解释数值,也不据此 直接生成 reason 或 route。超限正文必须由标准 refs 指向,packet 只保留 bounded copy 或 shape index。- refs 必须指向五桶 digest / source refs;app 不得在 Step 6 手拼 raw envelope。
所有 Production 都通过 App ToolLoop 合同的 control_envelope 显式声明
哪些 producer status 允许当前图继续。WQ 的 Product 合同把 partial 映射为
graph.disposition=continue,表示“本轮结果有问题,但可继续消费”。底座只读取
编译后的 disposition,不维护 partial/degraded/missing_required 等隐式允许列表。
这一决定不以 artifact_refs 存在为前提;artifact 缺失或不可读只是独立
evidence fact,不是隐藏的 Product status gate。
partial 可以令 requires_diagnosis=true,但 Step6 / Diagnosis / Campaign
不得将它在本轮就地升级为 failed / stop,也不得改写 producer
给出的 reason。若后续需要修复,Campaign 只能安排后续 cycle 重新运行
Production。当前 graph 必须按显式 graph.disposition=continue 继续。
skipped 不是第四种 Product status;合法 skip 由 producer 返回
status=partial 及其原始 reason,后续层仍只能原样转运。
6.2 diagnosis_result envelope
标准输出至少包括:
{
"execution_status": "success | failed",
"result_code": "...",
"explanation": "...",
"confidence": 0.0,
"failure_class": "schema | evidence | coverage | business_semantics | upstream_dependency | runtime | unknown",
"why_not_others": [],
"evidence_refs": [],
"artifact_refs": [],
"metadata": {}
}
diagnosis_result.execution_status 只表示 Diagnosis 这次执行是否产生了合法
诊断,不是 Product status。Diagnosis 不输出 active target_step /
target_subagent、recommended_disposition 或 Product-like status。最终
route / halt / continue 必须由 Campaign 根据
diagnosis_result.result_code 和 campaign.yml 控制,且不改写当前
production_result。
6.2.1 Diagnosis result classification
Step 6 evidence may contain multiple factual signals, including the producer's
immutable reason_code plus schema/runtime facts. Diagnosis may classify those
facts into one independent advisory result_code, but it does not select a
replacement Product reason. The substrate may perform this classification only
through generic rules:
- candidate facts come from the evidence bundle;
signal_class,fallback_only,overridden_by_signal_classes, and priority come from the consumer diagnosis catalog/golden assets;- fallback reasons may be suppressed by stronger signal classes declared in assets;
- priority is only a tie-breaker after asset-declared suppression rules;
- diagnosis returns an advisory
result_codeonly insidediagnosis_result.
Diagnosis still must not execute campaign restart, halt, budget mutation, or checkpoint changes. Campaign remains the only layer that validates and executes the resulting route. No arbitration result may be copied back into Product facts.
6.2.2 Non-blocking Production issue diagnosis
Diagnosis 不能靠“忽略 partial”实现放行。对于 Production 上报的非阻断质量 问题,Diagnosis 必须:
- 消费
phase_issue_facts中该 producer 自己的原始 reason、errors、warnings 和 refs; - 原样保留
production_result.status/reason/reason_code; - 从当前 step scoped
diagnosis.yml选择受证据支持的diagnosis_result.result_code,并给出explanation; - 保留
why_not_others,说明其他诊断分类为何不成立; - 把后续 cycle 的执行权交给 Campaign。
Diagnosis 不判定 partial “能否继续”;这已由 Production 的
status=partial 定义。即使 Diagnosis 失败或无法给出合法
result_code,也只能记录独立 Diagnosis runtime incident,不得把已有
Product partial 改成 stop。
6.3 campaign_control handoff
Campaign 消费 diagnosis 之后应返回独立控制结果,例如:
{
"status": "continue | continue_with_repair | restart_requested | halt | failed",
"target_subagent": null,
"restart_from_phase_1": false,
"internal_phase_hot_repair_allowed": false,
"routing_decision": {}
}
Diagnosis 不直接产出:
- reset 行为
- halt 行为
- budget 扣减
- replay 执行
- lifecycle mutation
- middle-phase restart
- prompt-level patch-and-continue
6.4 Diagnosis fallback_alarm semantics
Fallback is an alarm, not recovery. fallback 是报警,不是恢复成功。
Diagnosis LLM unavailable, no result, no suggestion, adapter signature mismatch,
asset pack mismatch, and malformed diagnosis output must produce
fallback_alarm or an equivalent failed diagnosis envelope. They must not be
normalized into successful diagnosis output.
Minimum failed diagnosis envelope:
{
"diagnosis_result": {
"execution_status": "failed",
"fallback_alarm": {
"triggered": true,
"kind": "llm_unavailable | diagnosis_missing_result | diagnosis_no_suggestion | adapter_mismatch | unknown",
"source": "diagnosis",
"severity": "failed",
"diagnosis_ready": true
}
}
}
Diagnosis must not return a fake result_code, fake target_subagent, fake
suggestion, or execution_status=success to hide fallback. no_suggestion is not
success. If diagnosis cannot produce a valid result, Campaign receives a failed
Diagnosis envelope and decides the Diagnosis retry/escalation or later-cycle
engineering action. That failure remains separate from the already returned
Product result and cannot reclassify a valid Product partial.
7. 底座与应用层边界
Diagnosis 的底座/应用边界必须像 ToolLoop 一样被明确钉死。
7.1 底座负责什么
放在 nexrur:
src/nexrur/engines/diagnosis/src/nexrur/prompts/diagnosis.md- five-bucket evidence readers/builders/interpreters where generic
- diagnosis asset pack loading and generic matching shell
- asset-driven diagnosis result classification
- diagnosis result envelope normalization
负责:
- 消费 app diagnosis asset pack
- 消费 app-provided evidence bundle / refs
- 解释 Validation (schema-driven)、production、runtime、business/local evidence 的 failure signal
- 产出
diagnosis_result - 保持 app-agnostic,不硬编码 consumer 业务词
7.1.1 Diagnosis Prompt pack
所有 nexrur-owned Diagnosis LLM 文本必须只存在于
src/nexrur/prompts/diagnosis.md。该文件使用既有的
```prompt:<section_name>
...
```
命名块合同,覆盖 Flash、Pro、Golden A/B/C、历史学习以及 learning research
planning/synthesis。Python 只允许加载、变量渲染、hash、预算和 Schema 校验,不得
保留 _DEFAULT_*、应急 Prompt 或字符串 fallback。
多个运行角色可以显式绑定同一个命名块,但绑定表只能描述底座 Prompt 角色,不得
包含 App/provider 语义。Prompt 文件缺失、命名块缺失或命名块为空时必须 fail
closed;不得退回 Python 内嵌文本。App-owned 业务 Prompt 仍留在 App 的
scripts/skills/*.md,不得搬入本文件。
旧的 root-level Markdown compatibility 已退场:DiagnosisMarkdownAsset、
patterns_text、counterexamples_text、examples_text 以及相应的目录扫描、选择
和渲染链均不属于 active contract。Golden 只能通过已登记的 index/full assets
进入 Prompt A/B;底座不得重新扫描 patterns/、examples/、
counterexamples/ 拼接自由文本。
nexrur.engines.diagnosis 包入口必须使用显式 import 与 __all__ 白名单,只公开稳定
边界、输入组装、Golden handoff、Engine 和公共诊断入口。禁止
from .context import * 或把 context 内部 helper 自动升级成公共 API。
7.1.2 Diagnosis boundary / context / execution split
engines/diagnosis/boundary.py 只拥有声明:输入输出 dataclass、运行 Protocol、Schema
role 常量、Schema 读取和声明结构的机械校验/序列化。它不得读取消费方资产、解析
evidence、计算 evidence fingerprint、渲染 Prompt JSON、生成 diagnosis id、校验 LLM
响应或执行 Campaign route。DiagnosisAssets 不得保留 targets 等 Campaign-shaped
兼容字段;LLM 协议只保留唯一正式名称 LLMClient。
engines/diagnosis/context.py 只拥有输入侧工作:消费方资产读取、Golden 文件解析、
catalog/evidence 事实规范化、DiagnosisInput 组装、Prompt pack 加载,以及 Prompt
A/B/C 所需的 bounded material preparation。Prompt A 的 eligible cards、Prompt B 的
selected full-asset handoff、Prompt C 的 episode/scope/approved/inactive comparison、
historical fact bundle 都必须在这里准备完成。它不得调用 LLM、裁决 Prompt 输出、选择
最终 Diagnosis result、编译或写入新的 learning candidate。
context.py 的正式 material API 必须直接以公开函数定义存在;禁止先定义 _private
helper、再在文件末尾批量赋值成公开别名。Diagnosis 和 StepSix 只能导入这些显式公开
接口。Golden YAML 只要存在就必须严格解析为 mapping;损坏、空 index、路径穿越或
真实路径逃出显式 Golden root 时一律 fail closed。
engines/diagnosis/diagnosis.py 只拥有判断与结果:调用 Prompt A/B/C、规范化并校验
模型输出、形成唯一 Diagnosis result、编译 learning candidate、持久化 inactive
candidate、编译同 episode Candidate Trial handoff,并形成最终
DiagnosisSuggestion。所有写入仍须保持 proposed/inactive、幂等去重、真实路径约束、
原子发布和 fail-closed;该边界不授予 Diagnosis active promotion 或 Campaign route
权限。
diagnosis.py 内部按唯一责任顺序组织为七段:Prompt 输出规范化/校验、Candidate
编译/持久化、Candidate Trial handoff、Diagnosis 结果构造/校验、Engine、ToolLoop
LLM 适配、公共 facade。这里的“规范化”只允许合同明示的 Prompt A 解释字段别名;
规范化后必须删除别名并按正式 Schema 验收。Flash、Pro、Golden A/B/C 或 ToolLoop
返回任何 Schema 违规都必须拒绝该次输出,不能只记 warning 后继续采用。
DiagnosisInput.subject_id 是调用方给出的诊断主体真值。模型输出不得包含或覆盖
target_subject_id;Diagnosis ID 与 RepairScope.subject_id 只能从该显式输入生成。
Diagnosis 也不得输出 target_covered、route basis、lifecycle verdict 等
Campaign-shaped 字段。Engine 不保留未参与裁决的 confidence threshold;可采用性由
Schema、catalog/evidence gate 和明确的零置信度失败规则共同决定。
两个模块之间只允许显式公开接口。diagnosis.py 不得导入 context.py 的 _private
helper;context.py 也不得反向导入 diagnosis.py。材料准备与判断执行不得再因为一次
大块迁移而混在同一文件。
Episode identity 只能由顶层 projection_identity.trace_id + cycle_no 和 canonical
diagnosis_evidence_packet.source_phase 编译;cycle_id 机械写成
cycle-000N。可选 phase_path 也只能来自同一个 diagnosis packet。底座不得从
metadata、顶层 source_phase / cycle_id / source_scope、failed_phase / phase
别名、目录名或相邻结构补值;缺失或冲突必须 fail closed。
Golden card 的 app/subagent/module scope 同样只读显式 source_scope;asset_ref
目录仅用于文件寻址,不得反推业务身份。
Inactive candidate queue 是受治理输入。读取时必须验证真实路径仍位于明确绑定的
Diagnosis asset root 内,并校验 candidate schema、review_status: proposed 与
active_runtime_allowed: false。任何损坏、越界或冲突文件都必须阻断比较、编译和写入,
不得静默跳过。新候选必须先写入同目录临时文件并原子发布到最终路径;不得直接向最终
文件写入半成品,也不得覆盖已有文件。
历史学习中的文件读取不属于 Diagnosis 执行。engines/evidence/read_golden_artifacts.py
拥有 app-relative source 校验、Markdown heading 定位、表格/围栏代码/行内代码/
数值与声明文本事实抽取,以及 source file hash、line span、span hash 和事实单元身份
编译。它只返回带明确来源的 bounded fact units,不调用 LLM、不生成 Candidate、
不执行 Prompt C。diagnosis.py 只能消费这些已编译事实来运行历史 Prompt C 和后续
candidate 逻辑,不得再次直接解析历史 Markdown。
Learning Research 也不属于 Diagnosis 执行。engines/stepsix/fail2pivot.py 独占
learning_research / learning_research_eligibility 合同编译、是否允许外部学习的
判断、query planning、search/read 调度、synthesis context 和 grounded unit 编译。
StepSix 只能把编译完成的标准 learning_research_units 和已验证的 app provenance
evidence_role 显式交给 Prompt C;
diagnosis.py 不得读取 Learning Research 合同、猜测 app evidence_role,也不得
组织 search/read 或重新编译 units。Prompt C 只把这些 units 当作 learning-only
参考材料,不能将其升级为普通 Diagnosis evidence、approved Golden 或 route 权限。
Candidate persistence 和 Candidate Trial 的授权只能来自 app
diagnosis.yml::contracts 中值严格为 boolean true 的
learning_candidate_persistence_enabled / learning_candidate_trial_enabled。
运行 payload、options、旧别名或 truthy 字符串/数字都不能授予权限。
同一 episode 的 step6.json 是 replay receipt。文件不存在表示首次执行;文件一旦
存在,就必须是可读 JSON mapping,并带匹配的 episode_key、
replay_complete: true、Diagnosis verdict 和 Campaign control。损坏、缺字段、
episode 冲突或 Projection 无法解析都必须 fail closed,禁止把坏 receipt 当成
“首次运行”而再次搜索、生成或持久化 Candidate。
7.2 应用层负责什么
放在 consumer 仓库:
_shared/engines/diagnosis/
只负责:
- evidence
- catalog
- golden positive cases
- golden counterexamples
- golden patterns
- golden learning candidates
- app-specific diagnosis result families
应用层不再负责:
- diagnosis engine 主流程
- route/halt 执行
- review merge
- diagnosis.py 真身
- app 自己的
ai_diagnosis.py - result-to-target mapping in owner Python
7.3 Diagnosis + Campaign Sovereignty
Diagnosis + Campaign 是 nexrur 的 fail-to-pivot 主脑,不是 consumer app 内部某个 phase 的 helper。
底座主脑负责:
- context acquisition through five-bucket evidence
- evidence bundle construction
- LLM/root-cause diagnosis
- independent
diagnosis_result.result_codeexplanation - campaign routing handoff by Diagnosis
result_code - campaign route / halt / restart orchestration
consumer app 只能提供:
- evidence asset pack:
evidence.yml - diagnosis asset pack:
diagnosis.ymlandgolden/index.ymlplus selected full assets undergolden/; legacytargets.ymlmaterial belongs under_archived/only - thin Step 6 adapter that gathers subject/run refs and calls substrate diagnosis
- app-owned business artifacts and local validation artifacts
consumer app 不允许实现:
- local detector engine
_build_candidate_root_causes- hardcoded result -> target routing
- phase-local root cause classifier
- LLM diagnosis replacement
- app-local campaign route / halt / restart controller
Step 6 的职责是薄适配:
evidence subject_id / trace_id / current phase refs
-> call nexrur build_evidence_bundle
-> call nexrur diagnosis engine with consumer diagnosis assets
-> receive diagnosis_result
-> hand off to campaign
Step 6 不得维护大段业务 detector。需要更强 evidence reading 时,优先扩展
substrate five-bucket readers、evidence.yml contract,或 consumer
diagnosis asset pack,而不是在 app owner Python 中重写诊断器。
7.4 Phase Boundary For Diagnosis Signals
Phase 1/2/3 evidence wrappers 只能负责:
- facts
- digest
- obligations
- artifact refs / lineage refs
- readiness
- blockers
- warnings
它们可以给 Diagnosis 提供原材料 refs,但不能替 Diagnosis 加工诊断语义。
禁止在 Step 1/2/3 evidence.py 中加入:
- upstream semantic diagnosis summary
_summarize_curate_business_summarize_dataset_l1_summarize_field_updater_summarize_dataset_l2_build_upstream_diagnosis_context- candidate root cause hints
- Diagnosis
result_code-> target suggestion
Phase 4 Production 不得判断 root cause、不得给 campaign route target、不得做
diagnosis summary。但每个 Production leaf/module/subagent 必须能够原样返回自己的
status=partial、事实型 reason_code / failure_kind / errors / warnings 和真实
artifact_refs / evidence_refs。这是 Diagnosis 输入,不是 Production 的路由
裁决。Production 不得把该问题吞掉、包装成 success,或复制上游问题冒充自身
失败。这些 Product 字段一旦返回,后续所有层只能原样转运。
Phase 5 Validation/schema wrappers 只能输出 schema-driven validation facts。
完整命名与禁止边界见 DESIGN_SCHEMA.md:
validation_passedvalidation_factsschema_errorsdiagnosis_readyartifact_refs
Phase 5 不得升级为 diagnosis classifier,也不得把 validation failure 直接解释成
restart dataset_l2、curate is weak、evidence source too weak 等 campaign
target 决策。这些解释属于 Step 6 调用底座 Diagnosis 后的结果。
8. Consumer Diagnosis Asset Pack 标准
Diagnosis 的 app 边界不是 Python 真身,而是标准化资产包。
标准目录(目标态):
_shared/engines/diagnosis/
evidence.yml
diagnosis.yml
golden/
index.yml
positivecases/
<subagent>/
<module-or-layer>/
<subagent>-<module-or-layer>-<case-slug>.md
counterexamples/
<subagent>/
<module-or-layer>/
<subagent>-<module-or-layer>-<case-slug>.md
patterns/
<subagent>/
<module-or-layer>/
<subagent>-<module-or-layer>-<case-slug>.md
candidates/
positivecases/
<subagent>/
<module-or-layer>/
<subagent>-<module-or-layer>-<case-slug>.md
counterexamples/
<subagent>/
<module-or-layer>/
<subagent>-<module-or-layer>-<case-slug>.md
patterns/
<subagent>/
<module-or-layer>/
<subagent>-<module-or-layer>-<case-slug>.md
_archived/
legacy_classified_markdown/
patterns/
examples/
counterexamples/
8.0 evidence.yml
作用:
- 定义 Step 6 可消费的 five-bucket evidence truth
- 声明 required / optional sources、current_scope、upstream_feedback、 digest / obligation views
- 告诉 production、schema、diagnosis 读取哪些 step artifact 与 envelope
evidence.yml 是证据真相源,不是 diagnosis result catalog。它只说
"证据在哪里、是否必需、如何归入五桶",不解释 root cause,不输出 target。
8.1 diagnosis.yml
作用:
- 定义本 consumer 支持的 Diagnosis result ontology
- 解释每个
result_code的语义、family、severity、evidence gates - 明确区分 Product 输入
reason_code与 Diagnosis 输出result_code; 二者不共用字段、不做别名、不双写 - 声明 contradiction guards
diagnosis.yml 不声明 continue / restart / reroute / halt、
recommended_disposition 或 Product status 语义。这些控制规则只属于
campaign.yml。
示意:
result_codes:
- code: L2_FIELD_BINDING_BAD
description: 字段绑定不合理
family: business_semantics
severity: high
- code: REPORT_DRAFT_USABLE_WITH_REFERENCE_GAPS
description: 底稿可继续消费,但引用缺口需后台修复
family: coverage
severity: medium
- code: curate_skeleton_invalid
description: 骨架结构本身不可修
family: business_semantics
severity: high
- code: PLATFORM_NOISE_DIAGNOSTIC_ONLY
description: 平台噪声,仅用于诊断归档
family: runtime
severity: low
8.1.1 Current-Step Scoped Result Catalog
diagnosis.yml may be stored under an app-level shared path such as
_shared/engines/diagnosis/, but shared storage is not a global runtime
candidate pool. Runtime diagnosis must scope the result catalog by the active
orchestrator step before any diagnosis chooser sees the codes.
Default scope is derived from the catalog block name:
| current_step | eligible catalog blocks |
|---|---|
outline | outline, mirror, common |
papers | papers, extractors, common |
reports | reports, qcc, penetration, common |
Rules:
commonis the only global block. It may contain platform-level or cross-step codes, but must not contain step-owned business codes.- Step-owned blocks are not globally visible. A papers result code must not be a candidate during an outline diagnosis unless that code explicitly declares a valid current-step override.
- Optional
valid_current_stepson a result code narrows or extends the derived block scope. If present, runtime must intersect it with the current step before exposing the result to diagnosis. - Golden index cards and selected full golden assets must expose only
related_result_codesthat are valid in the same current-step scoped catalog. A golden pattern may be shared across steps, but its out-of-scope related result codes must be hidden from Prompt A/B for the current run. - Campaign routing remains in
campaign.yml. Diagnosis only decides which scopedresult_codeis allowed to leave the diagnosis layer.
Failure example that must be rejected:
current_step=outline
diagnosis candidate=PAPERS_EVIDENCE_CONTEXT_MISSING
This is invalid because the papers result is outside the outline-scoped catalog. The run should remain an outline diagnosis failure/blockage until an outline/mirror/common result is supported by evidence.
8.2 Deprecated targets.yml
diagnosis/_archived/targets.yml is deprecated as active executable truth. Diagnosis no
longer owns result_code -> target_step / target_subagent / restart / route
policy. Runtime loaders must not read or convert the archived sample. It is
history-only migration reference and cannot participate in route arbitration.
The replacement split is:
diagnosis.yml -> result ontology, evidence gates, classification hints
campaign.yml -> result_code -> lifecycle / disposition / executable target
alphas_campaign.yml -> run-level budget and execution limits
checkpoint / trace -> step status, artifact validity, resume facts
Prompt B must not output target_step, target_subagent, campaign_control,
or repair_plan as route verdict. If a compatibility envelope still contains
these fields, they must be campaign lookup projections, not diagnosis truth.
8.3 Diagnosis result / Campaign lifecycle boundary
Diagnosis-side targets.yml / halt.yml / escalation.yml are not active
assets. Diagnosis has exactly one structured classification truth entrypoint:
diagnosis.yml.
diagnosis.yml只定义result_code的诊断语义和 evidence gates。- halt / diagnostic-only / non-retryable / continue-with-repair semantics are
written only in
campaign.yml. - 当前 Product 是否可继续消费,只由
production_result.status决定;Diagnosis 和 Campaign 不得再做一次当前轮状态判定。 - 需要后续修复的
result_code可由 Campaign 映射为continue_with_repair,但该映射只决定后续行动,不改写当前 Product。 - repair / retry / stop / escalate / manual_review is decided by Campaign from
the validated Diagnosis
result_code, Product facts, history, budget facts, settings, andcampaign.yml; Diagnosis / LLM does not emit that disposition. - executable target projection and fatal runtime guards are written in
campaign.yml. - budget values are written in run config / CLI, not campaign assets.
- step status, resume, and artifact validity are checkpoint / trace facts.
- loader must not continue reading or converting diagnosis-side
halt.yml/escalation.yml; archivedtargets.ymlis history-only migration reference.
Campaign side campaign.yml is the target execution boundary contract; see
DESIGN_ENGINES_CAMPAIGN.md §10.
8.3.1 External Provider And Authentication Failures
External authentication is an MCP/toolhost runtime concern until its bounded retry policy is exhausted. Diagnosis must not authenticate, refresh provider sessions, or repeat an external call.
The canonical handoff is:
MCP/toolhost bounded auth retry exhausted
-> leaf emits one stable raw reason_code plus bounded provider failure facts
-> orchestrator uploads phase_failure_facts
-> Step6 evidence points to those facts
-> diagnosis emits an independently namespaced app-catalog result_code
-> campaign applies halt/no-route policy
Rules:
- A diagnosis-ready leaf must emit its stable Product reason itself.
Orchestrator, evidence obligations, and Diagnosis must preserve that field
exactly. Diagnosis may classify it into an independent
result_code, but must not translate or replace the Product reason through aliases or error-string guesswork. phase_failure_factsmay carry tool name, provider-neutral failure class, bounded status, and redacted message. Credentials, auth headers, cookies, tokens, full provider responses, and retry request payloads are forbidden.- A leaf may also emit bounded
diagnosis_contextfacts. Orchestrator preserves them insidephase_failure_facts; Diagnosis and golden assets interpret them. The leaf must not place a repair target or campaign route in that context. - An app diagnosis result representing unavailable credentials or exhausted provider
authentication should normally receive
halt_onlyhandling incampaign.ymlunless the app has a genuinely different executable repair target. - A provider authentication failure is not production quality failure and must not be routed back to the same production phase merely to try again.
- MCP retry mechanics and session reset behavior are defined by
DESIGN_MCP.md; Diagnosis consumes only the final bounded failure facts.
8.4 Archived patterns/, counterexamples, examples
Root-level patterns/, examples/, and counterexamples/ are retired. If an
app keeps them for migration history, they must live under
_archived/legacy_classified_markdown/ and must not be loaded as active
diagnosis assets.
Active case-grounding knowledge belongs in golden/:
golden/positivecases/golden/counterexamples/golden/patterns/golden/candidates/
Case-grounded cognition belongs only to diagnosis golden. Any material currently
under campaign/_archived/examples, campaign/_archived/counterexamples, or
campaign/_archived/patterns that explains why a diagnosis is right or wrong
must move to the corresponding diagnosis golden folder:
| Current campaign material | Diagnosis golden target |
|---|---|
| diagnosis case / positive route rationale | golden/positivecases/ |
| anti-diagnosis guard / tempting wrong explanation | golden/counterexamples/ |
| abstract failure mechanism / reusable semantic pattern | golden/patterns/ |
Campaign does not consume these cognition assets. The pre-LLM selector and
Prompt B may consume
approved diagnosis golden assets through the golden retrieval chain; Prompt C
may automatically write inactive learning candidates under
golden/candidates/{positivecases,counterexamples,patterns}/<subagent>/<module-or-layer>/.
The substrate default for candidate persistence is opt-in, because nexrur must
not write app knowledge for every consumer by default. An app may, however,
declare candidate persistence as required app contract. In that case Prompt C is
attempted at fail2pivot end-of-episode after the diagnosis result and campaign
outcome are resolved. Auto-written candidates remain review queue material
only.
The archived markdown is history-only. It cannot override
evidence.yml, envelope, diagnosis.yml, campaign route assets, or golden index
truth, and it must not be injected into the production diagnosis prompt.
8.5 Golden Library: case-grounded diagnosis knowledge substrate
Golden Library is not a pattern directory. It is the reviewed diagnosis knowledge substrate containing grounded cases, counterexamples, abstract patterns, retrieval index cards, and learning candidates. Patterns are one asset class inside golden, not the whole golden.
Golden exists to make diagnosis case-grounded without moving business judgment into Python. It provides reviewed cognition material for the LLM diagnosis chain; it does not own result ontology, prescriptions, campaign routes, or halt policy.
Canonical app-side physical layout:
.gemini/skills/_shared/engines/diagnosis/golden/
index.yml
positivecases/
<subagent>/
<module-or-layer>/
<subagent>-<module-or-layer>-<case-slug>.md
counterexamples/
<subagent>/
<module-or-layer>/
<subagent>-<module-or-layer>-<case-slug>.md
patterns/
<subagent>/
<module-or-layer>/
<subagent>-<module-or-layer>-<case-slug>.md
candidates/
positivecases/
<subagent>/
<module-or-layer>/
<subagent>-<module-or-layer>-<case-slug>.md
counterexamples/
<subagent>/
<module-or-layer>/
<subagent>-<module-or-layer>-<case-slug>.md
patterns/
<subagent>/
<module-or-layer>/
<subagent>-<module-or-layer>-<case-slug>.md
golden/ is already the asset root. Do not add an extra assets/ layer
under it. asset_ref values are relative to golden/, for example
counterexamples/evaluate-alphas/platform/evaluate-alphas-platform-cache-noise.md.
Candidate file names must include the app diagnosis scope slug and
module-or-layer names. The diagnosis scope slug is not necessarily the runtime
campaign target or skill package name; apps should remove product/runtime
prefixes so the convention remains portable across WQ-YI, AGN, AUDIT, and
other consumers. For WQ-YI, use curate-knowledge, dataset-explorer,
evaluate-alphas, and collect-papers instead of their brain-* runtime
package names. dataset-explorer keeps l1, l2, and field_update as
module-or-layer values rather than pretending they are separate subagents.
Apps may pre-create empty candidate directories for known module-or-layer
values; if a VCS placeholder such as .gitkeep is used, it is not a diagnosis
asset and must not be loaded.
WQ-YI's current candidate scope scaffold is:
collect-papers/collect
curate-knowledge/skeleton
curate-knowledge/validation
curate-knowledge/fail2pivot
dataset-explorer/l1
dataset-explorer/l2
dataset-explorer/field_update
evaluate-alphas/settings
evaluate-alphas/metrics
evaluate-alphas/platform
evaluate-alphas/fail2pivot
8.5.1 Golden asset classes
| Class | Purpose | Runtime authority |
|---|---|---|
positive_case | A reviewed episode where a specific evidence combination correctly supported a diagnosis result; stored under golden/positivecases/<subagent>/<module-or-layer>/ | advisory grounding only |
counterexample | A reviewed episode or constructed guard showing why a tempting diagnosis is wrong; stored under golden/counterexamples/<subagent>/<module-or-layer>/ | advisory guard only |
pattern | Abstract reusable failure mechanism distilled from multiple cases / counterexamples; stored under golden/patterns/<subagent>/<module-or-layer>/ | advisory reasoning frame only |
index_card | Lightweight retrieval summary in golden/index.yml used to decide which full assets are worth reading | retrieval input only |
learning_candidate | Proposed future golden asset distilled from an episode; auto-written under golden/candidates/<future-class>/<subagent>/<module-or-layer>/ when candidate persistence is enabled | inactive until reviewed |
Root-level patterns/, examples/, and counterexamples/ are no longer a
transitional active surface. They are archived history only; target-state apps
must use canonical golden/{positivecases,counterexamples,patterns}/ folders.
8.5.2 Golden index contract
golden/index.yml is a retrieval index, not a route map. An index card should
be compact and must help choose full assets without carrying final diagnosis
or target decisions.
Minimum index card fields:
id: evaluate-alphas-metrics-low-fitness-alone-is-not-skeleton-invalid
type: counterexample
summary: Low fitness alone is not enough to diagnose skeleton invalid.
trigger_signals:
- weak simulation result
anti_signals:
- schema-level skeleton defect
guards_against:
- overdiagnosing structural failure
related_result_codes:
- curate_skeleton_invalid
asset_ref: counterexamples/evaluate-alphas/metrics/evaluate-alphas-metrics-low-fitness-alone-is-not-skeleton-invalid.md
review_status: approved
Index cards must not define target_step, target_subagent,
campaign_control, repair_plan, or any result_code -> target shortcut.
Those remain diagnosis.yml / campaign asset truth; route truth belongs to campaign campaign.yml.routes.
type and asset_ref must agree:
type | Canonical asset_ref prefix | Active Prompt B eligibility |
|---|---|---|
positive_case | positivecases/ | eligible when review_status: approved |
counterexample | counterexamples/ | eligible when review_status: approved |
pattern | patterns/ | eligible when review_status: approved |
learning_candidate | candidates/{positivecases,counterexamples,patterns}/ | never active; review/promote first |
Learning candidates should normally stay out of active index.yml. If an app
indexes them for review/audit, they must use type: learning_candidate,
review_status: proposed, and active_runtime_allowed: false, and the
pre-LLM selector
must not select them for active Prompt B grounding.
review_status minimum enum:
| Status | Runtime meaning |
|---|---|
draft | authoring only; not eligible for runtime pre-LLM selector use |
proposed | learning / review queue only; not eligible for runtime pre-LLM selector use |
approved | eligible for runtime pre-LLM selector use after schema validation |
deprecated | retained for audit/history; not selected unless explicitly enabled |
rejected | retained only as review history; never selected |
Only approved golden assets are eligible for active runtime pre-LLM selector
selection by default. draft, proposed, and learning_candidate assets are
offline-only. deprecated assets may be cited for audit/history only when an
explicit debug/review mode enables them.
8.5.3 Full golden asset contract
A full golden asset may contain the detailed case narrative, evidence signature, why a diagnosis was right or wrong, related patterns, and anti-overgeneralization boundaries. It must include:
summaryapplies_whendoes_not_apply_whenrequired_evidencecontradiction_evidenceor equivalent anti-signalsrelated_result_codessource_episodeor synthetic case provenancereview_status
related_assets is optional. A canonical family card may stand alone after its
positive and counterexample evidence has been merged into one full asset. When
the field is present, every referenced ID must still resolve to an indexed
asset; self-references and synthetic siblings are not required.
Full assets can explain why a diagnosis is plausible or implausible, but they
cannot introduce new active result codes. If a full asset needs a result not
present in diagnosis.yml, the asset is not runtime-active until catalog /
targets coverage is added and schema validation passes.
8.5.4 Prompt chain roles
Diagnosis golden retrieval is cognition, not mechanical business classification. Program code cannot enumerate semantic relevance by hand.
The diagnosis prompt chain is one instance of the broader controlled-LLM contract. It must use the same evidence/evidence substrate as Production and restarted Production, then add diagnosis-specific episode facts:
- current production artifact and validation envelope;
- runtime / simulator / toolloop failure facts;
- upstream feedback and prior campaign handoff facts;
- selected approved golden assets from the shared golden substrate.
Diagnosis must not create a private evidence world. If evidence is missing or
polluted, fix evidence.yml, envelopes, schema validation, or golden
assets; do not compensate with Python local arbitration.
phase_failure_facts.reason_code is the canonical leaf failure fact supplied
by Orchestrator. context.py must expose that exact value as a diagnosis
candidate and use it to scope Prompt A's eligible Golden cards when no explicit
reason_candidates list is present. This is transport and selection scoping,
not reason normalization: the value must not be renamed, aliased, or translated.
If an explicit reason_candidates list is present, it remains authoritative.
If the leaf fact and another legacy top-level reason disagree, both remain
visible for Diagnosis arbitration rather than one silently replacing the other.
Step 3 obligations are part of that same evidence world. The substrate may
assemble an obligation envelope from app-owned declarations, evidence digest
refs, and schema validation results, but it must not interpret app-specific
obligation semantics in Python. Relation formulas, field-family preferences,
fallback policies, weak-pattern bans, required roles, and downstream route
meaning belong to the app manifest/schema/assets. A generic
build_obligations surface is valid only when it acts as a schema-gated
assembler; missing declaration, missing schema, unresolved digest refs, or
schema failure must become failed / diagnosis-ready evidence.
Canonical chain:
Program loads schema-valid golden index
-> Program applies only mechanical gates / budgets
-> evidence.md::pre_llm_selector reads evidence + eligible index cards
-> pre_llm_selector selects relevant cases / counterexamples / patterns with reasons
-> Program loads selected full assets
-> Prompt B performs grounded diagnosis using evidence + selected full assets
-> Program validates result_code against catalog / schema
-> Campaign consumes validated diagnosis_result
-> Prompt C proposes zero or more learning_candidates after the episode
-> Candidate persistence may auto-write inactive candidate files when enabled
Allowed program gates before the pre-LLM selector:
- schema-valid index card
review_status: approvedfor active runtime use- hard scope mismatch filtering when a card explicitly belongs to another app or incompatible canonical step family
- token budget / count budget
- audit recording for eligible / selected / rejected cards
Forbidden program gates before the pre-LLM selector:
- business relevance scoring
- semantic similarity judgment
- result classification
- route target selection
- counterexample priority as a hard-coded route veto
- app-specific
if result -> targetlogic
The pre-LLM selector owns cognitive retrieval: it decides which eligible index cards are semantically useful for the current evidence and explains why. Program only loads and audits; it does not pretend to know which case is conceptually closest.
Minimum pre-LLM selector output contract:
If evidence.memory_recall is present, Prompt A treats it as historical
similar-case context only. It may use recall snippets to notice analogies or
avoid repeated confusion, but current-run claims still require current
evidence/production/schema/runtime evidence refs.
Minimum Prompt A / pre-LLM selector output contract:
selected_assets:
- id: evaluate-alphas-metrics-low-fitness-alone-is-not-skeleton-invalid
type: counterexample
asset_ref: counterexamples/evaluate-alphas/metrics/evaluate-alphas-metrics-low-fitness-alone-is-not-skeleton-invalid.md
why_relevant: current evidence shows weak performance without structural defect
expected_signal: performance symptom without schema/runtime skeleton failure
confusion_to_avoid: do not classify weak fitness alone as skeleton invalid
rejected_assets:
- id: platform-cache-permission-error
why_not_relevant: no platform/cache/permission evidence in current envelope
budget_notes:
truncated: false
candidate_count: 12
selected_count: 2
Pre-LLM selector output is an audit-visible retrieval decision, not a diagnosis. It
must explain why each selected index card is relevant, what confusion it helps
avoid, and why high-signal rejected cards were not selected. It must not output
result_code, reason_code, target_step, target_subagent, campaign_control, or
repair_plan.
Runtime predicate compilation must use meaningful values rather than key
existence. Empty surfaces such as schema_errors: [], validation_facts: {} or
an empty runtime list do not establish a failure signal. Nested bounded facts are
first-class: non-empty hard_fail_verdicts and execution_error_distribution
inside phase_failure_facts.diagnosis_context must be visible to Prompt A.
Mutually exclusive predicates must remain exclusive. In particular, a generic
quality label may coexist with a hard provider error, but
only_alpha_quality_failed is valid only when no hard runtime/physical execution
fact is present.
When the current Step6 packet already carries one explicit leaf reason_code,
Prompt A eligibility is mechanically scoped to approved index cards whose
input_reason_codes include that code. related_result_codes is relationship
metadata only and must never act as an implicit retrieval scope. Cards that need
reason-scoped retrieval must declare input_reason_codes explicitly; the
substrate must not infer or auto-fill that contract. The program does not choose
the winning case or route; Prompt A still performs semantic selection inside the
explicitly bounded set. Historical upstream feedback remains context and must
not make unrelated cards outrank the current leaf fact.
input_reason_codes belongs to the Product-input namespace. Every value is an
exact, producer-owned reason_code copied from a Product leaf or nested Product
result. Diagnosis may validate its shape and compare it for exact equality, but
must not translate it, normalize it into another semantic code, require it to be
a Diagnosis result_code, or add it to the Diagnosis output catalog merely to
make Golden retrieval pass. The app-owned Golden index is responsible for
declaring which approved cards accept each Product input code. Adding a new
Product reason without an eligible Golden mapping is therefore an explicit asset
contract gap, not permission to scan all cards or reinterpret the reason.
Every deterministic filter that changes Prompt A eligibility must atomically recompute all three trace fields from the same final list:
eligible_index_cards: []
eligible_card_count: 0
run_prompt_a: false
If reason scoping or any later predicate leaves zero eligible cards, Prompt A is
not called. This condition is non-correctable by the model and must be recorded
as an explicit golden_no_eligible_cards / asset-contract failure. In
golden_chain_mode: required it remains a failed Diagnosis, but the failure must
not replace the incoming Product reason_code. A stale pre-filter
eligible_card_count or run_prompt_a: true is invalid state.
Golden asset identity is available to Prompt A only through
eligible_index_cards[].id and its registered asset_ref. Filesystem paths from
the Golden reader are audit/source locations, never candidate IDs and never
business evidence. Prompt A must not run with an empty candidate list or derive
an asset identity from artifact_refs, evidence_refs, raw paths, filenames, or
free text in the evidence packet.
An approved asset may optionally declare diagnosis_result_codes. When Prompt A
selects such an asset, Prompt B's eligible catalog results are intersected with
that explicit set and its output is mechanically checked against the same set.
Every value in diagnosis_result_codes must reference a result_codes catalog
entry. Raw Product reasons remain in input_reason_codes; related Diagnosis
classifications remain in related_result_codes, but neither may be emitted as
the final diagnosis unless it is explicitly present in diagnosis_result_codes.
This separates a raw leaf reason used to retrieve an escalation pattern from the
root-cause result that the pattern permits Prompt B to produce. Assets that omit
diagnosis_result_codes retain the existing advisory behavior. Neither field may
contain route targets. Every diagnosis_result_codes / related_result_codes
value must exist in the app Diagnosis catalog and current-step scope;
producer-owned input_reason_codes are exact-match retrieval inputs and are not
required to become Diagnosis output catalog entries. App catalogs must map runtime current_step
names to diagnosis blocks through scope.current_steps.<step>.blocks; otherwise
scoped golden result metadata is not available to Prompt A/B.
current_step is an execution coordinate, not diagnosis material. Orchestrator
must derive the canonical app-level current_step from the recursive graph
path before Step6 calls Diagnosis. Local and nested identities remain separate
facts in phase, source_phase, failed_phase, phase_path, and
target_leaf.
Diagnosis context may validate those coordinates against the app catalog and
use phase_patterns only as a scope-consistency predicate inside the already
declared current_step. It must not promote a leaf name into current_step,
rewrite a non-empty current_step, or infer graph ownership from diagnosis
assets. Missing, undeclared, or internally inconsistent coordinates fail closed
as an input-contract error and must be repaired at the Orchestrator producer.
When golden_chain_mode: required, Prompt A/B failure or post-LLM catalog gate
failure is a failed diagnosis. The public diagnosis facade must not silently
replace it with a raw leaf reason candidate as the Diagnosis result; that would bypass the required
golden contract and create a false-success route.
The only exception is an app-catalog entry that explicitly declares:
adjudication:
mode: exact_leaf_fact
This mode is for facts that have already been decided by the owning leaf, such as an exhausted external discovery contract. It is not a semantic root-cause shortcut. The substrate may form a diagnosis suggestion without Prompt A/B only when all of the following are true:
- the current-step catalog contains exactly one eligible reason candidate;
phase_failure_facts.reason_codeis identical to that candidate;- the entry declares
diagnosis_reason: trueandsource: runtime_phase_fact; - the catalog evidence and contradiction gate has passed;
- the current app-step scope is valid.
Missing opt-in, multiple candidates, a mismatched leaf reason, or a failed evidence gate keeps required Golden fail-closed. Exact-leaf mode preserves the raw reason and produces no target; Campaign remains the only route owner. The substrate must not infer this mode from reason names, error text, lifecycle class, or app identity.
Prompt A may make one bounded output-contract correction after a successful
provider call returns model content that cannot be parsed or fails the
deterministic selector contract. This means at most two Prompt A model calls in
total: the initial call plus one correction call. The correction must carry only
the validation errors and the original bounded eligible-card input; it must not
widen retrieval scope, add a fallback diagnosis, or call Campaign. If the
corrected response still fails, required mode remains fail-closed with an
auditable prompt_a_failed result.
This correction is not provider retry. Diagnosis must not catch a generic LLM
exception and issue another model call. Transport timeout, authentication,
provider unavailability, rate limiting, connection failure, and other execution
errors remain owned by the LLM facade's ErrorClassifier, RetryPolicy, and
RecoveryLadder. After that owner reports failure, Prompt A fails without an
additional diagnosis-level call. Missing/invalid DiagnosisInput, Golden
registration failure, and an empty eligible-card set are also non-correctable
and must not consume a correction call. Runtime audit must distinguish the
initial call, the optional output-contract correction, and provider-internal
retry counts.
Pre-LLM selector validator/canonicalizer contract:
- Hard-fail only on verdict/route fields, invalid selected asset identity,
unregistered or non-approved assets, unresolved full assets, or non-list
selected_assets/rejected_assetsshapes. - Explanation fields are A-to-B audit hints. They must be canonicalized before
Prompt B consumes the trace:
relevance_explanation/reason/explanationmay fillwhy_relevant,expected_signalsmay fillexpected_signal,guards_against_confusion/mistake_to_avoidmay fillconfusion_to_avoid, and scalarbudget_notesmay become a structured{truncated: false, notes: ...}object. - Missing or aliased explanation text must not turn an otherwise valid, resolvable selector asset selection into a Step 6 hard fail. Prompt B receives the canonicalized selector result and the resolved full assets.
Production may use the same reviewed golden substrate, but production retrieval
uses the same substrate evidence.md::pre_llm_selector prompt in
mode=production. Concrete app subagents/modules own selector profiles and
selection goals, not full duplicate selector prompt text.
Production flow:
owner builds production_golden_input
-> owner/app supplies selector profile and eligible golden cards
-> substrate runs evidence.md::pre_llm_selector(mode=production)
-> substrate validates selected/rejected/budget output
-> substrate resolves selected full golden assets
-> substrate writes production_evidence.json with embedded evidence core
-> owner injects selected_golden_context into the existing production prompt
Production selector output must explain generation relevance:
selected_assets:
- id: string
type: positive_case | counterexample | pattern
asset_ref: string
why_relevant: string
expected_generation_help: string
mistake_to_avoid: string
rejected_assets:
- id: string
why_not_relevant: string
budget_notes:
truncated: false
Production selectors are retrieval only. They must not emit result_code, reason_code,
target_step, target_subagent, campaign_control, repair_plan,
routing_intent, or learning candidates. The existing production prompt remains
the business-generation prompt; selected golden assets are advisory grounding,
not final diagnosis or route authority.
Production selector canonicalizer contract mirrors diagnosis selector: selected asset
identity and route/verdict forbiddance are hard contract; explanatory aliases
are normalized into why_relevant, expected_generation_help,
mistake_to_avoid, and structured budget_notes before owner prompt injection.
A valid selected asset must not be dropped merely because the selector used a
recognized explanation alias.
Prompt B owns diagnosis reasoning but remains bounded by diagnosis.yml: it may
choose only catalog results and cite actual evidence refs. It cannot invent or
emit active route semantics. Campaign, not Prompt B, maps result_code to
target_step / target_subagent through campaign campaign.yml.routes.
Prompt B must cite selected golden assets explicitly when it uses them:
result_code: L2_FIELD_BINDING_BAD
evidence_refs:
- evidence://evaluate/step6_evidence/simulation_facts
selected_asset_refs:
- counterexamples/evaluate-alphas/metrics/evaluate-alphas-metrics-low-fitness-alone-is-not-skeleton-invalid.md
why_selected_assets_matter: selected counterexample prevents overdiagnosing skeleton invalid
why_not_others: weak performance alone did not prove skeleton structure failure
Selected golden assets can support or constrain reasoning, but they are not a
result_code allowlist. A card's diagnosis_reason_codes are retrieval and
interpretation hints only: they describe reasons previously associated with the
case, not reasons that Prompt B is authorized to emit. Final reason authority is
owned exclusively by the current App diagnosis.yml catalog, current-step
scope, required-evidence gate, and contradiction-evidence gate. Therefore a
selected card must not veto another catalog reason whose current evidence gates
are closed. Target route must come from campaign assets, primarily
campaign.yml.
Prompt C is the mandatory post-episode learning branch when golden learning is enabled. It may return an empty list, but the branch itself must be attempted and audited. Learning candidates are never active in the same run. They must be schema-validated, reviewed, deduplicated, and promoted before becoming golden. When candidate persistence is enabled, Prompt C candidates are auto-written to the inactive candidate queue.
The substrate default is learning_candidate_persistence_enabled: false.
This prevents a generic nexrur consumer from accidentally turning runtime
episodes into app knowledge. App contracts may override this explicitly. If an
app marks golden learning as required, the trigger is fail2pivot
end-of-episode:
An app may also declare optional external learning material under
contracts.learning_research. This is a provider-neutral contract. Its complete
active surface is limited to runtime_binding, evidence_role, llm_profile,
search_tool, read_tool, query_budget, result_budget, and timeout;
unknown fields fail closed. evidence_role and llm_profile are required when
the binding is active. Missing, empty, or malformed values make the learning
contract invalid; the substrate must not infer either value from an app name,
reason, phase, metric, source type, or installed provider.
learning_research:
runtime_binding: active
evidence_role: <app-owned-evidence-role>
llm_profile: <registered-llm-profile>
search_tool: <registered-search-tool>
read_tool: <registered-read-tool>
query_budget: 3
result_budget:
max_search_results_per_query: 8
max_documents: 5
max_unit_chars: 4000
max_total_chars: 20000
timeout: 60
The branch runs only after baseline diagnosis and provisional Campaign have
completed. A bounded planning prompt compares the current failure facts with
approved Golden context and decides whether external reading is useful. When it
is useful, it emits two or three queries. The declared search tool must return
canonical results[].source_id; the read tool must return canonical
document.source_id and document.content. Provider-specific fields remain in
the app adapter.
baseline diagnosis
-> provisional Campaign
-> compare bounded approved Golden context
-> optional query planning
-> declared search/read tools
-> bounded source documents
-> learning-only semantic synthesis
-> bounded unreviewed units under the app-declared evidence role
-> Prompt C only
The app-declared evidence_role is the external DiagnosisInput and provenance
identity. The substrate must preserve that exact role when handing off and
persisting evidence references. Prompt C does not receive the app-specific name:
its bounded context always exposes the selected units as
learning_research_units. This normalization prevents Prompt C and substrate
code from depending on an app's evidence vocabulary. Both learning LLM calls
use the exact declared llm_profile; no fixed Flash/Pro profile, provider name,
or legacy use_flash inference is permitted in this branch.
The synthesis LLM may write only research_question, repair_pattern,
applicability, and limitations against an exact program-supplied
source_id/source_span. The compiler validates those references, assigns the
unit identity and source-content hash, and fixes authority to
unreviewed_external. It rejects unknown fields instead of repairing them.
Each final app-declared learning-evidence units[] item contains:
source_id: <provider-neutral source identity>
source_span: <exact canonical source span>
research_question: <question addressed by the source>
repair_pattern: <reusable source-grounded pattern>
applicability: <conditions where the pattern may apply>
limitations: <uncertainty and non-applicable conditions>
authority: unreviewed_external
Raw source text is synthesis input only and must not enter Prompt C. Prompt C
receives three separate material classes: approved_golden, open_candidates,
and the substrate-normalized learning_research_units. These units are not
normal Diagnosis evidence, approved Golden, or a route authority. They must
never be added to the baseline Diagnosis input, normal Golden retrieval, or
evidence gate. Prompt C may use all three classes only to draft [],
enrich_existing, or
propose_new; it still cannot emit candidate identity, episode identity,
fingerprint, evidence refs, reason, route, target, or additional execution-wave
authority. Search, read, timeout, normalization, query-planning, or synthesis
failure is a learning-side failure: preserve the baseline diagnosis and
provisional Campaign outcome, stop Prompt C/candidate/Trial for this episode,
and persist only the bounded failed learning receipt needed to prevent replay.
diagnosis_evidence_packet ready
-> Prompt A/B diagnosis_result ready
-> campaign outcome resolved
-> candidate eligibility compiler matches one app learning_candidate_contract
-> candidate compiler resolves canonical scope and compiles an observed-signal catalog
-> candidate compiler retrieves bounded same-scope approved/candidate context
-> Prompt C chooses [] / enrich_existing / propose_new
-> candidate compiler validates novelty and assigns identity/provenance
-> only propose_new candidates are persisted
An app-required Prompt C branch may return learning_candidates: []; that is a
valid audited outcome. Prompt C failure is a learning-side failure and must not
invalidate, rewrite, downgrade, or reroute the already completed diagnosis /
campaign outcome.
Prompt C and the candidate compiler have different authority:
| Concern | Authority |
|---|---|
| whether the episode contains a reusable lesson | Prompt C |
| future asset class and semantic learning boundary | Prompt C |
candidate_family_key, candidate_id, fingerprint, scope, episode identity and path | candidate compiler |
| evidence provenance | candidate compiler from known episode roles |
| observed-signal membership and approved/open-family coverage | candidate compiler |
| review and active-runtime flags | candidate compiler constants |
| promotion to active Golden | human review workflow |
Enabling candidate persistence is not permission to learn from every diagnosed
episode. The consumer app must additionally declare at least one
contracts.learning_candidate_contracts entry. Before Prompt C is called, the
substrate compiles eligibility from that declaration and the current bounded
diagnosis_facts only:
learning_candidate_contracts:
- id: reusable-wave-pattern
fact_role: quality_wave_learning_facts
required_observed_signals:
- quality_wave_comparison_ready
- current_wave_unqualified
allowed_candidate_types:
- pattern
An entry is eligible only when its declared fact_role exists as a non-empty
value in diagnosis_facts, every required signal was produced by the app's
observed_signal_rules, and the allowed candidate-type set is valid. No matching
entry means Prompt C is not called and nothing is persisted. Missing, malformed,
or ungrounded declarations fail closed; persistence enablement alone must never
fall back to an unrestricted learning episode.
The same eligibility contract is enforced again after Prompt C. Every non-empty draft must match one eligible entry: its proposed type must be allowed, its trigger signals must include that entry's required observed signals, and its evidence roles must cite that entry's exact non-empty fact role. Matching scope or reason code is insufficient. This second gate prevents an LLM response from escaping the pre-call eligibility boundary.
Prompt C must not be asked to invent storage identity. The candidate compiler must be conservative:
- never write active assets;
- never update
golden/index.yml; - never make a candidate eligible for normal Prompt A/B retrieval in the same
run; an app-enabled one-shot trial may pass one newly persisted candidate
through the explicit
candidate_trial_contextchannel defined below; - never overwrite an existing candidate path by default;
- resolve canonical scope from the consumer app contract, not LLM text;
- reject absolute paths, URLs, filenames and Golden asset paths as episode evidence;
- compile evidence roles into
trace_id + cycle_id + artifact_rolerefs; - compile a bounded observed-signal catalog from structured episode evidence;
- compile a bounded learning-candidate eligibility contract from the consumer app declaration and non-empty producer-owned facts before invoking Prompt C;
- require every compiled candidate to match one eligible contract's candidate type, required observed signals, and evidence fact role;
- require every proposed trigger signal to copy a concrete catalog entry; reason codes, evidence-role names, source phase, and generic failure words do not establish novelty by themselves;
- derive one
candidate_family_keyfrom future asset type, canonical subagent/module scope, and sorted related reason codes; - allow at most one open inactive candidate in a candidate family; later
episodes must choose
enrich_existingor[]; - skip proposals structurally covered by a relevant approved Golden card;
- generate deterministic fingerprints and candidate IDs;
- enforce
max_candidates_per_episode: 2across all invocations sharing the sametrace_id + cycle_id + source_phase, not once per invocation.
Prompt C is opportunity-learning, not a fixed production step that emits every asset class on every diagnosis. The default output is an empty list:
learning_candidates: []
Candidate generation gates:
- emit no candidate when the episode adds no new reusable boundary;
- emit one candidate when the episode has a clear high-value learning signal;
- emit two candidates only when the same episode contains two distinct lessons;
- do not emit three candidates just to cover positive case, counterexample, and pattern buckets;
- cap output at
max_candidates_per_episode: 2unless a future contract explicitly raises the budget.
Candidate class selection:
| Proposed asset type | Use when | Do not use when |
|---|---|---|
positive_case | the diagnosis / route has a strong closed-loop confirmation, such as later convergence, accepted campaign action, or human confirmation | the episode only has an unverified diagnosis |
counterexample | the episode exposes a tempting but wrong diagnosis and has explicit contradiction evidence | there is no concrete wrong interpretation to guard against |
pattern | the episode reveals a reusable judgment pattern, success pattern, failure pattern, or boundary signal that can generalize beyond one run | the lesson is only a one-off story with no reusable signal shape |
Selection priority is:
clear misdiagnosis guard -> counterexample
reusable judgment pattern -> pattern
closed-loop proof that this diagnosis was right -> positive_case
Prompt C must compare the completed Prompt B diagnosis and Campaign decision
with verified post-episode feedback. Explicit human review, repeated
same-route/no-progress campaign history, and later verified evidence are
learning facts: they cannot rewrite the completed diagnosis or route, but they
can prove that the episode should propose a counterexample. A candidate that
only restates or extends the selected approved asset without citing a new
evidence boundary is not useful learning and must be omitted. When contradiction
evidence disproves the tempting diagnosis or route, the candidate should cite
those refs and use contrasts_with for the misleading related asset. When
post_episode_feedback.contradiction_evidence_refs is present, a proposed
counterexample must cite every declared contradiction ref or fail candidate
validation. The observed episode itself must satisfy the candidate's
generalization_boundary; verified episode facts must not be moved into
anti_signals or anti_overgeneralization. If an upstream surface reports
zero/empty while later verification finds usable source data, the lesson is a
stale discovery/materialization boundary, not actual source exhaustion.
Before this comparison, the substrate must provide a bounded set of relevant
approved Golden cards and inactive candidates. Retrieval is scoped first by the
app-declared canonical source scope, then by reason codes and normalized
trigger/anti signals. It must not send the entire approved index to Prompt C.
The comparison context also contains the program-compiled observed-signal
catalog. Prompt C may only copy concrete trigger labels from that catalog.
The compiler must not treat reason-code values, failure-kind values, phase names,
status values, tool names, or evidence-role keys as observed novelty. Those values
only identify the diagnosis episode. A reusable trigger must be either an exact
producer-declared trigger_signals item or the ID of a matched
contracts.observed_signal_rules rule. The compiler must not walk arbitrary fact
roles, inspect numeric signs, parse error prose, or synthesize labels from field
names. Purpose, current scope, selector state, artifact references and handoff
metadata remain comparison context rather than reusable failure signals.
App-specific facts enter Diagnosis only through app-declared evidence/catalog
contracts. The substrate does not reserve a fact role, infer an episode kind, or
add a special Prompt C output contract. Trace, asset, candidate, field and
revision IDs are identity, not observed novelty signals. Prompt C should center
any proposal on the most specific declared observed signal. A title or summary
that only restates the current reason code and Campaign route is not a reusable
lesson and should result in [].
Empty remains correct for transient, unverified, covered, or non-reusable facts.
Conversely, an uncovered concrete leaf that establishes a reusable distinction
between diagnosis classes or repair actions should normally produce one proposal.
The current Campaign outcome is an observed controller decision, not proof that
the selected target repaired the failure or that the target phase owns a missing
business product. Without explicit verified post-episode feedback, Prompt C must
describe only the evidence boundary. The draft validator rejects positive prose
that names the current Campaign target, even when the target is described as a
producer or repair owner rather than as a restart action. This gate is compiled
from the episode target; it must not hard-code app step names.
More generally, an episode without
post_episode_feedback.repair_outcome_verified: true cannot establish a repair
prescription. Its candidate may capture a diagnosis boundary, but positive prose
must not prescribe that a layer should/must restart, rerun, rebuild, generate,
relax, route, or otherwise fix the product. why_worth_reviewing explains the
value of the distinction, not an unverified solution.
Prompt C canonicalization may omit existing_candidate_ref: null only for
propose_new, where the field is contractually absent. It must not repair a
missing enrich_existing reference or synthesize any semantic field.
If a structured leaf error should become reusable learning input, the producer
must expose a stable trigger signal or the app must declare a path rule for that
fact. Diagnosis must not normalize the leading error token or infer business
meaning from parameter text.
Prompt C must not upgrade a missing binding/reference/input/handoff into source
data unavailability or exhaustion without explicit episode evidence. The
candidate should preserve the observed contract boundary and route distinction.
For missing-binding episodes, the admissible fact is “the current handoff lacks
the required binding.” Without verified post-episode repair evidence, a candidate
must not prescribe inspection/rebuild of the Campaign target or claim the field
was not produced. “Producer gap”, “field-generation gap”, and “field not
produced” are unsupported without an explicit producer fact. Related asset IDs
must be copied from supplied context.
Observed leaf IDs and catalog reason codes remain separate namespaces: triggers
come from observed_signal_catalog. Prompt C must not emit a reason code. The
candidate compiler copies related_reason_codes from the completed Prompt B
diagnosis and writes the same canonical codes into the persisted index-card
draft. This keeps diagnosis ontology out of the learning LLM's output surface.
Candidate similarity has three deterministic layers:
- an approved-card coverage gate rejects lessons already represented by active Golden;
- a candidate-family gate prevents multiple open proposals for the same future type, canonical scope, and reason-code family;
- exact fingerprint matching rejects the same structural signal boundary.
Free-form title, summary, generalization_boundary, and
anti_overgeneralization text cannot create a new identity or bypass these
gates.
Prompt C outcomes have these meanings:
| Outcome | Persistence behavior |
|---|---|
learning_candidates: [] | no new reusable lesson; write nothing |
enrich_existing | report the matched candidate and enrichment suggestion in learning audit; do not overwrite |
propose_new | compile identity/provenance and persist only if all gates pass |
These are Prompt C's only actions. An empty list is the no-op action; each
non-empty semantic draft must choose exactly enrich_existing or
propose_new. Prompt C must not emit candidate IDs, storage locators, source
scope, episode identity, diagnosis reasons, Campaign routes, or permission for
another repair/quality wave. Those values are either compiler-owned or outside
the learning side path entirely.
fail2pivot may receive this bounded feedback through the generic
episode_feedback payload. The substrate copies it into Prompt C's
episode_context.post_episode_feedback only after baseline Prompt B and a
provisional Campaign outcome have finished. The feedback channel remains
learning-only. It cannot directly rewrite Prompt B, Campaign, checkpoint state,
or the active Golden index. When the consumer app explicitly enables one-shot
candidate trial, one newly persisted candidate may be supplied to one fresh
Prompt A/B diagnosis as bounded trial context. Only that standard diagnosis may
produce a different app-declared result code; Campaign still routes solely from
the final diagnosis result. Consumer-specific diagnosis result/route semantics
remain owned by consumer assets.
pattern is not limited to failures. It may describe a successful convergence
shape, a healthy-module signal, a failure mechanism, or a boundary rule.
Prompt C does not contain episode-specific candidate-type rules. It may return
[], enrich_existing, or propose_new under the common candidate draft
schema. Candidate type and semantic content are assessed from app evidence and
normal Golden contracts, not from substrate predicates for a named workflow.
Minimum Prompt C semantic-draft contract:
learning_candidates:
- decision: propose_new # propose_new | enrich_existing
proposed_asset_type: counterexample
title: Zero qualified alone is not L2 physical failure
summary: A candidate guard against overdiagnosing physical execution.
why_new: observed confusion not covered by approved assets
why_worth_reviewing: repeated failure mode with clear evidence boundary
evidence_roles:
- phase_failure_facts
- diagnosis_facts
related_assets:
- id: evaluate-alphas-metrics-low-fitness-alone-is-not-skeleton-invalid
relation: contrasts_with
proposed_index_card:
summary: Zero qualified alone is not L2 physical failure.
trigger_signals:
- zero qualified with executed simulations
anti_signals:
- tool execution failure
guards_against:
- confusing low performance with runtime failure
generalization_boundary: applies only when platform/runtime errors are absent
anti_overgeneralization: do not use this to suppress true schema failures
existing_candidate_ref: '' # required only for enrich_existing
The persisted candidate is a compiled artifact. The compiler adds:
candidate_fingerprint: sha256-of-canonical-learning-boundary
candidate_id: lc-<fingerprint-prefix>
candidate_family_key: sha256-of-type-scope-and-reason-codes
related_reason_codes: # compiler copies exact Prompt B result codes
- L2_FIELD_BINDING_BAD
source_scope:
subagent: <app-declared canonical slug>
module_or_layer: <app-declared canonical module>
phase: <failed source phase>
source_episode:
episode_key: trace-...:cycle-0001:<failed source phase>
trace_id: trace-...
cycle_id: cycle-0001
source_phase: <failed source phase>
evidence_refs:
- trace_id: trace-...
cycle_id: cycle-0001
artifact_role: phase_failure_facts
review_status: proposed
active_runtime_allowed: false
source_episode is valid only for a real runtime episode. An app may import a
review candidate from a versioned historical experiment record, but it must not
invent a nexrur trace or cycle. A persisted candidate therefore carries exactly
one compiler-owned provenance form: source_episode or source_record.
source_record:
record_key: sha256-of-canonical-source-record
source_kind: historical_experiment_log
source_ref: tools_ai/example/tracking/experiment_log.md
source_sha256: <sha256 of the exact imported file version>
record_id: batch-08
line_start: 176
line_end: 185
source_span_sha256: <sha256 of the exact bounded line span>
subject_refs:
- kind: alpha_id
id: <external platform identity>
evidence_refs:
- source_record_key: <same record_key>
artifact_role: historical_experiment_record
The historical-record compiler must reject absolute paths, parent traversal,
missing or mismatched hashes, an end line before the start line, a record ID
that is absent from the bounded span, and external subject IDs that are absent
from that span. It derives record_key from the normalized app-relative source
reference, file hash, record ID, line interval, span hash, and sorted subject
references. Display prose and array order do not participate in identity.
Historical imports use the same inactive candidate queue, duplicate/family gates, review flags, and no-route boundary as runtime Prompt C candidates. They are not newly persisted by the current fail2pivot episode and are therefore never eligible for the same-episode one-shot Diagnosis Trial. They may affect runtime diagnosis only after human review, promotion into an approved Golden asset, and index registration.
Historical material must pass through a factual compilation boundary before an
LLM can summarize it. The app may declare
contracts.historical_learning_import with runtime_binding: review_only,
bounded record/table/text budgets, and one or more app-relative source records.
The substrate implementation is source-neutral: it knows Markdown headings,
tables, fenced blocks, labeled numeric facts, hashes, and line spans, but it does
not know Alpha metrics, Batch semantics, or app lesson names.
For a selected heading, the compiler closes the record at the next heading of the same or higher level. It may retain only the heading, declared table cells, enabled fenced blocks, and numeric tokens from app-declared labels. It must not copy ordinary prose or author-written hypotheses, decisions, lessons, attributions, or next-step recommendations. A record with no retained factual block fails closed instead of sending narrative text to the LLM.
The compiled unit contains source_record, a deterministic fact_unit_id, a
hash of the canonical factual payload, and the bounded factual payload itself.
The LLM may later infer a transferable pattern by comparing units, but it cannot
change source identity, line bounds, source hashes, subject references, or raw
facts. Factual compilation does not write a Candidate and does not invoke
Diagnosis Trial.
An app may separately declare a review-only historical Candidate plan. The
plan binds each proposal to explicit fact-unit selectors, a primary
source_record, canonical source_scope, catalog reason codes, allowed future
asset types, and a stable factual trigger. These are compiler inputs, not Prompt
C output. The app may also deny selected record-heading prefixes when an
incident belongs to deterministic Product Validation rather than Golden
learning.
The plan may include a review question that focuses Prompt C on a comparison. It is an instruction, not evidence: it cannot override the compiled records, and insufficient facts still require an empty result.
Historical Prompt C reuses the normal semantic draft schema and its only three
outcomes: [], enrich_existing, or propose_new. It runs once per declared
proposal over bounded fact units and the normal approved/open comparison set.
Unlike an unverified runtime episode, a historical review may describe a
bounded practice suggested by recorded comparisons. This does not relax the
ban on diagnosis reasons, Campaign routes, restart targets, active promotion,
or claims of universal/unique causality.
The compiler owns candidate family, fingerprint, ID, scope, provenance,
evidence refs and filename; persistence uses the existing inactive queue and
duplicate/family gates. Historical Candidates never receive source_episode,
never enter same-episode Trial, and never change Diagnosis or Campaign output.
Prompt C output containing compiler-owned identity, path, source scope, episode identity, diagnosis reason, route, activation flags, wave authorization, or absolute evidence paths must fail the draft contract. The compiler must not silently accept those values.
The candidate path is derived mechanically from proposed_asset_type, the
app-declared canonical source_scope, and the compiler-generated candidate ID:
golden/candidates/
positivecases/
<subagent>/
<module-or-layer>/
<subagent>-<module-or-layer>-<case-slug>.md
counterexamples/
<subagent>/
<module-or-layer>/
<subagent>-<module-or-layer>-<case-slug>.md
patterns/
<subagent>/
<module-or-layer>/
<subagent>-<module-or-layer>-<case-slug>.md
proposed_asset_type: positive_case maps to the positivecases/ candidate
bucket. counterexample maps to counterexamples/; pattern maps to
patterns/. The file stem must include the same <subagent> and
<module-or-layer> values used in the directory path.
Consumer apps own the allowed scope set. For example, an app may declare that
Evaluate candidates are limited to evaluate-alphas/metrics and
evaluate-alphas/settings. The compiler resolves that scope from the app's
current-step, failed-phase, and selected Prompt B reason-family mapping. Prompt C
cannot emit or override it. If no mapping matches, compilation fails closed;
the substrate must not invent a platform, fail2pivot, or catch-all scope.
Candidate compilation and persistence remain separate deterministic stages.
Compilation owns episode identity, family/fingerprint, candidate ID, filename,
structured evidence references, approved-card coverage, open-family and exact
duplicate gates. Persistence revalidates all compiled identities, writes only
inactive golden/candidates/ artifacts with exclusive create, and never updates
the active Golden index. Replaying the same episode and semantic boundary must
produce a duplicate/open-family skip and zero new files; it must not overwrite
the existing candidate or create a new trial identity.
Candidate family is computed from canonical JSON containing future asset type, canonical subagent/module scope, and sorted related reason codes. Candidate fingerprint adds normalized trigger, anti, and guard signals to that family. Neither identity may include title, summary, free-form generalization prose, source episode, filename, path, phase, or array order.
enrich_existing never updates a candidate file automatically. It is an audit
suggestion for the review workflow. An exact fingerprint duplicate is skipped
regardless of the Prompt C title or proposed filename.
Prompt C failure must be reported as a learning-side failure. It must not
invalidate, rewrite, or downgrade the baseline diagnosis. If candidate trial is
enabled but Prompt C, compilation, persistence, or the trial diagnosis fails,
fail2pivot must publish the baseline diagnosis and its Campaign route.
8.5.5 One-shot inactive candidate trial
An inactive learning candidate may participate in one real repair attempt without becoming active Golden truth. This is an explicit diagnosis replay, not automatic promotion and not a second routing engine.
The execution order is:
baseline Prompt A/B diagnosis
-> provisional Campaign outcome (Prompt C context only; do not publish)
-> same-episode Step6 receipt lookup
-> app-declared learning-research eligibility gate
-> optional Forum Learning declared by the app contract
-> Prompt C semantic draft
-> candidate compile and inactive persistence
-> one-shot trial eligibility gate
-> fresh Prompt A/B diagnosis with candidate_trial_context
-> final Campaign outcome from the selected diagnosis result
Forum Learning, Prompt C persistence, and Trial share the canonical episode
identity trace_id + cycle_id + source_phase. Their bounded completion receipt
is stored in the existing cycle step6.json; no process-local cache or parallel
learning state file is allowed. A replay of the same episode must load and
validate that receipt before eligibility compilation, search, read, Prompt C,
persistence, or Trial. A valid receipt suppresses all six operations, so replay
cannot repeat the learning gate, external research, candidate write, or one-shot
Trial.
The receipt may persist grounded learning units together with their app-declared
evidence_role, declared llm_profile, source hashes, candidate persistence
refs, Trial key, and baseline/final result codes.
It must not persist raw forum text, raw prompts, candidate prose, credentials, or
active Golden content. A receipt without an exact episode key or explicit
replay_complete: true is not reusable.
When a prior Trial was applied, replay may reuse its final diagnosis verdict only if the current app catalog still registers that result code for the same step and the current required/contradiction evidence gate still passes. Otherwise replay keeps the fresh baseline diagnosis. It must never call the candidate again to repair a stale receipt.
Only a candidate newly written by the current persistence call is eligible.
learning_candidates: [], enrich_existing, approved-coverage skips, open-family
skips, duplicate skips, and persistence failures do not start a trial. The trial
gate also requires:
- exact
trace_id + cycle_id + source_phaseprovenance; - one candidate only;
- a valid canonical source scope;
- no candidate-authored reason code, target step, route, or activation flag;
- an app contract that explicitly enables candidate trial;
- no prior trial for the same trial identity.
The explicit app permission is
contracts.learning_candidate_trial_enabled: true in the consumer diagnosis
catalog. learning_candidate_persistence_enabled grants only inactive storage;
it must not implicitly grant Trial. Runtime payloads may not enable Trial when
the consumer catalog does not. An app that omits the Trial flag therefore still
persists eligible candidates, but fail2pivot publishes the baseline diagnosis
without replaying Prompt A/B.
Trial identity is program-owned:
candidate_trial_key = hash(
candidate_family_key
+ subject_id
+ product_revision_id
)
product_revision_id is the failed product revision that the repair will
supersede, such as a skeleton revision or another app-declared stable revision.
The key is attempt identity, not candidate identity and not Golden identity.
Title, summary, path, array position, trace ID, and cycle ID do not participate.
The second diagnosis receives two explicit bounded inputs:
candidate_trial_context:
candidate_id: <compiler-owned ID>
candidate_family_key: <compiler-owned family>
summary: <bounded candidate diagnosis distinction>
why_worth_reviewing: <bounded learning value>
trigger_signals: []
anti_signals: []
generalization_boundary: ""
anti_overgeneralization: ""
source_episode: {}
trial_only: true
upstream_contract_snapshot:
producer_contract: {}
current_product_revision: {}
downstream_failure_facts: {}
context.py prepares and bounds these materials. It does not decide a root
cause, result code, or target. Prompt A/B may select only result codes already
declared by the consumer diagnosis catalog, and the normal evidence gate must
pass. The candidate may sharpen a distinction, but it cannot supply the answer
or bypass contradiction evidence.
The trial must preserve the candidate's bounded semantic distinction, not only
its trigger labels. summary, why_worth_reviewing, and
anti_overgeneralization are candidate-authored hypotheses and remain
untrusted; they cannot carry routes or become evidence. Prompt B compares that
hypothesis against all three snapshot sections: producer contract, current
product revision, and downstream failure facts. The raw leaf reason is an
observed symptom during Trial, not a preselected root cause. Prompt B must
re-evaluate which contract layer owns the failure and then choose only an
evidence-eligible app-catalog reason.
During this explicit Trial, the upstream snapshot is current contract evidence,
not optional historical context. Prompt A's selected active Golden may explain
only the leaf symptom. Prompt B may reject that asset for root-cause ownership,
leave selected_asset_refs empty, and choose another eligible catalog reason
when the candidate hypothesis plus snapshot explains the downstream failure
more completely.
For Trial only, catalog_constraints must include bounded semantic contracts
for every evidence-eligible reason: code, family, description, rendering hints,
and prefer/defer hints. A bare list of reason-code strings is insufficient for
cross-layer rejudgment because the model cannot recover app-owned responsibility
boundaries from names alone. These contracts contain no Campaign target or route
and do not relax the existing evidence or contradiction gates.
fail2pivot owns the composition order and failure policy:
- baseline diagnosis and provisional Campaign are computed first;
- the same-episode receipt is checked before learning eligibility;
not_eligibleskips Forum Learning but may continue Prompt C with the existing approved/open materials;- an invalid eligibility contract stops the learning side path and preserves the baseline diagnosis;
- Forum Learning failure stops the learning side path for this episode and preserves the baseline diagnosis;
- Prompt C and candidate compilation remain learning-side operations;
- the trial diagnosis is attempted at most once;
- a valid trial diagnosis becomes the final diagnosis;
- any trial-side failure publishes the baseline diagnosis;
- a same-episode replay reuses the Step6 receipt and does not rerun Forum Learning, Prompt C, persistence, or Trial;
- an existing unreadable, incomplete, or identity-conflicting receipt fails the StepSix handoff; it is never treated as a missing receipt or a first run;
- Campaign is generated from the final diagnosis exactly once for external handoff.
Joint mock acceptance must keep the learning side path independent from the baseline diagnosis result:
| Case | Required result |
|---|---|
| result code is outside the app allowlist | not_eligible; no Forum call |
| one or more required observed signals are absent | not_eligible; no Forum call |
| one approved Golden card covers every required signal | approved_golden_covered; no Forum call; Prompt C may still use approved/open materials |
| eligibility is valid and approved Golden does not cover the signal set | Forum Learning may run within the declared budgets |
| Forum planning, search, read, or synthesis fails | stop the learning side path and publish the baseline diagnosis/Campaign result |
| same-episode receipt is valid | skip eligibility, Forum, Prompt C, persistence, and Trial |
| same-episode receipt exists but is invalid | fail closed; do not rerun learning or persistence |
The focused acceptance suite must also scan active Diagnosis and Fail2pivot sources for app-owned reason-code literals. App result codes belong only to app catalogs and test fixtures; the substrate may compare declared values but must not branch on a built-in app reason.
Trial can choose only an existing, evidence-eligible diagnosis-catalog reason. It cannot mutate Campaign assets or retry policy and cannot emit route, target, repair-count, or retry authority. Any additional attempt must be authorized by app-owned diagnosis, Campaign, and execution-policy contracts; candidate prose, persistence, or Trial success cannot grant that authority.
The final Step6 envelope may report bounded audit metadata such as candidate ID, trial key, baseline result code, final result code, and whether the trial was applied or skipped. It must not inline candidate prose, raw prompts, or active Golden files. A successful real repair is evidence for later human promotion; it does not auto-promote the candidate.
8.5.6 Golden boundaries
Golden must never:
- replace
evidence.ymlas evidence truth; - replace
diagnosis.ymlas result ontology; - replace campaign
campaign.yml.routesas route truth; - replace campaign assets as halt / restart / escalation execution truth;
- become an app-local Python detector engine;
- auto-promote runtime failure stories into active prompt assets.
Golden may:
- ground diagnosis in reviewed prior episodes;
- prevent tempting but unsupported overdiagnosis;
- supply abstraction patterns and counterexamples to Prompt B;
- propose learning candidates for future asset evolution.
- auto-write inactive Prompt C candidate files when candidate persistence is enabled, without activating them.
- supply one newly persisted inactive candidate to the explicit one-shot trial channel when the consumer app enables it, without adding that candidate to normal Prompt A/B retrieval.
In short:
cases/counterexamples provide groundedness;
patterns provide abstraction;
index cards provide retrieval;
learning candidates provide controlled evolution.
8.5.7 Contract sample layout
src/nexrur/engines/contracts/diagnosis/golden/ should mirror the canonical
shape as a developer-facing contract sample:
src/nexrur/engines/contracts/diagnosis/golden/
README.md
index.example.yml
positivecases/
<subagent>/
<module-or-layer>/
example.md
counterexamples/
<subagent>/
<module-or-layer>/
example.md
patterns/
<subagent>/
<module-or-layer>/
example.md
candidates/
positivecases/
<subagent>/
<module-or-layer>/
example.md
counterexamples/
<subagent>/
<module-or-layer>/
example.md
patterns/
<subagent>/
<module-or-layer>/
example.md
This contracts tree is documentation and fixture material only. It is not a
production diagnosis asset pack and must not be loaded as app truth. Production
truth comes from the app-owned diagnosis asset root registered by payload /
overlay, such as .gemini/skills/_shared/engines/diagnosis/golden/.
8.6 Asset Pack 是 Schema-Validated Contract
§8.0–§8.5 描述的 asset 是 substrate-validated executable contract / classified advisory asset,不是散文配置。它们由 diagnosis contract / app schema pack 登记,由 substrate loader / builder 在加载阶段做 per-file schema 与 cross-file validation。
Golden obligations apply when an app registers golden assets in diagnosis contract / app schema pack. Apps without registered golden assets remain valid, but cannot enable the selector / Prompt B / Prompt C golden chain. In other words:
- feature absent: no golden loader hard fail; diagnosis can still run with
evidence.yml,diagnosis.yml, and classified advisory assets; - feature present but invalid: registered golden assets fail schema / cross-file validation at load time;
- feature present but no approved assets: the pre-LLM selector receives no active golden index cards and must report that no approved golden knowledge was available.
详细 schema governance 规则见 docs/DESIGN_SCHEMA.md §11。本节只声明
diagnosis pack 必须遵守的硬约束。
8.6.1 Per-File Schema Obligations (diagnosis pack)
| Asset | Required structural obligations |
|---|---|
evidence.yml | five-bucket 来源声明完备;path / kind / required 字段齐全;bucket 落在 substrate 已知 bucket 枚举 |
diagnosis.yml | result_code 必须有 family / severity / 描述 / evidence gates;无重复;命名落在 enum 规范;不得含 disposition / route / Product status |
_archived/targets.yml | history-only migration reference;不得作为 active route truth;不得覆盖 campaign routing |
_archived/legacy_classified_markdown/ | retired root-level patterns/examples/counterexamples;history-only;不得进入 active selector / Prompt B / Prompt C 或 production diagnosis prompt |
golden/index.yml | index card 必须有 id / type / summary / trigger_signals / anti_signals / related_result_codes / asset_ref / review_status;不得含 route verdict;asset_ref 相对 golden/ |
golden/positivecases/<subagent>/<module-or-layer>/*.md | approved 正例 full assets;必须有 applies_when / does_not_apply_when / evidence boundary / provenance / review_status;不得含 route verdict |
golden/counterexamples/<subagent>/<module-or-layer>/*.md | approved 反例 / guard full assets;必须有 applies_when / does_not_apply_when / required_evidence / contradiction_evidence / provenance / review_status;不得含 route verdict |
golden/patterns/<subagent>/<module-or-layer>/*.md | approved 抽象 pattern full assets;必须有适用边界 / 反适用边界 / evidence signature / provenance / review_status;不得含 route verdict |
golden/candidates/{positivecases,counterexamples,patterns}/<subagent>/<module-or-layer>/*.md | Prompt C 自动候选落点;必须 review_status: proposed 且 active_runtime_allowed: false;不进入 active selector / Prompt B,除非人工 review/promote 后迁入三类正式 folder 并同步 index |
8.6.2 Cross-File Validation Obligations
| Cross-check | Rule |
|---|---|
| evidence ↔ five-bucket | bucket / kind 必须在 substrate 已知枚举 |
| catalog ↔ campaign route boundary | 每个可输出 result_code 必须在 campaign.yml 有明确 handling;route、continue_with_repair、halt 或 diagnostic-only 都是 Campaign truth |
| campaign lifecycle | 无 executable route 的 result_code 必须在 campaign.yml 显式标记 no_action / halt_only / diagnostic_only |
| campaign escalation/halt ↔ catalog | escalation / halt 引用的 result_code 必须在 catalog 存在 |
| campaign routing ↔ step enum | target_step / target_subagent 必须在 substrate legal step / subagent 词表 |
| classified knowledge ↔ catalog/evidence | pattern/example/counterexample 的分类必须可映射到 known step / failure family / evidence signature |
| golden index ↔ full assets | index asset_ref 必须存在;full asset id / type 必须与 index 一致 |
| golden ↔ catalog | related result_code 必须在 catalog 存在;golden 不得引入裸 result_code |
8.6.3 Naked Result Code 禁令
Naked result_code =
diagnosis.yml声明了可输出 result_code, 但campaign.yml既没有 executable route,也没有显式 no_action / halt_only / diagnostic_only handling。
Naked result_code 必须在 substrate loader / builder 阶段 hard fail,不允许
拖到 longrun 阶段才被 campaign 拒绝。app 一旦在 diagnosis.yml 引入新
result_code,必须同步在 campaign.yml 登记 route 或显式的
no_action / halt_only / diagnostic_only handling。
底座责任: loader 检测到 naked result_code 立即拒绝加载,不允许 fallback
"unknown result"。
app 责任: 修补 diagnosis catalog 或 campaign asset YAML,不允许在 owner /
schema wrapper / Prompt B 中本地补 result_code → target_step 表(详见
§7.3 Sovereignty 与 DESIGN_SCHEMA.md §11.8)。
8.6.4 失败语义
| 时机 | 行为 |
|---|---|
| Load 阶段 schema 违反 | substrate loader hard fail |
| Load 阶段 cross-file 不一致 | substrate builder hard fail |
| Runtime 期 diagnosis 输出未登记 result_code | substrate diagnosis hard fail,不 fallback unknown |
| Runtime 期 naked result_code (未被 §8.6.2 在 load 阶段拦截) | 视为 substrate contract 漏洞,提工单修 loader,不在 app 端兜底 |
9. Diagnosis 与 ToolLoop / Campaign / Orchestrator 的关系
9.1 ToolLoop
ToolLoop 是局部探索器。Diagnosis 是全证据解释器。
-
ToolLoop 负责:
- 工具选择
- 局部探索
- 局部汇总
-
Diagnosis 负责:
- 解释全链路失败
- 融合五桶 evidence
- 产出 diagnosis_result
所以 ToolLoop 不是 Diagnosis 的替代,而是 Diagnosis 的局部感官之一。
9.2 Campaign
Campaign 是总控器。Diagnosis 是总控器的解释器。
-
Campaign 负责:
- budget
- loop
- route
- halt
- final decision
-
Diagnosis 负责:
- 原因分析
result_code诊断分类- evidence-based explanation
- 为 Campaign 提供 triage 输入
所以:
Campaign 可以调用 Diagnosis,但不能把总控权交给 Diagnosis。
9.3 Orchestrator
Orchestrator 是执行壳,不是病理学家。
- Orchestrator 负责执行拓扑
- Diagnosis 负责解释为什么某条路径失效
二者关系是:
- Orchestrator 提供运行事实
- Diagnosis 解释运行事实
Orchestrator 还是 Diagnosis 执行坐标的唯一生产者:
current_step:当前 leaf 所属的 app-level step;phase_path:从 app step 到 nested graph 的声明路径;phase/failed_phase:实际执行或失败的 local leaf;phase_failure_facts:leaf 明确输出后由 Orchestrator 有界转运的运行事实。phase_failure_facts.diagnosis_facts:leaf 生产、app contract 解释的 opaque 业务事实容器;Orchestrator 只做 bounded copy。
其中 phase_failure_facts.reason_code 必须作为原始 leaf candidate 进入
DiagnosisInput 和 Prompt A 作用域;context.py 只能复制、去重和限界,不能
翻译该值。这样 nested leaf 的失败不会因为 Step6 packet 顶层
reason_code 为空而退化成全局 Golden 卡片扫描。
Diagnosis 不得根据 phase_patterns、reason code、错误文本或 artifact 路径重新
解析这组坐标。坐标错误属于 Orchestrator/input contract failure,不属于
Diagnosis 的根因推理任务。
9.4 boundary.py / context.py / diagnosis.py Implementation Boundary
src/nexrur/engines/diagnosis/boundary.py 只定义声明合同并读取底座 Schema。材料读取、
Prompt 渲染、evidence fingerprint 与结果生成均不得放入该文件。
src/nexrur/engines/diagnosis/context.py 只负责准备材料。
输入:
- Step6 的 bounded facts 与 Orchestrator 执行坐标;
- consumer
diagnosis.yml/ evidence assets; - approved Golden index/full assets;
- Prompt 资产与历史 feedback refs。
输出:
- 经过选择、正规化、去重和体积控制的
DiagnosisInput; - Prompt A/B/C 所需的 bounded context、eligible catalog facts、episode/scope、 approved/inactive comparison 和验证约束;
- 已校验的 inactive candidate records;读取失败必须作为显式 contract error 返回。
context.py 不得:
- 决定 primary diagnosis candidate;
- 输出最终
diagnosis_result.result_code; - 输出或改写任何 Product
reason_code; - 把 raw leaf reason 翻译成另一个 app reason;
- 修补或重解释
current_step/phase_path; - 生成
target_step、target_subagent、restart、halt 或 route。 - 调用 Prompt A/B/C、解释 LLM 输出、编译/持久化新 candidate 或执行 Trial。
context.py 必须保留 DiagnosisInput.evidence.diagnosis_facts 的 bounded shape,
供 app diagnosis.yml 与 Prompt 资产消费;它不得把容器内 role 提升为底座字段,
也不得在 Python 中内置任何 app role、path、threshold 或 signal 名称。
Diagnosis runtime assets 必须由调用方显式传入 DiagnosisAssets 或精确的
diagnosis_assets_root。底座不得读取 CWD、父目录、环境变量或进程级缓存来猜当前
App,也不得从 knowledge_root、evidence payload 或其他相邻目录补出 Diagnosis 路径。
缺少或无法加载显式资产时,Diagnosis input contract 必须 fail closed。
Campaign CLI 也属于调用方。App CLI contract 必须用
contracts.diagnosis: <exact-assets-root> 显式绑定;命令行可用
--diagnosis-assets 做本次覆盖。nexrur 不再用固定 .gemini/.../diagnosis
目录作为默认值。
候选故障只允许来自两个 active envelope:显式 reason_candidates[],或单一
phase_failure_facts.reason_code。两者都只做原样、bounded 的机械正规化。底座不得
递归扫描 validation_artifacts、schema_artifacts、simulation_artifacts、
runtime_artifacts、local_artifacts 等旧容器找 reason_code,不得从顶层
reason_code / first_problem 猜候选,也不得按 brain- 等 App 命名约定修剪 scope。
Flash / Pro 使用的 ToolLoop profile 由 App 的 diagnosis.yml 显式声明:
contracts:
diagnosis_llm_profiles:
flash: <registered-profile>
pro: <registered-profile>
两个 profile 都必须是非空精确值;缺失、未知字段或空值均 fail closed。底座只把该
值原样交给 ToolLoop,不按 model 名、provider 名、flash / pro 字样或
use_flash 推断 Gemini、DeepSeek 或任何 provider。
diagnosis_suggestion 只公开 result_code、confidence、evidence、解释、bounded
repair constraints 与 metadata;不得公开 target_step、
suggested_escalation_target 或 diagnosis_actions。这些字段即使为空也不是合法的
Diagnosis Product。Campaign 必须仅凭 App route contract 和已验证的 Diagnosis
result_code 形成执行目标。
App 可以在 diagnosis.yml 的 contracts.observed_signal_rules 声明可审计规则:
contracts:
observed_signal_rules:
- id: <app-owned-stable-signal-id>
fact_role: <exact-key-under-diagnosis_facts>
path: <dotted-path-inside-that-role>
operator: eq
value: <app-owned-value>
底座只提供通用规则执行器:按 fact_role 选择 opaque facts,按 path 读取值,
执行白名单 operator,并在匹配时输出规则自身的 id。首批通用 operator 为
eq、ne、exists、not_exists、gt、gte、lt、lte、contains、
in。规则 ID、role、path 和比较值的业务含义全部归 App;底座不得根据 scope、
字段名、错误文本或数值正负自行合成 observed signal。缺失 path、非法 operator、
无效比较值或不兼容类型必须 fail closed:该规则不匹配,且不得退回文本猜测。
Prompt A/B/C 只能消费 observed_signals 与原始 bounded evidence。旧的
diagnosis_focus 属于 WQ Evaluate/Simulator 专属摘要,必须退出 active Diagnosis;
底座不得再组织 simulation、qualified、slot、pyramid、L2 或 alpha quality 摘要。
src/nexrur/engines/diagnosis/diagnosis.py 才负责执行 Prompt A/B/C、校验模型
输出、在 app catalog 允许范围内分类并形成唯一
diagnosis_result.result_code。它必须同时保持输入中的 Product
status/reason/reason_code 不变,不得把诊断分类写回 Product。
Prompt A/B 没有运行、没有合法候选或执行失败时,Diagnosis 只能在自身
execution_status / errors 中报告失败;不得制造一个 Diagnosis 分类来代替
Product reason,也不得把 diagnosis_unavailable、prompt_a_failed 等底座执行码
写进 Product reason_code。
它仍不得执行 route。campaign.py 只消费这个 Diagnosis result,
并依据 app-owned campaign.yml 决定后续 cycle 的 continue / restart /
reroute / halt;这个决定不得改写当前 cycle Product。
diagnosis.py 只能通过 context.py 的显式公开 material-preparation API 消费准备结果,
不得导入 context 私有 helper。旧的 rag 参数和执行期临时 memory 检索接口退场;
memory/cognition/cross-domain 必须在 DiagnosisInput 形成前显式准备并随输入传入。
9.5 2026-07-20 Rejected Implementation
本次错误实施的现象是:Step6 收到的非空 current_step 实际为 local leaf
dataset_l2_fail2pivot,而不是 app-level step。错误修法是在 context.py 中读取
phase_patterns、source_phase、phase、failed_phase,再把该 leaf 猜回一个
app step。
该修法被否决,原因是:
- 它掩盖了 Orchestrator 写错执行坐标的上游 contract defect;
- 它让 Diagnosis 长出第二套 nested graph resolver;
- 它让 diagnosis catalog 反向决定执行身份,破坏 contracts ownership;
- 同名、模糊或未来新增 leaf 会产生静默重解释,可能把错误送入错误 catalog;
context.py从材料准备层越权成为 reason scope 与 graph identity 决策层。
正确修复是:Orchestrator 从真实递归 graph stack 写入唯一 app-level
current_step,同时原样保留 local phase / failed_phase / phase_path;
context.py 对缺失或冲突坐标 fail closed;diagnosis.py 只基于合法
DiagnosisInput 产生 Diagnosis result;Campaign 再执行路由。不得保留旧推断作为
compatibility fallback。
10. 与五桶 evidence 的关系
Diagnosis 不是一个封闭 engines 模块,而是系统级消费者。
10.1 与 core
Diagnosis 必须吃:
- 失败步骤证据
- Validation (schema-driven) report
- outcome
- audit/evidence ledger
- schema/policy/runtime contract refs
如果 Diagnosis 不吃 core evidence,它就是盲诊。
10.2 与 engines
Diagnosis 必须吃 bounded engines facts:
- orchestrator checkpoint index
- campaign control state
- toolloop event index
- LLM/tool usage refs
- phase failure / timeout / provider error short facts
否则 Diagnosis 无法区分业务失败、执行失败和状态连续性失败。完整 checkpoint、 events、tool output、prompt、provider response 只能作为 refs,不能进入 diagnosis prompt。
10.3 与 aiskills
Diagnosis 必须吃:
- app business artifacts
- production verdict / bounded summary
- schema validation projection
- diagnosis / Step6 active projection
- upstream/downstream business refs
否则 Diagnosis 无法解释 app 业务语义是否漂移。
10.4 与 memory
Diagnosis 必须吃:
- contentstore / vectorstore bounded retrieved units
- app-declared historical raw material refs
- previous product / derived artifact recall
- transferable lessons or cross-domain lessons after store retrieval
否则 Diagnosis 只能看“发生了什么”,不能看“过去哪里失败过、哪些跨域经验可迁移”。 Memory 不能替代当前事实,也不能直接触发 route / halt。
10.5 与 golden
Diagnosis 必须吃 approved golden grounding:
- positive cases
- counterexamples
- patterns
- index cards selected by pre-LLM selector
否则 Diagnosis 只能自由发挥,无法受历史正反例约束。Golden 不含 route truth; 它只约束 Prompt B/C 的解释边界。
11. 标准数据流
Five-bucket evidence bundle
+ core / engines / aiskills / memory / golden refs
+ consumer diagnosis assets
│
▼
nexrur.engines.diagnosis
│
├─ load app diagnosis asset pack
├─ normalize Step6 evidence envelope
├─ match catalog + selected approved golden cognition
└─ produce diagnosis_result
│
▼
diagnosis_result
│
▼
campaign consumes diagnosis_result
│
▼
campaign_control decides continue / continue_with_repair / reroute / halt
continue_with_repair 是 Campaign 对后续行动的控制结果,不是
Diagnosis 对当前 Product 的二次状态判定。当前 Product 能否继续
由 producer 已经返回的 status 决定;Campaign 只登记后续 repair /
rerun target。Production、Diagnosis 和 Campaign 的原始结果必须分层进入
Step6、checkpoint、active 和 Admin 事实面,不得互相覆盖。
12. 文件归属与目录设计
12.1 nexrur active 目录
src/nexrur/engines/diagnosis/
__init__.py
boundary.py
context.py
diagnosis.py
schemas/
_schema_index.yml
nexrur_diagnosis_flash_assessment.yml
nexrur_diagnosis_pro_assessment.yml
nexrur_diagnosis_golden_asset_selection.yml
nexrur_diagnosis_golden_diagnosis_verdict.yml
nexrur_diagnosis_golden_candidate_draft.yml
nexrur_diagnosis_golden_candidate.yml
nexrur_diagnosis_candidate_trial_handoff.yml
nexrur_diagnosis_upstream_contract_snapshot.yml
nexrur_diagnosis_suggestion.yml
src/nexrur/prompts/
diagnosis.md
schemas/_schema_index.yml 是 Diagnosis logical role 到 schema file 的唯一 active
mapping truth;其余 schema files 是结构合同。目录命名沿用 Evidence 与 Projection 的
稳定格式:
nexrur_<engine>_<stable-role-or-artifact>.yml
因此文件名描述长期稳定的角色或产物,不描述当前实现顺序。禁止使用
prompt_a.yml、prompt_b.yml、prompt_c.yml、step_1.yml 之类流程字母或步骤号
命名;Prompt 顺序可以演进,但 golden_asset_selection、
golden_diagnosis_verdict、golden_candidate_draft 等合同角色必须保持稳定。
12.2 Schema 职责清单
| Schema | 结构职责 | 当前 Python 迁移来源 |
|---|---|---|
nexrur_diagnosis_flash_assessment.yml | Flash 初判输出 shape | boundary.py 声明 role 并通过 core Schema 读取 |
nexrur_diagnosis_pro_assessment.yml | Pro 复核输出 shape | boundary.py 声明 role 并通过 core Schema 读取 |
nexrur_diagnosis_golden_asset_selection.yml | Golden 资产选择结果;对应当前 Prompt A 角色 | boundary.py 声明 role;context.py 准备输入,diagnosis.py 校验输出 |
nexrur_diagnosis_golden_diagnosis_verdict.yml | Golden-grounded Diagnosis verdict;对应当前 Prompt B 角色 | boundary.py 声明 role;context.py 准备输入,diagnosis.py 校验输出 |
nexrur_diagnosis_golden_candidate_draft.yml | Prompt C 只可生成的语义草稿与 [] / enrich_existing / propose_new 决策 | diagnosis.py 的 Prompt C 输出校验;context.py 只准备输入材料 |
nexrur_diagnosis_golden_candidate.yml | Candidate compiler 编译后的 inactive persisted candidate | diagnosis.py 的 compiler/persistence;context.py 只负责 fail-closed queue read |
nexrur_diagnosis_candidate_trial_handoff.yml | 本 episode 新候选进入一次性 Diagnosis Trial 的 bounded handoff | diagnosis.py 的 Trial handoff compiler;context.py 只准备显式 episode identity |
nexrur_diagnosis_upstream_contract_snapshot.yml | Trial 使用的 bounded upstream contract snapshot | diagnosis.py 的 snapshot section/shape 检查 |
nexrur_diagnosis_suggestion.yml | Diagnosis 对 Campaign 公开的结构化 Product;不含 route/control | diagnosis.py 的最终 suggestion/result shape |
必须明确区分:
golden_candidate_draft是 LLM 的无身份语义草稿;golden_candidate是程序分配 identity、scope、fingerprint、evidence refs 后的 inactive candidate;candidate_trial_handoff是一次性试用通道,不是 approved Golden,也不进入普通 Golden retrieval;diagnosis_suggestion是 Diagnosis Product,不得携带target_step、target_subagent、restart、halt 或 Campaign route。
12.3 加载与消费规则
Diagnosis schema 使用与 Evidence/Projection 相同的 JSON-Schema-like YAML 形状:
type、required、properties、items、enum 等。实现对齐时遵守:
schemas/_schema_index.yml只登记稳定 logical role 到 schema file 的映射;nexrur.core.schema是唯一 YAML loader、schema definition checker 和递归 validator;boundary.py可以缓存通过 core schema 加载的 schema,并提供 enum/required/ properties introspection,但不得读取 YAML、保存 role-to-filename 字典或实现私有 validator;context.py只消费已加载合同来准备、裁剪和验证材料,不复制 required/allowed 字段常量;diagnosis.py只消费已验证结构执行 Diagnosis,并形成最终 Product,不维护第二份 schema dict;- schema index/mapping/file 缺失、YAML 无法解析、根节点不是 mapping、合同自身不完整时, Diagnosis 执行失败,不得退回内联 Python schema;
- schema logical role 由底座固定,不允许 app payload 覆盖 index 或任意文件路径;
- 不新增 Diagnosis-local schema helper 模块;公共能力继续收敛在
core/schema.py。
12.4 Schema 与 Policy 边界
应迁入 YAML 的只有可机械验证的结构事实:
- required / optional 字段;
- object / array / string / number / boolean 类型;
- 稳定枚举;
- nested object shape;
- LLM 草稿、编译产物、Trial handoff、最终 Product 的字段边界。
不得迁入 Diagnosis schema:
- app
result_code的业务含义与 catalog evidence gate; - reason 选择、置信度解释和 Golden 语义判断;
- candidate fingerprint、episode limit、近似检索和去重算法;
- candidate scope 到物理目录的映射;
- cross-wave applicability、改善/退化的业务解释;
- Campaign route、repair budget、restart、halt、replacement trace;
- 任何 WQ-YI、AUDIT 或其他 app-specific reason/phase/target 值。
底座 schema 可以要求 result_code 是非空字符串,但合法值仍必须在 consumer
diagnosis.yml 中声明并由 catalog gate 校验;不能把 app 枚举复制进底座 schema。
同理,schema 可以禁止 route 字段,却不能决定 route。
12.5 去重与迁移完成条件
YAML 生效后,Python 中对应的内联结构定义必须删除,禁止“YAML 校验一次、Python 常量再校验一次”的双真相。语义算法可以保留,但只能读取 schema 校验后的结构。
迁移完成必须满足:
- 五个
boundary.py内联 LLM output schema 已删除; context.py中只表达结构的 draft/candidate/trial 字段集合已删除或由 schema 派生;diagnosis.py中只表达结构的 Trial/snapshot/output 字段集合已删除或由 schema 派生;- 缺失、损坏、不完整 index/mapping/schema 的 focused tests 均 fail closed;
- Flash、Pro、Prompt A/B/C、candidate compile、Trial 和最终 suggestion 的既有行为测试 继续通过;
context.py仍不决定 reason,diagnosis.py仍不执行 Campaign route。
迁移完成后,active Diagnosis Python 不再直接调用 yaml.safe_load 读取自己的 schemas,
也不再出现 DIAGNOSIS_SCHEMA_FILES 或第二套 _validate_json_schema_properties
实现。只创建 YAML/index 而未删除私有 loader/validator 不算完成。
12.6 consumer(WQ-YI / AGV / AUDIT)
_shared/engines/diagnosis/
evidence.yml
diagnosis.yml
golden/
index.yml
positivecases/
<subagent>/<module-or-layer>/
counterexamples/
<subagent>/<module-or-layer>/
patterns/
<subagent>/<module-or-layer>/
candidates/
positivecases/<subagent>/<module-or-layer>/
counterexamples/<subagent>/<module-or-layer>/
patterns/<subagent>/<module-or-layer>/
_archived/
legacy_classified_markdown/
12.7 兼容期遗留
_shared/engines/modules/diagnosis/
仅可作为:
- legacy import compatibility subtree
不得再作为:
- diagnosis 主实现目录
- prompt 真身目录
- knowledge 真身目录
13. 为什么不能让 app 继续长 diagnosis engine
如果 app 继续拥有自己的:
toolloop_diagnosis.pyskill_diagnosis.pyai_diagnosis.py- 各种 detector Python 主逻辑
那么结果一定是:
- 底座失去统一智能主脑
- 每个 app 各长一套 diagnosis
- cross_domain / cognition / evidence / memory 永远接不成统一闭环
- nexrur 再次沦为半吊子 runtime substrate
所以 app 的边界必须像 Claude Code 的 skill 体系一样窄:
只允许交标准化资产,不允许再长 agent 主脑。
14. 与 Cross-Domain / Cognition 的统一关系
Diagnosis 不只是 consumer asset pack 的消费者,它是五桶 evidence 的统一解释层:
coreenginesaiskillsmemorygoldenconsumer diagnosis assets
其中 cognition、调用方显式准备的 memory lessons、crossdomain lessons 都归入
memory bucket,而不是独立决策层。Diagnosis 不持有 RAG 执行接口。
14.1 Cross-Domain 是 memory bucket 的经验迁移输入
Cross-domain knowledge 不是独立 feature,也不直接触发 reroute。它必须先成为 memory bucket evidence,再由 Diagnosis 解释。
14.2 Cognition 是 memory bucket 的认知输入
Cognition 不是 AUDIT 独有 feature,它是 Diagnosis 的:
- 上下游认知契约输入
- trace-local semantic evidence
14.3 统一结论
Cross-Domain 与 Cognition 都应被视为
memorybucket 中的 evidence,而不是并列的小 feature,更不能绕过 Diagnosis/Campaign 直接改 lifecycle 或 route。
15. Diagnosis Input Ownership
Diagnosis 输入不是单一 ownership。它至少分成 app-owned evidence、substrate-owned mechanism、asset-pack truth 三个 ownership 面:
| 输入层 | ownership | 内容 | 作用 | 跨 app 语义 |
|---|---|---|---|---|
| raw evidence payload | app-owned | step outcome、gate report、simulation summary、skill output、domain metrics | 解释当前 app / 当前 trace / 当前资产发生了什么 | 顶层 evidence envelope 可通用,payload 解释不保证跨 app 成立 |
| local cognition | app-owned | brief、validation、trace-local reasoning、current pipeline-local lessons | 解释当前 app / trace / asset 的上下文和认知偏差 | 不保证跨 app 成立 |
| crossdomain lessons | substrate-owned bridge mechanics + app-owned physical storage | promoted transferable lessons、reusable patterns、cross-app guidance | 给多个 app 的 diagnosis 提供可迁移 grounding | 应尽量跨 app 成立 |
硬规则:
原始 evidence payload 的解释权归 app。原始 cognition 一律 app-owned;可迁移的 crossdomain lessons 由 substrate bridge mechanics 生成,但物理落盘在当前 app 的 runtime support root。底座可以拥有提升/检索机制,但不自动拥有内容语义。
15.1 Local cognition
Local cognition 指:
- brief
- validation
- trace-local reasoning
- current pipeline-local lessons
- 当前 app 对某个资产 / trace / run 的上下文解释
它回答的是:
- 当前 app 认为自己在做什么?
- 当前 trace 上下文里,哪些判断已经被上游或下游确认?
- 当前资产为什么进入这个 repair / route / halt 分支?
它的 ownership 是 app-owned,原因是:
- 它通常包含 app step vocabulary。
- 它通常依赖 app asset schema。
- 它通常依赖 app diagnosis / campaign contract 的业务解释。
- 它不保证离开当前 app 后仍可正确解释。
因此,local cognition 可以被底座 diagnosis 消费,但不能被底座当成生产语义真值。
15.2 Crossdomain lessons
Crossdomain lessons 指被明确提升为 transferable 的经验:
- reusable failure pattern
- transferable repair lesson
- cross-app guidance
- 经过归一化的结构相似性结论
它的 bridge mechanics 是 substrate-owned,物理存储是 app-owned,原因是:
- 它已经从 app-local payload 中抽象出来,需要底座提供通用提升和检索机制。
- 它的目标是服务多个 app。
- 它不能继续依赖某个 app 私有字段才能解释。
- 它仍是由当前 app 运行触发产生的运行产物,不应串写进另一个 app 或 nexrur 仓的
docs/ai-runs。
进入 crossdomain layer 的前提是 promotion,而不是简单复制:
app local cognition / evidence
│
│ normalize + abstract + promote
▼
substrate crossdomain lesson
没有 promotion 的原始 cognition 仍然归 app。
16. Diagnosis And Multi-App Execution
跨 app subagent 调用不改变 local cognition ownership。
核心规则:
subagent 来源 app 不等于 local cognition ownership。ownership 取决于它服务哪个 trace,以及内容是 trace-local 认知还是 transferable shared lesson。
16.1 触发 trace 的 app 拥有 local cognition
如果某个 trace 由 AGV 触发,即使它调用了 AUDIT 或 WQ-YI 的 subagent:
- AGV 拥有该 trace 的 local cognition。
- AUDIT / WQ-YI subagent 只是在该 trace 内提供执行能力或 app-specific skill 输出。
- 这些输出进入 AGV trace 的 local evidence / cognition 时,不自动变成 AUDIT / WQ-YI owned cognition。
16.2 底座拥有 cross-app shared lesson layer
只有当 trace-local 内容被归一化并提升为 transferable lesson 时,才进入 substrate crossdomain layer。
例如:
- AGV
agv-asset-oracle调 AUDIT 审计 subagent。 - AUDIT subagent 产生的原始审计解释服务 AGV trace,因此 local cognition 归 AGV。
- 如果其中某个 failure pattern 被抽象成可迁移 lesson,才进入 substrate crossdomain layer。
再例如:
- AGV
agv-mm-arv调 WQ-YI curate / dataset subagent。 - WQ-YI subagent 产出的 raw skeleton / dataset binding 解释服务 AGV trace,因此原始 local cognition 仍归 AGV。
- 只有跨 app 可复用的“curate failure pattern”或“dataset binding failure pattern”经过 promotion 后,才归 substrate crossdomain。
16.3 不允许的误判
禁止:
- 因 subagent 来自 WQ-YI,就把 AGV trace 的 local cognition 归 WQ-YI。
- 因文件写在
nexrur/docs/ai-runs,就把 app evidence payload 解释权归底座。 - 因 lesson 被底座存储,就把未归一化 app-local 语义当成 substrate truth。
17. ai-runs Ownership Model
ai-runs 不是单一语义 root。它同时承载:
- substrate runtime state
- substrate runtime support stores
- app-owned business run artifacts
- mixed / transitional runtime containers
runroot.py 已退场;路径 ownership 必须由各 writer/engine owner 显式解析,不能再恢复成一个全局 resolve_runs_root()。
17.1 Ownership table
| 目录族 | 物理位置 | ownership | 原因 |
|---|---|---|---|
.engines/.orchestrator/ | nexrur/docs/ai-runs | substrate-owned | 纯 runtime checkpoint / trace state;step_order 等值来自 app contract,但 checkpoint 外壳归底座 |
.memory/vectorstore/ | current app docs/ai-runs | app-owned runtime support with substrate mechanics | 可由 Diagnosis 上游准备 memory lessons;Diagnosis 自身不打开或查询该索引 |
.memory/contentstore/ | current app docs/ai-runs | app-owned runtime support with substrate mechanics | ContentStore index/cache 在 app 内共享,不承接其他 app 的业务内容 |
.core/.audit/<trace_id>/<cycle_id>/audit.jsonl | app local audit root under app docs/ai-runs | app-owned observability stream with substrate envelope | audit envelope 可通用;WQ 等 app 的业务 audit 不写入 nexrur 仓,trace/cycle 是主寻址维度 |
.migration-* | nexrur/docs/ai-runs | substrate-owned audit/support | 迁移审计与冲突记录,不是 app 生产资产 |
.llm/.usage/<profile>/<run_id>.jsonl | current app docs/ai-runs | provider-neutral usage ledger with substrate envelope | usage accounting 主通道;summary / hotspots / diagnostics 只消费 provider-neutral usage helpers |
.gemini-usage/ / gemini_usage.jsonl | deprecated compatibility only | legacy Gemini-only explicit audit | 仅当显式配置 AI_AUDIT_JSONL 时用于历史 Gemini 诊断;新代码不得默认写入或扫描 |
evidence-papers/<run-id>/ | app business runs root,当前可能暂在 nexrur/docs/ai-runs | app-owned run artifact | WQ evidence 业务语义强绑定;manifest/outcome 外壳可通用,内容解释归 app |
curate-knowledge/<run-id>/ | app business runs root,当前可能暂在 nexrur/docs/ai-runs | app-owned run artifact | WQ skeleton / idea packet / curate semantics 强绑定 |
dataset-explorer/<run-id>/ | app business runs root,当前可能暂在 nexrur/docs/ai-runs | app-owned run artifact | WQ field binding / pyramid / slot semantics 强绑定 |
evaluate-alphas/<run-id>/ | app business runs root,当前可能暂在 nexrur/docs/ai-runs | app-owned run artifact | WQ simulation / gate / alpha metrics semantics 强绑定 |
datafield-updater/<run-id>/ | app business runs root,当前可能暂在 nexrur/docs/ai-runs | app-owned run artifact | WQ dataset knowledge/category snapshot 强绑定 |
.golden/.cognition/ | app golden cognition root | app-owned | brief / validation / trace-local reasoning 不保证跨 app 成立 |
.memory/local/ | app local memory root | app-owned | app-local lessons / trace-local lessons 归 app |
.golden/.crossdomain/ | current app docs/ai-runs | app-owned storage with substrate bridge mechanics | promoted transferable lessons 由底座机制提升,物理记录留在当前 app |
.engines/.campaign/ | nexrur/docs/ai-runs | substrate runtime | 承载 campaign runtime state;不承载 app semantic summary |
17.2 Substrate-owned
以下目录归底座:
nexrur/docs/ai-runs/.engines/.orchestrator/
nexrur/docs/ai-runs/.migration-*
它们的共同点:
- 保存 runtime state 或 runtime support data。
- 外壳可以跨 app 复用。
- app label 可以出现在 payload 中,但不改变设施 ownership。
17.3 App-owned
以下目录归 app:
WQ-YI/docs/ai-skills/**
WQ-YI/docs/ai-runs/evidence-papers/<run-id>/
WQ-YI/docs/ai-runs/curate-knowledge/<run-id>/
WQ-YI/docs/ai-runs/dataset-explorer/<run-id>/
WQ-YI/docs/ai-runs/evaluate-alphas/<run-id>/
WQ-YI/docs/ai-runs/datafield-updater/<run-id>/
WQ-YI/docs/ai-runs/.core/.audit/**
WQ-YI/docs/ai-runs/.golden/.cognition/**
WQ-YI/docs/ai-runs/.memory/vectorstore/**
WQ-YI/docs/ai-runs/.memory/contentstore/**
WQ-YI/docs/ai-runs/.memory/local/**
WQ-YI/docs/ai-runs/.golden/.crossdomain/**
硬规则:
step run artifacts 的语义 ownership 属于 app,即使当前物理位置暂在 substrate root。
底座可以定义 manifest.json / outcome.json 的通用外壳,但不能拥有:
- WQ reason_code 的业务解释。
- WQ metrics 的业务含义。
- WQ artifact_id / skeleton_id / alpha_id 的领域含义。
- WQ gate / simulation / field binding / curate semantics。
17.4 Shared / Transitional
.engines/.campaign/ 是 active campaign runtime root。
允许短期保留在:
nexrur/docs/ai-runs/.engines/.campaign/
但它的目标状态是:
- 只保留 campaign runtime state。
- 不再承载 app semantic summary 真值。
- app summary / matrix / budget interpretation 应通过 app contract 或 app-owned business runs 表达。
.golden/.crossdomain/ 的 bridge mechanics 归 substrate,但物理落盘归当前 app golden support layer。
它只能接收经过 promotion 的 transferable lessons,不能直接吞 app-local cognition。
17.5 诊断读取规则
Diagnosis 读取这些目录时必须遵循:
- 读取
.engines/.orchestrator/:获得 trace/checkpoint runtime facts。 - 读取
.engines/.campaign/:获得 campaign runtime state;app semantic summary 不在这里持久化。 - 读取 app step run dirs:获得 app business run artifacts;通用
manifest/outcome外壳可由底座解释,业务字段由 app 解释。 - 读取
.memory/local/:获得 app-local lessons。 - 读取
.golden/.crossdomain/:获得当前 app 通过 substrate bridge mechanics 提升的 transferable lessons。
18. Retired runroot Constraints
resolve_runs_root() / runroot.py 已退场,不应作为 V2 active 语义入口恢复。
未来如确需重新引入部署级 root override,只能设计 owner-specific contract,不能恢复全局 root router。最低限度应区分:
resolve_business_assets_root()
resolve_business_runs_root()
resolve_runtime_state_root()
resolve_runtime_support_root()
进一步拆分时,应提供:
resolve_runtime_audit_root()
resolve_runtime_cache_root()
resolve_runtime_checkpoint_root()
resolve_local_evidence_root()
resolve_local_cognition_root()
resolve_local_memory_root()
resolve_crossdomain_root()
硬规则:
resolve_business_runs_root()指向 app-owned business run artifacts。resolve_runtime_state_root()指向 substrate-owned runtime state,例如.engines/.orchestrator/、.engines/.campaign/。resolve_runtime_support_root()对业务 app 指向 app-owned.memory/vectorstore/、.memory/contentstore/等 runtime support 设施;LLM usage 由nexrur.llm.usage写入.llm/.usage/。resolve_runtime_audit_root()对业务 app 指向 app-owned.core/.audit/<trace_id>/<cycle_id>/audit.jsonl根,不承接 WQ 业务 audit 到 nexrur 仓。resolve_local_evidence_root()与resolve_local_cognition_root()指向 app-owned diagnosis input。resolve_crossdomain_root()指向 app-owned.golden/.crossdomain/物理存储;bridge mechanics 仍归 substrate。
后续重构不允许:
- 用单一
runs_root同时表达 app business output、runtime checkpoint、audit cache、local cognition、crossdomain lesson。 - 因目录当前物理位置在
nexrur/docs/ai-runs就改变内容 ownership。 - 把 app evidence/cognition payload 升格为底座 truth。
19. 迁移路线
Phase 1
diagnosis.py成为 substrate diagnosis shell- consumer diagnosis asset pack 标准化
Phase 2
- Step 6 输入统一为五桶 evidence envelope
- app owner 不再自行维护 result-to-target Python mapping
Phase 3
campaign.py消费diagnosis_result并返回campaign_control- reroute 一律从目标 subagent phase 1 重启
Phase 4
- 清退
_shared/engines/modules/diagnosis/与 app-local diagnosis engine 真身 - legacy compatibility shim 只保留在明确退场条件下
20. 完成定义
Diagnosis Substrate 完成时,必须满足:
diagnosis.py是唯一 diagnosis engine shell- app 只提供标准化 diagnosis asset pack
- Diagnosis 统一消费五桶 evidence + consumer diagnosis assets
- Campaign / Orchestrator / ToolLoop 不再各自长隐性 diagnosis 真脑或 route mapping
_shared/engines/modules/diagnosis/被清退或只剩极薄兼容壳- no Step 7 repair;所有 reroute 都由 campaign 控制并从 target subagent phase 1 重启
- Product
status/reason/reason_code在 Diagnosis 前后完全一致 - Diagnosis 只输出
diagnosis_result.result_code,不存在diagnosis_result.reason_code兼容别名 - Diagnosis / Step6 / Campaign 不得把 valid Product partial 就地升级为 stop
21. 反模式与禁止事项
禁止
- app 自己再新增
ai_diagnosis.py - app 在 diagnosis 边界下继续长 Python 主逻辑
- 让 cross_domain 直接触发 reroute,而不进入五桶 evidence
- 让 cognition 只停留在上游 artifact,而不进入 diagnosis 输入
- 让 campaign/toolloop 各自偷偷长 diagnosis intelligence
- 把底座 diagnosis 再次塞满 consumer 专属业务语义
- 在 diagnosis 后新增 Step 7 repair 或 middle-phase hot repair
- 在 app
evidence.py/ Step 1/2/3 中加工 diagnosis semantic summary - 在 app Step 4 production / Step 5 schema wrapper / simulator loop 中判断 root cause 或 campaign target
- 在 app owner Python 中硬编码 reason -> target routing truth
- 用 app-local detector engine 代替
diagnosisengine + consumer diagnosis asset pack - Diagnosis 通过忽略 Production partial 实现假放行
- Step6 / Orchestrator Python 按 app reason code 硬编码 non-blocking
- 把
continue_with_repair输出成 no-action / success,丢失修复事实 context.py根据 leaf 名、phase_patterns或错误文本修补/重解释current_stepcontext.py选择 primary diagnosis、输出最终result_code或生成 route- Diagnosis 输出
reason_code,或用任何别名兼容双写 Product reason - Diagnosis 输出
governance_class/recommended_disposition重建 Product 的 pass / partial / stop 状态机 - Step6 将
diagnosis_result.result_code提升为自身、child graph 或 parent graph 的 Productreason_code - 用 artifact 存在性验证 Product partial 是否“合法”或是否可继续
22. 一句话总结
Diagnosis 是 nexrur program-first 智能闭环的统一解释层:它消费五桶 evidence 与 consumer diagnosis assets,输出独立的
diagnosis_result.result_code;Production 对当前 Product 的status/reason/reason_code保持唯一所有权,Campaign 只决定后续 cycle 动作,任何诊断或控制结果都不得回写当前 Product。
23. Diagnosis 调用图与父级 deadline
Diagnosis 必须向 fail2pivot 声明足以防止父级误杀 child 的 bounded call topology,而不是 把单次 LLM provider watchdog 当作整个父级时限。一次 child floor 包含底座最大 admission wait、provider 无进展 watchdog 和有界返回 tail;串行/并发信息只用于形成保守安全下限, 不用于预测完成时间或中断仍有进展的调用。
nexrur_fail2pivot 的 ToolLoop watchdog floor 不得短于已接纳的 Diagnosis child 加
Campaign 与投影收尾;Orchestrator graph floor 只能延长 Worker operator watchdog。
不得保留短于单个 Diagnosis child 的通用 120 秒父级,也不得用 ToolLoop batch-local
max_total_latency_ms 冒充精确的 Step5/6 完成时限。
若 Diagnosis child 超时、排队耗尽或输出不可用,Diagnosis 返回自己的 execution incident;
它不修改输入 Product。父级超时同样不能把 Product reason 改成 Diagnosis result、
diagnosis_unavailable 或 batch error。测试必须验证父级不会缩短 child watchdog、健康长
调用可继续完成,以及 Product code 原样透传。
24. Active Source App Boundary Freeze
Diagnosis substrate 只能解释 app 通过 catalog、schema、observed signals 和 evidence 合同声明的业务事实,不能在 active Python 中拥有 WQ-YI 的 Evaluate、Dataset、 Pyramid 或 Alpha 质量词汇。以下词属于 app contract,不属于底座 ontology:
quality_wave_learning_facts
evaluate_diagnosis_context
qualified_count
alpha_quality
dataset_l1
dataset_l2
skeleton_preflight_facts
all_relevant_pyramids_*
2026-08-01 的 Diagnosis 现存债务冻结如下;这是迁移清单,不是允许继续扩展的 设计:
| active file | frozen occurrences | 迁移方向 |
|---|---|---|
engines/diagnosis/context.py | 0 | app predicate、quality 解释和 dataset scope 已迁入 app diagnosis assets;context.py 只执行通用 path + operator + value 规则 |
quality_wave_learning_facts、cross-wave candidate 特判、retry 正则、Evaluate
scope、simulation/qualified/slot/pyramid/L2 predicates、alpha-quality 文本猜测和
diagnosis_focus 已于 2026-08-01 从 Diagnosis active code/schema 移除,边界基线
为 0。通用 Diagnosis schema 外置、候选编译、持久化和 trial 边界保持不变。
边界冻结规则:
- active
src/nexrur/**/*.py|yml|yaml按大小写不敏感扫描,不得增加上述词的 新文件或新次数; _archived不参与 active 边界扫描;- 删除现存命中允许直接通过,不要求维持旧计数;
- 已归零的词继续保持 0;其余命中后续以 app contract 替代并逐项降低基线;
- 边界测试只检查源码归属,不判断运行结果,也不得成为新的业务 gate。