Genairus logoGenAI-R-Us
Genairus logoGenAI-R-Us
Introducing Chronos: A Language for Product Intent
chronosrequirementsspecificationsDSLlanguage-design
Part 4 of 7 in Specification Factory

Introducing Chronos: A Language for Product Intent

Scott Walkinshaw

"We Built a New Language. I Know. Stay With Me."

I can already hear the groans. Another domain-specific language? Another thing to learn?

But here's the thing: You already have a requirements language. It's called Jira + Excel + Confluence + tribal knowledge. It's just not a very good one.

Your current "language" has:

  • No syntax validation (typos everywhere)
  • No type safety (references to things that don't exist)
  • No semantic meaning (machines can't understand it)
  • No validation (ambiguity discovered at runtime—aka production)

Chronos fixes this. And before you say "I don't want to learn a language," remember: PMs review Chronos, they don't write it. That's the AI's job.

What Makes Chronos Different

Chronos is designed around a simple idea: Product intent is data. If we structure it correctly, we can:

  1. Validate it (catch ambiguity before code is written)
  2. Transform it (generate Jira, Gherkin, diagrams, telemetry)
  3. Track it (trace features back to business outcomes)
  4. Version it (see how requirements evolved over time)

Let's see what this looks like.

A Complete Example: Insurance Claim Submission

Here's a Chronos definition for the claim submission journey we've been discussing:

namespace com.insurance.claims.submission

// Import existing entities from the data model
use com.insurance.data.policies#Policy
use com.insurance.data.claims#Claim
use com.insurance.data.users#Policyholder

// Define what success looks like
@kpi(metric: "ClaimSubmissionRate", target: ">90%")
@kpi(metric: "AutoApprovalRate", target: ">85%")
@slo(latency: "5s", percentile: 95)
journey SubmitClaim {
    actor: Policyholder

    // What must be true before this journey starts
    preconditions: [
        "Actor has active policy",
        "Actor is authenticated",
        "No claim submitted for this incident already"
    ]

    // The happy path
    steps: [
        step NavigateToClaimForm {
            action: "Clicks 'Submit Claim' from dashboard"
            expectation: "Form loads with policy details pre-filled"
            @telemetry(event: "ClaimFormStarted", attributes: ["policyId", "userId"])
        },

        step ProvideIncidentDetails {
            action: "Enters incident date, type, and description"
            expectation: "System validates incident date is within policy period"
            outcome: If("incident date > 30 days ago", TransitionTo(IncidentTooOld))
        },

        step UploadDocumentation {
            action: "Attaches photos/receipts (max 5 files, 10MB each)"
            expectation: "System validates file types (jpg, png, pdf) and sizes"
            @compliance(policy: "DataRetention", duration: "7years")
            @compliance(policy: "HIPAA", applies: "medical claims only")
        },

        step ReviewAndSubmit {
            action: "Reviews claim summary and clicks 'Submit'"
            expectation: "System creates Claim entity with status SUBMITTED"
            @telemetry(event: "ClaimSubmitted", attributes: ["claimId", "claimAmount", "claimType"])
            outcome: If("claimAmount < $1000 AND validPolicy", TransitionTo(AutoApproved),
                       Else(TransitionTo(ManualReview)))
        },

        step ReceiveConfirmation {
            action: "Views confirmation page with claim number"
            expectation: "System sends confirmation email with claim number and next steps"
            outcome: TransitionTo(ClaimTrackingAvailable)
        }
    ]

    // Error and edge cases
    variants: [
        variant IncidentTooOld {
            trigger: "Incident date is more than 30 days ago"
            outcome: "Show error: Claims must be submitted within 30 days of incident"
            @telemetry(event: "ClaimRejected", reason: "incident_too_old")
        },

        variant PolicyExpired {
            trigger: "Policy was not active on incident date"
            outcome: "Show error: No active coverage for incident date"
        },

        variant FileTooLarge {
            trigger: "Uploaded file exceeds 10MB"
            outcome: "Show error: Maximum file size is 10MB. Please compress or resize."
        },

        variant AutoApproved {
            trigger: "Claim amount < $1000 AND policy is valid"
            outcome: "Claim status set to APPROVED, payment processed within 2 business days"
            @telemetry(event: "ClaimAutoApproved", attributes: ["claimId", "approvalAmount"])
        },

        variant ManualReview {
            trigger: "Claim amount >= $1000 OR requires additional verification"
            outcome: "Claim assigned to adjuster, user notified of 3-5 day review period"
            @telemetry(event: "ClaimSentToReview", attributes: ["claimId", "assignedAdjuster"])
        }
    ]

    // What must be true when this journey completes successfully
    postconditions: [
        "Claim record exists with valid claim number",
        "User received confirmation email",
        "Claim telemetry event recorded"
    ]
}

What Just Happened?

That Chronos definition contains everything needed to build the feature:

Business Logic

  • Claim submission rules (30-day window, file size limits)
  • Auto-approval criteria (< $1,000 with valid policy)
  • Success metrics (>90% submission rate, >85% auto-approval)

Technical Requirements

  • Which entities to use (Policy, Claim, Policyholder)
  • Performance expectations (5-second p95 latency)
  • Data validation rules (file types, date ranges)

Compliance

  • HIPAA applies to medical claims
  • 7-year data retention required
  • Audit trail via telemetry events

Testing Scenarios

  • Happy path (all 5 steps)
  • Error cases (incident too old, policy expired, file too large)
  • Business logic branches (auto-approve vs manual review)

Telemetry

  • Which events to track
  • Which attributes to capture
  • How to measure KPIs

From Chronos to Everything Else

Here's what gets generated from that single Chronos file:

For Product/QA (Jira & Gherkin)

Jira Epic:

# Submit Insurance Claim

## Business Value
- KPI: Claim Submission Rate >90%
- KPI: Auto-Approval Rate >85%
- SLO: 95th percentile latency <5s

## Stories
1. As a policyholder, I want to navigate to claim form from dashboard
2. As a policyholder, I want to provide incident details with date validation
3. As a policyholder, I want to upload supporting documentation
4. As a policyholder, I want to review and submit my claim
5. As a policyholder, I want to receive confirmation of submission

## Edge Cases
- Incident date > 30 days old
- Policy expired on incident date
- File upload exceeds 10MB limit
- Auto-approval for claims < $1000
- Manual review for claims >= $1000

Gherkin Test Scenarios:

Feature: Submit Insurance Claim

  Background:
    Given a policyholder is authenticated
    And the policyholder has an active policy

  Scenario: Successfully submit claim under $1000
    When the policyholder navigates to the claim form
    And enters incident details from 5 days ago
    And uploads 2 photos (each 3MB)
    And submits a claim for $800
    Then the claim is created with status SUBMITTED
    And the claim is automatically approved
    And a confirmation email is sent
    And a "ClaimAutoApproved" event is recorded

  Scenario: Claim over $1000 requires manual review
    When the policyholder submits a claim for $5000
    Then the claim is created with status SUBMITTED
    And the claim is assigned to an adjuster
    And a "ClaimSentToReview" event is recorded

  Scenario: Incident date too old
    When the policyholder enters an incident date from 45 days ago
    Then the system shows error "Claims must be submitted within 30 days"
    And a "ClaimRejected" event is recorded with reason "incident_too_old"

For Engineering (State Diagrams & Telemetry)

Mermaid State Diagram:

stateDiagram-v2
    [*] --> FormLoaded
    FormLoaded --> IncidentDetailsEntered
    IncidentDetailsEntered --> IncidentTooOld : date > 30 days
    IncidentDetailsEntered --> DocumentationUploaded : date ok
    DocumentationUploaded --> FileTooLarge : file > 10MB
    DocumentationUploaded --> ReadyToSubmit : files ok
    ReadyToSubmit --> Submitted
    Submitted --> AutoApproved : amount < $1000
    Submitted --> ManualReview : amount >= $1000
    AutoApproved --> [*]
    ManualReview --> [*]
    IncidentTooOld --> [*]
    FileTooLarge --> DocumentationUploaded : retry

OpenTelemetry Schema:

events:
  - name: ClaimFormStarted
    attributes:
      - policyId: string
      - userId: string

  - name: ClaimSubmitted
    attributes:
      - claimId: string
      - claimAmount: number
      - claimType: string

  - name: ClaimAutoApproved
    attributes:
      - claimId: string
      - approvalAmount: number

  - name: ClaimRejected
    attributes:
      - claimId: string
      - reason: string

The Magic: It's Validated

Before generating anything, Chronos validates:

✅ Entities exist:

  • Policy, Claim, Policyholder are defined in data model

✅ Transitions are complete:

  • Every TransitionTo(X) has a matching step or variant X

✅ Business rules are feasible:

  • Auto-approval references claimAmount (which must be a Claim field)

✅ Compliance is enforced:

  • HIPAA policy applied correctly to medical claims

✅ Telemetry is measurable:

  • KPIs reference events that are actually emitted

If any of these fail, you get a validation error before code is written:

Error: Journey 'SubmitClaim' references entity 'Claim.claimAmount'
but field 'claimAmount' does not exist in com.insurance.data.claims#Claim

Suggestion: Add 'claimAmount' to Claim entity or use existing field 'amount'

Why PMs Don't Write This

"But wait," you're thinking, "I still have to learn this syntax!"

No, you don't. Here's the actual workflow:

  1. PM describes the journey in a conversation with an AI agent:

    "We need to let policyholders submit claims online. They should be able to upload photos. Claims under $1,000 should auto-approve. We need to track submission rates and auto-approval rates. HIPAA applies."

  2. AI generates the Chronos definition based on:

    • Your company's existing data models
    • Your company's compliance policies
    • Your company's engineering patterns
    • Standard insurance industry practices
  3. PM reviews the Chronos file (like a code review):

    • "Yes, 30-day window is correct"
    • "No, file limit should be 5MB not 10MB"
    • "Add a check for suspended policies"
  4. AI updates and regenerates

The Chronos file becomes the source of truth. Human-readable for review. Machine-readable for generation.

Next: The Full Stack

Chronos doesn't exist in isolation. It's one layer of a complete software factory:

  • Chronos defines what users need to accomplish
  • Smithy defines how services communicate
  • Capacitor defines how data is structured
  • Flux defines how UI is presented
  • Fusion defines how infrastructure is deployed

In the next post, The Full Stack of Intent, we'll show how these five languages work together—and why that matters for product managers.


Want to dive deeper?


This is Part 4 of the "Look Up" series exploring how AI is finally freeing product managers to do their best work.