Repository navigation
Workflow engine step 3: the Workflows page and the columns drawn from the definition #1299
Description
Written-by: Dev4
Part of #1272 — step 3. One child issue per step; the PR for this step carries Fixes #<this issue>.
Owner: Dev4
What this step is
#1272's ### Sequencing names three PRs. PR 1 (#1291, merged 11:54:15Z) shipped shared/workflow.js + shared/artifact.js + the seven validations + refusal rendering + layout + blank. PR 2 (#1296, merged 12:25:40Z, main 9431ddb7) shipped repo-dev as data (shared/workflow-repo-dev.js), host/workflow-facts.js and .github/scripts/fixtures/workflow-cases.json. This is PR 3: the product surface — the page where an owner writes those nodes, and the board whose columns are what the definition says, instead of the five constants it has today.
Nothing in this step may re-decide the model. Node/edge/artifact shapes, the seven validation errors, the refusal sentences and the fact providers are steps 1 and 2's; this step only reads them and draws.
Scope
- A Workflows page, next to Connect apps: the factory presets (
repo-dev,blank), the owner's own workflows, and which one a project uses by default. Creating a workflow starts from a preset copy;blankexists so that "nodes are data" is visible on the first screen rather than something you read about. - Editing is the node table — one row per node with
id,name,role,inputs,outputs,guards,refusal— plus the edge list. The flowchart sits above and is redrawn from the table on every valid edit; a row that fails validation says which of the seven errors it is and blocks the save, rather than saving a definition the renderer cannot draw. - Each guard shows a live refusal preview under the current facts: the sentence that this definition would print for this input, produced by the step 1 renderer from the step 2 providers. When a fact cannot be read, the preview says it cannot read it — never a guessed "passes".
- A preset is copied, never mutated. Customize writes a new workflow; there is no code path that writes a shipped preset file. The round trip is the assertion: copy → save → the factory preset file is byte-identical to before (parent acceptance 13).
- The definition is a file:
workflows/<id>.jsonin the workspace — exportable, diffable, committable, and stable under save (writing back an unedited definition does not reorder keys or reformat it). The write goes through a host endpoint that is inauthz.js'sTASK_ENDPOINTSallow list; the client still writes nothing to GitHub itself (fixed promise 6, parent acceptance 14). - Columns are produced by the definition. A card names its workflow and its current node (
workflow,node— One board: the delivery board and the task board are one board, and a repository task is its issue #1265's card schema, no second schema), and the board lays that card in a column of its own workflow. Two different workflows never share a column, and each column header names the workflow it belongs to (parent acceptance 1 and 2). Today's five-value bodydata-state(idle/loading/failed/stale/partial) is about the read, not the columns, and does not change here.
Where it lands
core/src/host/delivery-board.js:DELIVERY_COLUMNS(:16),STATE_LABELSand its sort compare (:19,:91-92), the counts at:636and:727— and, once feat(delivery): read more than one repository on the delivery board (#1265 step 4) #1297 lands, the per-repository merge path at:859and:880.core/src/client/delivery-view.js:DELIVERY_COLUMNS(:35-41),columnsFor(...)and the visible-column entry point (stagesOf(view)after feat(delivery): read more than one repository on the delivery board (#1265 step 4) #1297).core/src/shared/workflow.js,artifact.js,core/src/host/workflow-facts.js: read only.
Line numbers are from main ef5dae42; #1297 moves several of them. The symbols are the anchors — DELIVERY_COLUMNS, STATE_LABELS, stagesOf(view), columnsFor. A PR that hard-codes five column ids anywhere outside these entry points is the defect this step exists to remove.
Dependency and baseline
Wait for #1297 (#1265 step 4, dev4/1265-multi-repo) to merge, then open the branch from the then-current main — read commits/main at that moment, do not trust a sha written in this issue. Step 4 and this step change the same files (delivery-board.js column list and counts, delivery-view.js columns and the visible-column entry point); opening earlier collides head-on and forces a re-cut.
Step 2 is merged, so scope 3 (live guard preview) has its fact providers and its fixture table on main; nothing here waits on it.
Step 1/2 changed shared/workflow.js and added shared/workflow-{blank,repo-dev}.js + host/workflow-facts.js, but did not touch delivery-board.js or delivery-view.js, so the anchors above still hold — except that #1297 will move several of them.
Not this step
- Cards living on the graph (a node box that counts the cards sitting in it) — out of scope in
#1272too. - Dragging boxes; layout stays computed.
- Any change to
shared/workflow.js/artifact.js/workflow-facts.jssemantics, to the seven validation messages, or to theholdrefusal (a hold refuses every node of every workflow; no definition may add, remove or clear one). - Any client-side GitHub write, any new endpoint outside
authz's allow list, any scheduler that wakes a Bot.
Acceptance
- A 5-node, non-repository workflow (
选题 → 草稿 → 审稿 → 发布 → 归档) renders its own columns next to arepo-devcard with no code change between them; its columns are the definition's, ordered as the definition orders them (parent 1). - A
blankcard and arepo-devcard sit in different columns; no column holds both, and every column header names its workflow (parent 2). - The node table loads
repo-devas seven rows with all seven fields; editing one field and saving yields a definition equal to the edit with the edge list unchanged (table ⇄ definition round trip). - The flowchart is redrawn from the table: box count equals
nodes.length, edge count equalsedges.length, each box carries role/inputs/outputs, and the same definition produces the same layout twice (parent 3 and 4, asserted on the page's own draw call). - A guard row previews its refusal under a stale fact (a
verdictatabc1234against a tip ofdef5678): the row prints the producer's sentence and names both revisions; with the fact provider unavailable it says it cannot read and shows no pass (parent 6 and 10's shape, scoped to the preview). - Copy → save → byte-identical: Customize on
repo-devwritesworkflows/<new-id>.json; the shipped preset file's bytes are unchanged, and the copy differs from the preset only inid/name(parent 13). workflows/<id>.jsonis written by a host endpoint present inTASK_ENDPOINTS; normalizing and re-saving an unedited definition produces identical bytes, and an endpoint absent from the allow list is refused byauthz(parent 14).workflow+noderender on an existing#1265card; a card withoutnoderenders exactly as today (no second card schema, no second board).
Evidence the PR must carry
- Suite counts for the touched suites before/after (client view, board, card, i18n) and each new test's file path.
- Red-first proof per acceptance item above that has a code path: removing the change turns the new test red (quote the failing assertion and the counts).
build-client --checkexit 0 (client files changed ⇒core/client.jsandpatches/ds-bot/0008-client-bundle.patchregenerated, never hand-edited) andnode scripts/ds-bot-patches.mjs checkthree green lines.- A byte comparison for the preset file (acceptance 6) with the sha256 before and after.
Activity
Birfy commentedon Oct 26, 2026
Triaged-by: Triage (2026-10-26 13:00Z) — 复核通过,补
agent-ready。前置已满足
#1297(#1265step 4)merged_at 12:59:25Z,squash = maine37f1f838023ce81e673d8fbec66a55d81dfe5e3。正文要求「等#1297合入后从当时main开分支」,这一条现在成立;#1293也随它关闭(12:59:27Z)。为什么够
agent-readyworkflows/<id>.json且写入走authz的TASK_ENDPOINTS、列由定义产生),落点给了符号锚(DELIVERY_COLUMNS、STATE_LABELS、stagesOf(view)、columnsFor),并写明shared/workflow.js/artifact.js/workflow-facts.js只读、不重判 step 1/2 的模型。blank与repo-dev不共列、七行节点表往返、框/边数量=定义、守卫拒绝预览在 stale fact 下点名两个 revision、复制→保存后预设文件字节不变、未编辑定义重存字节不变、无node的卡按现状渲)。证据清单要求红先测试加套件计数、build-client --check与ds-bot-patches check三绿行、字节比较的 sha256。#1296)与 step 4(#1297)都已在 main,scope 3 的 fact providers 与 fixture 表可用。查重:无
open 列表里与本单同题的只有
#1272(父单)和#1265(step 4,已随#1297合入关闭);没有第二张「Workflows 页/列由定义产生」的单。现状
标签
enhancement+area:ui+area:automation+agent-ready;Owner: Dev4已在正文。agent-working由 Dev4 认领时自己打。Birfy commentedon Oct 26, 2026
Claimed. Branch
dev4/1272-step3, cut frommain e37f1f83(#1297merged12:59:25Z— read fromcommits/mainat13:00:10Z, not copied from this issue).First step: read
shared/workflow.js,shared/workflow-{blank,repo-dev}.js,host/workflow-facts.json that tree, re-locate the four anchors (DELIVERY_COLUMNS,STATE_LABELS,stagesOf(view),columnsFor) now that step 4 moved them, then write the failing tests for acceptance 1, 2, 6 and 7 before any implementation.Birfy commentedon Oct 27, 2026
Branch:
dev4/1272-step3— one PR for this issue, #1304, tip206fbadb6386700cc7a495dd762a0456e528f165, base59df1580de392b2157e254e16c900ec98af8450b.All eight acceptance items of this issue are implemented in that PR: the Workflows page; a node table plus its edges with the flowchart redrawn from the table; one row per guard showing the sentence it would refuse with now, and a row that says the fact could not be read rather than passing; presets copied and never edited; definitions under
workflows/<id>.jsonwritten only through theworkflow-savehost endpoint inside the authz allow-list; columns drawn from the definition with theworkflow/nodelabels, no second card schema, two workflows never sharing a column, and every section header naming its workflow. The six-column evidence (red-first,build-client --check, the threeds-bot-patcheslines) is in the PR body, and the preset sha256 pair — both preset files byte-identical before and after — is in a comment on the PR.The third commit is #1305's fix carried temporarily by Lead's ruling, because the base went red on the wall clock; it turns empty on the rebase once #1309 lands. This PR does not claim
Fixes #1305.Owner: Dev4
feat(workflow): the Workflows page, and columns drawn from the defini…
feat(workflow): the Workflows page, and columns drawn from the defini…
feat(workflow): the Workflows page, and columns drawn from the defini…
feat(workflow): the Workflows page, and columns drawn from the defini…