Skip to content

Commit 6737387

Browse files
author
Test
committed
fix(fkg): P0-P4 gaps — orchestrate sort, extension steps, nanoflow, attr types
P0: Orchestrate REQUIRES direction Outbound→Inbound (entity before security) P1: Java Action (4 steps), JS Action (3 steps), CSS Theme (3 steps) P2: Nanoflow Quick-Create Pattern + 4 steps P3: Entity attribute types (7 ImplDetail nodes) P4: Knowledge base curriculum skill reference CLI: explore now displays Pattern, ImplDetail, CodeExtension neighbor groups
1 parent 1dcbcf4 commit 6737387

8 files changed

Lines changed: 385 additions & 7 deletions

File tree

cmd/mxcli/cmd_onto.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ var ontoExploreCmd = &cobra.Command{
189189
for _, n := range result.Nodes {
190190
byLabel[n.Label] = append(byLabel[n.Label], n)
191191
}
192-
for _, label := range []string{"Concept", "SyntaxFeature", "Skill", "Doc"} {
192+
for _, label := range []string{"Concept", "SyntaxFeature", "Pattern", "ImplDetail", "Skill", "CodeExtension", "Doc"} {
193193
nodes := byLabel[label]
194194
if len(nodes) == 0 {
195195
continue
Lines changed: 255 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,255 @@
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(不修改现有逻辑)。

internal/fkg/concepts/cross_patterns.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,23 @@ func (a *CrossPatternsAdapter) Build(_ context.Context, sink mxgraph.EventSink)
3232
extNode("css-theme", "CSS Theme", "Atlas UI CSS variable override: --brand-primary, --border-radius-button"),
3333
skillNode("theme-atlas-ui", "Atlas UI theme customization with CSS variable overrides in theme/web/main.css"),
3434

35+
// ── CSS Theme step nodes ───────────────────────────────────────────────
36+
patternNode("theme-branding", "Branding Theme Pattern",
37+
"Override Atlas UI CSS variables for brand colors and button styles in theme/web/main.css"),
38+
39+
stepNode("theme-locate", "Locate theme file",
40+
"Find theme/web/custom-variables.css (Mendix 9) or theme/web/main.css (Mendix 10/11)",
41+
1, "configure", "ThemeFile", "main.css",
42+
"Edit theme/web/main.css in the project directory"),
43+
stepNode("theme-override", "Override CSS variables",
44+
"Set --brand-primary, --brand-primary-hover, --border-radius-button etc.",
45+
2, "configure", "CSSVariables", "brand colors",
46+
":root { --brand-primary: #1565C0; --brand-primary-hover: #0D47A1; --border-radius-button: 8px; }"),
47+
stepNode("theme-verify", "Verify theme",
48+
"CSS changes do not affect mxcli check — purely visual",
49+
3, "verify", "Theme", "visual check",
50+
"Run the app (mxcli docker check does not validate CSS)"),
51+
3552
// ── ImplDetail nodes ──────────────────────────────────────────────────
3653
implDetailNode("self-ref-assoc", "Self-Referencing Association", "from KB.Category to KB.Category type reference owner default"),
3754
implDetailNode("intermediate-entity", "Intermediate Entity", "Many-to-Many via intermediate entity with two associations"),
@@ -40,18 +57,40 @@ func (a *CrossPatternsAdapter) Build(_ context.Context, sink mxgraph.EventSink)
4057
implDetailNode("system-members", "System Members", "system members (owner, createdDate, changedDate, changedBy)"),
4158
implDetailNode("non-persistent", "Non-Persistent Entity", "create or modify non-persistent entity HD.TicketSearch ( ... )"),
4259

60+
// ── Entity attribute type ImplDetail nodes (P3) ───────────────────────
61+
implDetailNode("attr-string", "string attribute", "string(200), string(500), string not null, string(100) not null unique"),
62+
implDetailNode("attr-boolean", "boolean attribute", "boolean default true, boolean default false"),
63+
implDetailNode("attr-datetime", "datetime attribute", "datetime — date and time value"),
64+
implDetailNode("attr-integer", "integer attribute", "integer default 0 — numeric value"),
65+
implDetailNode("attr-enum", "enumeration attribute", "Status: HD.TicketStatus default Draft"),
66+
implDetailNode("attr-unique", "unique constraint", "Name: string(100) not null unique — database-level uniqueness"),
67+
implDetailNode("attr-system-members", "system members", "system members (owner, createdDate, changedDate, changedBy)"),
68+
4369
// ── Edges: pattern → concept ──────────────────────────────────────────
4470
edge("microflow", "pattern:seed-demo-data", HasPattern),
4571
edge("entity", "pattern:seed-demo-data", HasPattern),
4672
edge("entity", "pattern:self-ref-association", HasPattern),
4773
edge("entity", "pattern:many-to-many", HasPattern),
4874
edge("page", "ext:css-theme", HasExt),
75+
edge("page", "pattern:theme-branding", HasPattern),
76+
77+
// ── Edges: entity → attribute type details (P3) ─────────────────────
78+
edge("entity", "detail:attr-string", HasSyntax),
79+
edge("entity", "detail:attr-boolean", HasSyntax),
80+
edge("entity", "detail:attr-datetime", HasSyntax),
81+
edge("entity", "detail:attr-integer", HasSyntax),
82+
edge("entity", "detail:attr-enum", HasSyntax),
83+
edge("entity", "detail:attr-unique", HasSyntax),
84+
edge("entity", "detail:attr-system-members", HasSyntax),
4985

5086
// ── Edges: pattern → detail ──────────────────────────────────────────
5187
edge("pattern:self-ref-association", "detail:self-ref-assoc", HasSyntax),
5288
edge("pattern:many-to-many", "detail:intermediate-entity", HasSyntax),
5389
edge("pattern:seed-demo-data", "detail:loop", HasSyntax),
5490
edge("pattern:seed-demo-data", "detail:change-object", HasSyntax),
5591
edge("pattern:seed-demo-data", "detail:commit-object", HasSyntax),
92+
edge("pattern:theme-branding", "step:theme-locate", HasSyntax),
93+
edge("pattern:theme-branding", "step:theme-override", HasSyntax),
94+
edge("pattern:theme-branding", "step:theme-verify", HasSyntax),
5695
})
5796
}

internal/fkg/concepts/curriculum_academy.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ func (a *CurriculumAcademyAdapter) Build(_ context.Context, sink mxgraph.EventSi
8787
edge("curriculum:academy-06-kb", "curriculum:academy-05-security", Depends),
8888
edge("curriculum:academy-06-kb", "entity", Teaches),
8989
edge("curriculum:academy-06-kb", "security", Teaches),
90+
edge("curriculum:academy-06-kb", "skill:manage-security", Teaches),
9091
edge("curriculum:academy-06-kb", "pattern:self-ref-association", Teaches),
9192
edge("curriculum:academy-06-kb", "pattern:many-to-many", Teaches),
9293

internal/fkg/concepts/java_action.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,31 @@ func (a *JavaActionAdapter) Build(_ context.Context, sink mxgraph.EventSink) err
3131

3232
skillNode("extend-with-java", "Java Action creation, parameters, return types, external JAR dependencies"),
3333

34+
// ── Pattern ─────────────────────────────────────────────────────────────
35+
patternNode("extend-with-java", "Java Action Extension Pattern",
36+
"Create Java Action definition → implement Java code → call from microflow"),
37+
38+
// ── Step nodes ─────────────────────────────────────────────────────────
39+
stepNode("ja-create", "Create Java Action definition",
40+
"CREATE OR MODIFY JAVA ACTION with parameters, return type, imports and code blocks",
41+
1, "create", "JavaAction", "HD.JA_HashPassword",
42+
"create or modify java action HD.JA_HashPassword (Password: string not null) returns string imports $$ ... $$ code $$ ... $$"),
43+
stepNode("ja-implement", "Implement Java code",
44+
"Write imports and code blocks for hashing, encryption, or custom logic",
45+
2, "configure", "JavaCode", "implementation",
46+
"imports $$ import java.security.MessageDigest; $$ code $$ MessageDigest digest = MessageDigest.getInstance(\\\"SHA-256\\\"); ... $$"),
47+
stepNode("ja-call-from-mf", "Call from microflow",
48+
"Use CALL JAVA ACTION in microflow to invoke the extension",
49+
3, "wire", "Microflow", "VerifyPassword",
50+
"call java action HD.JA_VerifyPassword(Password = $Password, HashedPassword = $HashedPassword);"),
51+
stepNode("ja-deploy-jar", "Deploy external JAR",
52+
"Place third-party JAR files in project's userlib/ directory for Java Action imports",
53+
4, "configure", "Dependency", "bcrypt.jar",
54+
"cp bcrypt-0.9.jar ./userlib/"),
55+
56+
// ── Edges ──────────────────────────────────────────────────────────────
57+
edge("java-action", "pattern:extend-with-java", HasPattern),
58+
3459
edge("java-action", "ext:java-action", HasExt),
3560
edge("java-action", "ext:java-action.bcrypt", HasExt),
3661
edge("java-action", "ext:java-action.sha256", HasExt),
@@ -39,5 +64,10 @@ func (a *JavaActionAdapter) Build(_ context.Context, sink mxgraph.EventSink) err
3964
edge("java-action", "skill:extend-with-java", HasSkill),
4065
edge("java-action", "microflow", RelatedTo),
4166
edge("java-action", "entity", RelatedTo),
67+
68+
edge("pattern:extend-with-java", "step:ja-create", HasSyntax),
69+
edge("pattern:extend-with-java", "step:ja-implement", HasSyntax),
70+
edge("pattern:extend-with-java", "step:ja-call-from-mf", HasSyntax),
71+
edge("pattern:extend-with-java", "step:ja-deploy-jar", HasSyntax),
4272
})
4373
}

0 commit comments

Comments
 (0)