Inspiration

Every engineering org has a folder of Architecture Decision Records that nobody reads. "Billing stays on Postgres." "No destructive migrations." "Never store raw card data." Each one cost a meeting, a debate and a page. Six months later a new engineer, or a coding agent, adds MongoDB to the billing service, and the decision that should have stopped them sits three clicks deep in Confluence.

Decisions aren't the problem. Writing them down isn't enough, because a written decision doesn't act on anything. We wanted a decision to behave like a test: written once, and checked every time the work changes.

What it does

Precedent turns an ADR into guardrails, small rules a machine can check, and applies them everywhere work happens.

  • Capture (Confluence): on any ADR page, ••• → Record as precedent extracts the decision, context, alternatives, owner and proposed guardrails (100% extraction confidence on the demo ADRs). Save it as a draft or approve it. A byline shows every decision recorded from a page. A decision card macro embeds a live decision on any page, and shows when it has been superseded.
  • Enforce (Jira):
    • Every work item gets a verdict: pass / info / warn / block. It shows in a Precedent section of the issue sidebar (for example a red block · DEC-1) and in a full issue panel with the evidence and links.
    • The verdict is also stored on the issue, so JQL works: precedentVerdict = block.
    • A workflow validator refuses a transition that breaks a decision, for example moving a migration ticket to Done during the year-end freeze. A condition hides that transition. The precedent-override label is an audited escape hatch.
    • An Automation action (Check against Precedent) returns {{verdict}}, {{blocking}} and {{summary}} to any rule.
  • Ask (Rovo): the Precedent agent answers "Can we use MongoDB for the new invoices service?" with BLOCK DEC-1, the rationale, the compliant alternative and links. Its skills check work items, capture decisions from conversations and draft superseding decisions. It never approves anything by itself.
  • Prevent (MCP): the same tools are exposed through rovo:mcp to Cursor, Claude Code and any MCP client. Our open-source skill.md tells the agent to call check-change before it adds a dependency, writes a migration or changes an API. The verdict arrives before the code exists.
  • Connect (Teamwork Graph):
    • Approved decisions are published into the graph as documents linked to the work items they govern, so Rovo Search and every agent can find them.
    • Each decision reads the graph back to show who owns it, which teams and goals it touches, and which pull requests reference the affected work.
  • Maintain: each decision has a supersede lineage (moment.js → date-fns). A daily sweep flags decisions past their review date, decisions whose owner has gone inactive, and decisions that have no guardrails.

The verdicts come from a deterministic rule engine with no AI: the same input gives the same verdict, so it can safely gate a workflow. AI handles the language work (capture, Q&A, drafting) through Rovo. Precedent makes no outside calls and stores everything in Forge SQL and Forge KVS: it Runs on Atlassian.

How we built it

  • Forge, all-in. Modules:
    • Jira: issue panel, issue context (with dynamic status), issue action, global page, admin pages, workflow validator, workflow condition, entity property (JQL aliases), product triggers, scheduled trigger.
    • Confluence: content action, byline, macro with a UI Kit config.
    • global:ui, Automation action provider.
    • Rovo: rovo:agent, three rovo:skills, nine actions, rovo:mcp.
    • Teamwork Graph: graph:connector, plus curated requestTeamworkGraph queries.
    • Storage: sql (Forge SQL with versioned migrations) and Forge KVS.
  • Guardrail language. A small DSL with a parser, formatter and round-trip tests: deny dependency mongodb aka mongo, mongoose in service billing-*, freeze transitions to Done between 2026-12-14 and 2027-01-04 in label db-migration, require label deprecation-plan when service public-api. Scopes are evaluated tri-state (match / no-match / unknown). When the engine can't see a dimension, it caps the finding at warn instead of guessing.
  • Evidence. Dependencies are read from text, explicit lists and unified diffs (package.json, requirements.txt, go.mod, imports). Services are inferred from labels, components and services/<name>/ paths. Search is BM25. The ADR extractor parses the Confluence storage format.
  • UI. Custom UI with React 18 and Atlaskit, in the Atlassian light theme. UI Kit for global:ui and the macro config.
  • Tests. 45 unit tests cover the DSL, the engine, the service and the extractor. On the live site, 22 of 22 demo work items got their expected verdict from the real issue-created trigger.

Challenges

  • A verdict that can block a workflow has to be trustworthy. We kept AI out of the enforcement path entirely, made scope evaluation tri-state, and made the validator fail open: a broken app must never freeze a team.
  • Teamwork Graph details. Ingestion silently rejected documents that had a relative URL or SQL-style timestamps. Once those were fixed, all documents were accepted and indexed within minutes.
  • The rough edges of a platform in Preview:
    • Configure pages live on a different URL from normal admin pages.
    • Custom macro config needs its own resource.
    • External MCP exposure has to be enabled before Confluence is connected.
  • Forge time limits. The one-click demo builds 2 containers, 10 pages, 10 decisions and 22 checked work items, so it runs as a resumable, step-wise job driven by the admin page.

Accomplishments

  • One decision record drives seven surfaces: Jira panel, sidebar, validator, Automation, Confluence, Rovo and MCP.
  • The same guardrail stops an engineer clicking Done in Jira and a coding agent about to npm install mongodb.
  • Runs on Atlassian eligible: no egress, no outside AI, no data leaving the customer's cloud.
  • One click turns an empty site into a believable engineering org with real conflicts to explore.

What we learned

  • Writing decisions down is not enough on its own. A decision only has an effect when it is wired to the moment a change is made.
  • The judgement belongs to humans and the proof belongs to the engine. Rovo is excellent at turning prose into draft guardrails, and humans approve them. A deterministic engine applies them.
  • Teamwork Graph turns "a rule" into "a rule owned by these people, for this goal", which is what makes an override conversation productive.

What's next

  • Bitbucket and GitHub pull-request checks using the same check-change engine, as a status check.
  • Compass component scopes, so guardrails attach to services directly.
  • Suggested guardrails mined from incident postmortems.
  • Decision analytics: which decisions get overridden most, a signal that they should be revisited.

Built With

Share this project:

Updates

Submission history