Policy Not Prose

Never hard-code a decision's DATE or its AUTHOR into committed source, a comment, an XML doc comment, or documentation prose. State the rule; link to the policy record. The record carries the date and the name — once.

A rule written as "Maintainer, 2026-09-07: do it this way" embeds three different things in one sentence: the rule, when it took effect, and who decided. Only the first belongs in the place you are reading. The other two are data about the rule, and prose is the worst available store for them.

Why

Prose copies drift. The same decision gets restated in an AGENTS.md, two doc pages and a skill. Change the decision and you must find all four; you will find three. The fourth goes on instructing people for months, and it is indistinguishable from the live ones because they all look equally authoritative.

Names go stale faster than rules. People change roles, hand over areas, and leave. The rule outlives the attribution, so a name in a comment converts a durable instruction into something that reads as gossip about a decision nobody can now ask about. It also invites the wrong question — "is this still true, or just what someone said once?"

Prose cannot be queried. "Which policies are in force, and since when?" is a reasonable thing to ask a system. If the answers live in sentences scattered across repos, there is no answer — only a grep and a guess. A register answers it in one read.

The shape

A policy is a record with five fields and a link:

field what it is
id a stable slug — what other pages cite
value the decision itself, in as few words as carry it
status in force, or proposed when it was cited before it existed — the field the self-healing step below turns on
in force since the date it started applying
set by the role or identity that set it — a role where one exists

Everything else — source, comments, AGENTS.md, docs, skills — states the rule and cites the id. No dates, no names.

- # A What's New entry is written per RELEASE, not per change (maintainer, 2026-09-20)
+ # A What's New entry is written per RELEASE, not per change — policy `whatsnew-cadence`

🚨 What this does NOT forbid

This rule is about policy markers and attributions, not about dates as such. A date that is evidence stays exactly where it is:

Those are facts about events, and an event without its date is not a fact. The test is simple: would this date need changing if the decision changed? If yes, it is a policy marker and belongs in the register. If no, it is evidence and belongs where it is.

For review

A diff that introduces a hard-coded policy date or a person's name into source, a comment, an XML doc comment or doc prose is a review finding. The fix is never to delete the information — it is to move it: add or cite a register entry, and leave a link behind.

The finding is self-healing — it never blocks

A reviewer who finds a hard-coded date or name does not hand back a chore. They run a two-step that always terminates:

  1. Look for a policy that already covers it in the register below. Found → replace the prose with the citation. Done, no issue, one line changed.
  2. Not found → file an issue to introduce the policy, add a proposed row to the register naming that issue, and cite it in place.

The citation is written first and the policy catches up. That is the whole trick: the text is never blocked on the policy existing, and the reviewer is never asked to settle a policy question in a review thread — which is the thing that turns a two-line finding into a three-day argument. Because step 2 adds the register row immediately, a citation never dangles; what is pending is the ratification, not the reference.

This is why the rule converges without a migration. Nobody sweeps the corpus, but every page that gets edited for its own reasons leaves behind one more citation and, where it was missing, one more policy. The register fills from actual traffic — the decisions people actually touch — rather than from an archaeology project, and the pages nobody edits are, by definition, the pages nobody is misled by.

File the issue and carry on. Do not stop the change you came to make in order to ratify a policy you just discovered was implicit — that is the incidental-findings rule, and it applies here exactly as it does everywhere else.

This is the hamster wheel, applied to policy. Triage → implement → test, with every step filing what it finds back into triage rather than absorbing it: the same loop, and the same reason. A change that stopped to ratify every implicit policy it brushed against would land late, review badly, and abandon what it set out to do. The exit has to be cheap or the wheel stops turning — so the exit here is one register row and one issue, and then you carry on with what you were doing.

🚨 Forward-only. No backward migration.

This rule applies to what is WRITTEN FROM NOW ON. It is not a licence to sweep the existing corpus, and a pull request whose purpose is to retrofit old pages is out of scope.

The existing prose is not a defect. It records decisions that were taken and communicated the way the house wrote at the time, it is accurate, and rewriting it would touch a large number of pages to change nothing a reader relies on — while burning the review attention that new work needs. A migration would also be the more dangerous edit, because mechanical rewriting of attributions is exactly the kind of change that quietly alters meaning in the one page nobody re-reads.

So a reviewer checks the direction of travel: does this diff ADD a hard-coded policy date or name? If it does, that is the finding. If it merely fails to remove existing ones, that is not. Old pages migrate only when they are being edited anyway for their own reasons, and only the lines already being touched.

The register

A row is in force once ratified, or proposed when a reviewer cited it before it existed — a proposed row names the issue that will settle it, so the citation resolves from the moment it is written.

id value status in force since set by
module-live-update-default A module update goes live IN THE RUNNING PROCESS by default — each module in its own collectible load context; an update loads N+1, recycles the hubs bound to N and unloads N — with no flag, no opt-in, no governed activity and no approval. A restart is taken only when a module DECLARES restartRequired with a reason (a guard fails a module that blocks a live swap without the declaration) or when the live swap FAILS at runtime; then N keeps serving, the reason is recorded by name, and the automatic, approval-free self-update restart loads N+1. Modules update independently of the platform: platform contracts resolve from the running platform and are never bundled, admission is the declared floor against the running platform, and an image's module copy is only a boot baseline a newer generation supersedes live. Restart-required is legitimate ONLY for genuinely boot-time infrastructure — the declaration is [assembly: ModuleRestartRequired(ModuleBootCategory.<StorageDriver|Orleans|Authentication|Host>, "<why>")], a closed list; the guard (ModuleLiveUpdateGuard) fails any other category and any undeclared blocker. Owed: running the guard over every shipped module, the declarations, and the bundled-platform-assembly refusal in MeshWeaver.Plugins (slice 3). Manual: Live Module Update. in force 2026-10-05 maintainer
platform-semver-versioning Platform builds and images are versioned as plain SemVer <major>.<minor>.<run>. The patch is the monotonic CD run number, so the old 3.0.0-ci.<run> notation and the new one share ONE lineage, and the cut-over can never roll backwards. The minor is bumped deliberately; the major only on a declared break (the same-major-is-compatible roll rule). Main builds carry no pre-release label. Images carry the floating tags <major>-latest and <major>.<minor>-latest, moved forward only by the arm step. A deployment record follows a version PATTERN resolved against the registry (3.*), never a floating tag. The new notation starts at line 3.1 (PlatformReleaseOrder.SemVerEraStart). Readers land first, then the records' patterns, then the minter. Manual: Platform Versioning (SemVer). in force 2026-10-06 maintainer
tiered-pgo-off-5212 TEMPORARY STOPGAP for a .NET runtime defect, stated as one: every process that runs an in-process Roslyn Emit runs with DOTNET_TieredPGO=0 — the CI test, doc-gate and platform-compat jobs, the satellite lanes that compile or bake (node-repo-{compile-check,gate,module-pack,publish-bake}.yml, carried INTO each emitting docker run), and every portal through its Deployment record's extraPortalConfig (rendered by the chart's memex-portal-config ConfigMap). It complements the runtimeconfig half (<TieredPGO>false</TieredPGO>, #890), which reaches only hosts built from this tree. Every place it is set names #5212 and is removed when the runtime fix ships — with the split-arm measurement re-run on that runtime, never on faith. Root cause tracked in #5212 and upstream in dotnet/runtime. Manual: Node Type Compilation. in force 2026-10-07 maintainer
stale-adoption-bound A NodeType build the source has moved past keeps serving (StaleAdopted, same module MAJOR) only while it is at most N MINOR versions behind the current source; past N it is refused like a MAJOR bump, named on the node and logged at Error, and within N every judgement and /health's live record census say how far behind it is. N is Modules:StaleAdoptionMaxMinorVersionsBehind, default 5 (the shipped default, ratified as the value); a deployment may override it, and a negative value disables the bound. Settled on Systemorph/Memex#668. Manual: Node Type Compilation. in force 2026-10-07 maintainer
sole-maintainer-approval Every approval is four-eyes — the approver is not the requester — with ONE exception: the installation's DECLARED maintainer (Hosting:Operator:Maintainer, rendered from the deployment record's operator.maintainer; never a node an administrator can edit) may approve a request they filed themselves. ONE rule (SoleMaintainerApproval.Decide) decides it for every gate — instance actions, operation requests, and governed-activity signatures (a standard's own authority.maintainer). Every such approval is stamped who and when on the node, written to its log and shown on its page as "self-approved by maintainer"; everyone else still needs a different approver, and every other check of each gate is unchanged. Manual: Sole-Maintainer Approval. in force 2026-10-08 maintainer
whatsnew-cadence A What's New entry is written per RELEASE, not per change. A merge updates its doc page and mints no dated file. in force 2026-09-20 maintainer
issue-taxonomy-scope Classification covers OPEN issues only. Closed issues are not classified, not counted, and appear in no query. in force 2026-09-20 maintainer
release-blocker-gate A release may not be cut while any sev:B or sev:H bug is open in the seven repositories that carry the taxonomy; sev:M and sev:L never gate a cut. Enforced by the release.cut standard in the Governance package. in force 2026-09-20 maintainer
data-sync-approval Adding or widening the synchronisation of data needs a global admin's approval. in force 2026-09-20 maintainer
platform-backwards-compatibility Platform builds are backwards compatible within a major and a declared compatibility epoch — a ladder: a platform roll keeps the old plugin bytes (no rebuild, no re-seal) and plugins roll independently against the running platform. Compiled bytes are keyed on c<major>e<epoch>, never on a per-build identity (provenance only), and carry a platform range: floor (the producing build) ≤ running ≤ ceiling (open by default), else declined loudly naming both versions; platform assemblies bind whenever running ≥ compiled-against. Only a DECLARED break (an epoch or major bump in platform-compatibility.json, with a ceiling for the previous epoch) steps off the ladder and obliges a coordinated rebuild and seal; never seal or pin around a compatibility break — fix compatibility. Manual: Doc/Architecture/ModuleVersioning. in force 2026-09-25 maintainer
version-shapes Exactly two version shapes: X.Y.Z-ci.<n> and clean X.Y.Z. No rc, preview or labelled line is ever minted. in force 2026-09-07 maintainer
query-fanin-stall-terminal A query provider that neither emits, completes nor errors TERMINATES its merged query with a named error instead of hanging: the fan-in's Initial gate is a bound, not a wait. Every consumer that turns a mesh read into a decision reads that error as an availability failure — an access-control read fails CLOSED and reports that it could not be established, never denied and never granted. in force 2026-09-21 maintainer
dynamic-content-type-registration-pass Every replica registers the content type of each already-baked dynamic NodeType it has not activated, in a PACED, REGISTRATION-ONLY pass after the boot's bake settles and OFF the readiness path: it loads the existing bytes and builds the configuration on a transient probe, and never compiles or writes a NodeType record. The cost is the ~13.5 s of assembly opening #1660 removed from boot, moved to that background pass. Never from a read seam. Mechanism: DynamicContentTypeRegistrar (MeshWeaver.Hosting); manual: Dynamic Content Type Registration. in force 2026-09-25 maintainer
open-vocabulary-string-constants A vocabulary that is persisted, serialised, or extended by a module is a static class of const string named exactly as the enum would have been — never a C# enum. It stays OPEN: any other party may add its own values from its own constants class, so the platform's set is never treated as exhaustive. Consumers compare against constants and always carry a branch for a value this build does not know. in force 2026-09-21 maintainer
thread-graceful-error Wherever user code is executed, innermost in a thread, it must gracefully error: every failure path ends in a stamped terminal state on the node. A failure the thread's own hub cannot stamp — because it is the hub that died — is observed, cleaned up and relaunched under a bound, and what a relaunch cannot fix is filed into bug triage. The relaunch/dispatch side is bounded by a configurable pool cap (maxConcurrentAgents, default 50) whose queue is a page, not a log. in force 2026-09-20 maintainer
roll-migrates-first A schema change ships as a new image, and every roll runs that image's database migration FIRST — outside the portal, as its own run-once Job that must report succeeded — before the image moves. The operator half is hosting-migrate; the Roll plan calling it is the Plugins half. in force 2026-09-21 maintainer
db-migration-planned A database schema change is planned before it merges, and every step is enforced by code. Every migration is EXPAND-ONLY: the previous image must run correctly against the new schema, because old pods keep serving until new pods are fully ready (maxUnavailable: 0). A destructive change ships as a two-release expand→contract pair. A pull request that bumps DbVersion.Latest declares Db-migration: V<N> — <kind>; <compat>; rolls migrate-first and passes a rehearsal against a real Postgres (MeshWeaver.Plugins). Every release publishes its ExpectedDbVersion (_releases/_db/<version>, OCI expectedDbVersion). Every roll path runs the target's migration Job before the image moves, or refuses naming both numbers; the operator's run.sh interlock enforces this for every plan, whatever Hosting generation composed it. One documented exception remains until its lane is fixed: the break-glass HelmRelease dispatch (Systemorph/Memex helm-release.yml) applies the migration Job alongside the Deployment; use Reconcile instead. Manual: Doc/Architecture/PlanningADatabaseMigration. in force 2026-09-25 maintainer
first-admin-no-learning-path The instance's FIRST global administrator is seeded with no learning path (User.PinnedPaths empty); an ordinary new user is seeded with the four documentation sections. The learning path is a create-time SEED, never a value a later onboarding write re-imposes. in force 2026-09-21 maintainer
first-sign-in-becomes-admin A provisioned instance with no HUMAN administrator sends an anonymous visitor to SIGN-IN, and the first person to complete onboarding is admitted without an invitation and becomes platform admin; every later person needs one. "Human administrator" is ONE rule, asked by every gate (onboarding page load, onboarding submit, entry page): an undenied Admin grant in Admin/_Access whose holder is not System, Anonymous or Public and has an Active mesh User node. So a grant SEEDED for someone who has not onboarded (Auth:GlobalAdmins, the image's own settings) does not block the first person. It is read entirely as System and fails closed (unreadable ⇒ administered). The image SHOULD seed no administrator, but today it still does: Memex.Portal.Distributed/appsettings.json carries Auth:GlobalAdmins: ["rbuergi"], so every instance of the current image holds that static grant until MeshWeaver.Plugins#2431 lands. The rule above keeps it from blocking the first person, because the holder has no User node on a fresh instance. Safe ONLY where sign-in is restricted to the owning organisation; an instance whose sign-in admits the public is provisioned with an administrator. Mechanism: AdministratorProbeService.HasHumanAdministrator + OnboardingAdmissions (MeshWeaver.Plugins#2430), FirstPersonBecomesAdminOnAFreshInstanceTest; the image seed goes in MeshWeaver.Plugins#2431; account in First-run setup on a provisioned instance. in force 2026-09-27 maintainer
setup-secrets-three-valued The first-run setup dialog's secrets step shows a declared vault mapping whose object does not exist as its own state, missing, decided by the object's versions listing: 200 is exists, 404 is missing, anything else is not checked and never either answer. Missing rows sort first. in force 2026-09-21 maintainer
platform-backwards-compatibility Platform builds within one major and one compatibility epoch are backwards compatible: plugin bytes built against platform N run UNCHANGED on platform N+1 — the ladder P1+p1 → P2+p1 → P2+p2 → P2+p3 → P3+p3, each step changing one side. Only a DECLARED epoch bump (src/MeshWeaver.Compiler/platform-compatibility.json, every broken member listed) breaks it; a plugin whose floor or producing platform is newer than the running one is declined loudly. Proven on every platform build, never assumed: the Platform compatibility … (ladder) check links the deployed plugin set against each platform pull request and hangs off the required check. in force 2026-09-25 maintainer
cluster-upgrade-governed The AKS Kubernetes upgrade — control plane and every node pool — runs only as the governed UpgradeCluster Hosting/InstanceAction on the control instance, behind a mesh approval; never an ad-hoc az aks upgrade, az aks nodepool upgrade or kubectl. ONE approval covers the whole upgrade: control-plane minors chained one at a time, every pool upgraded once straight to the final version, the pool hosting the portals last, a health gate before each pool, and a stuck portal roll refuses it. Mechanism: hosting-aks-upgrade (operator), Hosting/ClusterUpgrade (MeshWeaver.Plugins — plan, approval, executor), the UpgradeCluster lane in Systemorph/Memex aks-ops.yml. in force 2026-09-25 maintainer
module-sync-per-manifest-hash An instance ALWAYS syncs every module it has; nothing holds a whole Space or partition behind a per-identity seal. Each module is judged alone by the content hash (moduleVersion) in its manifest.lock: unchanged ⇒ nothing written; changed ⇒ it syncs to the incoming commit; a declared platform floor above the running platform ⇒ that one module is declined, loudly and by name, and holds no sibling. The seal decides only whether a NodeType ADOPTS prebuilt bytes or COMPILES from the synced source — never whether, or at which commit, sources arrive. Manual: Doc/Architecture/ModuleSyncPerManifestHash. in force 2026-09-25 maintainer
package-min-mesh-version "source must ask for which min version. any version > min is used. normally we attempt to install latest" A package version declares minMeshVersion, and an installation uses it only when its running platform is at or above that floor. Only a floor that is COMPARABLE with the running version and strictly above it holds, decided by the ONE comparator PlatformFloor (run numbers where both sides have one, else the numeric core). A floor that cannot be ordered, an unknown running version or a local -ci.0 build proceeds as advisory, which keeps the 2026-09-07 ci < rc < clean trap closed. A held update keeps the installed version running and files ONE blocking ticket per held state through the control inbox (package-update-held). It never holds a platform roll. Replaces R2's "measured, never declared" for version selection. Owed: phase 2, where the registry keeps older versions with their floors and installers and GitSync pick the newest satisfiable one; and the MeshWeaver.Plugins control-plane intake of package-update-held as a blocking triage item. Manual: Module Adoption Policy → R2: the declared floor. in force 2026-09-29 maintainer
init-timeout-retires-activation A hub that demand routing re-creates (WithReactivationOnDemand — every per-node hub) whose DataContext initialization TIMES OUT is disposed and logged at Error, never latched FAILED for the life of the process; the NEXT ACCESS re-creates it. No timer and no background retry: the parked backlog is answered terminally (ErrorType.Failed) so no re-ask latch retries on its own. A non-transient init FAULT keeps the latch. Mechanism: DataContext.SettleInitializationGate; account in What the DataContext Init Time-Box Bounds. in force 2026-09-25 maintainer
area-view-reopens-on-deadline-miss A layout-area view whose stream fails with a transport DEADLINE MISS (the owner did not answer within the 30 s response deadline) opens a FRESH area stream — a new subscription to the owner — at most once per 30 s per open view, so it renders the owner's next frame instead of staying on "Area unavailable" until a reload. Only a deadline miss re-opens; every other error stays terminal, and no deadline is raised. The router's verdict for a bare timeout stays terminal (ErrorType.Failed) for every other path. Mechanism: AreaStreamReopen.ReopenOnDeadlineMiss + AreaErrorClassifier.IsDeadlineMiss (MeshWeaver.Layout); account in Error Propagation & Wedges → A deadline miss re-opens the view. in force 2026-10-01 maintainer
dependent-suites-gate RETIRED — superseded by core-merge-never-blocked and one-promotion-gate. Was: a core change reached main only after MeshWeaver.Plugins' suites passed against the candidate, on every merge-queue entry, failing Consolidate test results on silence (measured cost: MeshWeaver#5807 green at 13:21Z, ejected 17:21Z on "did not answer within 42 min"). The advisory pull-request run and the verdict machinery remain; see One Promotion Gate. retired 2026-09-25 → 2026-09-27 maintainer
core-merge-never-blocked SUPERSEDED by dependent-suites-affected-gate. Was: a core pull request merges on core's OWN required checks; no required context waits on MeshWeaver.Plugins; the dependent-suites run on a pull request is advisory (label dependent-suites, or a declared Pairs-with: Plugins counterpart). The merge queue on main stays off. Manual: One Promotion Gate. superseded 2026-09-27 → 2026-10-08 maintainer
dependent-suites-affected-gate A core pull request PROVES it does not break MeshWeaver.Plugins before it merges (MeshWeaver#2689): every non-fork pull request asks Plugins to build and run, against the candidate (its fresh merge with main), exactly the suites and in-mesh Tests areas the diff can reach — selected PER REALM (one package, or the hosts) from the compiled and import graph, each with the edge that pulled it in, every unreached realm named as not selected — and Consolidate test results fails unless that verdict is green. Only what is affected runs: a selection that cannot be computed is RED naming why, never a full run; the once-a-day run stays the only full run. A measured break merges only when DECLARED in the body (Breaks-plugins: <realms> — <what> — counterpart Systemorph/MeshWeaver.Plugins#<n>; semver: <major|minor|ceiling>), the counterpart is green against the same candidate, and the semver consequence is in the diff. A fork pull request is the one event exemption, printed by name. Manual: Cross-Repo Pair Gate → "The dependent's suites run against the candidate". in force 2026-10-08 maintainer
build-latest-green Every CI consumer and the image build take the NEWEST GREEN core main build (the resolver's newest set with a sealed platform trio — promoted, verified, baked — resolved by identity tag whether or not it is armed) together with MeshWeaver.Plugins main HEAD; a red core main falls back to the last green build, never forward into red. Plugins pull requests follow the newest set by default (the main-passed ceiling is opt-in, label platform:main-passed); the freeze variable MW_PLATFORM_REF stays for incidents. A burst of merges coalesces to one build of the newest heads; a run in flight is never cancelled. Manual: One Promotion Gate. in force 2026-09-27 maintainer
one-promotion-gate The fleet rolls only to an ARMED set, and main-cd arm arms (the portal's <version> tag, the <line>-latest pointers, the release event) only the newest promoted set, newer than every armed one, whose PLATFORM verdict is green: the platform's own tests (promoted only from a green required check), that run's compatibility ladder (the published module set links against the image), and control running it (platform-deploy-control-first). No MeshWeaver.Plugins dependent-suites verdict is read (platform-module-deploy-separate; it decided arming until then). A ladder still running or a control not yet on the set waits, a red ladder is refused, a newer green set supersedes both; an override is a dispatch input carrying its reason. Platform delivery (promote, verify, bake, delivery-verdict) never waits on it. Every set is stamped with its commits (promotion record with full core_sha/plugins_sha, the release event's coreSha/pluginsSha, and the portal's staging-<core7>-<run id> tag that arm writes the version from; the <core7>-p<plugins7> host pair tag is retired and survives only on sets promoted before its retirement) so containment is answerable by ancestry. Manual: One Promotion Gate, Platform and Module Deploy. in force 2026-09-27 (platform verdict: 2026-10-05) maintainer
platform-deploy-control-first Every platform build that passes the control image's own acceptance becomes the control instance's next image in the run that built it (memex-control:<version> + line pointers, never backwards — main-cd control-first), waiting for no arming, Plugins verdict, seal or module publication. The control record is Continuous with no rollGate, so that roll needs no approval; any OTHER roll of control still does. The fleet is offered a build only once control RUNS it (core commit contained by ancestry) and answers /health 200 — the control half of arm's platform verdict. Control is declared once, in .github/control-instance.json. Manual: Platform and Module Deploy. in force 2026-10-05 maintainer
platform-module-deploy-separate The platform deploy ships the host image only — the core platform plus boot-time infrastructure modules (storage backends, the instance gate, and for control its fleet-control and self-update modules) — and never packs, bakes or seals a module, nor gates on a module's tests or verdict. Modules publish on their own lanes and every instance auto-updates them independently of any platform build, seal, pair or framework identity (packages-auto-update). What still guards a platform roll: its own tests and the compatibility ladder (the published module set links unchanged against the image); a module that needs a newer platform is held by its floor and blocks nothing. Owed: the image's non-boot module seeds (AI, Blazor.Chat, Mcp, Markdown.Export, Markdown.Collaboration, Blazor.Graph, Blazor.EntityViews) leave, under a boot-time declaration and a shrink-only ratchet, once a fresh instance lands them from the registry before readiness. The host pair tag is retired (Done, manual item 5). Manual: Platform and Module Deploy. in force 2026-10-05 maintainer
control-first-never-silent One broken control instance must never freeze the fleet silently. When nothing is armed and control has been behind the newest build it was given for longer than platformLagBoundMinutes (the same bound and clock as control-always-latest, walked back to the first build control contains), main-cd arm goes RED, and its sentence names control's own self-update verdict. A failing self-update (SelfUpdateVerdict.IsFailure) is public on every instance: the census-tagged self_update entry on /health reads Degraded (never Unhealthy, no probe tag), and Admin/UpdatePolicy.lastCheckFailed is set. A 200 from the control inbox is reported as stored, never as a roll. Control-first itself is unchanged, and an arm override stays the maintainer's call. Manual: Platform and Module Deploy → A frozen fleet is red. in force 2026-10-08 maintainer
control-always-latest The control instance always runs the newest platform build it was given and the newest compatible publication of every module it has installed. Lag past a declared bound is an ALARM: the platform half is core control-always-latest.yml (RED + the one control-lag issue; an unreadable control is lag, never a pass; bound platformLagBoundMinutes in .github/control-instance.json), the module half MeshWeaver.Plugins FleetTarget.ControlBreaches (a fleet-behind-target triage item per module behind a compatible served version past the bound; a floor-held module is not lag). Manual: Platform and Module Deploy. in force 2026-10-05 maintainer
paired-change-sets A change spanning core and MeshWeaver.Plugins is built and tested TOGETHER before either half merges: the core pull request declares Pairs-with: Systemorph/MeshWeaver.Plugins#<n>, the Plugins one Core-ref: Systemorph/MeshWeaver#<n>, and the dependent suites run against the core candidate plus the Plugins head. Merging stays per repository, core first and never waiting; the Plugins half goes green only once a green core build contains the core half (checked by ancestry). Manual: Paired Change Sets. in force 2026-09-27 maintainer
content-neutral-push-keeps-run A push to a pull request that changes nothing the pull request AUTHORED — a merge of main, regenerated generated files — never cancels the run testing that content; the new head adopts its verdict. Only a push that changes the authored diff supersedes. Mechanism (MeshWeaver.Plugins): pr-supersede.yml + scripts/ci-change-set.py. in force 2026-09-27 maintainer
self-update-record-authoritative When a deployment record declares the platform image's update policy (rendered as SelfUpdate__DefaultPolicy, with SelfUpdate__DefaultPattern), that declaration is AUTHORITATIVE: at every start the self-updater converges the instance's Admin/UpdatePolicy policy and pattern to it, touching no other field. With no policy declared the configuration only seeds a new node, and an existing node belongs to the instance's admin. Mechanism: UpdatePolicyNodeType.ConvergeToDeclaration (memex/Memex.Portal.Shared); account in Why the Fleet Stopped Rolling Itself. in force 2026-09-28 maintainer
oauth-bounded-live-credentials The MCP OAuth token exchange keeps a BOUNDED number of live credentials per (user, client_id) — the N newest, N configurable as Mcp:OAuth:MaxLiveCredentialsPerClient, default 5 — and evicts the oldest beyond it, logging each eviction. Not one per client: processes of one installation share a client_id, and one-per-client made each new sign-in revoke every sibling session (#5074). Mechanism: OAuthCredentialEviction (Memex.Portal.Shared); manual: MCP Authentication. in force 2026-09-25 maintainer
bake-gate-readiness-only A ROLL GATE — today the NodeType bake gate, nodetype_bake — holds READINESS only and never fails the startup probe. The startup probe proves only that the process booted; the gate's verdict is read by /ready alone, so a refusal stalls a roll (the pod stays alive, out of the Service) and never kills anything, and a restarted previous-image pod keeps serving. /health still runs and prints the gate; its status excludes it. The startup-critical checks (db_version, PostgreSql) stay on the startup probe; required_modules is a roll gate too (required-modules-readiness-only). Mechanism: ProbeEndpoints.RollGateTag + ServiceDefaults.TagRollGates, chart invariant 10b, RollGateReadinessOnlyTest; manual: The Bake Gate Only Stalls a Roll. in force 2026-09-26 maintainer
required-modules-readiness-only The required-modules check (required_modules) is a ROLL GATE under the same rule as bake-gate-readiness-only: its Unhealthy verdict (a required module the image should ship is absent, or a present one did not install against this platform) stalls the roll and keeps the pod out of the Service, and never fails the startup probe or liveness. Its Degraded verdict (a store-delivered module not here yet) is a 200 and holds nothing, as before. /health still runs and prints it; its status excludes it. Core applies the tag by name, whatever the host's registration carries. Mechanism: ProbeEndpoints.RequiredModulesCheckName in ServiceDefaults.RollGateChecks, RollGateReadinessOnlyTest; manual: The Bake Gate Only Stalls a Roll. in force 2026-09-26 maintainer
silos-pool-autoscaler-max The silos node pool (every portal) has its cluster-autoscaler maximum raised by one, 4 → 5, so a portal roll's surge pod is not left Pending while the public instance's KEDA scale-out holds its maximum. Node-pool bounds change only through the governed InfraDeploy action over Systemorph/Memex infra/estate.bicep — what-if first, then an approved deploy — never az aks nodepool update. Owed: the Memex change declaring the pool, the approved deploy, and the agentPools write grant for hosting-operator (the same Azure Kubernetes Service Contributor Role grant UpgradeCluster owes). proposed — maintainer
governed-action-preflight A governed operation (a Hosting/InstanceAction) runs EVERY step under the system identity from its first step, and at PLAN time — before it parks for approval — verifies that each step is feasible: the rights it needs as system, and the scale bound of the mechanism each step uses. A step known to exceed its bound, or one the system identity cannot perform, is REFUSED AT PARK with the reason, never discovered partway through a destructive run. A whole-space deletion drops the partition as ONE teardown (PartitionTeardown.TearDownPartition), never a per-node recursive delete of its content. Manual: Partition Teardown → The direct teardown. in force 2026-09-27 maintainer
severity-closes-on-verification A sev:B or sev:H issue closes on post-roll production verification of the running portal, never on the merge that lands its fix: a merge puts the fix on main, and what the label gates is whether the defect is gone from production. sev:M, sev:L, chore, enhancement and documentation issues close on a merge as before. Cited by the Closing keywords (no accidental close) gate, which refuses a body whose closing keyword targets an issue carrying either label. Ratification owed — filed for triage as rbuergi/Feedback/20260922-ratify-severity-closes-on-verification-policy, which carries the measurement that six merges closed a sev:H in the two days before the gate existed. proposed — —
internal-code-review Pull requests are reviewed by the internal GLM-5.3 reviewer of the PR steward (MeshWeaver.Plugins Governance/PullRequestSteward), posting through the systemorph-com App; GitHub Copilot code review is retired from every repository. The steward reviews every in-scope, non-fork pull request and communicates only with global admins. Gate: check-review-answered.py accepts both reviewers until Copilot's rule is gone everywhere. Superseded by copilot-code-review. retired 2026-09-27 maintainer
copilot-code-review GitHub Copilot code review is the fleet's pull-request reviewer again, replacing internal-code-review. Every repository's ruleset carries copilot_code_review with review_on_push: true (review_draft_pull_requests: false), so Copilot reviews every head. internal-review is not a required context anywhere. The gates accept a Copilot review: Automatic review answered takes a landed Copilot review, and the stage gate and the arm gate take a landed Copilot review AGAINST THE CURRENT HEAD as that head's review (check-review-answered.py copilot_review_on). An internal-review run, if one is still posted, is accepted as before. Every thread either reviewer opened still needs a person's reply. Owed: the internal reviewer's off-switch on the control instance, and the MeshWeaver.Plugins PrArming port of the same acceptance (Systemorph/MeshWeaver.Plugins#3088) merged and deployed on the control instance — until then the control plane arms nothing, and core #6063 (auto-arm disarm-only) waits on it. Manual: Review Findings Answered → Copilot is the reviewer again. Its per-head review (review_on_push: true) is narrowed by review-once-per-pull-request. in force 2026-10-07 maintainer
review-once-per-pull-request A pull request gets ONE automatic review, not one per push. Every gate in check-review-answered.py (Automatic review answered, the stage gate, the arm gate) counts a landed Copilot review against ANY head of the pull request as "reviewed" (copilot_review_of_pull_request); a refusal is still not a review. Every thread a reviewer opened, on whichever head, still needs a person's reply. The rulesets' copilot_code_review rule runs with review_on_push: false (review_draft_pull_requests unchanged), applied by .github/scripts/set-copilot-review-once.py only AFTER the gate change is merged — the other order would leave new heads with no review and the old gate holding them. Owed: applying the ruleset flip in all nine repositories, and the same acceptance in MeshWeaver.Plugins PrArming. Manual: Review Findings Answered → One review per pull request. in force 2026-10-07 maintainer
secrets-write-only-entry No manual Key Vault access. Every secret the fleet uses is entered through a GUI in the app that owns it. The GUI is WRITE-ONLY: it sets or replaces a value, never reads or displays it back, and shows only status and a fingerprint. The vault has two identities: a READER (the pods' CSI identity: get only, per secret where the scope allows) and a WRITER (secret-writer: list, metadata, set, delete, recover, purge; never get), used only by the governed write path running as system. No human holds either. Mechanism: hosting-kv-set / hosting-kv-status / hosting-kv-state, the SetSecrets action; gate: check-manual-keyvault.py; manual: Secrets: Write-Only Entry, Split Identities. Owed: the secret-writer identity and its access policy (Systemorph/Memex infra/estate.bicep through an approved InfraDeploy), the reader narrowed to get, the Plugins status/lifecycle actions on the Deployments page, the Store payment-keys GUI, and the four operator steps that still read a value. proposed — maintainer
governed-action-preflight A governed action (Hosting/InstanceAction) runs EVERY step with system credentials, and checks the rights and the scale each step needs at PLAN time, before it parks. A step that cannot complete (a right the system identity lacks, a volume a bound cannot cover) refuses the request at park, with the reason on the page. It never fails partway through a destructive run. Evidence: a DeleteSpace failed at its ninth step, on 31,138 per-node delete validations against a 25 s bound, after the space's grant and GitSync configuration had already been removed. Owed: the scale and rights pre-flight, in MeshWeaver.Plugins (in flight). Manuals: MeshWeaver.Plugins Hosting/AksOperationsViaActions, Hosting/DeleteSpaceAction. proposed — maintainer
action-page-controls-and-queries An activity or action page is composed of platform UI controls in a real layout: cards, grids, and query controls that offer "show matching nodes". A SET of nodes is expressed as a mesh query (the top-level node plus scope:subtree), never as an enumerated listing dumped into a code control. The summary goes last. Owed: plan steps expressed as queries, in MeshWeaver.Plugins (in flight). Manual: MeshWeaver.Plugins Hosting/AksOperationsViaActions, "The run page". proposed — maintainer
pr-babysitter-authority The fleet PR babysitter, the PR steward's heal/observe half, HEALS and never MERGES, and nothing irreversible runs unvalidated. Its deterministic pass only PROPOSES its one heal, with the evidence: a re-run of the failed jobs of a pull request whose every failing check died of infrastructure (runner, network, registry, artifact quota, or a stale review-gate verdict). Its validator agent approves or refuses each proposal against that evidence, with its reasoning. Only an approval runs: ONCE per head SHA, after the live head and the marker are re-checked, and behind a marker comment that carries the reasoning. It never merges, enables auto-merge, pushes, dequeues, approves a pull request or uses an administrator override. A waiting-for-platform pull request is read off its repository's label and re-run by that repository's own waker, never by the babysitter. Implementation owed: the validator's fail-closed EU enforcement (MeshWeaver.Plugins#2448) and the arming on the build instance (a governed Reconcile of its record). Shipped: MeshWeaver.Plugins#2439 (PrBabysitter, Hosting/PrWatch, agent pr-babysitter). Manual: MeshWeaver.Plugins Hosting/PrBabysitter. proposed — maintainer
pr-babysitter-cadence The PR babysitter is event-driven, with a full fallback pass every 30 minutes. Its triggers are GitHub pull-request and check events and the arrival of a new sealed platform set. The events come from the ONE organisation webhook, and the control instance forwards them over the control lane. It runs on the BUILD instance only (opt-in configuration), one pass at a time. Implementation owed: as pr-babysitter-authority, plus the build instance's control-lane key, without which nothing is forwarded and the fallback pass is the only trigger. Shipped: core #5797 (forwarded events). proposed — maintainer
code-review-eu-only Code review of pull requests — the PR steward's internal review and the PR-agent validator on the build instance — runs on GLM 5.3 through OpenRouter's EU endpoint https://eu.openrouter.ai/api/v1 ONLY, and FAILS CLOSED: a review that cannot run in the EU does not run. Mechanism (MeshWeaver.Plugins): the review model node Provider/OpenRouterEU/glm-5.3-review declares providerRouting (region EU; only Inceptron and Mistral; no fallbacks; zero data retention; no data collection), which makes it RESIDENCY-BOUND — reachable by node path only, credentialed only through its own provider (Provider/OpenRouterEU, which references the account key on Provider/OpenRouter rather than holding one), never substituted by another model, and refused before sending unless the endpoint is the EU host; OpenRouterProviderRoutingPolicy writes the pinned provider object onto every request. Governed setup: the standards pr.review-provider-eu.create and pr.review-model.bind. Owed: the two standards signed (the account is on OpenRouter's Business plan, which EU in-region routing needs), and the build instance's copy of the two nodes. Manual: MeshWeaver.Plugins Governance/PullRequestSteward § 6.2a. proposed — maintainer
domain-config-apps Configuration and secrets live in the app that owns their DOMAIN — AI, Databases, Sign-in, Email, Payments, Integrations — never as ad-hoc panels or dialogs on the Deployment record page or elsewhere. A deployment's recorded shape is edited in the control instance's fleet app for that domain (/Hosting/{X}/Deployment/{id}: the record's block bound to the record, the domain's vault objects write-only, Apply files a governed Reconcile); what an instance changes about itself live is a tab of its own Admin app, under the same domain name. The record page links to the apps and carries no entry of its own. The AI domain's fleet app is named Models (/Hosting/Models; /Hosting/Ai redirects there). Owed: the six fleet apps (Models first) in MeshWeaver.Plugins Hosting/, and the record page's secret dialog and panels removed as each domain lands. Manual: Domain Configuration Apps. proposed — maintainer
secret-actions-interim-actions-lane 🚧 TRANSITIONAL. Until the secret-writer identity is provisioned AND every secret action runs in the in-cluster Job under it, the two VALUE-FREE secret actions — a generate-only SetSecrets (hosting-kv-set --generate, approved in the mesh like every SetSecrets) and a SecretStatus (hosting-kv-status, metadata only) — may run on the Actions executor (Systemorph/Memex aks-ops.yml) as hosting-operator (which holds get, list, set: the accepted interim risk is a writer that COULD read; the verbs never do and no value crosses the lane); each run says so on its node (writerIdentityNote). A pasted value and every lifecycle verb stay refused there, so a third-party-held secret has no write path until the exception ends. Manual: Secrets: Write-Only Entry → Interim: the value-free verbs on the Actions lane. Enforcement halves: the MeshWeaver.Plugins executor verdict (HostingOperator.ActionsLaneSecretVerdict, Plugins#2528, OWED until it is merged and rolled onto the control instance, when this row becomes in force) and the Memex aks-ops classifier (Memex#613, shipped). proposed — maintainer
operations-instance-per-estate Every estate has the same shape, 1:1: exactly ONE operations instance, which holds BOTH the control role (the Deployments/* records, InstanceActions and their approvals, the signed inbox, triage, the fleet watch, the ops-lane dispatch) and the build role (the build queue, its scheduler and admission, the PR babysitter, build Jobs), plus any number of working instances. A separate build instance is retired through the generic migration, and the control role cuts over onto the instance the estate's records name as its operations instance; the cutover is decided. Exactly one inbox consumer per estate at every step. Owed: the build role's code and chart gaps G1–G10 (MeshWeaver.Plugins Hosting/OperationsInstance §7), then each estate's cutover acts (its records repository's cutover pull request). Manual: MeshWeaver.Plugins Hosting/OperationsInstance. proposed — maintainer
bug-fix-eu-only The 24/7 bug-fix pool runs agent rounds on EU-routed models ONLY, and FAILS CLOSED: a variant whose dataResidency is not Eu is never eligible (there is no approval path for a non-EU variant), and a bug for which no EU variant is served on its estate is QUEUED — visibly, "queued — no EU variant served on this estate" — and never run on the agent's own or the deployment's default model; no thread round is dispatched for it. Mechanism (MeshWeaver.Plugins): BugFixPool.Assign / Ineligible (eligible only when dataResidency is Eu) and the pool's re-drive gate. Owed: that change merged (MeshWeaver.Plugins#2595) and rolled onto each estate's control instance, when this row becomes in force; and each estate's EU route (ai.openRouterEU) so a variant is served. Manual: MeshWeaver.Plugins Essentials/BugTriage → "The bug-fix pool". proposed — maintainer
packages-auto-update Every installed package updates by itself as soon as a newer COMPATIBLE version is published to the registry: the only inputs are "a version was published" and "its declared platform floor ≤ the running platform". It depends on NOTHING else — not a platform image build, deploy or roll, not a publication seal or a seal for the running framework identity, not a green build of the platform or of the package repository beyond the package's own publish, not the platform's CD or fleet arming, not a per-identity prebuilt match, and not the partition's sync source (the module lane's sync-owned hold is retired). A fresh install is Auto; a record SEEDED with the old reminder-only default is migrated to Auto at boot; the only opt-outs kept are a per-package pin (None) or a policy a global administrator chose on the catalog card, each named in the log. An incompatible floor is declined by name and the running version keeps serving. What lands is activated through the module reload path (live, else exactly one automatic restart, no approval). Manual: Module Reload → "Auto-update". in force 2026-10-05 maintainer
package-uninstall-request A platform admin uninstalls a package through ONE durable request (Admin/_PackageUninstall/{id}), in two phases. Phase 1, no confirmation: refuses by name a package not installed, a partition shared with another installed package or holding user data; retires the module (live, else exactly one automatic restart), closes the package's hubs, removes the install record, blocks every unattended re-install, and records exactly what phase 2 would destroy. Phase 2, the irreversible drop of the partition storage and its registry record through the platform's governed partition teardown, runs only after the REQUESTER repeats the partition name, recorded with who and when; without it the package stays uninstalled with its data retained. Owed: the MCP uninstall_package tool (MeshWeaver.Plugins), and a package-page entry. Manual: Package Uninstall. proposed — maintainer
module-reload-request Any authorised caller (a platform admin, an agent through MCP, the platform's own watchers) can ask an instance to reload one module, or all, through ONE durable request (Admin/_ModuleReload/{id}). The instance resolves the newest compatible published version — its declared platform floor against the running platform, never a seal or a green platform build — lands it through the existing landing path, activates it live when the module can be swapped and otherwise by exactly one automatic restart through the self-update restart path, with no governed activity, no approval and no confirmation, and reports on the request node the version found, what landed, how it activated and what every replica loaded, or RED with the reason. Owed: the MCP reload_module tool and the fleet-target intake's switch from RefreshModules (MeshWeaver.Plugins), and the live loader's swap registering IModuleLiveActivation (MeshWeaver#6121, slice 2). Manual: Module Reload. proposed — maintainer
instance-reboot ONE operation brings an instance to a known-good, NEWEST state: a durable request (Admin/_Reboot/{id}) runs, in order, Sync (every GitSynced module source at its branch HEAD, the git_hub_sync op=update import), Modules (the newest COMPATIBLE published version of every installed module, the module-reload landing), Image (the newest image the instance's update policy admits and its availability gate clears), ONE roll/restart that activates all of it, and Verify (every process booted after it: the critical-namespace bake, pending module activation, content types, and a thread-start smoke check — a process that measured no smoke check is RED). Every step is reported on the request with a named reason when skipped or failed. A person's call (MCP reboot_instance, the Reboot button, a platform admin) IS the signature — no second approver, the requester recorded; the instance's own watchdog files it without approval ONLY on the explicit wedge predicate (repeated load/binding faults on thread start, or a critical NodeType continuously in compile Error), at most once per interval, never twice for evidence a reboot already failed to clear, and every firing or refused firing is a Critical alarm. Owed: the MeshWeaver.Plugins half (the MCP tool, the deployment page's button and the Reboot InstanceAction kind, the AI module's thread-start smoke check and wedge reports). Until the smoke check is rolled onto an instance, every reboot there ends Failed at Verify by design — verification that cannot measure fails closed — and the verdict says so by name ("no smoke check was measured (none registered on this host)"), so the merge order is this core half first, the MeshWeaver.Plugins half right after, and a reboot is trusted green only once both are live. Manual: Instance Reboot. proposed — maintainer
exact-release-surface The portal type surface the release gate links a landed module against belongs to ONE release: it is published at _releases/_surface/<release-version>, measured on that release's portal image, carried byte for byte to the clean version, and it is the ONLY surface the gate reads — no fallback to another release's or to a publication's. The platform-surface.json inside a content publication is descriptive and read by no gate; the shared _current pointer decides content, never a per-image fact. Chosen over shared canonical surfaces with producer provenance and ordering. Manual: Sealed Publication Reads, "The release gate reads the surface of the release it gates". proposed — maintainer
ci-two-pools-priority-queues CI runs on exactly TWO runner pools split by technical need — plain (vars.MW_RUNNER) and Docker (vars.MW_RUNNER_DOCKER) — sharing ALL capacity; no pool, label or PriorityClass is reserved for a kind of work. Priority comes from the control instance's CI queue (Hosting/Queues/operator/ci), whose tiers express > trunk > gate > pr are dispatched in that order with a measured, relative share of the pool kept free for express; the order is mesh state, re-orderable by a platform admin through MCP (queue_list, queue_reorder). CI never depends on the control instance to run: every path to the queue fails OPEN, loudly. The SAME queue model carries every control-plane agent thread (reviews, fixer hand-offs, bug-fix and triage rounds) on Hosting/Queues/operator/agents with NO LIMIT: no pre-set concurrency or share — only a live provider refusal (429/402/quota) holds work back, by backoff on that (model, upstream) pair; this binds the per-round agent admission too (MeshWeaver.Plugins AI/AgentAdmission: no relative per-lane share once a pool is measured exhausted — a slow, stalled or round-capped round holds nothing back); executors scale with KEDA on queue depth. Owed: the removal of that per-lane share from AI/AgentAdmission (MeshWeaver.Plugins#2896 — until it merges, the share still applies); the queue live on the control instance and MW_BUILD_QUEUE=dispatch in MeshWeaver.Plugins, when this row becomes in force; then the retired trunk and gate scale sets removed (Systemorph/Memex). Manual: Runner Pools and Dispatch Queues. proposed — maintainer
review-then-suites RETIRED — superseded by suites-parallel-with-review. Was: every pull request in the fleet moved REVIEW FIRST, then the suites, then the arm: the stage gate (node-repo-stage-gate.yml, default review-before-suites: true, with its stage-advance.yml listener) holds the expensive suites until the head's automatic review landed and every finding is answered; the suites then test a fresh merge with the current main (suites-test-fresh-merge); and auto-merge is armed only when the review is answered AND every required status check of the base is green on the head (check-review-answered.py arm gate condition 4, ported by MeshWeaver.Plugins PrArming). Replaces suites-parallel-with-review (suites beside the review), which it reverted the same day; review-before-suites: false remains a per-caller opt-out that never changes the merge or the arm. Manual: Staged Pull Request Pipeline. retired 2026-10-05 → 2026-10-07 maintainer
suites-parallel-with-review The expensive suites run BESIDE the automatic review: the stage gate (node-repo-stage-gate.yml, default review-before-suites: false) lets them start as soon as stage 0 is green, on a fresh merge with the current main (suites-test-fresh-merge). Merging and arming are untouched — auto-merge is armed only when the review is answered AND every required status check of the base is green on the head (check-review-answered.py arm gate condition 4, ported by MeshWeaver.Plugins PrArming). Back in force after review-then-suites (review first, then the suites) was retired — the reviewer takes one review at a time, so holding the suites behind it left runners idle. review-before-suites: true (with the stage-advance.yml listener) remains a per-caller opt-in. Manual: Staged Pull Request Pipeline. in force 2026-10-07 maintainer
suites-test-fresh-merge Every suite job of a pull request tests the head merged onto the base branch's CURRENT tip, resolved when the suites start and reported in the run — never GitHub's refs/pull/N/merge as it stood at the push, and never a stale merge on a re-run. The merge is computed in the job (no push, no branch update, no new head or review); a head that conflicts with the current tip is red. Manual: Fresh Merge Under Test. in force 2026-10-05 maintainer
review-carries-over-clean-base-merge A pull request's internal review CARRIES OVER to a new head that differs from the last reviewed head only by a clean merge of the base branch: walking back from the head through merge commits only reaches a head with a real internal-review, every commit added since is a merge, and the pull request's own diff (merge-base..head) has the same patch-id as the reviewed head's. Then the stage gate and the arm gate judge the reviewed head's run (and the pull request's answered threads) for the new head, and the PR steward posts that verdict as the new head's internal-review instead of starting a review round. Computed from the repository, never from a commit message; anything unreadable, any non-merge commit, or any conflict resolution that changed the pull request's diff owes a fresh review. The gate logs the reviewed head, its check run and both patch-ids. Manual: Staged Pull Request Pipeline. in force 2026-10-06 maintainer
sources-sync-on-push An instance takes a repository's sources on every PUSH to a sync source's configured branch, at the pushed commit (after), never waiting for a green or sealed build; each module is judged alone by ModuleSyncDecision.Decide (unchanged ⇒ nothing, changed ⇒ synced, a declared floor above the running platform ⇒ that module alone declined with both versions named). A periodic branch reconcile (GitSync:BranchReconcileMinutes, default 10) repairs a lost delivery by resolving each branch head and importing at that sha. A green workflow_run records the build and imports nothing. Manual: Sources Sync on Push. in force 2026-10-05 maintainer
record-change-applies-itself A change to a Hosting/Deployment record reaches the pods without anyone filing or approving anything. Every Roll — CD's routed roll included — re-applies the CURRENT record at its tag (hosting-deploy over the record's render, after the tag's migration), never a bare set image that keeps the old environment. A record whose rendered values differ from every render a roll or reconcile applied gets ONE Reconcile the control plane opens itself, as system, with origin: record-change and the render's digest; it runs unattended exactly while the record still renders that digest (the record write is the governed act), a newer render supersedes a queued one, an identical render opens none, and no image tag is ever written. A render never SILENTLY drops a value the live release carries: hosting-deploy refuses, naming each path, until the record expresses it (e.g. its features, Memex#376) or it is removed deliberately. A hand-filed Roll/Reconcile stays the break-glass path. Manual: Hosting's Hosting/RecordChangeAppliesItself (MeshWeaver.Plugins) · Operating From the Portal. in force 2026-10-07 maintainer
prune-requires-provenance A source import prunes a node only when the repository put it there — the node is in the partition's prior import manifest — in every pruning mode (FullReplace and Additive now prune the same set). A node created in a synced partition at runtime is never pruned by a source sync, and unknown provenance (no or an unreadable manifest) is never prunable. Manual: Sources Sync on Push → The prune. in force 2026-10-05 maintainer
authorize-as-caller-execute-as-system A control-plane / system operation (an instance action and its approval re-plan, a governance pass, a sync, an operator step, a watcher acting on a request node) separates AUTHORIZATION from EXECUTION. The caller's access is checked EXPLICITLY — first when the request node is WRITTEN (its create/update is validated and refused by name, so an unauthorized request is never parked), and again immediately before executing (the requester or approver may have lost the right) — fail-closed, naming the missing permission. Then the operation executes as System (ImpersonateAsSystem, composed via RunAsSystem): reading the records it acts on, rendering plans, writing results; it never depends on the caller's RLS reach mid-execution. Impersonation is never a substitute for the check, and application writes on a user's behalf still carry the user's identity. Manual: Authorize as Caller, Execute as System. in force 2026-10-08 maintainer
declared-not-derived Anything the platform cannot run without — language models and providers, agents, queues, policies, credential references — is DECLARED (deployment-record config or committed content), and the declaration is the source of truth. A boot-time importer or reconciler never deletes a declared item because a module, plugin or registration did not contribute it on this replica: an absent contributor is not a removal. Pruning removes only what the declaration itself dropped. A change that makes a critical catalogue depend on module wiring alone is a defect. Carried as the shared rule block of the same id in AGENTS.md — in this repository (the hub) now. Owed: the six spoke copies (step 2 in .github/shared-rules.json) and widening that block's required-in to all seven repositories (step 3); this row becomes in force when both have landed. Manual: Declared, Not Derived. proposed — maintainer

Cited by: Release Process · The Self-Update Schema Wall · Issue Taxonomy and the Release Readiness Gate · Adding a Data Sync Needs a Global Admin · Thread Supervision · Access Control · Closing Keywords and Issue State · The Platform Compatibility Ladder · The Bake Gate Only Stalls a Roll · Deployment (AKS) · Secrets: Write-Only Entry, Split Identities · Module Adoption Policy · Declared, Not Derived.

🚨 A proposed row is not a weaker in force — it is an honest one. The first draft of this register listed release-blocker-gate as in force while the standard that enforces it was still an unmerged pull request; the row was moved to proposed naming what was owed, and back to in force only once that standard had merged. That is the precise failure this page exists to prevent, committed in the page that defines the rule. If a row's mechanism does not exist yet, the row says proposed and names what is owed.

Adding a policy here is cheap and reversing one is cheap. That is the point: a register entry can be changed in one place and every citation follows, which is exactly what a sentence copied into four files cannot do.