Repository navigation
Release: merge development into beta - #3980
Open
github-actions[bot] wants to merge 752 commits into
Open
github-actions[bot] wants to merge 752 commits into
github-actions[bot] wants to merge 752 commits into
Conversation
github-actions
Bot
requested review from
SudoThijn,
WilcoLouwerse,
bbrands02,
remko48 and
rjzondervan
as code owners
October 15, 2026 23:25
… relation's cases on the map The contact's Woonadres card and the organisation's KvK-and-address card declared their link as a bare page name, which the facts widget does not draw (it reads a route object), so the link the board shows never rendered. It is now a route object to the cases list in map view, narrowed to this relation as requester. Assisted-by: ClaudeCode:claude-opus-5-5
The example data the setup wizard loads was three generated placeholder objects per schema, so a fresh install still showed empty work pages. Curated fragments in lib/Settings/demo.d now load with the generated set: five Woo requests (four assigned to whoever loads the set, one overdue, two received today), four documents on one of them assessed as public, partly public and not public with citable refusal grounds, and an AVG request case type with three data subject requests. Everything is fictional. ExampleDataFragments fills the load-time tokens: @me for the loading user (left out when nobody is signed in), @today±Nd and @now±Nd, so the deadlines fall around the day the set is loaded. A test holds every fragment object to its schema, because OpenRegister drops undeclared properties without a word. Assisted-by: ClaudeCode:claude-opus-5-5
A status name is a translatable field, so a statusType row read through
ObjectService::searchObjects() carries it as a language map
({"nl": "Publicatie"}). DwellTimeAnalyzer and TransitionMatrixBuilder
accepted only a string and fell back to the status id, so every phase of
a case type whose statuses were seeded with a language map (the Woo
request's 3c0f5a00-…-b00x) showed as a raw id on DqProcesanalyse and was
left out of the days-per-phase matrix. Both now read the name through
LanguageMapText, the helper the rest of dossiq uses for translatable
titles.
Assisted-by: ClaudeCode:claude-opus-5-5
A new load-time token, @mygroup, is the loading user's first group other than admin, by id. The Afvalinzameling Woo request and the correctie AVG request carry it as assignedGroup with nobody assigned, so they land in the team queue on My team (DqMijnTeam). For a user in no such group, or with nobody signed in, the property is left out. Assisted-by: ClaudeCode:claude-opus-5-5
…DqZaakBetrokkenen) The parties grouped by role come first, titled Partijen, as the board draws them; the linked contacts follow as Contacten, then the roles' seats and the followers. Every card stays. Assisted-by: ClaudeCode:claude-opus-5-5
…WIP, audit part 1) A case type title and a status name arrive from OpenRegister as a language map. These readers cast it, so they produced "Array": - LeaverHandoverService::draftsOf(): the draft case type's title - KpiAggregationService::caseTypeTitles(): the team queue's case type names - RequestCatalogue::entries(): the intake catalogue's title and description - DemoCaseloadSeedDataService::statusTypesByCaseTypeAndName(): the status lookup key, so a seeded status was never found by its name Each now reads through LanguageMapText, with a test on a language-map row. Assisted-by: ClaudeCode:claude-opus-5-5
Where a case-object link's objectUrl is OpenRegister's objects endpoint, the object-types endpoint resolves that schema and returns its title, property count and views (map when a property is a geo type, table always); free-text types stay empty. The catalogue table gains Schema and Display columns (board DqCatalogus). Assisted-by: ClaudeCode:claude-opus-5-5
…vice The case page draws its What now? card per status role. An objection's "Advies uitgebracht" and a tender's "Beoordeling" now carry the review role (bezwaar-beroep 1.4.0, aanbesteding 1.3.0, and the seeded Bezwaar statuses), so the card for deciding shows there; no case type gives one role to two statuses. The LHS advice page declares its card per final intervention: a pre-announcement and a two-week period for a view for a penalty order or enforcement, the letter for a warning. Assisted-by: ClaudeCode:claude-opus-5-5
Assisted-by: ClaudeCode:claude-opus-5-5
…P, audit part 2) Role type names and descriptions, content template names and bodies, status public labels and descriptions, obligation titles and decision and document type names arrive from OpenRegister as a language map. These readers cast or compared them as strings: - MunicipalRoleSetService: seeding by name (re-seeded the set every time), the offer and the role-in-use name - ContentTemplateService: offered names, bodies and search, apply's body - DomainCopyService: the name of a template that was not carried - ShippedConfigurationService: the overview title - StatusTypeLookup::announcedLabelOf(), CaseStatusStore::lookupStatusDescription() - TransitionPreconditions: the blocking obligation's title - ZgwBrcRulesService: a decision type matched by its description - BrcDocumentLinkRules: the document type name an allowed-list is checked against - ZtcRelatedTypeLookup: the name the same-named document types are searched by Each reads through LanguageMapText (ZgwRulesBase gains textOf() for its subclasses), with a test on a language-map row. The in-memory test register can now refuse a save, for the not-carried path. Assisted-by: ClaudeCode:claude-opus-5-5
A detail page hands a chart its content keys as props, and the chart's kind prop is `type`; `chartKind` is only the dashboard dispatcher's name for it. The advice page declared `chartKind: matrix` alone, so the chart fell back to an empty area chart. The widget now also sets `type: matrix`, and the spec holds it. Assisted-by: ClaudeCode:claude-opus-5-5
…y requests name themselves in the Actief row (DqContacten, DqOrganisaties, DqPrivacy) A selected tab now shows as an active-filter chip (activeLabel), as the boards draw "Actief:" over these lists. Assisted-by: ClaudeCode:claude-opus-5-5
… count Assisted-by: ClaudeCode:claude-opus-5-5
…reader's language
/api/case-types/{id}/phases passed a status's translatable name through as
the raw language map, and the case type page's phase board feeds it to a
widget that renders "[object Object]". The name is now read through
TranslatedText, in the reader's language with the usual fallbacks. No
other consumer of the endpoint reads the map, so no raw field is kept.
Assisted-by: ClaudeCode:claude-opus-5-5
The detail host passes a chart only the content keys it declares, and the chart's kind prop is `type`. A spec now walks every detail page of both profiles and fails on a chart without `type`. The LHS matrix on the advice page was the only one; the other charts sit on dashboards, whose dispatcher reads `chartKind`. Assisted-by: ClaudeCode:claude-opus-5-5
…tion Activate has no backing action yet; only publish, deprecate and chain exist. Assisted-by: ClaudeCode:claude-opus-5-5
…-batch-9 # Conflicts: # src/menu-layout.simple.json # tests/vitest/simpleCasePage.spec.js
…e case
Board DqArchiveren draws archiving as its own dialog: the case, what the
case type keeps, "Klaar om te archiveren", a reason and the read-only
note. CaseArchiveDialog posts the same archive act the Lifecycle dialog
posts, behind the same role check and the same refusal of an open case,
and is offered under More on an ended case (case-archive) and by the
closed stage card. The Lifecycle dialog keeps its Archive act.
The checklist is GET /api/case/{caseId}/archive/readiness
(CaseArchiveReadiness behind CaseActsOverview): ended, result recorded,
decisions, documents final out of all, and open tasks, each read off the
stored case; a task list the engine could not read is unknown, not zero.
Only "ended" blocks, as the archive act itself only refuses that. A case
type can add its own items through the action's `checks` prop.
Assisted-by: ClaudeCode:claude-opus-5-5
…dq-batch-9 # Conflicts: # src/menu-layout.simple.json # tests/vitest/simpleCasePage.spec.js
…ion/dq-batch-9
…ation/dq-batch-9
…dq-batch-9 # Conflicts: # src/menu-layout.simple.json
Library batch 20. Syncs the vendored manifest schema to the installed one for the lag check. Assisted-by: ClaudeCode:claude-opus-5-5
…ntegration/dq-batch-18
…ion/dq-batch-18 MenuCaseTypesService rows carry both development's identifier and the branch's icon. In src/manifest.json the branch's colour, icon and teal-tone edits to Cases, CaseTypes and CaseTypeDetail are applied onto development's pages; the Queue page the branch still carried stays retired. The result equals a structural 3-way merge of the manifest. Assisted-by: ClaudeCode:claude-opus-5-5
…gration/dq-batch-18 # Conflicts: # tests/schemas/app-manifest-v2.schema.json
…tion/dq-batch-18
…on/dq-batch-18
…on/dq-batch-18
…ntegration/dq-batch-18 # Conflicts: # src/dialogs/CaseLocationDialog.vue
…q-batch-18 # Conflicts: # src/menu-layout.simple.json
…ation/dq-batch-18
…ation/dq-batch-18 # Conflicts: # src/manifest.json
…egration/dq-batch-18
lib/Service/StatusTypePalette.php: recolour() has a cyclomatic complexity of 11 against phpmd's 10, on the branch's own head and with a fresh HOME. Dropped from batch 18; back to BLD-Dq-PILLS. This reverts merge 4c428d0. Assisted-by: ClaudeCode:claude-opus-5-5
- caseTypeColourIcon: the Queue, the one list with case type tags, is a view on Cases now, so the spec no longer requires a tag to exist; any tag must resolve. Teal is checked where the test's name says, on the Cases board columns and map markers. - simpleListAndDashboard: the map list's second line is the case address with the identifier as fallback (fix/zakenkaart-map-list); a view link with a saved-view route is not matched to a menu entry by route. Assisted-by: ClaudeCode:claude-opus-5-5
…r schema allows feat/case-type-colour-icon adds teal and teal-light to statusType.colour, and the statuses editor from development drew a swatch only for the colours it knew. Its two swatches use the same palette tokens as the case type colour. Assisted-by: ClaudeCode:claude-opus-5-5
feat(screens): round 18 dossiq batch 18
* feat(case): the case page lists its links in one Gekoppeld side card DqZaak draws projects inside the Gekoppeld side card with the other apps' links, not as a widget of their own. The simple case page now places nextcloud-vue's linked widget after Handling with the documents, fees, contract and projects leaves, and the standalone case-projects widget and its grid cell are gone. Assisted-by: ClaudeCode:claude-opus-5-5 * fix(case): full profile keeps the Linked card; money panels mount shillinq's render leaves The full profile has no side column, so removing the Projects widget lost projects there. It now places the same linked card in that grid cell; the simple profile drops the cell. The fees and contract placements named shillinq's data leaves, which no host can mount, so they drew nothing; they now name the -panel render leaves. Assisted-by: ClaudeCode:claude-opus-5-5 * feat(settings): personal settings open with Views in my menu Board DqPersoonlijkeInstellingen (design-system #305) opens the personal settings with "Weergaven in mijn menu": the pinned My views entries, reordered, taken out with "Uit menu halen", and a "Weergave toevoegen" picker. The dialog now draws the library's `views` section first, where the case type picker was. Needs nextcloud-vue feat/saved-view-menu-settings; a library without the key ignores it. Assisted-by: ClaudeCode:claude-opus-5-5 * feat(cases): the case page's stage dates, what-now title and people tab as the boards draw them - The header stages read the date each status was reached from the case type blueprint (datesSource), so a stage reads "Ontvangst / 14 okt" as the boards do. - In progress, the what-now card reads "Wat nu? Stap 2: {status label}" and "Daarna: naar stap 3, besluit" (DqZaak), with the old title as the fallback. Needs nextcloud-vue with next-step title tokens (schema 2.134.0). - The People tab puts seats and followers side by side, half a row each (DqZaakBetrokkenen). Assisted-by: ClaudeCode:claude-opus-5-5 * feat(cases): the assistant as a tab on the case page DqZaakAssistent draws the assistant inside the case page, in the AI-toezicht tab; it was reachable only through the launcher's floating window. The simple case page gets an AI oversight tab holding the same AI Chat Companion, embedded through nextcloud-vue's `ai-chat` widget, with the case as its context and hermiq required. It waits under Acties with the other panels and joins the strip while open. The hex and the Assistant sidebar tab stay. Assisted-by: ClaudeCode:claude-opus-5-5 * feat(cases): the case's Tasks tab is the library task table The simple case page's Tasks tab draws the case's tasks with the library task table (type tasks, variant table) instead of dossiq's case task pane: every task on the case, open first and finished struck through, the summary under the title and New task in the card header (board DqZaakTaken). Claim, complete (also a colleague's task; the engine decides), cancel and adding a task stay on the case page; a task's form, candidates and notes are on its own page, which the title opens. The view-all link still opens Tasks filtered on the case. Needs nextcloud-vue with the record task table (r20/board-retention-tasks). Assisted-by: ClaudeCode:claude-opus-5-5 * feat(cases): say on the case that advice is still asked DqZaak opens the side column with "Advies gevraagd aan Mobiliteit en verkeer. Antwoord uiterlijk 10 oktober. Afronden kan pas daarna." while advice is open on the case. The simple profile's case page now opens its side column with a banner that shows while an open advice request (adviesAanvraag, status requested) points at this case and names the soonest due one. Configuration only; it needs nextcloud-vue notice-scoped-to-the-record for the @objectid token in a banner source. Assisted-by: ClaudeCode:claude-opus-5-5 * feat(case-types): the side column follows the open tab The case type page showed Versions and Data beside every tab and drew the publish check in the Overview body. The boards change the side column per tab: Overview has Versions and Check (DqZaaktypeOverzicht), Phases and tasks has Versions, Data and History (DqZaaktype), Fields has the parent type (DqZaaktypeVelden). Every tab now has an id and each side card names the tabs it stands beside, which the library already reads. Assisted-by: ClaudeCode:claude-opus-5-5 * fix(doorlooptijd): the monthly chart fits its tile with its source line under the plot The plot was pinned at 260px in a gridHeight 4 tile, which cut it off and scrolled (DqDoorlooptijd). Without a height a dashboard chart fits its tile. The source line moves from the card's subtitle to the chart's footnote, under the plot, where the board draws it. Assisted-by: ClaudeCode:claude-opus-5-5 * feat(case-types): the Overview carries the board's cards and the phase board opens the flow Board DqZaaktypeOverzicht draws Statuses, Rules, Rights, Personal data and Translations on the Overview; the page showed Statuses and Rights only. Overview now lists all five in the board's order, with a Rules card on the case schema's rule inventory. The phase board links "View as flow" to the case type's workflow (board DqZaaktype), which needs nextcloud-vue feat/header-link-param-tokens to resolve the id. Assisted-by: ClaudeCode:claude-opus-5-5 * feat(organisations): suspend, resume and end an organisation from its page Board DqTenant draws Opschorten in an organisation's header and says Beëindigen is under More; the page offered neither. Suspend (while active) and Resume (while suspended) are header actions and End the organisation is under More, each calling OpenRegister's organisation lifecycle endpoint. Edit and the History tab have no backing function yet and are listed in the change. Assisted-by: ClaudeCode:claude-opus-5-5 * fix(vth): inspection checklists are library rows with an accessible pill The VTH tab drew each checklist as a box with Edit and Delete buttons and an Actief badge whose text took the main ink on the solid success colour under the Zuiddrecht theme: 2.59:1, failing WCAG AA. Board DqVthInstellingen draws list rows with a pill. The checklists are now CnObjectRow rows with a CnStatusBadge (5.77:1) and Edit and Delete in the row menu. Assisted-by: ClaudeCode:claude-opus-5-5 * feat(doorlooptijd): the case type choice is a page filter on the description line DqDoorlooptijd draws 'alle zaaktypen' on the description line, before the period group; live mounted a bespoke select in the header's action slot, where the board draws Downloaden. The choice is now a declarative page filter (nextcloud-vue: select filters on the description line, library batch 21) that keeps what the bespoke one did: only case types with a processing deadline, clearable to every case type, writing caseType into the workspace the widgets read. DtCaseTypeFilter is removed. Assisted-by: ClaudeCode:claude-opus-5-5 * fix(features): the overlay carries each feature's category The pre-commit hook regenerates docs/features.json from the overlay with ConductionNL/.github's extract-features.py on every spec commit. `category`, which the dashboard groups the Features tab by, lived only in the generated file, so each spec commit dropped it and DashboardControllerContractTest broke twice. Every overlay entry now carries its category. The generator is fixed in ConductionNL/.github (fix/extract-features-keeps-fields): it reads `category` from the overlay and keeps any field the existing file holds that its sources do not give. Assisted-by: ClaudeCode:claude-opus-5-5 * feat(case-page): a case type names the special categories of personal data it processes DqSociaalDomein draws 'Bijzondere persoonsgegevens: gezondheid.' at the top of a Melding Jeugdwet case's side column. A case type now lists the GDPR article 9 and 10 categories its cases process (caseType.specialDataCategories, caseType schema 1.27.0), and the case page has one warning card per category, shown when the case type lists it and placed by the case type's sideCards. Melding Jeugdwet lists health and puts its card first. The board's second sentence ('Elke inzage wordt gelogd met het doel') is left out: dossiq does not record a purpose per view, so the card would claim what does not happen. Assisted-by: ClaudeCode:claude-opus-5-5 * fix(case-types): Dutch for the parent type side card Assisted-by: ClaudeCode:claude-opus-5-5 * feat(statuses): a shipped status takes the colour its boards draw, again Batch 18 merged fcb959f and reverted it (3dbd7be): phpmd measured StatusTypePalette::recolour() at complexity 11 against 10. This brings the change back on top of development and splits recolour() into boardColourOf(), isUnchosen() and wasShipped(); the rule is the same. The teal entries in the board colour maps are development's own now (batch 18 added teal to the statuses editor), so this branch no longer carries them. Assisted-by: ClaudeCode:claude-opus-5-5 * feat(example-set): jeugdwet case facts, a saved search and Sanne as contact DqSociaalDomein draws the jeugdwet example case's legal basis, who reported it, its regisseur and a deadline about five weeks out; the package example now carries them (assignee fatma.kaya, the cast's new jeugdteam regisseur, also the case's role participant). DqZoekresultaten draws a saved search for Lindelaan with its count alert at 12; the Zuiddrecht set declares it as a public view on the search page, owned by the cast's Woo coordinator (OpenRegister example-set views). DqContact draws the portal resident Sanne de Vries; the set seeds her as a brpPerson, every field from the cast. Assisted-by: ClaudeCode:claude-opus-5-5 * chore(deps): bump @conduction/nextcloud-vue to ^2.114.0 Syncs the vendored manifest schema to the installed one for the lag check. Assisted-by: ClaudeCode:claude-opus-5-5 * fix(doorlooptijd): one case type page filter on the processing time page development moved the case type filter onto a pageFilters entry and r20/doorlooptijd-case-type-in-description did the same with the board's description placement; the merge kept both keys, so the JSON carried a duplicate pageFilters. Keeps the branch's entry, which adds the placement and label field and uses openregister's _isnull filter grammar. Assisted-by: ClaudeCode:claude-opus-5-5 * test: the side column keeps the Linked card and the lag check reads actionFields feat/case-linked-card puts side-linked after Handling on every case and feat/advice-requested-notice extended the generic side cards without it, so the merged column lists both. nextcloud-vue schema 2.136.0 (2.114.0) closes an action through $defs/actionFields and unevaluatedProperties instead of additionalProperties, so the _note check reads the new shape. Assisted-by: ClaudeCode:claude-opus-5-5 * test(schemas): record the digest of the caseType special-data fragment r20/case-special-data-notice ships 99-case-type-special-data.json at caseType 1.27.0 without a recorded digest, which SchemaVersionFloorTest refuses. Assisted-by: ClaudeCode:claude-opus-5-5
…4115) * feat(ai-oversight): report every AI suggestion on a case to hermiq The case's AI features panel asks what the handler does with each answer and feature run (use, adapt, reject) and reports it; a suggestion nobody acted on is reported ignored as superseded, closed or expired. Redaction proposals report their review and their supersession. record-action now checks case read access before writing, accepts ignored with unusedBecause, and the delegation names dossiq as the origin app. Without hermiq it stays a no-op. Assisted-by: ClaudeCode:claude-opus-5-5 * fix(ai-oversight): format, @SPEC tags, catalogue and version bumps for the dispatch Prettier on the new files, @SPEC on every new method, en and nl entries for aiAuditEntry.unusedBecause, the rebuilt l10n js catalogues, and the register (0.20.60) and app version bumps that make the aiAuditEntry change import on an existing install. Assisted-by: ClaudeCode:claude-opus-5-5
* feat(example-set): the Lindelaan Woo case is portaliq's The Zuiddrecht set wrote two "Verlichting fietspad Lindelaan" cases: portaliq's, Sanne de Vries's request through Mijn Zuiddrecht, and dossiq's, with Linda Bakker as requester. The DqZaak boards draw Sanne's. Dossiq's fragment drops its case and everything on it (contact moments, documents and their files, tasks, advice, term); portaliq's fragment carries them on Sanne's case. The Woo document type stays here, described "Document bij een Woo-verzoek", which only it carries, so portaliq's documents find it by lookup. Assisted-by: ClaudeCode:claude-opus-5-5 * fix(case): hand the loaded case to the attention strip CaseBannerStack bound only objectId on CaseAttentionPanel. The strip reads attentionMarkers and riskAssessment off objectData, so on the live case page neither the markers nor the risk assessment were ever drawn. Assisted-by: ClaudeCode:claude-opus-5-5 * fix(case): write the picked role to the Add party form RoleTypePicker emitted `select`, but CnFormDialog mounts a form-field widget listening for `input` and `update:modelValue` only, so a picked role never reached the form. Emit update:modelValue and read the modelValue the dialog binds. Assisted-by: ClaudeCode:claude-opus-5-5 * fix(case): read the case title from objectData in the programme section CaseProgrammeSection declared a prop `object`, but CnDetailWidgetHost binds the loaded case as `objectData`, so the link dialog always got an empty case title. Assisted-by: ClaudeCode:claude-opus-5-5 * fix(case): stop the review panel shadowing the library document-review widget dossiq registered DocumentReviewPanel under `document-review`, the key of nextcloud-vue's library widget (CnDocumentReviewWidget). The app registry resolves first, so the app key replaced the library widget for any page of this app asking for it. Register the panel as `document-relevance-review` and point the case Review tab at it. The widget id `case-document-review` is unchanged, so saved arrangements and the menu layout keep finding it. Assisted-by: ClaudeCode:claude-opus-5-5 * chore(register): move the register to 0.20.61 and bump the app version Batch 19 (#4118) and the hermiq AI audit (#4115) each moved the register from 0.20.59 to 0.20.60 with different content (status type colours; the aiAuditEntry ignored outcome and unusedBecause). An install that imported one 0.20.60 would not import the other, so the register moves once more. Assisted-by: ClaudeCode:claude-opus-5-5
* feat(case-page): a case type names the special categories of personal data it processes
DqSociaalDomein draws 'Bijzondere persoonsgegevens: gezondheid.' at the
top of a Melding Jeugdwet case's side column. A case type now lists the
GDPR article 9 and 10 categories its cases process
(caseType.specialDataCategories, caseType schema 1.27.0), and the case
page has one warning card per category, shown when the case type lists
it and placed by the case type's sideCards. Melding Jeugdwet lists
health and puts its card first. The board's second sentence ('Elke
inzage wordt gelogd met het doel') is left out: dossiq does not record a
purpose per view, so the card would claim what does not happen.
Assisted-by: ClaudeCode:claude-opus-5-5
* feat(case-page): opening a sensitive case records the reader's purpose
Ruben decided to build purpose logging. A case whose case type lists
special categories of personal data opens only after the reader states
why: POST /api/cases/{id}/access-purpose reads the case as the reader and
writes the purpose to the case's OpenRegister audit trail with the
reader, the time, the purpose, the reader's own words for other and the
categories. An unreadable case, an unknown purpose, an empty other and a
failed write are refused, so the case does not open unrecorded. The case
page declares nextcloud-vue's accessPurpose with the same purposes (needs
detail-access-purpose; schema 2.136.0).
Assisted-by: ClaudeCode:claude-opus-5-5
* fix(case-page): an unreadable case or case type refuses the purpose, never answers null
The architecture rule keeps swallowing catches from growing: a read miss
is a refusal here. An unreadable case answers 404, and an unreadable case
type is not taken to ask nothing, it refuses the open (503).
Assisted-by: ClaudeCode:claude-opus-5-5
* feat(case-page): the special-data notice says every view is logged with its purpose
DqSociaalDomein's notice reads 'Bijzondere persoonsgegevens: gezondheid.
Elke inzage wordt gelogd met het doel.' The sentence was left out while
dossiq recorded no purpose; opening such a case now records the reader's
purpose in its audit trail (case-access-purpose), so each category card
carries it. Built on r20/case-access-purpose with r20/case-special-data-
notice merged in.
Assisted-by: ClaudeCode:claude-opus-5-5
* feat(end-of-day): Close out your day is manifest config, with the day worked out on the server
Ruben decided that the custom EndOfDayView moves onto the manifest setup,
losing nothing, with the day lists on the server so Recorded today
survives a reload. GET /api/personal-queue/end-of-day (EndOfDayController,
EndOfDayService) answers what the reader opened today without a note (by
OpenRegister's per-reader read state, never the object's own update), the
reader's notes of today with their time, what comes first tomorrow, the
figures and the sources that could not be read. Each row names its route
and the notes endpoint of its own case or task.
The page is a dashboard over nextcloud-vue widgets: the open list as a
record list of notes (field per row, humaniq's hours leaf per row, one
button for all, the browser-only ready figure, two empty texts), Recorded
today, Your day, First thing tomorrow, How this works, and the crumb to My
work with today's date. EndOfDayView and its client helpers are removed;
the custom-page ratchet goes down by one. Needs nextcloud-vue
record-list-notes.
Assisted-by: ClaudeCode:claude-opus-5-5
* fix(end-of-day): register the Check icon the Recorded today list draws
Hydra gate 60: an icon a manifest names and the app does not register
renders as nothing.
Assisted-by: ClaudeCode:claude-opus-5-5
* refactor(lists): deadline, export and personal queue as library config
- Deadline columns use the library `date` cell with `due` and an
`upcomingLabel`; DeadlineCountdownCell and the dead
`deadlineCountdown()` helper are gone (daysUntilDeadline and isOverdue
stay for their other callers).
- The Cases page uses CnIndexPage's own Export menu (`allowExport`, case
schema `configuration.exportable`, case 1.46.0); CaseListExportAction
and caseExportHelpers.js are gone.
- /my-queue is a dashboard page with one `work-queue` widget, a
breadcrumb and an `open-modal` CnActionDialog header action;
PersonalQueueView and planItemDialog.js are gone.
- Specs ported to manifest assertions; e2e reads the library test id.
Assisted-by: ClaudeCode:claude-opus-5-5
* refactor(cases): retire dead pages, components and registry keys
Removes code nothing mounts: LocationPicker (and the leaflet and
leaflet-draw dependencies it alone used), PropertyDefinitionFields with
its vocabulary and concept-scheme services, InspectionPanel, and the
DeelzaakList and DeelzaakDetail pages. Drops the unused registry keys
BesluitvormingLeafTab, CaseNotesTab and CaseTimelineTab; their
components stay under the keys that mount them. registerNavCardGrid
goes because nextcloud-vue 2.114.0 resolves nav-card-grid through its
built-in widget fallback.
The old sub-case addresses redirect: /cases/:id/deelzaken opens the
parent on its Related tab, /cases/:parentId/deelzaken/:id opens the
sub-case. E2e tests that opened the removed pages or targeted the
#pd-add-* ids are parked with test.fixme and a reason.
Assisted-by: ClaudeCode:claude-opus-5-5
* test(case types): drive the field vocabulary e2e through the manifest field form
The two specs targeted #pd-add-* ids from a component no page mounted.
They now open the case-type-fields-editor form. The form gains the
list entry type (items) for an array field, so a set-valued answer can
be declared there.
Assisted-by: ClaudeCode:claude-opus-5-5
* test(queue): the queue widget names no source
Assisted-by: ClaudeCode:claude-opus-5-5
* chore(deps): bump @conduction/nextcloud-vue to ^2.116.0
Syncs the vendored manifest schema to the installed one for the lag check.
Assisted-by: ClaudeCode:claude-opus-5-5
* chore(register): move the register to 0.20.62 and bump the app version
The case schema moves to 1.46.0 (the L1 list config) in this batch, so the
register moves once over development's 0.20.61.
Assisted-by: ClaudeCode:claude-opus-5-5
* test(manifest): count the personal queue as a retired custom page
feature/dq-abstract-l1-config-dossiq-only moves PersonalQueue onto library
config without moving the custom page ratchet, so the count read one short.
Assisted-by: ClaudeCode:claude-opus-5-5
* test(architecture): the personal queue widget is the reader's own
feature/dq-abstract-l1-config-dossiq-only puts the personal queue on a
dashboard widget without roles; it shows only what waits on the reader, so it
is listed as public with that reason.
Assisted-by: ClaudeCode:claude-opus-5-5
* feat(tasks): the task leaves are detail widgets
Moving the task page (DqTaak) onto a manifest detail page needs its
task-anchored parts as widgets a manifest can name. The notes, appointments
and history leaves and the waiting-case section are registered as carded
widgets (task-notes, task-events, task-audit, task-waiting-case) and read
the task the page hands them as objectId; the history opens with
content.open. The case card needs no entry: it is the library facts widget.
Assisted-by: ClaudeCode:claude-opus-5-5
* feat(tasks): the task page is a manifest detail page
TaskDetailView, a custom view of about 1,000 lines, is replaced by the
TaskDetail detail page on entitySource "tasks", on the same route and page
id so deep links and notifications keep working. The header carries the
state and priority pills, the Tasks breadcrumb, the deadline in words and
the engine's verbs, Finish through dossiq's completion route. Overview holds
the description, checklist, appointments and notes; History the engine's
trail; the side column the task facts, the case card, the waiting-case card
and the history. Needs the nextcloud-vue record-source verbs, checklist
widget and pill values.
Assisted-by: ClaudeCode:claude-opus-5-5
* docs(tasks): name the spec on the history leaf's open switch
Assisted-by: ClaudeCode:claude-opus-5-5
* fix(case): write the picked role to the Add party form
RoleTypePicker emitted `select`, but CnFormDialog mounts a form-field
widget listening for `input` and `update:modelValue` only, so a picked
role never reached the form. Emit update:modelValue and read the
modelValue the dialog binds.
Assisted-by: ClaudeCode:claude-opus-5-5
* refactor(settings): declare eight plain admin forms as settings fields
Menu structure, queue urgency, mandate and consultation behaviour, the
review report switches, the payment callback secret, the store registry and
the archival reminder interval become CnSettingsFieldsSection declarations
in adminFields.js. Their eight tab components, archivalApi.js and
menuStructureSetting.js go. Section ids, setting keys and endpoints stay as
they were, so stored app config reads unchanged.
Needs the nextcloud-vue release with the settings field kinds of
feature/dq-abstract-l2-settings-fields (radio, status, action, visibleWhen,
trueValue/falseValue, setKey, integer, detailedDescription, autoSave,
savedMessage).
Assisted-by: ClaudeCode:claude-opus-5-5
* refactor(lists): deadline, export and personal queue as library config
- Deadline columns use the library `date` cell with `due` and an
`upcomingLabel`; DeadlineCountdownCell and the dead
`deadlineCountdown()` helper are gone (daysUntilDeadline and isOverdue
stay for their other callers).
- The Cases page uses CnIndexPage's own Export menu (`allowExport`, case
schema `configuration.exportable`, case 1.46.0); CaseListExportAction
and caseExportHelpers.js are gone.
- /my-queue is a dashboard page with one `work-queue` widget, a
breadcrumb and an `open-modal` CnActionDialog header action;
PersonalQueueView and planItemDialog.js are gone.
- Specs ported to manifest assertions; e2e reads the library test id.
Assisted-by: ClaudeCode:claude-opus-5-5
* wip(cells): library cells via manifest config
Assisted-by: ClaudeCode:claude-opus-5-5
* test(settings): tidy imports after the forms moved to declarations
Assisted-by: ClaudeCode:claude-opus-5-5
* refactor(tasks): tasks, task leaves and decidiq leaves on library widgets
The case's Tasks section is the library task widget (`variant: focus`): the
first open task with its number, handler, deadline, lock, candidates, form and
verbs, completing through dossiq's route and claiming only where dossiq's
capability probe says the engine can. The simple profile's task table
completes and claims the same way. CaseTaskPane, TaskFormFields and
caseTaskPaneHelpers are gone.
The task page's notes, appointments and history are the library cards on the
task's engine endpoints (`source: flow-task`), and the case a flow run waits
on is a library notice linking it. TaskNotesLeaf, TaskEventsLeaf,
TaskAuditLeaf, TaskWaitingCaseSection and flowTaskHelpers are gone.
My work's task list is the library task widget (`scope: assigned`).
Substituted work shows only in the work queue (Ruben, 20 Oct), so
MyWorkWidget, its toggle, the SubstitutedWork card and the substitution
helpers behind them are gone; the e2e now finds the covered case in the
queue.
The case's Decisions tab and the document dialog's approval chain go through
the library integration widget, which mounts decidiq's leaves and says
"Decidiq not available" without them. BesluitvormingLeafTab and
ApprovalChainLeafTab and their registry keys are gone.
Needs the nextcloud-vue branch feature/dq-abstract-l3-tasks.
Assisted-by: ClaudeCode:claude-opus-5-5
* refactor(settings): declare KCC, AI, background account and digest forms
The KCC bridge, AI-assisted processing and background service account
admin sections, and the daily digest in the user settings dialog, become
CnSettingsFieldsSection declarations. Their four components, the KCC
trigger-word util and the AI and digest service calls they alone used go;
the AI switch-state and trigger-word specs move to the declaration spec
and the nextcloud-vue field-kind spec. The KCC e2e finds its fields by
label and waits for the section's PUT.
Needs the nextcloud-vue release with feature/dq-abstract-l2-settings-fields.
Assisted-by: ClaudeCode:claude-opus-5-5
* refactor(settings): declare the shared mailbox as settings fields
The shared mailbox section becomes a CnSettingsFieldsSection declaration
over its three endpoints: the intake keys on /api/settings/email, matching
on the instance matching endpoint (which still checks the pattern), and
the sender and allowed recipients on dossiq's own settings. Those three
were posted to the mailbox endpoint, which drops them, so they never
saved; now they do. The explanations fold behind one button as before.
EmailSettings.vue goes.
Needs the nextcloud-vue release with feature/dq-abstract-l2-settings-fields.
Assisted-by: ClaudeCode:claude-opus-5-5
* refactor(settings): the register and schema picker is CnRegisterMapping
The Configuratie section becomes the library's CnRegisterMapping over one
group: the `register` key and a `<kind>_schema` key per kind, the ids the
app config has always held. AdminRoot reads and saves them through
dossiq's settings; Settings.vue goes. Schema titles keep reading in the
reader's language through the cnTranslate the page already provides
(nextcloud-vue feature/dq-abstract-l2-settings-fields).
Assisted-by: ClaudeCode:claude-opus-5-5
* refactor(forms): bulk acts, field filters, party and role fields, templates, file set and rebind fields on the library
The bulk dialogs mount CnBulkJobProgress and CnSelectionScope with the case
wording; the Cases page declares relatedFieldFilters; requester and
represented party are the form's party widget with manifest sources; the
Role field is the form's resource widget scoped to the case type; the search
plan and the close form use CnTemplateSelect; the delivered set's items are
a field-list widget whose Compare opens DocumentCompareDialog; the rebind
fields are CnSettingsField; the party kinds editor uses CnOrderedListField.
Deletes BulkJobProgress, BulkSelectionScope, CaseTypeFieldFilters,
PartySearchField, partySources, RoleTypePicker, roleTypeOptions,
RecordTemplateSelect, TemplatePicker, FileSetItems and RebindPropertyField,
and the InitiatorPicker, RoleTypePicker, CaseTypeFieldFilters and
file-set-items registry keys. Needs @conduction/nextcloud-vue with
feature/dq-abstract-l5-forms.
Assisted-by: ClaudeCode:claude-opus-5-5
* test(queue): the queue widget names no source
Assisted-by: ClaudeCode:claude-opus-5-5
* test(tasks): my-work is the task widget; l10n tokens are not text
The my-work assertion reads the library `tasks` type. The l10n check no
longer collects a manifest value that is a record token (`@object.<field>`,
the notice link's label) as a string to translate, and the catalogues are
back in canonical order.
Assisted-by: ClaudeCode:claude-opus-5-5
* refactor(cells): case list cells as library config, app cell registry gone
- Days in status: library `number` cell with unit and the stuck flag.
- Lens columns: no widget; the library cell reads the withheld marker.
- Incomplete / on hold / draft: Cases `rowIndicators` (held via
`after: "now"`), the state column is gone.
- Status: library `badge` with `resolve` on the status type colour.
- Priority: library `badge` with `valueField: priority`, a colorMap and
the "set by hand" `titleWhen` tooltip.
- Unread: column gone, `showUnreadRows: true` on the Cases page.
- Store: `type: "store"` (CnStorePage) with the built-in items as config;
StoreGallery is gone.
- All seven cells, src/services/cellWidgets.js and the CnAppRoot
`cellWidgets` prop are deleted; specs ported to manifest and library
cell assertions.
Needs the nextcloud-vue release carrying feature/dq-abstract-l1-config
(number cell, withheld default, row indicator dates, titleWhen,
valueField, showUnreadRows, translated store items).
Assisted-by: ClaudeCode:claude-opus-5-5
* docs(tasks): the simple My tasks note names the library widget on both profiles
Assisted-by: ClaudeCode:claude-opus-5-5
* refactor(cases): the deleted cases list is an endpoint index
CasesDeleted becomes `type: "index"` over dossiq's /api/cases/deleted
(entitySource `endpoint`). Restore and destroy are row actions that open
CnActionDialog, which posts and shows the server's refusal sentence; the
list reads its rows again after an act. The refusal sentences move to the
server (CaseRecycleController answers `message` beside `code`), and each
row carries `windowNote` ("12 days left", "the window has passed") for the
line under its date. DeletedCasesView.vue and caseRecycleApi.js go; the
lens spec and the e2e follow the declaration.
Needs the nextcloud-vue release with feature/dq-abstract-l2-index-row-modal
(row actions of type open-modal, refresh on cn:page:refresh).
Assisted-by: ClaudeCode:claude-opus-5-5
* fix(forms): lint, l10n order and four specs on the forms branch
The field-list Compare row action compares against `@row.originalRef`, the
token the manifest schema accepts, so the built simple manifest validates.
The registry orphan check counts a field-list row action's `dialog` as a
way to reach a registry dialog. The party widget count is the nine requester
overrides plus the represented party there were before, sorted. The contact
on a contact moment is asked through the party widget wherever a form asks
it; the Log contact forms preset it. Import order and l10n catalogue order
fixed.
Assisted-by: ClaudeCode:claude-opus-5-5
* fix(l10n): English entries for the deleted cases dialogs
feature/dq-abstract-l2-index-pages added the restore and destroy dialog
strings and the days-left plural to the Dutch catalogue only. The JS
catalogues are rebuilt with scripts/build-l10n-js.js.
Assisted-by: ClaudeCode:claude-opus-5-5
* chore(deps): bump @conduction/nextcloud-vue to ^2.117.0
Syncs the vendored manifest schema to the installed one for the lag check.
Assisted-by: ClaudeCode:claude-opus-5-5
* test: the ratchet and the team queue follow the L1 and L2 page moves
feature/dq-abstract-l1-config makes Store a library store page and drops the
team queue's unread column for unread rows; feature/dq-abstract-l2-index-pages
makes CasesDeleted an endpoint index. Neither branch moved the custom page
ratchet or the team queue spec.
Assisted-by: ClaudeCode:claude-opus-5-5
* style(cases): wrap the retention refusal sentence under 150 characters
feature/dq-abstract-l2-index-pages added the line at 168 characters, which
phpcs refuses.
Assisted-by: ClaudeCode:claude-opus-5-5
* fix: batch 22 CI reds (phpmd, l10n order, deleted cases saved views)
- CaseRecycleController takes the translator as a tenth collaborator for the
window note and refusal sentences (feature/dq-abstract-l2-index-pages);
the coupling and parameter-count rules are suppressed with the reason, as
the repository's other wide controllers do.
- l10n/nl.json is put back in canonical order (npm run test:l10n:write) and
nl.js rebuilt.
- CasesDeleted joins the index pages without a filter sidebar in the saved
views spec: /api/cases/deleted takes only limit and offset, so a view saved
there would hold nothing.
Assisted-by: ClaudeCode:claude-opus-5-5
* fix(case): write the picked role to the Add party form RoleTypePicker emitted `select`, but CnFormDialog mounts a form-field widget listening for `input` and `update:modelValue` only, so a picked role never reached the form. Emit update:modelValue and read the modelValue the dialog binds. Assisted-by: ClaudeCode:claude-opus-5-5 * refactor(cases): retire dead pages, components and registry keys Removes code nothing mounts: LocationPicker (and the leaflet and leaflet-draw dependencies it alone used), PropertyDefinitionFields with its vocabulary and concept-scheme services, InspectionPanel, and the DeelzaakList and DeelzaakDetail pages. Drops the unused registry keys BesluitvormingLeafTab, CaseNotesTab and CaseTimelineTab; their components stay under the keys that mount them. registerNavCardGrid goes because nextcloud-vue 2.114.0 resolves nav-card-grid through its built-in widget fallback. The old sub-case addresses redirect: /cases/:id/deelzaken opens the parent on its Related tab, /cases/:parentId/deelzaken/:id opens the sub-case. E2e tests that opened the removed pages or targeted the #pd-add-* ids are parked with test.fixme and a reason. Assisted-by: ClaudeCode:claude-opus-5-5 * test(case types): drive the field vocabulary e2e through the manifest field form The two specs targeted #pd-add-* ids from a component no page mounted. They now open the case-type-fields-editor form. The form gains the list entry type (items) for an array field, so a set-valued answer can be declared there. Assisted-by: ClaudeCode:claude-opus-5-5 * feat(cases): create sub-cases and roll them up on the case page The Sub-cases section on a case's Related tab declares a createAction that opens DeelzaakCreateModal for the case on screen, shown only on an open case that is not itself a sub-case, and a summary line that rolls up how many sub-cases are completed. Both structure profiles carry it. DeelzaakCreateModal reads the parent and its case type itself when it is opened from the manifest, says why a closed case or a sub-case cannot take one, and refreshes the page and closes after a create. It is a registered modal again, so it leaves the unimported list. The deelzaak-support e2e scenarios for create, roll-up and the parent link run on the case page; the delete-from-list tests go with the page. Needs the nextcloud-vue object-list createAction and summary keys (feature/dq-abstract-l8-dead there); on the current release the section renders as before, without the action and the roll-up. Assisted-by: ClaudeCode:claude-opus-5-5 * refactor(forms): bulk acts, field filters, party and role fields, templates, file set and rebind fields on the library The bulk dialogs mount CnBulkJobProgress and CnSelectionScope with the case wording; the Cases page declares relatedFieldFilters; requester and represented party are the form's party widget with manifest sources; the Role field is the form's resource widget scoped to the case type; the search plan and the close form use CnTemplateSelect; the delivered set's items are a field-list widget whose Compare opens DocumentCompareDialog; the rebind fields are CnSettingsField; the party kinds editor uses CnOrderedListField. Deletes BulkJobProgress, BulkSelectionScope, CaseTypeFieldFilters, PartySearchField, partySources, RoleTypePicker, roleTypeOptions, RecordTemplateSelect, TemplatePicker, FileSetItems and RebindPropertyField, and the InitiatorPicker, RoleTypePicker, CaseTypeFieldFilters and file-set-items registry keys. Needs @conduction/nextcloud-vue with feature/dq-abstract-l5-forms. Assisted-by: ClaudeCode:claude-opus-5-5 * feat(substitution): substitution admin lives only in the admin settings Ruben's decision (20 Oct 2026): one place. The app page /substitution-admin, its menu entry and its registry key go; the Substitution tab of the admin settings keeps the console. The old address goes on to that tab (RETIRED_ROUTES), and the e2e opens the console there. Merges feature/dq-abstract-l8-dead for its RETIRED_ROUTES entries. Assisted-by: ClaudeCode:claude-opus-5-5 * feat(cases): the Sub-cases section says why it offers no Create sub-case A closed case and a sub-case get the createAction hiddenNote in the action's place, the sentence the old list page showed. Assisted-by: ClaudeCode:claude-opus-5-5 * feat(case): the Proposals tab stands in the case strip while proposals wait Board PtVoorstelBeoordelen draws the case with a Voorstellen tab and its count in the strip. The simple profile kept Proposals under More at all times. It now sits after Contact, shows only while portaliq's queue route answers proposals for this case, and counts them from the same route, so a reader who may not review, a case without waiting proposals and an instance without portaliq keep today's strip. Needs the nextcloud-vue release that resolves @objectid in an endpoint condition and counts an endpoint's list (feat/tab-endpoint-visibility-and-count). Assisted-by: ClaudeCode:claude-opus-5-5 * refactor(lifecycle): the act fields are library input declarations CaseLifecycleMenuDialog draws the chosen act's inputs with the library's CnTransitionInputFields and decides whether it may confirm, and what it sends, with readTransitionInputs. What each act asks is declared in src/utils/caseActInputs.js: the result template (applied to the reason, never over typed text), the case type's pause reasons with Other falling back to the reason text, the reason (one line beside the days on suspend, a text area elsewhere, label above it tied by id), the result picker, the return date, and the days with the legal basis of the picked reason as helper and the comes-back-on preview. The archive summary, retention facts, read-only notice, dialog title and confirm icon are the archive act's declarations instead of act.id branches. The dialog's reason, result, until, days and pause reason fields become one values object. Only what an act asks now is sent, so text typed before a declared pause reason was picked instead of Other is no longer posted. Deletes CaseActFields.vue and pauseReasonChoice.js; their specs are ported to the declarations and to the library's own specs. Needs @conduction/nextcloud-vue with feature/dq-abstract-l5b-actfields. Assisted-by: ClaudeCode:claude-opus-5-5 * fix(forms): lint, l10n order and four specs on the forms branch The field-list Compare row action compares against `@row.originalRef`, the token the manifest schema accepts, so the built simple manifest validates. The registry orphan check counts a field-list row action's `dialog` as a way to reach a registry dialog. The party widget count is the nine requester overrides plus the represented party there were before, sorted. The contact on a contact moment is asked through the party widget wherever a form asks it; the Log contact forms preset it. Import order and l10n catalogue order fixed. Assisted-by: ClaudeCode:claude-opus-5-5 * fix(case): Proposals follows the DqZaak tabs and goes under More Where PtVoorstelBeoordelen and DqZaak draw a different case strip, the dossiq board wins: Overview, Documents, Contact, Tasks and Case history keep their five places, so Taken stays in the strip. Proposals now stands after Case history and, while proposals wait, is listed under More with their count. Assisted-by: ClaudeCode:claude-opus-5-5 * feat(cases): a Suspended lens on the case list DqZaken, DqZakenSorteren, DqFilterBeheren and DqNieuweZaak draw the case list's view strip ending in "Opgeschort": the open cases whose term stands still. A pause under Awb 4:5 lives on the case's term row (deadlineInstance status paused, written by DeadlinePauseService), not on the case, so the lens asks OpenRegister for the case through the term rows that point at it (_related, query-related-schema-rows), the way the organisations list asks for its open cases. The simple structure shows it as the sixth counted view after Woo requests, as the boards draw the strip; the full structure keeps its four pills and lists it last behind the overflow chip. Assisted-by: ClaudeCode:claude-opus-5-5 * fix(landing): name the My work / My team switch "Display" DqMijnWerk and DqMijnTeam label the landing page's view switch "Weergave"; the page called it "Whose work". The label is the switch's accessible group name and reads "Weergave" in Dutch. Assisted-by: ClaudeCode:claude-opus-5-5 * test(registry): the sub-case create modal is mounted again feature/dq-abstract-l2-substitution-admin (2479605) mounts DeelzaakCreateModal from the Sub-cases section's create action and empties KNOWN_UNIMPORTED; the merge kept development's entry, so the branch's change is restored. Assisted-by: ClaudeCode:claude-opus-5-5 * chore(deps): bump @conduction/nextcloud-vue to ^2.118.0 Syncs the vendored manifest schema to the installed one for the lag check. Assisted-by: ClaudeCode:claude-opus-5-5 * test: the substitution admin page leaves the menu and the custom page count feature/dq-abstract-l2-substitution-admin moves substitution admin into the admin settings, which drops its menu entry and its custom page; neither spec had moved with it. Assisted-by: ClaudeCode:claude-opus-5-5 * docs(settings): name the spec on the background service group feature/dq-abstract-l2-settings-forms-d added the computed without an @SPEC anchor (hydra gate 16). Assisted-by: ClaudeCode:claude-opus-5-5 * docs(cases): name the spec on the sub-case types the create form offers feature/dq-abstract-l2-substitution-admin (2479605) changed the computed without an @SPEC anchor (hydra gate 16). Assisted-by: ClaudeCode:claude-opus-5-5 * test: page and tab counts follow substitution admin and the proposals tab Compared with development, one page and one menu entry move and one tab changes kind; nothing a user has is lost: - SubstitutionAdmin (menu: Substitutions & reassignment) moves into the admin settings; /substitution-admin goes there (54dcb5d). - Proposals stops being a fixed overflow tab and shows while proposals wait on the case, with portaliq installed (feat/case-proposals-tab). The page counts drop by one (58 -> 57, 75 -> 74), and the domain-tab spec leaves Proposals out of the case type domains it lists. Assisted-by: ClaudeCode:claude-opus-5-5
* feat(cases): the assistant as a tab on the case page DqZaakAssistent draws the assistant inside the case page, in the AI-toezicht tab; it was reachable only through the launcher's floating window. The simple case page gets an AI oversight tab holding the same AI Chat Companion, embedded through nextcloud-vue's `ai-chat` widget, with the case as its context and hermiq required. It waits under Acties with the other panels and joins the strip while open. The hex and the Assistant sidebar tab stay. Assisted-by: ClaudeCode:claude-opus-5-5 * feat(cases): the AI oversight tab lists what the assistant did and the macros DqZaakAssistent draws the AI-toezicht tab with a table of the assistant's suggestions on the case, a Macro's card and the chat. The tab held only the chat. It now stacks an object list over hermiq's advisory approvals for this case (moment, user, question, outcome, model), the library macros widget over the case schema's macros, and the chat. Both sources exist; dossiq does not yet report decisions to hermiq and the case schema declares no macros, so both cards say so. Assisted-by: ClaudeCode:claude-opus-5-5 * feat(cases): the assistant chat beside the AI oversight tab DqZaakAssistent draws the chat in the side column beside the AI-toezicht panel, not inside it. The tab gets an id, its panel stacks the activity list and the macros, and the chat moves to the side column with `tabs: ["ai-oversight"]`, so it shows only while that tab is open. It follows the four generic side cards, which keeps a case type's own side-card list valid. Assisted-by: ClaudeCode:claude-opus-5-5 * feat(cases): the case schema ships the board's two macros DqZaakAssistent's Macro's card lists "Woo-verzoek afronden" and "Opschorten voor aanvulling", and the case schema declared no macros. It now declares both as actions with macro: true, bound by name to two manual flows it declares: status to Besluit and the Publiceren task; and the term suspended, then the handler asked to send the message Aanvullende gegevens. Suspending needed a flow step, so a generic dossiq.suspendTerm node runs the same pause the Termijn card registers, under the case type's rules. Every changing step carries a label for the card's last-run line. Assisted-by: ClaudeCode:claude-opus-5-5 * chore(l10n): rebuild the browser catalogues for the AI oversight strings Assisted-by: ClaudeCode:claude-opus-5-5 * feat(cases): the AI oversight tab gives the side column to the assistant DqZaakAssistent draws the Assistent card alone beside AI-toezicht, but the four generic side cards showed beside every tab. They now declare notTabs ["ai-oversight"] (nextcloud-vue side-card-not-on-tabs) and stand aside while that tab is open. Assisted-by: ClaudeCode:claude-opus-5-5 * feat(cases): AI-toezicht reads its records through hermiq hermiq#1172 makes AI oversight records readable only through their subject, so the AI-toezicht list reads GET /apps/hermiq/api/ai-oversight/subject for the case (object-list endpointSource) instead of the OpenRegister list. It names hermiq's new unused status "Niet gebruikt" and carries the board's subtitle. Assisted-by: ClaudeCode:claude-opus-5-5 * feat(cases): a case type chooses the macros its cases offer The case schema declares its macros, so every case type offered every one: Woo-verzoek afronden on an objection. caseType gets `macros`, the keys its cases offer in order; the Woo request lists both; and the Macro's card reads the list through nextcloud-vue macrosFrom. A case type that lists none offers none. Assisted-by: ClaudeCode:claude-opus-5-5 * test(architecture): the term suspension node asks nobody The queue-source architecture test lists every flow node that may ask a person. dossiq.suspendTerm registers a pause and asks nobody; in a macro the askPerson step after it does the asking. Classified in the allowlist with that reason. Assisted-by: ClaudeCode:claude-opus-5-5 * fix(cases): move the case schema to 1.46.0 for its macros The macros and their flows live in the case schema's configuration, which OpenRegister's importer does not compare, so an instance that already had 1.45.0 would skip them on import. The version moves and the digest record is updated. Assisted-by: ClaudeCode:claude-opus-5-5 * test(schemas): record the digest of the caseType macros fragment Assisted-by: ClaudeCode:claude-opus-5-5 * feat(cases): whoever may edit a case may run its macros Ruben decided who may run the macros: whoever may edit the case. The two macro actions had no rule of their own, so OpenRegister's default decided. Each now carries the case's update rule, the same groups and assignee match, and a test keeps the two equal. Assisted-by: ClaudeCode:claude-opus-5-5 * fix(case): hand the loaded case to the attention strip CaseBannerStack bound only objectId on CaseAttentionPanel. The strip reads attentionMarkers and riskAssessment off objectData, so on the live case page neither the markers nor the risk assessment were ever drawn. Assisted-by: ClaudeCode:claude-opus-5-5 * fix(case): read the case title from objectData in the programme section CaseProgrammeSection declared a prop `object`, but CnDetailWidgetHost binds the loaded case as `objectData`, so the link dialog always got an empty case title. Assisted-by: ClaudeCode:claude-opus-5-5 * fix(case): stop the review panel shadowing the library document-review widget dossiq registered DocumentReviewPanel under `document-review`, the key of nextcloud-vue's library widget (CnDocumentReviewWidget). The app registry resolves first, so the app key replaced the library widget for any page of this app asking for it. Register the panel as `document-relevance-review` and point the case Review tab at it. The widget id `case-document-review` is unchanged, so saved arrangements and the menu layout keep finding it. Assisted-by: ClaudeCode:claude-opus-5-5 * feat(reports): shape the processing-time and process-mining figures on the server Add GET /api/reports/processing-time?period&caseType&view&threshold. It answers the blocks the processing-time dashboard drew from every case, case type and status loaded into the browser: sla (+ slaSummary), distribution (+ distributionTarget), trend, throughput, atRisk and breakdown, each in the shape a chart, stat or object-table widget reads through responsePath. Rows carry severity and status words beside the colour keys. A case type filter matches id or slug, `truncated` says the load hit its limit, and the reporting audience gate refuses everyone else with its sentence. The unfiltered figures are handed to the OpenRegister analytics leaf under the existing procest-sla-* keys. /api/reports/process-mining accepts `period` (preset) and `view`, and answers the summary, dwell, throughput, bottlenecks and byAssignee blocks plus the clock-disclosing column labels beside the existing report. The quarterly deadline report adds `rows`, the per-type figures as a list named by case-type title, with the penalty total in euros. The JS shaping specs (doorlooptijdHelpers, doorlooptijdChartShaping, processMiningShaping, dwellTimeClock) are ported to PHPUnit. Assisted-by: ClaudeCode:claude-opus-5-5 * feat(dashboards): processing time, process mining and deadline reports as library widgets The three report dashboards are now manifest config over chart, stat and object-table widgets on the server-shaped report endpoints; the dossiq widget components, their mixins, the shaping modules, the doorlooptijd and processMining stores and their API clients are deleted. - Processing time: four charts (compliance by type, distribution, monthly trend, weekly throughput) on /api/reports/processing-time, one view each. The cases at risk and the deadline list of one case type are the same at-risk object-table; the second is narrowed to its case type by configuration (id or slug), not by "title contains woo". Severity is a translated enum badge, so text sits beside the colour, and rows open the case. The breakdown is a sortable table that names each status band. - Process mining: four stat tiles, a dwell chart, a throughput chart and two tables on /api/reports/process-mining views. The duration headings and the dwell series name come from the report's `labels`, so they still say which clock the numbers are on; the hint sentences are subtitles. - Deadline reports: the quarterly report is an object-table over the report's `rows` with CSV export, percent and euro formats and English column text; the annual audit is three stat tiles. Quarter and year are page filters. - The mail parties report is nextcloud-vue's CnCountTablesReport, configured in mailPartiesReport.js. - The substituted-work card on My work is dropped (Ruben, 20 Oct): the work queue carries covered work. The annual audit summary adds totalEuros and warningCount; the at-risk severity reads "at risk" from fourteen days left, as the deadline list did. Depends on the unreleased nextcloud-vue branch feature/dq-abstract-l6-dash (endpoint notices, exportCsv, labelPath, namePath, quarter/year page filters, CnCountTablesReport). Assisted-by: ClaudeCode:claude-opus-5-5 * docs(audit): the processing-time calculator's date buckets are not a term Assisted-by: ClaudeCode:claude-opus-5-5 * feat(reports): the document review reports page as dashboard config, read on request The reports page is a dashboard: a date range, the throughput table on /api/woo/reports/throughput with `loadOn: "request"`, the mail parties report as a registered CnCountTablesReport widget, and the CSV as a header link carrying the page's period. The throughput endpoint records every read on the audit trail of the cases it counts, so the table reads only when the reader presses Show: a plain visit records nothing. Each half shows only while its report is offered, read from the new GET /api/reports/offered (the same answer the menu reads). The throughput endpoint reads a moment from the date range as the tenant's calendar day. The custom WooReportsView is deleted. Assisted-by: ClaudeCode:claude-opus-5-5 * refactor(case): the record widgets are library config (DQ-ABSTRACT L4) The case page's record widgets are declared in the manifest over nextcloud-vue widgets, and dossiq's sixteen copies are gone: - banner row: a `sections` widget over a `banner` (archived, on @self.archived), a `status-explainer` (/available-transitions) and an `attention-flag` (/attention). New-since-you-looked is counted on the tabs (`badgeSource: readState`, files and notes) and cleared on open; CnDetailPage keeps the read stamp and Mark as unread. - followers: the header popover only (Ruben, 20 Oct 2026); the People tab section and the simple profile's Followers card are gone. - location map (`map`), parties (`parties`), contact moments in the customer record (`record-list` with row actions and an "Also on" line), family plan (`sections`: review-due banner and grouped cards), related cases (`related` with endpoint sections, the parent and Plan follow-up), programme and work instruction (`facts`), Notes tab (the notes leaf with mentionUrl and the push action), redaction page (`redaction` page type), First today (`banner` naming the first row). - Widget ids users may have stored are unchanged (family-plan, case-pipelinq-contact-moments and the rest); L7 renames them. - FileContactMomentDialog and LinkProgrammeDialog are registry modals the widgets open; both ask the page to refresh on success. - Helpers only the deleted components used are pruned; the reading moved to nextcloud-vue (objectParties, statusDeclaration, fieldRules). - Specs: the declarations are asserted here (recordPageLibraryWidgets and the rewritten specs); the behaviour specs moved to the nextcloud-vue widgets. The DQ-BUGS specs for the attention strip and the programme title assert the fixed declarations. - check:manifest treats a page type only the newer schema lists as a library lag; the vendored schema is 2.137.0. Depends on nextcloud-vue feature/dq-abstract-l4-record and feature/dq-abstract-l4-record-b (unreleased): with the installed 2.114.0 one spec, the note push, waits for that release. Assisted-by: ClaudeCode:claude-opus-5-5 * test(manifest): tell a value or branch lag from a defect; vendor schema 2.138.0 The reports page's header link drops its `_note`, which $defs/action refuses. The validator now also asks the vendored newer schema about a path when the installed one refuses a value or an anyOf branch there (the generated quarter and year page filters): with nothing refused near that path in the newer schema, the error is the library lagging. The vendored schema is the nextcloud-vue branch's 2.138.0, ahead of the installed 2.136.0 until that release lands. Assisted-by: ClaudeCode:claude-opus-5-5 * chore(manifest): record the deadline page's dependency on nextcloud-vue schema 2.139.0; vendor it Assisted-by: ClaudeCode:claude-opus-5-5 * feat(example-set): Pieter Jansen owns a saved view on the case list The saved-view boards (DqFilterBeheren, -Bewerken, -Delen, -InMenu, -Verwijderen) draw the case list's side panel on Weergaven with the reader's own views and their row menu: edit, share, add to the menu, delete. That menu exists only on a view the reader owns, and the example data gave the boards' handler none. The Zuiddrecht set now gives him "Termijn deze week": his open cases with a deadline within seven days, sorted on deadline, scoped to the case list. Its conditions are the shipped default view "Mine, due this week", so it names no status or case type id. Needs OpenRegister's example-set views and Pieter in the cast (openregister r21/cast-pieter). Sharing and the menu entry are not seeded: an example-set view writes name, description, owner, isPublic, query, presentation and alert only. Assisted-by: ClaudeCode:claude-opus-5-5 * fix(enforcement): the advice page follows board DqHandhaving The enforcement advice page drew a Follow toggle the board does not, put the recommendation and the deviation as full-width data panels where the board has side cards, and titled its history card Geschiedenis where the board and the other record pages say Historie. - follow: false on LhsRecommendationDetail - Aanbeveling and Afwijking en definitief become side cards with every field the panels showed; deviating stays the header's edit action - the main column holds the matrix and the violation - the history card uses "Record history" (nl Historie) Assisted-by: ClaudeCode:claude-opus-5-5 * fix(organisations): the organisation page's history card reads Historie Board DqTenant titles the side card Historie, as the contact and organisation record pages do; the organisation page used "History", which reads Geschiedenis in Dutch. Assisted-by: ClaudeCode:claude-opus-5-5 * feat(procurement): contracts, suppliers and portal accounts share one set of tabs Board DqContracten draws Contracten | Leveranciers | Portaalaccounts. The procurement pages now link the supplier portal accounts as a third tab, shown to an admin only and without a count there (the library still requests a hidden tab's count). The accounts page gets the same three tabs; it stays admin-only on its own. Assisted-by: ClaudeCode:claude-opus-5-5 * fix(lists): task and case type lists read as boards DqTaken and DqZaaktypen The simple profile's task list searched "Zoeken..." and headed its due column Termijn; board DqTaken says "Zoek op taak of zaaknummer" and Deadline. The case type list searched "Zoeken in deze lijst"; board DqZaaktypen says "Zoek een zaaktype". Assisted-by: ClaudeCode:claude-opus-5-5 * chore(deps): bump @conduction/nextcloud-vue to ^2.119.0 Syncs the vendored manifest schema to the installed one for the lag check. Assisted-by: ClaudeCode:claude-opus-5-5 * chore(register): move the register to 0.20.63 and bump the app version The macros branch moves the case schema to 1.47.0, caseType to 1.28.0 and the Woo-verzoek case type to 1.4.12, so the register moves once over development's 0.20.62. Assisted-by: ClaudeCode:claude-opus-5-5 * fix(l10n): put the merged catalogues back in canonical order The batch's merges appended keys out of order; npm run test:l10n:write sorts them (no key added or dropped) and the JS catalogues are rebuilt. Assisted-by: ClaudeCode:claude-opus-5-5 * test(reports): drop the imports only the moved admin switches used Assisted-by: ClaudeCode:claude-opus-5-5 * test(landing): the simple dashboard may have no slots at all feature/dq-abstract-l4-record moves First today onto the library banner, the last slot the simple dashboard named, so its slots map can be absent. Assisted-by: ClaudeCode:claude-opus-5-5 * test(registry): the sweep floor follows the retired record and report components Development held 104 registry entries; this batch retires 28 (the L4 record widgets and the L6 report dashboards, now library config) and adds 3, so 79 remain. Every name the manifests still use resolves (the registers-every-name case passes), and none of the retired keys is a type, component, handler, widget or target in any manifest. Assisted-by: ClaudeCode:claude-opus-5-5
The Gemachtigde role of kenteken-henk was looked up by name alone, which matches the generic role type and the vth package's two per-case-type ones, so the installer refused the set wherever vth was installed. It now also asks genericRole "gemachtigde", which only the generic role type holds. The Woo decision type lookup names "WOO-besluit" as well as its case type. A new test resolves every dossiq lookup of the set, chained lookups included, against the rows the register, register.d, the packages and the repair seeds ship, and fails when one matches more than one row. Assisted-by: ClaudeCode:claude-opus-5-5
The inspectionChecklistRun schema requires case, and the run in progress shipped without one, so OpenRegister refused the whole Zuiddrecht set on install. The run belongs to the terrace roofing case Esra handles. A test now checks every dossiq object of the set against its schema's required properties. Assisted-by: ClaudeCode:claude-opus-5-5
* feat(reports): shape the processing-time and process-mining figures on the server
Add GET /api/reports/processing-time?period&caseType&view&threshold. It
answers the blocks the processing-time dashboard drew from every case,
case type and status loaded into the browser: sla (+ slaSummary),
distribution (+ distributionTarget), trend, throughput, atRisk and
breakdown, each in the shape a chart, stat or object-table widget reads
through responsePath. Rows carry severity and status words beside the
colour keys. A case type filter matches id or slug, `truncated` says the
load hit its limit, and the reporting audience gate refuses everyone else
with its sentence. The unfiltered figures are handed to the OpenRegister
analytics leaf under the existing procest-sla-* keys.
/api/reports/process-mining accepts `period` (preset) and `view`, and
answers the summary, dwell, throughput, bottlenecks and byAssignee blocks
plus the clock-disclosing column labels beside the existing report.
The quarterly deadline report adds `rows`, the per-type figures as a list
named by case-type title, with the penalty total in euros.
The JS shaping specs (doorlooptijdHelpers, doorlooptijdChartShaping,
processMiningShaping, dwellTimeClock) are ported to PHPUnit.
Assisted-by: ClaudeCode:claude-opus-5-5
* feat(dashboards): processing time, process mining and deadline reports as library widgets
The three report dashboards are now manifest config over chart, stat and
object-table widgets on the server-shaped report endpoints; the dossiq
widget components, their mixins, the shaping modules, the doorlooptijd and
processMining stores and their API clients are deleted.
- Processing time: four charts (compliance by type, distribution, monthly
trend, weekly throughput) on /api/reports/processing-time, one view
each. The cases at risk and the deadline list of one case type are the
same at-risk object-table; the second is narrowed to its case type by
configuration (id or slug), not by "title contains woo". Severity is a
translated enum badge, so text sits beside the colour, and rows open the
case. The breakdown is a sortable table that names each status band.
- Process mining: four stat tiles, a dwell chart, a throughput chart and
two tables on /api/reports/process-mining views. The duration headings
and the dwell series name come from the report's `labels`, so they still
say which clock the numbers are on; the hint sentences are subtitles.
- Deadline reports: the quarterly report is an object-table over the
report's `rows` with CSV export, percent and euro formats and English
column text; the annual audit is three stat tiles. Quarter and year are
page filters.
- The mail parties report is nextcloud-vue's CnCountTablesReport,
configured in mailPartiesReport.js.
- The substituted-work card on My work is dropped (Ruben, 20 Oct): the
work queue carries covered work.
The annual audit summary adds totalEuros and warningCount; the at-risk
severity reads "at risk" from fourteen days left, as the deadline list
did. Depends on the unreleased nextcloud-vue branch
feature/dq-abstract-l6-dash (endpoint notices, exportCsv, labelPath,
namePath, quarter/year page filters, CnCountTablesReport).
Assisted-by: ClaudeCode:claude-opus-5-5
* docs(audit): the processing-time calculator's date buckets are not a term
Assisted-by: ClaudeCode:claude-opus-5-5
* feat(rename): UI-facing names say what they do, with aliases for the old ones
What the UI calls and names no longer carries a procedure word, and
nobody who used the earlier name loses anything.
- Routes: /api/checklists, /api/cases/{id}/checklist-results,
/api/deadlines/{dashboard/kpi, reports/quarterly|annual|first-response|
open-workload-age, definitions, calendar, instances/{id}/pause|resume|
extend|complete}, /api/payments/callback and
/api/document-review/reports/throughput. Every old URL stays routed to
a <method>LegacyPath() delegate with the same auth posture (AppHost
rejects duplicate route names); the payment callback's old URL is
permanent because the payment provider is configured with it.
- Deadline reports carry generic keys beside the old ones for one
release (total, withinTermPct, penaltyTotalCents, period, year, ...).
- Processing-time series publish under dossiq-sla-* and procest-sla-*.
- Widget ids dt-* -> processing-time-*, td-* -> deadline-report-*,
family-plan -> goal-plan, case-pipelinq-contact-moments ->
linked-contact-moments; WooReports -> DocumentReviewReports at
/document-review-reports, /woo-reports redirects. RewriteRenamedLayoutIds
rewrites them in stored buildiq arrangements.
- Document review report settings on generic keys, read with a fallback
to the old keys; CarryRenamedSettingKeys copies them over.
- Settings files renamed (DeadlineDefinitionsTab, DeadlineDefinitionEditor,
DelegationMatrixTab, DelegationImportPanel, DelegationMatrixTable,
RoleAssignmentsTable, RoleTreeManager, ChecklistTemplatesTab). The role
tree is CnTreeView; the checklist template editor is CnFormDialog with
the items as sub-objects, without the Dutch placeholder.
- NC dashboard ids procest_* stay frozen.
Assisted-by: ClaudeCode:claude-opus-5-5
* test(rename): role tree, renamed UI names and the refused checklist save
Assisted-by: ClaudeCode:claude-opus-5-5
* fix(rename): lint on the renamed files; tree update event and button variants
Assisted-by: ClaudeCode:claude-opus-5-5
* fix(rename): phpmd and eslint on the renamed settings and reporting files
Assisted-by: ClaudeCode:claude-opus-5-5
* chore(deps): bump @conduction/nextcloud-vue to ^2.120.0
Syncs the vendored manifest schema to the installed one for the lag check.
Assisted-by: ClaudeCode:claude-opus-5-5
* test(rename): the reports page is a library dashboard
development (batch 24) made the reports page a dashboard with no app view,
so the renamed page is checked by its type and no reports view is registered.
Assisted-by: ClaudeCode:claude-opus-5-5
* fix(rename): hydra findings of the rename batch
- The fifteen deprecated path aliases declare @contract exclude, as the
existing StUF aliases do: each calls the canonical method its tests cover
(gate 25).
- The role tree's roles watcher names its spec (gate 16).
- The app version moves so the two new repair steps run on upgrade (gate 110).
Assisted-by: ClaudeCode:claude-opus-5-5
OpenRegister refuses a view alert without recipients, so the Zuiddrecht install skipped zoek-lindelaan and DqZoekresultaten had no saved search. Thomas, the view's owner, is now its one recipient: since openregister#4685 only the owner or an administrator may name others. Assisted-by: ClaudeCode:claude-opus-5-5
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Automated PR to sync development changes to beta for beta release.
Merging this PR will trigger the beta release workflow.