Kenii Releases

August 2026

2.12.0

Handbook Builder fix, safer catalog-year cloning, in-app staff accounts, and editor gaps closed.

  • Added A Team screen for administrators to invite and manage Catalog Editors from inside Kenii. Enter a name and email and the person receives an email to set their own password, then they can sign in and edit the catalog without a separate WordPress account. Only administrators see the screen, so an editor cannot create more editors.
  • Added Campus descriptions are now editable. The campus editor has a rich-text Description field that shows on the campus page. Previously the page could display a description but there was no way to write one in the app.
  • Added New catalog years start as a private draft instead of publishing immediately, so a year is never public while it is still empty. New Publish and Return to Draft actions let you make a year public (visible alongside the active year) when it is ready, or pull it back.
  • Fixed The Handbook Builder now edits the handbook that actually appears on the site. Previously sections built in the admin were saved to a place the public handbook never read, so building a handbook had no visible effect. The Builder now organizes the real handbook pages directly, and existing handbooks are unchanged.
  • Fixed Cloning a catalog year now re-links each credential's requirements and plan of study to the cloned courses instead of pointing back at the source year, and it shifts the academic calendar dates and term titles forward by the year difference. Cloned years are now a correct starting draft rather than one that references the previous year's courses and dates.
  • Fixed Continuing education course pages no longer show an empty "Schedule" or "Course Description" heading when the field has been cleared. The section now appears only when there is real content.

2.11.1

Documentation moved to the website.

  • Changed The user documentation now lives on the Kenii website instead of inside the plugin. The in-admin documentation viewer has been removed, and the Help & Support link in the sidebar opens a configurable documentation URL, set under Settings > Display. This keeps the docs current in one place and makes the plugin smaller.

2.11.0

Students can now search the handbook.

  • Added A search box on the student handbook page. As a student types, the handbook filters live: policies that do not match hide, sections with matches open automatically, the term is highlighted, and a result count and a clear "no results" state update as they go. It searches the full text of each policy, not just the visible titles, so a term that appears deep in a policy still finds it, with a short snippet showing where. Works on a phone, needs no page reload, and can be turned off per site in Settings under Display.

2.10.4

A correctness fix for colleges outside North Carolina, plus wording cleanup in curriculum messages.

  • Fixed Career projection data no longer assumes North Carolina when a college has not chosen its state. The Bureau of Labor Statistics state is already an admin setting, but two code paths ignored it and defaulted to North Carolina, so an unconfigured site could show another region's projections. They now follow the setting and default to national data until a state is chosen. Colleges that have set their state are unaffected.
  • Fixed Cleaned up the punctuation in proposal validation and status messages.
Show 2 earlier releases from August 2026

2.10.3

Multiple campuses are now first-class in the catalog. Colleges with more than one location can show which campuses a program or course is offered at, publish a page for each campus, and let students filter the program listing by campus.

  • Added Programs and courses now show the campuses where they are offered, each linked to a page for that campus with its address, contact details, and the programs available there. A campus directory lists every location, students can filter the program listing by campus, and campuses are assigned from the program and course editors.
  • Fixed Campus assignments are now saved. Previously a campus chosen in the program or course editor was accepted on screen but dropped when the record was saved, so no campus ever appeared on the site.

2.10.2

A small fix to the public catalog. On narrow screens, large page-hero titles like “Career Pathways” could break in the middle of a word; they now scale to fit and always wrap on whole words.

  • Fixed Page-hero titles no longer break mid-word. The shared hero heading used a fixed large size that overflowed its box on smaller screens, splitting long words (for example "Pathways" rendered as "Pathwa / ys"). It now uses a fluid size that caps on desktop and scales down on narrow screens, wrapping on whole words. This applies everywhere the hero is used, including the Pathways landing pages.

July 2026

2.10.1

A small accessibility patch. Checkboxes and close buttons in the admin were smaller than the WCAG 2.2 AA minimum touch target, making them fiddly to hit , especially on touch screens. They’re now sized correctly.

  • Fixed The academic-year setup checkboxes (term selection and "clone dates") and the dialog close buttons were below the 24×24px minimum touch-target size (WCAG 2.2 AA, 2.5.8). They're now sized to meet it, so they're easier to tap and click.

2.10.0

This release makes the admin **translatable and easier to read**. The whole interface can now run in another language, high school (CCP) pathways are far easier to find and edit, and the dark theme and contrast issues that made a few screens hard on the eyes are fixed.

  • Added The admin is now fully translatable. Every screen in the Kenii admin , labels, buttons, messages, tab names, table headers, empty states , reads through WordPress's standard translation system, so a college can run the whole interface in another language by dropping in one language file. Ships a translation template (`languages/kenii-catalog-admin.pot`, ~2,400 phrases) for translators, detects the WordPress site/user language automatically, and leaves English unchanged for everyone else.
  • Added A "HS Pathway" indicator and filter on the Pathway Programs list , each program shows how many of its credentials have an active high school (CCP) pathway, and a "Has HS pathways" filter narrows the list to just those. Finding which programs carry high school pathways is now a glance instead of a hunt.
  • Changed Replaced the earlier lightweight admin translation layer with the native WordPress one (`@wordpress/i18n`), so translations use the same tools every WordPress translator already knows (Poedit, Loco, translate.wordpress.org) and load without a rebuild. Stored data (course codes, saved settings, credential-type tokens) stays canonical and untranslated , only what a user reads on screen is localized.
  • Fixed The "Enable CCP Pathways" toggle now reflects and saves its real state. It was loading off on every visit regardless of what was saved, hiding a program's credentials until it was manually switched on , confusing on programs that already had pathways configured.
  • Fixed Requirement group cards no longer render as bright white blocks in dark mode , they now use the theme's dark surface, so the Requirements editor reads cleanly in the dark theme.
  • Fixed The CCP phase editor is easier to read and work with , the grade, term, subject, and course-name fields no longer truncate ("Secondary", full course names, and subjects now fit).
  • Fixed Fixed a color-contrast shortfall on "Missing"/error badges so they meet WCAG AA (4.5:1) against their light background.

2.9.0

This release makes the catalog **easier to read, easier to trust, and easier to show off**. Public catalog text now grows when a visitor turns up their browser’s font size, so low-vision readers finally get larger type. The licensing that keeps your modules running got sturdier , it survives a stalled site scheduler, shows you when it last checked in, and keeps Help & Support reachable even during a billing hiccup. The Curriculum module’s validation got simpler: regulatory defaults apply in one click, proposals are checked against your own catalog, and a course-library import that could only ever be half-complete is gone. It also ships a guided product tour for demos and the groundwork for translating the admin into other languages.

  • Removed Removed the state-pack course-library import , the custom reference-course table, its importer, admin screen, and the bundled North Carolina sample. It could only ever ship a partial, unmaintainable slice of one state's course list; the "code in reference library" check went with it. The validation rules the pack carried live on as a preset (above), and the catalog-code checks (above) cover the real need against your own courses.
  • Added A guided product tour for demos and onboarding , an in-app walkthrough that carries a viewer through one course change, from a curriculum proposal to committee approval to the live catalog page and Compass. Off by default and loaded only where a site opts in, so it never ships to ordinary visitors.
  • Added Optional catalog-code checks in validation , flag a New Course proposal whose code already exists in the catalog, or a Revise Course proposal whose code has no matching catalog course (advisory by default, read straight from the catalog with nothing to import).
  • Added One-click rule presets on the Validation screen , apply a named, provenance-stamped set of regulatory defaults (credential envelopes and change thresholds) instead of typing them in; review and save, and it's yours to edit.
  • Added The license client now accepts more than one signing key, so the license service can rotate its signing key without interrupting any live site (the plugin selects the right key by a content-derived id and falls back to trying all pinned keys).
  • Added Internationalization groundwork for the admin , a lightweight translation layer so admin screens can be localized by adding a language file instead of rewriting each screen, detecting the WordPress site language (English-only today).
  • Changed License check-ins are resilient to a stalled WordPress cron , the plugin re-confirms entitlement on admin visits as well, on a ~12-hour cadence , and the Account screen now shows when the license was last checked, when it checks next, and a heads-up if a site hasn't confirmed in over two days.
  • Fixed Public catalog text now scales with the visitor's browser text-size preference , every frontend font size moved from `px` to `rem` across program, course, and credential pages, so readers who enlarge their default text finally get larger type (WCAG 1.4.4 Resize Text).
  • Fixed Help & Support stays reachable when a site's license is suspended or lapsed , the admin no longer collapses to the Account screen only, so a customer with a billing problem can still open a support ticket.

2.8.0

This release is about **who can run the catalog and how polished it looks**. Catalog staff can now do their jobs without a full administrator account, names with an “&” , like “Accounting & Finance” , display correctly everywhere, and old catalog years now retire themselves on schedule. Curriculum committees also get faster bulk approvals, a personal “My Work” page, and an at-a-glance view of what’s ready to act on.

  • Added Staff can manage the catalog without an administrator account , a Catalog Editor can now create, edit, and preview unpublished programs, credentials, courses, and handbook pages. Everyone who could edit catalog content before keeps that access.
  • Added Approve several proposals at once , select with checkboxes and use "Approve Selected" to advance each one, with a clear summary of what went through and what didn't.
  • Added A personal "My Work" page with Authored and Watching tabs, plus a watch star on every proposal so you can follow the ones you didn't submit.
  • Added Meeting agendas show an "X of Y complete" readiness badge on each proposal so a committee can see what's ready before the meeting.
  • Changed Catalog years retire on their own , the public catalog-year window is enforced automatically, the moment the setting changes and once a day, so old years roll offline without anyone doing it by hand.
  • Fixed Ampersands display correctly , names like "Accounting & Finance" no longer show as "Accounting & Finance" on the live site or in new demo data.
  • Fixed The gate that hides administrator-only navigation now works; it was previously ignored because of a data-type bug.
  • Fixed Release builds regenerate the readme changelog from the changelog file and fail on any drift, so the two can't disagree.
Show 10 earlier releases from July 2026

2.7.0

This release is about **who can get into Kenii, and how**. Catalog staff now have a permission of their own instead of borrowing an administrator’s, so nobody needs a full admin account just to edit the catalog. **Two things need checking before you upgrade**: the Catalog Editor role no longer grants general WordPress editing, so anyone who relied on it to edit ordinary pages needs a second role, and anyone who reached Kenii only through that general permission will lose access until they are granted the new one. Catalog documentation also now appears in Help & Support on multisite installs.

  • Added New `kenii_manage_catalog` capability so catalog staff no longer need an administrator account.
  • Changed The Catalog Editor role no longer grants `edit_posts`. Sites relying on it for general content editing must assign a second role.
  • Changed Kenii access now requires the `kenii_manage_catalog` capability; users who reached Kenii only through `edit_posts` will lose access.
  • Changed Administrator-only screens (Settings, Account, and the audit log) are hidden from catalog editors instead of showing a form that fails on save.
  • Fixed Catalog documentation was missing from Help & Support on multisite installs.

2.6.1

A single fix. **The dashboard could report catalog completeness above 100%** , it now tops out where you would expect.

  • Fixed Catalog completeness on the dashboard no longer shows over 100%.

2.6.0

A tidy-up pass across the admin. **Spacing and type now follow one scale**, a duplicated brand colour was consolidated, and the search icon no longer overlaps the text beside it. Nothing changed about how anything works; it simply looks consistent from screen to screen.

  • Changed Admin design-consistency pass: complete spacing and type token scale, deduped brand color, search-icon overlap fix, and minor token cleanups.

2.5.0

This release is about **letting students find previous catalog years themselves**. A quiet “View a previous catalog year” link sits beside the results count on the Programs page and switches the listing to whichever published year they choose. If a year has no programs online but does have an uploaded catalog PDF, they get a download card instead of an empty page. The link only appears when more than one year is public, so nothing changes for a college running a single year.

  • Added Student-facing catalog year switcher on the Programs page: a quiet "View a previous catalog year" link beside the results count opens a small dropdown of the public catalog years and switches the listing to the chosen year (native “, no JavaScript). When a selected archived year has no online programs but has an uploaded catalog PDF, the page shows a "Download the {year} Catalog (PDF)" card with a link back to the current catalog, instead of an empty list. The control only appears when more than one public year exists.

2.4.0

This release is about **help being where the work is**. Every module now carries its own documentation inside the plugin , tutorials, how-to guides and reference , browsed from Help & Support with a switcher that hides anything the college is not licensed for. A support form sits alongside it and shows exactly which site details will be sent before anything leaves. Behind the scenes the admin’s design system is now enforced by the build rather than by discipline: nine button styles, one input style, and a check that fails if a screen invents its own.

  • Added Per-module in-plugin documentation, discovered from three manifests (Kenii Catalog, Pathways, Curriculum) and browsed from Help & Support with a module switcher. A locked module's docs never appear. Tutorials, how-to guides, reference, and explanations for each module, rewritten against the current product , including a step-by-step guide to building requirements with groups and subject rules.
  • Added Support form in Help & Support: subject, category, and message, with the site context (URL, plugin version, active modules, WordPress and PHP versions) shown to the user before sending. Submissions email the support address with reply-to set to the sender and a copy back to them; an honest failure state shows the address to write to directly if mail can't send.
  • Changed Design-system conformance is now enforced, not just intended. The admin ships exactly nine button variants and one input style; a CI rail (`tests/design-conformance.mjs`) fails the build if any component styles its own button or form control, or renders a button that isn't the shared primitive or an allowlisted structural control. Every admin button and form field was swept onto the shared framework.
  • Changed Brand alignment of admin controls to the Kenii design system: form inputs (light border, 12×16 padding, purple focus ring, eyebrow labels), the nine buttons with their exact spec, and a shared field-rhythm wrapper so every labeled control has consistent spacing , also enforced by the rail.
  • Changed Helper text across the editors uses one quiet framework style instead of oversized per-editor paragraphs; the CIP-code hint reads in plain English.
  • Changed Program-listing accordion toggles are a transparent circle with a light border that fills with the brand color on hover, open, and keyboard focus, replacing an opaque gray disc.
  • Changed Admin and frontend stylesheets bust their browser cache when the file changes, not only on a version release.
  • Fixed Accessibility: the requirement rule ("Choose one of the following", "Take N credits from") is now the course table's “ , its native, programmatically-associated label , instead of a loose paragraph; subject-prefix rules (not a table) keep `role="group"` with `aria-labelledby`. Assistive technology announces the rule as the list's label.

2.3.1

Two accessibility fixes for anyone using a keyboard or a screen reader. **The “Skip to main content” link works again** on program, credential, course and archive pages, and each requirement rule , “Choose one of the following”, “Take N credits from” , is now properly attached to the course list it governs, so it is announced as that list’s heading instead of read out as stray text.

  • Fixed Accessibility: catalog single and archive templates now render a “ landmark instead of a bare “, restoring the theme's "Skip to main content" target on program, credential, course, and archive pages.
  • Fixed Accessibility: each requirement rule ("Choose one of the following", "Take N credits from") is now programmatically tied to the course list it governs , `aria-labelledby` on the course table, `role="group"` on subject rules and grouped sections , so assistive technology announces the rule as the list's label instead of reading it as loose text.

2.3.0

The largest release so far, and really two things at once. **Curriculum arrives as a full module**: propose, review, approve and record course changes, with approval workflows the college configures, committee voting with quorum and thresholds, meeting agendas, a field-by-field redline of what is changing, and a printable evidence package for accreditation. Nothing a committee is still debating touches the live catalog until an approval deliberately writes it into a catalog year. **Credential requirements also gained real degree-audit structure** , groups with rules like “take all”, “choose one”, or “take 49 credits from these subjects, maximum 12 per subject”, which is one rule where it used to take hundreds of rows. Existing requirements keep working untouched. Colleges can also now manage their own lists , program areas, credential types, delivery modes, transfer institutions , without leaving Kenii for the WordPress admin.

  • Added Requirement groups: credential requirements now express real degree-audit structure. A section can hold multiple groups, each with its own rule (take all, choose one, take N credits, take N courses, or complete N of the child groups), and sections can be grouped under headings with auto-summed credit subtotals. A group's members are either an explicit course list or a subject rule , a set of course prefixes with optional level exclusions, a maximum-credits-per-subject cap, and a note , so "take 49 credits from these subjects, max 12 per subject" is one rule instead of hundreds of rows. Legacy flat requirements parse forever and render unchanged; a credential upgrades to the new shape the first time it is saved. One shared traversal layer (`includes/requirements.php` and its JS counterpart) serves every consumer , public rendering, junction-table reverse lookups (explicit courses only; subject rules deliberately never inflate "programs using this course"), Compass, exports, year diffs, and editor counts. On the public page a subject rule renders as a sentence with each prefix linked into the prefix-filtered course directory. The credential editor gains the group/heading structure with progressive disclosure: a plain course list looks and works exactly as before.
  • Added `FormSection` shared primitive: titled card sections with an optional collapsible "Advanced" mode, used to restructure the program, credential, and course editors , identity fields first, everyday fields next, rarely-touched settings collapsed. Layout and hierarchy only; no field was removed, renamed, or moved to different storage.
  • Added In-app management for the remaining customer-defined catalog taxonomies, so every list a college maintains stays inside Kenii with no trip to raw WordPress. A new "Manage Lists" hub (in the Catalog sidebar) links to standardized management screens , matching the Program Areas pattern (page shell, shared row actions, add/inline-rename/guarded-delete) , for credential types, program types, delivery modes, course prefixes, and transfer institutions. The generalized admin REST controller now serves all of them behind the same in-use delete guard (refuses with the assigned-record count rather than orphaning) and duplicate-name rejection, decoding entities on intake and read and audit-logging every create, rename, and delete. Credential-type usage is counted across both programs and credentials. Structural values that the catalog's logic depends on are guarded: the program types "Curriculum" and "Continuing Education" (which drive the curriculum vs continuing-education rendering split) cannot be renamed or deleted, and the default "In Person" delivery mode cannot be deleted (its display label may still be changed, since the default is keyed by slug). Course prefixes are derived from course codes, so free-create is intentionally not offered; existing prefixes can be renamed for display (the slug is preserved so derivation keeps matching) and deleted only when unused. Transfer institutions gain rename and guarded delete to complete their in-app management. The fixed two-value `course_type` system vocabulary is deliberately excluded, as its values drive course rendering and are not a customer-editable list.
  • Added In-app program-area management. Program areas can now be created, renamed, re-parented, and deleted entirely inside Kenii , no trip to the WordPress taxonomy screen. A gated admin REST controller (`kenii/v1/admin/program-areas`) lists areas with the count of programs using each, creates them (rejecting duplicate names), renames/re-parents them, and deletes them behind an in-use guard that refuses with the assigned-program count rather than orphaning programs. A "Program Areas" management view (reached from a "Manage Areas" action on the Programs list) presents the areas in a table with add, inline rename, and guarded delete. The program editor's area field gains an inline "+ Create new area" affordance that adds and selects a new area without leaving the flow. The controller is structured to generalize to the other Catalog taxonomies via an allowlist; only `program_area` is wired in this release.
  • Added Curriculum module (license-gated): a complete curriculum-governance workflow for proposing, reviewing, approving, and recording course changes , new, revise, and discontinue proposals that stay isolated from the live catalog until an approval deliberately writes them into a catalog year. The module comprises:
  • Added Proposals , , draft course proposals (new, revise, discontinue) stored as an independent `kenii_proposal` entity that is isolated from catalog-year queries by construction. The proposal payload speaks the canonical field-bag vocabulary so the change-review redline reuses the existing diff engine. Gated REST endpoints and admin Proposals list + editor surfaces; the proposal data layer registers regardless of entitlement.
  • Added Institution-configured validation , , a validation engine driven entirely by rules the college configures for itself, stored in one site option. Admins set required fields per proposal type, a credit-hour range, credential total credit-hour envelopes, and an effective-dating check , each rule carrying a blocking or advisory severity. At submission a blocking violation aborts the proposal with the list of failed checks; advisory violations attach as non-blocking warnings. The engine is generic and ships no external or regulatory data; with no rules configured every submission passes. A gated Validation screen loads and saves the rule set, and the proposal editor surfaces blocking and advisory results distinctly.
  • Added Importable state packs , , an optional onboarding seed that pre-fills a reference course library and the institution's validation rules from a state's published values. A pack is imported once and then owned by the college , Kenii never runs it live, nothing auto-updates, and no pack asserts compliance; every pack-derived check is advisory by default and the active pack always shows its captured date honestly. The reference course library lives in its own isolated table, completely separate from the real catalog: a pack import can never create, modify, or delete a real course, program, or credential, and never changes a catalog-year count. Imports upsert and archive-flag reference courses (retired codes are archived, never deleted or reused). Three import paths , a bundled pack file, admin upload, and `wp kenii pack-import` (dry-run by default). A North Carolina pack ships bundled. A new optional `course_code_in_library` validation rule (advisory by default) flags proposal course codes absent from the active reference library. A gated State Pack screen shows the active pack, imports packs, and browses the reference library as a clearly labeled reference menu.
  • Added Workflow engine , , configurable approval workflows (`kenii_workflow`, structured step builder , steps, role/user assignees, participation modes, conditional step injection rules) with a seeded "Standard Curriculum Approval" template. Proposals submit into a route snapshot frozen at submission , later workflow edits never touch in-flight proposals , with approve/return/hold/resume decisions, an append-only decision log, and step/decision notifications.
  • Added Committee voting , , any approval step can be a committee vote with a quorum and threshold (simple majority, two-thirds, or unanimous). Members record approve/reject/abstain with optional notes into an append-only votes table , a changed vote supersedes the prior one, the tally uses each member's latest vote, and the full history is preserved. A step advances automatically only when quorum and threshold are met; when the threshold becomes mathematically unreachable no automatic action is taken and a member returns the proposal with a reason. The frozen route snapshot also freezes each step's committee configuration and membership.
  • Added Meetings and agendas , , track meetings (title, date, notes) and view a live agenda of every proposal currently awaiting a committee vote, each with its running tally and a link to the review screen; votes cast while a meeting is selected are recorded against that meeting for a minutes trail. A meeting with recorded votes cannot be deleted.
  • Added Review screen , , field-by-field redline of proposed vs current content (formatted rich text for descriptions), catalog impact via credential requirement/plan-of-study usage, discussion comments, and FYI notifications to affected colleagues , with the approve/return/hold/resume decision bar inline.
  • Added Substantive-change radar , , an advisory decision-support layer that computes signals on a proposal (credit-hour change vs the current record, a rough new-content magnitude, program-closure detection, delivery-method change) and flags where a configurable threshold may be crossed , it never asserts that a change is substantive. The threshold values are admin-editable configuration data (stored in the same validation-rules option, seedable via a state pack) carrying an honest "policy as of , verify against current policy" marker and no authority claim. When a signal crosses at submission the radar sets a `substantive_change` flag, which the workflow rule engine turns into an injected accreditation-liaison review step; setting the flag routes a human in and decides nothing, and the radar never changes proposal state or blocks submission on its own. The institution's determination is a human answer (yes / no / unsure + rationale) recorded on the proposal as accreditation evidence , Kenii never sets it automatically , with the latest answer kept and every change audit-logged. The review screen carries a radar panel with the signals, their thresholds, an advisory disclaimer, and the determination control.
  • Added Approval materializer , , final approval writes the change into the target catalog year through the catalog write services , new courses are created, revisions update the target year's counterpart course (matched by code), and discontinuations remove it. Draft and active years take record writes; published years receive an addendum documenting the change instead, so their records stay immutable; offline years are refused. Materialization runs at approval but never blocks it , a failure is recorded on the proposal with a Retry action, and re-running is idempotent. The review screen shows where the change landed (or the error), and the proposal keeps its full evidence trail.
  • Added Per-proposal evidence package , , a printable PDF that assembles a proposal's existing governance record , identification, the field-level change (redline), catalog impact, the approval history with its frozen route snapshot, committee votes and tallies, and the substantive-change signals with the institution's own determination , structured around the SACSCOC prospectus background-and-context outline. It is a factual record of what was proposed, who decided, how the committee voted, and what the institution determined; it asserts nothing on Kenii's behalf, shows the substantive-change answer as the institution's, and carries honest policy as-of dates with no compliance claim. Sections with no data read "none recorded". Any proposal state can export; the document is rendered through the existing catalog PDF pipeline, streamed from a gated endpoint, and every export is audit-logged. The review screen carries an "Export evidence package" action.
  • Added Reports and analytics , , six curriculum workflow reports with on-screen tables, HTML/CSS bar charts, and PDF export: Pending Proposals (active items and the step each is waiting on), Aging (open proposals ranked by total time in the workflow, day-bucketed), Bottleneck (per-step average and total active time across all history, work-in-progress count, and revisit count), Participation (per-reviewer assigned/acted/pending counts, average decision latency, and committee-vote turnout), User Activity (a single reviewer's decisions, votes, comments, and edits with time spent), and Historical Change (a single proposal's ordered decision timeline and time in each step). The append-only decision log now records a `submitted` transition so the stream is complete from step-zero entry, and a precomputed `{prefix}kenii_stage_durations` rollup , rebuilt idempotently on every transition and backfillable with `wp kenii rebuild-stage-durations [–commit]` , is the single source the reports read. Hold time is excluded from active time and tracked separately; a step re-entered after a return gets a new rollup row with an incremented visit number, and the bottleneck report sums every visit while surfacing the revisit count. Charts render identically on screen and in the PDF, which reuses the evidence-export Dompdf pipeline; every export is audit-logged. A gated Reports screen in the curriculum context carries the report picker, tables, charts, and per-report PDF export.
  • Added In-plugin documentation , , registrar-facing guides for the whole module (overview, proposals, workflows, committees and meetings, the review screen, validation rules and state packs, the substantive-change radar, and the evidence export) served through the in-plugin docs viewer.
  • Added Platform notification layer (`kenii_notify`): registered event catalog, role/user recipient resolution, per-user email opt-outs with a Notifications preferences screen in Settings. First events: addendum published, catalog year archived, license grace period.
  • Changed Brand alignment against the Kenii design system: form inputs adopt the brand treatment (10px radius, eyebrow labels, purple focus ring) through the shared field primitives; the sidebar's active item is now the brand's lime pill with dark text and an in-pill count badge; chart color 2 is the brand lime, and category bars cycle the five-token chart palette across Catalog, Pathways, and Curriculum report charts.
  • Changed Colorblind-safe status palette: Data Health and Pipeline good/ok/bad bars moved off green/amber/red onto a blue/amber/red set separated by lightness (`–kenii-status-*`), verified under deuteranopia and protanopia simulation, with non-color signals (labels, counts, warning icons) retained.
  • Changed Public frontend defaults align to the brand: Plus Jakarta Sans as the default font, the brand neutral scale, text and success colors , defaults only; sites with saved brand settings or custom CSS keep their exact look through the three-layer override system.
  • Changed Compare Catalog Years results render as separated entity cards with human names and design-system status badges; raw slug/key identifiers no longer appear, and a changed record expands to a field-level from → to view.
  • Changed Recent Activity and Recent Decisions lists across Catalog, Pathways, and Curriculum share one entity-type pill component with human labels, display names, and site-timezone dates.
  • Changed The Curriculum galaxy tile opens the module dashboard instead of the Proposals list, and the curriculum sidebar's settings entry reads "Curriculum Settings".
  • Changed Cross-module design-consistency pass (presentation only , no data model, behavior, report math, or REST contract changes). Catalog, Pathways, and Curriculum now share one visual system:
  • Changed Row actions , , a shared `RowActions` "primary + overflow" primitive (inline Edit plus a keyboard-accessible `⋯` menu, ≥24px targets) replaces the three previous patterns: Catalog's overflow-only menus, Pathways' bare Edit/Delete buttons, and the hand-rolled Catalog Years menu. It is now used by every list across all three modules (programs, program areas, credentials, courses, campuses, terms, policies, articulations, catalog years, pathways communities/institutions/programs, and curriculum proposals/workflows/meetings); the bespoke ContextMenu component was removed.
  • Changed Form fields , , the Add Course form no longer renders Course Code and Course Title at different heights; per-field size overrides were removed so both flow through the shared field primitive at one uniform height, padding, and typography. Course Code shows a `ACC-120` placeholder with a "Format: PREFIX-NUMBER" helper. Placeholder text across the admin was made example-form (never a real-looking value or institution name sitting in the box), and the small Pathways editors were moved onto the shared Field primitive.
  • Changed Charts , , a token-driven chart palette (`–kenii-chart-*`, anchored on the Kenii purple and green) replaces hardcoded hex values; the Catalog overview bars and the Curriculum report bars (Aging/Bottleneck/timeline) now draw from the same tokens.
  • Changed gains a module Overview dashboard matching the Catalog and Pathways dashboards (pipeline, needs-attention, recent decisions), and a Curriculum Settings hub that houses Validation and State Pack; the State Pack screen is reorganized into an Active-pack card, an Import card, and a drag-and-drop upload dropzone. Curriculum remains license-gated.
  • Changed Curriculum UI polish pass (presentation only , no data model, behavior, report math, or REST contract changes): decluttered every curriculum screen to one short helper line per section with the fuller narration behind disclosures or in Help; removed all command-line/developer affordances from the customer UI; State Pack reference-library search now filters as you type (single debounced field, no Search button) with a compact archived-courses toggle; the Validation required-fields grid gained a per-proposal-type "Require all / Clear" control; and the report charts (Aging buckets, Bottleneck per-step bars, Historical Change timeline) are now HTML/CSS bars that render identically on screen and in the Dompdf PDF, replacing the inline SVG that would not lay out in Dompdf.
  • Fixed An approved and materialized proposal's redline no longer renders empty: the target's field values are frozen at submission and the redline diffs against that snapshot, so the record of what changed survives the change itself being applied.
  • Fixed The Compare button on Compare Catalog Years aligns with the year selects, and the diff result cards are visually separated.
  • Fixed HTML entities imported into titles now decode at the intake boundary; `wp kenii decode-entities [–commit]` repairs existing records. The repair now also decodes stored taxonomy term names across the Kenii taxonomies (program areas, program/credential types, course prefixes and types, delivery modes, transfer institutions, catalog years), and term create/rename persist the decoded name so an ampersand renders as `&` everywhere , management screens, the program-editor area picker, and the front end , instead of a literal `&`.
  • Fixed The Program Areas management screen now uses the standard Catalog admin page shell (page padding, page-header block, and card/table spacing) so it matches the Programs, Credentials, and Courses lists instead of hugging the top of the panel.
  • Fixed Curriculum report PDFs rendered their charts as a run-together text blob above the table because Dompdf does not lay out inline SVG; charts are now HTML/CSS bars that render cleanly in the PDF.

2.2.0

This release is about **seeing what changed between catalog years**. A new comparison report shows added, removed, discontinued and edited programs, credentials, courses and policies between any two years, in a printable form a registrar can hand over. The handbook now renders per year as well, so each catalog year serves its own sections and its PDF matches. A migration is included for colleges whose older data shared records across years.

  • Added Year-to-year catalog diff report (admin): compare any two catalog years to see added, removed, discontinued, and field-level changed programs, credentials, courses, and policies, with a printable registrar-facing view
  • Added REST endpoint `GET kenii/v1/admin/catalog-years/diff` returning the structured year-over-year comparison
  • Added `wp kenii split-shared-years` migration: converts legacy shared-year data to true per-year records and assigns unassigned catalog records to the active year
  • Changed The handbook renders per catalog year: each year serves its own section tree (with a safe fallback for years without tagged sections), and the catalog PDF renders the handbook for its own year
  • Changed Internal write-service layer for programs, credentials, and courses (`includes/catalog-services.php`); the admin REST controllers are now thin wrappers over callable services. No user-facing change.
  • Fixed Year cloning no longer corrupts JSON meta containing escaped characters, no longer drops legacy program fields carried by hybrid credentials, and no longer copies internal snapshot/edit-lock keys onto the new year
  • Fixed Program hero subtitles render the program type (previously always empty)
  • Fixed Requirements and plan-of-study remapping no longer injects an empty course list into text-only sections

2.1.0

This release is about **speed and access**. Each screen now loads only its own data, with a skeleton while it arrives, so the admin opens in a fraction of the time it used to. Filters, search and grouping are kept in the address bar, which means a filtered view is a link you can send someone. **Accessibility went from 530 failures to zero**, checked automatically on every build against WCAG 2.2 AA rather than by hand.

  • Added Per-route data loading with skeleton loading states; the admin boots in a fraction of the time and fetches only what each screen needs
  • Added Filters, search, and grouping persist to the URL and survive reload; filtered views are shareable links
  • Added Toggle, ToggleRow, MediaPicker, InlineField, Tabs, and Lazy primitives complete the shared component library; every switch, media picker, tab strip, and table in the admin renders through one implementation
  • Added Automated WCAG 2.2 AA verification (axe-core) across every admin view, enforced in CI
  • Added Shared admin component library (Button, Field, Table, Card, Tabs, Skeleton, Spinner, confirm dialog, app-wide Modal and Toast) with existing admin screens migrated onto the primitives.
  • Changed All admin toggles use the settings-row layout with brand-color checked state
  • Changed Term list renders as grouped tables consistent with every other list screen
  • Changed Audit log detail rows are keyboard- and screen-reader-accessible
  • Fixed Accessibility: 530 WCAG violation nodes resolved to zero (contrast at root cause, accessible names on all controls, decorative icons hidden from assistive tech, 24px minimum targets)
  • Fixed Policy creation returns the standard API response envelope

2.0.0

The release where Kenii became **one plugin instead of several**. Every product module now lives in a single install and unlocks by licence rather than being installed separately, with a switcher in the sidebar to move between them. Licences are verified against Connect with a signed grant and keep working for 30 days if the site cannot reach us, so a network problem never locks a college out of its own catalog. Pathways moved inside as part of this.

  • Added Unified platform: a single plugin housing the catalog data foundation plus every WordPress product module as license-gated feature-sets.
  • Added Licensing client: Ed25519-signed entitlement grants verified against Connect, fail-open cache with a 30-day offline grace window, and a `KENII_ENTITLEMENT_OVERRIDE` override.
  • Added Galaxy module switcher driving one module context at a time in the sidebar.
  • Added Test rails: REST CRUD coverage across all custom post types and a headless screen smoke over every admin view.
  • Added Code-split admin bundle with lazy-loaded module route groups.
  • Changed Pathways is absorbed into the unified plugin (`includes/modules/pathways/`); its standalone repository is frozen as a rollback reference.