@zh-xx/antu 0.11.0 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/assets/viewer.html +48 -49
  2. package/bin/antu-mcp.mjs +62 -63
  3. package/bin/antu.mjs +54 -55
  4. package/embed/antu-embed.d.ts +11 -0
  5. package/embed/antu-embed.js +28227 -28093
  6. package/examples/agent/fact/1-minimal.en.json +8 -11
  7. package/examples/agent/fact/1-minimal.zh-CN.json +34 -9
  8. package/examples/agent/fact/2-single-actor.en.json +4 -30
  9. package/examples/agent/fact/2-single-actor.zh-CN.json +22 -10
  10. package/examples/agent/fact/{3-groups.en.json → 3-sides.en.json} +9 -9
  11. package/examples/agent/fact/{3-groups.zh-CN.json → 3-sides.zh-CN.json} +9 -9
  12. package/examples/agent/fact/4-one-side-several.en.json +44 -0
  13. package/examples/agent/fact/4-one-side-several.zh-CN.json +44 -0
  14. package/examples/agent/fact/5-duration.en.json +31 -8
  15. package/examples/agent/fact/5-duration.zh-CN.json +31 -8
  16. package/examples/agent/fact/6-sources.en.json +51 -12
  17. package/examples/agent/fact/6-sources.zh-CN.json +51 -12
  18. package/examples/agent/fact/7-undated.en.json +26 -9
  19. package/examples/agent/fact/7-undated.zh-CN.json +26 -9
  20. package/examples/fact/fang-yuan-loan-and-conflict.en.json +7 -66
  21. package/examples/fact/fang-yuan-loan-and-conflict.zh-CN.json +6 -29
  22. package/examples/fact/gym-membership-face-scan.en.json +1 -6
  23. package/examples/fact/gym-membership-face-scan.zh-CN.json +1 -6
  24. package/examples/fact/lin-fang-v-zhao-lei-private-lending.en.json +6 -19
  25. package/examples/fact/lin-fang-v-zhao-lei-private-lending.zh-CN.json +6 -19
  26. package/examples/fact/marketplace-platform-liability.en.json +5 -24
  27. package/examples/fact/marketplace-platform-liability.zh-CN.json +5 -24
  28. package/examples/fact/neighbour-corridor-charging.en.json +3 -25
  29. package/examples/fact/neighbour-corridor-charging.zh-CN.json +3 -25
  30. package/examples/fact/sample-construction-payment.en.json +8 -82
  31. package/examples/fact/sample-construction-payment.zh-CN.json +7 -25
  32. package/examples/fact/sample-four-parties-four-slots.en.json +8 -81
  33. package/examples/fact/sample-four-parties-four-slots.zh-CN.json +5 -22
  34. package/examples/fact/sample-no-groups.en.json +1 -1
  35. package/examples/fact/sample-no-groups.zh-CN.json +1 -1
  36. package/examples/fact/sample-three-slots.en.json +3 -15
  37. package/examples/fact/sample-three-slots.zh-CN.json +3 -15
  38. package/examples/fact/sample-two-actors-one-side.en.json +4 -23
  39. package/examples/fact/sample-two-actors-one-side.zh-CN.json +4 -23
  40. package/examples/fact/sample-two-parties-each-side.en.json +7 -34
  41. package/examples/fact/sample-two-parties-each-side.zh-CN.json +7 -34
  42. package/lib/chunks/report-BTsYMUG2.mjs +1461 -0
  43. package/lib/html.mjs +5 -5
  44. package/lib/validate.d.ts +9 -0
  45. package/lib/validate.mjs +5 -5
  46. package/package.json +1 -1
  47. package/server.json +2 -2
  48. package/spec/agent/fact/guide.md +39 -38
  49. package/spec/agent/relationship/guide.md +26 -7
  50. package/examples/agent/fact/4-views.en.json +0 -44
  51. package/examples/agent/fact/4-views.zh-CN.json +0 -44
  52. package/lib/chunks/report-BV3j2cS_.mjs +0 -1462
package/lib/html.mjs CHANGED
@@ -1,4 +1,4 @@
1
- // Antu 0.11.0
1
+ // Antu 0.13.0
2
2
  // Copyright (C) 2026 Ji Cheng
3
3
  //
4
4
  // Antu is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public
@@ -12,9 +12,9 @@
12
12
  // publish them, or sell them on any terms you like. This licence covers Antu's code in the page, and the notices in
13
13
  // the page must stay with it.
14
14
  //
15
- // Corresponding Source of this version: https://github.com/zh-xx/Antu/tree/v0.11.0
16
- // The licence: https://github.com/zh-xx/Antu/blob/v0.11.0/LICENSE
17
- // Third-party notices: https://github.com/zh-xx/Antu/blob/v0.11.0/skills/antu/THIRD-PARTY-NOTICES.md
15
+ // Corresponding Source of this version: https://github.com/zh-xx/Antu/tree/v0.13.0
16
+ // The licence: https://github.com/zh-xx/Antu/blob/v0.13.0/LICENSE
17
+ // Third-party notices: https://github.com/zh-xx/Antu/blob/v0.13.0/skills/antu/THIRD-PARTY-NOTICES.md
18
18
  //
19
19
  // === The licence of Antu ===
20
20
  //
@@ -1422,4 +1422,4 @@
1422
1422
  // SOFTWARE.
1423
1423
  // ````
1424
1424
  //
1425
- import{a as e,n as t,o as n,s as r}from"./chunks/report-BV3j2cS_.mjs";import{readFileSync as i}from"node:fs";import{dirname as a,join as o,resolve as s}from"node:path";import{fileURLToPath as c}from"node:url";var l=`/*ANTU_SPEC*/null`;function u(e){return String(e).replace(/</g,`\\u003c`)}function d(e,t,{preset:n}={}){if(e.split(`/*ANTU_SPEC*/null`).length!==2)throw Error(`the viewer template does not hold exactly one ${l}`);let r=u(JSON.stringify(t)),i=n?`;window.__ANTU_PRESET__ = ${u(JSON.stringify(n))}`:``;return e.replace(l,()=>r+i)}s(a(c(import.meta.url)),`../..`);var f=s(a(c(import.meta.url)),`..`);o(f,`dist-engine/engine.js`),o(f,`dist-engine/engine.css`);function p(e){return String(e).replace(/[&<>"]/g,e=>({"&":`&amp;`,"<":`&lt;`,">":`&gt;`,'"':`&quot;`})[e])}function m(e,{preset:t,force:n=!1,quiet:r=!1}={}){{let n=p(e?.title||`Antu`);return d(i(o(f,`assets/viewer.html`),`utf8`),e,{preset:t}).replace(/<title>[^<]*<\/title>/,()=>`<title>${n} · Antu</title>`)}}var h=[`document`,`modern`,`legal`],g={equity:{width:r.normal},control:{width:r.heavy},contract:{width:r.normal,dash:n.longDash},debt:{width:r.strong,dash:n.dashDot},guarantee:{width:r.normal,dash:n.dashed},kinship:{width:3.6,double:!0},employment:{width:r.normal,dash:n.dotted},agency:{width:r.strong,dash:`1 4`,round:!0},other:{width:r.hair,dash:`3 3`}},_=(e,t)=>Object.fromEntries(Object.entries(e).map(([e,n])=>[e,{...n,stroke:t}])),v={neutral:{width:r.normal},positive:{width:r.strong},negative:{width:r.normal,dash:n.dashed}},y={main:{width:r.strong},plain:{width:r.normal},back:{width:r.normal,dash:n.dashed}},b={conclusion:{width:r.heavy},norm:{width:r.normal},element:{width:r.normal},fact:{width:r.hair},inference:{width:r.normal,dash:n.dotted},judgement:{width:r.strong}},x={for:{width:r.normal},against:{width:r.strong,dash:n.dashed},basis:{width:r.normal,dash:n.dotted}},S=(e,t)=>Object.fromEntries(Object.entries(e).map(([e,n])=>[e,{...n,...t[e]}])),C={document:{id:`document`,shadowRgb:`17, 17, 17`,chrome:{radius:2,capsule:2,chip:2,bg:`#ffffff`,bgPop:`#ffffff`,border:`1px solid #111111`,shadow:`none`,blur:`none`},labelKey:`theme.document`,font:{body:`"FangSong", "STFangsong", "FangSong_GB2312", "Songti SC", "SimSun", "Noto Serif CJK SC", "Source Han Serif SC", serif`,head:`"SimHei", "Heiti SC", "STHeiti", "Microsoft YaHei", "Noto Sans CJK SC", "Source Han Sans SC", sans-serif`},color:{ink:`#111111`,ink2:`#2b2b2b`,ink3:`#4d4d4d`,ink4:`#767676`,bg:`#ffffff`,canvas:`#ffffff`,frame:`#111111`,line:`#c9c9c9`,chip:`#f0f0f0`,side1:`#111111`,side2:`#555555`,axis:`#767676`},radius:{person:12,company:0,organization:0,government:0,other:0,pill:2,group:0},entity:{person:{stroke:`#111111`,fill:`#ffffff`,width:1},company:{stroke:`#111111`,fill:`#ffffff`,width:1.5},organization:{stroke:`#111111`,fill:`#ffffff`,width:1,dash:n.dashed},government:{stroke:`#111111`,fill:`#ffffff`,width:1},other:{stroke:`#555555`,fill:`#ffffff`,width:.9,dash:n.dotted}},relation:_(g,`#111111`),camp:[{fill:`#ffffff`,stroke:`#111111`,text:`#111111`},{fill:`#ececec`,stroke:`#111111`,text:`#111111`},{fill:`#f7f7f7`,stroke:`#8a8a8a`,text:`#4d4d4d`}],group:{fill:`#f5f5f5`,stroke:`#8a8a8a`,title:`#111111`},flow:{outcome:S(v,{neutral:{stroke:`#111111`,fill:`#ffffff`},positive:{stroke:`#111111`,fill:`#ffffff`},negative:{stroke:`#111111`,fill:`#ececec`}}),start:{stroke:`#111111`,fill:`#e2e2e2`},note:{stroke:`none`,fill:`#f5f5f5`,fold:`#767676`},stage:{fill:`#f5f5f5`,stroke:`#8a8a8a`,title:`#111111`},stageLit:{fill:`#e2e2e2`,stroke:`#111111`,title:`#111111`},link:S(y,{main:{stroke:`#111111`},plain:{stroke:`#2b2b2b`},back:{stroke:`#4d4d4d`}})},justify:{node:S(b,{conclusion:{stroke:`#111111`,fill:`#ffffff`},norm:{stroke:`#111111`,fill:`#ececec`},element:{stroke:`#111111`,fill:`#ffffff`},fact:{stroke:`#111111`,fill:`#ffffff`},inference:{stroke:`#111111`,fill:`#ffffff`},judgement:{stroke:`#111111`,fill:`#ececec`}}),stance:S(x,{for:{stroke:`#2b2b2b`},against:{stroke:`#111111`},basis:{stroke:`#4d4d4d`}})},pill:{colored:!1,border:`#111111`}},modern:{id:`modern`,shadowRgb:`15, 23, 42`,chrome:{radius:14,capsule:999,chip:999,bg:`rgba(255, 255, 255, 0.78)`,bgPop:`rgba(255, 255, 255, 0.94)`,border:`1px solid rgba(15, 23, 42, 0.07)`,shadow:`0 4px 18px rgba(15, 23, 42, 0.10), 0 1px 2px rgba(15, 23, 42, 0.06)`,blur:`blur(16px) saturate(1.8)`},labelKey:`theme.modern`,font:{body:`system-ui, "PingFang SC", "Microsoft YaHei UI", "Microsoft YaHei", "Noto Sans CJK SC", "Source Han Sans SC", sans-serif`,head:`system-ui, "PingFang SC", "Microsoft YaHei UI", "Microsoft YaHei", "Noto Sans CJK SC", "Source Han Sans SC", sans-serif`},color:{ink:`#0f172a`,ink2:`#475569`,ink3:`#64748b`,ink4:`#94a3b8`,bg:`#fbfcfd`,canvas:`#fbfcfd`,frame:`#e2e8f0`,line:`#e8ebef`,chip:`#f1f4f8`,side1:`#475569`,side2:`#64748b`,axis:`#94a3b8`},radius:{person:14,company:8,organization:8,government:6,other:8,pill:12,group:12},entity:{person:{stroke:`#94a3b8`,fill:`#f1f5f9`,width:1},company:{stroke:`#334155`,fill:`#ffffff`,width:1.25},organization:{stroke:`#94a3b8`,fill:`#ffffff`,width:1,dash:n.dashed},government:{stroke:`#64748b`,fill:`#f8fafc`,width:1},other:{stroke:`#94a3b8`,fill:`#f8fafc`,width:.9,dash:n.dotted}},relation:_(g,`#475569`),camp:[{fill:`#f1f5f9`,stroke:`#94a3b8`,text:`#334155`},{fill:`#ffffff`,stroke:`#94a3b8`,text:`#334155`},{fill:`#f8fafc`,stroke:`#e2e8f0`,text:`#64748b`}],group:{fill:`#f8fafc`,stroke:`#e2e8f0`,title:`#475569`},flow:{outcome:S(v,{neutral:{stroke:`#64748b`,fill:`#f8fafc`},positive:{stroke:`#334155`,fill:`#f1f5f9`},negative:{stroke:`#64748b`,fill:`#f1f5f9`}}),start:{stroke:`#334155`,fill:`#e2e8f0`},note:{stroke:`none`,fill:`#f1f5f9`,fold:`#94a3b8`},stage:{fill:`#f8fafc`,stroke:`#e2e8f0`,title:`#475569`},stageLit:{fill:`#f1f5f9`,stroke:`#64748b`,title:`#334155`},link:S(y,{main:{stroke:`#0f172a`},plain:{stroke:`#475569`},back:{stroke:`#64748b`}})},justify:{node:S(b,{conclusion:{stroke:`#0f172a`,fill:`#f1f5f9`},norm:{stroke:`#475569`,fill:`#e2e8f0`},element:{stroke:`#64748b`,fill:`#f8fafc`},fact:{stroke:`#94a3b8`,fill:`#ffffff`},inference:{stroke:`#64748b`,fill:`#f8fafc`},judgement:{stroke:`#334155`,fill:`#e2e8f0`}}),stance:S(x,{for:{stroke:`#475569`},against:{stroke:`#334155`},basis:{stroke:`#94a3b8`}})},pill:{colored:!1,border:`#cbd5e1`}},legal:{id:`legal`,shadowRgb:`19, 35, 63`,chrome:{radius:6,capsule:6,chip:4,bg:`#ffffff`,bgPop:`#ffffff`,border:`1px solid #c7d2e4`,shadow:`0 2px 10px rgba(19, 35, 63, 0.10)`,blur:`none`},labelKey:`theme.legal`,font:{body:`system-ui, "PingFang SC", "Microsoft YaHei UI", "Microsoft YaHei", "Noto Sans CJK SC", "Source Han Sans SC", sans-serif`,head:`system-ui, "PingFang SC", "Microsoft YaHei UI", "Microsoft YaHei", "Noto Sans CJK SC", "Source Han Sans SC", sans-serif`},color:{ink:`#13233f`,ink2:`#2d4366`,ink3:`#5b6f8f`,ink4:`#8aa0c4`,bg:`#ffffff`,canvas:`#ffffff`,frame:`#c7d2e4`,line:`#dbe3f0`,chip:`#eef3fb`,side1:`#1f3f7f`,side2:`#9a1b1b`,axis:`#8aa0c4`},radius:{person:14,company:3,organization:4,government:3,other:4,pill:4,group:6},entity:{person:{stroke:`#2f5aa8`,fill:`#eef3fb`,width:1},company:{stroke:`#1f3f7f`,fill:`#e3ecfa`,width:1.5},organization:{stroke:`#2f5aa8`,fill:`#f4f7fc`,width:1,dash:n.dashed},government:{stroke:`#13233f`,fill:`#eef3fb`,width:1.1},other:{stroke:`#8aa0c4`,fill:`#f8fafd`,width:.9,dash:n.dotted}},relation:{equity:{...g.equity,stroke:`#1f3f7f`},control:{...g.control,stroke:`#13233f`},contract:{...g.contract,stroke:`#5b6f8f`},debt:{...g.debt,stroke:`#9a1b1b`},guarantee:{...g.guarantee,stroke:`#2f5aa8`},kinship:{...g.kinship,stroke:`#4b3a8c`},employment:{...g.employment,stroke:`#1d6b6b`},agency:{...g.agency,stroke:`#1d6b6b`},other:{...g.other,stroke:`#8aa0c4`}},camp:[{fill:`#eaf0fb`,stroke:`#9fb6e0`,text:`#1f3f7f`},{fill:`#fbecec`,stroke:`#e3b4b4`,text:`#9a1b1b`},{fill:`#f4f7fc`,stroke:`#c7d2e4`,text:`#5b6f8f`}],group:{fill:`#f4f7fc`,stroke:`#c7d2e4`,title:`#2d4366`},flow:{outcome:S(v,{neutral:{stroke:`#2f5aa8`,fill:`#eef3fb`},positive:{stroke:`#1f3f7f`,fill:`#e3ecfa`},negative:{stroke:`#9a1b1b`,fill:`#fbecec`}}),start:{stroke:`#13233f`,fill:`#dbe5f5`},note:{stroke:`none`,fill:`#f4f7fc`,fold:`#8aa0c4`},stage:{fill:`#f4f7fc`,stroke:`#c7d2e4`,title:`#2d4366`},stageLit:{fill:`#eaf0fb`,stroke:`#1f3f7f`,title:`#1f3f7f`},link:S(y,{main:{stroke:`#13233f`},plain:{stroke:`#2d4366`},back:{stroke:`#5b6f8f`}})},justify:{node:S(b,{conclusion:{stroke:`#1f3f7f`,fill:`#e3ecfa`},norm:{stroke:`#4b3a8c`,fill:`#efecf8`},element:{stroke:`#2f5aa8`,fill:`#eef3fb`},fact:{stroke:`#8aa0c4`,fill:`#f8fafd`},inference:{stroke:`#1d6b6b`,fill:`#e8f4f4`},judgement:{stroke:`#13233f`,fill:`#dbe5f5`}}),stance:S(x,{for:{stroke:`#2d4366`},against:{stroke:`#9a1b1b`},basis:{stroke:`#4b3a8c`}})},pill:{colored:!0,border:`#c7d2e4`}}},w=e=>Object.prototype.hasOwnProperty.call(C,e);function T(n,{kind:r,theme:i}={}){let a=e(n);if(a.length)throw Object.assign(Error(`antu: the spec is not valid (${a.length} problem(s)): ${a[0]}`),{errors:[...a]});let o=t(n,r);if(o)throw Error(`antu: ${o}`);if(i!==void 0&&!w(i))throw Error(`antu: the theme is one of ${h.join(`, `)}`);return m(n,{preset:r||i?{...r&&{defaultKind:r},...i&&{theme:i}}:void 0,quiet:!0})}export{T as renderHtml};
1425
+ import{a as e,n as t,o as n,s as r}from"./chunks/report-BTsYMUG2.mjs";import{readFileSync as i}from"node:fs";import{dirname as a,join as o,resolve as s}from"node:path";import{fileURLToPath as c}from"node:url";var l=`/*ANTU_SPEC*/null`;function u(e){return String(e).replace(/</g,`\\u003c`)}function d(e,t,{preset:n}={}){if(e.split(`/*ANTU_SPEC*/null`).length!==2)throw Error(`the viewer template does not hold exactly one ${l}`);let r=u(JSON.stringify(t)),i=n?`;window.__ANTU_PRESET__ = ${u(JSON.stringify(n))}`:``;return e.replace(l,()=>r+i)}s(a(c(import.meta.url)),`../..`);var f=s(a(c(import.meta.url)),`..`);o(f,`dist-engine/engine.js`),o(f,`dist-engine/engine.css`);function p(e){return String(e).replace(/[&<>"]/g,e=>({"&":`&amp;`,"<":`&lt;`,">":`&gt;`,'"':`&quot;`})[e])}function m(e,{preset:t,force:n=!1,quiet:r=!1}={}){{let n=p(e?.title||`Antu`);return d(i(o(f,`assets/viewer.html`),`utf8`),e,{preset:t}).replace(/<title>[^<]*<\/title>/,()=>`<title>${n} · Antu</title>`)}}var h=[`document`,`modern`,`legal`],g={equity:{width:r.normal},control:{width:r.heavy},contract:{width:r.normal,dash:n.longDash},debt:{width:r.strong,dash:n.dashDot},guarantee:{width:r.normal,dash:n.dashed},kinship:{width:3.6,double:!0},employment:{width:r.normal,dash:n.dotted},agency:{width:r.strong,dash:`1 4`,round:!0},other:{width:r.hair,dash:`3 3`}},_={equity:{width:.85},control:{width:1.9},contract:{width:.85,dash:`5 3`},debt:{width:1.3,dash:`5 2 1.5 2`},guarantee:{width:.85,dash:`4 3`},kinship:{width:3.2,double:!0},employment:{width:.85,dash:n.dotted},agency:{width:1.3,dash:`1 4`,round:!0},other:{width:.6,dash:`3 3`}},v=(e,t)=>Object.fromEntries(Object.entries(e).map(([e,n])=>[e,{...n,stroke:t}])),y={neutral:{width:r.normal},positive:{width:r.strong},negative:{width:r.normal,dash:n.dashed}},b={main:{width:r.strong},plain:{width:r.normal},back:{width:r.normal,dash:n.dashed}},x={conclusion:{width:r.heavy},norm:{width:r.normal},element:{width:r.normal},fact:{width:r.hair},inference:{width:r.normal,dash:n.dotted},judgement:{width:r.strong}},S={for:{width:r.normal},against:{width:r.strong,dash:n.dashed},basis:{width:r.normal,dash:n.dotted}},C=(e,t)=>Object.fromEntries(Object.entries(e).map(([e,n])=>[e,{...n,...t[e]}])),w={document:{id:`document`,shadowRgb:`17, 17, 17`,chrome:{radius:2,capsule:2,chip:2,bg:`#ffffff`,bgPop:`#ffffff`,border:`1px solid #111111`,shadow:`none`,blur:`none`},labelKey:`theme.document`,font:{body:`"FangSong", "STFangsong", "FangSong_GB2312", "Songti SC", "SimSun", "Noto Serif CJK SC", "Source Han Serif SC", serif`,head:`"SimHei", "Heiti SC", "STHeiti", "Microsoft YaHei", "Noto Sans CJK SC", "Source Han Sans SC", sans-serif`},color:{ink:`#111111`,ink2:`#2b2b2b`,ink3:`#4d4d4d`,ink4:`#767676`,bg:`#ffffff`,canvas:`#ffffff`,frame:`#111111`,line:`#c9c9c9`,chip:`#f0f0f0`,side1:`#111111`,side2:`#555555`,axis:`#767676`},radius:{person:18,company:3,organization:3,government:3,other:3,pill:2,group:0},entity:{person:{stroke:`#111111`,fill:`#ffffff`,width:1.3},company:{stroke:`#111111`,fill:`#ffffff`,width:1.6},organization:{stroke:`#111111`,fill:`#ffffff`,width:1.3,dash:n.dashed},government:{stroke:`#111111`,fill:`#ffffff`,width:1.3},other:{stroke:`#555555`,fill:`#ffffff`,width:1.1,dash:n.dotted}},relation:v(_,`#767676`),camp:[{fill:`#ffffff`,stroke:`#111111`,text:`#111111`},{fill:`#ececec`,stroke:`#111111`,text:`#111111`},{fill:`#f7f7f7`,stroke:`#8a8a8a`,text:`#4d4d4d`}],group:{fill:`#f5f5f5`,stroke:`#8a8a8a`,title:`#111111`},campBox:{fill:`none`,stroke:`#111111`,width:.75,dash:`2 3`},flow:{outcome:C(y,{neutral:{stroke:`#111111`,fill:`#ffffff`},positive:{stroke:`#111111`,fill:`#ffffff`},negative:{stroke:`#111111`,fill:`#ececec`}}),start:{stroke:`#111111`,fill:`#e2e2e2`},note:{stroke:`none`,fill:`#f5f5f5`,fold:`#767676`},stage:{fill:`#f5f5f5`,stroke:`#8a8a8a`,title:`#111111`},stageLit:{fill:`#e2e2e2`,stroke:`#111111`,title:`#111111`},link:C(b,{main:{stroke:`#111111`},plain:{stroke:`#2b2b2b`},back:{stroke:`#4d4d4d`}})},justify:{node:C(x,{conclusion:{stroke:`#111111`,fill:`#ffffff`},norm:{stroke:`#111111`,fill:`#ececec`},element:{stroke:`#111111`,fill:`#ffffff`},fact:{stroke:`#111111`,fill:`#ffffff`},inference:{stroke:`#111111`,fill:`#ffffff`},judgement:{stroke:`#111111`,fill:`#ececec`}}),stance:C(S,{for:{stroke:`#2b2b2b`},against:{stroke:`#111111`},basis:{stroke:`#4d4d4d`}})},pill:{colored:!1,border:`#111111`}},modern:{id:`modern`,shadowRgb:`15, 23, 42`,chrome:{radius:14,capsule:999,chip:999,bg:`rgba(255, 255, 255, 0.78)`,bgPop:`rgba(255, 255, 255, 0.94)`,border:`1px solid rgba(15, 23, 42, 0.07)`,shadow:`0 4px 18px rgba(15, 23, 42, 0.10), 0 1px 2px rgba(15, 23, 42, 0.06)`,blur:`blur(16px) saturate(1.8)`},labelKey:`theme.modern`,font:{body:`system-ui, "PingFang SC", "Microsoft YaHei UI", "Microsoft YaHei", "Noto Sans CJK SC", "Source Han Sans SC", sans-serif`,head:`system-ui, "PingFang SC", "Microsoft YaHei UI", "Microsoft YaHei", "Noto Sans CJK SC", "Source Han Sans SC", sans-serif`},color:{ink:`#0f172a`,ink2:`#475569`,ink3:`#64748b`,ink4:`#94a3b8`,bg:`#fbfcfd`,canvas:`#fbfcfd`,frame:`#e2e8f0`,line:`#e8ebef`,chip:`#f1f4f8`,side1:`#475569`,side2:`#64748b`,axis:`#94a3b8`},radius:{person:14,company:8,organization:8,government:6,other:8,pill:12,group:12},entity:{person:{stroke:`#94a3b8`,fill:`#f1f5f9`,width:1},company:{stroke:`#334155`,fill:`#ffffff`,width:1.25},organization:{stroke:`#94a3b8`,fill:`#ffffff`,width:1,dash:n.dashed},government:{stroke:`#64748b`,fill:`#f8fafc`,width:1},other:{stroke:`#94a3b8`,fill:`#f8fafc`,width:.9,dash:n.dotted}},relation:v(g,`#475569`),camp:[{fill:`#f1f5f9`,stroke:`#94a3b8`,text:`#334155`},{fill:`#ffffff`,stroke:`#94a3b8`,text:`#334155`},{fill:`#f8fafc`,stroke:`#e2e8f0`,text:`#64748b`}],group:{fill:`#f8fafc`,stroke:`#e2e8f0`,title:`#475569`},campBox:{fill:`#f8fafc`,stroke:`#e2e8f0`,width:1},flow:{outcome:C(y,{neutral:{stroke:`#64748b`,fill:`#f8fafc`},positive:{stroke:`#334155`,fill:`#f1f5f9`},negative:{stroke:`#64748b`,fill:`#f1f5f9`}}),start:{stroke:`#334155`,fill:`#e2e8f0`},note:{stroke:`none`,fill:`#f1f5f9`,fold:`#94a3b8`},stage:{fill:`#f8fafc`,stroke:`#e2e8f0`,title:`#475569`},stageLit:{fill:`#f1f5f9`,stroke:`#64748b`,title:`#334155`},link:C(b,{main:{stroke:`#0f172a`},plain:{stroke:`#475569`},back:{stroke:`#64748b`}})},justify:{node:C(x,{conclusion:{stroke:`#0f172a`,fill:`#f1f5f9`},norm:{stroke:`#475569`,fill:`#e2e8f0`},element:{stroke:`#64748b`,fill:`#f8fafc`},fact:{stroke:`#94a3b8`,fill:`#ffffff`},inference:{stroke:`#64748b`,fill:`#f8fafc`},judgement:{stroke:`#334155`,fill:`#e2e8f0`}}),stance:C(S,{for:{stroke:`#475569`},against:{stroke:`#334155`},basis:{stroke:`#94a3b8`}})},pill:{colored:!1,border:`#cbd5e1`}},legal:{id:`legal`,shadowRgb:`19, 35, 63`,chrome:{radius:6,capsule:6,chip:4,bg:`#ffffff`,bgPop:`#ffffff`,border:`1px solid #c7d2e4`,shadow:`0 2px 10px rgba(19, 35, 63, 0.10)`,blur:`none`},labelKey:`theme.legal`,font:{body:`system-ui, "PingFang SC", "Microsoft YaHei UI", "Microsoft YaHei", "Noto Sans CJK SC", "Source Han Sans SC", sans-serif`,head:`system-ui, "PingFang SC", "Microsoft YaHei UI", "Microsoft YaHei", "Noto Sans CJK SC", "Source Han Sans SC", sans-serif`},color:{ink:`#13233f`,ink2:`#2d4366`,ink3:`#5b6f8f`,ink4:`#8aa0c4`,bg:`#ffffff`,canvas:`#ffffff`,frame:`#c7d2e4`,line:`#dbe3f0`,chip:`#eef3fb`,side1:`#1f3f7f`,side2:`#9a1b1b`,axis:`#8aa0c4`},radius:{person:14,company:3,organization:4,government:3,other:4,pill:4,group:6},entity:{person:{stroke:`#2f5aa8`,fill:`#eef3fb`,width:1},company:{stroke:`#1f3f7f`,fill:`#e3ecfa`,width:1.5},organization:{stroke:`#2f5aa8`,fill:`#f4f7fc`,width:1,dash:n.dashed},government:{stroke:`#13233f`,fill:`#eef3fb`,width:1.1},other:{stroke:`#8aa0c4`,fill:`#f8fafd`,width:.9,dash:n.dotted}},relation:{equity:{...g.equity,stroke:`#1f3f7f`},control:{...g.control,stroke:`#13233f`},contract:{...g.contract,stroke:`#5b6f8f`},debt:{...g.debt,stroke:`#9a1b1b`},guarantee:{...g.guarantee,stroke:`#2f5aa8`},kinship:{...g.kinship,stroke:`#4b3a8c`},employment:{...g.employment,stroke:`#1d6b6b`},agency:{...g.agency,stroke:`#1d6b6b`},other:{...g.other,stroke:`#8aa0c4`}},camp:[{fill:`#eaf0fb`,stroke:`#9fb6e0`,text:`#1f3f7f`},{fill:`#fbecec`,stroke:`#e3b4b4`,text:`#9a1b1b`},{fill:`#f4f7fc`,stroke:`#c7d2e4`,text:`#5b6f8f`}],group:{fill:`#f4f7fc`,stroke:`#c7d2e4`,title:`#2d4366`},campBox:{fill:`#f4f7fc`,stroke:`#c7d2e4`,width:1},flow:{outcome:C(y,{neutral:{stroke:`#2f5aa8`,fill:`#eef3fb`},positive:{stroke:`#1f3f7f`,fill:`#e3ecfa`},negative:{stroke:`#9a1b1b`,fill:`#fbecec`}}),start:{stroke:`#13233f`,fill:`#dbe5f5`},note:{stroke:`none`,fill:`#f4f7fc`,fold:`#8aa0c4`},stage:{fill:`#f4f7fc`,stroke:`#c7d2e4`,title:`#2d4366`},stageLit:{fill:`#eaf0fb`,stroke:`#1f3f7f`,title:`#1f3f7f`},link:C(b,{main:{stroke:`#13233f`},plain:{stroke:`#2d4366`},back:{stroke:`#5b6f8f`}})},justify:{node:C(x,{conclusion:{stroke:`#1f3f7f`,fill:`#e3ecfa`},norm:{stroke:`#4b3a8c`,fill:`#efecf8`},element:{stroke:`#2f5aa8`,fill:`#eef3fb`},fact:{stroke:`#8aa0c4`,fill:`#f8fafd`},inference:{stroke:`#1d6b6b`,fill:`#e8f4f4`},judgement:{stroke:`#13233f`,fill:`#dbe5f5`}}),stance:C(S,{for:{stroke:`#2d4366`},against:{stroke:`#9a1b1b`},basis:{stroke:`#4b3a8c`}})},pill:{colored:!0,border:`#c7d2e4`}}},T=e=>Object.prototype.hasOwnProperty.call(w,e);function E(n,{kind:r,theme:i}={}){let a=e(n);if(a.length)throw Object.assign(Error(`antu: the spec is not valid (${a.length} problem(s)): ${a[0]}`),{errors:[...a]});let o=t(n,r);if(o)throw Error(`antu: ${o}`);if(i!==void 0&&!T(i))throw Error(`antu: the theme is one of ${h.join(`, `)}`);return m(n,{preset:r||i?{...r&&{defaultKind:r},...i&&{theme:i}}:void 0,quiet:!0})}export{E as renderHtml};
package/lib/validate.d.ts CHANGED
@@ -24,6 +24,15 @@ export interface VersionsReport {
24
24
 
25
25
  export function validate(spec: unknown): ValidateResult
26
26
  export function layout(spec: unknown, options?: { kind?: string; orientation?: 'vertical' | 'horizontal' }): LayoutResult
27
+ export interface NormalizeResult {
28
+ /** A repaired copy; the input is not modified */
29
+ spec: unknown
30
+ /** What was changed, in words an agent can read; empty when nothing was */
31
+ changes: string[]
32
+ }
33
+
34
+ /** Repair what is inconsistent in the marks of a spec but not in its content (a procedure's main line). Call it before `validate` */
35
+ export function normalize(spec: unknown): NormalizeResult
27
36
  /** Each type and its kinds, the first kind being the one a diagram opens in */
28
37
  export function kinds(): Record<string, string[]>
29
38
  export function versions(): VersionsReport
package/lib/validate.mjs CHANGED
@@ -1,4 +1,4 @@
1
- // Antu 0.11.0
1
+ // Antu 0.13.0
2
2
  // Copyright (C) 2026 Ji Cheng
3
3
  //
4
4
  // Antu is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public
@@ -12,9 +12,9 @@
12
12
  // publish them, or sell them on any terms you like. This licence covers Antu's code in the page, and the notices in
13
13
  // the page must stay with it.
14
14
  //
15
- // Corresponding Source of this version: https://github.com/zh-xx/Antu/tree/v0.11.0
16
- // The licence: https://github.com/zh-xx/Antu/blob/v0.11.0/LICENSE
17
- // Third-party notices: https://github.com/zh-xx/Antu/blob/v0.11.0/skills/antu/THIRD-PARTY-NOTICES.md
15
+ // Corresponding Source of this version: https://github.com/zh-xx/Antu/tree/v0.13.0
16
+ // The licence: https://github.com/zh-xx/Antu/blob/v0.13.0/LICENSE
17
+ // Third-party notices: https://github.com/zh-xx/Antu/blob/v0.13.0/skills/antu/THIRD-PARTY-NOTICES.md
18
18
  //
19
19
  // === The licence of Antu ===
20
20
  //
@@ -1422,4 +1422,4 @@
1422
1422
  // SOFTWARE.
1423
1423
  // ````
1424
1424
  //
1425
- import{a as e,c as t,d as n,i as r,l as i,n as a,r as o,t as s,u as c}from"./chunks/report-BV3j2cS_.mjs";function l(e,r){return{release:e,types:n().map(e=>e.type).filter(e=>!r||e===r).map(e=>({type:e,specVersion:i(e).specVersion,diagrams:t(e).map(({kind:e,version:t,status:n,since:r})=>({kind:e,version:t,status:n,since:r}))}))}}var u=`0.11.0`;function d(t){let n=e(t);return{ok:n.length===0,errors:[...n],notes:n.length?[]:[...r(t)]}}function f(t,{kind:n,orientation:r}={}){let i=e(t);if(i.length)return{ok:!1,reason:`the spec is not valid`,errors:[...i]};let c=a(t,n);if(c)return{ok:!1,reason:c};let l=o(t,{kind:n,orientation:r});return l.ok?{...l,text:s(l)}:l}function p(){return Object.fromEntries(n().map(({type:e})=>[e,c(e)]))}function m(){return l(u)}export{p as kinds,f as layout,d as validate,m as versions};
1425
+ import{a as e,c as t,d as n,i as r,l as i,n as a,r as o,t as s,u as c}from"./chunks/report-BTsYMUG2.mjs";function l(e,r){return{release:e,types:n().map(e=>e.type).filter(e=>!r||e===r).map(e=>({type:e,specVersion:i(e).specVersion,diagrams:t(e).map(({kind:e,version:t,status:n,since:r})=>({kind:e,version:t,status:n,since:r}))}))}}function u(e){if(typeof e!=`object`||!e||Array.isArray(e))return{spec:e,changes:[]};let t=structuredClone(e),n=typeof t.type==`string`?i(t.type)?.normalize:void 0;return{spec:t,changes:n?[...n(t)]:[]}}var d=`0.13.0`;function f(t){let n=e(t);return{ok:n.length===0,errors:[...n],notes:n.length?[]:[...r(t)]}}function p(t,{kind:n,orientation:r}={}){let i=e(t);if(i.length)return{ok:!1,reason:`the spec is not valid`,errors:[...i]};let c=a(t,n);if(c)return{ok:!1,reason:c};let l=o(t,{kind:n,orientation:r});return l.ok?{...l,text:s(l)}:l}function m(e){return u(e)}function h(){return Object.fromEntries(n().map(({type:e})=>[e,c(e)]))}function g(){return l(d)}export{h as kinds,p as layout,m as normalize,f as validate,g as versions};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zh-xx/antu",
3
- "version": "0.11.0",
3
+ "version": "0.13.0",
4
4
  "description": "Antu: legal diagrams (fact, procedure, relationship, justification) from JSON, as one offline HTML page. The command line, the MCP server, and the entries to embed a diagram in an application.",
5
5
  "license": "AGPL-3.0-or-later",
6
6
  "author": "Ji Cheng",
package/server.json CHANGED
@@ -6,12 +6,12 @@
6
6
  "url": "https://github.com/zh-xx/Antu",
7
7
  "source": "github"
8
8
  },
9
- "version": "0.11.0",
9
+ "version": "0.13.0",
10
10
  "packages": [
11
11
  {
12
12
  "registryType": "npm",
13
13
  "identifier": "@zh-xx/antu",
14
- "version": "0.11.0",
14
+ "version": "0.13.0",
15
15
  "transport": {
16
16
  "type": "stdio"
17
17
  }
@@ -19,59 +19,61 @@ scale changes). `date`, `dateEnd` and their precision matter more there: a day-o
19
19
  drawn as the whole day. The same JSON draws in all three; `kind: "chronicle"` or
20
20
  `kind: "scale"` on `layout`, `preview` and `render` shows it.
21
21
 
22
- ## Where an event is drawn is decided by three things
22
+ ## Where an event is drawn
23
23
 
24
- ```
25
- Row (time) the order of the slots array. Earlier in the array = earlier in time.
26
- date is display-only: it never orders or reorders anything.
24
+ Down the page is time: the order of the `slots` array (earlier in the array = earlier in time;
25
+ `date` is display-only and never reorders anything). Across the page are three places: **side 1,
26
+ the axis, side 2** (left, middle, right when vertical). The `groups` list names them: the 1st group
27
+ is side 1, the 2nd is side 2, the 3rd (optional) is the axis.
28
+
29
+ **What the groups split depends on how many parties the diagram has.** Count `actors` first.
30
+
31
+ ### Two or more parties: the groups split the parties
27
32
 
28
- Column (side) groupId decides which side:
29
- the 1st group -> side 1 (left when vertical)
30
- the 2nd group -> side 2 (right when vertical)
31
- the 3rd group or none -> the axis (the middle column)
33
+ Each party says which side it is on, with `groupId` on the **party**: the 1st or the 2nd group,
34
+ never the 3rd. Events carry **no** `groupId`; an event goes where its `actorIds` put it:
32
35
 
33
- Column (lane) actorIds decides the lane:
34
- exactly 1 party -> that party's lane
35
- 2 or more, or none -> the axis
36
+ ```
37
+ actorIds where
38
+ one party that party's side, in that party's column
39
+ several, or none the axis (both sides together, several of one side together,
40
+ or an objective fact)
36
41
  ```
37
42
 
38
- **An event with several parties lands on the axis.** That is a hard rule: it means
39
- "both sides did this" or "this happened objectively", and belongs to neither side.
43
+ See `3-sides` and `4-one-side-several`.
40
44
 
41
- So list in `actorIds` **the party who did it**: "A pays B" is A's act (one party, A's lane); "A and B sign a
45
+ So list in `actorIds` **the party who did it**: "A pays B" is A's act (one party, A's side); "A and B sign a
42
46
  contract" is both's (two parties, the axis). Name the other party in the label or the summary, not in `actorIds`,
43
47
  unless both acted.
44
48
 
45
- ## What a view is
49
+ **Someone on neither side** (the police who came, the ambulance, the court that served a paper) is not a party:
50
+ write the name in the label and leave `actorIds` out. The event goes on the axis.
46
51
 
47
- The same data can be looked at in several ways. A view only changes how the two
48
- rules above are applied. It **never changes the data**:
52
+ Several parties on one side each get their own column, the earlier in `actors` the closer to the axis. A party
53
+ with no card of its own (it only acts with others) has no column.
49
54
 
50
- ```json
51
- { "label": "parties side by side", "splitBy": "actor",
52
- "side1": { "label": "Huayuan Trading", "actors": ["a-1"] },
53
- "side2": { "label": "Xincheng Building Materials", "actors": ["a-2"] } }
54
- ```
55
+ ### One party (or none): the groups split the events
56
+
57
+ With a single party there is no "who is on which side", so the two sides sort its acts by kind
58
+ (performed as agreed / departed from it, act / consequence...; choose from the case). The group goes on
59
+ the **event**: the 1st group side 1, the 2nd side 2, the 3rd or none the axis. The party carries no
60
+ `groupId`.
55
61
 
56
- - `splitBy: "actor"`: split by party; `side1` / `side2` say who is on which side;
57
- - `splitBy: "group"`: split by group; no need to name parties;
58
- - `views` may be omitted; the engine then provides a single "all" view.
62
+ There are no views: a `views` field is an error. The chronicle and the time scale use the same three
63
+ places, one lane (or colour) per group.
59
64
 
60
65
  ## One limit: one event per cell
61
66
 
62
67
  **A time point holds at most one event per lane.** Two events in the same lane of the
63
- same slot means that view cannot be drawn, and it disappears from the interface options
64
- (an option that cannot be clicked is noise). `validate` checks the data once and does not call
65
- this an error, since a data set may keep a view that does not fit on purpose; it does list each such
66
- view as a note after "Validation passed", so it never goes unseen. `layout` reports the same views.
68
+ same slot is an error: `validate` reports it with the slot and the two event ids.
67
69
 
68
70
  Three ways to fix it, most common first:
69
71
 
70
72
  1. **Split the time point.** If two things happened at 9:24, one at 9:24:03 and one at
71
73
  9:24:16, make two slots and give each its exact time.
72
- 2. **Add actorIds.** If the two events belong to different parties, add `actorIds` and
74
+ 2. **Check actorIds.** If the two events belong to different parties, name the party who did each, and
73
75
  they fall into different lanes.
74
- 3. **Add groupId.** If they are of different kinds, add `groupId` and they fall on
76
+ 3. **Add groupId** (one party only). If they are of different kinds, add `groupId` and they fall on
75
77
  different sides.
76
78
 
77
79
  After splitting, check again that each slot holds exactly one event.
@@ -80,9 +82,8 @@ After splitting, check again that each slot holds exactly one event.
80
82
 
81
83
  ```
82
84
  validate reports each problem, with the field path and the event id
83
- (e.g. slots[0].events[1] (ev-2)); when it passes, notes any view that
84
- does not fit (not an error, but that view will not be offered)
85
- layout no rendering: how large, which orientation, which views do not fit
85
+ (e.g. slots[0].events[1] (ev-2))
86
+ layout no rendering: how large, which orientation, how many columns per side
86
87
  preview take a screenshot and look: are cards cramped, is the text small,
87
88
  is there too much empty space
88
89
  render produce the self-contained HTML
@@ -117,10 +118,10 @@ diagram looks good. Always run `preview` and look before delivering.
117
118
 
118
119
  Each adds one idea (`<name>.zh-CN.json`, `<name>.en.json`):
119
120
 
120
- - `1-minimal`: two parties, no `groups` (every card on the axis)
121
- - `2-single-actor`: one party
122
- - `3-groups`: `groupId` picks the side
123
- - `4-views`: the same data, two views
121
+ - `1-minimal`: two parties, each on its side
122
+ - `2-single-actor`: one party, its acts split by kind (`groupId` on the events)
123
+ - `3-sides`: two parties: `groupId` on the parties, none on the events
124
+ - `4-one-side-several`: two parties on one side, and an act of both on the axis
124
125
  - `5-duration`: spans and approximate times
125
126
  - `6-sources`: facts traced to sources
126
127
  - `7-undated`: no `date`
@@ -15,15 +15,14 @@ boxes around parties.
15
15
 
16
16
  The reader can also switch to a **focus view**: one party in the middle (by default the one with most
17
17
  relations; the reader clicks another), the parties tied to it around it, the others further out. It
18
- suits a case with many parties, where the graph is too busy. The **guarantee chain** shows one block per
19
- claim (a `debt`) with its guarantors beside it and what stands behind each; for a loan or guarantee
20
- dispute. **Write `secures` on every guarantee**: without it the chain ties a guarantee to a claim only when
21
- its creditor has exactly one, and puts it apart otherwise. The **matrix** puts the parties down and across and names the relations in each cell: for "is there any
18
+ suits a case with many parties, where the graph is too busy. **Write `secures` on every guarantee**: it
19
+ names the claim (a `debt`) the guarantee secures, and the graph ties the two lines together. The **matrix**
20
+ puts the parties down and across and names the relations in each cell: for "is there any
22
21
  relation between A and B". The **equity tree** draws the `equity` relations in levels with the `share` on each
23
22
  line, so **write `share` on every equity relation**. The **authority chart** draws `control`, `employment` and `agency` as an organisation chart; the **related-party
24
23
  list** is a table of one party's relations (to paste into a brief); the **path** draws the shortest chains between
25
- two parties; the **summary** draws each camp (`groupId`) as one block. The same JSON draws in all nine;
26
- `kind: "focus"`, `"chain"`, `"matrix"`, `"equity"`, `"authority"`, `"related"`, `"path"` or `"summary"` on `layout`, `preview` and `render` shows it.
24
+ two parties in one picture, one start and one end. The same JSON draws in all seven;
25
+ `kind: "focus"`, `"matrix"`, `"equity"`, `"authority"`, `"related"` or `"path"` on `layout`, `preview` and `render` shows it.
27
26
 
28
27
  ## Three things, three places
29
28
 
@@ -36,6 +35,22 @@ groups the camps "creditor side", "debtor side" (optional)
36
35
  It is a cross-section: write the relations as they stand on one date (`asOf`, optional). Do not
37
36
  write a history. If the relations changed, write two diagrams.
38
37
 
38
+ ## A relation is a tie that stands, not something that happened
39
+
40
+ Write what ties the parties to each other: a debt owed, a shareholding, a marriage, a job, a guarantee,
41
+ an instruction to act for someone. **Do not write acts as relations**: a push, a blow, a stabbing, an
42
+ insult, a lock changed, a visit to press for payment. Those happened once; they belong in a fact
43
+ diagram. Leave them out, and offer the user a fact diagram for them.
44
+
45
+ The test: is the sentence still true the day after? "A owes B" is; "A pushed B" is not.
46
+
47
+ An act that leaves a tie behind is written as the tie: lending money is a `debt` (with its `contract`);
48
+ "C sent people to collect the debt" is `agency` from C to those people; pledging a house for a loan is a
49
+ `guarantee` with `secures`. Many acts between the same two parties are no reason for a relation.
50
+
51
+ Write only the ties the material states. "Her family", "the company's people" do not say who is whose
52
+ mother or who works where: leave such a tie out rather than guess it.
53
+
39
54
  ## The kind of a relation, and its direction
40
55
 
41
56
  The direction runs from `from` to `to`. Write it the way the kind says:
@@ -49,7 +64,7 @@ contract either way, no arrowhead amount: "CNY 80,000"
49
64
  kinship either way, no arrowhead spouses, parents and children
50
65
  employment employer -> employee
51
66
  agency principal -> agent
52
- other anything else
67
+ other a standing tie none of the above fits (a lease, a licence); never an act
53
68
  ```
54
69
 
55
70
  `directed: true/false` overrides the kind's default arrowhead. A loan usually needs **two**
@@ -67,6 +82,10 @@ tell which of two loans the guarantee is for.
67
82
  `label` is the name; `role` is the role **in this case** on one short line ("Lender", "Guarantor").
68
83
  Keep labels short; put registered capital and the like in `detail` (its full text shows on click).
69
84
 
85
+ **Two names are two parties** unless the material says they are one. A judgment that hides names writes
86
+ "Fang X" for one person and "Fang Yuan" for another; do not merge them because they look alike, and do
87
+ not merge them with a note saying you did. If it matters and the material does not say, ask the user.
88
+
70
89
  ## Groups
71
90
 
72
91
  `groups` boxes together the parties a reader should see as one camp. An entity is in at most one
@@ -1,44 +0,0 @@
1
- {
2
- "type": "fact",
3
- "specVersion": 1,
4
- "title": "Views: the same data, seen two ways",
5
- "actors": [
6
- { "id": "a-1", "name": "Huayuan Trading" },
7
- { "id": "a-2", "name": "Xincheng Building Materials" }
8
- ],
9
- "groups": [
10
- { "id": "g-1", "label": "Performance as agreed" },
11
- { "id": "g-2", "label": "Deviation from the agreement" }
12
- ],
13
- "views": [
14
- {
15
- "label": "Parties side by side",
16
- "splitBy": "actor",
17
- "side1": { "label": "Huayuan Trading", "actors": ["a-1"] },
18
- "side2": { "label": "Xincheng Building Materials", "actors": ["a-2"] },
19
- "axis": { "label": "Common to both parties" }
20
- },
21
- { "label": "Split by group", "splitBy": "group" },
22
- { "label": "Huayuan Trading only", "splitBy": "actor", "side1": { "actors": ["a-1"] }, "side2": { "actors": [] } }
23
- ],
24
- "slots": [
25
- {
26
- "events": [
27
- { "id": "ev-1", "date": "2023-03-10", "label": "The loan contract is signed",
28
- "actorIds": ["a-1", "a-2"] }
29
- ]
30
- },
31
- {
32
- "events": [
33
- { "id": "ev-2", "date": "2023-03-12", "label": "Huayuan Trading disburses the loan",
34
- "groupId": "g-1", "actorIds": ["a-1"] }
35
- ]
36
- },
37
- {
38
- "events": [
39
- { "id": "ev-3", "date": "2024-03-11", "label": "Xincheng Building Materials fails to repay on time",
40
- "groupId": "g-2", "actorIds": ["a-2"] }
41
- ]
42
- }
43
- ]
44
- }
@@ -1,44 +0,0 @@
1
- {
2
- "type": "fact",
3
- "specVersion": 1,
4
- "title": "视角:同一份数据,两种看法",
5
- "actors": [
6
- { "id": "a-1", "name": "华远贸易" },
7
- { "id": "a-2", "name": "鑫城建材" }
8
- ],
9
- "groups": [
10
- { "id": "g-1", "label": "按约定履行" },
11
- { "id": "g-2", "label": "偏离约定" }
12
- ],
13
- "views": [
14
- {
15
- "label": "双方对照",
16
- "splitBy": "actor",
17
- "side1": { "label": "华远贸易", "actors": ["a-1"] },
18
- "side2": { "label": "鑫城建材", "actors": ["a-2"] },
19
- "axis": { "label": "双方共同" }
20
- },
21
- { "label": "按性质分侧", "splitBy": "group" },
22
- { "label": "只看华远贸易", "splitBy": "actor", "side1": { "actors": ["a-1"] }, "side2": { "actors": [] } }
23
- ],
24
- "slots": [
25
- {
26
- "events": [
27
- { "id": "ev-1", "date": "2023-03-10", "label": "签订借款合同",
28
- "actorIds": ["a-1", "a-2"] }
29
- ]
30
- },
31
- {
32
- "events": [
33
- { "id": "ev-2", "date": "2023-03-12", "label": "华远贸易放款",
34
- "groupId": "g-1", "actorIds": ["a-1"] }
35
- ]
36
- },
37
- {
38
- "events": [
39
- { "id": "ev-3", "date": "2024-03-11", "label": "鑫城建材逾期未还",
40
- "groupId": "g-2", "actorIds": ["a-2"] }
41
- ]
42
- }
43
- ]
44
- }