Skip to content

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

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

[Pull Request] Dev=v6-grammar#296
StardustSeemsInk wants to merge 410 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

## 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 全绿,无回归。
…/BsRenderer 重写 + round-trip)

## Lens 模式
- Lens/ILens.cs: ILens<TView,TDelta> 双向接口(Project + Diff),Diff 留 Phase 6 IrDiff

## BS 解析层(A 级直接复用,9 文件迁移到 Lens/BsTextLens/)
- BsParser.cs(716行 Superpower combinator 近乎原样): 28 条 EBNF 产生式 → BSExpression AST + BlockDefinition
- BlockStructureRecognizer.cs / BlockLinker.cs / CommentAnchor.cs / RecognizedBlock.cs / BlockScriptWellKnown.cs: 纯 namespace 适配
- SemanticAnalyzer.cs: V1-V7 校验 + L147 修复(fc.FunctionName=='ForLoop' → Registry.Get?.Kind==ControlFlow && is ForLoopFunction)
- DiagnosticSink.cs(新增): 包装 List<LoweringDiagnostic>,保持旧 AddError/AddWarning API
- BsTextLensParser.cs(新增): 编排器(recognise→parse→assemble→link→validate)

## BsLowerer(B 级算法借鉴重写,消灭 BS2CFGConverter 713 行 + PipelineFlattener 201 行的 Smell)
- 消灭 _currentContext 隐式字段 → 用 LoweringContext 显式传参
- 消灭 ForwardConversionState 散弹 → LoweringInput/LoweringResult/PubVarAllocator
- **关键简化**:新 IR 的 IrPipelineStatement 保留结构化 AST(Sources+Segments),不 flatten!故 BsLowerer 比 BS2CFGConverter 简单得多——BSPipeline(AST)→IrPipelineStatement 对等转换,不做嵌套调用展开为 PubVar 序列(那是消费方 CFG2CS/执行器按需 flatten 的事,独立纯函数)
- ExpandExpression 重写为 proper BSExpression visitor

## BsRenderer(B 级算法借鉴重写,消灭 CFGRenderer 386 行的 Smell)
- 消灭 BuiltinFunctionRegistry.Instance 静态单例 → 构造注入
- 合并 Render/Generate 双路径为单一 visitor
- **关键简化**:新 IR 携带结构化 pipeline AST,故不需要 FoldCapacitors/FoldChain(旧版要把 flatten 后的 PubVar 序列折回 > 形式;新版直接从 Sources+Segments 渲染)
- IrControlFlowStatement → Branch/ForLoop/Switch/Goto/Break/Exit 文本

## BsTextLens
- 实现 ILens<string,string>: Project(ir)→BsRenderer.Render, Parse(bsText)→BsParser+BsLowerer

## 测试(41 新增,累计 112 全绿)
- BsParserTests(20): 字面量/pipeline/>多目标链/pass-through tap/Branch/ForLoop/Switch/ConstBlock/PubVarBlock/注释/错误诊断(BS_NESTED_CALL/BS_ILLEGAL_ASSIGNMENT 等)
- BsTextLensRoundTripTests(21): BS→IR→BS 语义等价(Print/赋值/pipeline/控制流/嵌套 block/稳定 fingerprint)

## IrDiff 占位
- Ir/IrDiff.cs: Phase 6 placeholder(BsTextLens.Diff 签名需要)

旧 KitX.Workflow 测试 143 全绿,无回归。
…函数重写 + Layout 继承)

## IrDiff 不可变 diff 模型(替换 Phase 5 占位)
- Ir/IrDiff.cs: IrDiff record(BlockChanges/StatementChanges/PositionsChanged/IsEmpty),BlockChange(Name/Kind/NewBlock),StatementChange(BlockName/Fingerprint/Kind/NewValue/NewIndex/FromIndex/ToBlock),DiffKind enum(Added/Removed/Modified/Moved)

## IrDiffer(A 级 LCS 算法近乎原样复用)
- Diff/IrDiffer.cs: static Compute(oldIr, newIr)
- 复用旧 CfgDiffer 三层结构:block 级 diff(by name) → per-block statement LCS → off-LCS 配对分类(same→Move/diff→Modify/未配对→Remove/Add)
- LCS 算法(LongestCommonSubsequenceIndices DP 双向回溯)字面移植,仅类型 string→IrFingerprint
- 增强:跨块 move 检测(Removed 的 fingerprint 若在另一 common block 作 Added 出现 → 配对为 Moved+ToBlock)

## IrDiffApply(C 级 mutation → A 级纯函数重写)
- Diff/IrDiffApply.cs: static Apply(ir, diff) → 新 IrWorkflow
- 绝不 mutate 输入:空 diff 返回引用相同输入(Assert.Same 验证)
- 用 with 表达式 structural sharing:按块重建 Statements,重建 IrBlock,重建 IrWorkflow
- Successors/Targets 清理:删块时纯函数重建其他块的 Successors(移除指向被删块的边)+ control-flow Targets(置空)
- 修复 MoveToImmutable 陷阱:跳过项时 Count<Capacity 抛异常,统一用 ToImmutable()

## Layout 继承(计划 §7 关键路径)
- Apply 第三趟纯函数后处理 InheritLayouts:对每个结果块重建 Layout annotations
- 保留块锚点 BlockPos + 仅保留 fingerprint 仍在结果块的语句的 layout
- Modified 语句因 fingerprint 变了,旧 layout 自动丢弃
- 保证 BS 编辑后未变节点的 BP 位置不丢失

## 连接 ILens.Diff
- BsTextLens.Diff 真实实现:BsLowerer.Lower(newBs) → IrDiffer.Compute(oldIr, newIr)

## 测试(18 新增,累计 130 全绿)
- IrDiffTests: 空 diff/Added/Removed/Modified/Moved/PositionsChanged/跨块 move/加块删块/纯函数性(输入引用相等+结构相等)/Successors 清理/Layout 继承(未变保留+块锚点保留+Modified 不继承)/Diff→Apply round-trip

旧 KitX.Workflow 测试 143 全绿,无回归。
…me 整合 + 端到端执行,填上旧库 ICfgExecutor 空白)

## 后端架构
- Backend/IExecutionBackend.cs: 可插拔执行后端接口(Name + ExecuteAsync(IrWorkflow, LoweringResult?, CancellationToken))
- Backend/RoslynBackend/RoslynExecutionBackend.cs: IExecutionBackend 实现,编排 Codegen→ScriptCompiler.Compile→加载→new ExecutionGlobals→RunAsync

## CFG2CSConverter 1021行 static God module 拆解
- RoslynExprBuilders.cs: 纯 SyntaxFactory builder(ResolveArgumentExpression/BuildConvertToInvocation/BuildGetInvocation/BuildGInvoke/BuildValueAssignment/BuildPluginCall*/GenerateDebugCheckpoint/EmitDefault)——无 static mutable IsDebugMode
- CodeGenContextFactory.cs: 把 RoslynExprBuilders 方法注入 CodeGenContext 的 init 委托(消灭旧 CSEmitContext 对 CFG2CSConverter static 的依赖)
- TypeInferer.cs: 两遍 PubVar 类型推断算法保留;清除 ForwardConversionState 泄漏,签名改用 LoweringResult
- IrCodegen.cs: IR→CompilationUnitSyntax 编排器(ConvertTo 方法 + helper 函数 + RunAsync while-switch dispatcher)
- FlattenPipeline.cs: 纯函数 Flatten(IrPipelineStatement)→FlatPipelineStep 列表(把结构化 AST 展开为 imperative 序列,消费方按需 flatten)
- ScriptCompiler.cs: LoadOrCompile template method 保留,合并 4 重载为单一 Compile 入口
- ScriptCompilationBackend.cs/CollectibleAssemblyLoadContext.cs/ScriptPersistenceManager.cs/CompiledScriptEntry.cs/CompiledScriptMeta.cs/ICompiledBlockScript.cs: 直接迁移(namespace 适配)

## Runtime(整合旧 partial 扩散)
- Runtime/ExecutionGlobals.cs: 合并的 runtime(G),变量存储+NextBlock+全部 builtin runtime 方法(Print/Pause/Branch/ForLoop/Switch/Goto/Flip/Break/Exit/Get/Set/StringConcat/JSON×7/PluginCall/Service×10)——消灭旧 ~20 文件 partial 扩散,直接实例方法分派
- Runtime/BlockScope.cs/BlockScopeManager.cs: 直接迁移
- Runtime/IPluginHost.cs: 替换旧 is RealPluginManager 类型嗅探的主机抽象
- ForLoop counter 改实例字段(消灭旧 static 跨实例泄漏)

## 设计胜利
- 消灭 static mutable IsDebugMode(改注入参数)
- 消灭 ForwardConversionState 泄漏(TypeInferer 用 LoweringResult)
- 消灭 partial 扩散(runtime 整合为单一 ExecutionGlobals + 直接方法分派)
- 消灭 is RealPluginManager 类型嗅探(IPluginHost 抽象)

## 测试(15 新增,累计 145 全绿)
- RoslynBackendTests: 代码生成(Print→G.Print/while-switch/StringConcat/Branch terminator)、FlattenPipeline(纯调用/赋值/TryGetAssignmentTarget)、TypeInferer(Branch→bool/StringConcat→string/常量类型)、端到端执行(Print输出/两次Print/FallThrough顺序/Goto+Exit控制流)
- 端到端执行真实跑通(含 Roslyn 编译+加载+ForLoop 状态机)

旧库 ICfgExecutor 的 throw NotImplementedException 空白已填补。旧 KitX.Workflow 测试 143 全绿,无回归。
…ranslator 消除硬编码)

## BpRenderer(B 级,从新 IR 完整实现 §11,旧版只做 §11.1/§11.3)
- Lens/BpGraphLens/BpRenderer.cs: Blueprint Render(IrWorkflow)
- §11.1: 每 IrBlock→BlockNode(entry→EntryNode),标题/注释从 IrAnnotation(Comment),Exec 输入 pin
- §11.2(新增,旧版故意 out-of-scope): ForLoop index→EntryPointNode(loop body 内),IrBlockVars→内部 VariableNode(BlockVar),作 BlockNode 子图节点
- §11.3: control-flow terminator Targets→Exec 输出 pin(True/False/LoopBody/LoopEnd/Exec/Default/0..N),Sequential fall-through→FallThroughTarget
- §11.4: 数据边正确溯源到产生值的语句节点(**修复旧版 SourceNodeId 占位 hack**)
- 坐标: IrAnnotation(Layout) BlockPos→block 节点 X/Y;fingerprint 键→per-statement X/Y
- 自定义节点模板: registry.GetBpRenderer(name)?.RenderToBp 或默认 BuiltinFunctionNode

## BpEditTranslator(完全新写,消灭 DashboardToCfgName 硬编码)
- Lens/BpGraphLens/BpEditTranslator.cs: IrDiff Translate(IrWorkflow, IReadOnlyList<BpEditAction>)
- 9 种 BpEditAction→IrDiff(AddNode→Added/DeleteNode→Removed/MoveNodeToBlock→Moved/SetNodeArgument→Modified/SetControlFlowArm→Modified(targets)/AddBlock/RenameBlock/DeleteBlock→BlockChange/MoveNodePosition→PositionsChanged)
- **BP 名称→IR 名称通过 registry.GetBpReverseByBpName(bpName)**(ForLoop 的 Loop→ForLoop 已 Phase 4 注册),绝不再用 DashboardToCfgName 字典
- 产出 IrDiff(调用方 Phase 9 负责 IrDiffApply),不直接 mutation baseline

## BpNodeIds.cs
- 确定性节点 ID 方案(block→block:name, statement→stmt:DeriveStableId, pubvar/const/blockvar/loopindex),跨 BS re-parse 稳定

## BpGraphLens
- 实现 ILens<Blueprint, IReadOnlyList<BpEditAction>>: Project+BpEditTranslator,构造注入 registry

## 测试(26 新增,累计 171 全绿)
- BpGraphLensTests: §11.1 block 节点/注释、§11.3 控制流 Exec 边(Branch/ForLoop/Goto/Switch)、§11.4 数据边溯源、坐标、BpEditTranslator 各 action→IrDiff、反射断言无 DashboardToCfgName 字典

## TODO(留 Phase 9)
- ConnectData/Disconnect 数据连线编辑:IrDiff 无边级操作,留 Phase 9(BP 数据线在重渲染时从 statement diff 重新推导)

旧 KitX.Workflow 测试 143 全绿,无回归。
## Session 层(编排 BS/BP 编辑→IrDiff→Apply→IrChanged)
- Session/IrChangeSet.cs: record(StatementDiff/AffectedBlocks/PositionsChanged),CollectAffectedBlocks 工具
- Session/WorkflowSession.cs: 持有不可变 IrWorkflow(每次编辑替换引用非 mutation),HelperFunctions,IrChanged 事件,ApplyChange
- Session/SyncService.cs: 顶层协调器
  - ApplyBsEdit: BsTextLens.Parse(新文本) → IrDiffer.Compute(oldIr,newIr) → IrDiffApply.Apply(纯函数,Layout 继承) → session.ApplyChange → IrChanged
  - ApplyBpEdits: BpEditTranslator.Translate → IrDiffApply.Apply → session.ApplyChange
  - 两路径收敛于 IrDiffApply 纯函数,BS 编辑后未变节点的 BP 位置不丢失(§7 要求)

## 设计胜利
- 替换旧 Conversion.BsSyncService + Blueprint.BpEditApplier 双类为单一 SyncService
- 双向编辑(BS/BP)走统一 IrDiff 管线,无 special-case 分叉
- Layout 继承由 IrDiffApply 统一处理(已在 IrDiffTests 单测覆盖)

## 测试(6 新增,累计 177 全绿)
- SyncServiceTests: 相同文本/空 action→空 changeSet、AddNode→Added+IrChanged 触发、IrChanged 携带 changeSet、空 BS re-parse→entry block、session 持有最新 IR

旧 KitX.Workflow 测试 143 全绿,无回归。

注:解析器命名 entry block 为 'MainBlock'(# 是源标记),非 '#MainBlock'。
## Phase 12-prep:旧库归档(Package/Archive/)
- KitX.Workflow/ + Test.Xunit/ + Tools/ 移至 Package/Archive/(保留代码作参考)
- 从 KitX.sln 移除这 3 个项目
- KitX.Core.csproj: 注释旧库 ProjectReference
- KitX.Core/DI/CoreServiceCollectionExtensions: 注释 AddKitXWorkflow() 调用(功能不连接但编译过)
- 旧文档归档至 Package/Archive/Docs/

## Phase 11:新库 DI 入口
- KitX.WorkflowIR/Hosting/ServiceCollectionExtensions.cs: AddKitXWorkflowIR() 注册 BuiltinFunctionRegistry(反射发现)/BsTextLens/BpGraphLens/SyncService/IExecutionBackend(RoslynExecutionBackend)

## Phase 12:namespace 重命名
- KitX.WorkflowIR → KitX.Workflow(81 个 .cs + csproj RootNamespace)
- 项目名/程序集名保持 KitX.WorkflowIR(避免破坏 sln 路径)
- 与归档旧库同名 namespace 无冲突(旧库不编译)

## Phase 10:Contract record 重设计(跳过,按用户约束)
- Contract 节点模型仍为 mutable class(26 文件含 Dashboard Avalonia 绑定依赖,record 重设计威胁编译保证)
- 子模块未动
- 留待前端重构期

## 编译保证(硬性验收通过)
- dotnet build KitX.sln: 0 错误,37 警告(均既有/stub 相关)
- dotnet test KitX.WorkflowIR: 177 全绿
- Dashboard 4 处旧库引用已 stub 化(编译过,运行期待前端迁移)

## 架构文档
- Package/IR-Architecture-v6.0.md(不可变 IR + Lens + 内容寻址 Diff + 可插拔后端 + 迁移对照 + TODO)

子模块:KitX Dashboard(stub 化解耦),KitX Standard(未动)。

greenfield 重构完成。新 KitX.Workflow(namespace) 库功能完备,旧库已归档。
Track J — JSON 端到端链路迁移:
- J1: 移植 JsonElementExtensions(AsJsonElement/HasValue)到新库 Conversion/
- J2: PluginCall/PluginCallWithTarget 返回引脚 PinType.Any→Json;ExecutionGlobals
  归一化返回值为 JsonElement;ConvertTo<T> 补 JsonElement 特判分支
- J4: PinType.Json 端口蓝色(#4FC3F7)+ ConstTypeToPinType 补 json 映射
- J5: 10 项端到端测试(PluginCall→JsonArrayAt→JsonGetField→JsonAsString→Print)

附带修复:BuiltinEmitHelpers.FlatArguments 原读 pipeline 末尾 segment,但赋值
语句末尾是 Variable tap(无参数),导致 [FunctionCall, Variable] 语句生成无参数
调用。修复为查找最后一个 FunctionCall segment。

Track F — Dashboard Phase F1 接线(子模块指针更新):
- F0.1-F0.2: 项目引用 + AddKitXWorkflowIR + NodeFactory + IPluginHost 适配器
- F1.1: 移除 INodeRegistry/IBlueprintRenderDataService/IBlockScriptExecutor 孤儿依赖
- F1.2-F1.3: BS↔BP 双向转换用 Lens.Project 接线
- F1.6: WorkflowSession 从 BS 源构造

验证:dotnet build KitX.sln 0 错误;dotnet test 187 通过(177 原有 + 10 新增)

# Date: 2026-07-11
# Author: StarInk
…7 子模块更新

IExecutionBackend 新增 4 参数 ExecuteAsync 重载(接受 IBlueprintDebugController);
RoslynExecutionBackend 实现该重载:Compile 时 isDebug=true 生成 checkpoint 调用,
ExecutionGlobals.Debugger = debugger 使生成的代码在每条语句间触发断点/步进/暂停。

子模块 Dashboard 更新(F1.4-F1.7):
- F1.4: BP 编辑回流(AddNode/DeleteNode/ConnectData/MoveNodeToBlock/SetControlFlowArm)
- F1.5: RealBlueprintDebugger 真实现 + RunWithDebugAsync 接线
- F1.7: 删除 WorkflowStubs.cs(stub 全部移除)

验证:dotnet build KitX.sln 0 错误;dotnet test 187 通过

# Date: 2026-07-11
# Author: StarInk
… + VM 高亮映射简化

根因:debug codegen 在 checkpoint 传 stmt.Fingerprint.Value(如 Print("hello")),
而 canvas 节点 ID 是 "stmt:" + DeriveStableId(block, fp, ordinal)(12 位 SHA-256)。
两者不同,导致 _statementToNodeId 映射为空且从未被填充,单步高亮失效。

修复(方案 A):
- IrCodegen.cs: per-block ordinal 计数与 BpRenderer.RenderStatementNodes 逐字节一致,
  checkpoint 直接传 "stmt:" + DeriveStableId,消除映射表需求
- BlueprintEditorViewModel.cs: OnDebugNodeExecuting/Executed 直接用 statementId
  作 BlueprintNodeId 查询;移除 _statementToNodeId 字段 + SetDebugNodeMapping
- RoslynBackendTests.cs: 新增 3 项测试验证 debug checkpoint id 格式
  (190 项全绿 = 187 原有 + 3 新增)
根因:BpEditTranslator 的 ConnectData/Disconnect case 是空实现,且 BpRenderer
.RenderDataEdges 只画输出→PubVar 的 tap 连线,不画 PubVar→输入 的消费连线。
导致画布上从变量节点拖线到节点输入引脚后,IR 不立即更新、连线不可见。

修复(方案 2:Translate ConnectData → SetNodeArgument):
- BpEditTranslator.cs: TranslateConnectData 解析 SourceNodeId 前缀取变量名,
  ResolvePinIndex 通过 registry 的 InputPorts 按端口 title 匹配出数据 argument
  索引(跳过 Execution 端口,与 SetNodeArgument 的索引语义一致),复用 WithArgument
  生成 StatementChange(Modified)。Disconnect 保持 no-op(VM 无生产者)
- BpRenderer.cs: RenderDataEdges 增加消费连线扫描——遍历 statement 的 head
  FunctionCall argument literals,命中已知 PubVar 名则画 PubVar→stmt 连线,
  用 (src,tgt,var) 三元组去重避免与 tap 连线重复
- BpGraphLensTests.cs: 新增 3 项测试(ConnectData 翻译 / 未知 pin no-op /
  消费连线渲染),193 项全绿(190 + 3 新增)
- 主设备让位/观察仅接受已授权设备(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 删除
C-1..C-6/C-13/C-14/C-15: ① EncryptStringAsync RSA-only 分支改用目标设备公钥 + UTF-8 字节数判定;② DI 双 SecurityManager 改工厂单例;③ _signedDeviceTokens 改 ConcurrentDictionary+反向索引,AddDeviceToken 收紧 internal;④ token 移入 Authorization header(保留 legacy query fallback);⑤ ConfigLoadTrail.log 写盘删除(收敛 Log.Debug);⑥ 死配置/死常量删除;⑦ EventService 逐处理器异常隔离+重复订阅覆盖;⑧ ActivityManager 去 UI 图标依赖+确定性 Id+时间戳注册表;⑨ 统计键 yyyy.MM.dd+旧键迁移+原子写;⑩ KeyHookManager 字典并发安全;⑪ DeviceHttpClient 连接池限制;⑫ 端口回退链统一/NetworkSerialization 收敛/HttpClient 复用。
C-7..C-12/C-15: ① _plugins 改 ConcurrentDictionary+名称索引+volatile IsRunning;② 进程 Exited 监控(崩溃清理+通知去重);③ FindConnection(PluginInfo) 改按 Name 匹配;④ DevicesOrganizer ConcurrentQueue+循环重启+Dispose;⑤ PluginHostAdapter 9 个 stub 桥接真实服务(插件类注入 IPluginService,工作流类 Lazy 延迟解析避 DI 注册顺序);⑥ csproj 清理(KitX.Contract.CSharp 死引用/死 IVT/DITestProgram);⑦ 插件输出日志降级截断/GeneratePluginId 改 SHA1/Close 收敛 Stop。
C-16: ① 删除 Core 本地 EventArgs/EventNames(已迁入 KitX.Core.Contract.Event),using 全量适配;② 配置接口 IPluginsConfig→IPluginsConf 等全量迁移(消除 Obsolete 别名警告);③ Config_Log.LogLevel 改契约自定义枚举;④ Config_Pages.Device/Market 实现 IDevicePageConf/IMarketPageConf;⑤ 新增测试 12 项(加密边界/并发 token/事件隔离/插件生命周期并发);⑥ Core.Test.Xunit 22→36、DI.Tests 断言 ReferenceEquals 同实例。
W-1/W-2/W-4/W-5/W-7/W-8: ① 非调试路径每 1000 语句+循环体首行插桩取消检查(死循环可 Stop,同步 Invoke 语义保留);② RenderLiteral 非字符串类型严格词法校验(消除任意 C# 注入面),字符串转义复用 KsScalarLiteralCodec;③ NodeId 32 位碰撞确定性消歧(格式 n_XXXXXXXX 不变,零兼容风险);④ RawArgs/RawArguments 双缓存删除(6 写 0 读,Equals 仅比较 Arguments);⑤ 执行/编译错误传播补日志上下文;⑥ ScriptCompiler InnerException 明细。
W-3/W-6/W-9/W-10/W-11 + SeedNodePins: ① BpRenderer 新增 SeedNodePins(契约描述器机制删除的补偿,10 个创建点全覆盖);② KsParseException:解析错误抛异常而非产出残缺 IR(连带修复多行条件头缩进锚点与渲染换行两个隐蔽 bug);③ ExecGraphWalker arm 路径段统一为索引语义;④ TriggerManager 按 workflowId 在途去重;⑤ 存储路径改 AppContext.BaseDirectory + .kcs 10MB 上限 + 威胁模型文档化;⑥ 删除恒 0 的 ExecutedBlockCount 赋值;⑦ 未知函数降级加日志;⑧ 错误传播补日志。
W 组测试:W1CancellationTests(4)/WorkflowOverridesSecurityTests(~25)/NodeIdCollisionTests(4)/ArmScopePathTests(3)/KsParseStrictnessTests(5)/TriggerManagerThrottleTests(2)/StorageServiceSecurityTests(2),并适配 W-5/W-9 行为变更(Print(x)→管道形式等)。基线 581→644 全绿。
…修复(第二轮审查 F 组)

子仓库/目录变更:Standard(契约收敛+哈希修复)、Dashboard(C3 收敛+缺陷修复+拼写统一)、SDK(生成器弃用+清理,含嵌套 Loaders/Plugins);根仓库 Core/WorkflowV6 修复见本仓库内提交。
D-REG: Config_Pages.Device/Market 使用接口类型 IDevicePageConf/IMarketPageConf,System.Text.Json 无法实例化接口 → Load<AppConfig> 抛异常 → 全部配置回退默认值且保存覆盖(日志级别/窗口位置/RanTime 恒 1)。改为具体类型 Config_DevicePage/Config_MarketPage(与 Home/Settings 节一致),显式接口实现适配保持契约不变。顺带删除死配置 EnabledMica/DebugServicesServerPort。
D-REG: ① ConfigurePort(0)(未配置时 NetworkService 传 0)通过 0..65535 校验导致 DevicesServer 绑定随机端口(日志 43286),UDP 广播端口(8888)与实际端口不一致;改为 >0 判断(与 PluginsServer 一致)。② DevicesOrganizer.ObserveMainDevice 内层循环后 break 意外退出外层 while,观察只跑一轮 7 秒即终止;删除 break 恢复持续观察(日志确认 foundMainDevice 后续恢复 True)。
KitX.sln 移除 Kscript.Compiler/Parser/VM 三个已归档项目引用(上轮 slnx 已清,sln 遗漏);Standard 与 Dashboard 子模块提交回归修复(MAC 归一化/配置反序列化/跨线程/端口 0)。
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