Skip to content

Development Governance Overview

How we keep the mcc-systems codebase healthy, consistent, and safe to work on. This page covers all the governance infrastructure — automated checks, conventions, documentation, and development workflows. Detailed docs live in the repo; this page tells you what exists and where to find it.

Automated health checks

Two automated checks run on GitHub Actions to catch problems early.

Nightly health check runs at 3am UTC (1pm AEST) every day. It's fully deterministic — no AI involved. It checks file sizes against enforced limits, scans for forbidden patterns (unguarded console.log, hardcoded emails, hardcoded API keys), runs all three builds (BMS, Portal, TypeScript), validates migration files follow our conventions (RLS, timestamps, triggers), detects duplicate constants, tracks bundle sizes against baselines, and verifies production is in sync with the repo (migrations applied, Edge Functions deployed).

If anything fails, the GitHub Action goes red and sends a notification. Reports are saved to the repo at docs/admin/audit/health-reports/.

Weekly AI review runs Monday at 4am UTC (2pm AEST). It collects the week's nightly reports, the repo structure, top files by size, and the enforcement rules, then sends them to the Claude API for architectural review. It looks for things the nightly check can't catch — architecture drift, files approaching size thresholds, inconsistencies between apps, and trends across the week. If it finds must-fix items, it creates a GitHub Issue.

Both checks can also be run manually — the nightly check via npm run health-check from the repo root, and either check from the GitHub Actions tab.

Full detail: docs/admin/automated-health-check.md

File size enforcement

Every source file (.ts, .tsx, .jsx, .js) has a size limit. The default is 300 lines. Files that have been reviewed and accepted at a higher limit have an override entry in docs/admin/audit/file-size-limits.json, which records the specific limit and the reason. A small number of files are exempt entirely (e.g. legacy frozen files).

The nightly health check enforces these limits automatically. Claude Code also checks after every file edit and stops if a file exceeds its limit.

The goal is to keep files small enough to be understood in isolation and edited safely. When a file grows past its limit, we either extract a cohesive piece into its own file or raise the limit with a documented reason.

Migration and schema conventions

All database changes go through migration files — no exceptions. This includes schema changes, reference data, and data fixes. We never make database changes directly via the Supabase Dashboard or SQL Editor (reading is fine, writes are not).

Every new table must include timestamps (created_at, updated_at), a trigger to auto-update updated_at, row-level security enabled, and an auth policy. Trigger functions use the set_ prefix. Migration files must never hardcode UUIDs — dev and prod generate different UUIDs for the same logical rows, so migrations use name-based lookups instead.

The nightly health check enforces the table checklist and trigger naming conventions automatically.

Full detail: docs/admin/migration-schema-conventions.md

Reference documentation

The repo has two documentation directories:

docs/live/ contains feature documentation for built and deployed features. These are the primary regression defence — they describe intended behaviour and design decisions for key functional areas. Claude Code is required to read the relevant doc before modifying any files in that area. Changes that break the documented behaviour are treated as regressions.

Current docs cover: BMS architecture, pricing model, service hierarchy and quoting, proposal/contract lifecycle, proposal send and unlock flow, organisation details data flow, contract clause variables, portal architecture, legacy tender responses, portal external integrations, portal legacy pages, and deployment safety nets.

docs/admin/ contains development governance docs — the ones described on this page. These cover how the codebase is managed rather than what the features do.

Both directories are listed in CLAUDE.md so Claude Code knows when to read them.

Claude Code standing instructions (CLAUDE.md)

CLAUDE.md in the repo root is the single instruction file that Claude Code reads at the start of every session. It defines all the rules CC must follow — monorepo structure, default environment (dev), workflow (one step at a time, report back), regression prevention, file size enforcement, database change management, pricing integrity rules, portal isolation rules, and pointers to every reference doc.

There is only one CLAUDE.md — in the repo root. It covers both apps.

State file discipline

Each app has a _project-state.md file that serves as a chronological audit trail of what's been built and why. Entries document the problem that was solved, why the solution works the way it does, and any design choices that were made — not just a list of files that changed.

At the start of each month, previous entries are rolled into a dated archive (e.g. _project-state-2026-04.md). The archives are for historical reference only.

Claude Code updates the state file as the final step of every task.

Dashboard isolation

Jordan has access to a dashboards section in the BMS (src/resources/dashboards/). This area is isolated from the core BMS by strict rules — dashboard code can read from any table but can only write to dashboard_* tables, cannot import from other resource folders (enforced at build time by ESLint), and cannot modify files outside its own directory (with three specific exceptions for routing and navigation).

This lets Jordan (or his CC instance) build dashboards with full autonomy without risk of breaking the core BMS or Client Portal.

Full detail: docs/admin/dashboard-development-guide.md

Development environment setup

A setup guide covers everything needed to get the monorepo running from scratch — Node.js, Supabase CLI, VS Code, cloning and installing, environment variables, dev servers, Edge Function deployment, Git identity, Vercel projects, and production deployment.

Written primarily for onboarding a second developer (e.g. if Gian joins as Glenn's offsider), but also useful as a reference for setting up a new machine.

Full detail: docs/admin/dev-environment-setup.md

Spec and plan guide

A guide for writing specs and implementation plans before building features. Covers how to structure a spec, what to include, and how the spec-to-build workflow connects with Claude Code instructions.

Full detail: docs/admin/spec-and-plan-guide.md

Audit artifacts

Several files in docs/admin/audit/ support the automated checks:

  • file-size-limits.json — default limit, per-file overrides with reasons, and skip list
  • bundle-baselines.json — bundle size baselines for the 20% growth threshold
  • accepted-exceptions.md — explanatory context for patterns that are intentionally accepted (e.g. staleTime: 0 is intentional, legacy tender files are frozen). This is read by the weekly AI review so it doesn't flag accepted patterns as issues.
  • health-reports/ — directory where daily and weekly reports are saved automatically

Production deployment

Production deployment has multiple safety nets. Database migrations deploy via a PowerShell script (deploy-prod.ps1) that Glenn runs manually. Edge Functions deploy via a separate script (deploy-edge-prod.ps1) that updates a deploy manifest for tracking. The nightly health check verifies that prod is in sync with the repo — flagging any unapplied migrations or outdated Edge Functions.

Full detail: docs/live/deployment-safety-nets.md

Where to put new documentation

All documentation lives in the docs/ directory of the repo, organised into three subfolders. The deciding factor is the audience and purpose.

docs/live/ — Feature documentation for built and deployed features. These are the primary regression defence. CC must read the relevant doc before modifying files in that area, and each doc has a corresponding CLAUDE.md entry. Put a doc here when it describes intended behaviour and design decisions that CC needs to respect when editing code.

docs/admin/ — Development governance, conventions, audit config, and reports. Put a doc here when it describes how the codebase is managed — enforcement rules, conventions, automated checks, or development workflows. These are referenced by CLAUDE.md, automated checks, or developers working in the repo.

docs/user/ — Human-readable documentation published to the documentation site at docs.matthewscleaningco.com.au. Put a doc here when it's aimed at a broader audience (Jordan, Gian, future staff) who may not work in the repo day-to-day. This includes high-level overviews, onboarding guides, system explanations, and business context documents. This page is an example — it summarises governance infrastructure and points to the repo docs for depth.

When it's not obvious: ask whether CC needs to read this doc before making a code change. If yes, it goes in docs/live/ or docs/admin/. If it's purely for human understanding, it goes in docs/user/.

Some topics exist in multiple places at different levels of detail — e.g. migration conventions have a full technical reference in docs/admin/migration-schema-conventions.md and a summary on this page in docs/user/. That's fine. The repo doc is the source of truth; the documentation site summary helps people get oriented without reading the full technical reference.

How to update the documentation site

The documentation site is built with MkDocs (Material theme) and hosted on Cloudflare Pages. It serves content directly from docs/user/ in the repo — there's no separate publishing step beyond pushing to master.

To edit an existing page: Edit the markdown file in docs/user/ (either directly or via Claude Code), commit, and push to master. Cloudflare Pages will automatically rebuild and deploy the site within about a minute.

To add a new page: Create the markdown file in the appropriate subfolder under docs/user/ (either Airtable/ or Supabase+React/). Then add a nav entry for it in mkdocs.yml at the repo root — the nav: section controls what appears in the sidebar and in what order. Commit and push.

To add a new section: Add a new top-level entry under nav: in mkdocs.yml, create the corresponding subfolder in docs/user/, and add your markdown files. Commit and push.

Site configuration: mkdocs.yml at the repo root controls the site name, theme settings, navigation structure, plugins, and markdown extensions. Custom CSS lives in docs/user/stylesheets/extra.css. Theme overrides live in docs/user/overrides/.

Access control: The site is protected by Cloudflare Access. Only @matthewscleaningco.com.au email addresses can log in (via one-time code). To grant access to someone outside the domain, add their email in the Cloudflare Zero Trust dashboard under Access → Applications → MCC System Documentation.

Where everything lives

What Location
CC standing instructions CLAUDE.md (repo root)
Feature docs (regression defence) docs/live/
Governance docs docs/admin/
Audit config and reports docs/admin/audit/
Health check script scripts/health-check.mjs
Weekly AI review script scripts/weekly-ai-review.mjs
GitHub Actions workflows .github/workflows/
State files apps/bms/_project-state.md, apps/client-portal/_project-state.md
Page templates apps/bms/_page-templates.md, apps/client-portal/_page-templates.md
Deploy scripts scripts/deploy-prod.ps1, scripts/deploy-edge-prod.ps1
Documentation site content docs/user/
Documentation site config mkdocs.yml (repo root)
Documentation site CSS docs/user/stylesheets/extra.css