Release: merge development into beta - #813
Conversation
…60821043606 chore(release): 1.0.1-unstable.20260821043606
…60821045501 chore(release): 1.0.1-unstable.20260821045501
…60821051111 chore(release): 1.0.1-unstable.20260821051111
Quality Report — ConductionNL/decidesk @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| check-manifest | ✅ | ||||
| check-nav-ceiling | ✅ | ||||
| test-l10n | ✅ | ||||
| format | ✅ | ||||
| composer | ✅ | ✅ 104/104 | |||
| npm | ✅ | ✅ 538/538 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| PHPUnit | ✅ | ||||
| Newman | ❌ | ||||
| Playwright | ❌ | ||||
| Hydra gates | ❌ |
Quality workflow — 2026-08-21 05:28 UTC
Download the full PDF report from the workflow artifacts.
…60821052845 chore(release): 1.0.1-unstable.20260821052845
Quality Report — ConductionNL/decidesk @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| check-manifest | ✅ | ||||
| check-nav-ceiling | ✅ | ||||
| test-l10n | ✅ | ||||
| format | ✅ | ||||
| composer | ✅ | ✅ 104/104 | |||
| npm | ✅ | ✅ 538/538 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| PHPUnit | ❌ | ||||
| Newman | ❌ | ||||
| Playwright | ❌ | ||||
| Hydra gates | ❌ |
Quality workflow — 2026-08-21 05:46 UTC
Download the full PDF report from the workflow artifacts.
Supersedes the dependabot PR, which failed `PHP Quality (phpcs)` with:
Script ./vendor/bin/phpcs --standard=phpcs.xml ... returned with error code 3
Exit 3 is a phpcs PROCESSING failure, not a verdict on the code. Reading it as a
phpcs-4 policy change (warnings starting to fail the build) and reaching for
`ignore_warnings_on_exit` would have suppressed a real breakage and left the
sniffs half-running.
The lockfile, not the sniffer
-----------------------------
The bump itself is fine. What differed was everything around it:
dependabot branch: conduction/hydra-gates v1.8.0 + php_codesniffer 4.0.4
development: conduction/hydra-gates v1.8.2 + php_codesniffer 3.13.6
this branch: conduction/hydra-gates v1.8.2 + php_codesniffer 4.0.4
hydra-gates v1.8.0 predates phpcs 4 and its sniffs cannot load under it.
Dependabot branched before v1.8.2 landed, so its lockfile pinned the older gates
package and carried it forward -- the bump was being tested against a sniff
bundle that no longer matches the sniffer. pipelinq's dependabot bump failed the
same way, from the same v1.8.0 pin.
Rebuilding the same bump on current development is the whole fix. Nothing in
phpcs.xml or the composer scripts changes, and no warning is suppressed: the 116
`@spec` warnings are still reported, exactly as on development today, and still
do not fail the build.
Verified locally against the exact CI invocation
------------------------------------------------
`./vendor/bin/phpcs --standard=phpcs.xml`, not a summary report -- report format
changes what is printed, and it is easy to "confirm" a pass with the wrong one.
phpcs 3.13.6 on development: 0 errors / 116 warnings in 108 files, exit 0
phpcs 4.0.4 on this branch: 0 errors / 116 warnings in 108 files, exit 0
Same counts, same exit, different sniffer -- what a clean linter major should
look like.
phpstan No errors
psalm No errors
phpmd exit 0
phpunit 1153 tests, 4573 assertions, 0 failures
Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
Quality Report — ConductionNL/decidesk @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ❌ | ||||
| check-manifest | ✅ | ||||
| check-nav-ceiling | ✅ | ||||
| test-l10n | ✅ | ||||
| format | ✅ | ||||
| composer | ✅ | ✅ 104/104 | |||
| npm | ✅ | ✅ 538/538 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| PHPUnit | ❌ | ||||
| Newman | ❌ | ||||
| Playwright | ❌ | ||||
| Hydra gates | ❌ |
Quality workflow — 2026-08-21 06:00 UTC
Download the full PDF report from the workflow artifacts.
Quality Report — ConductionNL/decidesk @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| check-manifest | ✅ | ||||
| check-nav-ceiling | ✅ | ||||
| test-l10n | ✅ | ||||
| format | ✅ | ||||
| composer | ✅ | ✅ 104/104 | |||
| npm | ✅ | ✅ 538/538 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| PHPUnit | ✅ | ||||
| Newman | ✅ | ||||
| Playwright | ✅ | ||||
| Hydra gates | ✅ |
Quality workflow — 2026-08-21 06:48 UTC
Download the full PDF report from the workflow artifacts.
#815) * style: apply php-cs-fixer across lib/ and tests/ (no behaviour change) `composer cs:check` was red on 119 files. The fixer is wired into no workflow, so this had drifted silently — running it now brings the tree to the standard the repo declares. The ruleset is exactly Nextcloud's: `Conduction\CodingStandard\Config` extends it and its ADDITIONS array is EMPTY by design, because every rule the fleet wants beyond Nextcloud's is semantic rather than typographic and lives in PHP_CodeSniffer instead. So this can only move whitespace and syntax, never meaning. Verified rather than assumed, because an autofix CAN change meaning: * `git diff -w` (whitespace-blind) is NOT empty — 110 files — so the run did make token-level changes, and they were inspected rather than waved through. Every one falls into three groups: `use` statements REORDERED (identical text, moved lines), trailing commas added to multi-line signatures (PHP 8.0+; CI runs 8.3 and 8.4), and promoted constructor properties split across lines. No comparison operators, no `declare(strict_types)` insertion, nothing semantic. * All 119 changed files parse (`php -l`). * Suite identical before and after: 1153 tests, 4573 assertions, 0 failures — the same counts, which is what a typographic change should produce. * phpmd, psalm, phpstan all exit 0. `cs:check` now exits 0. `composer phpcs` still exits 1, unchanged by this commit and expected: the 108 SPDX-header `InvalidEndChar` warnings are DELIBERATE. A full stop after `SPDX-License-Identifier: EUPL-1.2` makes it a different, invalid identifier and breaks REUSE, so hydra-gates' shared ruleset downgrades that one code to a warning on purpose. CI counts errors only. * fix(style): keep the @return prose out of the tag so phpcs and the fixer agree The sweep introduced ONE phpcs error, caught by CI and confirmed by measuring both branches: development has 0 files with errors, the sweep branch had 1. php-cs-fixer's docblock aligner indents a tag description to clear the longest type on the block. Behind HealthController::engineBody()'s 88-character `array{...}|null` shape that lands at column 95, producing a 162-character line — over phpcs's 150-character budget, which the shared ruleset adds deliberately because Nextcloud enforces no line length at all. The two tools genuinely disagree here, so the fix is to remove what they disagree about: the prose moves into the docblock body, leaving the tag with nothing to over-align. Verified against BOTH tools and against the baseline: phpcs errors 0 (same as development), php-cs-fixer clean (exit 0), warnings still 108 (unchanged — those are the deliberate SPDX ones REUSE requires), suite green. --------- Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
Quality Report — ConductionNL/decidesk @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| check-manifest | ✅ | ||||
| check-nav-ceiling | ✅ | ||||
| test-l10n | ✅ | ||||
| format | ✅ | ||||
| composer | ✅ | ✅ 104/104 | |||
| npm | ✅ | ✅ 538/538 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| PHPUnit | ✅ | ||||
| Newman | ✅ | ||||
| Playwright | ❌ | ||||
| Hydra gates | ✅ |
Quality workflow — 2026-08-21 07:46 UTC
Download the full PDF report from the workflow artifacts.
Quality Report — ConductionNL/decidesk @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| check-manifest | ✅ | ||||
| check-nav-ceiling | ✅ | ||||
| test-l10n | ✅ | ||||
| format | ✅ | ||||
| composer | ✅ | ✅ 104/104 | |||
| npm | ✅ | ✅ 538/538 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| PHPUnit | ✅ | ||||
| Newman | ✅ | ||||
| Playwright | ✅ | ||||
| Hydra gates | ✅ |
Quality workflow — 2026-08-21 08:25 UTC
Download the full PDF report from the workflow artifacts.
) `development` is red on one E2E test: "Display preferences: default view Meetings redirects the app root to the meetings list" timed out at 20s. It is mis-budgeted, not slow. The suite's 20s cap is calibrated in playwright.config.ts as "2.6× the slowest observed pass", which holds for a test that loads one page and asserts. This one cannot: proving a REDIRECT PREFERENCE needs the settings panel plus three full app navigations — save, app root, deep link — and those alone cost ~16s of the 20. The evidence that it is load and not defect: the same commit range passed at 05:54 and timed out at 07:08 with no code change between, and the test's own comment records an earlier round of exactly this, where the restore step was moved off the UI and onto the API to buy back a fourth page load. test.slow() triples the budget for THIS test only. The global cap is untouched, so every other failure still costs 20s rather than 60, and `retries: 0` stays — nothing here can convert a red into a green. Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
Quality Report — ConductionNL/decidesk @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| check-manifest | ✅ | ||||
| check-nav-ceiling | ✅ | ||||
| test-l10n | ✅ | ||||
| format | ✅ | ||||
| composer | ✅ | ✅ 104/104 | |||
| npm | ✅ | ✅ 538/538 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| PHPUnit | ✅ | ||||
| Newman | ✅ | ||||
| Playwright | ✅ | ||||
| Hydra gates | ✅ |
Quality workflow — 2026-08-21 09:27 UTC
Download the full PDF report from the workflow artifacts.
hydra-gates v1.8.2 -> v1.8.2 nc-vue 2.8.2 -> 2.9.2 Lock-only: both packages are already declared with caret ranges that permit these versions, so nothing about what this app ACCEPTS changes - only what it currently resolves to. Opened by the weekly fleet shared-dependency bump, because a lock nobody re-resolves is a pin nobody chose. Merging is gated by this repository's own suite, deliberately: taking hydra-gates v1.8.1 added patchObject() to a published interface, which is a load-time fatal for any concrete double that implements it without the method. CI is the only thing that can tell a safe bump from that. Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Quality Report — ConductionNL/decidesk @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| check-manifest | ✅ | ||||
| check-nav-ceiling | ✅ | ||||
| test-l10n | ✅ | ||||
| format | ✅ | ||||
| composer | ✅ | ✅ 104/104 | |||
| npm | ✅ | ✅ 538/538 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| PHPUnit | ✅ | ||||
| Newman | ✅ | ||||
| Playwright | ✅ | ||||
| Hydra gates | ✅ |
Quality workflow — 2026-08-21 12:09 UTC
Download the full PDF report from the workflow artifacts.
hydra-gates v1.8.2 -> v1.8.2 nc-vue 2.9.2 -> 2.10.1 Lock-only: both packages are already declared with caret ranges that permit these versions, so nothing about what this app ACCEPTS changes - only what it currently resolves to. Opened by the weekly fleet shared-dependency bump, because a lock nobody re-resolves is a pin nobody chose. Merging is gated by this repository's own suite, deliberately: taking hydra-gates v1.8.1 added patchObject() to a published interface, which is a load-time fatal for any concrete double that implements it without the method. CI is the only thing that can tell a safe bump from that. Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Quality Report — ConductionNL/decidesk @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| check-manifest | ✅ | ||||
| check-nav-ceiling | ✅ | ||||
| test-l10n | ✅ | ||||
| format | ✅ | ||||
| composer | ✅ | ✅ 104/104 | |||
| npm | ✅ | ✅ 538/538 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| PHPUnit | ✅ | ||||
| Newman | ✅ | ||||
| Playwright | ✅ | ||||
| Hydra gates | ✅ |
Quality workflow — 2026-08-21 14:40 UTC
Download the full PDF report from the workflow artifacts.
…a claimed prefix (#829) Prepares this app for ConductionNL/.github#531, which drops `OCA\OpenRegister\Contract\` from conduction/hydra-gates' RUNTIME psr-4 autoload. That prefix is LONGER than both openregister's own `OCA\OpenRegister\` -> `lib/` and the stub root this bootstrap registers, and PSR-4 is longest-prefix-wins, so whichever app's autoloader registers first defines OpenRegister's contract for the whole process. Without this block, once the prefix is gone the stub root resolves `...\Contract\ObjectServiceInterface` to tests/Stubs/Contract/, which this app does not ship. MEASURED: 662 errors, every one "Class or interface OCA\OpenRegister\Contract\ObjectServiceInterface does not exist" out of MockBuilder. interface_exists() is order-independent: it asks whether the interface is RESOLVABLE rather than who registered first. Appending a fallback autoloader does not work, because spl_autoload_register appends relative to registration order and that order across independently loaded apps is the thing nobody controls. Placed in tests/bootstrap-unit.php, which is what phpunit.xml actually loads — this app has BOTH bootstrap.php and bootstrap-unit.php, and the first edit went to the wrong one and changed nothing. MEASURED both directions, with the prefix removed from the vendored package's entry in vendor/composer/installed.json (editing the vendored composer.json does nothing — Composer reads installed.json): prefix PRESENT (today) Tests: 1108, Assertions: 4456, Skipped: 22 prefix REMOVED (after #531) Tests: 1108, Assertions: 4456, Skipped: 22 Safe to land now: while hydra-gates still declares the prefix this is a no-op. Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
Quality Report — ConductionNL/decidiq @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| check-manifest | ✅ | ||||
| check-nav-ceiling | ✅ | ||||
| test-l10n | ✅ | ||||
| format | ✅ | ||||
| composer | ✅ | ✅ 104/104 | |||
| npm | ✅ | ✅ 538/538 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| PHPUnit | ✅ | ||||
| Newman | ✅ | ||||
| Playwright | ✅ | ||||
| Hydra gates | ✅ |
Quality workflow — 2026-08-22 01:08 UTC
Download the full PDF report from the workflow artifacts.
* test(e2e): the registry spec must report a diff, not stand down
integration-registry.spec.ts ran 12 of its 76 tests. The other 64 skipped, and
46 of those said a version of "leaves PR not deployed yet" — a claim that cannot
be true in decidiq's own CI, where the app under test IS the commit under test.
The mechanism, verbatim from the file:
if (ids.length < EXPECTED_COUNT) {
test.skip(true, `partial registry: ${ids.length}/${EXPECTED_COUNT}
providers — leaves PR not deployed yet (have: …)`)
}
expect(ids).toHaveLength(EXPECTED_COUNT)
for (const id of EXPECTED_IDS) expect(ids).toContain(id)
The stand-down sits DIRECTLY ABOVE the loop that names exactly which providers
are missing. So a registry at 27/29 skipped instead of naming the two, and a
registry that was 93% correct reported as "not deployed".
The two were `hermiq-agent` and `sync-contract` — both registered by ANOTHER
app's bundle. This CI installs exactly one additional app, openregister
(.github/workflows/code-quality.yml `additional-apps`), so neither can ever
register here. Requiring them is what stood the whole spec down.
WHAT REPLACES IT
openregister's IntegrationsCapability::describe() already publishes `available`
— the server's own answer to "is this provider's backing Nextcloud app
installed?" — and documents it as a public discovery field for exactly this
decision. So the spec now asks the instance instead of guessing:
* `providerCaps()` reads id, enabled, requiredApp, available from OCS caps.
* `absenceReason()` returns a reason NAMING THE ABSENT APP, or null.
* A skip is permitted only when the server gives such a reason. Everything
else asserts.
Concretely:
- the registry test asserts arrayContaining(EXPECTED_IDS) — a missing
provider now fails BY NAME. Not toHaveLength: another app installed
alongside decidiq legitimately adds providers, and an exact total would
make every such addition a failure.
- cross-app mount leaves are asserted conditionally, by app.
- the sidebar count compares against what the server says is AVAILABLE (5 on
this CI), not against 29. The old code compared 5 against 29 and blamed a
frontend deploy for a sidebar that was behaving correctly.
- each per-id tab test skips only on a server-given absence, and otherwise
REQUIRES the tab to render.
This will surface anything that was hiding behind the stand-downs. That is the
point: a provider the server reports as available whose tab does not render is
a defect, and until now it was indistinguishable from a green run.
* test(e2e): a mount-mode leaf renders no tab — stop demanding one
Correction to the previous commit, found by the CI run it produced.
The per-id tab loop and the sidebar count both ran over EXPECTED_IDS, which
includes `decidesk-decisions` — a `renderMode: 'mount'` leaf. Mount leaves
expose mount()/unmount() INSTEAD of a tab + widget component, as this file's
own MOUNT_IDS docblock says and as its parity test asserts. Demanding a tab for
one is wrong.
The old code had the same error; it was invisible because it skipped when the
tab was (correctly) absent. Removing the stand-down turned it into a failure,
which is the spec being wrong rather than the app.
Adds TAB_IDS — builtin + external + component leaves, no mount leaves — and
points both the per-id loop and the count expectation at it.
WHAT THE RUN ALSO FOUND, AND IT IS REAL
The remaining failures are not spec error. On decidiq run 32702211376:
* the JS registry carries every expected provider (test passed)
* every component leaf carries a tab + widget component (test passed)
* OCS caps and the JS registry agree, no drift (test passed)
* the server reports 10 providers available
* the sidebar renders 5 tabs
Five is exactly the number of hard-coded built-ins in CnObjectSidebar's
BACKWARDS-COMPATIBLE branch (files, notes, tags, tasks, audit-trail), which is
what renders when `useRegistry` is false. src/manifest.json sets
`config.sidebar.useRegistry: true` on MeetingIntegrations
(/meetings/:id/integrations), so the flag is declared and is not reaching
CnObjectSidebar at runtime — App.vue binds
`:useRegistry="objectSidebarState.useRegistry"`, whose default is false.
So ADR-019's whole integration surface is inert on those pages, and the
registry-mode assertions in this spec have never actually run against registry
mode.
The old guard predicted this in so many words — 'registry sidebar mode not
active — check use-registry forwarding' — but it only fired at count === 0, and
the five fallback tabs kept the count non-zero, so control fell through to the
'partial sidebar … leaves PR not deployed yet' skip and blamed a deploy for a
forwarding bug.
This commit does NOT fix that. It removes the one assertion that was mine to
fix, so what remains red is the app.
* fix(deps): take nextcloud-vue 2.16.0, the release that forwards useRegistry
This branch's registry-sidebar spec asserts the gap instead of standing down,
and it has been failing honestly: 7 tests, all reporting that a
`config.sidebar.useRegistry: true` page renders 5 tabs rather than one per
registered provider.
The cause was never in this app. `CnDetailPage.syncSidebarState()` never
included `useRegistry` in the field list it hands to `assignSidebarState()`,
and that helper only writes the keys it is given — so the flag reached
`resolvedSidebar` intact, survived `mergeSidebarSources()`, and was dropped on
the last hop. The host sidebar therefore saw the prop default `false` and
rendered its five hard-coded built-in tabs.
ConductionNL/nextcloud-vue#754 fixes it. This lockfile was pinned to 2.15.0,
which predates it — 2.16.0 is the first release that carries it.
Verified against the published tarball rather than the repo, because a green
source branch says nothing about what consumers install:
useRegistry publish line in 2.16.0 ... present
CnEditSupportModal export ........... present
supportButton in the v2 schema ...... present
The spec should now pass on its own. If it does not, the remaining failure is
a real one in this app and worth reading rather than re-pinning.
* fix(e2e): the panel selector picked a hidden sibling, not the open panel
Last failure on this PR:
clicking tab-button-shares activates it + mounts the panel
Locator: aside.app-sidebar [role="tabpanel"]:not([hidden]),
aside.app-sidebar .app-sidebar__tab .first()
Expected: visible Received: hidden
The tab itself was fine — `aria-selected=true` passed on the line above. The
selector was a UNION whose second branch, `.app-sidebar__tab`, did not exclude
hidden elements, and the sidebar renders one such element per tab with all but
the active one hidden. `.first()` returns the first match in DOM ORDER, not the
first visible one, so it kept landing on a hidden sibling of the panel that had
just opened correctly.
`:not([hidden])` could not have saved it: these panels are hidden by CSS, not by
the `hidden` attribute, so that guard never applied to the branch that mattered.
Both branches now carry `:visible`.
WHERE THIS PR NOW STANDS
nextcloud-vue 2.16.0 (this branch's dependency bump) carries the useRegistry
forwarding fix, and the sidebar is finally in registry mode. Measured across the
two runs:
before 135 passed 8 failed 46 skipped
after 141 passed 1 failed 46 skipped
Seven of the eight were the one nextcloud-vue defect. This commit is the eighth,
and it was mine.
Quality Report — ConductionNL/decidiq @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| check-manifest | ✅ | ||||
| check-nav-ceiling | ✅ | ||||
| test-l10n | ✅ | ||||
| format | ✅ | ||||
| check-l10n-js | ✅ | ||||
| check-schema-l10n | ✅ | ||||
| composer | ✅ | ✅ 104/104 | |||
| npm | ✅ | ✅ 555/555 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| PHPUnit | ✅ | ||||
| Newman | ✅ | ||||
| Playwright | ✅ | ||||
| Hydra gates | ✅ |
Quality workflow — 2026-08-25 00:06 UTC
Download the full PDF report from the workflow artifacts.
The committed sbom.cdx.json dates from this app's scaffold commit in May 2026 and has never been regenerated, while composer.lock and package-lock.json have moved many times underneath it. A stale SBOM asserts a dependency set that is no longer true while still looking authoritative. The SBOM is generated per run by the shared quality workflow, published as the sbom-<app> artifact and, as of ConductionNL/.github#572, attached to stable releases. It is never committed — see the hydra sbom-generation spec (ConductionNL/hydra#617). hermiq already ignores it; the app template shipped the file despite already carrying the rule, which is how this app inherited it. Refs ConductionNL/.github#572, ConductionNL/hydra#617 Co-authored-by: Ruben van der Linde <juan.claude@conduction.nl>
Quality Report — ConductionNL/decidiq @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| check-manifest | ✅ | ||||
| check-nav-ceiling | ✅ | ||||
| test-l10n | ✅ | ||||
| format | ✅ | ||||
| check-l10n-js | ✅ | ||||
| check-schema-l10n | ✅ | ||||
| composer | ✅ | ✅ 104/104 | |||
| npm | ✅ | ✅ 555/555 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| PHPUnit | ✅ | ||||
| Newman | ✅ | ||||
| Playwright | ✅ | ||||
| Hydra gates | ✅ |
Quality workflow — 2026-08-25 05:27 UTC
Download the full PDF report from the workflow artifacts.
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Bumps [phpstan/phpstan](https://github.com/phpstan/phpstan-phar-composer-source) from 2.2.8 to 2.2.9. - [Commits](https://github.com/phpstan/phpstan-phar-composer-source/commits) --- updated-dependencies: - dependency-name: phpstan/phpstan dependency-version: 2.2.9 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.29.7 to 8.0.1. - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v8.0.1/packages/babel-core) --- updated-dependencies: - dependency-name: "@babel/core" dependency-version: 8.0.1 dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest) from 3.2.6 to 4.1.11. - [Release notes](https://github.com/vitest-dev/vitest/releases) - [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md) - [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.11/packages/vitest) --- updated-dependencies: - dependency-name: vitest dependency-version: 4.1.11 dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
#895) Bumps [node-polyfill-webpack-plugin](https://github.com/Richienb/node-polyfill-webpack-plugin) from 3.0.0 to 4.1.0. - [Release notes](https://github.com/Richienb/node-polyfill-webpack-plugin/releases) - [Commits](Richienb/node-polyfill-webpack-plugin@v3.0.0...v4.1.0) --- updated-dependencies: - dependency-name: node-polyfill-webpack-plugin dependency-version: 4.1.0 dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [sass](https://github.com/sass/dart-sass) from 1.102.0 to 1.103.1. - [Release notes](https://github.com/sass/dart-sass/releases) - [Changelog](https://github.com/sass/dart-sass/blob/main/CHANGELOG.md) - [Commits](sass/dart-sass@1.102.0...1.103.1) --- updated-dependencies: - dependency-name: sass dependency-version: 1.103.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [@vitest/coverage-v8](https://github.com/vitest-dev/vitest/tree/HEAD/packages/coverage-v8) from 3.2.6 to 4.1.11. - [Release notes](https://github.com/vitest-dev/vitest/releases) - [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md) - [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.11/packages/coverage-v8) --- updated-dependencies: - dependency-name: "@vitest/coverage-v8" dependency-version: 4.1.11 dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [eslint](https://github.com/eslint/eslint) from 10.8.1 to 10.9.0. - [Release notes](https://github.com/eslint/eslint/releases) - [Commits](eslint/eslint@v10.8.1...v10.9.0) --- updated-dependencies: - dependency-name: eslint dependency-version: 10.9.0 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [gridstack](https://github.com/gridstack/gridstack.js) from 12.6.0 to 13.2.0. - [Release notes](https://github.com/gridstack/gridstack.js/releases) - [Changelog](https://github.com/gridstack/gridstack.js/blob/master/doc/CHANGES.md) - [Commits](gridstack/gridstack.js@v12.6.0...v13.2.0) --- updated-dependencies: - dependency-name: gridstack dependency-version: 13.2.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [dexie](https://github.com/dexie/Dexie.js) from 4.4.4 to 4.4.5. - [Release notes](https://github.com/dexie/Dexie.js/releases) - [Commits](dexie/Dexie.js@v4.4.4...v4.4.5) --- updated-dependencies: - dependency-name: dexie dependency-version: 4.4.5 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [@vue/compat](https://github.com/vuejs/core) from 3.5.40 to 3.5.41. - [Release notes](https://github.com/vuejs/core/releases) - [Changelog](https://github.com/vuejs/core/blob/main/CHANGELOG.md) - [Commits](vuejs/core@v3.5.40...v3.5.41) --- updated-dependencies: - dependency-name: "@vue/compat" dependency-version: 3.5.41 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Quality Report — ConductionNL/decidiq @
|
| 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-25 06:02 UTC
Download the full PDF report from the workflow artifacts.
Quality Report — ConductionNL/decidiq @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| check-manifest | ✅ | ||||
| check-nav-ceiling | ✅ | ||||
| test-l10n | ✅ | ||||
| format | ✅ | ||||
| check-l10n-js | ✅ | ||||
| check-schema-l10n | ✅ | ||||
| composer | ✅ | ✅ 104/104 | |||
| npm | ✅ | ✅ 555/555 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| PHPUnit | ✅ | ||||
| Newman | ✅ | ||||
| Playwright | ✅ | ||||
| Hydra gates | ✅ |
Quality workflow — 2026-08-25 06:43 UTC
Download the full PDF report from the workflow artifacts.
… resolved (#904) #886 added a slug→UUID resolver for `urgencyPolicy.ratifyingBody` and I reported it as fixing the last two template migrations. IT DID NOT. Re-running the step on a live instance after the merge, both failures were still there: Failed to migrate process-template 8d3460b3-…: Property 'urgencyPolicy.ratifyingBody' should match format 'uuid' but 'gemeenteraad-amsterdam' does not. The resolver filtered `['slug' => $slug]`. A seeded `slug:` key is an IMPORT-TIME IDENTIFIER that OpenRegister keeps in `@self` metadata — it is not a stored object property. Measured on the live instance: filters ['slug' => 'gemeenteraad-amsterdam'] -> 0 rows scan of all 60 governance bodies for a `slug` FIELD -> none carry one filters ['@self' => ['slug' => 'gemeenteraad-amsterdam']] -> 1 row So the lookup returned null every time, and my deliberate "leave the slug as is rather than blank it" fallback then re-emitted the original error — which is why the symptom was unchanged and looked like the fix simply had not deployed.⚠️ WHY I SHIPPED IT ANYWAY. The 16 unit tests pass either way: the fake answers whatever shape the query asks for, so a filter naming a field that does not exist matches the fixture just as well as the right one. I verified `anonymousFailures=0` — the IDENTITY half — and took the format half on trust because the tests were green. A fake cannot tell you that you are querying a field the real store does not have. Live-verified after the change: the step now completes with NO failures of either kind. All 14 legacy templates migrate. 16 tests green, phpcs 0 errors. Co-authored-by: Ruben van der Linde <juan.claude@conduction.nl>
Quality Report — ConductionNL/decidiq @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| check-manifest | ✅ | ||||
| check-nav-ceiling | ✅ | ||||
| test-l10n | ✅ | ||||
| format | ✅ | ||||
| check-l10n-js | ✅ | ||||
| check-schema-l10n | ✅ | ||||
| composer | ✅ | ✅ 104/104 | |||
| npm | ✅ | ✅ 555/555 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| PHPUnit | ✅ | ||||
| Newman | ✅ | ||||
| Playwright | ✅ | ||||
| Hydra gates | ✅ |
Quality workflow — 2026-08-25 07:28 UTC
Download the full PDF report from the workflow artifacts.
Bumps [sass-loader](https://github.com/webpack/sass-loader) from 16.0.8 to 17.0.0. - [Release notes](https://github.com/webpack/sass-loader/releases) - [Changelog](https://github.com/webpack/sass-loader/blob/main/CHANGELOG.md) - [Commits](webpack/sass-loader@v16.0.8...v17.0.0) --- updated-dependencies: - dependency-name: sass-loader dependency-version: 17.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Quality Report — ConductionNL/decidiq @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| check-manifest | ✅ | ||||
| check-nav-ceiling | ✅ | ||||
| test-l10n | ✅ | ||||
| format | ✅ | ||||
| check-l10n-js | ✅ | ||||
| check-schema-l10n | ✅ | ||||
| composer | ✅ | ✅ 104/104 | |||
| npm | ✅ | ✅ 555/555 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| PHPUnit | ✅ | ||||
| Newman | ✅ | ||||
| Playwright | ✅ | ||||
| Hydra gates | ✅ |
Quality workflow — 2026-08-25 14:04 UTC
Download the full PDF report from the workflow artifacts.
* chore: ignore agent/test scratch and untrack generated files
Part of the 2026-08-25 fleet structure audit (ADR-100 Decision 2: the
repository root is a closed set; generated files are never tracked).
Ignore rules added: .stale/ /.e2e-state/ .phpunit.result.cache test-results/
`.stale/` was missing from ALL 19 fleet repos and is the one that
matters most operationally: agent scratch there grew unbounded and
filled the dev disk once already.
Refs ConductionNL/hydra ADR-100.
* chore: re-trigger CI
The checks on this PR are the 2026-08-25 21:5x runs, which failed on a GitHub
infrastructure fault, not on this change:
Failed to download action 'shivammathur/setup-php' ...
Error: Name or service not known (internal-api.service.iad.github.net:443)
`gh run rerun` refuses those runs ('cannot be rerun; its workflow file may be
broken' — the reusable-workflow case), and closing/reopening the PR did not
replace the recorded check entries because the head SHA was unchanged. An empty
commit moves the SHA, which is the only thing that gets a fresh verdict.
The diff is unchanged: this commit adds nothing.
---------
Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
* fix(manifest): drop 8 em-dashes from user-visible copy Found by gate-96 (manifest-copy-style, ConductionNL/.github#581). Two tour steps, four sidebar-integration descriptions and two empty states. All were already real user copy, so the meaning is unchanged. Four of them said "surface on the body", which is our word for it and not the reader's. Those now say "appear on the page itself", paired with "stay in the sidebar" so the sentence actually tells you where to look: "External integrations linked to this meeting. The Action items board (Deck), Discussion (Talk), files and notes appear on the page itself; linked articles, tags and the audit trail stay in the sidebar." The empty states lost "the public Participation surface" for "the public Participation page", same reason. CHECKED, NOT ASSUMED: humaniq's sibling fix broke `check:l10n` because that app asserts every manifest string has an en/nl key, so rewriting the English orphaned its Dutch. decidiq is different, and I verified rather than guessing: `test:l10n` PASSES here, and `test:l10n:parity` fails identically on development and on this branch (+553 missing on both, none of them mine). That 553 is real pre-existing translation debt, but it is not in this repo's frontend-checks list and this change neither causes nor worsens it. Verified: gate-96 0 findings over 943 strings, check:manifest PASS, test:l10n PASS, check:l10n-js PASS, check:schema-l10n PASS. * test(e2e): match the rewritten integration-surface copy The copy fix in the previous commit changed this description from "... linked Emails, files and tasks surface on the body; notes, tags and the audit trail remain in the sidebar." to "... Linked emails, files and tasks appear on the page itself; notes, tags and the audit trail stay in the sidebar." and `integration-surfaces.spec.ts:267` asserted the old wording verbatim, so it failed. 1 failed, 141 passed. My change, correctly caught. Narrowed the pattern to `/linked emails, files and tasks/i` rather than re-pinning the new sentence in full. The assertion's job, per its own comment, is to prove the AGENDA-ITEM page's copy rendered and not another surface's. The discriminator is the LIST of surfaces, which really is unique per page: meeting -> Deck + Talk + files + notes dossier -> emails + Deck + files agenda -> emails + files + tasks The verb after it ("appear on the page itself") is shared by all three, so pinning it added no discriminating power while guaranteeing this test breaks again on the next copy edit. Verified both surviving patterns still match EXACTLY ONE description each, so the test can still fail if the wrong surface renders. A pattern that matched two would have gone green while testing nothing. Line 206's pattern needed no change: it is case-insensitive and stops before the words that moved, which is why only one of the two failed.
… resolved (#913) #886 added a slug→UUID resolver for `urgencyPolicy.ratifyingBody` and I reported it as fixing the last two template migrations. IT DID NOT. Re-running the step on a live instance after the merge, both failures were still there: Failed to migrate process-template 8d3460b3-…: Property 'urgencyPolicy.ratifyingBody' should match format 'uuid' but 'gemeenteraad-amsterdam' does not. The resolver filtered `['slug' => $slug]`. A seeded `slug:` key is an IMPORT-TIME IDENTIFIER that OpenRegister keeps in `@self` metadata — it is not a stored object property. Measured on the live instance: filters ['slug' => 'gemeenteraad-amsterdam'] -> 0 rows scan of all 60 governance bodies for a `slug` FIELD -> none carry one filters ['@self' => ['slug' => 'gemeenteraad-amsterdam']] -> 1 row So the lookup returned null every time, and my deliberate "leave the slug as is rather than blank it" fallback then re-emitted the original error — which is why the symptom was unchanged and looked like the fix simply had not deployed.⚠️ WHY I SHIPPED IT ANYWAY. The 16 unit tests pass either way: the fake answers whatever shape the query asks for, so a filter naming a field that does not exist matches the fixture just as well as the right one. I verified `anonymousFailures=0` — the IDENTITY half — and took the format half on trust because the tests were green. A fake cannot tell you that you are querying a field the real store does not have. Live-verified after the change: the step now completes with NO failures of either kind. All 14 legacy templates migrate. 16 tests green, phpcs 0 errors. Co-authored-by: Ruben van der Linde <juan.claude@conduction.nl>
* feat(nav): a Flows surface in this app, on the shared page types ADR-110 Decision 4. A flow is app-specific — it operates on this app's objects — so the authoring surface belongs here rather than behind a deep link to another app's list. The ENGINE stays single (ADR-065): these pages are a scoped view onto OpenRegister's one native flow store, not a per-app store. Two manifest pages and one settings entry, no component files: `type: "flows"` and `type: "flow-detail"` are shipped page types in @conduction/nextcloud-vue 2.19.0, scoped by `config.app`. Note the layout of the diff: entries are appended textually rather than by reserialising the manifest. A `json.dump` round-trip rewrote pipelinq's file as a 3,950-line diff for a 20-line addition — correct output, unreviewable change. * build(deps): @conduction/nextcloud-vue 2.19.0 for the flows page types Required by the manifest change: `type: "flows"` / `type: "flow-detail"` are rejected by the compiled validator in earlier versions, and CI installs with `npm ci` — so the LOCK is what decides, not the `^2.x` range. Several of these locks were pinned many minors back, which is why some lockfile diffs are large: npm restructures the nested tree (mostly @esbuild platform binaries under @nextcloud/vue) to satisfy 2.19.0's peers. No direct dependency other than @conduction/nextcloud-vue changes. * chore(tests): refresh the vendored manifest schema to 2.25.0 The manifest gate resolves its schema from `tests/schemas/` FIRST, ahead of node_modules — deliberately, so the gate is self-contained and does not depend on a fresh install. The cost is that the copy freezes: this one was 12 minors behind, so the gate could not see any page type, widget or field the library had added since, and reported PASS the whole time because nothing it knew about was wrong. Refreshed from the installed 2.19.0 (schema 2.25.0) so `type: "flows"` and `type: "flow-detail"` validate. Worth noting for whoever owns this gate: four apps vendor this file and all four had drifted — 2.12.0, 2.13.0, 2.13.0 and 2.22.0 against a library at 2.25.0. A copy with no refresh step is a gate with a silent expiry date. --------- Co-authored-by: Ruben van der Linde <juan.claude@conduction.nl>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
|
Superseded by #919, which is the same development->beta merge with the version-stamped conflicts resolved. This PR could not be merged as-is: it conflicted, and a conflicting PR runs no CI at all. |
Automated PR to sync development changes to beta for beta release.
Merging this PR will trigger the beta release workflow.