docs(plan): pluggable step parsers (plugin runtime) + code node for arbitrary TypeScript (KTD-15, U14)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -15,7 +15,7 @@ Extend the engine→workflow inversion to **task steps**. Today the engine owns
|
||||
|
||||
Steps additionally gain **parallel execution and worktree isolation as explicit foreach axes** (`mode: sequential|parallel`, `isolation: shared|worktree`): PROMPT.md steps may carry `depends:` metadata, and a parallel foreach runs dependency-satisfied instances concurrently — each in its **own worktree/branch off a common base** — with an **ordered integration stage** that lands step branches in step order and routes rebase conflicts to an `integration-conflict` rework outcome (KTD-11).
|
||||
|
||||
Third, the **task shape itself becomes workflow-defined** (KTD-12/13/14): the existence of PROMPT.md and the `### Step N:` parsing convention stop being engine law — workflows declare their **artifacts** (named task documents), and **step parsing is itself a graph node**: `parse-steps(artifact, parser)` reads an artifact, runs a registry parser, and writes the step list, with routable `no-steps`/`parse-error` outcomes. Workflows also declare **custom task fields** (typed, with enum options and rendering instructions); the task model reduces to core fields (title, description) plus standard metadata, with everything else as workflow-defined fields, and the task UI renders the field schema dynamically (detail form + card badges).
|
||||
Third, the **task shape itself becomes workflow-defined** (KTD-12/13/14): the existence of PROMPT.md and the `### Step N:` parsing convention stop being engine law — workflows declare their **artifacts** (named task documents), and **step parsing is itself a graph node**: `parse-steps(artifact, parser)` reads an artifact, runs a registry parser, and writes the step list, with routable `no-steps`/`parse-error` outcomes — and parsers are **plugin-pluggable**. A **`code` node** (KTD-15) runs arbitrary sandboxed TypeScript for logic no built-in covers. Workflows also declare **custom task fields** (typed, with enum options and rendering instructions); the task model reduces to core fields (title, description) plus standard metadata, with everything else as workflow-defined fields, and the task UI renders the field schema dynamically (detail form + card badges).
|
||||
|
||||
The default workflow is untouched (monolithic `execute` seam, declares PROMPT.md + the step-headings parser + zero custom fields — byte-identical; it is the parity oracle, same posture as the columns track). Inversion is opt-in via custom workflows; a new built-in **stepwise coding workflow** demonstrates the full modeling and is the parity-comparison subject.
|
||||
|
||||
@@ -47,6 +47,8 @@ The FN-4359 reliability-freeze waiver carried by plans 002/003 continues to appl
|
||||
- **Parallel step execution** (KTD-11): `TaskStep.dependsOn` metadata parsed from PROMPT.md `### Step N (depends: 1,2):` annotations; foreach `concurrency` config; per-instance worktrees/branches off a common base via the existing worktree pool; ordered integration (rebase/cherry-pick in step order) with `outcome:integration-conflict` routed as rework on the updated base; branch-scoped RETHINK reset in parallel mode.
|
||||
- **Workflow-defined task artifacts & a `parse-steps` node** (KTD-12): workflows declare named task documents (riding the existing task-documents machinery), and step parsing is a first-class graph node — `parse-steps(artifact, parser)` reads the artifact and writes the step list, with `no-steps`/`parse-error` outcome edges; `parseStepsFromPrompt` becomes the built-in `step-headings` parser in a parser registry; the default workflow keeps its legacy in-execute step init for byte-identical parity.
|
||||
- **Workflow-defined custom task fields** (KTD-13): typed field definitions (string/text/number/boolean/enum/multi-enum/date/url) with enum options and rendering instructions in the IR; values stored per task and validated against the schema through a single store authority; agent-tool parity.
|
||||
- **Pluggable step parsers**: plugins register parsers (namespaced ids) through the plugin runtime, mirroring the plugin-trait adapter; fail-closed to `parse-error`.
|
||||
- **`code` node** (KTD-15): inline TypeScript compiled with esbuild, executed in a timeout-bounded child process against a narrow harness contract (`ctx` in, `{outcome, contextPatch, customFields}` out); save-time syntax validation.
|
||||
- **Dynamic task UI** (KTD-14): TaskDetailModal renders the field schema as a form section; TaskCard renders card-front-placed fields as badges/chips; workflow editor gains a field-definitions panel.
|
||||
- Built-in **stepwise coding workflow** (new, opt-in) modeling today's per-step review policy explicitly; parity assertions against legacy in-session behavior.
|
||||
- Workflow node editor support for authoring foreach/step-review/rework constructs; agent-tool and plugin-SDK type parity; docs.
|
||||
@@ -58,7 +60,7 @@ The FN-4359 reliability-freeze waiver carried by plans 002/003 continues to appl
|
||||
- Step-template authoring from the dashboard *board* (lanes/cards unchanged); authoring lives in the existing workflow node editor.
|
||||
- Plugin-defined node kinds (plugins already reach gates via traits; new node kinds stay built-in this round).
|
||||
- **Recasting existing built-in task fields** (priority, labels, etc.) as workflow custom fields — this plan ships the field *system*; migrating built-ins onto it is a follow-up with its own compatibility track (every built-in field has hardcoded consumers across ~150 files). The field system is designed so that migration is additive when it comes.
|
||||
- Plugin-contributed field types or parsers (the registries are built-in-only this round, same posture as node kinds).
|
||||
- Plugin-contributed field *types* (the field-type whitelist is built-in-only this round; step parsers ARE pluggable, KTD-12).
|
||||
- Cross-workflow field identity (two workflows defining a field with the same id are distinct schemas; no shared/global field namespace yet).
|
||||
- Graduating any flag default.
|
||||
|
||||
@@ -177,7 +179,7 @@ Today `PROMPT.md` is hardcoded engine law: created by the planning phase, parsed
|
||||
|
||||
- **IR gains an `artifacts` declaration**: `artifacts: [{ key, title?, producedBy?: "planning" | "manual", role?: "step-source" | "context" }]`. Artifacts ride the **existing task-documents machinery** (`TaskDocument`, `fn_task_document_write/read`) — no new storage; `PROMPT.md` becomes the default workflow's declared `step-source` artifact backed by its current file location (the document layer already fronts it).
|
||||
- **New node kind `parse-steps`**, config `{ artifact: <key>, parser: "step-headings" | "json-steps" }`. Its handler reads the artifact at walk time, runs the named parser, and writes the canonical step list through the projection sink (`Task.steps[]` via the store, graph source — same single authority as everything else). Outcomes: `success`, `outcome:no-steps` (parsed cleanly, zero steps — routable, defaults to success), `outcome:parse-error` (malformed artifact — routable, defaults to failure). The node is the *only* graph-side writer of the step list; running a `parse-steps` after a foreach has already expanded trips the KTD-3 pin protection (audited failure), so re-plan loops cannot silently desynchronize an expanded foreach.
|
||||
- **Parser registry**: a **built-in parser registry** (same registry posture as traits — built-in-only this round) holds `step-headings` (the extracted `parseStepsFromPrompt` logic, including the `(depends: …)` annotation from U1 — extraction, not rewrite) and `json-steps` (a structured `[{name, depends?}]` document for workflows that plan in JSON). The node invokes parsers from the registry; the registry is the extension point when parsers go pluggable later.
|
||||
- **Parser registry is pluggable**: the registry (same posture as the trait registry) holds built-ins `step-headings` (the extracted `parseStepsFromPrompt` logic, including the `(depends: …)` annotation from U1 — extraction, not rewrite) and `json-steps` (a structured `[{name, depends?}]` document for workflows that plan in JSON), and **plugins register parsers** under namespaced ids (`plugin:<pluginId>:<parserId>`) through the plugin runtime — mirroring `plugin-trait-adapter.ts`. Contract: `(artifactContent, ctx) → {steps: [{name, dependsOn?}]}`, executed through the plugin runner with a timeout; an unavailable or throwing plugin parser maps to `outcome:parse-error` (fail-closed, audited) — never a crash. IR referencing a parser absent from the live registry is rejected at save with the id named.
|
||||
- **foreach consumes, never parses**: foreach `source: "task-steps"` just reads `Task.steps[]`; the KTD-3 dominance validation is now concrete — a `parse-steps` node must dominate any `foreach(source:"task-steps")` on all paths (the monolithic default workflow has no foreach and keeps its legacy in-`execute()` step init untouched).
|
||||
- **The planning seam contract**: the workflow's `producedBy: "planning"` artifacts are what the planning seam is told to produce (surfaced in the planning prompt); the engine no longer assumes PROMPT.md by name outside the default workflow's declaration. Reconcile (`reconcileStepsFromGitHistory`) and resume read through the workflow's parse-steps declaration to know which artifact/parser governs the task.
|
||||
- **Parity**: the legacy path (`parseStepsFromPrompt` callers in store/executor) delegates to the same extracted `step-headings` parser function — byte-identical, proven by the existing parse tests running against both the direct call and the registry resolution. The stepwise builtin's chain becomes: plan seam → `parse-steps(PROMPT.md, step-headings)` → foreach.
|
||||
@@ -200,6 +202,17 @@ The task model is recast as: **core fields** (title, description) + **standard m
|
||||
- **Workflow editor**: a **Fields panel** in the workflow editor (sibling to the column panel from the columns track) — add/edit/remove field definitions, enum option editor with color picker, render-placement controls, live badge preview. Reuses the editor's existing validation-at-save surfacing.
|
||||
- **TUI**: read-only rendering of card-placed fields in the task detail view (chips → bracketed labels); no TUI editing this round.
|
||||
|
||||
### KTD-15 — `code` node: arbitrary TypeScript in the graph
|
||||
|
||||
A general computation escape hatch so workflows can express logic no built-in node covers (derive a field from artifacts, call an internal API, compute routing data):
|
||||
|
||||
- **New node kind `code`**, config `{ source: string, timeoutMs?: number }` — inline TypeScript. Compiled in-memory with esbuild at execution (and syntax-checked at save: the validator runs the same transform and rejects IR whose source fails to compile), then run in a **child process** with cwd = the task's worktree.
|
||||
- **Harness contract**: the script default-exports `async (ctx) => result`, where `ctx = { task, steps, customFields, context, artifacts: {read(key)}, instance? }` (instance present inside a foreach template — the `foreach:active` data). The returned `{ outcome?, value?, contextPatch?, customFields? }` maps to graph behavior: `outcome` routes `outcome:<value>` edges (absent → success), `contextPatch` merges into walk context, `customFields` writes through the U11 validation authority. Throw/timeout/non-zero exit → `failure` outcome with the error audited.
|
||||
- **Boundaries**: the code node does NOT get a store handle, engine internals, or the step-list write path — steps are written only by `parse-steps` (KTD-12), task fields only through the validated patch it returns. It can read artifacts and the worktree; it runs with the same trust as existing workflow script steps (workflows are project-local, user-authored config — `WorkflowStepMode "script"` already executes arbitrary project scripts today, so this adds expressiveness, not a new trust tier). Timeout clamped (default 30s, cap 300s); stdout/stderr captured and size-capped into the node result; source size capped (64KB).
|
||||
- **Placement rules**: legal anywhere a script node is legal, including inside foreach templates and split branches (it is review-side/read-only with respect to git unless the author's code itself writes files in the worktree — same as script nodes today; the file-scope guard still applies to anything it commits via the session, and the code node itself never commits).
|
||||
- **Editor**: palette entry + inspector with a code textarea (monospace, esbuild syntax errors surfaced at save), timeout input.
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Requirements
|
||||
@@ -219,9 +232,10 @@ The task model is recast as: **core fields** (title, description) + **standard m
|
||||
- R13: Agent tools and plugin SDK expose the new IR types (type-only in SDK); `fn_workflow_create/update` accept the new constructs with the same validation.
|
||||
- R14: Five lifecycle invariants + lost-work guard trio remain non-configurable and covered by tests on the stepwise path.
|
||||
- R15: Parallel step execution per KTD-11 — foreach exposes explicit `mode` (sequential|parallel) and `isolation` (shared|worktree) axes (parallel+shared validator-rejected); `dependsOn` parsed from PROMPT.md (unannotated steps depend on the previous step, preserving sequential behavior by default); per-instance worktrees off the integration base; ordered integration flips the projection (done iff integrated); rebase conflicts route `outcome:integration-conflict` to rework on the updated base within the rework budget; concurrency clamped by semaphore availability without deadlock; dependency cycles rejected at expansion.
|
||||
- R16: Step parsing is a graph node per KTD-12 — `parse-steps(artifact, parser)` is the only graph-side writer of the step list, with routable `no-steps`/`parse-error` outcomes; workflows declare task artifacts; the parser registry's `step-headings` is the extracted `parseStepsFromPrompt`, byte-identical for legacy callers; a parse-steps node must dominate any foreach; parse-steps after foreach expansion trips the pin protection.
|
||||
- R16: Step parsing is a graph node per KTD-12 — `parse-steps(artifact, parser)` is the only graph-side writer of the step list, with routable `no-steps`/`parse-error` outcomes; workflows declare task artifacts; the parser registry's `step-headings` is the extracted `parseStepsFromPrompt`, byte-identical for legacy callers; a parse-steps node must dominate any foreach; parse-steps after foreach expansion trips the pin protection; plugin-registered parsers resolve through the plugin runtime and fail closed to `parse-error`.
|
||||
- R17: Workflows define custom task fields (typed, enum options, render instructions) per KTD-13; values validated through a single store authority with typed rejections; field removal orphans (never destroys) values; agent tools have full read/write parity.
|
||||
- R18: Task UI renders the field schema dynamically per KTD-14 — detail form widgets by type, card badges by placement, workflow-editor Fields panel; zero custom fields renders exactly today's UI.
|
||||
- R19: `code` node per KTD-15 — save-time compile validation, child-process execution with clamped timeout and capped output, harness contract honored (no store handle, fields only via the validated patch, steps never), throw/timeout → audited failure.
|
||||
|
||||
---
|
||||
|
||||
@@ -293,7 +307,7 @@ The task model is recast as: **core fields** (title, description) + **standard m
|
||||
- **Files**: Modify `packages/dashboard/app/components/WorkflowNodeEditor.tsx`, `packages/dashboard/app/components/workflow-flow-mapping.ts`, `packages/dashboard/app/components/WorkflowNodeEditor.css` (or sibling component CSS per the extraction convention); tests extend `packages/dashboard/app/components/__tests__/WorkflowNodeEditor.test.tsx`, `workflow-flow-mapping.test.ts`; register any new component test in `packages/dashboard/vitest.config.ts` `qualityAppComponentTests`.
|
||||
- **Approach** (design decisions committed here, not deferred):
|
||||
- **Template authoring is inline**: template nodes are always-visible React Flow children of the foreach group node (`parentId` set to the group), no drill-in canvas mode. `flowToIr` partitions nodes by `parentId` — children of a foreach group reassemble into that node's `config.template`; everything else stays top-level. Empty foreach groups render an empty-state hint ("drag a step-execute node here").
|
||||
- **Palette**: add `foreach` (preset `source:"task-steps"`, auto-populating one `step-execute` child so the group is never confusingly empty), `step-review`, and `parse-steps` (preset artifact `PROMPT.md`, parser `step-headings`; inspector renders an artifact select over the workflow's declared artifacts and a parser select) entries to the PALETTE array (`WorkflowNodeEditor.tsx:87`).
|
||||
- **Palette**: add `foreach` (preset `source:"task-steps"`, auto-populating one `step-execute` child so the group is never confusingly empty), `step-review`, `parse-steps` (preset artifact `PROMPT.md`, parser `step-headings`; inspector renders an artifact select over the workflow's declared artifacts and a parser select sourced from the live registry incl. plugin parsers), and `code` (inspector: monospace source textarea with save-time esbuild error surfacing + timeout input) entries to the PALETTE array (`WorkflowNodeEditor.tsx:87`).
|
||||
- **Inspector fields**: `foreach` branch renders a `mode` select (sequential|parallel), an `isolation` select (shared|worktree — shared disabled when mode is parallel, matching the validator), a numeric `concurrency` input shown only in parallel mode (min 1, max 8, placeholder 2), and a numeric `maxReworkCycles` input (min 1, max 10, placeholder 3 — mirroring the `maxRetries` input pattern at `WorkflowNodeEditor.tsx:711`); `step-review` branch renders a `type` select (plan|code) and the existing `CustomModelDropdown` (optional, like the gate node's model field).
|
||||
- **Edge authoring**: selecting an edge whose source is a `step-review` node shows an edge inspector with a condition dropdown (approve/revise/rethink/unavailable — stored as `outcome:<verdict>` conditions, displayed as short labels) and a "rework" toggle (sets `kind:"rework"`). Rework edges render dashed in the accent color with a loop indicator.
|
||||
- Validation errors from `parseWorkflowIr` surface inline at save (existing pattern); all strings `t("key","Default")`; i18n keys added across the 6 locales via the deep-merge convention (do not let the sync prune dynamic keys — prior incident).
|
||||
@@ -322,10 +336,10 @@ The task model is recast as: **core fields** (title, description) + **standard m
|
||||
### U12 — `parse-steps` node, workflow artifacts & parser registry
|
||||
|
||||
- **Goal**: KTD-12 (R16) — the `parse-steps` node handler, artifact declarations, and the parser registry. **Execution note: characterization-first** — pin `parseStepsFromPrompt` behavior before extraction.
|
||||
- **Files**: Modify `packages/core/src/workflow-ir-types.ts` / `workflow-ir.ts` (`artifacts` declaration — parse-steps node-kind validation itself lands in U1), new `packages/core/src/step-parsers.ts` (registry + `step-headings` extraction + `json-steps`), `packages/core/src/store.ts` (`parseStepsFromPrompt` delegates to the registry), `packages/engine/src/workflow-node-handlers.ts` (parse-steps handler: read artifact → run parser → write step list via the graph-source projection path → outcome mapping), `packages/engine/src/executor.ts` (reconcile + planning-prompt artifact contract reads the workflow declaration; pin-protection check for parse-steps after expansion); tests new `packages/core/src/__tests__/step-parsers.test.ts`, new `packages/engine/src/__tests__/workflow-parse-steps.test.ts`, executor reconcile tests extended.
|
||||
- **Files**: Modify `packages/core/src/workflow-ir-types.ts` / `workflow-ir.ts` (`artifacts` declaration — parse-steps node-kind validation itself lands in U1), new `packages/core/src/step-parsers.ts` (registry + `step-headings` extraction + `json-steps`), `packages/core/src/store.ts` (`parseStepsFromPrompt` delegates to the registry), `packages/engine/src/workflow-node-handlers.ts` (parse-steps handler: read artifact → run parser → write step list via the graph-source projection path → outcome mapping), `packages/engine/src/plugin-parser-adapter.ts` (new — plugin parser registration through the plugin runtime, mirroring `plugin-trait-adapter.ts`; timeout + fail-closed mapping to parse-error), `packages/engine/src/executor.ts` (reconcile + planning-prompt artifact contract reads the workflow declaration; pin-protection check for parse-steps after expansion); tests new `packages/core/src/__tests__/step-parsers.test.ts`, new `packages/engine/src/__tests__/workflow-parse-steps.test.ts`, executor reconcile tests extended.
|
||||
- **Approach**: per KTD-12 — the node is the only graph-side step-list writer; registry is built-in-only; foreach `source: "task-steps"` reads the projection; the default workflow keeps its legacy in-execute step init (untouched code path) while legacy `parseStepsFromPrompt` callers delegate to the same extracted parser (parity by construction); planning seam surfaces `producedBy: "planning"` artifact keys in its prompt.
|
||||
- **Patterns to follow**: trait registry (`trait-registry.ts`) for the registry shape; `createGateHandler` for handler wiring; task-documents machinery for artifact backing.
|
||||
- **Test scenarios**: step-headings extraction byte-identical on existing fixtures (incl. depends annotations); json-steps parses `[{name, depends}]`; parse-steps writes steps through the graph-source projection path; `outcome:no-steps` on clean-empty parse routes (defaults success); `outcome:parse-error` on malformed artifact routes (defaults failure), not crash; missing artifact → parse-error; parse-steps after foreach expansion → pin-protection audited failure; default workflow parity (direct call vs registry resolution identical); reconcile reads through the workflow's parse-steps declaration.
|
||||
- **Test scenarios**: step-headings extraction byte-identical on existing fixtures (incl. depends annotations); json-steps parses `[{name, depends}]`; parse-steps writes steps through the graph-source projection path; `outcome:no-steps` on clean-empty parse routes (defaults success); `outcome:parse-error` on malformed artifact routes (defaults failure), not crash; missing artifact → parse-error; parse-steps after foreach expansion → pin-protection audited failure; default workflow parity (direct call vs registry resolution identical); reconcile reads through the workflow's parse-steps declaration; plugin parser happy path through the runner; plugin parser timeout/throw → parse-error (fail-closed, audited); IR referencing an unregistered plugin parser rejected at save.
|
||||
- **Verification**: characterization tests green pre/post extraction; core + engine suites green.
|
||||
|
||||
### U13 — Dynamic task UI: field rendering + Fields panel
|
||||
@@ -336,6 +350,15 @@ The task model is recast as: **core fields** (title, description) + **standard m
|
||||
- **Test scenarios**: each widget type renders + edits + validation error inline; card badge placement honors max-3 overflow; enum color applied; orphaned values shown in disclosure, absent from card; Fields panel CRUD + option color editor + save-time IR validation surfaced; zero-fields snapshot identical; SSE workflow:updated refreshes field defs.
|
||||
- **Verification**: dashboard component shards green; `qualityAppComponentTests` registration verified; TUI render test.
|
||||
|
||||
### U14 — `code` node: compile, sandbox runner, harness contract
|
||||
|
||||
- **Goal**: KTD-15 (R19). **Execution note: test-first** for the harness contract and failure modes.
|
||||
- **Files**: Modify `packages/core/src/workflow-ir-types.ts` / `workflow-ir.ts` (`code` node kind + save-time esbuild syntax validation + source/timeout clamps), new `packages/engine/src/code-node-runner.ts` (esbuild in-memory compile + child-process execution + harness I/O + output caps), `packages/engine/src/workflow-node-handlers.ts` (handler wiring: ctx assembly incl. `foreach:active`, result mapping to outcome/contextPatch/customFields-via-U11-authority); tests new `packages/engine/src/__tests__/code-node.test.ts`, IR validation tests extended.
|
||||
- **Approach**: per KTD-15 — esbuild is already in the toolchain (vitest); child process gets cwd = worktree, a minimal env, and the serialized ctx; no store handle crosses the boundary; returned customFields patch goes through `updateTaskCustomFields`; stdout/stderr captured (capped) into the node result for the audit log.
|
||||
- **Patterns to follow**: script-step execution for process spawning + capture posture; `createPromptLikeHandler` for handler shape; U11 authority for field writes.
|
||||
- **Test scenarios**: happy path returns value + routes success; `outcome: "foo"` routes `outcome:foo` edge; contextPatch merges; customFields patch validated (invalid → node failure with typed rejection surfaced); syntax error rejected at IR save; runtime throw → failure audited; timeout kills the child and fails; output cap enforced; source size cap; inside a foreach template receives `instance`; no steps-write path exists (attempting one is not expressible via the contract).
|
||||
- **Verification**: code-node suite green; validator round-trip green.
|
||||
|
||||
### U9 — Agent tools, plugin SDK, docs, changeset
|
||||
|
||||
- **Goal**: Agent-native parity and documentation (R13, R16/R17 agent halves).
|
||||
@@ -347,7 +370,7 @@ The task model is recast as: **core fields** (title, description) + **standard m
|
||||
|
||||
U1 → (U2 ∥ U4-core-half) → U3 → U5 → U6 → U10 → U7; U9 last. U2, U3, U5, U6, U10 are **strictly serial** (all touch `executor.ts`/graph executor). U4's core-only half (db.ts migration + store CRUD) parallelizes with U2; U4's executor wiring (`buildStepInstancePersistence`) waits for U3. U10 (parallel/isolated execution) builds on sequential foreach (U3) + projection discipline (U6) and lands before U7 so the parity/invariant suite covers all modes. U8 may start IR-type authoring, palette, inspector, and CSS work in parallel with U3–U6 (the `foreach:active` context decision is now committed in U3's approach, so no mid-stream rewrite risk); its round-trip tests land after U1 is merged.
|
||||
|
||||
The task-shape track is largely independent of the step-execution track: **U11 (fields core) parallelizes with U2–U6** (core-only, no executor surface beyond the U4 migration it shares); **U12 (artifacts/parsers) follows U1** (shares IR validation) and its executor touches (reconcile/planning contract) slot between U6 and U10 in the serial executor chain; **U13 (dynamic UI) follows U11** and parallelizes with U8 (different dashboard surfaces; both register component tests). U7's parity scope includes U12's default-workflow declaration.
|
||||
The task-shape track is largely independent of the step-execution track: **U11 (fields core) parallelizes with U2–U6** (core-only, no executor surface beyond the U4 migration it shares); **U12 (artifacts/parsers) follows U1** (shares IR validation) and its executor touches (reconcile/planning contract) slot between U6 and U10 in the serial executor chain; **U13 (dynamic UI) follows U11** and parallelizes with U8 (different dashboard surfaces; both register component tests). U7's parity scope includes U12's default-workflow declaration. **U14 (code node) follows U1** (node kind) and **U11** (field-write authority); its engine half is independent of the U2–U10 executor chain except the handler-registration touch, which slots anywhere after U3.
|
||||
|
||||
---
|
||||
|
||||
@@ -363,6 +386,8 @@ The task-shape track is largely independent of the step-execution track: **U11 (
|
||||
- **Worktree pool pressure**: per-instance worktrees multiply pool usage. Mitigation: concurrency cap 8, semaphore clamp, and release-on-integration hygiene in U10; pool reuse machinery already exists for fan-out branches.
|
||||
- **Parser extraction parity (KTD-12)**: `parseStepsFromPrompt` has subtle behaviors (auto-reinit interplay, regex edge cases) that a registry indirection could perturb. Mitigation: characterization-first in U12; default workflow resolves to the same extracted function, asserted identical on existing fixtures.
|
||||
- **Dynamic UI regression surface (KTD-14)**: schema-driven rendering touches TaskCard/TaskDetailModal, the two highest-traffic components. Mitigation: zero-fields snapshot guard (today's UI byte-identical when no fields are defined); new rendering isolated in `TaskFieldsSection`; card overflow bounded at 3.
|
||||
- **Code-node misuse surface (KTD-15)**: arbitrary TS in workflows can do anything the user can. Mitigation: explicit trust framing (same tier as existing script steps), no store handle across the boundary, field writes only through the validated patch, steps never writable, clamped timeout + output caps, save-time compile rejection, full stdout/stderr audit capture.
|
||||
- **Plugin parser availability drift (KTD-12)**: a workflow saved against a plugin parser can outlive the plugin. Mitigation: save-time registry check; at runtime fail-closed to `parse-error` (routable), never a crash; audit names the missing parser id.
|
||||
- **Field-schema drift vs stored values**: workflow edits can strand values. Mitigation: orphan-not-delete posture (KTD-13), `coerce` confirmation on incompatible type changes, orphaned-fields disclosure in detail UI.
|
||||
|
||||
## System-Wide Impact
|
||||
|
||||
Reference in New Issue
Block a user