Skip to content

Release: merge development into beta - #512

Open
github-actions[bot] wants to merge 244 commits into
betafrom
development
Open

github-actions[bot] wants to merge 244 commits into
betafrom
development

Conversation

@github-actions

Copy link
Copy Markdown
Contributor

Automated PR to sync development changes to beta for beta release.

Merging this PR will trigger the beta release workflow.

Reminder: Add a major, minor, or patch label to this PR to control the version bump. Default is patch.

github-actions Bot and others added 5 commits August 31, 2026 16:05
Co-authored-by: Ruben van der Linde <rubenvdlinde@gmail.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
The 0.2.17 release bumped the version on main. Without this,
development stays behind main and the next development -> main promotion
conflicts on the version file.

Version files resolve to development's side, which is the higher line,
so this never moves a version backwards.
…260831154331

chore(sync): carry beta back into development
@github-actions

Copy link
Copy Markdown
Contributor Author

Quality Report — ConductionNL/planninq @ d15c1bf

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

Quality workflow — 2026-08-31 15:56 UTC

Download the full PDF report from the workflow artifacts.

Dependabot cannot update these packages. Its npm updater fails with:

  npm error code EOVERRIDE
  npm error Override for <pkg> conflicts with direct dependency

The package is listed BOTH as a direct dependency and as a literal overrides
entry pinned to the same range. Dependabot bumps the direct dependency and
does not move the override, npm rejects the mismatched pair, and the update
is abandoned -- so these packages can never be updated, security advisories
included.

npm's self-reference is the idiom for exactly this: $<name> tells the
override to follow whatever the direct dependency resolves to, instead of a
range that has to be kept in lockstep by hand. This repo already uses it (see
the vue entry under @vue/test-utils).

Transitive consumers still get pinned to one version -- the direct
dependency's -- which is what the override was there to do. What changes is
that the pin tracks the dependency instead of duplicating it.

Verified in a clean container: bumping the direct dependency with the literal
override reproduces the EOVERRIDE above; with the self-reference the same
bump resolves.

Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
@github-actions

Copy link
Copy Markdown
Contributor Author

Quality Report — ConductionNL/planninq @ ec45c03

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

Quality workflow — 2026-08-31 16:29 UTC

Download the full PDF report from the workflow artifacts.

Bumps [@eslint/config-helpers](https://github.com/eslint/rewrite/tree/HEAD/packages/config-helpers) from 0.4.2 to 0.7.0.
- [Release notes](https://github.com/eslint/rewrite/releases)
- [Changelog](https://github.com/eslint/rewrite/blob/main/packages/config-helpers/CHANGELOG.md)
- [Commits](https://github.com/eslint/rewrite/commits/core-v0.7.0/packages/config-helpers)

---
updated-dependencies:
- dependency-name: "@eslint/config-helpers"
  dependency-version: 0.7.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>
@github-actions

Copy link
Copy Markdown
Contributor Author

Quality Report — ConductionNL/planninq @ f19edf0

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

Quality workflow — 2026-08-31 17:06 UTC

Download the full PDF report from the workflow artifacts.

…2.17

chore(release): sync main back into development
@github-actions

Copy link
Copy Markdown
Contributor Author

Quality Report — ConductionNL/planninq @ 9fd270e

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

Quality workflow — 2026-08-31 17:13 UTC

Download the full PDF report from the workflow artifacts.

…527)

planninq was the last app in the fleet on eslint 8. Dependabot's
@nextcloud/eslint-config 8.4.2 -> 9.0.1 bump could not install at all:
that release declares `peer eslint: ">=10"`, so twelve checks went red at
npm ci, before a single file was linted.

Bumping the config alone was never going to work. eslint 8 was held in
three more places at once:

  @typescript-eslint/parser@7  peers eslint ^8.56.0
  eslint-plugin-import@2.32.0  peers eslint up to ^9
  @eslint/eslintrc             exists only to bridge the eslintrc era

So the stack moves together, to the versions hermiq, versioniq and keepiq
already run green: eslint ^10.9.1, @nextcloud/eslint-config ^9.0.1,
@typescript-eslint/parser ^8.68.0. eslint-plugin-vue is dropped because
v9 bundles its own v10, and a stale ^9 hoists over it and makes every SFC
parse as TypeScript. conductionVue3Fixes is dropped too: it patched a
Vue-2 ruleset, and against v9's recommended all 21 vue/no-deprecated-*
rules are already on while the two it existed to disable are not enabled
at all. Spreading it does not merely duplicate work, it BREAKS the run,
naming vue/* rules while registering no plugin.

THE CHECK THAT MATTERS HERE IS THE FILE COUNT, NOT THE ERROR COUNT.
An eslint 10 install pointed at a config it cannot read lints NOTHING and
exits 2 in a way that reads as a lint failure. That is how versioniq's
whole Vue and TypeScript layer went unchecked with 266 real problems
behind it. This migration hit exactly that on the first attempt, exit 2
and zero files, and it was caught because the file count was the check.
eslint 8 linted 46 files; this lints 47.

Those 47 files carried 284 errors nobody could see. --fix cleared 222.
The remaining 62 are fixed here rather than deferred:

  21 no-console        all console.error/warn, i.e. real diagnostics, so
                       the rule now allows those two by name instead of
                       being switched off. A stray console.log is still
                       an error, which is what the rule is for.
  18 max-statements    single-line `if (c) { stmt }` expanded.
  14 unused catch      every one of the 8 blocks handles the failure and
                       simply does not read the binding, so they become
                       optional catch binding. None was an empty swallow.
   5 multi-word-names  route views only. They are mounted by path and
                       never written as a tag, so they cannot collide
                       with an HTML element, which is the rule's purpose.
                       Scoped off for views/, kept everywhere else.
   2 deprecated props  can-close -> no-close, which is its INVERSE, so
                       `:canClose="!loading"` becomes `:noClose="loading"`.
                       And Vue Router 4 removed `exact`.
   2 jsdoc tags        {@see X} is not a valid inline tag, {@link X} is.
   1 event casing      MainMenu emitted 'open-settings' while App.vue
                       listens with @OpenSettings. That matched only
                       through Vue 3's camelize fallback in emit(); the
                       emit is now camelCase and the two agree directly.
   1 dead assignment   every branch assigns or returns, so the null
                       initializer was never read.

Verified: eslint 47 files 0/0, build exits 0, stylelint exits 0, and the
unit suite is 98/98 both before and after, run on the same checkout.

Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
@github-actions

Copy link
Copy Markdown
Contributor Author

Quality Report — ConductionNL/planninq @ 5fa3854

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

Quality workflow — 2026-08-31 17:47 UTC

Download the full PDF report from the workflow artifacts.

planninq was the last fleet app whose shell was hand-written: a router
with 11 routes in src/router/index.js, a MainMenu.vue listing the same
five destinations again, an own-rolled "OpenRegister is required" gate,
and a Dashboard.vue that computed its three KPI counts by filtering an
already-fetched project list in the browser. The manifest carried only
observability keys and said so: "planninq renders no manifest-driven UI".

It does now. The manifest owns the routes, the navigation, the dependency
gate and the dashboard:

  dependencies  -> CnAppRoot's dependency phase, keeping planninq's own
                   empty state through the #dependency-missing slot
  menu          -> CnAppNav (5 destinations + a Documentation footer link)
  pages         -> 9 pages; main.js builds the vue-router config from
                   them, one route per page with name === page.id
  Dashboard     -> type:"dashboard" with three declarative "stat" widgets
                   counted BY OPENREGISTER instead of in the browser

MainMenu.vue, router/index.js and views/Dashboard.vue are deleted. The
dashboard's two non-KPI panels move to components/DashboardPanels.vue
unchanged; UserSettings.vue loses its own dialog wrapper and becomes a
bare NcAppSettingsSection in CnAppRoot's #user-settings slot. The sidebar
outlet and its provide()d setSidebar/closeSidebar stay in App.vue — that
is app behaviour the shell does not own.

Two things worth knowing for the next app that does this:

1. A dashboard widget TYPE resolves against the LIBRARY's widget catalog
   (registerDashboardWidget / getWidgetTypeEntry), not the app's
   "registry" prop and not the page's "slots" map. Both of those are for
   PAGE components and slot overrides. A type with no catalog entry
   renders "Widget not available" with nothing logged, so the panels
   widget is registered in main.js, not in registry.js.
2. CnStatWidget resolves its "icon" through the library's own widget-icon
   catalog too, which is ~57 names and does not include every MDI icon —
   AccountGroupOutline and ArchiveOutline silently became the default
   grid glyph. The registered names are AccountGroup and History.

Also fixes a pre-existing display bug the move surfaced: the project list
printed project.icon raw, so a stored icon NAME rendered as text
("AccountMultiplePlusOnboarding Automation"). A name now goes through
CnIcon; an emoji still renders as text.

Verified in the browser against the published @conduction/nextcloud-vue
(USE_LOCAL_LIB=false, not the sibling checkout): all 9 routes resolve to
the right page id with real content and no JS errors, including the
parameterised project board / backlog / timeline; the three KPI tiles
read 3 / 3 / 0 from OpenRegister in the canonical horizontal card; both
panels render and navigate. 98 unit tests pass, eslint is clean.

Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
@github-actions

Copy link
Copy Markdown
Contributor Author

Quality Report — ConductionNL/planninq @ ee48191

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

Quality workflow — 2026-08-31 19:39 UTC

Download the full PDF report from the workflow artifacts.

github-actions Bot and others added 2 commits August 31, 2026 22:14
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
check:manifest failed on development after #530, and took Hydra Gates, E2E and
Quality Report down with it:

  /pages/1..8 must have required property '_note'

The schema requires a custom page to say why decomposition into a standard page
type was not feasible. It relaxes that only when the component matches the
library's ^Cn[A-Z]\w+$ pattern, because then the component name documents the
choice itself. All eight pages use host-app SFCs, so none qualified.

Each note is derived from what the component actually does, read from its
template, not from the page id:

  ProjectBoard    column-per-status board with drag-to-transition
  ProjectTimeline task bars plus dependency edges, fed by /api/timeline
  Timesheet       entries grouped per day, inline edit
  TaskDetail      detail plus an embedded time-entry log
  Portfolio       per-assignee aggregate with no single backing record
  Projects        card list with a client-side status chip filter
  ProjectBacklog  parent-scoped list under a breadcrumb
  Boards          board picker: entry points rather than records

⚠️ Three of these are worth a second look rather than treating this as settled.
Projects, ProjectBacklog and Boards are thin list surfaces (113 to 424 lines)
that may well fit CnIndexPage once the chip filter and the parent breadcrumb
have primitives. The notes record what each is and what the primitive lacks, so
converting them later is a smaller decision than rediscovering why they were
custom.

Verified: check:manifest, lint and build all exit 0, and the diff is exactly
eight changed lines. An earlier attempt round-tripped the JSON and reformatted
218 lines while still passing the gate.

Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
@github-actions

Copy link
Copy Markdown
Contributor Author

Quality Report — ConductionNL/planninq @ 747d5ca

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

Quality workflow — 2026-08-31 20:47 UTC

Download the full PDF report from the workflow artifacts.

@github-actions

Copy link
Copy Markdown
Contributor Author

Quality Report — ConductionNL/planninq @ 82bc71d

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

Quality workflow — 2026-08-31 20:57 UTC

Download the full PDF report from the workflow artifacts.

rubenvdlinde and others added 2 commits August 31, 2026 23:34
Both were failing on development before the manifest work, and both are
user-visible rather than bookkeeping.

gate-102 manifest-l10n-coverage: 9 manifest strings had no translation, so a
Dutch user saw English navigation. The parity checker requires the official
language of every European country, so the strings are added across all 36
required locales, not only nl. Dutch follows this app's own catalogue, where
board is already 'bord' (Kanban-bord, Bordweergave) and Archived is
'Gearchiveerd'.

gate-60 icon-vocabulary, two findings:
  - src/icons.js did not register AccountGroup or History while the manifests
    name them. An unregistered name renders NO icon, not a fallback, so those
    entries were shipping a blank.
  - the Dashboard entry used 'Home' where ADR-077 Tier A requires
    ViewDashboardOutline for the dashboard concept. Tier A is a MUST.

The remaining Tier B warning (Portfolio on ChartBar rather than
BriefcaseOutline) is a SHOULD and is left alone.

⚠️ Twice while doing this a scripted edit passed the gate and produced a wrong
diff. Round-tripping the manifest through json.dumps reformatted 218 lines, and
sorting the locale dicts rewrote every existing key in all 37 files: 13,635
added lines for 333 real ones. Both were reverted and redone as order-preserving
edits. The diff is now 745 added over 76 files, which is the 9 keys per locale
plus the generated .js.

Verified: check:l10n, check:l10n-js, check:manifest, lint and build all exit 0,
and icon-vocabulary reports 0 failures.

Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
… swallowing clicks (#536)

due-date-reminder-settings.spec.ts failed with a 60s click timeout on the
Planninq settings button. The button was never the problem. The call log reads:

  - locator resolved to <button ... aria-controls="nc-vue-7">
  - element is visible, enabled and stable
  - <div role="dialog" ... data-testid-modal="cn-support-dialog"> subtree
    intercepts pointer events

nc-vue opens the support dialog on first visit and records that the user has
seen it in a per-user preference. Playwright starts from a fresh browser
profile every run, but that preference lives on the SERVER, so it is never
there and the dialog mounts as a full modal mask over the app in every spec.

The seed now writes it once for the admin the suite runs as, which is what
buildiq's seed already does for the same reason.

Verified against the dev instance rather than assumed: deleting the preference
and replaying the exact call the seed makes returns HTTP 200 and the preference
reads back as present. bash -n passes.

This addresses the E2E job only. The app itself was never broken here: the
settings dialog works, it was covered.

Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
@github-actions

Copy link
Copy Markdown
Contributor Author

Quality Report — ConductionNL/planninq @ ee5f879

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-31 21:50 UTC

Download the full PDF report from the workflow artifacts.

@github-actions

Copy link
Copy Markdown
Contributor Author

Quality Report — ConductionNL/planninq @ 264f8d6

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

Quality workflow — 2026-08-31 22:08 UTC

Download the full PDF report from the workflow artifacts.

rubenvdlinde and others added 2 commits September 1, 2026 07:00
… label (#540)

With the support-dialog fix in, due-date-reminder-settings.spec.ts stopped
failing on an intercepted click and started failing on a locator that resolves
to nothing:

  waiting for locator('#app-navigation-vue').locator('a[title="Settings"]')

There is no such element. CnAppNav auto-prepends the entry that opens the app's
NcAppSettingsDialog and names it "Personal settings", and that name is
translated, so a title selector is a language assertion this suite has no
business making. It is the same defect class as the vault unlock button, which
matched /^(Unlock|Set up vault)$/ and found nothing on a Dutch instance.

The library carries stable ids for exactly this: data-testid="cn-nav-settings"
on the foldout and data-testid="cn-nav-personal-settings" on the entry. Both
are present in the installed bundle (2.27.2), verified rather than assumed.

🔴 The click targets the <a> INSIDE the entry, not the test id itself.
data-testid lands on NcAppNavigationItem's ROOT, which is an <li>; clicking
that is a silent no-op and the failure then surfaces several lines later on
whatever the dialog was supposed to show.

planninq declares no section:"settings" menu entries, so the foldout exists
solely because includePersonalSettings defaults true. That is why the entry is
the auto-prepended one rather than an app-declared item.

Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
gate-60 reported 1 Tier B warning. Adopted. 1 -> 0.

  Portfolio  ChartBar -> BriefcaseOutline

A portfolio of projects is not a bar chart. ChartBar described one VIEW of a
portfolio rather than the thing itself.

⚠️ BriefcaseOutline had to be REGISTERED in src/icons.js in the same commit.
It was not there, and an icon a manifest names but the registry does not hold
renders as NOTHING, not a fallback.

Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor Author

Quality Report — ConductionNL/planninq @ 6bb2ede

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

Quality workflow — 2026-09-01 05:19 UTC

Download the full PDF report from the workflow artifacts.

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor Author

Quality Report — ConductionNL/planninq @ ac99c51

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

Quality workflow — 2026-09-01 05:34 UTC

Download the full PDF report from the workflow artifacts.

@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor Author

Quality Report — ConductionNL/planninq @ 3b81340

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

Quality workflow — 2026-09-01 05:59 UTC

Download the full PDF report from the workflow artifacts.

rubenvdlinde and others added 30 commits September 29, 2026 18:12
…th dates around today

platform-demo-data tasks 1.1-2.3: curated fixed-id dataset for all 14 schemas,
@operator placeholder and anchorDate shift in DemoDataService::prepare(), the
real register seeds only the five labels (register 0.23.0).
Every session the upsert writes, created or updated, is now validated
against the real timetableSession schema (control: a wrong-typed startsAt
fails it). The code itself landed in #685 and #761.
…read, and admins publish a window

timetable-draft-review tasks 1.1-4.1: draft status and read rule (timetableSession 0.3.0,
register 0.24.0), already-published refusal, includeDrafts on the HTTP read and the query
event, POST /api/timetable/sessions/publish (admin).
… timetable-draft-review, tt-draft-publish built
feat(timetable): teachers review a draft timetable before it is published, and admins publish it per week
…roject roadmap (#782)

* feat(releases): a project-scoped release schema and task.release (wip: frontend follows)

* feat(releases): release store actions and roadmap helpers

* feat(roadmap): Roadmap view on the timeline, release dialogs, release and epic fields on a task, 36 locales

* test(roadmap): e2e and Newman coverage; design amended (roadmap is a Timeline view, slug projectRelease)

* chore(roadmap): archive backlog-releases-roadmap; bkl-releases, bkl-roadmap and prj-phases built; app version for the register import

* style(releases): one scoped schema per line (phpcs line length)

* docs(roadmap): @SPEC tags on refId, isEpic and dayIso (gate-16)
… tt-scenario-compare to build (Ruben, 29 Sep); learniq's planninq rows from learniq#1493 (#785)
…to swimlanes (#787)

* feat(board): card colour and swimlane helpers; a board view stored per person and project (wip: board screen follows)

* feat(board): View menu with card colours and swimlanes by assignee, priority or epic; 36 locales

* chore(board): archive boards-card-display; brd-card-colours and brd-swimlanes built

* refactor(settings): build the board view store from SettingsService's IConfig (phpmd parameter list, phpcs param doc)

* docs(board): @SPEC on laneValue (gate-16)
…hool week grid (#790)

* feat(timetable): wish and scenario schemas and the week grid setting for the timetable generator

timetableWish and timetableScenario (admin write, planninq-timetable read),
three demo rows each, register 0.26.0; admin settings timetable_period_grid
and timetable_generator_budget_minutes validated by TimetableGridService.
Schema strings in 36 locales. Design: window is windowFrom/windowTo.

* refactor(timetable): the grid settings live in TimetableGridService and reach the settings page through SettingsController (phpmd coupling on SettingsService)

* fix(timetable): period keys count the periods (psalm InvalidOperand); task 1.2 names the grid tests
docs(timetable): the generator's feature page and Newman folder; archive timetabling-generator
* wip: saved by the coordinator after the 30 Sep 09:51 WSL restart, not verified by the gate

* feat(boards): column rules run in the same save when a task enters the column

column.automation (column 0.5.0, register 0.27.0) and ColumnAutomationListener on
task creates and updates: set priority, assign a member, assign the mover,
unassign, add a label. Each value is checked; an invalid rule is skipped and
logged, and the move still succeeds.

* feat(boards): the owner edits column rules on the board, and a moved card shows what they changed

ColumnRulesDialog (members, labels and priorities only; former members marked),
a Rules entry in the column menu, a rules icon with a count in the header, and a
live region announcing the rule effects after a move. Newman folder Column Automation.

* l10n(boards): column rules strings in all 36 locales

* chore(openspec): archive boards-column-automation; brd-column-automation built, e2e cases, spec tags point at the archive
…e, and save the filter (#805)

* wip: saved by the coordinator after the 30 Sep 09:51 WSL restart, not verified by the gate

* feat(boards): column rules run in the same save when a task enters the column

column.automation (column 0.5.0, register 0.27.0) and ColumnAutomationListener on
task creates and updates: set priority, assign a member, assign the mover,
unassign, add a label. Each value is checked; an invalid rule is skipped and
logged, and the move still succeeds.

* feat(boards): the owner edits column rules on the board, and a moved card shows what they changed

ColumnRulesDialog (members, labels and priorities only; former members marked),
a Rules entry in the column menu, a rules icon with a count in the header, and a
live region announcing the rule effects after a move. Newman folder Column Automation.

* l10n(boards): column rules strings in all 36 locales

* chore(openspec): archive boards-column-automation; brd-column-automation built, e2e cases, spec tags point at the archive

* feat(boards): the board filter model and saved filters in the register

src/utils/boardFilter.js (assignee incl. me/unassigned, label, priority, due;
is / is not; query-string round trip). boardFilter schema (register 0.28.0),
project-scoped, read by its owner or by project members when shared, changed
only by its owner; BoardFilterOwnerListener stamps and keeps the owner.

* feat(boards): filter the board by assignee, label, priority and due date, exclude a value, and save the filter

BoardFilterBar (label chips kept as the label dimension, is-not toggles, count
line, Clear filters, Saved filters menu), BoardFilterSaveDialog, filter in the
page address, store actions, strings in 36 locales, Newman folder Board Filters,
e2e board-filters.spec.ts. Archived 2026-09-30-boards-filters; brd-filter,
brd-filter-exclude and brd-saved-filters built.

* style(boards): phpmd, the owner listener's update path in its own method

This branch has not been deployed

No deployments
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