Skip to content

[Pull Request] Dev=v6-grammar - #296

Open
StardustSeemsInk wants to merge 400 commits into
dev=mainfrom
dev=v6-grammar
Open

[Pull Request] Dev=v6-grammar#296
StardustSeemsInk wants to merge 400 commits into
dev=mainfrom
dev=v6-grammar

Conversation

@StardustSeemsInk

Copy link
Copy Markdown
Member

What does this PR do?

将 dev=v6-grammar 分支(WorkflowV6 后端库的 v6 语法体系)合并向 dev=main。

本分支承载 v6.0 Workflow 体系的后端实现(KScript 缩进式 DSL ↔ Blueprint 蓝图 1:1 等幂互译)与近期架构重构:

架构重构(消重与死代码清理)

  • Parser 两条管道解析路径(语句版/条件头版)合体为 ParsePipelineCore/ParsePipelineContinuations,消除 ~200 行逐字重复
  • BpReverseTranslator 新增 GraphIndex 图查询门面(O(V+E) 一次性建索引,收敛线性扫描助手与手写入边查找循环)
  • 控制流节点分类收敛至 BpPinNames(IsControlFlowName/IsTerminatorName),消除 4 文件 6 变体语义分叉
  • 节点路径契约集中至 Ir/NodePath.cs(BpRenderer/DebugCodegen 同源,生成文本逐字节不变)
  • 错误码常量化(KsErrors / KsConstraintErrors)
  • ExecutionGlobals 按语义域拆分为 6 个 partial 文件

功能

  • ReverseWithNodePaths:BpReverseTranslator 导出画布节点 → 规范 ID(FNV(path))映射,为断点迁移与 BP 布局持久化铺路

测试

  • 489 个测试全部通过(476 基线 + 13 项新增节点映射回归测试)

Related issues

#289 #291

…BuiltinFunctionDefinition

函数驱动统一模型:所有函数(值产生+控制流)通过单一 IBuiltinFunctionDefinition 注册。
控制流函数不再有独立接口或枚举标签——它们只是 ArgLayout != null 的函数。

## 接口合并
- IFlowControlFunctionDefinition → IBuiltinFunctionDefinition (合并为单一的注册接口)
- IBuiltinFunctionDefinition 新增成员(带 default):
  · FlowControlArgLayout? ArgLayout — Parser 可见的参数布局
  · IReadOnlyList<string> ArmPinNames — 块名 arm 的 pin 名
  · bool IsBlockTerminator — 终止当前块
  · bool HasInternalState — 跨激活持久状态(ForLoop 计数器)
  · string RenderSource(...) — 自我描述为 BS 文本
  · CFGEdgeType GetEdgeType(string) — arm→edge 映射
- FlowControlArgLayout record 移至 IBuiltinFunctionDefinition.cs

## 删除项
- IFlowControlFunctionDefinition.cs — 删除
- FlowControlShape (IBuiltinFunctionSpec) — 删除
- FlowControlType? FlowControlShape (CFGStatement) — 删除
- FlowControlStatement.ControlType — 不再设置(FunctionName 已标识)
- CfgStatementBuilder.FlowControlShape — 删除,改为 FunctionName 查注册表

## 15 处 FlowControlType 枚举判断替换
- BSParser:516  CondJump|IndexDispatch → ArmPinNames.Count > 0
- BSParser:562  IterativeCounted     → HasInternalState
- CFG2CS:98     ConditionalJump      → ConditionExpression != null
- BlockLinker:35 ScriptReturn        → FunctionName == "Exit"
- BlockSerializer:119 枚举5个值      → last is FlowControlStatement
- BP2CFG:411    IterativeCounted     → registry lookup HasInternalState
- BP2CFG:600    UnconditionalJump    → Arms.Count == 1
- BP2CFG:612    ScriptReturn         → Arms.Count == 0
- BP2CFG:717    switch→BranchHeader  → Arms.Count >= 2
- BP2CFG:1120   枚举4个值            → IsBlockTerminator
- BP2CFG:1231-39 (shape,arm)→edge   → def.GetEdgeType(armPinName)
- CFG2BS:227    UnconditionalJump    → Arms.Count == 1
- RenderSource  5分支switch          → fcDef.RenderSource(...) 每个函数自带
- SemanticAnalyzer IterativeCounted  → FunctionName == "ForLoop"

## IPipelineFlattenContext 接口更新
- GetFlowControlShape(string) → bool IsFlowControl(string)
  改为返回布尔值(是否流控),不再返回枚举类型

## CfgStatementBuilder 重构
- 删除 FlowControlShape 字段
- DeriveFingerprint / RenderDefault 改用 FunctionName 查注册表
- Build 不再设置 FlowControlShape

## 5 个流控函数
- class 声明: IFlowControlFunctionDefinition → IBuiltinFunctionDefinition
- 删除 FlowControlShape 声明
- ExitFunction/ForLoopFunction 新增 IsBlockTerminator/HasInternalState

📊 编译: 0 errors
📊 FlowControlType 枚举仍在定义中但大量引用已替换
…ated, unified IBuiltinFunctionDefinition

函数驱动统一模型完成。FlowControlType.cs 删除,IFlowControlFunctionDefinition.cs 删除,
ControlType / FlowControlShape 字段删除。所有流控判别改为属性推导或注册表查询。

## 删除文件 (7 files total across Phases A-C)
- FlowControlType.cs (enum, 5 values → 0)
- IFlowControlFunctionDefinition.cs (merged into IBuiltinFunctionDefinition)
- ControlFlowMapping.cs (shape→name mapping, replaced by registry)
- CFGStatementKind.cs (removed in Phase B)

## 删除字段
- FlowControlStatement.ControlType → FunctionName (已是唯一标识)
- CFGStatement.FlowControlShape → IsBlockTerminator + 注册表查询
- CfgStatementBuilder.FlowControlShape → 注册表查询
- IBuiltinFunctionSpec.FlowControlShape → 删除

## 统一接口
- IBuiltinFunctionDefinition 新增成员: ArgLayout, ArmPinNames, IsBlockTerminator,
  HasInternalState, RenderSource, GetEdgeType
- 6 个流控函数 (Exit/Goto/Branch/ForLoop/Switch/Flip) 实现统一的 IBuiltinFunctionDefinition
- FlowControlArgLayout 移至 IBuiltinFunctionDefinition.cs

## 判别点替换
- BlockSerializer.EndsWithControlFlow: 5值switch → last is FlowControlStatement
- BSParser 条件赋值: FlowControlShape is Xxx → ArmPinNames.Count > 0
- BSParser indexName: == IterativeCounted → HasInternalState
- CFG2CS: == ConditionalJump → ConditionExpression != null
- BlockLinker: != ScriptReturn → ArmPinNames.Count == 0
- CFG2BS: == UnconditionalJump → Arms.Count == 1
- BP2CFG 多处分发 → Arms 计数 / 注册表查询
- SemanticAnalyzer: == IterativeCounted → FunctionName == "ForLoop"

## FlowControlStatement.RenderSource 静态 switch → 删除
- 每个函数的 RenderSource 内化到 IBuiltinFunctionDefinition
- RegenerateSourceCode / RenderForLoopSource / RenderSwitchSource 删除

## CFGStatement 新增 IsBlockTerminator
- CfgStatementBuilder.Build: 从注册表查询 def.IsBlockTerminator 设置到 CFGStatement
- CFGBlock.EndsWithControlFlow: 通过注册表查询

## FlipFunction 升级
- 从遗留的 FlowControlShape 模式改为 ArgLayout + ArmPinNames + RenderSource

## BP2CFG GetEdgeType 简化
- (FlowControlType, PinName) tuple switch → PinName-only switch

## IPipelineFlattenContext 接口更新
- GetFlowControlShape(FlowControlType?) → IsFlowControl(bool)

📊 编译: 0 errors (Workflow), test project 1 error (T28 fixed)
📊 测试: 主链路可编译,详细回归待后续修复
… tests recovered)

根因:CFG2CSConverter 将 "ALL registered builtins" dispatch 的门槛设为
IsBlockTerminator,导致 Print/StringConcat 等值产生函数走 bare-call 路径,
生成无效 C# (CS0103) 而编译失败。

## 修复
- CFG2CS:596  var def = stmt.IsBlockTerminator ? ... : null
         → var def = !string.IsNullOrEmpty(stmt.FunctionName) ? ... : null
  所有注册函数(含值产生)统一走 EmitStatements 描述符派发

- CFG2CS:109  helper 类型推断条件修复
  stmt.FunctionName == null && stmt.IsBlockTerminator
  → stmt.FunctionName != null && FunctionRegistry.Get(...) == null
  (仅对非注册 helper 函数做参数类型推断)

- BSParser 流控判别: { ArgLayout: not null } → fcDef.ArgLayout != null
  (避免 nullable value type 的 pattern match 边界情况)

- IBuiltinFunctionDefinition 新增 IsFlowControl => ArgLayout.HasValue

- CfgStatementBuilder: { ArgLayout: not null } → { IsFlowControl: true }

📊 测试: 53 PASS / 27 FAIL (从 34/46 恢复 19 PASS)
📊 T19-T27 pipeline 执行全部恢复
📊 T28-T36 控制流解析/执行仍待查 (ArgLayout 值类型接口实现细节)
… + IsFlowControl

## 根因
C# 中 `FlowControlArgLayout?` (Nullable<value type>) 接口属性无法被
class 的 `FlowControlArgLayout` (non-null value type) 属性覆盖——
接口 default `=> null` 始终生效。导致所有 `ArgLayout != null` 检查
对控制流函数返回 false。

## 修复
- IBuiltinFunctionDefinition 新增 `bool IsFlowControl => false` (显式 bool)
  6 个流控函数覆写 `IsFlowControl => true` (bool 可被 class 正确覆盖)
- 所有 `definition.ArgLayout != null` → `definition.IsFlowControl`
  (BuiltinFunctionRegistry×3, BP2CFG×3, BS2CFG×4, CfgStatementBuilder×2)
- BSParser 流控判别: `{ IsFlowControl: true }` pattern match
- BSParser BuildFlowControlFromArgLayout:
  `fcDef.ArgLayout!.Value` → `fcDef.ArgLayout is { } layout` 安全提取
- CFG2CS:596 `stmt.IsBlockTerminator ? ... : null`
         → `!string.IsNullOrEmpty(stmt.FunctionName) ? ... : null`
  (所有注册函数走 EmitStatements 派发,不仅是控制流)
- CFG2CS:109 helper 类型推断: 从错误的 IsBlockTerminator 条件
  → 正确检查非注册 helper
- BS2CFG IsFlowControl 接口实现: `_functionRegistry?.Get(...)?.IsFlowControl == true`

## 删除
- IBuiltinFunctionDefinition.FlowControlShape — 从接口 Spec 层删除
- IFlowControlFunctionDefinition.cs — 合并回主接口
- FlowControlType.cs 枚举 — 文件删除
- FlowControlStatement.ControlType — 字段删除
- FlowControlStatement.RenderSource 静态 switch + helpers — 删除
- CFGStatement.FlowControlShape — 字段删除
- CFGStatementKind.cs — Phase B 删除
- ControlFlowMapping.cs — Phase B 删除

## 测试回归修复
T28 (Branch 解析为 FlowControlStatement): 从 FAIL → PASS
T19-T27 (pipeline 执行): 全部恢复 PASS

📊 测试: 57 PASS / 25 FAIL (Phase C 后 34/46, +23 PASS)
📊 剩余: 控制流执行(5) + 往返(6) + 注释(5) + ForLoop index(1) + 编译(2) + 模板(1) + 未分类(5)
## 根因
C# 中 `FlowControlArgLayout?` (Nullable<value type>) 接口属性无法被
class 的 `FlowControlArgLayout` (non-null value type) 属性覆写。
`fcDef.ArgLayout is { } layout` 模式匹配始终返回 false,
导致 BSParser 中所有控制流函数的 FlowArguments 和 Arms 为空。

受影响函数:Branch, ForLoop, Switch, Goto
(ExitFunction 和 FlipFunction 已使用 `FlowControlArgLayout?` 故不受影响)

## 修复
- BranchFunction/ForLoopFunction/SwitchFunction/GotoFunction:
  添加 `FlowControlArgLayout? IBuiltinFunctionDefinition.ArgLayout`
  显式接口实现
- CFG2BSConverter.RenderStatement: 非终止符函数调用使用
  `FuncName(args)` 而非 `Arguments[0]`
- BP2CFGConverter.RegenerateBranchSource: 通过注册表
  RenderSource 重新生成 OriginalExpression(不再返回空值)
- BP2CFGConverter.ConvertBlockStatementToCfgStatement:
  FlowControlStatement case 从节点引脚提取 Arguments
- BP2CFGConverter: 从 blueprint.ConstValues 恢复 PubVar 类型
- CFG2BPConverter: 在 BuiltinFunctionNode.Properties["FlowArguments"]
  中保存流控参数(ForLoop indexName 等)
- BlockScriptToBlueprintConverter: 为已声明未写入的 PubVar
  创建类型元数据(不添加到 AllNodes 以避免重复)
- CFG2CSConverter.ResolveArgumentExpression: 防御性添加
  SyntaxKind.IdentifierToken 守卫

📊 测试: 67 PASS / 15 FAIL (+10 PASS)
📊 剩余: ForLoop CS0103(2) + 往返(6) + 注释(5) + 编译一致性(2)
## 动机
BuildFlowControlFromArgLayout 通过 FlowControlArgLayout 元数据集中
解析所有流控函数的调用参数。这导致两个问题:
1. C# 值类型接口陷阱:FlowControlArgLayout? 无法被 non-nullable class
   属性覆写,需显式接口实现
2. 低内聚:参数布局语义分散在 ArgLayout + ArmPinNames 两处

## 变更
- IBuiltinFunctionDefinition 新增 ParseInvocation(BSCall, int)
  每个流控函数自己解析自己的调用,返回 FlowControlStatement?
  非流控函数返回 null → 走原有 ExpressionStatement 路径
- 6 个流控函数各实现 ParseInvocation:
  Branch(1 expr + 2 blocks)、ForLoop(3 expr + 3 blocks)、
  Switch(1 expr + variadic blocks)、Goto(1 block)、
  Exit(0 args)、Flip(2 blocks)
- BSParser: def.ParseInvocation(call, line) 替代
  BuildFlowControlFromArgLayout(fcDef, call, line)
- 删除 BuildFlowControlFromArgLayout (65行) + ExtractStringArg
- 删除 Branch/ForLoop/Switch/Goto 的显式 ArgLayout 接口实现
  (BSParser 不再通过接口读取 ArgLayout)
- 保留 ArgLayout 属性供 Dashboard UI 签名渲染

📊 测试: 67 PASS / 15 FAIL (零回归)
## 问题
ForLoop 运行时通过 G.Set(indexName, index) 注入循环变量到 _variables
字典,但 C# codegen 不知道这个变量存在 → 生成的 G.Print(i) 中的裸 i
导致 Roslyn CS0103。

## 设计
不是特化 ForLoop,而是由 IBuiltinFunctionDefinition 声明"我会注入哪些变量":
- 接口新增 GetInjectedVariables(CFGStatement) → IReadOnlySet<string>
- ForLoopFunction 实现:从 Arguments[3] 提取 indexName
- CFG2CSConverter.CollectInjectedVariables 通过注册表通用收集
  (零硬编码函数名)
- CSEmitContext.ResolveArgument 对注入变量名生成 G.Get("name")
  而非裸 C# 标识符

## SOLID
- SRP: codegen 只负责"收集 → G.Get",不知具体函数
- OCP: 新函数实现 GetInjectedVariables 即可,codegen 零修改
- DIP: codegen 依赖 IBuiltinFunctionDefinition 抽象

📊 测试: 69 PASS / 13 FAIL (+2: T30, T61)
…容器过滤

## 根因
1. CFG2BPConverter.ProcessStatement 对非终止符内置函数
   (Print/StringConcat) 将 funcDef 设为 null,导致
   ProcessCallOrAssignment 被跳过 → 节点未创建 → BP 缺少节点
2. ExitFunction.ToStatement 未设置 FunctionName
   → RenderStatement 渲染为 "null;"
3. 管道展开产生的电容变量 (vaaa####) 泄漏到 PubVarBlock

## 修复
- CFG2BPConverter.ProcessStatement: 始终解析 funcDef
  (添加 FunctionName null 守卫)
- ExitFunction.ToStatement: 添加 FunctionName = "Exit"
- BP2CFGConverter: PubVarDeclarations 过滤电容变量
  (ExprUtils.TryExtractPubVarCounter == null)
- 清理调试输出

📊 测试: 70 PASS / 12 FAIL (+3: 往返执行输出一致性)
📊 剩余: 管道文本形式(6) + 注释(5) + ScriptHash(1)
…容器过滤

## 修复
- CFG2BPConverter.ProcessStatement: 对非终止符内置函数
  (Print/StringConcat) 解析 funcDef 而非设为 null
  修复管道语句在 BP 中丢失的问题
- ExitFunction.ToStatement: 添加 FunctionName = "Exit"
- BP2CFGConverter: PubVarDeclarations 过滤电容变量
  (TryExtractPubVarCounter == null)
- T43 测试: 将 " = " 检查范围限定在 MainBlock 之后
  (ConstBlock 中的 `string name = "World"` 不应影响判断)

## 剩余问题
往返管道文本一致性需要 BP 模型扩展:
- 管道形式重建 (不可逆电容器展开)
- ForLoop 注入变量在 DataEdgeBuilder 中的识别
- 控制流语句在 BP→CFG→BS 路径中的完整转换
- BlockVars 序列化

📊 测试: 71 PASS / 11 FAIL (+14 from Phase C baseline)
## 变更
- CFGBlock: BlockVars + HasExplicitBlockBody
- BS2CFG/CFG2BS: BlockVars 透传
- BlockScriptSerializer: ##BlockVars / ##BlockBody 渲染
- BlueprintBlockScope: BlockVarEntry list + HasExplicitBlockBody
  (Contract 项目 — 与 Dashboard 共享)
- BlueprintAssembler: CFGBlock.BlockVars → BlueprintBlockScope
- BP2CFGConverter: BlueprintBlockScope.BlockVars → CFGBlock

📊 测试: 71 PASS / 11 FAIL
📊 T48 BlockVars 往返已验证通过
## F-1: BlockVars CFG/BP 全链路
- CFGBlock.BlockVars + HasExplicitBlockBody
- BS2CFG → CFG2BP → BlueprintBlockScope → BP2CFG → CFG2BS → Serializer
  六层全透传
- Contract: BlueprintBlockScope.BlockVars + BlockVarEntry record
- BlockScriptSerializer: ##BlockVars / ##BlockBody 渲染

## F-2: 注入变量识别 + 函数派发
- ForwardConversionState.InjectedVariableNames + DataEdgeBuilder 识别
- ConversionContext.InjectedVariableNames + FormatLiteralValue 去引号
- BP2CFG Step 1.5 从 BP 节点提前收集注入变量
- CFG2BP ProcessStatement: 修复 helper/plugin 函数节点创建
- BranchFunction.ToStatement: 添加 FunctionName

📊 测试: 72 PASS / 10 FAIL (+15 from Phase C baseline)
📊 剩余: 管道文本形式(4) + 注释(5) + ScriptHash(1)
## 新增
- MigrateKcs.cs: CFG JSON 序列化 DTO 层
  - CfgDto / CfgBlockDto / CfgStmtDto / CfgEdgeDto / CfgArmDto
  - ToDto(ControlFlowGraph) / ToCfg(CfgDto) 双向映射
  - PipelineStatement 标记为 Kind="Pipeline"
- Program.cs: --migrate-kcs <path> 命令
  - 读取旧 .kcs → parse BS → CFG → DTO → 写 .cfg.json
  - 验证往返执行一致性

## 设计
CFG DTO 是 CFG 的序列化格式。未来 .kcs 将以此替代
BlockScriptSource + BlueprintData。CFG 成为唯一持久化模型,
BS 和 BP 都是渲染视图。
## G-1: CFG JSON 序列化 + 迁移工具
- MigrateKcs.cs: CFG DTO 层 (CfgDto/BlockDto/StmtDto/EdgeDto/ArmDto)
  - ToDto(CFG) / ToCfg(Dto) 双向映射
  - PipelineStatement 标记 Kind="Pipeline"
- Program.cs: --migrate-kcs <path> 命令
  - 遍历旧 .kcs → parse BS → CFG → DTO → .cfg.json
  - 往返执行一致性验证

## G-2: CFG2BSConverter.Render() 统一渲染
- 新增 Render(ControlFlowGraph) → string (CFG 直接到 BS 文本)
- 管道折叠算法 FoldCapacitors:
  识别 capacitor 链 (vaaa####) → 重构成 > 管道形式
- PipelineStatement 直接渲染 (BSPipeline.RenderPipelineSource)
- 流控语句通过注册表 RenderSource 渲染
- BlockVars / ConstBlock / PubVarBlock 声明渲染
- 删除 CFGBlockRenderer.cs (合并入 CFG2BSConverter)
- Generate() 保留向后兼容 (BlockScript 中间模型)
- MigrateKcs 改用 CFG2BSConverter.Render()

## 验证
--test-renderer: CFG → Render → BS text → Parse → Execute
  输出与原始完全一致 (Hi World, done == Hi World, done)
## 变更
- CFG2BSConverter.Render(ControlFlowGraph) → string
  CFG 直接渲染为 BS 文本,跳过 BlockScript 中间模型
- FoldCapacitors 管道折叠算法
- PipelineStatement 直接 BSPipeline.RenderPipelineSource()
- 流控语句通过注册表 RenderSource 渲染
- BlockVars / ConstBlock / PubVarBlock 声明渲染
- 删除 CFGBlockRenderer.cs (合并入 CFG2BSConverter)
- Program.cs: 新增 CfgRoundTrip (BS → CFG → Render → text)
- TestRoundTrip: T39/T46/T47 改用 CFG 直接路径
- TestCompileConsistency: T69/T70/T71 改用 CFG 直接路径
- --test-renderer 验证: 渲染-执行输出完全一致

📊 测试: 76 PASS / 6 FAIL (+19 from Phase C baseline)
📊 剩余: T48 (块顺序) + T49-T53 (注释)
## 架构变更
CFG 从中间翻译层变为唯一持久化数据模型。
BS 文本和 BP 图都是 CFG 的渲染视图。

## 删除
BlockScriptToBlueprintConverter, BlueprintToBlockScriptConverter,
CFG2BPConverter, BP2CFGConverter, BlueprintAssembler,
DataEdgeBuilder, NodeExportHelper, ConversionContext,
BlockScriptSerializer, IBlueprintConverters,
Arguments/ (ArgumentSourceClassifier)

## 重命名
CFG2BSConverter → CFGRenderer (public class)

## 新增
- CFGRenderer: 统一的 CFG → BS 文本渲染器
- CfgRoundTrip: CFG 直接往返路径 (BS → CFG → Render)
- BSParser.ExtractComments: 注释提取算法

## 更新
- ConversionPaths: 简化为 BS2CFG + CFG2BS 两个路径
- BlueprintService: 适配新架构
- ServiceCollectionExtensions: 移除旧转换器注册
- 所有测试类签名简化 (移除 converter/reverseConverter 参数)

📊 测试: 77 PASS / 5 FAIL (+20 from Phase C baseline)
## 注释保留 (T49-T53)
- BSParser.ExtractComments: 注释提取算法重写
  - 顺序匹配:独立注释按顺序分配到语句
  - 内联注释:匹配同行的语句
- BlockStructureRecognizer: 捕获 #Block 前的 // 块级注释
- RecognizedBlock.BlockComment → BlockDefinition.Comment
- CFGBlock.BlockComment 全链路传递
- CFGRenderer: 块级注释在 #Block 前渲染
- BS2CFG.FormatFlowControl: FlowControlStatement.Comment 传递

## T48 BlockVar
- 测试源调整为主块优先顺序 (CFG 规范)
- BlockDefinition.Comment 传递至 CFGBlock.BlockComment

## 旧架构清理 (Phase G)
- 删除 12 个旧转换器/状态文件
- CFG2BSConverter → CFGRenderer (public)
- 测试项目简化——移除 converter/reverseConverter 参数
- --migrate-kcs CFG 迁移工具
- CfgRoundTrip: CFG 直接往返路径
- Package/CFG-Architecture-v5.1.md: 架构设计文档

📊 测试: 82 PASS / 0 FAIL (起始 57 → +25)
## G-4: KcsFileFormat.CfgData
- Contract 项目新增 CfgDto 系列 DTO 类
- KcsFileFormat.CfgData 字段

## G-5: 存储层 (JSON 自动序列化 CfgData)
- SaveKcsFileInternalAsync 自动序列化 CfgData
- 无需额外代码——CfgDto 是简单 POCO

## G-6: --migrate-kcs 正式迁移
- 遍历 Data/workflows/*.kcs → parse BS → CFG → CfgData
- 往返执行验证 (前后输出一致)
- 自动备份 (.bak) + 覆盖写入
- 3/5 文件迁移成功

## 注释全链路 (T49-T53)
- ExtractComments 顺序匹配算法
- BlockStructureRecognizer 块级注释
- CFGBlock.BlockComment → CFGRenderer 渲染
- FlowControlStatement.Comment 丢失修复

📊 测试: 82 PASS / 0 FAIL (起始 57 → +25)
v5.1 把 BP 降为 CFG 的渲染视图后,旧的 BP→BS/BS→BP 装配管线被删,但大量
生产者代码残留(接口成员、字段、实现、分析器),形成"生产者无消费者"的死代码。
本轮按设计审查 R1 批次做机械清理,零功能回归(console harness 保持 82 PASS / 0 FAIL)。

主要清理:
- IBuiltinFunctionDefinition 删除 Layer D 整层(IBuiltinFunctionExporter:ToStatement/
  GetOutputArms/OnNodeCreated/ConfigureNode/GetOutputPinsFor/GetReuseKey)+ 死的 BP-node
  成员(NodeKind/ArmPinNames/AutoSynthesizePubVar/HasInternalState/GetEdgeType)+
  BuiltinNodeKind 枚举;24 个内置函数文件删除对应死 override 方法
- ForwardConversionState 删除 12 个死字段 + 5 个死结构体(DeferredControlFlowEdge/
  PubVarAssignment/SubAssignment/PendingExecEdge/PendingDataEdge),只留 BS→CFG→CS 活路径用的 9 个字段
- 删孤儿:ReachingDefinitionsAnalysis(235行)、IBlueprintToBlockScriptConverter、
  INodeExportHelper、OutputArmDescriptor
- 删 BlockScript.LoopBlocks v5.0 残留 + executor 死读
- 删 4 处死 StripQuotes(ConfigureNode 删除后成孤儿)
- BlueprintService 两个空转 stub 改 throw NotImplementedException,避免静默返空
为前端三项新功能(最小化 Diff 同步 / 折叠缩略图 / 并排 Diff 高亮)的后端前置能力
编写 TDD 红灯测试。红灯 = 断言期望行为但当前失败(功能未实现或存在真实缺陷)。

新增 xUnit 项目 KitX.Workflow.Test.Xunit(与现有 console harness 并列,互不干扰),
含 WorkflowFixture(复用 AddCoreServices DI)+ TestData(helper 声明)。

四套红灯测试(共 16 个:11 红 / 5 绿):
- A 稳定 ID 往返:1 红灯抓到真缺陷——0 > currentLoop 往返后变 currentLoop(0),
  指纹不稳定(diff 引擎的前置条件被破坏,需后续修复)
- B CFG→BP 渲染器:4 全红,引用新接口 ICFGGraphRenderer(G-3 被搁置阶段,从未实现)
- C 语义 diff:6 全红,引用新接口 ICFGDiffer + CfgDiff(块名 + 指纹 + Myers 对齐契约)
- D 轻量校验:3 全绿,验证现有 Validate(为并排同步的"保存且校验通过"前置)

新增接口骨架(待后续绿灯实现):
- Conversion/ICFGGraphRenderer.cs(CFG→Blueprint 渲染契约,§11)
- Conversion/ICFGDiffer.cs + CfgDiff/StatementChange/StatementMove(语义 diff 契约)

配套:KitX.Workflow.csproj 加 InternalsVisibleTo(KitX.Workflow.Test.Xunit);
KitX.sln 加入新项目。
✅-Test = test PASS(让测试通过的改动)
❌-Test = test FAIL(引入预期失败测试,如 TDD 红灯)
助记:emoji 镜像该提交后的测试结果。
11 个红灯全部转绿(xUnit 16/0);console harness 回归验证 82/0。

实现内容:
- ICFGDiffer + CfgDiffer.cs:块级身份=Name、语句级身份=Fingerprint、LCS 对齐;
  Move(同身份位移)、Modify(同位异身份)、Add/Remove(单侧无配对)、块增删
- ICFGGraphRenderer + CFGGraphRenderer.cs:最小版——MainBlock→EntryNode、
  pipeline→data 边、#Block→复合 BlockNode;完整 §11(exec 臂/子图/位置复用)留后续
- DI 注册两个新服务(ServiceCollectionExtensions)

往返稳定性 bug 修复(StableIdRoundTripTests.RoundTrip_BS_CFG_BS_CFG_PreservesStructure):
根因不是渲染端,而是 BS2CFGConverter.Format 未把 ConstBlock/PubVarBlock 声明提升进
CFG——渲染出的 BS 丢失 #PubVarBlock 头,重解析后 currentLoop/cond 不再被识别为变量,
pipeline flattener 把它们当函数调用(0 > currentLoop → currentLoop(0))。
- BS2CFGConverter.Format 现在提升声明(幂等 Contains 防重)
- 清理 WorkflowFixture/CfgRoundTrip/MigrateKcs 中冗余的手动后填
- DeriveFingerprint 纯赋值分支统一 fingerprint 公式(与 RenderDefault 一致)

未实现(保持 fail-loud,不在本次范围):
- BlueprintService.ImportFromBlockScript/ExportToBlockScript 仍 throw NIE
  (依赖 BP→CFG 反向路径,更大工作,留后续)
- CFGGraphRenderer 完整 §11 语义(exec 臂、EntryPoint/ExitPoint 子图、LayoutX/Y 位置复用)

验证:
- dotnet test KitX.Workflow.Test.Xunit → 16 PASS / 0 FAIL
- dotnet run KitX.Workflow.Test → 82 PASS / 0 FAIL
10 个测试覆盖 §11 的稳定子集(讨论后收缩范围):
- §11.3 Exec 连线:Goto/Branch/ForLoop/Switch 各自的块间 Exec 连线
  (源引脚名 Exec/True/False/LoopBody/LoopEnd/Default/0/1,PinType.Execution)
- §11.1 Block 节点字段:标题=块名、Exec 引脚、Comment 来自块级注释、
  Exec 输出引脚数=终止符 Arms 数
- §11.3 边界:控制流函数不生成独立 BuiltinFunctionNode

红灯状态(当前最小渲染器未实现 Exec 连线):
- 7 红:Goto/Branch/ForLoop/Switch Exec 连线、Exec pin 类型、
  Exec 输出引脚数、Block 注释
- 3 绿(现有渲染器已满足):BlockNode 标题=块名、BlockNode 有 Exec 引脚、
  控制流不生成独立节点

明确不在本轮范围(见 Blueprint-Editor-Redesign-Plan.md + 本次讨论):
- §11.2 通用 EntryPoint/ExitPoint 数据边界(对 BS 无意义,跨块数据流走 PubVar 全局存储)
- §11.2 ForLoop index EntryPoint(ForLoop 待演进为 Each 集合迭代)
- §11.2 BlockVar 内层 VariableNode(BlockVar 将作为过度设计删除)
- §11.4 auto-temp 长命名(§14.2 待定)
- 位置保留(已确认本轮不做)

验证:dotnet test --filter Section11Tests → 7 失败 / 3 通过(红灯预期)
扩展 CFGGraphRenderer(92 → ~210 行),把 §11 红灯全部转绿:
- 10 个 §11 测试 PASS(xUnit 16→26)

实现内容(CFGGraphRenderer 4 阶段):
1. 块节点:每个 #Block → BlockNode(MainBlock → EntryNode);标题=块名;
   Comment 来自 block.BlockComment(§9.3,#Block 标记上方的 // 行)
2. Exec 引脚 + 连线(§11.3 核心):
   - 控制流终止符(Goto/Branch/ForLoop/Switch)的每个 arm 成为 BlockNode 的一个
     Exec 输出引脚(Name=arm.PinName: True/False/LoopBody/LoopEnd/Default/0..N/Exec)
   - 每条 arm 连一条 Exec 连线到目标块的 Exec 输入引脚
   - 控制流函数不生成独立节点(§11.3 line 650)
   - Sequential fall-through(无显式终止符)→ 到 FallThroughTarget 的 Exec 连线
3. 数据边(保留现有):PubVarTarget 语句 → PubVarName 标记的数据连接
4. BlockScope 元数据:Name/IsMainBlock/NextBlockName/HasExplicitBlockBody
   (不填 BlockVars — 该类别将作为过度设计删除)

明确不在本轮(见 Blueprint-Editor-Redesign-Plan.md + 设计讨论):
- §11.2 通用 EntryPoint/ExitPoint(对 BS 无意义)
- §11.2 ForLoop index EntryPoint(待 Each 演进)
- §11.2 BlockVar 内层 VariableNode(将删)
- §11.4 auto-temp 长命名(§14.2 待定)
- 位置保留(已确认本轮不做)

验证:
- dotnet test KitX.Workflow.Test.Xunit → 26 PASS / 0 FAIL
- dotnet run KitX.Workflow.Test → 82 PASS / 0 FAIL(无回归)
把手写 console 测试框架(KitX.Workflow.Test,82 测试)整体迁移为 xUnit,
与现有 KitX.Workflow.Test.Xunit 合并;两个 CLI 工具落进新建的 KitX.Workflow.Tools 项目。

测试迁移(1:1 语义保持,T00–T80):
- 新增 3 个 xUnit 文件:
  · ParseAndDiagnosticsTests.cs(T00-T38/T54-T60:parsing/blocks/pipeline/diagnostics)
  · RoundTripAndControlFlowTests.cs(T39-T53:round-trip/comments/control-flow)
  · ExecutionAndBuiltinsTests.cs(T61-T80:execution/compile-consistency/builtins)
- WorkflowFixture 扩充共享 helper:ExecuteScript(DI→parse→compile→run)、
  TextEquals(忽略空行的逐行比较)
- 翻译规则:check→Assert.True(bool,label)、fail→Assert.Fail、pass→无断言
- 删除 KitX.Workflow.Test 项目(含手写 Program.Main harness、shouldRun 过滤、
  delegate 回调等脆弱基础设施)

新建 KitX.Workflow.Tools(开发期/运维 CLI 工具):
- --kcs <path|dir>:加载 .kcs,优先走 v5.1 CfgData 路径(ToCfg→render→parse→
  compile→run)验证,旧文件回退 BlockScriptSource 源路径
- --gen-kcs <bs> [--out]:BS 源 → 生成 .kcs(含 BlockScriptSource + 往返验证的 CfgData),
  即"BS→kcs 生成器"(替代原 MigrateKcs 的迁移语义,因已无待迁移旧文件)
- 复用 MigrateKcs 的 ToDto/ToCfg CFG↔CfgDto 映射器
- 修正原 MigrateKcs 的 JSON 读写不一致(写用 camelCase,读用默认 → 现统一 camelCase)
- InternalsVisibleTo 从 KitX.Workflow.Test 改为 KitX.Workflow.Tools

验证:
- dotnet test KitX.Workflow.Test.Xunit → 108 PASS / 0 FAIL
  (26 原 xUnit + 82 迁移自 console)
- dotnet build KitX.sln → 0 错误
- Tools 冒烟:--gen-kcs 生成 3867B .kcs;--kcs 验证 1 ok/0 failed(CfgData 路径)
实现 Package/List-Port-And-Json-Functions-Design.md 的 B1+B2 批次,
为插件返回的富 JSON(如 kxp-Search 的 List<SearchResultItem>)提供一等操作能力。
TDD:16 个红灯测试 → 全绿(xUnit 108→124,无回归)。

B1 — 契约 + 运行时基础:
- PinType.Json(契约层,见 KitX Standard 子模块提交)
- RealPluginManager.MapReturnType:修正"插件集合返回类型静默丢失"的 bug
  —— List<*>/Dictionary<*>/插件 POCO 名此前 fallback 到 typeof(object),
    现映射到 typeof(JsonElement),让 ParseResult<JsonElement> 正确反序列化
- JsonElementExtensions.AsJsonElement:统一"任何 JSON 形态"(JsonElement /
  JSON string / 可序列化对象)为 JsonElement,Clone detached 避免释放后访问
- CFG2CSConverter.InferPubVarTypes:注册的内置函数按 Return 引脚 PinType 推断
  PubVar C# 类型(Json→JsonElement),让 JsonElement 返回值能赋给类型化局部变量
- ScriptCompilationBackend.GetCompilationReferences:种子加入 System.Text.Json
  程序集;CFG2CSConverter 生成代码 using System.Text.Json

B2 — JSON 函数族(7 个,统一 System.Text.Json):
- 重构 JsonGetField:String→String 改为 Any→Json,支持链式取字段 + JsonElement 入参
- 新增 JsonAsString/JsonAsInt/JsonAsBool(标量落地)
- 新增 JsonArrayLength/JsonArrayAt/JsonObjectKeys/JsonContains(数组/对象导航)
- 全部经反射自动注册(BuiltinFunctionRegistry.Discover)

附带修复(被 JSON-in-string-literal 用例暴露的预存 bug):
- BSParser 字符串字面量 SourceText 未转义内部引号 —— "{\"a\":1}" 编译成破坏的
  C# 源码。修正 SourceText = 转义 \ 和 " 后重组。影响所有含内部引号的 BS 字符串常量。

端到端验证靶标:PluginCall 返回 List → JsonArrayAt(0) → JsonGetField("Title")
→ JsonAsString → PubVar(见设计文档 §九)。

后续(不在本次):B3 BS PubVar 声明 json 关键字;B4 Each 集合迭代控制流;
B5 BP 渲染 Json 端口着色。

验证:dotnet test → 124 PASS / 0 FAIL
…cService/BpEditApplier/CfgDiffApplier

## 核心改动

### G4 稳定 ID(内容派生身份)
- CfgStatementBuilder.DeriveStatementId: SHA256(blockName + fingerprint + ordinal) 生成稳定 ID
- BS2CFGConverter: build 每个块后调用 DeriveStatementIds,相同 BS 重 parse 产出相同 StatementId
- 解决旧 Guid.NewGuid() 跨 re-parse 身份不稳定问题

### G5 布局坐标(per-node 位置保留)
- CFGBlock 新增 LayoutX/LayoutY(块级锚点)+ NodePositions(按 StatementId 的 per-node 相对坐标字典)
- CFGGraphRenderer: 从 block.LayoutX/LayoutY 读取坐标写入节点 X/Y,给 var/entry/block 节点补 Id 前缀
- CfgBlockDto 已含 LayoutX/LayoutY

### Session-based 双向编辑模型
- IWorkflowSession + WorkflowSession: 持有单一真相 CFG,CfgChanged 事件
- IBsSyncService + BsSyncService: BS 编辑 → 全量 re-parse → CfgDiffer.Diff → CfgDiffApplier.Apply 回写
- IBpEditApplier + BpEditApplier: 9 种 BpEditAction 翻译为 CFG 就地变异(Decision 2)
- ICfgDiffApplier + CfgDiffApplier: block/语句级增删改移应用
- ICfgBsRenderer/ICfgBpRenderer: 薄适配器,委托既有渲染器
- ICfgExecutor: 占位(throw NotImplementedException,待 greenfield 实装)
- BlueprintService.cs 删除(被 session 抽象替代)

### Diff 强化
- ICFGDiffer 扩展: BlockChange record,StatementChange 增加 NewStatement/Index,StatementMove 增加 FromIndex/ToIndex
- CfgDiffer 适配新签名

### DI 注册
- ServiceCollectionExtensions: 注册 5 个新 v5.2 服务 + ICfgExecutor 占位

### 测试(143 全绿)
- BpEditApplierTests: 7 个 Fact(增删改节点/块)
- BsSyncServiceTests: 4 个 Fact(同步/CfgChanged 事件)
- CfgDiffApplierTests: 6 个 Fact(增删改移/跨块 move 端到端)
- SemanticDiffTests/StableIdRoundTripTests 适配新签名

### 子模块
- KitX Standard: 新增 BpEditAction record 族 + 移除废弃 IBlueprintConverter
- KitX Dashboard: 清理 IBlueprintService 引用(前端下一期处理)

此 commit 建立旧架构稳定基线,作为后续 KitX.WorkflowIR greenfield 重构的回退点与算法参考源。
…mutable CFG 4 件套 C 级债根)

## 新建项目
- KitX.WorkflowIR: net10.0,依赖 Contract + Csharpell.Core + Superpower + Roslyn,不引用旧 KitX.Workflow(新旧无耦合)
- KitX.WorkflowIR.Test.Xunit: 配套测试项目
- 两者加入 KitX.sln,置于 KitX Workflow 解决方案文件夹下

## 不可变 IR 模型(完全重新设计,C 级 → A 级)
- IrWorkflow: record 顶层容器,ImmutableArray/Dictionary;剔除 PubVarCounter(过程态,归 lowering)与 DebugStatementToNodeId(调试态,归 session)
- IrBlock: record,IrBlockKind(Entry|Basic|BranchHeader);坐标移出至 Annotations(消灭旧 CFGBlock LayoutX/Y/NodePositions 视图态混入 IR 的 Smell);Equals 显式排除 Annotations
- IrStatement: sealed hierarchy(IrPipelineStatement + IrControlFlowStatement),消灭旧 CFGStatement 14 个 nullable 判别字段
- IrSegment: pipeline 原子段,纯数据(消灭旧 PipelineStatement 持 converter 闭包的紧耦合)
- IrControlFlowStatement: 统一 Targets 列表,消灭旧 Arms/TrueBlock/FalseBlock/Loopback 四元组
- IrFingerprint: 内容派生身份(替换 Guid.NewGuid() 随机身份)+ DeriveStableId(SHA256 前 12 hex)
- IrAnnotation: Layout/Comment/SourcePosition 元数据分离,IrLayout/IrSourcePosition
- IrEdge: immutable 控制流边(Sequential/BranchTrue/BranchFalse/LoopBody/LoopExit/Break/Switch)
- IrConstant/IrGlobalVar/IrBlockVar: immutable 声明,类型内联(消灭旧 PubVarTypes 平行字典)

## AST 迁移(解析层强依赖,A 级直接复用,class → record)
- Ir/Ast/BsAst.cs: BSExpression 族(BSLiteral/BSIdentifier/BSCall/BSAssignment/BSBinary/BSParenthesized/BSPipeline/BSPlaceholder)+ BSExpressionExtensions
- Ir/Ast/BlockStructure.cs: BlockType/VariableDeclaration/BlockStatement/ExpressionStatement/FlowControlStatement/BlockDefinition/BlockScript

## Util
- PubVarNaming: GeneratePubVarName/TryExtractPubVarCounter(从旧 ExprUtils 迁移,ComputeFingerprint 已移入 IrFingerprint)

## 测试(27 全绿)
- IrModelTests: record 结构相等、不可变、坐标不参与相等、fingerprint 内容派生与 re-parse 稳定、DeriveStableId 确定性、控制流 Targets 统一模型、pipeline 结构化 AST、PubVarNaming 往返

旧 KitX.Workflow 测试 143 全绿,无回归。
…值范式(C 级债根杠杆点)

## 消灭 ForwardConversionState(C 级 Smell 源,13 处引用)
旧 ForwardConversionState 是 grab-bag:同时是入参(Script/HelperFunctions)+Phase1 输出(ConstNodes/VariableNodes/PubVarNames)+Phase2 输出(FormattedScript)+共享可变计数器(NextPubVarCounter)+Diagnostics,被 13 处方法签名按引用传递,任何位置可改任何字段——shotgun-parameter 反模式。

## 新设计:三角色分离
- LoweringInput: immutable 入参(Script + HelperFunctions)
- LoweringResult: immutable 出参(Ir + PubVarTypes + PubVarNames + InjectedVariableNames + Diagnostics),Equals 内容比较
- PubVarAllocator: 受控局部可变助手,封装计数器+累积集合,单一职责,绝不逃逸单次 Lower() 调用
- LoweringContext: 传给 builtin LowerToIr 的上下文(BlockName/FullFunctionName/SourceLine/Allocator),替换旧 LowerContext 对 ForwardConversionState.PubVarNames 的引用泄漏
- LoweringDiagnostic: record,替换旧 ConversionDiagnostics mutable bag

## 设计胜利
lowering 函数签名变为 LoweringResult Lower(LoweringInput)——准纯函数,所有 mutation 局限于自己的 locals。下游 5 个 B 级模块(BsLowerer/CfgDiffer/CFG2CSConverter/CSCompiler/IBuiltinFunction.LowerToCFG)的 Smell 等级因此自动从 B 降向 A。

## 测试(9 新增,累计 36 全绿)
- LoweringTypesTests: record 不可变、PubVarAllocator 唯一电容名/注册/redirect 优化、LoweringDiagnostic record 相等

旧 KitX.Workflow 测试 143 全绿,无回归。
## 新建序列化层
- Serialization/IrDto.cs: DTO record 族(IrDto Version=6.0 / BlockDto / StmtDto / PipelineStmtDto / ControlFlowStmtDto / SegmentDto / PipelineArgDto / ControlFlowTargetDto / EdgeDto / ConstDto / GlobalVarDto / BlockVarDto / AnnotationDto / PositionDto)
- Serialization/IrSerializer.cs: Serialize(IrWorkflow)→string / Deserialize(string)→IrWorkflow,用 System.Text.Json,内部 ToDto/FromDto 双向转换

## 解决旧 CfgDto 两大缺陷
1. Pipeline AST 完整序列化:PipelineStmtDto 携带完整 Sources + Segments(每段含 FunctionName/FullFunctionName/VariableName + Arguments 区分 Placeholder/Literal)——旧 CfgStmtDto 仅存 PipelineSource 文本丢失结构
2. Per-node 位置完整序列化:BlockDto.Annotations(Layout 类型, Key=fingerprint/stableId) 承载 (X,Y)——旧 CfgBlockDto 只有块级 LayoutX/Y,NodePositions 完全不序列化

## 设计决策
- StmtDto 用扁平 Kind 判别字段(Pipeline/ControlFlow)避免多态 JSON 复杂性
- AnnotationDto 用 Kind + 显式字段(LayoutX/LayoutY/Line/Column/Text)承载 object? Value,避免多态转换器

## 模型一致性修复
为 IR 子 record 补 Equals/GetHashCode 重写(ImmutableArray 默认引用相等):IrPipelineStatement/IrControlFlowStatement/IrSegment,使 record 相等性在任意深度生效

## 测试(10 新增,累计 45 全绿)
- IrModelRoundTripTests: 复杂 IrWorkflow(pipeline 多 segment+placeholder / per-node 位置 / 控制流 Branch 2 targets / 常量 / 全局变量)Serialize→Deserialize 结构相等,特别断言 Pipeline AST 完整往返 + per-node 位置完整往返 + 控制流 Targets 完整往返

旧 KitX.Workflow 测试 143 全绿,无回归。
## ISP 接口拆分(消灭旧 IBuiltinFunctionDefinition fat interface)
- Builtin/IBuiltinFunction.cs: 必实现接口(Name/Kind/InputPorts/OutputPorts/InputVariadic/OutputVariadic),FunctionKind(Pure/ControlFlow/SideEffect),PortSpec record
- Builtin/IFunctionHandlers.cs: 5 个按需特征接口 IParserHandler/ILoweringHandler/ICodeGenHandler/IBpRenderHandler/IBpReverseHandler + BpNodeTemplate/BpNodeInfo
- Builtin/CodeGenContext.cs: Roslyn builder 上下文(自包含 Literal/GInvoke/EmitNextBlockAssignment 等;ResolveArgument/EmitValueAssignment/PluginCall*/GetInvocation/ConvertTo 为 init 委托,Phase 7 注入)
- Builtin/BuiltinFunctionRegistry.cs: Discover 反射发现 + per-role 独立 lookup 表(消灭旧 default-interface-method 运行时 override 检查)

## 32 函数迁移(按 Smell 分级)
- A 级直接复用(7): Print/Pause/ReadTextFile/WriteTextFile/Branch/Goto/Exit
- B 级借鉴重写(11): ForLoop/Switch/Flip/StringConcat/Json×8(用 JsonBuiltinBase 抽象基类收敛 7 倍重复 emit)
- C 级专项设计(14): Break/PluginCall/PluginCallWithTarget/TryGetDevice/StartPlugin/StopPlugin/StopWorkflow/CreateWorkflow/RunWorkflow/InstallPlugin/GetPluginInfoByName/ListPluginNames/ListWorkflows

## 解决的 Smell
1. 硬编码 DashboardToCfgName['Loop'] → ForLoop 实现 IBpReverseHandler 声明 BpNames=['Loop'],registry.GetBpReverseByBpName 查找
2. HasInternalState 孤立成员(ForLoop) → 删除
3. GetOutputPinsFor 孤立成员(Switch) → 删除,变长 arm 由 OutputVariadic 声明式驱动
4. ExtractStatement 旧 API 残留(Flip) → 删除
5. is RealPluginManager 类型嗅探(PluginCall) → descriptor 不再嗅探,runtime 留 Phase 7
6. IsNonExtractable 矛盾(StartPlugin/StopPlugin/StopWorkflow 有 Return 却 NonExtractable) → 统一由 FunctionKind 推导
7. TryGetDevice 裸调用无 target → ILoweringHandler + LoweringContext.Allocator.AllocateCapacitor 自生成 PubVar
8. GBK 乱码注释 → UTF-8 重写
9. control-flow 函数 OutputPins 置空(v5.0 §7 规则:control-flow 无 data output pin,臂是结构化控制边)

## runtime 部分留 Phase 7(执行后端)
descriptor 与 runtime 分离:runtime(BlockScriptExecutionGlobals partial)属执行后端,不在本 Phase

## 测试(26 新增,累计 71 全绿)
- RegistryTests: Discover 发现 32 函数、per-role lookup、ForLoop IBpReverseHandler 注册、control-flow 集合、代表性函数角色实现

旧 KitX.Workflow 测试 143 全绿,无回归。
…30 补 const 定义名

- 问题 1(用户报告):const 使用型节点不存在——所有标识符引用渲染为 PubVar 且带 Value 输入 pin,暗示常量可变;且 KS130 的 defVarNames 不含 const 定义名,const 引用触发假违规(临时测试确认)
- BpRenderer:新增 _constNames(渲染时从 ir.Constants 收集);MakeIdentifierUsageNode 对 const 引用设 VarKind=Const 并移除 Value INPUT pin(写入结构性不可能),var 引用保持 PubVar 双 pin;5 处 KsIdentifier 渲染点统一改用
- StructuralReducer KS130:defVarNames 补 ConstNode 定义名 + DictNew DeclName 不限 DeclKind(const dict 引用同享)
- 测试 +4:const 引用 KS130 放行(含 const dict)/ const usage 只读形态与往返空 diff / var usage 保持可写双 pin;525 全通过
- WebSocket 监听 0.0.0.0 → 127.0.0.1(按 kitx-dashboard-network 文档,Loader 与本机同进程,消除 LAN 冒充插件攻击面)
- _connections 由 List 改为 ConcurrentDictionary<ConnectionId, IPluginConnection>,修复 Fleck 多线程回调下 Add/Remove/遍历竞争(FindConnection 顺带 O(1) 化)
- 热路径日志降级(MessageReceived/PluginMessageReceived 改 Debug),删除构造函数 HashCode 调试残留
- 拒绝消息中性化
- 删除解码失败后复制 kxp 源目录全部文件的兜底逻辑(任意文件注入面),失败直接返回
- FinalizeImport 与 StartPluginAsync 对 RootStartupFileName 做 IsPathInsideDirectory 校验,拒绝逃逸插件目录的启动文件
- 新增私有 helper IsPathInsideDirectory(GetFullPath + Ordinal 前缀比较)
- AES 重写:PBKDF2-SHA256(100k) 派生密钥 + 随机 salt/IV + PKCS7(消除 Key=IV 与手写 ExpandKey KDF,删 GetSHA1 死代码)
- 密钥交换:B 端用用户输入密码(A 屏幕读取)解密而非自生成 code;密码错误保持 pending 可重输(加密环文档 F→G 语义)
- 回传仅公钥,私钥永不离开本机;接收方只信任公钥字段
- 交换状态保留至 ExchangeKeyBack 完成统一清理;验证码不再落日志;异常回显中性化
- 主设备让位/观察仅接受已授权设备(IDeviceKeyService.IsDeviceAuthorized),未授权设备的 IsMainDevice 声明仅展示不生效
- ServerBuildTime 补赋值点(AddCoreServices 首个装配点,进程启动时刻)并统一 NetworkHelper/DiscoveryServer 同源读取,修复让位逻辑恒不触发
- _deviceInfosQueue 有界化(1024 上限丢最旧)
- 删除 UpdateSourceAndAddCards(DeviceInfo) 死代码
- Connect/PluginInvoke catch 不再回显 ex.Message(异常细节仅进日志)
- SignInDevice 不再打印 token;DeviceHttpClient URL 日志剥离 query token
- AesSecurityTests(5): 往返一致性/随机 salt-IV/错误密钥拒绝/短密文拒绝
- KxpDecoderSecurityTests(7): ../ 穿越与绝对路径拒绝(Theory)+ 合法包解包
- PluginsServerSecurityTests(5): 回环绑定验证 + 无效连接 ID 拒绝
- DevicesOrganizerTrustTests(2): 未授权伪造主设备不生效 / 已授权触发让位
- 删除 ScriptPersistenceManager 及磁盘分支(消除无校验 DLL 加载、workflowId 路径注入、重复编译三个问题)
- 内存缓存改 LRU(16 条上限),淘汰时卸载 collectible ALC——修复缓存无限增长与 Unload 失效
- 修复缓存 miss 后 Unload 摧毁刚写入缓存条目的隐藏 bug;Compile 签名去除恒 null 的 workflowId
- 新建 Ir/KsScalarLiteralCodec:InvariantCulture 编解码 + 与 Tokenizer 对称的转义表 + 类型判定统一
- 替换 10 个站点(Tokenizer/Parser/KsRenderer/BpRenderer/BpReverseTranslator/CodegenBase/Fingerprint),消除字符串含引号/反斜杠往返损坏与逗号小数文化下 double 漂移
- double 编码补 .0 防重解析漂移 int;参数侧补 null 判定;dict 侧单字符→char 行为按 T8 固化
- 新增 29 个测试(转义对称/文化/往返),554 全绿
- GraphIndex 新增宽松 exec 索引(srcPin-only)与 Nodes 枚举,ScopeAnalyzer/LayoutService/StructuralReducer 复用(消除 4 份重复实现;FindCycle data 模式保留内联并注释原因)
- 新建 ExecGraphWalker 抽象(子作用域递归+End 继续+nodeScope 路径计算),StructuralReducer(KS101 短路/循环栈) 与 ScopeAnalyzer(区域收集/Skip) 改 visitor 模式
- BpReverseTranslator.WalkExecChain 因 pipeline-group 状态机语义保留独立实现(注释说明)
- 逐文件替换逐步验证,554 测试全绿
- 新建 BlueprintNodePredicates:引脚形状/连通性两种定义判定并存共享(语义差异文档化),消除 StructuralReducer 与 BpReverseTranslator 的散落内联
- Parser switch arm 间整行注释不再误报 KS021(注释归属语义与 ParseBody 一致)
- ParseExpression/ParseBody 加 200 层嵌套深度上限,超限报 KS078 而非 StackOverflow 崩溃;补 3 个测试,557 全绿
- StructuredCodegen/CodegenBase 的未知分支由生成注释改抛 InvalidOperationException(编译期炸出,杜绝用户以为执行了的静默失败)
- 顺带修复 DebugCodegen.EmitStatement 无 default 分支的隐蔽静默丢弃
- 新增 CodegenFailureModeTests 4 项(伪造未知语句/节点类型),561 全绿
- WorkflowDiff 扩展声明区(Constants/GlobalVars/HelperFunctions 按 name 对齐的 DeclarationChange),SyncService 声明区编辑不再静默失效(IsEmpty 覆盖声明区)
- StatementChange 增加 OldIndex(LCS 配对信息),Apply 改为按目标索引重建——纯重排 [A,B]→[B,A] 不再产生 [A,A] 错误结果(任何删+插顺序都无法表示重排)
- 新增 17 测试(声明区 diff/重排/Layout 保留),578 全绿
- 删除 ExecutionGlobals 的 GetVar/SetVar/Vars/GetVariableSnapshot(codegen 零调用)、DeriveStableId(已标 Obsolete)、EmitCheckpoint 恒 0 ordinal 参数
- StringConcatMethod 改名 StringConcat,BuiltinToGMethod 别名表整体删除(反射发现机制不受影响)
- JsonAsInt 改 TryGetInt32 回退 double 截断(消除与 JsonElementToObject 的语义矛盾);JsonGetField/JsonContains 抽 TryGetPropertyPath 复用
- 19 处 'Inherited from WorkflowIR' 叙事改 'Ported from archived';not-yet-implemented/476 tests/singleton 等漂移注释纠正
- 新增 E2E_JsonAsInt_From_NonIntegral_Number_Truncates,579 全绿
- LiteralCodecTests(29): 转义对称/文化/往返(B2 遗漏)
- KsTextLensTests +3: switch 注释 KS021/嵌套上限 KS078(B5 遗漏)
- CodegenFailureModeTests(4): 未知语句/节点抛异常(B6 遗漏)
- DiffTests(13) + SessionTests(4): 声明区 diff/重排重建(B7 遗漏)
- WorkflowStorageService/WorkflowSessionManager/TriggerManager 迁入 KitX.WorkflowV6/Services,RealBlueprintDebugger 迁入 Backend/Debugging(按架构文档:业务逻辑归后端,前端只放 UI)
- AddKitXWorkflowV6() 注册 IWorkflowStorageService/IWorkflowManagementService/ITriggerManager,App.axaml.cs 删除对应注册
- 顺带修复 TriggerManager 并发(ConcurrentDictionary + volatile 快照发布)
- Core.DI.Tests 同步去除重复注册,完整 DI 图验证通过
…rdPluginServiceProvider 归位后端

- PluginHostAdapter(含 NoOpPluginManager)与 DashboardPluginServiceProvider 从 Dashboard 迁入 KitX.Core/Plugin(零 UI 依赖,按架构文档归位)
- Core 启用 Kscript.CSharp.Parser 引用(去 Condition=false)+ 新增 WorkflowV6 引用(IPluginHost 接口,无循环依赖)
- Kscript 桥接三注册(IPluginServiceProvider/IPluginManager/IPluginHost)移入 AddCoreServices,App.axaml.cs 删除
- DI.Tests 同步镜像更新,完整 DI 图验证 IPluginHost→PluginHostAdapter 解析成功
…nner

- Core 新增 NetworkService(启动顺序/端口配置/延迟/停止,端口修正 discovery+devices 共用 DevicesServerPort),AppFramework 与 DevicesPageViewModel 改消费接口(删除 3 处强转具体类与 Thread.Sleep 编排)
- WorkflowV6 新增 WorkflowRunner(ApplyConstantOverrides + ExecuteAsync 统一),SessionManager 与编辑器 Run/DebugRun 共用,消除双执行路径
- 新增 WorkflowRunnerTests 2 项,581 全绿
…dException

- 9 个 stub(StartPlugin/InstallPlugin/ListWorkflows 等)由静默假成功改 Log.Warning + NotImplementedException,经 ExecutionGlobals.Service 调用时工作流以可见错误失败,消除难排查的假结果
- TryGetDevice 保留 null('not found' 是接口文档化的合法语义);NoOpPluginManager fallback 行为不变
- KitX.slnx 移除 Kscript.Compiler/Parser/VM,添加 Kscript.Runtime
- KitX.Core.csproj 的 Kscript.CSharp.Parser 引用改为 Kscript.Runtime(命名空间不变,零代码改动)
…atus 重复枚举

- Core 删除零使用的 Microsoft.CodeAnalysis.CSharp.Scripting 与 Csharpell×2(Dashboard 已补直接引用,Serilog.Sinks.Console 补显式引用)
- 删除 ServerStatus 本地枚举(与契约版同值,统一为 Contract.Device.ServerStatus)
- 删除 CheckNewAnnouncements 抛异常方法、DevicesServer.PortChanged 零订阅事件、ConstantTable.IsExchangingDeviceKey/ExchangeDeviceKeyCode 死状态
- Dashboard: Workflow 服务迁出、ServiceLocator 收敛、调试节流、端口 bug、kxp 引用清理
- Standard: kxp 路径穿越修复、INetworkService 契约、Kscript 僵尸系清理(Kscript.Runtime 拆分)、GetSHA1/WorkflowInfo 删除
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants