decisions.py 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. # -*- coding: utf-8 -*-
  2. """P3-a 决策捕获: 人的裁决成为对象 (谁/何时/依据哪些对象/裁了什么), 事后结果回填.
  3. Palantir decision capture 的轻量版: 组织在自己的决策史上学习.
  4. 纪律: 只录**真实发生**的裁决 (用户原话/指令), 建议级未裁的标 pending_user, 禁把建议写成已批."""
  5. from src import paths as P
  6. import copy, json, pathlib
  7. from .store import Store
  8. ONT = P.ont()
  9. def capture(store, did, decided_by, when, decision, basis_ids=None, status='decided', note=''):
  10. """裁决入库; basis_ids = 依据的对象 (快照其当时关键态)."""
  11. snapshot = {}
  12. for b in (basis_ids or []):
  13. if b in store.objects:
  14. p = store.objects[b].get('props', {})
  15. snapshot[b] = {k: p[k] for k in ('level', 'status', 'name', 'review_tier') if k in p}
  16. store.put(dict(id=f'decision/{did}', type='Decision',
  17. props=dict(decided_by=decided_by, when=when, decision=decision,
  18. status=status, note=note, basis_snapshot=snapshot),
  19. links=dict(basedOn=list(basis_ids or []))))
  20. return f'decision/{did}'
  21. def close(store, decision_id, outcome, when):
  22. """事后结果回填 (决策闭环的另一半).
  23. F8: 走 force 通道 (回填=合法演进), when 由调用方显式传, 旧版本自动进 props.history."""
  24. o = copy.deepcopy(store.get(decision_id)) # 深拷贝: 就地改库内引用会让 F8 差异检测失效
  25. o['props']['outcome'] = outcome
  26. o['props']['outcome_when'] = when
  27. o['props']['status'] = 'closed'
  28. store.put(o, force=True, when=when)
  29. def seed_real_decisions():
  30. """录今天已真实发生的用户裁决 (原话为据); 排期沙盘=建议级挂 pending_user, 不冒充已批."""
  31. s = Store(ONT / 'objects.json')
  32. capture(s, 'user/20260827_ontology_six', '用户', '2026-08-27',
  33. '本体六问五裁: 天气窗=查公开记录 / Action边界=照可逆性三级 / 种子=29#全链 / '
  34. '离线分工=本体查询约束动作走结构化工具·qwen 30b-a3b 只做语义编排 / '
  35. '备件供给侧先不管·更换与备件成本找网上招标公开信息 (本体载体默认轻量自建)',
  36. basis_ids=['scenario/WTG29/repair_scheduling_v1'], note='原话见会话 2026-08-27/28')
  37. capture(s, 'user/20260828_phase_rollout', '用户', '2026-08-28',
  38. '阶段推进: windscada v3 整体规划批准执行 — P1 开跑(本体铺开) → P2 开跑(本体经MCP暴露给dsh) → P3 开(决策闭环+月度滚动)',
  39. note='三条独立指令合录; 每阶段验收判据见 docs/windscada_规划_v3.md')
  40. capture(s, 'pending/WTG29_repair_scenario_A', '待用户', '2026-08-28',
  41. '29# 修泵排期: 沙盘建议=情景A (2026-09 首个CTV窗), 建议级 L3 动作待人裁',
  42. basis_ids=['scenario/WTG29/repair_scheduling_v1', 'verdict/WTG29/TCM-16'],
  43. status='pending_user', note='禁把建议写成已批; 用户裁后 status→decided 并录原话')
  44. s.save()
  45. return s