Skip to main content

GOVERNANCE

ZARA’s Hecate

Purpose​

Hecate is the governance and integrity subsystem of Ask ZARA.

Its role is not to answer questions, modify documentation, or approve changes —
its role is to detect, surface, and explain governance drift across the ZAYAZ knowledge system.

Hecate exists to protect institutional truth, not to enforce authority.


Core Principle​

Hecate does not decide what is correct.
Hecate detects when the system is drifting away from its own rules.

Hecate is:

  • A sentinel
  • An early-warning system
  • A guardian of boundaries

Hecate is not:

  • An editor
  • An approver
  • A reviewer
  • A process owner

Position in the System​

Hecate operates alongside Ask ZARA — not inside it.

ComponentResponsibility
Docusaurus DocsStable system of record
JiraExecution & traceability
ConfluenceEvolving engineering narrative
HubSpot (RFCs)Change governance
Ask ZARAKnowledge retrieval & explanation
HecateGovernance integrity & drift detection

Ask ZARA answers questions.
Hecate flags when answers may be compromised.


What Hecate Monitors​

Hecate evaluates relationships, not raw content.

Primary Inputs​

  • Documentation metadata (Spec IDs, sections, last_updated)
  • <JiraNeed /> tags
  • Jira issue metadata (status, links, Spec ID)
  • Jira epic structure
  • RFC metadata from HubSpot (status, page_url)
  • (Later) Confluence metadata and Jira ↔ Confluence links

Hecate does not interpret intent or rewrite content.


What Is a Violation?​

A violation is not an error.

A violation is a signal that a governance rule may have been breached.

Hecate treats violations as traffic signals, not enforcement actions.


Violation Classes​

1. Source-of-Truth Violations (Highest Severity)​

Rule
Docusaurus Docs are the system of record.

Examples

  • Jira or Confluence contradicts documented contracts
  • Acceptance criteria redefine documented behavior
  • External narrative diverges from published specs

Hecate Behavior

  • Raises explicit warning
  • Cites the Playbook
  • Defers to Docs as authoritative

2. Traceability Violations​

Rule
Every execution item must trace back to Docs.

Examples

  • <JiraNeed /> without a Jira issue
  • Jira issue without Spec ID
  • Epic exists but has no children
  • Doc references a missing epic

3. Freshness & Drift Signals​

Rule
Stabilized work must be promoted to Docs.

Examples

  • Jira marked Done but Docs unchanged
  • RFC marked Published but no doc update
  • High Jira churn with stale documentation

These are warnings, not accusations.


4. Governance Process Signals​

Rule
If it’s not approved via RFC, it does not exist in the Manual.

Examples

  • Doc changes without an RFC
  • RFC approved but not deployed
  • RFC rejected but execution continues

Severity Model​

Hecate uses a graduated severity model to avoid alarm fatigue.

LevelMeaningNature
P0Governance brokenHard violation
P1High risk of wasted workImmediate warning
P2Growing entropySoft warning
P3Hygiene / qualityAdvisory signal
P4Observational insightInformational

Only P0–P2 are considered violations.
P3–P4 are system health signals.


How Hecate Surfaces Issues​

Hecate never blocks workflows.

Primary Channels​

  • Inline trust notices in Ask ZARA answers
  • System dashboards (e.g. /system/violations)
  • Cross-spec governance views

Optional Channels (Severity-based)​

  • Slack notifications
  • Email summaries
  • Jira “Validation” issues (optional, explicit)

Example Hecate Signal​

⚠️ Possible source-of-truth violation

The ZAYAZ Manual states that API contracts are immutable once published,
but Jira issue ZYZ-281 describes a breaking change.

According to the Documentation & Delivery Playbook,
Docs take precedence.

Hecate does not fix — it flags.


What Hecate Must Never Do​

🚫 Modify Docs
🚫 Approve changes
🚫 Override human decisions
🚫 Invent governance rules
🚫 Treat Jira or Confluence as authoritative over Docs

Hecate protects the system — it does not control it.


Relationship to Ask ZARA​

Ask ZARA may:

  • Reference Hecate signals
  • Adjust confidence indicators
  • Surface governance context

Ask ZARA must never:

  • Suppress answers because of violations
  • Rewrite content to “fix” violations

Design Philosophy​

Most AI systems answer questions.

Hecate ensures the questions remain answerable.

This transforms Ask ZARA from:

  • A search assistant

Into:

  • A governance-aware system
  • A drift detector
  • An institutional memory guardian

North Star​

Truth degrades silently.
Hecate exists to make drift visible.


Hecate Audit Rules v1​

#Rule (type)What it detectsSeverityDeterministic checkInputsSuggested routing
1missing-jira-key
JiraTaskUnlinked(unlinked)
 exists but has no jiraKey
P0Parse MDX → find <JiraNeed …/>→ if jiraKey missing/blankDocs MDXDashboard + Slack/Email
2jira-issue-not-foundjiraKey exists in MDX but not found in progress.json(or Jira API)P0Validate key pattern + lookup in progress.json issues (optional: Jira /issue/{key})Docs MDX + progress.json(+ Jira API)Dashboard + Slack/Email
3jira-missing-doc-backlinkJira issue exists but has no remote link back to SpecsP1Jira issue remotelinks contain no URL starting with DOCS_BASE_URLJira API (remotelink)Dashboard + Slack/Email (to governance owner)
4epic-declared-in-docs-but-not-foundDocs frontmatter declares jira.epic, but progress index has no matching epic entryP0Docs specId has epicKey, but progress.epics[specId] missing or epicKey mismatchDocs frontmatter + progress.jsonDashboard + Slack/Email
5epic-has-no-childrenDoc has jira.epic but epic has 0 childrenP1progress.epics[specId].counts.total === 0Docs frontmatter + progress.jsonDashboard (Slack if >24h / “age” threshold)
6jira-not-linked-to-doc-epicA doc’s jiraKey exists but is under a different epic/spec in the progress indexP1jiraIssueByKey[jiraKey].specId !== doc.specId OR epicKey mismatchDocs MDX + progress.jsonDashboard + Slack/Email (PM + governance owner)
7done-but-doc-staleEpic has recent activity / done work but docs appear staleP2if epic.updatedMax > doc.last_updated + staleDaysprogress.json+ Docs frontmatterDashboard (digest optional)
8rfc-published-but-docs-unchangedHubSpot RFC is Published for a page_url but doc unchanged since RFC updatedP2(raise later if needed)Compare hubspot.updatedAt(stage=Published)vs doc.last_updatedHubSpot metadata export + Docs frontmatterDashboard + Slack/Email (owner)

Notes on severity (why P0/P1/P2)​

  • P0 = traceability is broken at the leaf level (the thing you think is being executed can’t even be reliably located).
  • P1 = execution is disconnected from authority (Jira exists but isn’t anchored to Docs properly, or specs/IDs don’t line up).
  • P2 = system drift / staleness (not necessarily wrong, but risky and should be surfaced).

Violation object shape (with Canonical violation types v1)​

This format is designed to:

  • work for dashboards + sorting + filtering
  • be “attachable” to Ask ZARA answers
  • survive growth (Confluence, richer refs) without breaking

/workspaces/zayaz-docs/docusaurus/src/shared/hecate-types.ts:

// src/shared/hecate-types.ts

export type Severity = "P0" | "P1" | "P2" | "P3" | "P4";

export type ViolationType =
| "missing-jira-key"
| "jira-issue-not-found"
| "jira-missing-doc-backlink"
| "jira-not-linked-to-doc-epic"
| "epic-declared-in-docs-but-not-found"
| "epic-has-no-children"
| "spec-has-epic-but-epic-empty"
| "done-but-doc-stale"
| "orphan-jira-specid"
| "rfc-published-but-docs-unchanged";

export type Violation = {
id: string; // stable hash
severity: Severity;
type: ViolationType;

title: string;
message: string;
ruleRef?: string;

scope: "need" | "section" | "page" | "spec" | "system";

specId?: string;
doc?: {
id?: string;
path?: string;
sourceFile?: string;
lastUpdated?: string;
};
section?: {
anchor?: string;
heading?: string;
needId?: string;
};

jira?: {
key?: string;
epicKey?: string;
url?: string;
updated?: string;
};

rfc?: {
pageUrl?: string;
ticketId?: string;
stage?: string;
updated?: string;
};

evidence?: Array<{
source: "docs" | "jira" | "hubspot" | "confluence";
note: string;
}>;

suggestedFix?: {
kind: "run-script" | "edit-doc" | "update-jira" | "review-rfc";
label: string;
command?: string;
link?: string;
};

detectedAt: string;
};

Severity mapping​

ViolationTypeSeverity
missing-jira-keyP0
jira-issue-not-foundP0
epic-declared-in-docs-but-not-foundP0
jira-not-linked-to-doc-epicP1
epic-has-no-childrenP1
jira-missing-doc-backlinkP2
done-but-doc-staleP2
rfc-published-but-docs-unchangedP3

Rule definitions with title/message templates + suggestedFix​

1. missing-jira-key (P0)​

When: <JiraNeed /> exists but no jiraKey.

  • scope: need (or section if you don’t want per-need granularity)
  • title: Unlinked JiraNeed
  • message template:
    • A tag exists but has no jiraKey. Execution cannot be traced to Jira.
      JiraTaskUnlinked(unlinked)
  • evidence:
    • source=docs: Found without jiraKey in section {anchor}
      JiraTaskUnlinked(unlinked)
  • suggestedFix:
    • run-script: npm run sync:jira-needs
    • edit-doc: “Add jiraKey to tag”
{
"type": "missing-jira-key",
"severity": "P0",
"title": "Unlinked JiraNeed",
"message": "A <JiraNeed/> tag exists but has no jiraKey. Execution cannot be traced to Jira."
}

2. jira-issue-not-found (P0)​

When: MDX contains jiraKey, but it’s not present in your Jira index (progress.json or dedicated Jira ETL).

  • scope: need
  • title: Jira issue not found
  • message:
    • The docs reference Jira key {jiraKey}, but it was not found in the Jira index.
  • evidence:
    • docs: jiraKey={jiraKey} present in MDX
    • jira: key not found in progress.json
  • suggestedFix:
    • run-script: npm run jira:progress-index (and/or Jira ETL)
    • update-jira: verify key exists / permissions

When: Jira issue exists but has no remote link back to Docs (DOCS_BASE_URL).

  • scope: need
  • title: Jira issue missing Docs link
  • message:
    • Jira issue {jiraKey} has no web link back to the ZAYAZ Manual. Traceability is incomplete.
  • evidence:
    • jira: No remotelink matching ${DOCS_BASE_URL}
  • suggestedFix:
    • run-script: npm run jira:backfill-links (or sync:jira-needs for new)
    • update-jira: add remote link manually

4. jira-missing-spec-id (P1)​

When: Jira issue exists but Spec ID custom field is empty.

  • scope: need
  • title: Jira issue missing Spec ID
  • message:
    • Jira issue {jiraKey} is missing Spec ID. It cannot be reliably tied to a spec.
  • suggestedFix:
    • update-jira: set Spec ID field
    • run-script: (optional) re-sync/patch script if you automate it later

5. spec-has-epic-but-epic-empty (P1)​

When: doc has jira.epic, but epic has 0 children.

  • scope: spec
  • title: Epic has no child issues
  • message:
    • Spec {specId} links to epic {epicKey}, but no child issues were found.
  • evidence:
    • progress: counts.total = 0
  • suggestedFix:
    • update-jira: add/link child issues to epic
    • run-script: npm run jira:progress-index (after fixing)

6. done-but-doc-stale (P2)​

When: Jira activity is newer than doc last_updated by threshold (e.g. 7 days), OR epic has done work but doc hasn’t moved.

  • scope: spec (or page)
  • title: Documentation may be stale
  • message:
    • Jira activity for {specId} is newer than the doc update timestamp. Consider promoting stabilized outcomes to Docs.
  • evidence:
    • docs: last_updated={...}
    • jira: updatedMax={...}
  • suggestedFix:
    • edit-doc: update page + bump last_updated
    • (optional) create Jira “Validation” task later

7. orphan-jira-specid (P1)​

When: Jira issue has Spec ID that does not exist in docs index.

  • scope: need (or system if you group)
  • title: Orphaned Jira Spec ID
  • message:
    • Jira issue {jiraKey} references Spec ID {specId}, but no matching doc id was found.
  • suggestedFix:
    • edit-doc: add/create doc with that id, or correct Spec ID in Jira
    • update-jira: fix Spec ID

8. rfc-published-but-docs-unchanged (P2)​

When: HubSpot RFC ticket is Published (or equivalent stage), but doc last_updated is older than RFC updated time.

  • scope: page
  • title: RFC published but docs not updated
  • message:
    • An RFC for this page is marked Published in HubSpot, but the manual has not been updated since.
  • suggestedFix:
    • review-rfc: open HubSpot ticket
    • edit-doc: implement approved change

Architecture​

  • hecate-types.ts = law
  • knowledge-audit.ts = enforcement
  • ZARA = messenger
/workspaces/zayaz-docs
│
├─ docusaurus/
│ └─ src/
│ └─ shared/
│ ├─ jira-types.ts
│ ├─ hecate-types.ts
│ └─ trust-types.ts
│
├─ scripts/
│ └─ audit/
│ └─ knowledge-audit.ts ← imports hecate-types
│
└─ docusaurus/static/
└─ system/
└─ violations.json ← generated

How imports should look​

From Docusaurus / React / Ask ZARA

import type { Violation, Severity } from "@site/src/shared/hecate-types";

(Docusaurus aliases @site → docusaurus root)

From audit scripts (Node)

import type { Violation } from "../../docusaurus/src/shared/hecate-types";

(relative path from scripts/audit/knowledge-audit.ts)

Explicit rule​

If a type is used by both build scripts and the site, it lives in docusaurus/src/shared/.



GitHub RepoRequest for Change (RFC)