<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:media="http://search.yahoo.com/mrss/" xmlns:discourse="http://discourse.org/rss/modules/discourse/">
<channel>
<title>Governance on Roque</title>
<link>https://j-roque.com/tags/governance/</link>
<description>Recent content in Governance on Roque</description>
<generator>Hugo -- gohugo.io</generator>
<language>en</language>
<managingEditor>joao.roque.94@gmail.com (João Roque)</managingEditor>
<webMaster>joao.roque.94@gmail.com (João Roque)</webMaster>
<copyright>© 2026 João Roque</copyright>
<lastBuildDate>Wed, 14 Oct 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://j-roque.com/tags/governance/index.xml" rel="self" type="application/rss+xml"/>
<item>
<title>Auditing an MES Project as Telemetry</title>
<link>https://j-roque.com/posts/20261014-cmfaudit/</link>
<pubDate>Wed, 14 Oct 2026 00:00:00 +0000</pubDate>
<author>joao.roque.94@gmail.com (João Roque)</author>
<guid>https://j-roque.com/posts/20261014-cmfaudit/</guid>
<description>How big is a customer&amp;rsquo;s MES customization, and what is it made of? cmf audit, a CM CLI plugin, counts configuration and code per package type and stores each run as telemetry in the MES Data Platform, so projects can be tracked and compared over time.</description>
<content:encoded>&lt;p&gt;&lt;img src="https://j-roque.com/posts/20261014-cmfaudit/featured.png" alt="Auditing an MES Project as Telemetry" /&gt;&lt;/p&gt;&lt;p&gt;Ask how big a customer&amp;rsquo;s MES customization is and you get a shrug, a gut feeling or a spreadsheet that went stale two releases ago. That makes estimating, upgrades and governance guesswork.&lt;/p&gt;
&lt;p&gt;We built &lt;code&gt;cmf audit&lt;/code&gt;, a plugin for the CM CLI, to replace the shrug with numbers. It reads a project the way a build does, counts what it finds per package type, and posts the result as telemetry to the MES itself. It descends from the plugin approach in &lt;a
href="https://community.criticalmanufacturing.com/t/anatomy-of-a-script/694?sort=top"
target="_blank"
&gt;Anatomy of a Script&lt;/a&gt;, but this post is about what it measures, not how plugins work.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;figure&gt;&lt;img
class="my-0 rounded-md"
loading="lazy"
decoding="async"
fetchpriority="low"
alt="Title Video"
src="https://image.j-roque.com/posts/20261014-cmfaudit/titlevideo.gif"
&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;em&gt;What to look at: the audit running against a project and the results landing in the generated dashboards.&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 class="relative group"&gt;What Is an MES Project, Really?
&lt;/h2&gt;
&lt;p&gt;A &lt;strong&gt;Critical Manufacturing MES&lt;/strong&gt; project is not a running system. It is a repository: a root package that depends on a tree of versioned, typed packages, each delivered to a customer. The &lt;a
href="https://github.com/criticalmanufacturing/cli"
target="_blank"
&gt;CM CLI&lt;/a&gt; gives that tree a uniform structure, so we know every package type and broadly what it is for.&lt;/p&gt;
&lt;p&gt;A &lt;code&gt;Data&lt;/code&gt; package carries configuration as metadata: MES modeling, low-code workflows, business rules, master data. &lt;code&gt;Business&lt;/code&gt; and &lt;code&gt;HTML&lt;/code&gt; packages carry customization code. &lt;code&gt;IoT&lt;/code&gt; packages carry equipment integration tasks, converters and drivers.&lt;/p&gt;
&lt;p&gt;As the product grows, more behavior moves from code into that metadata layer: UI low code, IoT low code, rules configured instead of programmed. The customization does not disappear. It changes shape, and the share of a project that is code versus configuration is exactly what nobody measures.&lt;/p&gt;
&lt;p&gt;That is the question the audit answers, and the only honest answer is a set of numbers per project.&lt;/p&gt;
&lt;h2 class="relative group"&gt;What It Measures
&lt;/h2&gt;
&lt;p&gt;The audit runs one auditor per package type, plus one for the project root. Everything below comes straight from the plugin source.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style="text-align: left"&gt;Package type&lt;/th&gt;
&lt;th style="text-align: left"&gt;What &lt;code&gt;cmf audit&lt;/code&gt; collects&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align: left"&gt;&lt;strong&gt;Root&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: left"&gt;Project configuration from &lt;code&gt;.project-config.json&lt;/code&gt; (MES version, registries, generator and schematics versions). Package id, version, first-level dependency count, test package count, &lt;code&gt;global.json&lt;/code&gt; SDK and roll-forward, repositories, NuGet sources. &lt;strong&gt;Unused packages&lt;/strong&gt; (a &lt;code&gt;cmfpackage.json&lt;/code&gt; on disk that the root dependency tree never references). &lt;strong&gt;Committed scripts&lt;/strong&gt; (&lt;code&gt;.ps1&lt;/code&gt;, &lt;code&gt;.cmd&lt;/code&gt;, &lt;code&gt;.bat&lt;/code&gt;, &lt;code&gt;.sh&lt;/code&gt;).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left"&gt;&lt;strong&gt;Data&lt;/strong&gt; and &lt;strong&gt;IoTData&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: left"&gt;Files per content type (exported objects, process rules pre/post, entity types, DEE, master data, automation workflows). Exported objects by type and name. Process rule counts per execution. &lt;strong&gt;DEE&lt;/strong&gt; files with lines of code and cyclomatic complexity. &lt;strong&gt;Master data&lt;/strong&gt; record counts per entity, with the record content. &lt;strong&gt;Automation workflows&lt;/strong&gt;: tasks with inputs and outputs, code tasks with lines of code, MES service calls and entities mentioned, converters.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left"&gt;&lt;strong&gt;IoT&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: left"&gt;Tasks, converters and drivers with injects, inputs, outputs or parameters, and lines of code. Whether each one is &lt;strong&gt;bundled&lt;/strong&gt; with the package or lives in an Automation Task Library. &lt;code&gt;package.json&lt;/code&gt; dependencies. Totals for customization objects, tasks and converters.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left"&gt;&lt;strong&gt;Pipeline&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: left"&gt;The committed &lt;code&gt;Builds&lt;/code&gt; folder hashed against what the CM pipeline tool would generate today. Files only in the repo, only in the generated output, or present in both with different content. Local report only: this auditor does not post to the MES.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Two things the table hides. The auditor also records &lt;strong&gt;unaudited dependencies&lt;/strong&gt;, packages the root references that are not in the working copy, so a gap in coverage is visible rather than silent.&lt;/p&gt;
&lt;h3 class="relative group"&gt;How the Dashboards Use It
&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;Cmf.Audit&lt;/code&gt; package deploys Grafana dashboards on top of the telemetry. They are organized around the questions above: a project portfolio overview, a project governance view, a root package overview, data package overview and structures, the data model customization footprint, custom entity type properties, DEE actions and business rules, automation configuration maps, and for IoT the package overview, code tasks, converters, task components and dependencies.&lt;/p&gt;
&lt;p&gt;You can look at one project and see how many DEEs it carries and how complex they are, or how many IoT tasks are bundled versus shared.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Counts are weak proxies for complexity and quality. A project with 400 trivial entity types is easier to carry than one with ten 2,000-line DEEs, and the moment a count becomes a target people will game it. We use the numbers to start conversations and to see trends, never to score a team.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 class="relative group"&gt;What We Found
&lt;/h2&gt;
&lt;p&gt;By Project filtering, we can see the data governance. What are its packages, when was the last time it was audited, what are the versions it&amp;rsquo;s currently deploying and have a notion of scale.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;img
class="my-0 rounded-md"
loading="lazy"
decoding="async"
fetchpriority="low"
alt="Governance"
src="https://image.j-roque.com/posts/20261014-cmfaudit/governance.png"
&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;We can dig deeper and understand where our business complexity lies, if it&amp;rsquo;s on configurations or business rules, with dedicated screens.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;img
class="my-0 rounded-md"
loading="lazy"
decoding="async"
fetchpriority="low"
alt="Root Governance"
src="https://image.j-roque.com/posts/20261014-cmfaudit/root%20package%20overview.png"
&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;We can dig deeper and understand where we are hooking our custom business rules and how complex they are. This is a good metric to understand if you will have performance issues or if you are customizing out of your comfort zone.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;img
class="my-0 rounded-md"
loading="lazy"
decoding="async"
fetchpriority="low"
alt="DEE Deep Dive 1"
src="https://image.j-roque.com/posts/20261014-cmfaudit/dee%20deep%20dive%201.png"
&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;img
class="my-0 rounded-md"
loading="lazy"
decoding="async"
fetchpriority="low"
alt="DEE Deep Dive 2"
src="https://image.j-roque.com/posts/20261014-cmfaudit/dee%20deep%20dive%202.png"
&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;This is just a small sample of the types of drill downs and rabbit holes we can go to understand our project. Of course we are looking at snapshots, but over time if you audit every release, you are able to see how your solution is evolving.&lt;/p&gt;
&lt;p&gt;So what is an MES project? After the run above, the answer fits in one table: this many packages, of these types, carrying this much configuration and this much code.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;img
class="my-0 rounded-md"
loading="lazy"
decoding="async"
fetchpriority="low"
alt="Remote Audit"
src="https://image.j-roque.com/posts/20261014-cmfaudit/remote%20audit.gif"
&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;em&gt;What to look at: one command walking every project in the repository and posting each one&amp;rsquo;s audit to the local MES, with the projects appearing side by side in the dashboards.&lt;/em&gt;&lt;/p&gt;
&lt;h2 class="relative group"&gt;Why Telemetry, and Why the MES
&lt;/h2&gt;
&lt;p&gt;Auditing a project produces a snapshot: a set of measurements, at a point in time, about a thing with a hierarchical identity. That is the shape of telemetry. A telemetry store already knows how to keep timestamped values keyed by a hierarchy, aggregate them, and show them over time. Re-running the audit nightly or every release gives you a trend line for free.&lt;/p&gt;
&lt;p&gt;The first idea was to post to our global telemetry database. We dropped it for two reasons. It would force an outside-the-project dependency, and it would kill local runs. So we went with the MES we already ship.&lt;/p&gt;
&lt;p&gt;Every CM MES comes with the &lt;strong&gt;MES Data Platform&lt;/strong&gt;, the event-driven layer that ingests events, materializes them into a columnar database, and exposes them through datasets and Grafana dashboards (&lt;a
href="https://help.criticalmanufacturing.com/userguide/data-platform/"
target="_blank"
&gt;Data Platform user guide&lt;/a&gt;). That gives us ingestion, aggregation, dashboards and deployment without writing a backend. The dashboards and datasets are themselves a customization package, so they install with the same tooling as everything else, and teams can build their own with skills they already have.&lt;/p&gt;
&lt;p&gt;We used the same engine built for massive manufacturing data volume, to store our audit system.&lt;/p&gt;
&lt;p&gt;The audit is not a check of a running MES. It reads a repository, and the MES plays only one role: the data sink. That is also why a running MES and an access token are required to post results.&lt;/p&gt;
&lt;p&gt;There is a fair objection here. If the pitch is &amp;ldquo;run it locally, no outside dependencies&amp;rdquo;, needing a token and a reachable MES looks like a contradiction. It is a narrower promise than that. The audit itself runs locally and writes console output, CSV and Excel with no MES at all. Posting is opt-in (&lt;code&gt;--postEvent&lt;/code&gt;) and needs the MES host, a tenant and a security token, which belongs in &lt;code&gt;CMF_AUDIT_SECURITY_TOKEN&lt;/code&gt; rather than on the command line. The token is the price of the dashboards, and the audit posts master data record content for Data packages, so only send it to systems you are allowed to send it to.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The MES is the sink, not the subject. Wiring it up costs one token. In return, the history lives where the customer&amp;rsquo;s own dashboard skills already are.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 class="relative group"&gt;How a Project Becomes an ISA95 Path
&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;ISA95&lt;/strong&gt; is the standard that models a manufacturing enterprise as a hierarchy, from enterprise down to site, area and equipment. The &lt;strong&gt;CDM&lt;/strong&gt;, CM&amp;rsquo;s Common Data Model, follows that structure to identify where an event came from.&lt;/p&gt;
&lt;p&gt;The plugin borrows it, and the source comment says so plainly: &amp;ldquo;we will hijack the ISA95 for our context&amp;rdquo;. Every audit event is a &lt;code&gt;PostTelemetry&lt;/code&gt; with this mapping:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style="text-align: left"&gt;Audit concept&lt;/th&gt;
&lt;th style="text-align: left"&gt;ISA95 level&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align: left"&gt;Team project&lt;/td&gt;
&lt;td style="text-align: left"&gt;&lt;code&gt;Enterprise&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left"&gt;Package id&lt;/td&gt;
&lt;td style="text-align: left"&gt;&lt;code&gt;Site&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left"&gt;Package version&lt;/td&gt;
&lt;td style="text-align: left"&gt;&lt;code&gt;Facility&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left"&gt;Record type (&lt;code&gt;Task&lt;/code&gt;, &lt;code&gt;DEE&lt;/code&gt;, &lt;code&gt;PackageMetadata&lt;/code&gt;&amp;hellip;)&lt;/td&gt;
&lt;td style="text-align: left"&gt;&lt;code&gt;Area&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left"&gt;Record name&lt;/td&gt;
&lt;td style="text-align: left"&gt;&lt;code&gt;Resource&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Each measured value becomes a parameter on that resource: numbers are stored as numeric values, everything else as strings. A project, a package and a version get a unique, queryable identity without a single new entity in the data model.&lt;/p&gt;
&lt;p&gt;The ingestion uses the CDM &lt;a
href="https://developer.criticalmanufacturing.com/11.3/reference/api-data-platform/docs/index.html#operation-receive-PostTelemetry"
target="_blank"
&gt;Post Telemetry&lt;/a&gt; event, which is documented from MES 11.3. The audit package we ship targets 11.3, so treat 11.3 as the baseline. The plugin does not declare a minimum version in code.&lt;/p&gt;
&lt;h2 class="relative group"&gt;What Multi-Site Looks Like
&lt;/h2&gt;
&lt;p&gt;A customer with several sites rarely has one project. It has a baseline and a handful of site projects that drift from it. With the telemetry above, each site&amp;rsquo;s project posts under its own &lt;code&gt;Enterprise&lt;/code&gt; node, and the baseline posts under another. Putting them on one dashboard answers the questions a program manager actually asks: which site carries the most customization the baseline does not, which sites are behind on package versions, and which have unused packages nobody dares delete.&lt;/p&gt;
&lt;p&gt;The architecture below is how we ran it against the whole &lt;code&gt;mes-common-library&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;img
class="my-0 rounded-md"
loading="lazy"
decoding="async"
fetchpriority="low"
alt="Architecture"
src="https://image.j-roque.com/posts/20261014-cmfaudit/architecture.png"
&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;em&gt;What to look at: the audit reads projects from the remote repository and posts every result to one MES, which is the only place the data lives.&lt;/em&gt;&lt;/p&gt;
&lt;h2 class="relative group"&gt;Where This Fits
&lt;/h2&gt;
&lt;p&gt;Static-analysis tools such as SonarQube or CodeScene look at code quality and hotspots in any language. They do not know what a &lt;code&gt;Data&lt;/code&gt; package, an exported object or an IoT task library is. &lt;code&gt;cmf audit&lt;/code&gt; knows the CM package model and counts its units. It complements those tools and replaces none of them.&lt;/p&gt;
&lt;h2 class="relative group"&gt;Trying It
&lt;/h2&gt;
&lt;p&gt;The tool lives in &lt;a
href="https://github.com/criticalmanufacturing/mes-common-library/tree/main/utils/plugins/cmf-audit"
target="_blank"
&gt;mes-common-library&lt;/a&gt;, with the README covering build and options. The current release is &lt;a
href="https://github.com/criticalmanufacturing/mes-common-library/releases/tag/cmf-audit%2Fv0.0.1"
target="_blank"
&gt;audit v0.0.1&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Copy it into your MES customization and deploy it to your local registry.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;img
class="my-0 rounded-md"
loading="lazy"
decoding="async"
fetchpriority="low"
alt="Load Repo"
src="https://image.j-roque.com/posts/20261014-cmfaudit/loadrepoflow.gif"
&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;em&gt;What to look at: the package landing in the project&amp;rsquo;s local registry.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Then install it globally. If your registry does not proxy npmjs, add a scope filter such as &lt;code&gt;--@criticalmanufacturing:registry=https...&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;npm i -g @criticalmanufacturing/audit&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure&gt;&lt;img
class="my-0 rounded-md"
loading="lazy"
decoding="async"
fetchpriority="low"
alt="Install Audit"
src="https://image.j-roque.com/posts/20261014-cmfaudit/install%20audit.gif"
&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;em&gt;What to look at: the scoped install resolving from the private registry.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Run &lt;code&gt;cmf audit init&lt;/code&gt; to scaffold the pipelines:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;cmf audit init&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It adds a &lt;code&gt;CD-Audit&lt;/code&gt; pipeline and an audit step at the end of &lt;code&gt;CD-Containers&lt;/code&gt; (the pipeline that builds and deploys the project into containers). It also adds the &lt;code&gt;Cmf.Audit&lt;/code&gt; package with the dashboards and datasets, and a root dependency on it.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;img
class="my-0 rounded-md"
loading="lazy"
decoding="async"
fetchpriority="low"
alt="Install Audit Init"
src="https://image.j-roque.com/posts/20261014-cmfaudit/install%20audit%20init.gif"
&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;em&gt;What to look at: the prompts and the files the init command adds to the project.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The audit step needs a system access token to post results. We typically generate it before creating the default MES backup, so the same token survives every restore.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;img
class="my-0 rounded-md"
loading="lazy"
decoding="async"
fetchpriority="low"
alt="Create Access Token"
src="https://image.j-roque.com/posts/20261014-cmfaudit/audit%20run.gif"
&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;em&gt;What to look at: creating the access token that the pipeline will use.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Then run &lt;code&gt;CD-Audit&lt;/code&gt; directly, or let the final step in &lt;code&gt;CD-Containers&lt;/code&gt; do it.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;img
class="my-0 rounded-md"
loading="lazy"
decoding="async"
fetchpriority="low"
alt="Audit Demo"
src="https://image.j-roque.com/posts/20261014-cmfaudit/audit%20demo.gif"
&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;em&gt;What to look at: the pipeline run, then the populated dashboards.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;To audit projects without checking them out, use &lt;code&gt;review-remote-github&lt;/code&gt;. It downloads a project folder from a GitHub repository at a given ref, audits it locally and posts the results. Use &lt;code&gt;--repository&lt;/code&gt;, &lt;code&gt;--gitRef&lt;/code&gt;, and &lt;code&gt;--project&lt;/code&gt; or &lt;code&gt;--path&lt;/code&gt;, and set &lt;code&gt;GITHUB_TOKEN&lt;/code&gt; for private repositories. The default target is &lt;code&gt;criticalmanufacturing/mes-common-library&lt;/code&gt; on &lt;code&gt;11.3/dev&lt;/code&gt;. The &lt;code&gt;review-remote-ado&lt;/code&gt; command does the same for Azure DevOps.&lt;/p&gt;
&lt;p&gt;A clarification on pipelines: &lt;code&gt;cmf audit init&lt;/code&gt; only generates Azure DevOps YAML today. Running the audit against a GitHub-hosted repository works through the remote command, but you wire it into GitHub Actions yourself. The pipeline auditor also compares against Azure DevOps pipelines, so it needs Azure DevOps options even for a GitHub source.&lt;/p&gt;
&lt;h2 class="relative group"&gt;What Comes Next
&lt;/h2&gt;
&lt;p&gt;The tool is at v0.0.1 and it shows. &lt;code&gt;Business&lt;/code&gt; and &lt;code&gt;HTML&lt;/code&gt; packages have no auditor, and the metric set is a first guess. We will roll it out to customer projects and let their feedback decide the rest.&lt;/p&gt;
&lt;p&gt;Two uses are next on our list:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Upgrade effort estimation.&lt;/strong&gt; Pair the artifact counts (DEEs, code tasks, converters) with the target version&amp;rsquo;s breaking changes to price an upgrade before opening the repository.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Multi-site comparison.&lt;/strong&gt; Track every site against its baseline over time and see drift as it happens.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I have one specific question for you. Which artifact types should we audit next: &lt;code&gt;Business&lt;/code&gt; packages, &lt;code&gt;HTML&lt;/code&gt; and web customization, process rules, or something else you carry in your own projects? Tell us what you would measure, and what you would never want a dashboard to count.&lt;/p&gt;
</content:encoded>
<enclosure url="https://j-roque.com/posts/20261014-cmfaudit/featured.png" type="image/png" length="0"/>
<media:content url="https://j-roque.com/posts/20261014-cmfaudit/featured.png" type="image/png" medium="image"/>
</item>
</channel>
</rss>