{
  "policy": {
    "version": 5,
    "patterns": {
      "version": 1,
      "method": "CURATED_PRACTICE_TOPIC",
      "notice": "Pattern topics identify design choices to practice. Read the ticket's acceptance criteria and justify the simplest suitable approach. Tags are not capability or ownership evidence; an untagged ticket has no curated pattern topic assigned."
    },
    "fieldMix": {
      "version": 1,
      "method": "CURATED_ESTIMATE",
      "notice": "Field percentages are editorial estimates of the ticket's engineering focus. They total 100%; they are not measured time, proficiency scores, or ownership evidence."
    },
    "contentStatus": "PRACTICE_BRIEF",
    "assessmentStatus": "NOT_QUALIFIED",
    "evidenceUse": "NONE",
    "aiPolicy": "AI tools are welcome during implementation. Record assumptions, review the result, and verify its behavior.",
    "notice": "Fictional engineering practice briefs. Starter repositories, fixtures, automated grading, and verified ownership are not included.",
    "outcomeEvidence": "Tests, patches, and runbooks are requested deliverables. They become Outcome Evidence only through a qualified Mission and immutable Evidence IDs.",
    "ownershipEvidence": "Independent adaptation must be observed under a declared verification policy and cite immutable Evidence IDs. Completing a planning ticket establishes no Ownership Evidence."
  },
  "patternTopics": [
    {
      "id": "factory-method",
      "label": "Factory Method",
      "group": "Creational"
    },
    {
      "id": "abstract-factory",
      "label": "Abstract Factory",
      "group": "Creational"
    },
    {
      "id": "builder",
      "label": "Builder",
      "group": "Creational"
    },
    {
      "id": "prototype",
      "label": "Prototype",
      "group": "Creational"
    },
    {
      "id": "singleton",
      "label": "Singleton",
      "group": "Creational"
    },
    {
      "id": "adapter",
      "label": "Adapter",
      "group": "Structural"
    },
    {
      "id": "bridge",
      "label": "Bridge",
      "group": "Structural"
    },
    {
      "id": "composite",
      "label": "Composite",
      "group": "Structural"
    },
    {
      "id": "decorator",
      "label": "Decorator",
      "group": "Structural"
    },
    {
      "id": "facade",
      "label": "Facade",
      "group": "Structural"
    },
    {
      "id": "flyweight",
      "label": "Flyweight",
      "group": "Structural"
    },
    {
      "id": "proxy",
      "label": "Proxy",
      "group": "Structural"
    },
    {
      "id": "chain-of-responsibility",
      "label": "Chain of Responsibility",
      "group": "Behavioral"
    },
    {
      "id": "command",
      "label": "Command",
      "group": "Behavioral"
    },
    {
      "id": "interpreter",
      "label": "Interpreter",
      "group": "Behavioral"
    },
    {
      "id": "iterator",
      "label": "Iterator",
      "group": "Behavioral"
    },
    {
      "id": "mediator",
      "label": "Mediator",
      "group": "Behavioral"
    },
    {
      "id": "memento",
      "label": "Memento",
      "group": "Behavioral"
    },
    {
      "id": "observer",
      "label": "Observer",
      "group": "Behavioral"
    },
    {
      "id": "state",
      "label": "State",
      "group": "Behavioral"
    },
    {
      "id": "strategy",
      "label": "Strategy",
      "group": "Behavioral"
    },
    {
      "id": "template-method",
      "label": "Template Method",
      "group": "Behavioral"
    },
    {
      "id": "visitor",
      "label": "Visitor",
      "group": "Behavioral"
    },
    {
      "id": "ports-and-adapters",
      "label": "Ports and Adapters",
      "group": "Architectural"
    },
    {
      "id": "cqrs",
      "label": "CQRS",
      "group": "Architectural"
    },
    {
      "id": "strangler-fig",
      "label": "Strangler Fig",
      "group": "Architectural"
    },
    {
      "id": "saga",
      "label": "Saga",
      "group": "Distributed and reliability"
    },
    {
      "id": "transactional-outbox",
      "label": "Transactional Outbox",
      "group": "Distributed and reliability"
    },
    {
      "id": "circuit-breaker",
      "label": "Circuit Breaker",
      "group": "Distributed and reliability"
    },
    {
      "id": "bulkhead",
      "label": "Bulkhead",
      "group": "Distributed and reliability"
    }
  ],
  "projects": [
    {
      "id": "caa606e0-b31e-4e75-a62f-6c4f294f1a93",
      "key": "ROLL",
      "title": "Make a small service release recoverable",
      "field": "Platform engineering",
      "summary": "Build a release workflow that can distinguish a healthy process from a safe application version.",
      "context": "A fictional scheduling service has an API, a worker, and PostgreSQL. Releases use immutable images on two application instances. The team needs compatibility checks, staged traffic, and a rehearsed rollback without introducing a new orchestration platform.",
      "stack": [
        "TypeScript",
        "OCI image metadata",
        "PostgreSQL",
        "CI workflows"
      ],
      "prerequisites": [
        "HTTP health checks",
        "CI pipelines",
        "Database migrations"
      ],
      "developerValue": "Practice release contracts, compatibility windows, measurable canaries, and incident decisions on a modest application topology.",
      "companyValue": "Review whether an engineer can make deployments diagnosable and reversible while identifying when rollback is unsafe.",
      "delivery": "Ten phased issues using a synthetic service and simulated release provider; submit manifests, failure drills, and an operator handoff.",
      "phases": [
        {
          "id": "identity",
          "title": "Know what is running",
          "goal": "Establish artifact identity and useful health signals."
        },
        {
          "id": "safety",
          "title": "Control release risk",
          "goal": "Enforce compatibility, serialization, and staged rollout decisions."
        },
        {
          "id": "recovery",
          "title": "Recover with evidence",
          "goal": "Drain work, diagnose failures, and rehearse rollback."
        }
      ],
      "tickets": [
        {
          "id": "b7a9d0a1-ab9e-46eb-b1e5-26fe700a6709",
          "key": "ROLL-101",
          "title": "Display the exact release identity in diagnostics",
          "type": "TASK",
          "priority": "MEDIUM",
          "difficulty": "FOUNDATIONAL",
          "estimateMinutes": 90,
          "phaseId": "identity",
          "dependsOn": [],
          "scenario": "Two API instances report version latest even though only one received yesterday's build. On call cannot connect a failing request to its deployed artifact.",
          "acceptanceCriteria": [
            "Expose build revision, immutable artifact digest, and deployment ID through an authorized diagnostic endpoint.",
            "Fail validation when a release manifest lacks immutable identity.",
            "Keep build secrets and environment values outside the response."
          ],
          "implementationNotes": [
            "The build injects identity; request parameters cannot override it."
          ],
          "verification": [
            "Read distinct diagnostics from two synthetic release versions.",
            "Reject a manifest containing only a mutable tag and inspect response redaction."
          ],
          "deliverables": [
            "Release manifest schema and diagnostic projection"
          ],
          "rollout": "Add diagnostics before changing deployment routing; remove endpoint exposure without changing artifact identities.",
          "skills": [
            "Artifact provenance",
            "Configuration",
            "Diagnostics"
          ],
          "fieldMix": [
            {
              "field": "Platform engineering",
              "percentage": 70
            },
            {
              "field": "Site reliability",
              "percentage": 30
            }
          ],
          "patterns": []
        },
        {
          "id": "f402689e-6dd3-47b2-aefc-de7d55a0d892",
          "key": "ROLL-102",
          "title": "Separate liveness from database readiness",
          "type": "BUG",
          "priority": "HIGH",
          "difficulty": "FOUNDATIONAL",
          "estimateMinutes": 120,
          "phaseId": "identity",
          "dependsOn": [],
          "scenario": "A brief database outage makes the process liveness endpoint fail. The restart policy kills every API instance and turns a recoverable connection issue into a restart loop.",
          "acceptanceCriteria": [
            "Liveness reports whether the process can serve its own health handler.",
            "Readiness fails when required database operations cannot complete within a bounded timeout.",
            "Dependency errors return a stable diagnostic code without connection strings."
          ],
          "implementationNotes": [
            "A readiness probe must not create user records or run migrations."
          ],
          "verification": [
            "Assert both probes succeed with healthy synthetic dependencies.",
            "Disable the database and verify readiness fails while liveness remains successful."
          ],
          "deliverables": [
            "Separate health routes and dependency-outage reproduction"
          ],
          "rollout": "Switch traffic readiness first, then restart-policy probes; restore prior routing if probe semantics are misconfigured.",
          "skills": [
            "Health checks",
            "Dependency failures",
            "Operational contracts"
          ],
          "fieldMix": [
            {
              "field": "Site reliability",
              "percentage": 60
            },
            {
              "field": "Platform engineering",
              "percentage": 40
            }
          ],
          "patterns": []
        },
        {
          "id": "d87c1362-bc0a-447e-bcfb-cd0f853709e1",
          "key": "ROLL-103",
          "title": "Refuse deploys with incomplete runtime configuration",
          "type": "TASK",
          "priority": "HIGH",
          "difficulty": "INTERMEDIATE",
          "estimateMinutes": 150,
          "phaseId": "identity",
          "dependsOn": [
            "ROLL-101"
          ],
          "scenario": "The new worker image needs STORAGE_REGION, but its environment is missing the setting. The rollout reports success while every document job fails on first use.",
          "acceptanceCriteria": [
            "Validate required settings and allowed combinations before readiness succeeds.",
            "Produce setting names and reason codes without printing values.",
            "Validate API and worker manifests against their own declared configuration versions."
          ],
          "implementationNotes": [
            "Use dummy values in fixtures; configuration validation cannot contact production services."
          ],
          "verification": [
            "Validate complete API and worker manifests.",
            "Reject missing storage region and incompatible settings while checking log redaction."
          ],
          "deliverables": [
            "Configuration preflight and role-specific fixtures"
          ],
          "rollout": "Run preflight as an advisory CI step, then block invalid synthetic release manifests.",
          "skills": [
            "Typed configuration",
            "Fail-closed startup",
            "Secret redaction"
          ],
          "fieldMix": [
            {
              "field": "Platform engineering",
              "percentage": 80
            },
            {
              "field": "Security",
              "percentage": 20
            }
          ],
          "patterns": []
        },
        {
          "id": "0d38a80a-e6f2-4e7c-94a5-08c4e7d06a3d",
          "key": "ROLL-104",
          "title": "Keep old API instances working during a column rename",
          "type": "TASK",
          "priority": "HIGH",
          "difficulty": "ADVANCED",
          "estimateMinutes": 240,
          "phaseId": "safety",
          "dependsOn": [
            "ROLL-103"
          ],
          "scenario": "A migration renames booking.start to booking.starts_at before old API instances finish draining. Half the requests fail until every instance updates.",
          "acceptanceCriteria": [
            "Define expand, compatible application rollout, backfill, and contract stages.",
            "Prove old and new application versions work during the supported overlap.",
            "Block destructive cleanup while the old reader version remains active."
          ],
          "implementationNotes": [
            "Include rollback compatibility explicitly; a reverse rename alone is not a release strategy."
          ],
          "verification": [
            "Run mixed-version synthetic requests through the expanded schema.",
            "Attempt cleanup with an old instance present and assert the gate blocks."
          ],
          "deliverables": [
            "Versioned migration plan and mixed-version compatibility checks"
          ],
          "rollout": "Apply only expansion first; rollback application traffic before the contract stage if errors appear.",
          "skills": [
            "Expand-contract migrations",
            "Compatibility",
            "Release sequencing"
          ],
          "fieldMix": [
            {
              "field": "Database engineering",
              "percentage": 60
            },
            {
              "field": "Platform engineering",
              "percentage": 40
            }
          ],
          "patterns": []
        },
        {
          "id": "d59ab3d9-f718-44d3-8b6b-fc7de94307d2",
          "key": "ROLL-105",
          "title": "Prevent two release jobs from overwriting the same environment",
          "type": "BUG",
          "priority": "HIGH",
          "difficulty": "ADVANCED",
          "estimateMinutes": 180,
          "phaseId": "safety",
          "dependsOn": [
            "ROLL-101",
            "ROLL-103"
          ],
          "scenario": "Two commits deploy simultaneously. The older job finishes last and marks its artifact current after the newer release already passed validation.",
          "acceptanceCriteria": [
            "Serialize mutations per environment with a bounded renewable lease.",
            "Reject state updates from expired or superseded lease holders.",
            "Record the winning release identity and every rejected stale update."
          ],
          "implementationNotes": [
            "A process-local mutex cannot coordinate independent CI jobs."
          ],
          "verification": [
            "Race two simulated releases and inspect one current manifest.",
            "Expire a lease, acquire a successor, and prove the old holder cannot publish."
          ],
          "deliverables": [
            "Release lease protocol and stale-writer regression"
          ],
          "rollout": "Enable serialization on the test environment; disable dispatch while investigating lease failures.",
          "skills": [
            "Distributed leases",
            "Fencing",
            "CI concurrency"
          ],
          "fieldMix": [
            {
              "field": "Platform engineering",
              "percentage": 50
            },
            {
              "field": "Distributed systems",
              "percentage": 50
            }
          ],
          "patterns": []
        },
        {
          "id": "f07c604e-e325-417b-a5ba-e9a518c59c1e",
          "key": "ROLL-106",
          "title": "Base canary decisions on enough comparable requests",
          "type": "STORY",
          "priority": "HIGH",
          "difficulty": "EXPERT",
          "estimateMinutes": 300,
          "phaseId": "safety",
          "dependsOn": [
            "ROLL-102",
            "ROLL-104",
            "ROLL-105"
          ],
          "scenario": "A release automatically promotes after five error-free canary requests while the stable version serves thousands. Low traffic makes an untested version look healthy.",
          "acceptanceCriteria": [
            "Require a configured minimum request count and observation window before promotion.",
            "Compare matching route classes with error-rate and latency budgets declared in the fixture.",
            "Return HOLD for insufficient traffic and ABORT for breached safety thresholds."
          ],
          "implementationNotes": [
            "Use bounded route labels; a percentage alone cannot justify a decision without sample counts."
          ],
          "verification": [
            "Promote a synthetic canary with adequate comparable traffic.",
            "Exercise sparse traffic, a route-mix shift, and rising errors; inspect HOLD or ABORT reasons."
          ],
          "deliverables": [
            "Canary decision function, fixture traces, and decision report"
          ],
          "rollout": "Run decisions in observe mode against simulated traffic before allowing the simulated provider to advance stages.",
          "skills": [
            "Release analysis",
            "Measurement design",
            "Decision systems",
            "Observability"
          ],
          "fieldMix": [
            {
              "field": "Site reliability",
              "percentage": 40
            },
            {
              "field": "Platform engineering",
              "percentage": 40
            },
            {
              "field": "Performance engineering",
              "percentage": 20
            }
          ],
          "patterns": []
        },
        {
          "id": "46906410-3c14-47cd-b9c4-7e480b6c75d4",
          "key": "ROLL-107",
          "title": "Drain long requests before retiring an API instance",
          "type": "BUG",
          "priority": "HIGH",
          "difficulty": "INTERMEDIATE",
          "estimateMinutes": 150,
          "phaseId": "recovery",
          "dependsOn": [
            "ROLL-102"
          ],
          "scenario": "During release, an instance exits halfway through a report download. The load balancer keeps sending new requests during its shutdown grace period.",
          "acceptanceCriteria": [
            "Mark the instance unready before starting its bounded drain period.",
            "Allow existing requests to complete until the documented deadline.",
            "Close remaining connections and report forced terminations at deadline without hanging shutdown."
          ],
          "implementationNotes": [
            "Do not count idle keep-alive connections as unfinished business requests indefinitely."
          ],
          "verification": [
            "Start a long synthetic request, initiate shutdown, and observe completion.",
            "Keep a request stuck beyond the deadline and confirm bounded exit and termination count."
          ],
          "deliverables": [
            "Graceful shutdown behavior and request-drain reproduction"
          ],
          "rollout": "Exercise draining on one test instance; restore the previous grace settings if traffic does not stop arriving.",
          "skills": [
            "Graceful shutdown",
            "HTTP lifecycle",
            "Timeouts"
          ],
          "fieldMix": [
            {
              "field": "Platform engineering",
              "percentage": 50
            },
            {
              "field": "Networking",
              "percentage": 30
            },
            {
              "field": "Site reliability",
              "percentage": 20
            }
          ],
          "patterns": []
        },
        {
          "id": "2b37920d-080d-40a8-aeb5-b1d5e0bab23c",
          "key": "ROLL-108",
          "title": "Do not roll back a worker into an unreadable job format",
          "type": "TASK",
          "priority": "HIGH",
          "difficulty": "EXPERT",
          "estimateMinutes": 300,
          "phaseId": "recovery",
          "dependsOn": [
            "ROLL-104",
            "ROLL-105"
          ],
          "scenario": "Worker v8 enqueues a new payload shape. Rolling back to v7 starts a retry storm because v7 cannot parse jobs already accepted by v8.",
          "acceptanceCriteria": [
            "Version job envelopes and declare the worker versions able to consume each version.",
            "Gate rollback when queued work would become unreadable.",
            "Provide a safe drain or compatibility path that preserves accepted job identities."
          ],
          "implementationNotes": [
            "Do not rewrite historical payloads in place or discard incompatible jobs to make rollback green."
          ],
          "verification": [
            "Process old and new fixture envelopes with the declared compatible worker.",
            "Attempt an incompatible rollback with queued v8 work and assert a useful blocking reason."
          ],
          "deliverables": [
            "Job compatibility matrix and rollback preflight"
          ],
          "rollout": "Deploy backward readers before new writers; remove old readers only after the compatibility window closes.",
          "skills": [
            "Message evolution",
            "Rollback safety",
            "Queue operations",
            "Compatibility contracts"
          ],
          "fieldMix": [
            {
              "field": "Platform engineering",
              "percentage": 60
            },
            {
              "field": "Distributed systems",
              "percentage": 40
            }
          ],
          "patterns": []
        },
        {
          "id": "43d0beae-b8d1-475e-b862-b98121b28667",
          "key": "ROLL-109",
          "title": "Attach a release marker to bounded operational telemetry",
          "type": "CHORE",
          "priority": "MEDIUM",
          "difficulty": "INTERMEDIATE",
          "estimateMinutes": 120,
          "phaseId": "recovery",
          "dependsOn": [
            "ROLL-101",
            "ROLL-106"
          ],
          "scenario": "An error spike starts near a deploy, but the dashboard has no release event or stable artifact link. Engineers compare screenshots and guess which change was live.",
          "acceptanceCriteria": [
            "Emit a release event with environment, deployment ID, artifact digest, and stage outcome.",
            "Link stage failures to sanitized diagnostic references.",
            "Keep request bodies, secret values, and arbitrary commit messages out of metric labels."
          ],
          "implementationNotes": [
            "Store high-cardinality release details in events; use bounded dimensions for metrics."
          ],
          "verification": [
            "Trace a simulated canary abort from its marker to its release manifest.",
            "Inject secret-like fixture metadata and verify the telemetry projection excludes it."
          ],
          "deliverables": [
            "Release event schema and incident dashboard query"
          ],
          "rollout": "Add markers without changing alert thresholds; disable the new event sink if it delays release decisions.",
          "skills": [
            "Observability",
            "Cardinality",
            "Release diagnostics"
          ],
          "fieldMix": [
            {
              "field": "Site reliability",
              "percentage": 60
            },
            {
              "field": "Platform engineering",
              "percentage": 40
            }
          ],
          "patterns": []
        },
        {
          "id": "462e7886-df26-4e60-891f-ef6f4472ac55",
          "key": "ROLL-110",
          "title": "Rehearse an aborted release and write the operator handoff",
          "type": "TASK",
          "priority": "MEDIUM",
          "difficulty": "INTERMEDIATE",
          "estimateMinutes": 180,
          "phaseId": "recovery",
          "dependsOn": [
            "ROLL-106",
            "ROLL-107",
            "ROLL-108",
            "ROLL-109"
          ],
          "scenario": "The release checklist says rollback tested, but nobody has timed recovery or tried it with an expanded database schema and pending worker jobs.",
          "acceptanceCriteria": [
            "Run one simulated failed canary with pending jobs and expanded schema.",
            "Record detection, abort, drain, and recovery timestamps with observed limitations.",
            "Provide exact preconditions and stop conditions for the documented rollback path."
          ],
          "implementationNotes": [
            "A simulated drill establishes fixture behavior only; label its measured timings accordingly."
          ],
          "verification": [
            "Recover the previous compatible release and reconcile accepted jobs.",
            "Include an incompatible rollback example and prove the checklist tells the operator to stop."
          ],
          "deliverables": [
            "Recorded release drill and operator runbook"
          ],
          "rollout": "Version the runbook with the tested manifests; repeat the bounded drill when compatibility assumptions change.",
          "skills": [
            "Incident drills",
            "Runbooks",
            "Recovery measurement"
          ],
          "fieldMix": [
            {
              "field": "Platform engineering",
              "percentage": 50
            },
            {
              "field": "Site reliability",
              "percentage": 50
            }
          ],
          "patterns": []
        }
      ]
    }
  ]
}
