Refactor/frontend#248
Conversation
…26-04-15_branch-from-refactor-frontend
…26-04-15_branch-from-refactor-frontend
…/2026-04-15_console-web-ui-refactor # Conflicts: # apps/aevatar-console-web/src/pages/teams/home.tsx
…b-ui-refactor Refine Studio workspace recovery and teams home semantics
…26-04-15_branch-from-refactor-frontend
…-fixes Fix/2026 04 17 frontend review fixes
…into-frontend Refactor/2026 04 20 merge dev into frontend
/review 结果:2 个 critical + 4 个 informational整体方向 OK:前端围绕 create-team 草稿流和 scope query-param 做了一轮整理,后端 🔴 CRITICAL1. if (await IsAuthenticationEnabledAsync())
return (null, Unauthorized(...));
return (new AppScopeContext(normalizedRequestedScopeId, "query:scopeId"), null);当
建议:换成显式配置开关( 2. - ScopeWorkflowUpsertResult upsert;
- if (_workflowCommandPort != null) { ... upsert via IScopeWorkflowCommandPort ... }
- else { ... HTTP PUT /api/scopes/.../workflows/{id} ... }
+ await storagePort.UploadWorkflowYamlAsync(workflowId, workflowName, normalizedYaml, ct);
如果这是有意的 "save = 只写 draft,publish 才走 command port",请在 PR body / ADR 里把迁移路径写清楚,并至少加一个 test 证明 "save 后 list/get 能读到" + "runtime 执行要走另一条路径"。看了测试 🟡 INFORMATIONAL3. catch { return new Dictionary<...>(); }至少过滤 4. TryReadPersistedLayout(scopeId, workflow.WorkflowId) != null
5. <Button disabled style={secondaryActionButtonStyle}>Delete Draft</Button>
<Typography.Text type="secondary">Delete Draft 需要后端删除 workflow 接口,当前前端先不提供假删除。</Typography.Text>这个 PR 的 6.
✅ 看着还不错的部分
建议阻塞项
|
Codecov Report❌ Patch coverage is @@ Coverage Diff @@
## dev #248 +/- ##
==========================================
+ Coverage 68.49% 68.54% +0.04%
==========================================
Files 1108 1109 +1
Lines 77793 77905 +112
Branches 10178 10204 +26
==========================================
+ Hits 53287 53399 +112
+ Misses 20612 20600 -12
- Partials 3894 3906 +12
Flags with carried forward coverage won't be shown. Click here to find out more.
... and 3 files with indirect coverage changes 🚀 New features to boost your workflow:
|
Codex 二次评审 — 同意大部分,有重要补充和一处反驳拉 Codex 复审了一遍 + 我的 comment。Codex 同意大部分,但有一处反驳和两条我漏掉的 P0。 Codex 对我 comment 的判定
Codex 找到的、我漏掉的 P0A. public async Task UploadWorkflowYamlAsync(string workflowId, string workflowName, string yaml, CancellationToken ct)
{
_ = workflowName; // ← 入参直接丢弃
var yamlBytes = Encoding.UTF8.GetBytes(yaml);
var key = $"{WorkflowDirectory}/{workflowId}.yaml";
var context = _blobClient.TryResolveContext(string.Empty, key);
if (context == null)
return; // ← chrono-storage context 没解析出来 → 直接 no-op
await _blobClient.UploadAsync(context, yamlBytes, "text/yaml", ct);
}而 修法:context 解析失败时抛 exception(CLAUDE.md: "Don't add error handling, fallbacks, or validation for scenarios that can't happen. Trust internal code and framework guarantees."),或者把 storage 配置作为启动门禁(fail-fast on boot if Studio Save 路径启用但 chrono-storage 没接上)。 B. Query var normalizedScopeId = NormalizeRequired(scopeId, nameof(scopeId));
...
await storagePort.UploadWorkflowYamlAsync(workflowId, workflowName, normalizedYaml, ct); // scopeId 没传
PersistLayout(normalizedScopeId, workflowId, request.Layout); // layout 用了 scope
后果:用 query 修法:要么把 Codex 的其它发现
更新后的 blocking 清单Blockers(P0,merge 前必修):
Should-fix(P1-P2): Downgraded:
建议这个 PR 拆:先把前端部分(这 PR 70% 的 LOC)和 backend 的安全修复合进去;workflow save/storage 这三条 P0 单独起一个 PR 做显式的 draft/publish 拆分。 |
…ope-fixes Fix scoped workflow draft handling
回到病根:SaveAsync 是一次语义漂移,不是一个 bug前两条 comment 的 findings 都只是症状(no-op、scope 不传、storage 失败无感知)。用户指出:
这是对的。我把前面的 P0 重新排序一下——根问题是整条链的命名/契约 vs 实际行为已经错位,CLAUDE.md 里"API 字段单一语义" / "命名跟随职责" / "单一主干,插件扩展" 三条规则同时踩线。 证据:从外到内每层名字都在撒谎
|
Under PR #248 / #249, POST /api/workspace/workflows silently migrated from runtime-commit upsert to editor-draft blob write. The behaviour was corrected in #249, but the contract names still advertised the old semantics: - IWorkflowStoragePort / UploadWorkflowYamlAsync / StoredWorkflowYaml - AppScopedWorkflowService.SaveAsync - ChronoStorageWorkflowStoragePort Each name claimed "generic storage" or "save workflow", while the actual responsibility is "scoped workflow draft catalog". Per CLAUDE.md (命名跟随 职责 / API 字段单一语义), callers reading these names form incorrect expectations about runtime visibility, revision IDs, and commit semantics. This commit is a pure semantic rename — no behaviour change: - IWorkflowStoragePort -> IWorkflowDraftStore - ChronoStorageWorkflowStoragePort -> ChronoStorageWorkflowDraftStore - StoredWorkflowYaml -> WorkflowDraft - UploadWorkflowYamlAsync -> SaveDraftAsync - ListWorkflowYamlsAsync -> ListDraftsAsync - GetWorkflowYamlAsync -> GetDraftAsync - DeleteWorkflowYamlAsync -> DeleteDraftAsync - AppScopedWorkflowService.SaveAsync -> SaveDraftAsync (internal helpers named Stored*/storedWorkflow* also renamed to Draft/draft for consistency) - Test stubs / fixtures renamed in lock-step HTTP path POST /api/workspace/workflows and WorkflowFileResponse are intentionally left unchanged — phase 2 will address the response-type double semantics and optionally add an explicit publish endpoint. All 203 Aevatar.Studio.Tests and 339 Aevatar.Tools.Cli.Tests pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…semantic-rename Align scoped workflow draft port naming with actual semantics
No description provided.