diff --git a/apps/docs/public/figures/endor-purpose.svg b/apps/docs/public/figures/endor-purpose.svg new file mode 100644 index 0000000..3909302 --- /dev/null +++ b/apps/docs/public/figures/endor-purpose.svg @@ -0,0 +1,320 @@ + + + + +Endor 的意义:从访问程序到操作对象的对比示意 + +ENDOR / WHY OBJECTS +从程序入口,到对象的操作权 +一对概念图:改变用户与 AI 接触系统的基本单位。 +01 +以程序为入口 +OS +进程区 · 圆圈为进程中的对象 +程序 +用户入口 + + + + + + + + + +OS + + + + +2 个进程 + + + + + + + + + + + + + + + + + + + +程序 A + + + + +4 个进程 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +程序 B + + + + +3 个进程 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +程序 C + + + + + +用户 +界面 / Web / API +用户通过程序提供的入口访问功能;对象的组织与操作通常藏在程序内部。 +02 +以对象为操作单位 + + +Endor OS +OS +少量进程 + + + + + + + + + +OS + + + + +进程 + + + + +进程 + + + + +进程 + + + + +Endorphin +对象运行与操作空间 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +对象 +可引用 · 可组合 +按权限操作 + + +用户 + + + + + + +AI + + + + + + + + + + + + + + +选择对象 · 发起操作 +进程数量仅作概念对比,不代表性能测量或固定部署要求。 +圆圈 = 对象 细线 = 对象关系 贝塞尔曲线 = 用户 / AI 对选定对象的操作 +讨论草案 + \ No newline at end of file diff --git a/apps/docs/src/lib/navigation.ts b/apps/docs/src/lib/navigation.ts index 6f2d298..a37681f 100644 --- a/apps/docs/src/lib/navigation.ts +++ b/apps/docs/src/lib/navigation.ts @@ -5,6 +5,13 @@ export type Section = { symbol: string; }; export function sectionFor(slug: string): Section { + if (slug.includes("endor-purpose")) + return { + group: "项目讨论", + label: "讨论草案", + symbol: "○", + description: "逐步讨论 Endor 的意义:从程序入口走向用户与 AI 的对象操作。", + }; if (slug.includes("endor-concepts")) return { group: "架构设计", diff --git a/content/docs/04-endor-purpose-draft.md b/content/docs/04-endor-purpose-draft.md new file mode 100644 index 0000000..7484f25 --- /dev/null +++ b/content/docs/04-endor-purpose-draft.md @@ -0,0 +1,42 @@ +# Endor 的意义:从程序入口到对象操作 + +这篇文档用来逐步整理我们为什么要做 Endor。先记录一个切入点:**把对象的操作权交还给用户与 AI**。后续讨论可以在这里补充、修正,暂不把它写成一份已经定稿的项目宣言。 + +> **讨论草案**:以下是希望探索的系统组织方式。图中进程和对象的数量、对象关系与操作路径都是示意,不表示当前实现或性能测量。 + +## 一对图:我们希望改变什么 + +![从程序入口到对象操作的对比:上图中 OS 分出九个进程,按二、四、三个分为三组,对应三个程序;对象以进程内的随机小圆圈表示,用户通过程序入口访问。下图中 OS 只分出少量进程,承载 Endorphin 的对象关系网络,用户与 AI 用多条贝塞尔曲线直接指向选定对象;OS、进程区与 Endorphin 都位于 Endor OS 边界内](/figures/endor-purpose.svg) + +### 第一张图:用户面对程序 + +从 OS 出发,许多进程组成不同的程序。每个程序可以对应不同数量的进程;图中分别画了两个、四个和三个。进程区里的许多小圆圈表示对象,它们散布在各进程中。 + +用户通常通过程序提供的界面访问能力,也可能通过 Web 或 API。这里想强调的是操作入口:用户先选择程序,再在程序提供的功能中寻找自己要做的事。图中的对象仍然存在,但通常隐藏在程序的组织和入口之后。 + +这是一种用于对照的简化视角,并不是说现有程序都无法开放对象或让外部系统组合能力。 + +### 第二张图:用户与 AI 面对对象 + +仍然从 OS 出发,但这次只画少量进程,用来承载 Endorphin。接下来展开的是许多相互连接的小圆圈:对象不再只作为程序内部的实现细节出现,而成为可以被引用、选择和操作的基本单位。 + +用户与 AI 的多条曲线分别指向部分对象,表达我们希望提供的能力:**在授权范围内,直接找到所需对象,对它们执行操作,并把不同对象的能力组合起来**。图中没有把所有对象都连向用户,因为操作权应当是有范围、可控制的。 + +OS、进程区与 Endorphin 被共同框在 **Endor OS** 的边界内。这是此处对整体系统的命名;是否涉及内核层面的替换、哪些职责由底层 OS 保留,尚未在这张概念图中定义。 + +## 先记录下来的主张 + +我们希望讨论的变化,是让用户与 AI 不必总以一个个程序为唯一操作入口,而能以对象及其关系来组织工作。程序仍可以承担展示、交互和专业工作流;对象则有机会成为跨这些入口引用和组合能力的共同单位。 + +“交还操作权”不是开放任意内存访问,也不是绕过权限。它需要对象能够被明确定位,需要操作接口与授权边界,也需要让用户知道一次操作改变了什么。这些能力怎样落地,还需要后续设计。 + +## 接下来慢慢整理 + +- **对象是什么**:哪些东西应该成为可操作对象,身份和生命周期如何定义? +- **操作权是什么**:读取、修改、调用、组合与委托分别意味着什么,怎样授予和撤销? +- **AI 如何参与**:如何发现对象能力、请求授权,并让操作结果可以检查? +- **程序的位置**:Tessera、Web 与其他程序如何成为同一对象世界的不同入口? +- **运行边界**:对象跨进程、设备、自部署和平台运行时,哪些语义需要保持一致? +- **怎样验证意义**:用什么具体工作流说明这种组织方式给用户带来的变化? + +本文先保留这些问题,随讨论逐项展开。[系统架构](/docs/00-endor-concepts-draft)讨论部署与存储,[节点与对象挂载](/docs/02-mounting-draft)讨论运行位置和挂载边界;这里关注的是它们最终为什么值得做。 diff --git a/design/verification/purpose/comparison.png b/design/verification/purpose/comparison.png new file mode 100644 index 0000000..66f00b1 Binary files /dev/null and b/design/verification/purpose/comparison.png differ diff --git a/tools/figures/src/endor_figures/cli.py b/tools/figures/src/endor_figures/cli.py index dc22dc2..fd5ff6e 100644 --- a/tools/figures/src/endor_figures/cli.py +++ b/tools/figures/src/endor_figures/cli.py @@ -3,6 +3,7 @@ from pathlib import Path import drawsvg as draw from .architecture import build_architecture from .deployment import build_deployment +from .purpose import build_purpose def main() -> None: @@ -41,3 +42,7 @@ def main() -> None: deployment = output.parent / "endor-deployment.svg" build_deployment(deployment) print(f"Generated {deployment.relative_to(root)}") + + purpose = output.parent / "endor-purpose.svg" + build_purpose(purpose) + print(f"Generated {purpose.relative_to(root)}") diff --git a/tools/figures/src/endor_figures/purpose.py b/tools/figures/src/endor_figures/purpose.py new file mode 100644 index 0000000..1ff315d --- /dev/null +++ b/tools/figures/src/endor_figures/purpose.py @@ -0,0 +1,146 @@ +"""Paired concept views: application entry points versus authorized object operations.""" +from pathlib import Path +import math +import random +import drawsvg as d +from .architecture import INK, GREEN, BLUE, PURPLE, MUTED, LINE, FONT + + +def build_purpose(output: Path) -> None: + svg = d.Drawing(1800, 1290) + svg.append_title('Endor 的意义:从访问程序到操作对象的对比示意') + svg.append(d.Rectangle(0,0,1800,1290,fill='#fcfdfb')) + rng = random.Random(20261028) + + def text(s,x,y,size=16,color=INK,weight='400',anchor='start'): + svg.append(d.Text(s,size,x,y,fill=color,font_family=FONT,font_weight=weight,text_anchor=anchor)) + + def box(x,y,w,h,fill='white',stroke=LINE,r=12): + svg.append(d.Rectangle(x,y,w,h,rx=r,fill=fill,stroke=stroke,stroke_width=1.3)) + + def wire(points,color=GREEN,arrow=False,dash=None,width=1.5): + p=d.Path(fill='none',stroke=color,stroke_width=width,stroke_linejoin='round',stroke_dasharray=dash) + p.M(*points[0]) + for pt in points[1:]: p.L(*pt) + svg.append(p) + if arrow: + x,y=points[-1]; px,py=points[-2]; a=math.atan2(y-py,x-px) + for sign in [-1,1]: + svg.append(d.Line(x-7*math.cos(a+sign*.48),y-7*math.sin(a+sign*.48),x,y,stroke=color,stroke_width=width)) + + def objects(x,y,w,h,count,color=GREEN,r=3.5): + points=[] + while len(points)r*3.7 for qx,qy in points): points.append((px,py)) + for px,py in points: + svg.append(d.Circle(px,py,r,fill='#eff6f1',stroke=color,stroke_width=1.2)) + return points + + def os(x,y): + for dy in [-21,-3,15]: + svg.append(d.Rectangle(x-40,y+dy,80,13,rx=3,fill='white',stroke=MUTED,stroke_width=1.6)) + svg.append(d.Circle(x-30,y+dy+6,1.5,fill=MUTED)) + svg.append(d.Line(x-17,y+dy+6,x+25,y+dy+6,stroke=MUTED,stroke_width=1.2)) + text('OS',x,y+65,24,INK,'600','middle') + + def person(x,y,ai=False): + if ai: + box(x-20,y-25,40,36,'#f5f1fa',PURPLE,8) + for dx in [-8,8]: svg.append(d.Circle(x+dx,y-8,2,fill=PURPLE)) + wire([(x-8,y+4),(x+8,y+4)],PURPLE) + wire([(x,y-25),(x,y-35)],PURPLE) + svg.append(d.Circle(x,y-38,3,fill='white',stroke=PURPLE)) + else: + svg.append(d.Circle(x,y-20,13,fill='#f1f6f3',stroke=GREEN,stroke_width=1.8)) + svg.append(d.Path(fill='none',stroke=GREEN,stroke_width=1.8).M(x-25,y+23).Q(x-25,y-1,x,y-1).Q(x+25,y-1,x+25,y+23).Z()) + text('AI' if ai else '用户',x,y+57,18,PURPLE if ai else INK,'600','middle') + + text('ENDOR / WHY OBJECTS',40,43,14,GREEN,'600') + text('从程序入口,到对象的操作权',40,90,31,INK,'600') + text('一对概念图:改变用户与 AI 接触系统的基本单位。',40,123,16,MUTED) + + # Panel one: unequal groups of processes map to application boundaries. + text('01',40,181,20,BLUE,'600') + text('以程序为入口',95,181,24,INK,'600') + text('OS',135,225,13,MUTED,'600','middle') + text('进程区 · 圆圈为进程中的对象',585,225,14,MUTED,'500','middle') + text('程序',1100,225,14,MUTED,'600','middle') + text('用户入口',1615,225,14,MUTED,'600','middle') + os(135,414) + wire([(178,414),(250,414),(250,286),(300,286)],BLUE) + wire([(250,414),(250,545),(300,545)],BLUE) + wire([(250,414),(300,414)],BLUE) + for row,(count,cy) in enumerate([(2,286),(4,414),(3,545)]): + box(300,cy-49,570,98,'#f7f9fb') + text(f'{count} 个进程',315,cy-27,11,MUTED) + pw=112 + start=585-(count*pw+(count-1)*16)/2 + for i in range(count): + px=start+i*(pw+16) + box(px,cy-15,pw,53,'white','#c6d8e7',7) + objects(px,cy-14,pw,50,6+rng.randrange(4),BLUE,r=3) + wire([(870,cy),(999,cy)],BLUE,arrow=True) + box(1000,cy-33,200,66,'white','#bdcfdc') + wire([(1013,cy-15),(1187,cy-15)],BLUE,width=1) + text(f'程序 {chr(65+row)}',1100,cy+14,20,INK,'600','middle') + wire([(1568,414),(1400,414),(1400,cy),(1202,cy)],BLUE,arrow=True) + person(1615,414) + text('界面 / Web / API',1394,611,15,BLUE,anchor='middle') + text('用户通过程序提供的入口访问功能;对象的组织与操作通常藏在程序内部。',300,640,16,MUTED) + + # Panel two: OS, a small process pool and Endorphin belong to Endor OS. + text('02',40,709,20,GREEN,'600') + text('以对象为操作单位',95,709,24,INK,'600') + box(40,742,1410,421,'#f8fbf8','#a9cbbd',18) + box(64,758,162,36,'#eaf3ec','none',5) + text('Endor OS',145,783,21,GREEN,'600','middle') + text('OS',135,837,13,MUTED,'600','middle') + text('少量进程',415,837,14,MUTED,'600','middle') + os(135,961) + wire([(178,961),(270,961),(270,886),(335,886)],GREEN) + wire([(270,961),(335,961)],GREEN) + wire([(270,961),(270,1036),(335,1036)],GREEN) + for cy in [886,961,1036]: + box(335,cy-22,160,44,'white','#bdd5c8',7) + text('进程',415,cy+6,15,MUTED,anchor='middle') + wire([(495,cy),(555,cy),(555,961),(615,961)],GREEN,arrow=True,width=1.2) + box(615,807,805,322,'white','#cbded1',14) + text('Endorphin',644,845,25,INK,'600') + text('对象运行与操作空间',644,874,14,MUTED) + # Seeded randomness gives an organic network and reproducible repository assets. + nodes=[] + for i in range(43): + while True: + px,py=rng.uniform(845,1380),rng.uniform(843,1090) + if all(math.hypot(px-qx,py-qy)>33 for qx,qy in nodes): break + nodes.append((px,py)) + edges=set() + for i,(px,py) in enumerate(nodes): + nearest=sorted((math.hypot(px-qx,py-qy),j) for j,(qx,qy) in enumerate(nodes) if j!=i) + for _,j in nearest[:2 if i%3 else 3]: edges.add(tuple(sorted((i,j)))) + for i,j in sorted(edges): wire([nodes[i],nodes[j]],'#c8dcd2',width=1) + selected=sorted(range(len(nodes)),key=lambda i:nodes[i][0],reverse=True)[:7] + for i,(px,py) in enumerate(nodes): + svg.append(d.Circle(px,py,7 if i in selected else 5, + fill='#e5f1e8' if i in selected else 'white', + stroke=GREEN,stroke_width=1.8 if i in selected else 1.2)) + text('对象',647,1000,17,GREEN,'600') + text('可引用 · 可组合',647,1028,13,MUTED) + text('按权限操作',647,1053,13,MUTED) + person(1630,888) + person(1630,1055,ai=True) + # Users/AI reach selected objects with explicit cubic Bezier curves. + for k,i in enumerate(selected): + px,py=nodes[i] + sy=888 if k<4 else 1055 + color=GREEN if k<4 else PURPLE + control_y=790+k*45 + svg.append(d.Path(fill='none',stroke=color,stroke_width=1.7,opacity=.85) + .M(1597,sy).C(1505,control_y,px+90,py-35,px,py)) + svg.append(d.Circle(px,py,10,fill='none',stroke=color,stroke_width=1,opacity=.6)) + text('选择对象 · 发起操作',1620,1196,16,GREEN,anchor='middle') + text('进程数量仅作概念对比,不代表性能测量或固定部署要求。',40,1220,13,MUTED) + text('圆圈 = 对象 细线 = 对象关系 贝塞尔曲线 = 用户 / AI 对选定对象的操作',40,1253,14,MUTED) + text('讨论草案',1730,1253,13,MUTED,anchor='end') + svg.save_svg(str(output))