{
  "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": "4cbe8d74-12ed-43d2-9bca-6503851d91a7",
      "key": "QUEUE",
      "title": "Bring document processing back under control",
      "field": "Platform engineering",
      "summary": "Operate an asynchronous document pipeline through retries, poison jobs, worker loss, and tenant bursts.",
      "context": "A fictional internal document portal creates previews through a trusted mock renderer. Large batches crowd out small teams, failed documents retry forever, and operators lack a safe replay command. This exercise never executes uploaded code or real document macros.",
      "stack": [
        "TypeScript",
        "BullMQ",
        "Redis",
        "PostgreSQL",
        "Object storage"
      ],
      "prerequisites": [
        "Queue semantics",
        "Database transactions",
        "Operational metrics"
      ],
      "developerValue": "Practice asynchronous lifecycle control, fair scheduling, bounded retries, and artifact recovery with a deterministic provider.",
      "companyValue": "See how an engineer accounts for accepted work and reduces operational toil without granting operators broad data access.",
      "delivery": "Ten tickets in intake, resilience, and operations phases; use only synthetic document metadata and a trusted deterministic renderer.",
      "phases": [
        {
          "id": "intake",
          "title": "Account for accepted work",
          "goal": "Create traceable jobs with bounded inputs."
        },
        {
          "id": "resilience",
          "title": "Handle failures deliberately",
          "goal": "Control retries, concurrency, cancellation, and worker loss."
        },
        {
          "id": "operations",
          "title": "Make recovery routine",
          "goal": "Expose useful lag signals and safe repair operations."
        }
      ],
      "tickets": [
        {
          "id": "430c0420-821f-4e1a-86a5-38b5c0a1a9e0",
          "key": "QUEUE-101",
          "title": "Expose a document job's current phase and terminal reason",
          "type": "STORY",
          "priority": "MEDIUM",
          "difficulty": "FOUNDATIONAL",
          "estimateMinutes": 90,
          "phaseId": "intake",
          "dependsOn": [],
          "scenario": "The portal shows Processing for both queued and permanently rejected documents. Support cannot tell whether a file is waiting, rendering, or never going to finish.",
          "acceptanceCriteria": [
            "Expose QUEUED, RUNNING, SUCCEEDED, FAILED, and CANCELLED through an allowlisted projection.",
            "Include a stable terminal reason code and last transition time.",
            "Deny jobs owned by another tenant."
          ],
          "implementationNotes": [
            "Only service transition methods may update lifecycle state; logs are not the source of truth."
          ],
          "verification": [
            "Read queued and failed fixture jobs with distinct explanations.",
            "Reject foreign-tenant lookup and ensure renderer payloads are absent."
          ],
          "deliverables": [
            "Job status contract and authorized read endpoint"
          ],
          "rollout": "Switch status reads for synthetic jobs first; retain historical transition records if the view is reverted.",
          "skills": [
            "State projection",
            "Tenant isolation",
            "API design"
          ],
          "fieldMix": [
            {
              "field": "API design",
              "percentage": 40
            },
            {
              "field": "Platform engineering",
              "percentage": 30
            },
            {
              "field": "Backend",
              "percentage": 30
            }
          ],
          "patterns": []
        },
        {
          "id": "371a4f08-25c9-43c8-bac3-e6e1dddbde08",
          "key": "QUEUE-102",
          "title": "Reject oversized document batches before accepting work",
          "type": "TASK",
          "priority": "HIGH",
          "difficulty": "FOUNDATIONAL",
          "estimateMinutes": 90,
          "phaseId": "intake",
          "dependsOn": [],
          "scenario": "A client submits 50,000 document references in one call. Validation exhausts API memory before the queue sees a single job.",
          "acceptanceCriteria": [
            "Enforce a documented request byte limit and a maximum of 100 document references.",
            "Reject duplicate references within the batch with a clear validation reason.",
            "Create no jobs when batch validation fails."
          ],
          "implementationNotes": [
            "Validate metadata only; the API must not download or render document contents."
          ],
          "verification": [
            "Accept a valid 100-reference synthetic batch.",
            "Reject 101 references, excessive bytes, and duplicate references without partial jobs."
          ],
          "deliverables": [
            "Bounded batch contract and boundary cases"
          ],
          "rollout": "Publish limits before enforcing them on the test client; rollback client batching rather than raising limits without measurement.",
          "skills": [
            "Input limits",
            "Resource bounds",
            "Contract testing"
          ],
          "fieldMix": [
            {
              "field": "Platform engineering",
              "percentage": 50
            },
            {
              "field": "Performance engineering",
              "percentage": 30
            },
            {
              "field": "API design",
              "percentage": 20
            }
          ],
          "patterns": []
        },
        {
          "id": "fa3b1d74-b9f5-4d75-8357-4d4523e8539f",
          "key": "QUEUE-103",
          "title": "Commit job acceptance and dispatch intent together",
          "type": "BUG",
          "priority": "HIGH",
          "difficulty": "ADVANCED",
          "estimateMinutes": 210,
          "phaseId": "intake",
          "dependsOn": [
            "QUEUE-101",
            "QUEUE-102"
          ],
          "scenario": "The portal returns 202 after storing a job, then loses Redis connectivity before enqueueing it. The job stays QUEUED forever with no delivery attempt.",
          "acceptanceCriteria": [
            "Commit accepted job records and durable dispatch intents atomically.",
            "Dispatch retries use deterministic job identities.",
            "A failed database transaction cannot return accepted status."
          ],
          "implementationNotes": [
            "Queue messages contain identifiers and bounded metadata, not document bytes."
          ],
          "verification": [
            "Lose Redis after acceptance and recover every job when dispatch resumes.",
            "Fail the database commit and assert neither job nor dispatch intent exists."
          ],
          "deliverables": [
            "Outbox-backed acceptance and recovery reproduction"
          ],
          "rollout": "Drain synthetic pending intents through the new dispatcher; pause dispatch without deleting accepted work to rollback.",
          "skills": [
            "Transactional outbox",
            "Durable acceptance",
            "Idempotency"
          ],
          "fieldMix": [
            {
              "field": "Distributed systems",
              "percentage": 40
            },
            {
              "field": "Database engineering",
              "percentage": 30
            },
            {
              "field": "Platform engineering",
              "percentage": 30
            }
          ],
          "patterns": [
            {
              "pattern": "transactional-outbox",
              "activity": "APPLY",
              "focus": "Commit acceptance and dispatch intent in one transaction, then demonstrate recovery after the queue is unavailable or the process stops before dispatch."
            }
          ]
        },
        {
          "id": "e3cb7c2c-1160-4aed-9af8-3df3c25fb6d1",
          "key": "QUEUE-104",
          "title": "Stop retrying unsupported document formats",
          "type": "BUG",
          "priority": "HIGH",
          "difficulty": "INTERMEDIATE",
          "estimateMinutes": 150,
          "phaseId": "resilience",
          "dependsOn": [
            "QUEUE-103"
          ],
          "scenario": "The trusted mock renderer returns UNSUPPORTED_FORMAT for a fixture file. The worker retries it every minute, consuming the same capacity as a temporary storage timeout.",
          "acceptanceCriteria": [
            "Classify unsupported format as terminal and storage timeout as retryable.",
            "Apply a bounded attempt count and backoff policy to retryable failures.",
            "Record each attempt and the final exhaustion reason without replacing earlier failures."
          ],
          "implementationNotes": [
            "Unknown provider errors need an explicit conservative policy; do not retry forever."
          ],
          "verification": [
            "Retry a transient failure that succeeds on its third attempt.",
            "Verify unsupported format runs once and persistent timeout reaches a bounded terminal state."
          ],
          "deliverables": [
            "Failure classification table and retry policy"
          ],
          "rollout": "Apply new classification to future attempts; stop scheduling exhausted jobs without erasing their attempt history.",
          "skills": [
            "Retry policy",
            "Error taxonomy",
            "Failure budgets"
          ],
          "fieldMix": [
            {
              "field": "Platform engineering",
              "percentage": 60
            },
            {
              "field": "Site reliability",
              "percentage": 40
            }
          ],
          "patterns": []
        },
        {
          "id": "ef2da24e-e945-4621-beb0-1d580d78bb6f",
          "key": "QUEUE-105",
          "title": "Keep one team's bulk import from occupying every worker",
          "type": "STORY",
          "priority": "HIGH",
          "difficulty": "ADVANCED",
          "estimateMinutes": 240,
          "phaseId": "resilience",
          "dependsOn": [
            "QUEUE-103",
            "QUEUE-104"
          ],
          "scenario": "A synthetic tenant uploads 10,000 documents. A second tenant's single preview waits behind the entire batch although the renderer has spare concurrency slots between completions.",
          "acceptanceCriteria": [
            "Enforce configured global and per-tenant active-job limits.",
            "Allow eligible tenants to make progress while a bulk tenant has backlog.",
            "Release capacity after success, terminal failure, cancellation, or expired execution lease."
          ],
          "implementationNotes": [
            "Do not create an unbounded queue or metric family per tenant; explain the fairness policy."
          ],
          "verification": [
            "Run one bulk tenant and two small tenants and measure their wait times.",
            "Crash a worker while holding capacity and prove another eligible tenant eventually progresses."
          ],
          "deliverables": [
            "Fair dispatch policy and controlled-load report"
          ],
          "rollout": "Start with conservative synthetic limits; disable new intake and drain leases if accounting diverges.",
          "skills": [
            "Fair scheduling",
            "Concurrency limits",
            "Capacity accounting"
          ],
          "fieldMix": [
            {
              "field": "Platform engineering",
              "percentage": 50
            },
            {
              "field": "Performance engineering",
              "percentage": 30
            },
            {
              "field": "Distributed systems",
              "percentage": 20
            }
          ],
          "patterns": []
        },
        {
          "id": "04530a6b-1191-4a5e-b627-b75324118e3f",
          "key": "QUEUE-106",
          "title": "Fence a late worker after its rendering lease expires",
          "type": "BUG",
          "priority": "HIGH",
          "difficulty": "EXPERT",
          "estimateMinutes": 300,
          "phaseId": "resilience",
          "dependsOn": [
            "QUEUE-104",
            "QUEUE-105"
          ],
          "scenario": "Worker A pauses long enough to lose its lease. Worker B completes the same preview, then A resumes and overwrites B's artifact pointer with stale output.",
          "acceptanceCriteria": [
            "Associate each execution attempt with a monotonic fencing identity.",
            "Accept completion only from the current authorized lease holder.",
            "Keep rejected late completions observable and prevent them from changing terminal job state."
          ],
          "implementationNotes": [
            "Lease expiration alone does not stop a process; the persistence boundary must reject stale writes."
          ],
          "verification": [
            "Expire A, complete through B, then submit A's completion and inspect unchanged output.",
            "Replay B's completion and assert one terminal transition and artifact reference."
          ],
          "deliverables": [
            "Fenced completion operation and paused-worker reproduction"
          ],
          "rollout": "Introduce fencing before extending concurrency; rollback dispatch while retaining fencing checks on completions.",
          "skills": [
            "Fencing tokens",
            "Worker leases",
            "Concurrency",
            "Artifact consistency"
          ],
          "fieldMix": [
            {
              "field": "Distributed systems",
              "percentage": 60
            },
            {
              "field": "Platform engineering",
              "percentage": 40
            }
          ],
          "patterns": []
        },
        {
          "id": "6502461a-e612-4d91-9fa6-cf8134370266",
          "key": "QUEUE-107",
          "title": "Cancel queued work without racing a completed preview",
          "type": "STORY",
          "priority": "MEDIUM",
          "difficulty": "ADVANCED",
          "estimateMinutes": 180,
          "phaseId": "resilience",
          "dependsOn": [
            "QUEUE-106"
          ],
          "scenario": "A user cancels a batch just as one preview finishes. The portal reports Cancelled while retaining an accessible success artifact, and a retry renders it again.",
          "acceptanceCriteria": [
            "Make cancellation an authorized state transition with documented running-job semantics.",
            "Resolve cancellation and completion races to one terminal result.",
            "Prevent cancelled jobs from being newly dispatched or retried."
          ],
          "implementationNotes": [
            "For the mock renderer, cancellation can be cooperative; disclose work that cannot stop immediately."
          ],
          "verification": [
            "Cancel queued work and prove the renderer is never called.",
            "Race running completion and cancellation, then replay both commands and inspect stable state."
          ],
          "deliverables": [
            "Cancellation contract and race regression"
          ],
          "rollout": "Enable queued cancellation first, then running cancellation after the race cases pass; retain terminal records on rollback.",
          "skills": [
            "Cancellation",
            "State transitions",
            "Race handling"
          ],
          "fieldMix": [
            {
              "field": "Backend",
              "percentage": 50
            },
            {
              "field": "Platform engineering",
              "percentage": 30
            },
            {
              "field": "Distributed systems",
              "percentage": 20
            }
          ],
          "patterns": []
        },
        {
          "id": "50c5f8de-f4b3-4723-b536-69305c0b8e70",
          "key": "QUEUE-108",
          "title": "Measure oldest runnable work instead of queue size alone",
          "type": "CHORE",
          "priority": "MEDIUM",
          "difficulty": "INTERMEDIATE",
          "estimateMinutes": 120,
          "phaseId": "operations",
          "dependsOn": [
            "QUEUE-104",
            "QUEUE-105"
          ],
          "scenario": "The queue contains only ten jobs, but the oldest eligible preview has waited 40 minutes. A queue-depth alert never fires, while scheduled retries inflate another dashboard.",
          "acceptanceCriteria": [
            "Measure oldest eligible-job age separately from delayed retries and running age.",
            "Expose attempt exhaustion and stale-lease counts with bounded labels.",
            "Alert when eligible wait exceeds the fixture's ten-minute budget for two observations."
          ],
          "implementationNotes": [
            "Exclude document IDs and tenant IDs from metric label sets."
          ],
          "verification": [
            "Advance a controlled clock and trigger runnable-age paging.",
            "Keep a future retry delayed and verify it does not inflate eligible wait."
          ],
          "deliverables": [
            "Queue age metrics and diagnosis-oriented alert"
          ],
          "rollout": "Compare alerts with the synthetic workload trace in report-only mode before paging.",
          "skills": [
            "Queue observability",
            "Metric semantics",
            "Alert design"
          ],
          "fieldMix": [
            {
              "field": "Site reliability",
              "percentage": 70
            },
            {
              "field": "Platform engineering",
              "percentage": 30
            }
          ],
          "patterns": []
        },
        {
          "id": "c9a69594-abdc-4f09-8121-2b43536a302a",
          "key": "QUEUE-109",
          "title": "Replay a failed preview through an audited repair command",
          "type": "TASK",
          "priority": "HIGH",
          "difficulty": "INTERMEDIATE",
          "estimateMinutes": 150,
          "phaseId": "operations",
          "dependsOn": [
            "QUEUE-104",
            "QUEUE-106"
          ],
          "scenario": "Operators repair failed jobs by deleting Redis keys. That loses failure history and can replay work for the wrong tenant when a copied ID is mistaken.",
          "acceptanceCriteria": [
            "Allow an authorized operator to create a linked repair attempt for a terminal failure.",
            "Require tenant scope, expected job revision, and a reason.",
            "Preserve original failure history and make duplicate repair requests idempotent."
          ],
          "implementationNotes": [
            "Do not reopen the failed record in place or expose a general queue-management console."
          ],
          "verification": [
            "Repair one terminal fixture failure and follow the linked attempts.",
            "Reject a foreign tenant, stale revision, and repair of a successful job."
          ],
          "deliverables": [
            "Scoped repair command and audit projection"
          ],
          "rollout": "Grant repair permission to a synthetic operator role; revoke command access while retaining read-only audit history.",
          "skills": [
            "Operational APIs",
            "Audit trails",
            "Least privilege"
          ],
          "fieldMix": [
            {
              "field": "Platform engineering",
              "percentage": 40
            },
            {
              "field": "Backend",
              "percentage": 30
            },
            {
              "field": "Security",
              "percentage": 30
            }
          ],
          "patterns": []
        },
        {
          "id": "ca2316a5-d93a-4bd0-849b-ad157c8a0d63",
          "key": "QUEUE-110",
          "title": "Collect orphaned preview artifacts without deleting live output",
          "type": "TASK",
          "priority": "MEDIUM",
          "difficulty": "ADVANCED",
          "estimateMinutes": 210,
          "phaseId": "operations",
          "dependsOn": [
            "QUEUE-106",
            "QUEUE-107",
            "QUEUE-109"
          ],
          "scenario": "A worker writes an artifact then loses its lease before committing the pointer. Storage grows with orphaned previews, but a naive age-based cleanup can delete an output still being committed.",
          "acceptanceCriteria": [
            "Separate temporary attempt artifacts from committed output references.",
            "Delete only unreferenced artifacts beyond a documented grace period with no active lease.",
            "Make cleanup resumable and record bounded deletion outcomes."
          ],
          "implementationNotes": [
            "Use synthetic objects; an artifact listing alone cannot prove an object is unreferenced."
          ],
          "verification": [
            "Collect an abandoned attempt artifact after its grace period.",
            "Race cleanup with a valid completion and prove committed output survives."
          ],
          "deliverables": [
            "Orphan collector, race fixture, and dry-run manifest"
          ],
          "rollout": "Review deletion manifests in dry-run mode, then enable cleanup for the synthetic storage prefix only.",
          "skills": [
            "Object lifecycle",
            "Garbage collection",
            "Race prevention",
            "Recovery"
          ],
          "fieldMix": [
            {
              "field": "Storage systems",
              "percentage": 50
            },
            {
              "field": "Platform engineering",
              "percentage": 30
            },
            {
              "field": "Distributed systems",
              "percentage": 20
            }
          ],
          "patterns": []
        }
      ]
    }
  ]
}
