Skip to content

refactor(flow): drop the forked flow frontend and the model it described - #606

Merged
rubenvdlinde merged 4 commits into
developmentfrom
refactor/drop-the-forked-flow-frontend
Aug 28, 2026
Merged

refactor(flow): drop the forked flow frontend and the model it described#606
rubenvdlinde merged 4 commits into
developmentfrom
refactor/drop-the-forked-flow-frontend

Conversation

@rubenvdlinde

Copy link
Copy Markdown
Contributor

Removes hermiq's parallel flow-authoring frontend — 9,317 lines deleted, 81 added — and moves its
four flow pages onto the shared index and flow page types.

The fork

File Lines
src/views/FlowBuilder.vue 2,456
src/store/flowEditor.js 1,812
src/views/FlowSidebar.vue 1,464
4 × src/modals/Flow/*.vue 1,517
src/api/flows.js, flowBranches.js, FlowIndex.vue, RunFlowDialog.vue 910

It imported CnGraphCanvas — the raw drawing widget — but not CnFlowDetail, so it reused the
geometry and reimplemented everything above it, including its own API client and store.

store.js already quoted the rule this breaks

"A flow definition SHALL NOT be stored as an OpenRegister object […] No other app SHALL own a
flow store, a flow controller, or a flow execution service
" — flow-storage/spec.md

That comment was written to explain why there is no agentflow object store. src/api/flows.js
and src/store/flowEditor.js sat directly beside it, doing what the sentence forbids. The rule was
satisfied on the backend and broken on the frontend, in the same file that cited it.

The justification was a model that no longer exists

The manifest said "a node is a PLACE and carries no config, an edge is the STEP that runs".
or-flow-action-nodes inverted that: a node is the action, carrying step type and config; an edge
is sequence.

hermiq's own backend already agrees — HermiqAgentNode::execute(array $items, array $config, array $context), whose docblock calls $config "The step configuration". Only the frontend still
described the pre-inversion world, and it had already drifted from it once: the builder read the old
shape and rendered "No step type" onto all 16 lines of a healthy flow while the engine ran it
correctly. That whole failure mode exists only because the app kept a second implementation.

What hermiq keeps

The supported extension point, which it was already using correctly:

lib/Flow/HermiqAgentNode.php
lib/Flow/HermiqWorkloadNode.php
lib/Flow/HermiqWorkloadCollectNode.php   → registered on RegisterFlowNodesEvent

The app provides nodes. It does not provide an editor. The sidebar is now the shared
CnFlowSidebar, registered from the library, so the only flow component this app registers is the
one the manifest names.

Tests

Removed, because their subject is gone:

  • flow-branches and flow-trigger-count — evaluated the fork's own source files off disk by path
  • flow-builder-dialect and flow-canvas — asserted the shared canvas's rendering, which is
    @conduction/nextcloud-vue's to prove

Kept, because they are hermiq's:

  • flow-seed — install-time seeding, through the OpenRegister API (untouched)
  • flow-execution — the engine runs a flow, and a save must not disarm it (retargeted from
    .flow-builder__verbs to the shared .cn-flow-detail__toolbar)
  • manifest-pages — the four flow routes leave the component map, since they no longer name one

Two comments that were wrong when written

dashboard-and-agents.spec.ts carried two successive comments each describing the flow model as
it had just stopped being — the second explaining the removal of a test for getting it backwards,
while itself stating the pre-inversion model. Both corrected.

Its test.fixme is re-explained rather than quietly greened. Its cause moved: the index is a
type:"index" again, so that reason is gone. It still cannot pass, for a narrower reason — the named
source declares exactly one row action (Edit), but a source's rowActions merge with the
built-ins rather than replacing them, so "these and no others" is currently inexpressible. Suppressing
a built-in is the show*Action toggles' job.

Verification

  • check:manifest and check:manifest-v2 — PASS, 0 errors, against schema 2.26.0
  • webpack build exits 0 — this is the load-bearing check: it is what proves no import of the
    eleven deleted files survives anywhere
  • eslint clean on both changed source files
  • the three touched specs have unchanged error counts (3 / 5 / 6, all pre-existing), measured in
    place
    — linting copies elsewhere gives a different answer and is not a valid control

Blocked on

  • @conduction/nextcloud-vue 2.21 (#810, #818) — 2.20 declares a named source's columns and
    create button without reading them
  • ConductionNL/.github#602 — hydra-gates' vendored schema is still 2.25.0, which has neither flow
    nor entitySource

E2E is the real proof for the editor swap and must be green before this merges.

Hermiq had a parallel flow authoring frontend: its own canvas (FlowBuilder),
sidebar, list, editor store, branch store, API client and four modals -
8,159 lines beside the shared one. It imported CnGraphCanvas, the raw drawing
widget, but not CnFlowDetail, so it reused the geometry and reimplemented
everything above it.

src/store/store.js already quoted the rule this breaks: 'No other app SHALL own
a flow store, a flow controller, or a flow execution service' (flow-storage/
spec.md). The comment was written to explain why there is no agentflow OBJECT
store, while src/api/flows.js and src/store/flowEditor.js sat next to it doing
exactly what the sentence forbids.

The justification for the fork was a model that no longer exists. The manifest
said 'a node is a PLACE and carries no config, an edge is the STEP that runs'.
or-flow-action-nodes INVERTED that: a node is the action, holding step type and
config, and an edge is sequence. Hermiq's own backend already agrees -
HermiqAgentNode::execute(array $items, array $config, array $context), whose
docblock calls $config 'The step configuration'. The frontend kept describing
the pre-inversion world, and had already drifted from it once: the builder read
the old shape and rendered 'No step type' onto all 16 lines of a healthy flow
while the engine ran it correctly.

So the fork is removed rather than repaired:

  FlowIndex, FlowIndexLegacyRedirect  custom -> index + config.entitySource
  FlowDetail, FlowDetailLegacyRedirect  custom -> flow

The sidebar is now the SHARED CnFlowSidebar, registered from the library, so the
only flow component this app still registers is the one the manifest names.

What hermiq keeps is the supported extension point, which it was already using
correctly: lib/Flow/HermiqAgentNode, HermiqWorkloadNode and
HermiqWorkloadCollectNode, registered on OpenRegister's RegisterFlowNodesEvent.
The app provides nodes; it does not provide an editor.

Tests: flow-branches and flow-trigger-count evaluated the fork's own source
files off disk and have no subject left. flow-builder-dialect and flow-canvas
asserted the shared canvas's rendering, which is nc-vue's to prove. The
survivors keep what is hermiq's: flow-seed (install-time seeding, via the
OpenRegister API), flow-execution (the engine runs a flow, and a save must not
disarm it - retargeted to the shared toolbar), and manifest-pages.

Two comments in dashboard-and-agents each described the model as it had just
stopped being; both are corrected, and the fixme there is re-explained rather
than quietly greened - its cause moved but it still cannot pass, because a
named source's row actions MERGE with the built-ins and so cannot express
'exactly one action'.

Verified: check:manifest and check:manifest-v2 PASS against schema 2.26.0,
webpack build exits 0 (which is what proves no dangling imports survive),
eslint clean on both changed source files, and unchanged error counts on the
three touched specs (3/5/6, all pre-existing, measured in place).
Two things the branch broke and local checks did not catch, because I ran
check:manifest, eslint and the build rather than the command CI runs.

1. package.json's check:specs still chained check:flow-branches and
   check:flow-trigger-count. Their spec files are deleted, so the chain died
   with MODULE_NOT_FOUND before reaching anything real.

2. tests/registry.spec.js evaluates registry.js by rewriting its imports into
   stubs, and the pattern only matched DEFAULT imports:
     /import\s+(\w+)\s+from\s+.../
   \w+ cannot match '{ CnFlowSidebar }', so the first NAMED import in the file
   survived the rewrite and vm.runInNewContext rejected the whole file with
   'Cannot use import statement outside a module' — a parse error naming
   neither the import nor the line. There were no named imports until the
   registry started importing a shared component instead of declaring its own.
   The evaluator now stubs both forms.

Verified by running the exact CI command, npm run check:specs, which now exits
0. That is the check that would have caught both before the push.
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/hermiq @ 47d3907

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-specs
check-manifest
test-l10n
format
check-l10n-js
check-schema-l10n
composer ✅ 123/123
npm ✅ 742/742
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-08-27 21:02 UTC

Download the full PDF report from the workflow artifacts.

@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/hermiq @ d730a75

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-specs
check-manifest
test-l10n
format
check-l10n-js
check-schema-l10n
composer ✅ 123/123
npm ✅ 742/742
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-08-27 22:26 UTC

Download the full PDF report from the workflow artifacts.

The stub itself is load-bearing and stays: registry.js now imports a SHARED
component (`import { CnFlowSidebar } from '@conduction/nextcloud-vue'`) instead
of declaring its own, and this spec's rewriter only handled DEFAULT imports.
A named import survived the rewrite intact and vm.runInNewContext rejected the
whole file with 'Cannot use import statement outside a module' — a parse error
naming neither the import nor the line.

Verified by mutation: deleting the named-import branch reproduces that exact
error, and restoring it is byte-identical.

Only the formatting was wrong, which is what `prettier --check` caught.
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/hermiq @ 536fb80

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-specs
check-manifest
test-l10n
format
check-l10n-js
check-schema-l10n
composer ✅ 123/123
npm ✅ 742/742
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-08-28 05:15 UTC

Download the full PDF report from the workflow artifacts.

This PR replaces hermiq's forked flow frontend with the shared `index` and
`flow` page types, and those need 2.21.0: 2.20 declares a named index source's
columns, create button and row actions without reading them.

The LOCK is the part that matters — CI installs with `npm ci`, so the caret
alone changes nothing about what actually installs.

2.21.0 is also what makes the shared CnFlowSidebar this PR registers resolve to
the same version the canvas comes from.
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/hermiq @ 638ff6b

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-specs
check-manifest
test-l10n
format
check-l10n-js
check-schema-l10n
composer ✅ 123/123
npm ✅ 742/742
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-08-28 08:08 UTC

Download the full PDF report from the workflow artifacts.

@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/hermiq @ 638ff6b

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-specs
check-manifest
test-l10n
format
check-l10n-js
check-schema-l10n
composer ✅ 123/123
npm ✅ 742/742
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-08-28 12:01 UTC

Download the full PDF report from the workflow artifacts.

@rubenvdlinde
rubenvdlinde merged commit 55405b7 into development Aug 28, 2026
75 of 77 checks passed
@rubenvdlinde
rubenvdlinde deleted the refactor/drop-the-forked-flow-frontend branch August 28, 2026 12:03
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.

1 participant