feat(walkthrough): show where flows are edited, without asking anyone to build one - #765
Conversation
… to build one This app ships a Flows page and its getting-started tour never mentions it, so the automation surface is reachable only by someone who already knows it is there. Measured across the fleet: 19 apps declare a walkthrough, 12 ship a flows page, and exactly one tour mentioned flows at all. The stop is deliberately view-only. `allowManualNext` with a `route-match` advance and `optional: true` means it points at the surface and lets the user walk past it — nothing here gates the tour on having built a flow, which is the difference between showing someone where something lives and making them do it before they may continue. `manifest.version` gets a minor bump because that is what `sinceVersion` is compared against: a returning user whose recorded seen-version equals the old manifest version would otherwise never be shown the new step.
Every string the tour puts on screen is user-facing. Dutch is written rather than machine-produced; "Flows" stays "Flows", which is what the existing catalogue already does for the term. Worth noting for whoever picks this up: this app's `tests/l10n/check-l10n.js` does NOT scan `src/manifest.json`, so it reported OK for these keys before they existed in any catalogue. The gate passed because it did not look, not because the strings were covered — every menu label, page title, setup step and tour line in the manifest is currently outside its scope. Only dossiq's copy of the checker reads the manifest.
…ly ship `l10n/*.json` is the source; `l10n/*.js` is what the browser loads. Adding the three tour strings to the JSON left the built catalogues stale, so the strings existed in the repo and reached no user — the exact shape of the 2026-08-24 finding where nine apps shipped 8,137 translations no browser ever received. `npm run check:l10n-js` catches it (`Stale browser catalogue: l10n/en.js, l10n/nl.js`), which is why the gate exists. This is `npm run l10n:build` and nothing else.
…lves CnWalkthrough.resolveTarget() looks a nav-item target up as `[data-cn-route="<ref>"]`, and CnAppNav sets that attribute from `item.route`. The step was authored with the MENU id (FlowsMenu), which matches nothing, so it fell back to a centred anchorless coachmark instead of pointing at the entry. Easy to miss because every tour step in this fleet that works today targets an entry whose menu id happens to EQUAL its route (Cases, MyWork). FlowsMenu -> Flows is the first place they differ. Verified against the live DOM: [data-cn-route="Cases"] resolves, [data-cn-route="FlowsMenu"] does not.
Quality Report — ConductionNL/stackiq @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ⏭️ | ||||
| phpcs | ⏭️ | ||||
| phpmd | ⏭️ | ||||
| psalm | ⏭️ | ||||
| phpstan | ⏭️ | ||||
| phpmetrics | ⏭️ | ||||
| eslint | ⏭️ | ||||
| stylelint | ⏭️ | ||||
| build | ⏭️ | ||||
| composer | ⏭️ | ⏭️ | |||
| npm | ⏭️ | ⏭️ | |||
| app:check-code | ⏭️ | ||||
| info.xml | ⏭️ | ||||
| REUSE | ⏭️ | ||||
| PHPUnit | ❌ | ||||
| Newman | ❌ | ||||
| Playwright | ❌ | ||||
| Hydra gates | ❌ |
Quality workflow — 2026-08-27 15:17 UTC
Download the full PDF report from the workflow artifacts.
gate-96 (manifest-copy-style) caught it: "Em-dashes and double-dashes are AI tells. Replace with a period, a comma, or a colon." The Flows stop's body ended "...read and edit them — nothing to build now."; it now ends with a full stop and a short sentence, which is what the rule asks for and reads no worse. The English string is the l10n KEY, so the catalogues are re-keyed in the same change and the browser .js rebuilt. Leaving the key behind would have made the string untranslated in every locale while the catalogue still claimed to cover it. The Dutch value drops its em-dash too, for the same reason the English one does. Verified per app with the script that app's own CI runs (test:l10n or check:l10n), plus check:l10n-js, plus schema validation of the manifest.
Quality Report — ConductionNL/stackiq @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| check-manifest | ✅ | ||||
| check-vue-demi | ✅ | ||||
| test-l10n | ✅ | ||||
| format | ✅ | ||||
| check-schema-l10n | ✅ | ||||
| check-l10n-js | ✅ | ||||
| composer | ✅ | ✅ 130/130 | |||
| npm | ✅ | ✅ 721/721 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| PHPUnit | ✅ | ||||
| Newman | ⏭️ | ||||
| Playwright | ✅ | ||||
| Hydra gates | ❌ |
Quality workflow — 2026-08-27 18:39 UTC
Download the full PDF report from the workflow artifacts.
Quality Report — ConductionNL/stackiq @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| check-manifest | ✅ | ||||
| check-vue-demi | ✅ | ||||
| test-l10n | ✅ | ||||
| format | ✅ | ||||
| check-schema-l10n | ✅ | ||||
| check-l10n-js | ✅ | ||||
| composer | ✅ | ✅ 130/130 | |||
| npm | ✅ | ✅ 721/721 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| PHPUnit | ❌ | ||||
| Newman | ⏭️ | ||||
| Playwright | ❌ | ||||
| Hydra gates | ❌ |
Quality workflow — 2026-08-27 20:34 UTC
Download the full PDF report from the workflow artifacts.
Quality Report — ConductionNL/stackiq @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| check-manifest | ✅ | ||||
| check-vue-demi | ✅ | ||||
| test-l10n | ✅ | ||||
| format | ✅ | ||||
| check-schema-l10n | ✅ | ||||
| check-l10n-js | ✅ | ||||
| composer | ✅ | ✅ 130/130 | |||
| npm | ✅ | ✅ 721/721 | |||
| 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.
…anchors
The `see-flows` stop added by this PR targets a nav item in the SETTINGS
section. CnAppNav emitted `data-cn-route` on its main, child and footer
loops but not the settings one, so the stop resolved nothing — and
CnWalkthrough.armStep() SKIPS an optional step whose target is absent,
with no console error and nothing on screen:
const el = this.resolveTarget(this.step)
if (!el) { if (this.step.optional) { this.wt.skip(); return } }
`optional: true` is exactly what keeps the stop from forcing anyone to
build a flow, so the friendly authoring choice is also the one that fails
silently. Without this bump the step ships and reaches nobody.
The caret range does not decide this: `npm ci` installs from
package-lock.json, and that was pinned at 2.19.0, which predates the fix
(nextcloud-vue#811). 2.21.0 was verified by unpacking the published
tarball — data-cn-route appears 4 times, one inside the
`v-for="item in settingsItems"` template.
Quality Report — ConductionNL/stackiq @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| check-manifest | ✅ | ||||
| check-vue-demi | ✅ | ||||
| test-l10n | ✅ | ||||
| format | ✅ | ||||
| check-schema-l10n | ✅ | ||||
| check-l10n-js | ✅ | ||||
| composer | ✅ | ✅ 130/130 | |||
| npm | ✅ | ✅ 721/721 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| PHPUnit | ✅ | ||||
| Newman | ⏭️ | ||||
| Playwright | ❌ | ||||
| Hydra gates | ❌ |
Quality workflow — 2026-08-28 06:00 UTC
Download the full PDF report from the workflow artifacts.
Quality Report — ConductionNL/stackiq @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| check-manifest | ✅ | ||||
| check-vue-demi | ✅ | ||||
| test-l10n | ✅ | ||||
| format | ✅ | ||||
| check-schema-l10n | ✅ | ||||
| check-l10n-js | ✅ | ||||
| composer | ✅ | ✅ 130/130 | |||
| npm | ✅ | ✅ 721/721 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| PHPUnit | ✅ | ||||
| Newman | ⏭️ | ||||
| Playwright | ❌ | ||||
| Hydra gates | ✅ |
Quality workflow — 2026-08-28 06:25 UTC
Download the full PDF report from the workflow artifacts.
…ther
@conduction/nextcloud-vue 2.21.0 makes the index row's Edit action navigate
to the record's detail page instead of opening a modal over the list. That
is the intended fleet rule: a record with its own detail page is edited
there, where its nested collections are reachable, rather than through a
dialog that shows only the schema's flat scalars.
These two tests asserted the old shape and so failed with "element(s) not
found" on `getByRole('dialog')` — the dialog was never going to appear,
because the click now routes. The edit form still exists; it is reached
from the detail page's Edit button (`cn-detail-page-edit`, gated on
canEditRecord).
Everything the tests actually check — the title field, the absence of a
scheduledDate format alert, the save round-trip — is unchanged.
Quality Report — ConductionNL/stackiq @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| check-manifest | ✅ | ||||
| check-vue-demi | ✅ | ||||
| test-l10n | ✅ | ||||
| format | ✅ | ||||
| check-schema-l10n | ✅ | ||||
| check-l10n-js | ✅ | ||||
| composer | ✅ | ✅ 130/130 | |||
| npm | ✅ | ✅ 721/721 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| PHPUnit | ✅ | ||||
| Newman | ⏭️ | ||||
| Playwright | ❌ | ||||
| Hydra gates | ✅ |
Quality workflow — 2026-08-28 08:29 UTC
Download the full PDF report from the workflow artifacts.
…e list Follow-up to the detail-page edit route. The first of these two tests passed once the extra click was added; this one still failed, for a different reason. It edits the record and then asserts the new job title is rendered as a row in the Table view. That assertion assumed the edit happened in a modal OVER the list, so the list was still on screen when it ran. It is not: the row's Edit action routes to the record's detail page, the save happens there, and the page never goes back on its own. Without the return trip the assertion runs against the detail page and fails as "row not found" — which reads like the save not persisting rather than the test standing on the wrong page.
…ugh-flows-stop # Conflicts: # tests/e2e/workflows/crud-persistence.spec.ts
Quality Report — ConductionNL/stackiq @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| check-manifest | ✅ | ||||
| check-vue-demi | ✅ | ||||
| test-l10n | ✅ | ||||
| format | ✅ | ||||
| check-schema-l10n | ✅ | ||||
| check-l10n-js | ✅ | ||||
| composer | ✅ | ✅ 130/130 | |||
| npm | ✅ | ✅ 721/721 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| PHPUnit | ✅ | ||||
| Newman | ⏭️ | ||||
| Playwright | ✅ | ||||
| Hydra gates | ❌ |
Quality workflow — 2026-08-28 09:25 UTC
Download the full PDF report from the workflow artifacts.
Quality Report — ConductionNL/stackiq @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| check-manifest | ✅ | ||||
| check-vue-demi | ✅ | ||||
| test-l10n | ✅ | ||||
| format | ✅ | ||||
| check-schema-l10n | ✅ | ||||
| check-l10n-js | ✅ | ||||
| composer | ✅ | ✅ 130/130 | |||
| npm | ✅ | ✅ 721/721 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| PHPUnit | ✅ | ||||
| Newman | ⏭️ | ||||
| Playwright | 🚨 NO VERDICT — enabled but never ran | ||||
| Hydra gates | ✅ |
Quality workflow — 2026-08-28 10:00 UTC
Download the full PDF report from the workflow artifacts.
This app ships a Flows page and its getting-started tour never mentions it, so the automation surface is reachable only by someone who already knows it is there. Adds one view-only stop pointing at it.
The stop is deliberately view-only:
optional: true,allowManualNext: true, and aroute-matchadvance. It shows where flows live and lets the user walk straight past — nothing gates the tour on having built one.Measured across the 20 fleet manifests: 19 apps declare a walkthrough, 12 ship a flows page, and exactly one tour mentioned flows at all. This is one of seven apps closing that gap, same step and copy in each.
manifest.versiongets a minor bump because that is whatsinceVersionis compared against (useWalkthrough.composeSteps) — a returning user whose recorded seen-version equals the old manifest version would otherwise never be shown the new step, silently.Diff is two lines: the version, and the step.