{
  "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": "0f2b69f0-2ba0-45e4-86a1-735091cab32b",
      "key": "ABOOK",
      "title": "Repair appointment holds and cancellation windows",
      "field": "Backend",
      "summary": "Keep scarce appointment slots consistent through holds, confirmations and cancellation.",
      "context": "A fictional equipment service books maintenance visits. Expiring checkout holds and reschedules occasionally double-book a technician.",
      "stack": [
        "TypeScript",
        "PostgreSQL",
        "REST"
      ],
      "prerequisites": [
        "Build synthetic technicians, slots and booking records.",
        "Use an injectable clock and separate clients for concurrency probes."
      ],
      "developerValue": "Practice resource allocation, interval conflicts and durable workflows.",
      "companyValue": "Review scheduling correctness and recovery before exposing scarce capacity.",
      "delivery": "Ten scoped tickets across three phases. Build a synthetic local service or select a ticket after recreating its prerequisites; estimates exclude setup.",
      "phases": [
        {
          "id": "slots",
          "title": "Define availability",
          "goal": "Make time and availability rules unambiguous."
        },
        {
          "id": "booking",
          "title": "Protect reservations",
          "goal": "Handle simultaneous actions and durable transitions."
        },
        {
          "id": "operations",
          "title": "Operate the calendar",
          "goal": "Reconcile state and explain cancellations."
        }
      ],
      "tickets": [
        {
          "id": "daa5d0cd-c14a-4ac7-97bd-c16ae291cd6e",
          "key": "ABOOK-101",
          "title": "Normalize maintenance-slot requests to explicit UTC intervals",
          "type": "TASK",
          "priority": "MEDIUM",
          "difficulty": "FOUNDATIONAL",
          "estimateMinutes": 75,
          "phaseId": "slots",
          "dependsOn": [],
          "scenario": "A technician's daylight-saving transition produces two appointments labelled 01:30 with no offset in the booking request.",
          "acceptanceCriteria": [
            "Require start, end and explicit offset.",
            "Reject end-before-start and zero-duration intervals.",
            "Persist UTC while returning the requested display zone separately."
          ],
          "implementationNotes": [
            "Create synthetic ambiguous-hour cases rather than reading real calendars."
          ],
          "verification": [
            "Round-trip two different offsets for the repeated hour.",
            "Reject an offset-free repeated-hour request."
          ],
          "deliverables": [
            "Slot input contract and DST cases"
          ],
          "rollout": "Add validation before new slot creation; retain original timestamps for existing rows.",
          "skills": [
            "Time zones",
            "Validation"
          ],
          "fieldMix": [
            {
              "field": "Backend",
              "percentage": 70
            },
            {
              "field": "API design",
              "percentage": 30
            }
          ],
          "patterns": []
        },
        {
          "id": "7ef0824d-ede6-4b1d-95b1-b50ea07c57ff",
          "key": "ABOOK-102",
          "title": "Model overlapping technician availability as half-open intervals",
          "type": "TASK",
          "priority": "MEDIUM",
          "difficulty": "INTERMEDIATE",
          "estimateMinutes": 150,
          "phaseId": "slots",
          "dependsOn": [
            "ABOOK-101"
          ],
          "scenario": "Adjacent visits are rejected as overlapping, while a visit completely containing another can pass a naive endpoint check.",
          "acceptanceCriteria": [
            "Adjacent end and start boundaries do not conflict.",
            "Contained and partially overlapping intervals conflict.",
            "Conflict checks include the technician's organization."
          ],
          "implementationNotes": [
            "Document the half-open interval convention in the query."
          ],
          "verification": [
            "Check adjacent, contained and identical intervals.",
            "Try the same technician identifier in another organization and deny access."
          ],
          "deliverables": [
            "Overlap query and interval matrix"
          ],
          "rollout": "Shadow-check overlap decisions; restore the old route if new conflicts need review.",
          "skills": [
            "SQL",
            "Interval reasoning"
          ],
          "fieldMix": [
            {
              "field": "Backend",
              "percentage": 50
            },
            {
              "field": "Database engineering",
              "percentage": 50
            }
          ],
          "patterns": []
        },
        {
          "id": "5358fce8-2a7b-482f-b4f4-01853c15ba7a",
          "key": "ABOOK-103",
          "title": "Return bookable slots in stable bounded pages",
          "type": "STORY",
          "priority": "MEDIUM",
          "difficulty": "FOUNDATIONAL",
          "estimateMinutes": 90,
          "phaseId": "slots",
          "dependsOn": [
            "ABOOK-101",
            "ABOOK-102"
          ],
          "scenario": "A busy service desk loads every future slot; several slots disappear from the second page when a new slot is inserted.",
          "acceptanceCriteria": [
            "Order by start instant and opaque slot ID.",
            "Use a cursor bound to technician and date window.",
            "Enforce a maximum page size and bounded date range."
          ],
          "implementationNotes": [
            "Do not expose unassigned technicians outside the organization."
          ],
          "verification": [
            "Insert a slot between pages and inspect stable cursor progression.",
            "Reject an altered cursor scope and excessive range."
          ],
          "deliverables": [
            "Availability page contract and cursor tests"
          ],
          "rollout": "Introduce cursor pagination alongside the old bounded endpoint; roll back its link.",
          "skills": [
            "Pagination",
            "API contracts"
          ],
          "fieldMix": [
            {
              "field": "API design",
              "percentage": 60
            },
            {
              "field": "Backend",
              "percentage": 40
            }
          ],
          "patterns": []
        },
        {
          "id": "dce90584-399b-48ac-a05c-7174e8e4dd42",
          "key": "ABOOK-104",
          "title": "Reserve one active hold for a contested maintenance slot",
          "type": "STORY",
          "priority": "HIGH",
          "difficulty": "ADVANCED",
          "estimateMinutes": 240,
          "phaseId": "booking",
          "dependsOn": [
            "ABOOK-102"
          ],
          "scenario": "Two customers reach checkout together and each receives a valid hold token for the same appointment.",
          "acceptanceCriteria": [
            "One active hold wins for a slot under concurrent requests.",
            "The loser gets a conflict without another customer's details.",
            "Hold creation and its expiry time commit atomically."
          ],
          "implementationNotes": [
            "Use a database invariant as the final concurrency guard."
          ],
          "verification": [
            "Start two clients at a barrier and assert one live hold.",
            "Force commit failure and assert no usable token escapes."
          ],
          "deliverables": [
            "Hold command and concurrent reservation test"
          ],
          "rollout": "Enable holds on synthetic slots; pause new holds if invariant monitoring detects duplicates.",
          "skills": [
            "Concurrency",
            "Database constraints"
          ],
          "fieldMix": [
            {
              "field": "Database engineering",
              "percentage": 60
            },
            {
              "field": "Backend",
              "percentage": 40
            }
          ],
          "patterns": []
        },
        {
          "id": "eb82de4e-1230-4e28-be4b-6257962c011f",
          "key": "ABOOK-105",
          "title": "Expire holds without cancelling a booking confirmed at the boundary",
          "type": "BUG",
          "priority": "HIGH",
          "difficulty": "EXPERT",
          "estimateMinutes": 360,
          "phaseId": "booking",
          "dependsOn": [
            "ABOOK-104"
          ],
          "scenario": "An expiry worker reads an old hold while checkout confirms it; the worker then frees a slot already sold.",
          "acceptanceCriteria": [
            "Confirm and expire use guarded state transitions.",
            "Exactly one terminal outcome wins at the expiry boundary.",
            "A stale expiry job cannot alter a confirmed booking."
          ],
          "implementationNotes": [
            "Specify whether confirmation at the exact deadline is rejected."
          ],
          "verification": [
            "Race confirmation and expiry with a controlled clock.",
            "Retry the stale expiry after confirmation and retain the booking."
          ],
          "deliverables": [
            "Hold state machine and boundary race reproduction"
          ],
          "rollout": "Canary the guarded worker; stop expiry consumption while preserving stored deadlines.",
          "skills": [
            "State machines",
            "Concurrency"
          ],
          "fieldMix": [
            {
              "field": "Backend",
              "percentage": 60
            },
            {
              "field": "Database engineering",
              "percentage": 40
            }
          ],
          "patterns": []
        },
        {
          "id": "a6470b32-f390-443c-b148-1e3b7185b67b",
          "key": "ABOOK-106",
          "title": "Reschedule a visit without releasing its old slot prematurely",
          "type": "STORY",
          "priority": "MEDIUM",
          "difficulty": "ADVANCED",
          "estimateMinutes": 240,
          "phaseId": "booking",
          "dependsOn": [
            "ABOOK-104",
            "ABOOK-105"
          ],
          "scenario": "A reschedule releases the old appointment before reserving the new one, leaving customers unbooked if the target is taken.",
          "acceptanceCriteria": [
            "Reserve the target and release the source atomically.",
            "Retain the original appointment on target conflict.",
            "A retried successful command returns the same replacement."
          ],
          "implementationNotes": [
            "Keep both slot locks in a documented stable order."
          ],
          "verification": [
            "Move a visit and inspect one confirmed appointment.",
            "Race for the target and verify the losing reschedule keeps its source."
          ],
          "deliverables": [
            "Reschedule command and transaction tests"
          ],
          "rollout": "Enable for synthetic bookings; disable rescheduling while ordinary reads continue.",
          "skills": [
            "Transactions",
            "Idempotency"
          ],
          "fieldMix": [
            {
              "field": "Database engineering",
              "percentage": 60
            },
            {
              "field": "Backend",
              "percentage": 40
            }
          ],
          "patterns": []
        },
        {
          "id": "ee2bec23-cee2-4128-bf69-84682be53eef",
          "key": "ABOOK-107",
          "title": "Calculate the cancellation window from the booked service policy",
          "type": "TASK",
          "priority": "MEDIUM",
          "difficulty": "INTERMEDIATE",
          "estimateMinutes": 150,
          "phaseId": "booking",
          "dependsOn": [
            "ABOOK-105"
          ],
          "scenario": "A policy update changes the cancellation deadline for appointments sold under yesterday's terms.",
          "acceptanceCriteria": [
            "Booking retains the applied policy version.",
            "Deadline calculation uses that frozen policy and UTC start.",
            "Cancellation returns the policy version and eligibility reason."
          ],
          "implementationNotes": [
            "This exercise models eligibility only, without charging money."
          ],
          "verification": [
            "Cancel bookings created under two policy versions.",
            "Change the current policy and verify old booking deadlines remain fixed."
          ],
          "deliverables": [
            "Versioned cancellation calculator"
          ],
          "rollout": "Publish a new policy version for new bookings; keep historical policy references intact.",
          "skills": [
            "Versioning",
            "Business rules"
          ],
          "fieldMix": [
            {
              "field": "Backend",
              "percentage": 100
            }
          ],
          "patterns": []
        },
        {
          "id": "83587c7d-baa7-46cf-93cd-6d0b4a361f15",
          "key": "ABOOK-108",
          "title": "Detect orphan holds without changing confirmed appointments",
          "type": "CHORE",
          "priority": "MEDIUM",
          "difficulty": "ADVANCED",
          "estimateMinutes": 210,
          "phaseId": "operations",
          "dependsOn": [
            "ABOOK-105",
            "ABOOK-106"
          ],
          "scenario": "A simulated outage leaves holds whose expiry jobs were never dispatched; operations needs a bounded reconciliation command.",
          "acceptanceCriteria": [
            "Scan expired held rows with cursor checkpoints.",
            "Release only rows still held at the checked version.",
            "Report confirmed rows skipped after concurrent change."
          ],
          "implementationNotes": [
            "Use dry-run by default and limit each batch."
          ],
          "verification": [
            "Reconcile an expired orphan and resume from a checkpoint.",
            "Confirm between scan and update and verify the booking survives."
          ],
          "deliverables": [
            "Orphan-hold reconciler and race check"
          ],
          "rollout": "Dry-run a bounded window; stop reconciliation and retain checkpoints if unexpected skips grow.",
          "skills": [
            "Reconciliation",
            "Optimistic concurrency"
          ],
          "fieldMix": [
            {
              "field": "Backend",
              "percentage": 50
            },
            {
              "field": "Database engineering",
              "percentage": 30
            },
            {
              "field": "Site reliability",
              "percentage": 20
            }
          ],
          "patterns": []
        },
        {
          "id": "6cd93527-9909-4c7a-97e6-6684a732ba98",
          "key": "ABOOK-109",
          "title": "Hide customer details in scheduling conflict responses",
          "type": "BUG",
          "priority": "HIGH",
          "difficulty": "FOUNDATIONAL",
          "estimateMinutes": 75,
          "phaseId": "operations",
          "dependsOn": [
            "ABOOK-106",
            "ABOOK-107"
          ],
          "scenario": "A failed reschedule currently returns the target booking object, exposing the name and contact information of its owner.",
          "acceptanceCriteria": [
            "Conflict responses contain only code and requested slot identity.",
            "Internal logs omit customer contact fields.",
            "Successful owners still receive their own booking projection."
          ],
          "implementationNotes": [
            "Use explicit response schemas instead of deleting selected fields."
          ],
          "verification": [
            "Check an owner's successful reschedule response.",
            "Force a conflict and assert another customer's fields appear nowhere in response or log."
          ],
          "deliverables": [
            "Sanitized conflict schema and disclosure regression"
          ],
          "rollout": "Deploy response shaping first; revert only with the same restricted projection.",
          "skills": [
            "Privacy",
            "Response schemas"
          ],
          "fieldMix": [
            {
              "field": "Privacy engineering",
              "percentage": 50
            },
            {
              "field": "Backend",
              "percentage": 30
            },
            {
              "field": "API design",
              "percentage": 20
            }
          ],
          "patterns": []
        },
        {
          "id": "2460e8d0-0a03-4a7a-b747-3a1e23fa1e1e",
          "key": "ABOOK-110",
          "title": "Prove booking recovery after a lost confirmation response",
          "type": "TASK",
          "priority": "HIGH",
          "difficulty": "EXPERT",
          "estimateMinutes": 300,
          "phaseId": "operations",
          "dependsOn": [
            "ABOOK-105",
            "ABOOK-108",
            "ABOOK-109"
          ],
          "scenario": "Checkout commits successfully, then the connection closes. A customer retries while the expiry worker is also running.",
          "acceptanceCriteria": [
            "Document persisted state at each interruption point.",
            "A stable command key resolves the committed confirmation.",
            "No retry creates a second booking or frees its slot."
          ],
          "implementationNotes": [
            "Build a deterministic fault-injection harness using synthetic visits."
          ],
          "verification": [
            "Drop the response after commit and retry to the same booking.",
            "Drop before commit, run expiry, and verify the declared expired outcome."
          ],
          "deliverables": [
            "Recovery trace and executable interruption probe"
          ],
          "rollout": "Run the drill before enabling checkout; fall back to read-only booking lookup during incidents.",
          "skills": [
            "Fault injection",
            "Recovery"
          ],
          "fieldMix": [
            {
              "field": "Quality engineering",
              "percentage": 40
            },
            {
              "field": "Backend",
              "percentage": 30
            },
            {
              "field": "Distributed systems",
              "percentage": 30
            }
          ],
          "patterns": []
        }
      ]
    }
  ]
}
