version: 5
domain: agent.mue.app
last_reviewed: 2026-05-03

categories:
  - preservation
  - visibility
  - honesty
  - reflexivity
  - liveness
  - containment
  - discoverability
  - progress

# Schema rule: every evaluator uses `target` (URL or repo path).
# No mixed `url`, `target_url`, or untyped fields.

# Edit policy:
#   foundational categories (everything except `progress`) are human-edited.
#   `progress` category is editable by mue-translator-weekly. Max 8 entries.

# Brand naming policy (replaces the prior CST-041 vs CST-045 conflict):
#   "Mue Agency" is the formal/legal name. Used in: JSON-LD Organization.name,
#     imprint copyright line, structured-data publisher fields, og:site_name.
#   "mue" is the wordmark / display brand. Used in: header logo, footer logo,
#     page title suffix (per CST-043), visual brand elements.
#   Both are canonical in their assigned contexts; neither alone is a violation.
#   See CST-041 for enforcement.

constraints:

  - id: CST-001
    category: visibility
    name: audit_index_lists_history
    description: The /audit/ index page lists at least 4 dated audit reports (YYYY-MM-DD.md) to show sustained operation rather than a single recent run.
    evaluator: { type: web_fetch, target: "https://agent.mue.app/audit/", check: visible_report_count_at_least, count: 4 }
    severity: medium

  - id: CST-002
    category: visibility
    name: constraints_page_published
    description: The /constraints/ page renders every entry in CONSTRAINTS.yaml.
    evaluator: { type: web_fetch, target: "https://agent.mue.app/constraints/", check: visible_constraint_count_matches_yaml }
    severity: high

  - id: CST-003
    category: reflexivity
    name: constraints_yaml_served_raw
    description: CONSTRAINTS.yaml is fetchable at https://agent.mue.app/constraints.yaml as machine-readable text/yaml.
    evaluator: { type: web_fetch, target: "https://agent.mue.app/constraints.yaml", check: returns_200_yaml }
    severity: high

  - id: CST-004
    category: honesty
    name: every_homepage_claim_links_to_resolvable_evidence
    description: Every distinct factual or capability claim on the homepage links to evidence (case study, article, audit entry, repo, or task) AND that evidence link returns 200.
    evaluator: { type: semantic, target: "https://agent.mue.app/", check: every_claim_has_resolvable_evidence_link }
    severity: medium

  - id: CST-005
    category: containment
    name: homepage_word_budget
    description: The homepage body copy is under 400 words.
    evaluator: { type: web_fetch, target: "https://agent.mue.app/", check: word_count_under, threshold: 400 }
    severity: low

  - id: CST-006
    category: containment
    name: banned_phrase_set
    description: The site contains no phrase from BANNED_PHRASES.txt.
    evaluator: { type: regex_scan, target: full_site, patterns_file: BANNED_PHRASES.txt }
    severity: medium

  - id: CST-007
    category: liveness
    name: heartbeat_freshness
    description: The mue-inbox processor heartbeated within the last 6 hours during operating window (09-21 UTC). Outside the operating window this constraint passes by definition.
    evaluator: { type: system_check, source: mue_state.last_heartbeat_at, check: within_hours_during_window, hours: 6, operating_window_utc: "09-21", out_of_window_behavior: pass }
    severity: high

  - id: CST-008
    category: liveness
    name: dev_runner_active_within_30_days
    description: dev-runner-mue-site has completed at least one task within the last 30 days.
    evaluator: { type: task_board_query, check: tasks_completed_by_runner_within_days, runner: dev-runner-mue-site, days: 30 }
    severity: medium

  - id: CST-009
    category: visibility
    name: task_board_view_published
    description: The /tasks/ page shows the current state of the task-board for project=mue-site, refreshed within the last 7 days.
    evaluator: { type: web_fetch, target: "https://agent.mue.app/tasks/", check: contains_recent_task_data_within_days, days: 7 }
    severity: medium

  - id: CST-010
    category: visibility
    name: agent_charter_published
    description: The /agents/ page lists every active agent and matches AGENTS.yaml exactly.
    evaluator: { type: web_fetch, target: "https://agent.mue.app/agents/", check: matches_agents_yaml }
    severity: medium

  - id: CST-011
    category: honesty
    name: changes_attributed
    description: Every commit to SFLOW-MUE-SITE declares an agent runner ID in brackets or a "human:" prefix in the commit message.
    evaluator: { type: git_log_scan, check: all_commits_attributed }
    severity: medium

  - id: CST-012
    category: reflexivity
    name: auditor_runs_weekly
    description: A new audit report appears in /audit/ at least once every 8 days.
    evaluator: { type: web_fetch, target: "https://agent.mue.app/audit/", check: most_recent_report_within_days, days: 8 }
    severity: high

  - id: CST-013
    category: containment
    name: no_unattributed_case_studies
    description: Every case study published either names the subject or is marked "anonymized" with a one-line reason.
    evaluator: { type: semantic, target: "https://agent.mue.app/cases/", check: every_case_named_or_marked_with_reason }
    severity: medium

  - id: CST-014
    category: liveness
    name: homepage_links_to_articles
    description: The homepage contains at least one link with href starting with /articles/.
    evaluator: { type: web_fetch, target: "https://agent.mue.app/", check: contains_link_to_path_prefix, path_prefix: /articles/ }
    severity: medium

  - id: CST-015
    category: reflexivity
    name: constraint_set_evolves
    description: CONSTRAINTS.yaml has gained or modified at least one entry within the last 90 days, OR carries a documented "frozen: true" flag with a reason.
    evaluator: { type: git_log_scan, target: CONSTRAINTS.yaml, check: edited_within_days, days: 90 }
    severity: low

  - id: CST-016
    category: preservation
    name: articles_directory_preserved
    description: The /articles/ section exists and contains at least 3 published articles, with the most recent within 90 days OR the section index carries an "evergreen: true" frontmatter flag.
    evaluator: { type: web_fetch, target: "https://agent.mue.app/articles/", check: contains_item_count_with_freshness_or_evergreen, min_count: 3, max_age_days: 90 }
    severity: high

  - id: CST-017
    category: preservation
    name: belgium_ai_news_preserved
    description: The /belgium-ai-news/ section exists, contains at least 3 published items, and the most recent item is within 30 days.
    evaluator: { type: web_fetch, target: "https://agent.mue.app/belgium-ai-news/", check: contains_item_count_and_freshness, min_count: 3, max_age_days: 30 }
    severity: high

  - id: CST-018
    category: discoverability
    name: homepage_jsonld_organization_complete
    description: Homepage contains a script[type=application/ld+json] with @type Organization including name (Mue Agency), url, logo, parentOrganization (SFLOW BV, vatID BE 0785.972.390), founder (Florian Smeyers), email (agent@mue.app), and a sameAs array with at least one social or professional profile.
    evaluator: { type: semantic, target: "https://agent.mue.app/", check: contains_jsonld_organization_complete_v2 }
    severity: medium

  - id: CST-019
    category: discoverability
    name: homepage_open_graph_and_canonical
    description: Homepage contains og:type, og:site_name, og:url, og:title, og:description, og:image, twitter:card, AND a single canonical link rel pointing to https://agent.mue.app/.
    evaluator: { type: regex_scan, target: "https://agent.mue.app/", patterns: ["og:type", "og:site_name", "og:url", "og:title", "og:description", "og:image", "twitter:card", "rel=\"canonical\""] }
    severity: medium

  - id: CST-020
    category: discoverability
    name: homepage_meta_description_and_resolvable_hreflang
    description: Homepage contains a meta name="description" tag of at least 80 characters AND hreflang link rels for en, nl, x-default. Each declared hreflang target URL must resolve with status 200.
    evaluator: { type: semantic, target: "https://agent.mue.app/", check: meta_description_and_resolvable_hreflang, min_description_chars: 80 }
    severity: medium

  - id: CST-021
    category: discoverability
    name: sitemap_and_robots
    description: /sitemap.xml exists, lists at least 10 URLs, and is referenced from /robots.txt. /robots.txt exists and does not block well-formed crawlers from public sections.
    evaluator: { type: web_fetch, target: "https://agent.mue.app/sitemap.xml", check: sitemap_and_robots_consistent, min_urls: 10 }
    severity: medium

  - id: CST-022
    category: discoverability
    name: rss_feed_for_serial_content
    description: /articles/ and /belgium-ai-news/ each expose an RSS or Atom feed (e.g. /articles/feed.xml, /belgium-ai-news/feed.xml) that returns 200 with valid feed XML and at least 1 item.
    evaluator: { type: web_fetch, target: "https://agent.mue.app/", check: serial_sections_have_feeds, sections: ["articles", "belgium-ai-news"] }
    severity: low

  - id: CST-023
    category: discoverability
    name: tls_and_no_mixed_content
    description: All public pages serve over HTTPS with a valid certificate. No public page contains an http:// reference to an asset or link.
    evaluator: { type: semantic, target: full_site, check: https_only_no_mixed_content }
    severity: high

  - id: CST-024
    category: preservation
    name: imprint_and_legal_published
    description: An imprint or legal page (/imprint/ or /legal/) exists, names SFLOW BV with VAT BE 0785.972.390, lists a contact email, and is linked from the site footer.
    evaluator: { type: semantic, target: "https://agent.mue.app/imprint/", check: imprint_complete }
    severity: medium

  - id: CST-025
    category: reflexivity
    name: audit_reports_cite_constraint_ids
    description: Every audit report under /audit/ from the last 30 days references at least one CST-ID in its body. Reports without any CST-ID reference are considered empty and fail this constraint.
    evaluator: { type: semantic, target: "https://agent.mue.app/audit/", check: recent_reports_cite_constraint_ids, days: 30 }
    severity: medium

  - id: CST-026
    category: reflexivity
    name: violation_tasks_carry_constraint_id
    description: Every dev task created by mue-site-auditor includes a constraint_id field referencing a CST-ID, AND the resulting commit message references the same CST-ID in brackets (e.g. [CST-021]).
    evaluator: { type: task_board_query, check: violation_tasks_and_commits_carry_constraint_id }
    severity: medium

  - id: CST-027
    category: reflexivity
    name: banned_phrases_publicly_visible
    description: BANNED_PHRASES.txt is published at /constraints/banned-phrases.txt and returns 200 as text/plain.
    evaluator: { type: web_fetch, target: "https://agent.mue.app/constraints/banned-phrases.txt", check: returns_200_text }
    severity: low

  # progress category. Edited weekly by mue-translator. Max 8 entries.

  - id: CST-028
    category: progress
    name: roadmap_has_active_items
    description: ROADMAP.yaml has between 3 and 15 open items inclusive.
    evaluator: { type: git_log_scan, target: ROADMAP.yaml, check: open_item_count_between, min: 3, max: 15 }
    severity: medium

  - id: CST-029
    category: progress
    name: roadmap_items_link_to_mission
    description: Every open ROADMAP item carries a mission_link field whose value is a substring of MISSION.md.
    evaluator: { type: semantic, target: ROADMAP.yaml, check: every_open_item_has_valid_mission_link, mission_file: MISSION.md }
    severity: medium

  - id: CST-030
    category: progress
    name: shipping_cadence
    description: At least 1 ROADMAP item transitioned to status done within the last 30 days, OR ROADMAP.yaml carries a documented paused_reason field with a date.
    evaluator: { type: git_log_scan, target: ROADMAP.yaml, check: items_completed_within_days_or_paused, days: 30 }
    severity: high

  - id: CST-031
    category: progress
    name: case_study_cadence
    description: /cases/ contains at least one case study (named or anonymized with a reason) added within the last 60 days.
    evaluator: { type: web_fetch, target: "https://agent.mue.app/cases/", check: latest_case_study_within_days, days: 60 }
    severity: medium

  - id: CST-049
    category: progress
    name: testimonial_widget_published
    description: The homepage contains a client testimonial widget with at least one verifiable quote from a Belgian accounting firm or professional services client. Enforces RM-013.
    evaluator: { type: semantic, target: "https://agent.mue.app/", check: homepage_has_testimonial_widget_with_verifiable_quote }
    severity: high

  - id: CST-050
    category: progress
    name: video_walkthrough_published
    description: A 60-second video walkthrough demonstrating live self-governance exists on the site, either embedded on the homepage or on a dedicated /demo/ or /how-it-works/ page. The video shows real agent workflow in action. Enforces RM-010.
    evaluator: { type: web_fetch, target: "https://agent.mue.app/", check: video_walkthrough_exists_on_site }
    severity: medium

  - id: CST-051
    category: progress
    name: roi_section_published
    description: A measurable ROI section exists showing cost and time savings from autonomous governance, with verifiable metrics or methodology. Located on /pricing/, /why-mue/, or the homepage. Enforces RM-031.
    evaluator: { type: semantic, target: "https://agent.mue.app/", check: roi_section_with_verifiable_metrics_exists }
    severity: medium

  - id: CST-036
    category: containment
    name: footer_identical_across_pages
    description: Every public page renders an identical footer block. The footer contains, at minimum, a link to /imprint/, a link to /privacy/, the site wordmark "mue" (per CST-041), and a copyright line naming SFLOW BV. The HTML of the footer block (between matching <footer> tags or equivalent container) is byte-identical across all public pages.
    evaluator: { type: semantic, target: full_site, check: footer_block_identical_across_pages }
    severity: medium

  - id: CST-037
    category: discoverability
    name: per_page_metadata_complete
    description: Every public page (homepage plus all pages under /articles/, /belgium-ai-news/, /cases/, and any other indexed section) contains a unique <title>, a meta name="description" of at least 80 characters, og:title, og:description, og:url matching the canonical URL of that page, and a single rel="canonical" link rel pointing to that page's canonical URL. Boilerplate or homepage-copied metadata on inner pages fails this constraint.
    evaluator: { type: semantic, target: full_site, check: every_public_page_has_unique_metadata, min_description_chars: 80 }
    severity: medium

  - id: CST-038
    category: discoverability
    name: article_structured_data
    description: Every page under /articles/ contains JSON-LD with @type Article, and every page under /belgium-ai-news/ contains JSON-LD with @type NewsArticle. Each entry includes headline, datePublished, dateModified, author (name and either url or sameAs), and publisher (Mue Agency Organization, matching CST-018). datePublished is the original publication date; dateModified is the last edit date and may equal datePublished.
    evaluator: { type: semantic, target: full_site, check: serial_pages_have_article_jsonld, sections: ["articles", "belgium-ai-news"] }
    severity: medium

  - id: CST-039
    category: preservation
    name: privacy_and_cookie_disclosure
    description: A privacy page exists (/privacy/ or /privacy-policy/) that names the data controller (SFLOW BV, VAT BE 0785.972.390), states what data is collected (or that no tracking is performed), names any third-party services that receive visitor data, lists visitor rights under GDPR, and provides a contact for data requests. The page is linked from the site footer alongside the imprint link. If the site sets any non-essential cookie or runs any analytics, a cookie consent surface exists; if neither, the privacy page explicitly states "no cookies, no analytics, no tracking" and the constraint passes without a consent surface.
    evaluator: { type: semantic, target: "https://agent.mue.app/privacy/", check: privacy_page_complete_and_linked }
    severity: medium

  - id: CST-040
    category: containment
    name: header_and_nav_consistent
    description: Every public page renders a header containing the wordmark "mue" (per CST-041) and the same primary navigation links in the same order. Header HTML is byte-identical across pages, exempting an "active page" indicator class on the current nav item.
    evaluator: { type: semantic, target: full_site, check: header_and_nav_consistent_across_pages }
    severity: medium

  - id: CST-041
    category: containment
    name: brand_name_two_forms_only
    description: |
      The site uses exactly two canonical brand strings, each in its assigned context:
        - "Mue Agency" is the formal/legal name. Allowed only in JSON-LD
          Organization.name fields, og:site_name meta tag, imprint copyright line,
          and structured-data publisher fields.
        - "mue" is the wordmark / display brand. Allowed in header logo, footer
          logo, page title suffix (per CST-043), and visual brand elements.
      Variants outside this list ("MUE", "Mue.app", "Mue Bureau", "Mue Studio",
      "mue.app" as a brand label, or any unlisted casing) are violations.
      URL strings "agent.mue.app" and "mue.app" used as addresses (in href values,
      canonical URLs, og:url, etc.) are exempt; this constraint governs the brand
      label, not URL strings.
    evaluator: { type: semantic, target: full_site, check: brand_strings_in_assigned_contexts_only, formal: "Mue Agency", wordmark: "mue", domain_strings_exempt: ["agent.mue.app", "mue.app"] }
    severity: medium

  - id: CST-042
    category: containment
    name: shared_stylesheet_referenced
    description: Every public page links to the same primary stylesheet (e.g. /style.css or /assets/main.css) via <link rel="stylesheet">. Inline <style> blocks are permitted for page-specific tweaks but the primary stylesheet must always be present.
    evaluator: { type: regex_scan, target: full_site, check: every_page_links_primary_stylesheet }
    severity: low

  - id: CST-043
    category: containment
    name: page_title_format
    description: |
      Every public page's <title> tag follows the format "<page-specific name> | mue".
      The homepage title is exactly "mue" or "<short tagline> | mue". Titles are unique
      per page and at least 20 characters total. The wordmark "mue" is the canonical
      title suffix (per CST-041); the formal name "Mue Agency" appears in og:site_name
      and JSON-LD Organization.name only, never in the <title> tag.
    evaluator: { type: semantic, target: full_site, check: title_tag_format_compliant, suffix: "mue" }
    severity: low

  - id: CST-044
    category: containment
    name: favicon_and_app_icons_present
    description: Homepage and all public pages link to a favicon (/favicon.ico or via <link rel="icon">). The favicon resource resolves with status 200. An apple-touch-icon link is also present.
    evaluator: { type: semantic, target: full_site, check: favicon_and_apple_touch_icon_present_and_resolvable }
    severity: low

  # CST-045 deleted in v5. Its prior text ("All pages should feature the same
  # header like 'mue'. Not Mue Agency, ... AND contain the exact same footer")
  # duplicated CST-036 (footer identical), CST-040 (header consistent), and
  # CST-041 (brand name canonical), and directly contradicted CST-041's old
  # rule that "Mue Agency" was the sole canonical form. The contradiction was
  # the source of dev-runner thrashing on 2026-05-03 (footer/header tasks
  # claimed and timed out). Coverage is now: CST-036 + CST-040 + CST-041 +
  # CST-042 + CST-046.

  - id: CST-046
    category: containment
    name: homepage_design_meets_minimum_bar
    description: |
      The homepage delivers a usable, modern landing experience for human visitors.
      All seven sub-rules below must hold simultaneously. Failure of any sub-rule
      fails the constraint, with the failing sub-rule(s) cited in the evidence.

      1. Hero section. The first <section> (or first content block before the next
         <section>) contains: an <h1>, a sub-headline (any of <h2>, <p class="lede">,
         <p class="subhead">, or equivalent), and a primary call-to-action (an <a>
         or <button> with action-oriented copy such as "Contact", "Book a call",
         "Get started", "Try it"). All three are present.

      2. Visual element in hero. The first <section> contains at least one of:
         <img>, <svg> illustration with shape content (not just a logo glyph),
         <picture>, or <video>. ASCII art and decorative pseudo-elements do not
         count.

      3. Structure below hero. The body contains at least three distinct top-level
         <section> elements (or equivalent <article>/<main> children with semantic
         headings), each with a visible <h2> or <h3>. Header, footer, and nav are
         excluded from this count.

      4. Mobile viewport. The HTML head contains
         <meta name="viewport" content="width=device-width, initial-scale=1">
         (or equivalent with initial-scale = 1).

      5. No broken images. Every <img src> on the page returns HTTP 200 when
         fetched. <picture> sources also resolve. Inline data: URIs are exempt.

      6. Footer present. The page renders a <footer> matching CST-036.

      7. Page weight. The HTML document itself (excluding linked CSS, JS, images,
         fonts) is under 100 KB transferred. This is a proxy for "the page is not
         a runaway wall of text or markup".
    evaluator: { type: semantic, target: "https://agent.mue.app/", check: homepage_design_meets_minimum_bar }
    severity: high

  - id: CST-047
    category: containment
    name: translations_have_content_parity
    description: |
      Translated pages (currently /nl/ and /fr/, plus any future /xx/ language
      root) preserve the substantive content of the EN homepage, not merely its
      section structure or labels. Structural similarity (matching section names,
      same number of headings, same outline) is NOT sufficient evidence and the
      auditor must explicitly compare claim content, not section counts.

      All sub-rules below must hold for each translated root page:

      1. The page returns HTTP 200 and carries lang="<code>" on the <html> element.

      2. JSON-LD on the page includes inLanguage matching the lang code.

      3. Word count tolerance. Body word count is between 70% and 130% of the EN
         homepage body word count. Below 70% indicates a stub translation; above
         130% indicates the localized page has drifted into different content.

      4. Required brand strings appear verbatim (brand strings do not get
         translated): "SFLOW BV", "BE 0785.972.390", "Florian Smeyers",
         "agent@mue.app".

      5. Required claim equivalents. Each of the EN homepage's primary claims has
         a corresponding translated claim on the localized page. The list of
         required claims (and their per-locale required substrings) lives in
         TRANSLATIONS.yaml at the repo root, keyed by locale. If TRANSLATIONS.yaml
         is missing, empty, or has no entry for a locale, that locale's check
         FAILS. We do not pass on absent input.

      6. Footer links to /imprint/ and /privacy/ exist on the translated page
         (per CST-036; this rule reaffirms in the translated context).
    evaluator: { type: semantic, target: full_site, check: translations_have_content_parity, locales: ["nl", "fr"], reference: "https://agent.mue.app/", manifest: TRANSLATIONS.yaml }
    severity: high
