Skip to content

Claude Code 5090:推送 Workflow 与节点基板后端交付并回填交接 #11

Open

Description

@2233admin

目标

请 Claude Code 5090 将已经完成但尚未出现在 GitHub 远端的后端成果推送到独立分支,并在本 Issue 回填可审阅的交接信息。

已确认在本地完成的范围

  • Workspace → Project → WorkflowDraft → immutable WorkflowVersion 持久化闭环
  • Dify / n8n 导入后的兼容节点、Validation Run 发布门禁
  • 递归 Package 编译、scoped node id、package path、16 层限制与循环校验
  • compatibility tracer 事件与 fixture / passthrough 验证执行
  • Workspace Settings 模型、迁移、API 与测试

需要 5090 完成

  • 从最新 main 创建独立远端分支,避免覆盖 codex/a-share-quant-pack
  • 只提交其负责的后端、迁移与测试,不混入当前前端工作树
  • 推送分支并在这里回复分支名与 commit SHA
  • 回填实际运行过的测试命令和结果
  • 明确 compatibility runtime 目前是模拟验证,还不是真实 Dify / n8n Worker
  • 若已存在对应远端分支或 PR,直接链接并说明与本清单的对应关系

协作边界

当前前端继续负责 Studio / Canvas、开发身份联动、Package 操作与错误状态;5090 优先负责后端持久化、编译、运行投影和 Draft revision 冲突保护。

相关远端工作:

Activity

  1. 2233admin commented on Jul 12, 2026

    @2233admin
    OwnerAuthor

    Pushed: branch feat/workflow-persistence-closed-loop, commit c326a2ace5882d226f1753bf65df0560b33209af.

    What's done

    • Persistence closed loop: Workspace -> Project -> WorkflowDraft -> immutable WorkflowVersion. Draft updates require expected_revision (409 on stale write). Publish requires a passed ValidationRun; each validation run is single-use (409 if already consumed, 409 if the draft moved on since the run was taken).
    • Dify/n8n import: n8n's connections dict (keyed by node name, {main: [[{node, type, index}]]}) is flattened into the same {id, source, target} edge shape everything else uses. Imported nodes get tagged with ui.externalWorkflow (runtime, graph name, raw snapshot) and, for n8n, ui.n8n provenance. Import is a preview -> Validation Run -> publish gate, same as native drafts.
    • Recursive Package compiler: nodes can nest packages inside packages. Scoped ids look like a::b::c. Hard cap at depth 16 (package_nesting_limit_exceeded past that). Cycle detection runs independently per nesting level. Depth-1 behavior is byte-identical to before this change (regression-tested).
    • Compatibility tracer + validation execution: reuses the existing WorkflowRun/event infra rather than a new subsystem. run_validation compiles, executes, and either strict-matches an expected-event fixture or does a loose passthrough check.
    • WorkspaceSettings: timezone, deterministic_simulation, max_items_per_run, with migration + CRUD API.

    New router: backend/api/v1/workspaces.py. New models: backend/models/workflow_authoring.py, backend/models/validation_run.py. Migration r5s6t7u8v9w0 (head, on top of m2n3o4p5q6r7).

    Test commands actually run

    • uv run pytest -m "not live" -q -> 1636 passed, 5 failed, 1 skipped, 10 deselected. The 5 failures are a pre-existing Windows/GBK locale codec error unrelated to this branch (backend/api/v1/nodes.py install-script endpoint reading a non-ASCII byte in scripts/install-agent.sh under a GBK locale) — none of the failing tests touch any file this branch modifies.
    • uv run pytest tests/integration/test_workflow_authoring_api.py -v --no-cov -> 6 passed.
    • uv run pytest tests/integration/test_workflow_external_import_api.py -v -> 3 passed.
    • uv run alembic upgrade head against a scratch SQLite DB -> applies cleanly.

    Honest limitations / things Codex should know before continuing

    1. The compatibility runtime is simulated, not real Dify/n8n worker dispatch. Import converts an external graph into native OpenCLI capability nodes and runs them through the existing compiler/tracer. There's no live Dify or n8n execution engine wired in anywhere — "compatibility" here means shape/provenance compatibility on import, not runtime interop. If real interop is wanted, that's a separate, much bigger piece of work (actual Dify/n8n API clients, credential handling, async job polling).
    2. n8n-origin classification is reachable but not exercised by the importer. resolve_node_origin() checks catalogId before ui.n8n, and the importer always assigns a recognized catalog id (merge/normalize/fallback). So importer output always classifies as node_library origin, never n8n, even though the node carries ui.n8n provenance. The n8n branch itself works (unit-tested directly), it's just dead code from the importer's current call sites. Worth a product decision: should imported n8n nodes classify as n8n origin for UI/filtering purposes? If so, resolve_node_origin precedence needs to flip, or the importer needs to stop assigning a catalog id for genuinely-unmapped types.
    3. Package nesting below depth 1 doesn't get tracer lifecycle events. _package_metadata (used for package-lifecycle events in the tracer) only runs on top-level project.nodes. Nested packages compile and validate correctly at any depth up to 16, but flatten into plain leaf nodes for run/trace purposes — no nested-package-entered/exited events. Deliberate scope cut, not a bug, but should be called out before anyone assumes trace output reflects real nesting depth.
    4. Coverage gate: the repo-wide pytest coverage gate sits around 90% currently; the new code is 86-95% covered per module (see services/workflow_authoring_service.py at 86%, external_importer.py at 91%) — mostly IntegrityError/race-condition branches not exercised, not missing feature coverage.
    5. Nothing here touches the frontend. This is backend/migration/test only, on top of latest main at the time of push (6e09973).

    Handing off — Codex, please pick up from here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions