|
| 1 | +# FKG Gaps Fix — SOLID 改进方案 |
| 2 | + |
| 3 | +> **Driver:** 逐模块推演发现 5 个 P0-P4 缺口。本计划按优先级修复。 |
| 4 | +
|
| 5 | +--- |
| 6 | + |
| 7 | +## P0: Orchestrate 排序方向修正 |
| 8 | + |
| 9 | +### 问题 |
| 10 | + |
| 11 | +`entity → REQUIRES → security` 被理解成"Entity 依赖于 Security"→ Security 排在 Entity 前。 |
| 12 | +但实现顺序是:先建 Entity,再配置 Security 规则。 |
| 13 | + |
| 14 | +### 根因 |
| 15 | + |
| 16 | +`Orchestrate()` 使用 outbound REQUIRES 边构建依赖图: |
| 17 | + |
| 18 | +```go |
| 19 | +// 当前 (错误) |
| 20 | +for _, e := range q.graph.Edges(info.node.ID, mxgraph.Outbound, concepts.Requires) { |
| 21 | + info.deps[targetID] = true // Entity.deps = {security: true} → security 先 |
| 22 | +} |
| 23 | + |
| 24 | +// 修正 |
| 25 | +for _, e := range q.graph.Edges(info.node.ID, mxgraph.Inbound, concepts.Requires) { |
| 26 | + // security 的入边: entity→REQUIRES→security → security.deps = {entity: true} |
| 27 | + info.deps[sourceID] = true // 谁 REQUIRE 我,我就是依赖谁 → 我先 |
| 28 | +} |
| 29 | +``` |
| 30 | + |
| 31 | +### 方案 |
| 32 | + |
| 33 | +`guidance.go` — `Orchestrate()` 中把 `Outbound` 改为 `Inbound`,1 行改动。 |
| 34 | + |
| 35 | +```go |
| 36 | +for _, e := range q.graph.Edges(info.node.ID, mxgraph.Inbound, concepts.Requires) { |
| 37 | + sourceID := string(e.From) |
| 38 | + ... |
| 39 | + info.deps[sourceID] = true |
| 40 | +} |
| 41 | +``` |
| 42 | + |
| 43 | +### 预期效果 |
| 44 | + |
| 45 | +```bash |
| 46 | +$ mxcli onto orchestrate entity microflow page security |
| 47 | +Implementation order: |
| 48 | + 1. Entity ← 无依赖 |
| 49 | + 2. Microflow ← 无依赖 |
| 50 | + 3. Page ← 无依赖 |
| 51 | + 4. Security ← depends on: entity (entity→REQUIRES→security 入边) |
| 52 | +``` |
| 53 | + |
| 54 | +**SOLID:** |
| 55 | +- **S**: 只改 Orchestrate 的依赖方向识别 |
| 56 | +- **O**: 不修改任何接口或类型 |
| 57 | +- **L**: `fkgQuerier` 行为改变但接口不变 |
| 58 | +- **I**: `Orchestrator` 接口不变 |
| 59 | +- **D**: 调用方不受影响 |
| 60 | + |
| 61 | +--- |
| 62 | + |
| 63 | +## P1: 扩展点补充 stepNode |
| 64 | + |
| 65 | +### 问题 |
| 66 | + |
| 67 | +`guide java-action`、`guide js-action`、`guide widget` 无实现步骤(Steps: None)。 |
| 68 | + |
| 69 | +### 方案 |
| 70 | + |
| 71 | +在每个扩展 adapter 中增加 stepNode + 对应 edges。 |
| 72 | + |
| 73 | +**`java_action.go`** 新增: |
| 74 | + |
| 75 | +```go |
| 76 | +stepNode("ja-create", "Create Java Action definition", |
| 77 | + "CREATE OR MODIFY JAVA ACTION with parameters and return type", |
| 78 | + 1, "create", "JavaAction", "...", |
| 79 | + "create or modify java action HD.JA_HashPassword (Password: string not null) returns string { ... }"), |
| 80 | +stepNode("ja-write-code", "Implement Java code", |
| 81 | + "Write imports and code blocks for the Java Action", |
| 82 | + 2, "configure", "JavaCode", "...", |
| 83 | + "imports $$ import java.security.MessageDigest; $$ code $$ ... $$"), |
| 84 | +stepNode("ja-call-from-mf", "Call from microflow", |
| 85 | + "Use CALL JAVA ACTION in microflow expression", |
| 86 | + 3, "wire", "Microflow", "...", |
| 87 | + "call java action HD.JA_VerifyPassword(Password = $Password, HashedPassword = $HashedPassword);"), |
| 88 | +edge("pattern:extend-with-java", "step:ja-create", HasSyntax), |
| 89 | +edge("pattern:extend-with-java", "step:ja-write-code", HasSyntax), |
| 90 | +edge("pattern:extend-with-java", "step:ja-call-from-mf", HasSyntax), |
| 91 | +``` |
| 92 | + |
| 93 | +但 java_action.go 当前没有 pattern 节点。需要先加 pattern: |
| 94 | + |
| 95 | +```go |
| 96 | +patternNode("extend-with-java", "Java Action Extension Pattern", |
| 97 | + "Create Java Action → implement code → call from microflow"), |
| 98 | +edge("java-action", "pattern:extend-with-java", HasPattern), |
| 99 | +``` |
| 100 | + |
| 101 | +同理对 `js_action.go`、`cross_patterns.go`(css-theme)。 |
| 102 | + |
| 103 | +### 预期效果 |
| 104 | + |
| 105 | +```bash |
| 106 | +$ mxcli onto guide java-action |
| 107 | +Patterns: |
| 108 | + Java Action Extension Pattern Create Java Action → implement → call |
| 109 | +Implementation steps: |
| 110 | + 1. [create] Create Java Action definition ... |
| 111 | + 2. [configure] Implement Java code ... |
| 112 | + 3. [wire] Call from microflow ... |
| 113 | +``` |
| 114 | + |
| 115 | +**SOLID:** |
| 116 | +- **S**: 每个 adapter 负责自己的 stepNode |
| 117 | +- **O**: 纯新增数据和 edges,不改已有逻辑 |
| 118 | +- **L**: stepNode 与其他 builder 可互换 |
| 119 | +- **I**: 不影响任何接口 |
| 120 | +- **D**: Guide() 自动消费新步骤 |
| 121 | + |
| 122 | +**改动量:** `java_action.go` +25 行,`js_action.go` +25 行,`cross_patterns.go` +15 行 |
| 123 | + |
| 124 | +--- |
| 125 | + |
| 126 | +## P2: Nanoflow 实现步骤 |
| 127 | + |
| 128 | +### 问题 |
| 129 | + |
| 130 | +`guide nanoflow` 返回 0 patterns、0 steps。Nanoflow 是 Microflow 的子概念但无独立引导。 |
| 131 | + |
| 132 | +### 方案 |
| 133 | + |
| 134 | +在 `microflow_patterns.go` 中增加 nanoflow 专属模式: |
| 135 | + |
| 136 | +```go |
| 137 | +patternNode("nanoflow-quick-create", "Nanoflow Quick-Create Pattern", |
| 138 | + "Client-side object creation: create → commit → return, no server round-trip"), |
| 139 | +stepNode("nf-create", "Create Nanoflow definition", |
| 140 | + "CREATE OR MODIFY NANOFLOW with parameters", |
| 141 | + 1, "create", "Nanoflow", "...", |
| 142 | + "create or modify nanoflow HD.NF_Ticket_QuickCreate (...) returns HD.Ticket as $Ticket { ... }"), |
| 143 | +stepNode("nf-create-object", "Create object client-side", |
| 144 | + "Use create + commit for client-side object creation", |
| 145 | + 2, "configure", "Object", "...", |
| 146 | + "$Ticket = create HD.Ticket (Subject = $Subject, Status = ...); commit $Ticket;"), |
| 147 | +stepNode("nf-return", "Return result", |
| 148 | + "Return the created object to the caller", |
| 149 | + 3, "configure", "Return", "...", |
| 150 | + "return $Ticket;"), |
| 151 | + |
| 152 | +edge("nanoflow", "pattern:nanoflow-quick-create", HasPattern), |
| 153 | +edge("pattern:nanoflow-quick-create", "step:nf-create", HasSyntax), |
| 154 | +edge("pattern:nanoflow-quick-create", "step:nf-create-object", HasSyntax), |
| 155 | +edge("pattern:nanoflow-quick-create", "step:nf-return", HasSyntax), |
| 156 | +``` |
| 157 | + |
| 158 | +### 预期效果 |
| 159 | + |
| 160 | +```bash |
| 161 | +$ mxcli onto guide nanoflow |
| 162 | +Patterns: |
| 163 | + Nanoflow Quick-Create Pattern Client-side object creation |
| 164 | +Implementation steps: |
| 165 | + 1. [create] Create Nanoflow definition ... |
| 166 | + 2. [configure] Create object client-side ... |
| 167 | + 3. [configure] Return result ... |
| 168 | +``` |
| 169 | + |
| 170 | +**改动量:** `microflow_patterns.go` +25 行 |
| 171 | + |
| 172 | +--- |
| 173 | + |
| 174 | +## P3: Entity 属性类型引导 |
| 175 | + |
| 176 | +### 问题 |
| 177 | + |
| 178 | +`guide entity` 有 3 个模式但没有属性类型选择(string vs boolean vs datetime)的引导。 |
| 179 | + |
| 180 | +### 方案 |
| 181 | + |
| 182 | +在 `cross_patterns.go` 中增加 ImplDetail + skill 节点: |
| 183 | + |
| 184 | +```go |
| 185 | +// Entity 属性类型 |
| 186 | +implDetailNode("attr-string", "string attribute", "string(200), string(500), string not null, string(100) not null unique"), |
| 187 | +implDetailNode("attr-boolean", "boolean attribute", "boolean default true, boolean default false"), |
| 188 | +implDetailNode("attr-datetime", "datetime attribute", "datetime — date and time value"), |
| 189 | +implDetailNode("attr-integer", "integer attribute", "integer default 0 — numeric value"), |
| 190 | +implDetailNode("attr-enum", "enumeration attribute", "Status: HD.TicketStatus default Draft"), |
| 191 | +implDetailNode("attr-unique", "unique constraint", "Name: string(100) not null unique — database-level uniqueness"), |
| 192 | +implDetailNode("attr-system-members", "system members", "system members (owner, createdDate, changedDate, changedBy)"), |
| 193 | +``` |
| 194 | + |
| 195 | +并连接到 entity 概念: |
| 196 | + |
| 197 | +```go |
| 198 | +edge("entity", "detail:attr-string", HasSyntax), |
| 199 | +edge("entity", "detail:attr-boolean", HasSyntax), |
| 200 | +edge("entity", "detail:attr-datetime", HasSyntax), |
| 201 | +edge("entity", "detail:attr-integer", HasSyntax), |
| 202 | +edge("entity", "detail:attr-enum", HasSyntax), |
| 203 | +edge("entity", "detail:attr-unique", HasSyntax), |
| 204 | +edge("entity", "detail:attr-system-members", HasSyntax), |
| 205 | +``` |
| 206 | + |
| 207 | +### 预期效果 |
| 208 | + |
| 209 | +```bash |
| 210 | +$ mxcli onto explore entity --depth 1 |
| 211 | +Concept: Entity [...] |
| 212 | + ImplDetail (7): |
| 213 | + string attribute string(200), string(500), string not null |
| 214 | + boolean attribute boolean default true/false |
| 215 | + datetime attribute datetime — date and time value |
| 216 | + integer attribute integer default 0 |
| 217 | + enumeration attribute Status: HD.TicketStatus default Draft |
| 218 | + unique constraint Name: string(100) not null unique |
| 219 | + system members system members (owner, createdDate, changedDate, changedBy) |
| 220 | +``` |
| 221 | + |
| 222 | +**改动量:** `cross_patterns.go` +25 行 |
| 223 | + |
| 224 | +--- |
| 225 | + |
| 226 | +## P4: 知识库课程引导增强 |
| 227 | + |
| 228 | +### 问题 |
| 229 | + |
| 230 | +Module 06 (知识库) 在 `plan` 中只显示 Entity + Security,缺少独立概念节点。 |
| 231 | + |
| 232 | +### 方案 |
| 233 | + |
| 234 | +知识库本身不需要独立适配器——它的核心模式(self-ref-association, many-to-many)已存在。 |
| 235 | +只需在 `curriculum_academy.go` 中补充 TEACHES edges 到现有 skill: |
| 236 | + |
| 237 | +```go |
| 238 | +// 在 academy-06-kb 的 Build 中补充 |
| 239 | +edge("curriculum:academy-06-kb", "skill:manage-security", Teaches), |
| 240 | +``` |
| 241 | + |
| 242 | +## 改动总览 |
| 243 | + |
| 244 | +| 优先级 | 改动 | 文件 | 行数 | |
| 245 | +|--------|------|------|------| |
| 246 | +| P0 | Orchestrate Inbound 依赖 | `guidance.go` | 1 | |
| 247 | +| P1 | Java Action stepNode | `java_action.go` | +25 | |
| 248 | +| P1 | JS Action stepNode | `js_action.go` | +25 | |
| 249 | +| P1 | CSS Theme stepNode | `cross_patterns.go` | +15 | |
| 250 | +| P2 | Nanoflow pattern + steps | `microflow_patterns.go` | +25 | |
| 251 | +| P3 | Entity 属性类型 ImplDetail | `cross_patterns.go` | +25 | |
| 252 | +| P4 | 知识库 skill 补充 | `curriculum_academy.go` | +1 | |
| 253 | +| | **合计** | **7 文件** | **~117 行** | |
| 254 | + |
| 255 | +所有改动都是**纯新增**,符合 OCP(不修改现有逻辑)。 |
0 commit comments