
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 发出的扁平语义 DSL10 个 op、验证与风险分级、lowering 降级为结构变更到 canonical 的graph propose→graph 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。文档状态注记内容反映main8dd175bc2026-06-29 复核。在展开前文档给出两条必须牢记的框定规则potpie graph …工作台workbench今天就是 V1.5。常量GRAPH_CONTRACT_VERSIONv1.5、ONTOLOGY_VERSION2026-06-graphworkbench envelope 中的graph_contract_versionv2只是传输层版本字符串。不存在所谓未来 Graph V2 写入面——propose/commit 是当下可用的真实能力。canonical 写入门是graph propose→graph commit --verify。graph mutate只是遗留包装器legacy wrapper内部实际调用 proposecommit而真正的即时应用路径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 DTOValidation riskapplication/services/semantic_mutation_validator.py纯领域校验每 op 的MutationRisk批量决策Loweringapplication/services/semantic_mutation_lowering.py被接受的 ops →MutationBatch provenance为 claim 属性盖章Spine Acanonicalapplication/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.pyvalidate_semantic_request定义于 L91lowering 在 semantic_mutation_lowering.pylower_semantic_request定义于 L70workbench 服务在 workbench_service.py即时 mutate 在 graph_service.py写入门在 apply_plan.py。3. 语义 DSL扁平操作flat opsAgent 发出的是批量形batch-shaped载荷——永远不是 Cypher也永远不是EntityUpsert{ pot_id: pot-id, operations: [ { op: ..., ... }, ... ] }SemanticMutationRequest.parse/SemanticMutation.parsesemantic_mutations.py将其转为 frozen DTO。单 op 别名{ op: ..., ... }也接受operation字段名会在解析时归一化为单元素 batch。CLI 的--pot会覆盖任何内置的pot_id。结构性解析失败抛出SemanticMutationParseError——注意这只是形状shape错误本体/权限ontology/authority检查发生在下一层。3.1 十个操作全部 APPLICABLESemanticMutationOpgraph_contract.pyL122-L139精确定义了 10 个 op且APPLICABLE_MUTATION_OPS就是全部十个L143-L154。不存在reconcile_snapshot这个 op——该名称是虚构的它只作为陈旧注释残留在domain/reconciliation.py对应实现中。Op用途降级lowers toupsert_entity稳定实体元数据name/summary/description/properties仅EntityUpsertlink_entities权威的类型化关系EdgeUpsertassert_claim有证据支撑的推断默认 Agent 写入方式EdgeUpsertvalue → 合成Observationappend_event时间线活动PR/commit/deploy/incidentActivity锚点 PERFORMED/TOUCHED/MENTIONS 边end_relation_validity带valid_until软终止一个关系InvalidationOpretract_claim使一个 claim 失效需要reasonInvalidationOpsupersede_claim替换 claim 并保留历史替换EdgeUpsertInvalidationOp(superseded_by_key)merge_duplicate_entities身份清理合并 props 一条RELATED_TO合并记录边patch_entity小属性更新字段白名单仅实体的EntityUpserttransition_state生命周期字段变更状态机lifecycle props 铸造的ActivityMENTIONS 边关键澄清op 集合没有为 review 预留分区。源码中REVIEW_REQUIRED_OPS与DEFERRED_OPS都是空元组graph_contract.py L159、L163注释明确说明高风险 V2 修正工作流通过 plan store 与显式审批可达因此该分区在加入已知但不可降级的 op 之前保持为空。review/阻塞是运行时由MutationRisklow/medium/high决定的见 §4而不是由你选用的 op 决定。旧文档中把supersede_claim或merge_duplicate_entities称为通常需要 review的说法是错误的它们在提供--allow-review-required与--approved-by时会自动应用否则因为运行时风险而返回review_required。3.2 Op 字段是扁平的FLAT所有字段都是operation 顶层字段——不存在嵌套的{event:{…}}、{claim:{…}}或{field/from/to}包装。旧graphv2.md示例中的嵌套形状无法通过解析。扁平字段全集op、subject、predicate、object、value、truth、confidence、evidence[]、description、environment、valid_from、valid_until、observed_at、reason、superseded_by、patch、expected_entity_version、from_state、to_state、external_ids。append_event额外增加verb、occurred_at、actor、targets[]、mentions[]。subject与object可以是裸 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:0005: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.pyEntityUpsert、EdgeUpsert、EdgeDelete、InvalidationOpProvenanceRef/ProvenanceContext是这些扁平 op **降级到lower into**的目标Agent 永远不直接编写它们。这些结构组合成一个MutationBatch即ReconciliationPlan定义于domain/reconciliation.py。4. 验证与风险分级Validation Riskvalidate_semantic_request(request) - SemanticMutationPlansemantic_mutation_validator.py L91是纯领域代码——它只读取本体/契约从不接触任何 backend。逐 op 检查包括op 是否已知一个存在但已死的deferred分支——因为DEFERRED_OPS为空truth class 是否合法confidence ∈ [0,1]时间戳为 ISO-8601evidence authority 合法逐 op 结构规则claim 端点经edge_spec.allows校验append_event需要Activity锚点 PERFORMED/TOUCHED/MENTIONS 端点retract/supersede 需要目标身份patch_entity强制字段白名单拒绝 state 字段并要求检索级 descriptiontransition_state校验生命周期状态机merge 要求 key 互异、同类型且提供external_ids。有证据或低权限evidence-or-low-authority规则只有authoritative_fact与source_observation类 claim 必须携带 evidenceagent_claim/quality_finding被明确定义为软事实soft无需 evidence。缺少description只是警告从不拒绝——但由于召回recall依赖 Agent 撰写的检索卡片retrieval cardskills 将其视为强制项。每个 op 变成一个LoweredOperation带状态accepted | review_required | deferred | rejected与MutationRisklow/medium/high见 graph_contract.py L177-L180。批量级决策函数_decidesemantic_mutation_validator.py L786-L806任一 error → 整批rejected任一 review op →review_requiredmedium/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.batchplan.provenance。要点claim 发出EdgeUpsertvalue字面量会铸造一个携带该字面量的合成Observation——体现绝不从原始文本产生权威事实的原则append_event锚定一个Activity并发出 PERFORMED/TOUCHED/MENTIONS 边retract_claim/end_relation_validity→InvalidationOpsupersede_claim写入替换 claim并且一条盖有superseded_by_key戳的 invalidationmerge_duplicate_entities盖合并 props 一条RELATED_TO合并记录边patch_entity仅实体transition_state盖 lifecycle props 并铸造 Activity MENTIONS 边。_claim_properties为每条边盖上完整 V1.5 claim 元数据claim_key、subgraph、truth、evidence_strength、confidence、fact、description、source_refs/evidence、valid_at/valid_from、observed_at、created_by、contract/ontology 版本、idempotency_key、identity_key元组、environment、code_scope及结构化字段。实体按 key 去重_ensure_entitysummary 只从撰写材料派生compact_entity_summary因此对实体的裸重引用bare re-reference永远不会覆盖已存储的 summary。6. Spine A —— propose → commitcanonical 写入门GraphWorkbenchServiceworkbench_service.py实现两阶段门。propose(payload, pot_id, ttl)—— 快照current_versions计算expected_versions检测版本冲突然后 parse → validate →非 invalid/conflict 时lower → 构建GraphMutationDiffclaim_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_pointeraudit_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.pyvalidated、invalid、conflict、review_required、approved、committed、expired、abandoned、error。TERMINAL_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_keys6.4 Bulkgraph bulk apply把 NDJSON/JSON 流中的 plan--chunk-size、--start-chunk、--continue-on-error、--manifest、--idempotency-key、--verify分块地走同一套 proposecommit 机制用于大批量基线/摄入写入。完整参数见 cli-flow.md。7. Spine B —— 直接 mutate仅 record 桥接DefaultGraphService.mutate(request)graph_service.pyvalidate →提前 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.pyingestion_submission_servicecontext_record确定性路径。record_to_semantic把每种record_type映射到固定的语义 oppreference/policy →assert_claim POLICY_APPLIES_TOtruthpreferencedecisions子图bug_pattern/fix → REPRODUCES RESOLVED/ATTEMPTED_FIX_FAILEDdebugging子图verification → VERIFIEDdecision → DECIDEDAFFECTStruthuser_decision未知类型 → 自由RELATED_TO。它设置allow_review_requiredTrue, approved_bycontext_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_batchapply_plan.py L103别名apply_reconciliation_plan。同步的GraphMutationPort.apply(...)在每个 backend 内通过 loop-aware 的asyncio.run桥接到这个 async 函数。它依次运行validate_reconciliation_plan预应用门§9铸造每次 apply 的mutation_iduuid4构建ProvenanceRef——对无事件的 batch它使用ProvenanceContext.source_event_id或整个 batch 的 stable blake2b 内容指纹_stable_batch_source_idapply_plan.py L38从不使用 per-apply uuid——因此重试保持幂等、不会铸造重复边在GraphWriterPort上按顺序运行四个动词upsert_entities → upsert_edges → delete_edges → invalidate返回MutationResultok、mutation_id、summary 计数、降级记录。其下是Position-B canonical writer由 Neo4j 与 FalkorDB 两个 writer 共享cypher.pyclaim 的形状是(: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 downgradevalidate_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_FAIL1且非 strict 模式时它降级而非失败丢弃未知 label、ADR 回退 → Document/Observation、把无效 lifecycle 强转unknown、用now()回填缺失的边时间锚点、把未知边类型改写为RELATED_TOconfidence 0.3、丢弃端点不匹配的边。每次降级都被记录并可附加一个QualityIssue节点。最终validate_structural_mutations invalidation 检查在 plan 仍然无效时抛出MutationBatchValidationError结构化问题。无 provenance 的实质 plan 会获得一条非阻塞的 evidence 警告。这是每次写入的结构完整性检查区别于 §10 的导入期本体一致性守卫。10. 一致性不变量Coherence invariantsdomain/coherence.py仓库实现coherence.py保持统一本体词汇表对齐确保写入 DSL 永远不偏离它降级所依据的目录catalogs。_run_import_time_checks()在模块加载时运行并快速失败启动identity labels ⊆ENTITY_TYPES每个RECORD_TYPES的anchor_label⊆ENTITY_TYPES每个emits_predicate⊆EDGE_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. 收件箱InboxInbox 条目是待处理的图工作故意在 harness 处理之前读/搜索 → propose → commit永不成为事实。实现domain/graph_inbox.pyadapters/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_id或mutation_id。持久化在~/.potpie/graph_inbox.json按 pot 键控。inbox store 端口是可选的——未接入时抛出CapabilityNotImplemented。CLIgraph inbox add | list | show id | claim id | mark-applied id [--plan|--mutation] | mark-rejected id [--reason] | close id。12. 质量评分仅诊断绝不写入质量从不写入——它只呈现发现findings并建议用 propose/commit 修正或转为 inbox 条目。两层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 与冲突发现。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。CLIgraph 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]遗留包装器内部 proposecommitgraph mutation-template --kind …静态纯 schema 骨架无 host 调用record --type … --summary …Spine B — record→semantic 桥接graph history [--entity\|--claim\|--plan\|--mutation\|--subgraph]已提交写入的审计轨迹graph inbox …/graph quality …待处理工作 / 诊断§11–12Canonical 写入循环发现契约graph catalog→ 读graph read→ 解析身份graph search-entities→graph propose→graph 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),仅供参考