Commit 2255f09c958c3592f1e4a58f9760f122bbd43d63
1 parent
74ea1ff8
feat(company): 新增 company-goal 字段;P2 需求审计的四个定案落入文档
起因:逐条比对 27-REQ 的原话与 P2 v0.4,发现四处偏离,其中两处是设计悄悄
改变了原意。本次修正并落定。
代码(P2 §五 T0):
- company.json 新增 goal 字段(company-goal),create({id,name,goal,description})
- POST /api/company/create 与 update() 同步支持
- 修的是一个实打实的遗漏:R-6 原话是"写入 company 的目标和描述"(两个字段),
而 create() 一直只有 description。orggraph-planning 规划流水线的主依据本该是
company-goal,此前根本拿不到。
文档定案(R-13):
- R-13.1 goal 三层递归:company-goal / task-goal / subagent-goal,与"验收逐层
递归"对应。澄清 R-12 说的"唯一的那个 goal"其实是 task-goal;三个验收 agent
保持通用不按层级拆分。记录一处待定:subagent-goal 按执行者命名,与另两个的
作用域命名轴不一致(按轴应为 subtask-goal)。
- R-13.2 公司类型完全由 orggraph-planning 推断 —— 这条**推翻了我自己记的一个
缺陷**:审计时我把"不加 type 枚举字段"记为擅自偏离原话,实际那正是所需,
当前设计无需改动。
- R-13.3 新 agent 从 system/templates/base 元 agent 继承骨架(自动带四段式
RESEARCH→PLAN→EXECUTE→VERIFY)+ agent-creator 填充,而非直接走 needs_training
全量培养;新建一律 scope='company';innovator 训练是可选后置步骤。
这是 R-9.2"所有 node agent 由元 agent 继承生成"在 P2 的落地点(新增 T5b)。
- R-13.4 org graph 强制单入口,原 open question 关闭。
顺带修掉 P2 的一处内部不一致:§六 承诺"提供手动触发 orggraph-planning 的端点"
给存量公司补图,但 §四.3 API 表和 §五 任务表都没有。已补 POST …/org-graph/replan。
另更正 R-11 中"代码层未执行"的过期表述——OKR 正名已于 74ea1ff 实施完毕。
回归:npm run test:unit 652 例全绿。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Showing
5 changed files
with
83 additions
and
13 deletions
docs/todo/system-design/27-naming-conventions.md
| ... | ... | @@ -23,8 +23,10 @@ |
| 23 | 23 | | `orggraph` | 公司级 workflow | |
| 24 | 24 | | `workgraph` | org node 级 workflow | |
| 25 | 25 | | `{domain}` | 业务领域(`code` / `content` / `ops` …),即 org node 所属领域 | |
| 26 | -| `goal` | **一个人类需求描述**(唯一,验收边界)| | |
| 27 | -| `task` | 图中的执行单元(一个 goal 分解出多个,可并行)| | |
| 26 | +| `company-goal` | **公司的目标**(建公司时写入,OKR 树的输入)| | |
| 27 | +| `task-goal` | **一次用户请求的目标**(唯一,验收边界;R-12 说的就是这一层)| | |
| 28 | +| `subagent-goal` | **子任务的目标**(一个 task-goal 分解出多个)| | |
| 29 | +| `task` | 图中的执行单元(一个 task-goal 分解出多个,可并行)| | |
| 28 | 30 | | `agent` | 单个 system agent | |
| 29 | 31 | | `skill` | 单个 skill | |
| 30 | 32 | |
| ... | ... | @@ -81,6 +83,22 @@ work graph 内动态选入的验收产出节点(见 [27-E2E](./27-e2e-task-exe |
| 81 | 83 | |
| 82 | 84 | 验收标准回答的是"**人类想要的东西做到了没有**"——这是 goal 级的判定。task 只是达成它的执行分支,一个 goal 下有很多个;把验收挂在 task 上会导致"到底以哪个 task 的验收为准"根本无法回答。 |
| 83 | 85 | |
| 86 | +### goal 是三层递归的(R-13) | |
| 87 | + | |
| 88 | +「goal」本身在三个层级上各有一个,与 [27-E2E](./27-e2e-task-execution-flow.md) §11.3「验收逐层递归」严格对应——每一层的 goal 就是那一层的验收边界: | |
| 89 | + | |
| 90 | +| goal | 归属 | 谁验收它 | 落在哪 | | |
| 91 | +|---|---|---|---| | |
| 92 | +| **`company-goal`** | 公司 | OKR 树(长周期度量) | `company.json.goal`,建公司时写入 | | |
| 93 | +| **`task-goal`** | 一次用户请求 | org graph 末端的 `{domain}-validator` | 任务入口带入 | | |
| 94 | +| **`subagent-goal`** | 子任务 / 并行分支 | 该 work graph 内的 validator 节点 | 由 `workgraph-planning` 拆分时产生 | | |
| 95 | + | |
| 96 | +**`company-goal` 与 OKR 的关系**:`company-goal` 是建公司时的一句话**定性**目标,是 **OKR 树的输入**——OKR 把它拆成可度量的 Objective → Key Result。两者不是替代关系,不要用 OKR 节点去存 `company-goal`。 | |
| 97 | + | |
| 98 | +**三个验收 agent(`goal-benchmark` / `goal-test-data` / `goal-test-script`)是通用的,不按层级拆分**:它们在哪一层被调用,就为那一层的 goal 产出验收标准。这与 §八bis 的元 agent 继承(全局通用本体 + 记忆分区)一致——不需要 `task-goal-benchmark` / `subagent-goal-benchmark` 这种按层级复制的 agent。 | |
| 99 | + | |
| 100 | +> **一处命名轴不一致(待定,不阻塞)**:`company-goal` / `task-goal` 是按**作用域**命名,`subagent-goal` 是按**执行者**命名。按作用域应为 `subtask-goal`。当前按提出时的原词 `subagent-goal` 记录,若要统一改为 `subtask-goal`,全局换一个词即可。 | |
| 101 | + | |
| 84 | 102 | > **决策沿革**(完整过程见 [27-REQ](./27-requirement.md) R-10 / R-12):最初选 `task-`,理由是"`goal` 被 OKR 占用";§六 把 OKR 正名后该理由失效,改用"验收跟着一次 task 执行走"继续保留 `task-`;最终因上面的基数论证推翻,定为 `goal-`。 |
| 85 | 103 | |
| 86 | 104 | --- | ... | ... |
docs/todo/system-design/27-p2-org-graph.md
| ... | ... | @@ -98,7 +98,7 @@ CREATE UNIQUE INDEX IF NOT EXISTS idx_org_graph_edges_dedupe_active |
| 98 | 98 | 与 work graph 的执行前校验同一套规则([27-P3/P4](./27-p3-p4-work-graph-console.md) §四.A): |
| 99 | 99 | |
| 100 | 100 | 1. **无环**(仅针对 `edge_kind='forward'`)—— 三色 DFS,复用 DevLoop `doc-store.js:167` 的 `hasCycle()` 实现。 |
| 101 | -2. **单一入口** —— 必须恰好有一个入度为 0 的 forward 节点(任务从这里进入)。多入口会让"任务从哪开始"无法确定。 | |
| 101 | +2. **单一入口**(✅ 已定案,见 [27-REQ](./27-requirement.md) R-13)—— 必须恰好有一个入度为 0 的 forward 节点,任务从这里进入。多入口会让"任务从哪开始"无法确定,且需要任务入口多带一个参数。 | |
| 102 | 102 | 3. **可达性** —— 每个节点都必须从入口可达,孤立节点直接拒绝。 |
| 103 | 103 | 4. **回退边必须显式标注** —— 任何指向"拓扑序更早节点"的边,`edge_kind` 必须是 `backward`;引擎独立复核,不信任标注(27 号文档 §3.4 第 5 点的同款兜底)。 |
| 104 | 104 | |
| ... | ... | @@ -110,13 +110,18 @@ CREATE UNIQUE INDEX IF NOT EXISTS idx_org_graph_edges_dedupe_active |
| 110 | 110 | |
| 111 | 111 | 新增 system agent 模板 `system/templates/orggraph-planning/`(`config.json.type` 取 `meta-bootstrap`,与业务角色区分)。工作流: |
| 112 | 112 | |
| 113 | -1. **读输入**:公司 `id` / `name` / `description`(由 §4.4 的首轮消息带入)。 | |
| 113 | +1. **读输入**:公司 `id` / `name` / **`goal`(company-goal)** / `description`(由 §4.4 的首轮消息带入)。 | |
| 114 | + `company-goal` 是「这家公司要达成什么」,`description` 是「这家公司是干什么的」——前者是规划流水线的主依据,后者是背景。见 [27-NAMING](./27-naming-conventions.md) §四。 | |
| 114 | 115 | 2. **读候选骨架**:`ls system/org-graph-templates/`,逐个读取,理解各自的 `whenToUse`。 |
| 115 | 116 | 3. **读可招角色**:`node bin/lemon.js company templates`(复用现成 CLI,`listTemplates()` 返回 id/name/type/description)。 |
| 116 | 117 | 4. **规划**:综合三者,产出一张 workflow —— 节点列表 + 执行流边。允许裁剪、替换、组合多个模板,也允许判断需要一个模板库里没有的新角色。 |
| 117 | 118 | 5. **落盘规划记录**:`workspace/orggraph-plan.md`(图 + 为什么这么设计的理由),供事后审计。 |
| 118 | 119 | 6. **提交图**:调用 §4.3 的整体写入 API,图通过 §3.3 校验后落库。 |
| 119 | -7. **执行招聘**:按拓扑序对每个节点调 `hire()`。模板不存在的角色走既有 `needs_training` 分支(自动触发 agent-creator + innovator,`company.js:917-940` 已实现)。 | |
| 120 | +7. **执行招聘**:按拓扑序对每个节点调 `hire()`。 | |
| 121 | + - **模板已存在** → 走 P1 虚拟引用寻址,不拷贝 `agent.md`。 | |
| 122 | + - **模板不存在** → **从 `system/templates/base/` 元 agent 继承出骨架**(自动带上 base 的 `RESEARCH → PLAN → EXECUTE → VERIFY` 四段式生命周期),再由 `agent-creator` 填充该角色特有的定义。这是 [27-E2E](./27-e2e-task-execution-flow.md) §八bis「所有 node agent 由元 agent 继承生成」在 P2 的落地点——**不是**直接走现有的 `needs_training` 全量培养分支。 | |
| 123 | + - **新建 agent 的 `scope`**:一律默认 `scope='company'`、`owner_company_id` 为本公司(27 号文档 §3.2)。升级为 `public` 走既有的 benchmark ≥95 门槛,不在 P2 范围内。 | |
| 124 | + - **训练是可选的后置步骤**:建成后可手动触发 `innovator` 培养,也可按公司需求配置为自动触发。P2 只保证「角色能被建出来且带四段式骨架」,不强制等训练完成。 | |
| 120 | 125 | 8. **收尾**:关闭自己的心跳转入休眠。后续增量调整归 HR。 |
| 121 | 126 | |
| 122 | 127 | `orggraph-planning` 自己**不出现在它规划的 org graph 里** —— 它是基础设施角色,类比 `agent-creator` / `innovator`。 |
| ... | ... | @@ -134,6 +139,7 @@ v0.2/v0.3 设计的 `hire(companyId, roleName, {reportsTo})` **不再需要**。 |
| 134 | 139 | | `POST /api/company/:companyId/org-graph` | **整体写入**:接收 `{nodes:[], edges:[]}`,过 §3.3 四项校验,事务性落库。校验失败返回 400 + 具体哪条规则不满足(供 `orggraph-planning` 读错误后自行修正重试) | |
| 135 | 140 | | `PATCH /api/company/:companyId/org-graph` | **增量修改**:加/删节点、加/删边(后续 HR 调整用)。同样过校验——改完之后整张图仍须合法 | |
| 136 | 141 | | `GET /api/company/:companyId/org-graph` | **只读**:返回 `{nodes, edges}`,只含 `status='active'` 的行 | |
| 142 | +| `POST /api/company/:companyId/org-graph/replan` | **重跑规划**:对已有公司手动再触发一次 `orggraph-planning`(§六 存量公司补图的入口)。异步,立即返回;agent 跑完后通过上面的 POST 写入新图 | | |
| 137 | 143 | |
| 138 | 144 | `GET` 返回形状: |
| 139 | 145 | |
| ... | ... | @@ -164,7 +170,7 @@ if (bootstrap.status === 'hired_from_template') { |
| 164 | 170 | fetch(`http://127.0.0.1:${PORT}/api/agent/orggraph-planning/chat`, { |
| 165 | 171 | method: 'POST', headers: { 'Content-Type': 'application/json' }, |
| 166 | 172 | body: JSON.stringify({ |
| 167 | - message: `公司 ${id}(${name})已创建。描述:${description || '(未填写)'}\n请按 orggraph-planning 工作流规划并建立这家公司的 workflow。`, | |
| 173 | + message: `公司 ${id}(${name})已创建。\n公司目标(company-goal):${goal || '(未填写)'}\n公司描述:${description || '(未填写)'}\n请按 orggraph-planning 工作流规划并建立这家公司的 workflow。`, | |
| 168 | 174 | conversationId: `orggraph-bootstrap-${id}-${Date.now().toString(36)}`, |
| 169 | 175 | }), |
| 170 | 176 | }).catch(e => console.error('[Create] orggraph-planning 触发失败:', e.message)); |
| ... | ... | @@ -215,17 +221,19 @@ if (bootstrap.status === 'hired_from_template') { |
| 215 | 221 | |
| 216 | 222 | | # | 任务 | 文件 | 依赖 | |
| 217 | 223 | |---|---|---|---| |
| 224 | +| **T0** | `company.json` 新增 `goal`(company-goal)字段;`create({id,name,goal,description})`;`POST /create` 与前端建公司表单同步 | `server/services/company-service.js`、`server/routes/company.js`、前端建公司表单 | 无 | | |
| 218 | 225 | | **T1** | schema:节点加 `status` / `reports_to_node_id`;DROP 全量唯一索引改建部分索引;**DROP 重建 `org_graph_edges` 为执行流边** | `server/services/graph-db.js` | 无 | |
| 219 | 226 | | **T2** | `org-graph-service.js`:图的整体写入(含 §3.3 四项校验)、增量改、只读查询、节点软删除级联失效边 | `server/services/org-graph-service.js`(新增) | T1 | |
| 220 | -| **T3** | 三个 API 端点(POST / PATCH / GET) | `server/routes/company.js` | T2 | | |
| 227 | +| **T3** | 四个 API 端点(POST / PATCH / GET / POST …/replan) | `server/routes/company.js` | T2 | | |
| 221 | 228 | | **T4** | `system/org-graph-templates/{dev,content,ops}.json` | 新增 | 无,可并行 | |
| 222 | 229 | | **T5** | `system/templates/orggraph-planning/` agent 本体(含 §4.1 八步工作流) | 新增 | T3, T4 | |
| 230 | +| **T5b** | 「从 base 元 agent 继承 + agent-creator 填充」的招聘分支(§4.1 第 7 步),含新建 agent 的 `scope='company'` 落库 | `server/services/company-service.js`、`server/services/graph-service.js` | T1 | | |
| 223 | 231 | | **T6** | `/create` 路由接入自动招聘 + 异步触发 | `server/routes/company.js` | T5 | |
| 224 | 232 | | **T7** | `/fire` 路由接入节点软删除(改路由 handler 本体,**不是** `CompanyService.fire()`——后者只有测试脚本在用,是死代码路径) | `server/routes/company.js` | T2 | |
| 225 | 233 | | **T8** | 前端:复用 P3 画布组件渲染 org graph(或先上纯文本拓扑序占位) | `web/src/views/CompanyDashboard.vue` | T3(+ P3 的 T3 若要画布) | |
| 226 | 234 | | **T9** | 测试:`org-graph-service.test.js`(四项校验各一条负例、幂等写入、软删除级联)+ e2e 扩展 | `server/tests/unit/org-graph-service.test.js` | T2, T3 | |
| 227 | 235 | |
| 228 | -**顺序**:T1→T2→T3 是主干。T4 可最早并行。T5 依赖 T3/T4。T7 独立于 T5/T6,可并行。T8 视是否等 P3 画布决定。 | |
| 236 | +**顺序**:T0 独立可先做(它是 `orggraph-planning` 的输入前提)。T1→T2→T3 是主干。T4 可最早并行。T5 依赖 T3/T4。T7 独立于 T5/T6,可并行。T8 视是否等 P3 画布决定。 | |
| 229 | 237 | |
| 230 | 238 | --- |
| 231 | 239 | ... | ... |
docs/todo/system-design/27-requirement.md
| ... | ... | @@ -148,7 +148,7 @@ |
| 148 | 148 | |
| 149 | 149 | **落点**:[27-NAMING](./27-naming-conventions.md) §六 |
| 150 | 150 | |
| 151 | -**要点**:体系整体从 `goal` 改为 `okr`;且当前第 1 层节点也叫 "Goal" 是一处自我遮蔽,建议正名为 `Objective`(`O-001`),成为标准的 Objective → Key Result → Sub-Task 三层。代码层是真实数据迁移(9 条 API 路径 + `data/companies/{cid}/goals/` 磁盘目录 + `G-` ID 前缀写在已有 JSON 里),已给影响面清单,未执行。 | |
| 151 | +**要点**:体系整体从 `goal` 改为 `okr`;且当前第 1 层节点也叫 "Goal" 是一处自我遮蔽,建议正名为 `Objective`(`O-001`),成为标准的 Objective → Key Result → Sub-Task 三层。代码层已于 commit `74ea1ff` **实施完毕**(`okr-service.js`/`routes/okr.js`、`/api/okr` + 旧路径别名、`scripts/migrate-goals-to-okr.js` 迁移脚本、7 例单测)。 | |
| 152 | 152 | |
| 153 | 153 | --- |
| 154 | 154 | |
| ... | ... | @@ -170,6 +170,44 @@ |
| 170 | 170 | |
| 171 | 171 | --- |
| 172 | 172 | |
| 173 | +## R-13 · P2 需求审计中的四个定案 | |
| 174 | + | |
| 175 | +针对「P2 是否兑现原话」的逐条比对,四个分叉的定案回答,逐条照搬。 | |
| 176 | + | |
| 177 | +### R-13.1 · goal 分三层 | |
| 178 | + | |
| 179 | +> 公司的目标是公司的 goal 叫做 company-goal ,任务的目标叫做 task-goal ,还有每一个子任务的目标叫做 subagent-goal,应该这么叫吧? | |
| 180 | + | |
| 181 | +**落点**:[27-NAMING](./27-naming-conventions.md) §四「goal 是三层递归的」、[27-P2](./27-p2-org-graph.md) §4.1 第 1 步 | |
| 182 | + | |
| 183 | +**澄清了什么**:R-12 说的「一个人类需求描述只有一个 goal」,指的其实是三层里的 **`task-goal`**。三个验收 agent(`goal-benchmark` / `goal-test-data` / `goal-test-script`)保持通用,不按层级拆分——在哪一层调用就为那一层的 goal 产出标准,与 R-9.2 元 agent 继承一致。 | |
| 184 | + | |
| 185 | +**待定(不阻塞)**:`subagent-goal` 是按执行者命名,另两个按作用域命名,轴不一致;按作用域应为 `subtask-goal`。当前按原词记录。 | |
| 186 | + | |
| 187 | +### R-13.2 · 公司类型由 agent 推断 | |
| 188 | + | |
| 189 | +> 完全由 orggraph-planning 推断 | |
| 190 | + | |
| 191 | +**落点**:[27-P2](./27-p2-org-graph.md) §4.6(模板是起点集合,不是代码里的 `switch(type)`) | |
| 192 | + | |
| 193 | +**推翻了什么**:审计时我把「不给 company.json 加枚举 type 字段」记为「我擅自偏离了 R-3 原话(原话把类型列为输入)」。本条确认 LLM 推断正是所需,**当前设计无需修改**,那条自我记过的缺陷不成立。 | |
| 194 | + | |
| 195 | +### R-13.3 · 新 agent 从元 agent 继承 | |
| 196 | + | |
| 197 | +> 从 base 元 agent 继承 + agent-creator 填内容,建成后可以手动或者根据 company 的需求设置自动innovator 培养训练 | |
| 198 | + | |
| 199 | +**落点**:[27-P2](./27-p2-org-graph.md) §4.1 第 7 步、§五 T5b | |
| 200 | + | |
| 201 | +**这是 R-9.2 在 P2 的落地点**:模板不存在的角色,先从 `system/templates/base/` 继承骨架(自动带上 `RESEARCH → PLAN → EXECUTE → VERIFY` 四段式),再由 `agent-creator` 填充角色定义——**不是**直接走现有的 `needs_training` 全量培养分支。训练是可选后置步骤,可手动触发或按公司需求配置自动。新建 agent 一律 `scope='company'`。 | |
| 202 | + | |
| 203 | +### R-13.4 · org graph 强制单入口 | |
| 204 | + | |
| 205 | +> 强制单入口(推荐) | |
| 206 | + | |
| 207 | +**落点**:[27-P2](./27-p2-org-graph.md) §3.3 第 2 条(原为 open question,现已定案) | |
| 208 | + | |
| 209 | +--- | |
| 210 | + | |
| 173 | 211 | ## 附 · 需求 → 设计落点 速查 |
| 174 | 212 | |
| 175 | 213 | | 需求 | 一句话 | 主要落点 | |
| ... | ... | @@ -186,3 +224,4 @@ |
| 186 | 224 | | R-10 | 统一命名前缀 | NAMING 全文 | |
| 187 | 225 | | R-11 | OKR 正名,不叫 goal | NAMING §六 | |
| 188 | 226 | | R-12 | **验收产物定名 `goal-`**;goal 唯一、task 多个 | NAMING §四 | |
| 227 | +| R-13 | goal 三层(company/task/subagent);类型由 agent 推断;新 agent 从 base 继承;强制单入口 | NAMING §四 / P2 §3.3 §4.1 §五 | | ... | ... |
server/routes/company.js
| ... | ... | @@ -21,7 +21,7 @@ const scheduleService = new ScheduleService(); |
| 21 | 21 | // POST /api/company/create |
| 22 | 22 | router.post('/create', async (req, res) => { |
| 23 | 23 | try { |
| 24 | - const { id, name, description } = req.body; | |
| 24 | + const { id, name, goal, description } = req.body; | |
| 25 | 25 | if (!id || !name) return res.status(400).json({ error: 'id 和 name 为必填项' }); |
| 26 | 26 | |
| 27 | 27 | // 校验 id 格式 (小写字母、数字、-) |
| ... | ... | @@ -29,7 +29,7 @@ router.post('/create', async (req, res) => { |
| 29 | 29 | return res.status(400).json({ error: 'id 格式无效 (只允许小写字母、数字、-)' }); |
| 30 | 30 | } |
| 31 | 31 | |
| 32 | - const company = companyService.create({ id, name, description }); | |
| 32 | + const company = companyService.create({ id, name, goal, description }); | |
| 33 | 33 | |
| 34 | 34 | res.json({ success: true, company, message: '公司已创建,当前为没有员工的空壳公司。请通知 MasterBot 从 Template 库中雇佣 Agent 到你的团队中。' }); |
| 35 | 35 | } catch (err) { | ... | ... |
server/services/company-service.js
| ... | ... | @@ -33,9 +33,12 @@ class CompanyService { |
| 33 | 33 | |
| 34 | 34 | /** |
| 35 | 35 | * 创建一家新公司 |
| 36 | - * @param {object} opts - { id, name, description } | |
| 36 | + * @param {object} opts - { id, name, goal, description } | |
| 37 | + * goal company-goal:这家公司要达成什么(定性,OKR 树的输入,orggraph-planning 规划流水线的主依据) | |
| 38 | + * description 这家公司是干什么的(背景) | |
| 39 | + * 两者的区分见 docs/todo/system-design/27-naming-conventions.md §四 | |
| 37 | 40 | */ |
| 38 | - create({ id, name, description = '' }) { | |
| 41 | + create({ id, name, goal = '', description = '' }) { | |
| 39 | 42 | const companyDir = path.join(DATA_DIR, id); |
| 40 | 43 | if (fs.existsSync(companyDir)) { |
| 41 | 44 | throw new Error(`公司 ${id} 已存在`); |
| ... | ... | @@ -51,6 +54,7 @@ class CompanyService { |
| 51 | 54 | const company = { |
| 52 | 55 | id, |
| 53 | 56 | name, |
| 57 | + goal, | |
| 54 | 58 | description, |
| 55 | 59 | status: 'creating', // creating → running → paused → shutdown |
| 56 | 60 | createdAt: now, |
| ... | ... | @@ -120,6 +124,7 @@ class CompanyService { |
| 120 | 124 | if (!company) return null; |
| 121 | 125 | |
| 122 | 126 | if (updates.name !== undefined) company.name = updates.name; |
| 127 | + if (updates.goal !== undefined) company.goal = updates.goal; | |
| 123 | 128 | if (updates.description !== undefined) company.description = updates.description; |
| 124 | 129 | if (updates.status !== undefined) { |
| 125 | 130 | company.status = updates.status; | ... | ... |
-
mentioned in commit cd897c803c1d9c6d1253fea8c0f51cc8e7353e5f
-
mentioned in commit 70a4727630e1078249e7cf67a62ea799d077865c