Potpie Context Graph 写入路径深度解析:语义变更、Propose/Commit 双阶段门、收件箱与质量检查
2026/9/17 22:44:35 网站建设 项目流程

Potpie Context Graph 写入路径深度解析:语义变更、Propose/Commit 双阶段门、收件箱与质量检查

【免费下载链接】potpieContext Graph for AI Native SDLC项目地址: https://gitcode.com/GitHub_Trending/po/potpie

本文基于 Potpie 仓库官方文档 writing.md 展开,系统讲解事实(facts)如何写入 Context Graph:从 Agent 发出的扁平语义 DSL(10 个 op)、验证与风险分级、lowering 降级为结构变更,到 canonical 的graph proposegraph commit --verify两阶段写入门、record 桥接的即时 mutate 路径、单后台写入门apply_mutation_batch、预应用软降级、收件箱(inbox)与质量评分。读完本篇,你可以直接编写可运行的 mutation JSON、理解每个写入层级的源码实现位置,并掌握 Potpie 写入纪律(write discipline)的完整闭环。

1. 定位与两条前提规则

文档首先声明了自己的职责边界:本篇只讲"写入路径"(write path)。读路径见 querying.md,静态契约(实体、谓词、truth classes、ops)见 ontology.md,完整命令/参数面见 cli-flow.md。文档状态注记:内容反映main@8dd175bc(2026-06-29 复核)。

在展开前,文档给出两条必须牢记的"框定规则":

  1. potpie graph …工作台(workbench)今天就是 V1.5。常量GRAPH_CONTRACT_VERSION="v1.5"ONTOLOGY_VERSION="2026-06-graph";workbench envelope 中的graph_contract_version="v2"只是传输层版本字符串。不存在所谓"未来 Graph V2 写入面"——propose/commit 是当下可用的真实能力。
  2. canonical 写入门是graph proposegraph commit --verifygraph mutate只是遗留包装器(legacy wrapper),内部实际调用 propose+commit;而真正的即时应用路径(DefaultGraphService.mutate)如今只能通过record/context_record桥接到达。

2. 分层写入栈(the tiered write stack)

无论是 harness skill、record桥接,还是(默认关闭的)服务端 reconciliation agent 发起的写入,都汇入同一套分层栈。核心设计原则:Agent 只发出语义(semantic)操作;Cypher 与结构化 edge/entity DTO 是内部表示,Agent 永远不直接编写

文档给出的分层流程(mermaid)如下:

分层职责表(文档原表,模块名以文档分层命名为准):

层级模块职责
Semantic DSLdomain/semantic_mutations.py将扁平 JSON ops 解析为 frozen DTO
Validation + riskapplication/services/semantic_mutation_validator.py纯领域校验;每 op 的MutationRisk;批量决策
Loweringapplication/services/semantic_mutation_lowering.py被接受的 ops →MutationBatch+ provenance;为 claim 属性盖章
Spine A(canonical)application/services/graph_workbench.pypropose → 持久化 plan → commit(--verify)
Spine B(即时)application/services/graph_service.pymutate()— 验证→降级→立即应用(仅 record 桥接)
Pre-apply gateapplication/services/reconciliation_validation.py上限(caps)、规范化、软失败降级
Write dooradapters/outbound/graph/apply_plan.pyapply_mutation_batch— 4 个动词、幂等指纹

补充:文档中的分层模块名是"概念路径"。在当前仓库源码中,对应实现的实际文件位于potpie/context-engine/src/potpie_context_engine/下——例如语义 DTO 解析在 semantic_mutations.py,校验器在 semantic_mutation_validator.py(validate_semantic_request定义于 L91),lowering 在 semantic_mutation_lowering.py(lower_semantic_request定义于 L70),workbench 服务在 workbench_service.py,即时 mutate 在 graph_service.py,写入门在 apply_plan.py。

3. 语义 DSL:扁平操作(flat ops)

Agent 发出的是批量形(batch-shaped)载荷——永远不是 Cypher,也永远不是EntityUpsert

{ "pot_id": "<pot-id>", "operations": [ { "op": "...", ... }, ... ] }

SemanticMutationRequest.parse/SemanticMutation.parse(semantic_mutations.py)将其转为 frozen DTO。单 op 别名{ "op": "...", ... }(也接受"operation"字段名)会在解析时归一化为单元素 batch。CLI 的--pot会覆盖任何内置的pot_id。结构性解析失败抛出SemanticMutationParseError——注意这只是形状(shape)错误;本体/权限(ontology/authority)检查发生在下一层。

3.1 十个操作,全部 APPLICABLE

SemanticMutationOp(graph_contract.py,L122-L139)精确定义了 10 个 op,且APPLICABLE_MUTATION_OPS就是全部十个(L143-L154)。不存在reconcile_snapshot这个 op——该名称是虚构的,它只作为陈旧注释残留在domain/reconciliation.py对应实现中。

Op用途降级(lowers to)
upsert_entity稳定实体元数据(name/summary/description/properties)EntityUpsert
link_entities权威的类型化关系EdgeUpsert
assert_claim有证据支撑的推断(默认 Agent 写入方式)EdgeUpsert(value → 合成Observation
append_event时间线活动(PR/commit/deploy/incident)Activity锚点 + PERFORMED/TOUCHED/MENTIONS 边
end_relation_validityvalid_until软终止一个关系InvalidationOp
retract_claim使一个 claim 失效(需要reasonInvalidationOp
supersede_claim替换 claim 并保留历史替换EdgeUpsert+InvalidationOp(superseded_by_key)
merge_duplicate_entities身份清理合并 props + 一条RELATED_TO合并记录边
patch_entity小属性更新(字段白名单)仅实体的EntityUpsert
transition_state生命周期字段变更(状态机)lifecycle props + 铸造的ActivityMENTIONS 边

关键澄清:op 集合没有为 review 预留分区。源码中REVIEW_REQUIRED_OPSDEFERRED_OPS都是空元组(graph_contract.py L159、L163,注释明确说明"高风险 V2 修正工作流通过 plan store 与显式审批可达,因此该分区在加入'已知但不可降级'的 op 之前保持为空")。review/阻塞是运行时MutationRisk(low/medium/high)决定的(见 §4),而不是由你选用的 op 决定。旧文档中把supersede_claimmerge_duplicate_entities称为"通常需要 review"的说法是错误的:它们在提供--allow-review-required--approved-by时会自动应用,否则因为运行时风险而返回review_required

3.2 Op 字段是扁平的(FLAT)

所有字段都是operation 顶层字段——不存在嵌套的{"event":{…}}{"claim":{…}}{"field"/"from"/"to"}包装。旧graphv2.md示例中的嵌套形状无法通过解析

扁平字段全集:opsubjectpredicateobjectvaluetruthconfidenceevidence[]descriptionenvironmentvalid_fromvalid_untilobserved_atreasonsuperseded_bypatchexpected_entity_versionfrom_stateto_stateexternal_idsappend_event额外增加verboccurred_atactortargets[]mentions[]subjectobject可以是裸 key 字符串,也可以是携带key/type/name/summary/description/properties的对象(即单条 op 可以同时铸造端点实体并断言关于它的事实)。

一个真实的 bug→fix 提案(与graph mutation-template --kind bug-fix匹配):

{ "pot_id": "<pot-id>", "idempotency_key": "bug-fix:<bug-slug>:<fix-hash>", "created_by": { "surface": "cli", "harness": "claude" }, "operations": [ { "op": "assert_claim", "subject": { "key": "bug_pattern:<bug-slug>", "type": "BugPattern", "summary": "<one-line symptom>", "description": "<retrieval card: error text, symptoms, synonyms, where it shows up>" }, "predicate": "REPRODUCES", "object": { "key": "service:<service-slug>", "type": "Service" }, "truth": "agent_claim", "confidence": 0.8, "description": "<how the bug manifests>" }, { "op": "assert_claim", "subject": { "key": "fix:<fix-hash>", "type": "Fix", "summary": "<one-line fix>" }, "predicate": "RESOLVED", "object": { "key": "bug_pattern:<bug-slug>", "type": "BugPattern" }, "truth": "agent_claim", "confidence": 0.8, "description": "<retrieval card: what fixed it, files touched, verification>" } ] }

一条时间线事件(append_event,注意扁平的 verb/occurred_at/actor/targets):

{ "pot_id": "<pot-id>", "operations": [ { "op": "append_event", "verb": "merged_pr", "occurred_at": "2026-06-05T01:35:00+05:30", "description": "<what changed, source title, regression keywords — written for timeline recall>", "actor": { "key": "person:<handle>", "type": "Person" }, "targets": [ { "key": "service:<service-slug>", "type": "Service" } ], "mentions": [ { "key": "feature:<feature-slug>", "type": "Feature" } ], "evidence": [ { "source_ref": "github:pr:acme/payments:812", "authority": "external_system" } ] } ] }

graph mutation-template --kind <repo-baseline|feature|preference|preference-policy|infra-snapshot|bug-fix|decision|timeline-event|timeline-change>只打印纯 schema 骨架(只有占位符——它从不读取仓库、也不推断事实)。

内部的结构性层级(domain/graph_mutations.pyEntityUpsertEdgeUpsertEdgeDeleteInvalidationOp+ProvenanceRef/ProvenanceContext)是这些扁平 op **降级到(lower into)**的目标;Agent 永远不直接编写它们。这些结构组合成一个MutationBatch(即ReconciliationPlan,定义于domain/reconciliation.py)。

4. 验证与风险分级(Validation + Risk)

validate_semantic_request(request) -> SemanticMutationPlan(semantic_mutation_validator.py L91)是纯领域代码——它只读取本体/契约,从不接触任何 backend。逐 op 检查包括:

  • op 是否已知;(一个存在但已死deferred分支——因为DEFERRED_OPS为空);
  • truth class 是否合法;confidence ∈ [0,1];时间戳为 ISO-8601;evidence authority 合法;
  • 逐 op 结构规则:claim 端点经edge_spec.allows校验;append_event需要Activity锚点 + PERFORMED/TOUCHED/MENTIONS 端点;retract/supersede 需要目标身份;patch_entity强制字段白名单(拒绝 state 字段)并要求检索级 description;transition_state校验生命周期状态机;merge 要求 key 互异、同类型且提供external_ids

"有证据或低权限"(evidence-or-low-authority)规则:只有authoritative_factsource_observation类 claim 必须携带 evidence;agent_claim/quality_finding被明确定义为软事实(soft),无需 evidence。缺少description只是警告,从不拒绝——但由于召回(recall)依赖 Agent 撰写的检索卡片(retrieval card),skills 将其视为强制项。

每个 op 变成一个LoweredOperation,带状态(accepted | review_required | deferred | rejected)与MutationRisk(low/medium/high,见 graph_contract.py L177-L180)。批量级决策函数_decide(semantic_mutation_validator.py L786-L806):

  • 任一 error → 整批rejected
  • 任一 review op →review_required
  • medium/high 风险的已接受 op仅当allow_review_required AND approved_by同时满足才自动应用,否则review_required

原子批语义(Atomic batch semantics):只要任一op 不能自动应用,整批就是review_required,且什么都不写入。子图路由(_subgraph_for/subgraph_for_predicate)把每个谓词映射到其命名切片。(由于 op 分区为空,validator 的review_required/deferredop 分支目前是死代码——review 永远由上述运行时风险决定。)

5. Lowering:从语义到结构

lower_semantic_request(request, plan)(semantic_mutation_lowering.py L70)只降级被接受的 ops,写入plan.batch+plan.provenance。要点:

  • claim 发出EdgeUpsertvalue字面量会铸造一个携带该字面量的合成Observation——体现"绝不从原始文本产生权威事实"的原则;
  • append_event锚定一个Activity并发出 PERFORMED/TOUCHED/MENTIONS 边;
  • retract_claim/end_relation_validityInvalidationOpsupersede_claim写入替换 claim并且一条盖有superseded_by_key戳的 invalidation;
  • merge_duplicate_entities盖合并 props + 一条RELATED_TO合并记录边;patch_entity仅实体;transition_state盖 lifecycle props 并铸造 Activity MENTIONS 边。

_claim_properties每条边盖上完整 V1.5 claim 元数据:claim_keysubgraphtruthevidence_strengthconfidencefactdescriptionsource_refs/evidencevalid_at/valid_fromobserved_atcreated_by、contract/ontology 版本、idempotency_keyidentity_key元组、environmentcode_scope及结构化字段。实体按 key 去重(_ensure_entity);summary 只从撰写材料派生(compact_entity_summary),因此对实体的裸重引用(bare re-reference)永远不会覆盖已存储的 summary。

6. Spine A —— propose → commit(canonical 写入门)

GraphWorkbenchService(workbench_service.py)实现两阶段门。

propose(payload, pot_id, ttl)—— 快照current_versions,计算expected_versions,检测版本冲突,然后 parse → validate →(非 invalid/conflict 时)lower → 构建GraphMutationDiff+claim_keys,并持久化一条GraphMutationPlanRecord(其降级后的 batch、provenance、expected/current versions、TTL 过期时间、warnings、被拒 ops)。状态为validated | invalid | conflict | review_required之一。返回GraphMutationProposal此阶段不发生任何图写入。

commit(plan_id, pot_id, approved_by, verify)—— 按 id 加载;未找到/终态/已过期则拒绝;重新检查版本冲突;强制审批(medium/high 风险需要--approved-by);随后调用backend.mutation.apply(record.lowered_batch, …)。Agent不需要重发 mutation——commit 重放服务端已持久化的 plan。成功后持久化committed状态、mutation_id与最终版本,并发出history_pointer+audit_ref

--verify执行_verify_ingestion_commit:通过claim_query.find_claims读回已提交的claim_keys(标记missing_claim_keys),取提交前后质量快照,并在读回缺失、backend 不可用或质量回退时把结果降级degraded/partial/watch。Skills 总是带--verify提交。

6.1 Plan 状态机

GraphMutationPlanStatusdomain/graph_plans.py):validatedinvalidconflictreview_requiredapprovedcommittedexpiredabandonederrorTERMINAL_PLAN_STATUSES阻止重复提交。Plan 持久化在adapters/outbound/graph/plan_stores/local_json.py(即~/.potpie/graph_plans.json,原子 tmp-replace,按 pot → plan_id 键控;仓库对应目录 plan_stores)。

6.2 乐观并发是"粗粒度"的

_subgraph_versions()只返回{"_global": <pot 的 claim 总数>}——没有per-subgraph 版本(尽管旧affected_subgraphs.{features,bugs,…}示例暗示过)。冲突只在 propose 与 commit 之间 pot 的claim 数发生变化时触发。冲突结果携带expected_version/actual_version和"重读并重新 propose"的建议。

Roadmap(尚未接入):真正的 per-subgraph 版本跟踪。目前并发是单一全局计数器,因此同一 pot 上互不相关的并发写入可能产生虚假冲突(spurious conflict)。

6.3 Diff 形状

GraphMutationDiff.to_dict()恰好输出这些键(不再是旧的entities_created/…):

entity_upserts · edge_upserts · edge_deletes · invalidations · claims_asserted · claims_retracted · claim_keys

6.4 Bulk

graph bulk apply把 NDJSON/JSON 流中的 plan(--chunk-size--start-chunk--continue-on-error--manifest--idempotency-key--verify)分块地走同一套 propose+commit 机制,用于大批量基线/摄入写入。完整参数见 cli-flow.md。

7. Spine B —— 直接 mutate(仅 record 桥接)

DefaultGraphService.mutate(request)(graph_service.py):validate →(提前 reject)→ lower → 若dry_run返回预览计数 → 若review_required则不写入直接返回 → 否则backend.mutation.apply(plan.batch, …)立即执行。没有 plan 持久化、没有 TTL、没有版本冲突保护。返回SemanticMutationResultapplied | validated | rejected | review_required | error)。

今天能到达 Spine B 的路径只有两条

  • record桥接application/services/record_to_semantic.py);
  • ingestion_submission_servicecontext_record确定性路径)。

record_to_semantic把每种record_type映射到固定的语义 op:preference/policy →assert_claim POLICY_APPLIES_TO(truth=preference,decisions子图);bug_pattern/fix → REPRODUCES + RESOLVED/ATTEMPTED_FIX_FAILED(debugging子图);verification → VERIFIED;decision → DECIDED(+AFFECTS,truth=user_decision);未知类型 → 自由RELATED_TO。它设置allow_review_required=True, approved_by="context_record",因此一次刻意的 record 写入(含 medium 风险的 decision)会自动应用;它从不生成 supersede/merge。该桥接由potpie record兼容命令暴露。

graph mutate是遗留包装器,不是 Spine B。CLI 的graph mutatecommands/graph.py)内部调用 workbench 的propose → commit,并发出遗留警告引导你转向 propose/commit。因此DefaultGraphService.mutate能经record/context_record到达,永远不会经graph mutate到达。

8. 单后台写入门(the single backend write door)

所有 apply——来自两条 spine——都汇聚到apply_mutation_batch(apply_plan.py L103,别名apply_reconciliation_plan)。同步的GraphMutationPort.apply(...)在每个 backend 内通过 loop-aware 的asyncio.run桥接到这个 async 函数。它依次:

  1. 运行validate_reconciliation_plan(预应用门,§9);
  2. 铸造每次 apply 的mutation_id(uuid4);
  3. 构建ProvenanceRef——对无事件的 batch,它使用ProvenanceContext.source_event_id整个 batch 的 stable blake2b 内容指纹_stable_batch_source_id,apply_plan.py L38),从不使用 per-apply uuid——因此重试保持幂等、不会铸造重复边;
  4. GraphWriterPort上按顺序运行四个动词upsert_entities → upsert_edges → delete_edges → invalidate
  5. 返回MutationResult(ok、mutation_id、summary 计数、降级记录)。

其下是Position-B canonical writer,由 Neo4j 与 FalkorDB 两个 writer 共享(cypher.py):claim 的形状是(:Entity {group_id, entity_key})-[:RELATES_TO {name, source_ref, valid_at, invalid_at, …}]->(:Entity)。MERGE 键包含source_ref,使来自不同来源的佐证写入互不冲突;双时间戳(bitemporal)把事件时间(valid_at/invalid_at)与系统时间(created_at)分开;_supersede_singleton_predecessors对先前的、不同意的 live singleton claim 盖invalid_atOWNED_BY是唯一 singleton)。backend 覆盖与GraphWriterPort形状详见 architecture.md。

9. 预应用验证与软失败降级(soft-fail downgrade)

validate_reconciliation_plan(batch, expected_pot_id)application/services/reconciliation_validation.py)是 writer 之前最后一道门:

  • 规范化 plan;执行硬上限(5000 实体 / 10000 边 / 2000 invalidations、重复 key 检测、ISO 时间检查);
  • 可选的 canonical-label 富化;回填必需属性。

设置CONTEXT_ENGINE_ONTOLOGY_SOFT_FAIL=1(且非 strict 模式)时,它降级而非失败:丢弃未知 label、ADR 回退 → Document/Observation、把无效 lifecycle 强转unknown、用now()回填缺失的边时间锚点、把未知边类型改写为RELATED_TO(confidence 0.3)、丢弃端点不匹配的边。每次降级都被记录,并可附加一个QualityIssue节点。最终validate_structural_mutations+ invalidation 检查在 plan 仍然无效时抛出MutationBatchValidationError(结构化问题)。无 provenance 的实质 plan 会获得一条非阻塞的 evidence 警告。

这是每次写入的结构完整性检查,区别于 §10 的导入期本体一致性守卫。

10. 一致性不变量(Coherence invariants)

domain/coherence.py(仓库实现:coherence.py)保持统一本体词汇表对齐,确保写入 DSL 永远不偏离它降级所依据的目录(catalogs)。_run_import_time_checks()模块加载时运行并快速失败启动:identity labels ⊆ENTITY_TYPES;每个RECORD_TYPESanchor_labelENTITY_TYPES;每个emits_predicateEDGE_TYPES;每个reader_include均已声明;STRUCTURAL_INCLUDES与 record includes 不相交;每个payload_schema都有 builder。assert_runtime_coherence(reader_backed_includes)(bootstrap 在 readers 就绪后调用)断言 live reader 注册表等于声明的READER_BACKED_INCLUDES,且 event-playbook 文案只使用规范 label/predicate。失败抛出OntologyCoherenceError——规则是"对齐声明,而不是放宽检查"。这是本体词汇表层面的一致性;目录本身归 ontology.md 所有。

11. 收件箱(Inbox)

Inbox 条目是待处理的图工作,故意在 harness 处理之前(读/搜索 → propose → commit)永不成为事实。实现:domain/graph_inbox.py+adapters/outbound/graph/inbox_stores/local_json.py(仓库目录:inbox_stores);方法挂在GraphWorkbenchService上(inbox_add/list/show/claim/mark_applied/mark_rejected/close)。状态流转:pending → claimed → applied/rejected/closedTERMINAL_INBOX_STATUSES)。mark_applied要求关联plan_idmutation_id。持久化在~/.potpie/graph_inbox.json,按 pot 键控。inbox store 端口是可选的——未接入时抛出CapabilityNotImplemented

CLI:graph inbox add | list | show <id> | claim <id> | mark-applied <id> [--plan|--mutation] | mark-rejected <id> [--reason] | close <id>

12. 质量评分(仅诊断,绝不写入)

质量从不写入——它只呈现发现(findings)并建议用 propose/commit 修正或转为 inbox 条目。两层:

  1. Resolve 期assess_graph_quality(refs, coverage, fallbacks)domain/graph_quality.py,仓库实现 graph_quality.py)→ 基于 source-reference 新鲜度(TTL 来自本体 fact 家族)、验证缺口、源访问缺口与覆盖率的GraphQualityReportgood/watch/degraded/unknown)。detect_family_conflicts按 predicate 家族 + subject 找出相互矛盾的 liveRELATES_TO边,并分类为 contradiction / supersession_pending / overlap(这喂给 auto-supersede 与冲突发现)。
  2. Workbench 只读GraphWorkbenchService.quality(report=…)通过backend.claim_query扫描ClaimRow,为summary | duplicate-candidates | stale-facts | conflicting-claims | orphan-entities | low-confidence | projection-drift发出GraphQualityFinding(状态 ok/watch/degraded)。同一份 summary 快照驱动commit --verify的回退检测(§6)。

CLI:graph quality <summary|duplicate-candidates|stale-facts|conflicting-claims|orphan-entities|low-confidence|projection-drift> [--threshold 0.5] [--subgraph] [--limit]

13. 写入命令总览与 canonical 循环

完整参数见 cli-flow.md;写入循环的纪律由potpie-graphskill 教授(见 skills.md)。

命令Spine / 角色
graph propose --file mutation.json [--ttl 1h]Spine A — 验证并持久化 plan(不写入)
graph commit <plan_id> --verify [--approved-by]Spine A — 应用持久化 plan,读回验证
graph bulk apply --file <ndjson> [--chunk-size] [--verify]Spine A — 分块多 plan 应用
graph mutate --file … [--dry-run] [--allow-review-required] [--approved-by]遗留包装器(内部 propose+commit)
graph mutation-template --kind <…>静态纯 schema 骨架(无 host 调用)
record --type … --summary …Spine B — record→semantic 桥接
graph history [--entity\|--claim\|--plan\|--mutation\|--subgraph]已提交写入的审计轨迹
graph inbox …/graph quality …待处理工作 / 诊断(§11–12)

Canonical 写入循环:发现契约(graph catalog)→ 读(graph read)→ 解析身份(graph search-entities)→graph proposegraph commit --verify→ 记录不确定性(graph inbox add)→ 检查graph quality

相关文档

  • ontology.md — 实体、谓词、truth classes、10 个 op、identity keys。
  • querying.md — 读主干与 AgentEnvelope。
  • cli-flow.md — 完整命令/参数面。
  • ingestion-nudge.md — 原始 episode/事件如何进入;nudge 模型。
  • architecture.md — backends、GraphWriterPort、共享引擎室。
  • skills.md — harness 教授的 propose/commit 写入纪律。

【免费下载链接】potpieContext Graph for AI Native SDLC项目地址: https://gitcode.com/GitHub_Trending/po/potpie

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询