{
  "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": "8c9f178c-225a-4c11-9d5b-66b1b37de6a7",
      "key": "TRIAGE",
      "title": "Support routing that agents can correct",
      "field": "Applied AI",
      "summary": "Build a routing assistant that suggests queues, validates model output, and preserves accountable human corrections.",
      "context": "A fictional software vendor receives billing, account-access, bug, and security reports. A prototype silently moves tickets based on vague model confidence. Replace it with bounded suggestions, deterministic safety rules, and an auditable review flow.",
      "stack": [
        "TypeScript",
        "PostgreSQL",
        "JSON Schema",
        "HTTP"
      ],
      "prerequisites": [
        "Create a synthetic support-ticket corpus with no real customer messages.",
        "Implement a deterministic local classifier double with success, malformed-output, and timeout modes."
      ],
      "developerValue": "Practice constrained classification, human correction workflows, model versioning, and evaluation under ambiguous inputs.",
      "companyValue": "Review whether automation saves triage effort while preserving queue ownership and safe escalation.",
      "delivery": "A local routing service with reviewable suggestions, correction history, and a replay evaluation report.",
      "phases": [
        {
          "id": "intake",
          "title": "Define routing inputs and rules",
          "goal": "Make categories and required human handling explicit."
        },
        {
          "id": "suggest",
          "title": "Offer bounded suggestions",
          "goal": "Validate and present proposals without silently moving tickets."
        },
        {
          "id": "feedback",
          "title": "Operate and learn from corrections",
          "goal": "Audit changes and compare revisions without leaking customer content."
        }
      ],
      "tickets": [
        {
          "id": "99e286b0-016a-459a-9d7c-bbecc230eb30",
          "key": "TRIAGE-101",
          "title": "Define queue labels with examples and an unknown outcome",
          "type": "TASK",
          "priority": "MEDIUM",
          "difficulty": "FOUNDATIONAL",
          "estimateMinutes": 60,
          "phaseId": "intake",
          "dependsOn": [],
          "scenario": "Different agents use Billing and Payments interchangeably, so routing reports cannot be compared. Define stable queue IDs with concise boundaries and ambiguous examples.",
          "acceptanceCriteria": [
            "Every queue has a stable ID, description, included examples, and excluded examples.",
            "UNKNOWN and NEEDS_REVIEW are explicit outcomes rather than invented queue names.",
            "Changing a label definition creates a new taxonomy version."
          ],
          "implementationNotes": [
            "Use fictional support topics and avoid demographic categories."
          ],
          "verification": [
            "Map a duplicate-charge example and an account-reset example to distinct documented queues.",
            "Validate that a mixed billing/security example can remain NEEDS_REVIEW."
          ],
          "deliverables": [
            "Versioned queue taxonomy and labeled examples"
          ],
          "rollout": "Use the taxonomy in suggestion-only mode; retain previous versions for historical reports.",
          "skills": [
            "Domain modeling",
            "Classification design",
            "Product specification"
          ],
          "fieldMix": [
            {
              "field": "Applied AI",
              "percentage": 100
            }
          ],
          "patterns": []
        },
        {
          "id": "d25b7795-2d3a-472f-bc0c-dfc8a0e4e36d",
          "key": "TRIAGE-102",
          "title": "Normalize inbound messages without discarding the original record",
          "type": "TASK",
          "priority": "MEDIUM",
          "difficulty": "INTERMEDIATE",
          "estimateMinutes": 90,
          "phaseId": "intake",
          "dependsOn": [
            "TRIAGE-101"
          ],
          "scenario": "Quoted email chains dominate routing input and duplicate attachments inflate request size. Create a bounded classification view while retaining the synthetic original message separately.",
          "acceptanceCriteria": [
            "The derived view records normalization version, source message revision, and truncation indicators.",
            "Input size is bounded and attachments contribute only permitted metadata.",
            "The original record is immutable and can be inspected by an authorized support reviewer."
          ],
          "implementationNotes": [
            "Normalization is deterministic; do not use a model to silently rewrite the complaint."
          ],
          "verification": [
            "Normalize a long quoted chain twice and compare identical derived views.",
            "Provide oversized text and an attachment filename containing markup; verify bounded plain-text input."
          ],
          "deliverables": [
            "Normalization pipeline and input-limit fixtures"
          ],
          "rollout": "Compare derived views in local review before enabling suggestions; use the original source reference for disputed cases.",
          "skills": [
            "Text processing",
            "Data provenance",
            "Input limits"
          ],
          "fieldMix": [
            {
              "field": "Data engineering",
              "percentage": 70
            },
            {
              "field": "Applied AI",
              "percentage": 30
            }
          ],
          "patterns": []
        },
        {
          "id": "92e7a7b0-80ed-4233-b450-9c7fca7a7892",
          "key": "TRIAGE-103",
          "title": "Route declared security incidents to review before calling a classifier",
          "type": "STORY",
          "priority": "HIGH",
          "difficulty": "ADVANCED",
          "estimateMinutes": 135,
          "phaseId": "intake",
          "dependsOn": [
            "TRIAGE-102"
          ],
          "scenario": "A user selects the security-incident contact form, but the model labels the message a normal login issue. Respect trusted intake metadata and require the security review queue.",
          "acceptanceCriteria": [
            "A trusted security-form source always produces a mandatory security-review state.",
            "The classifier cannot downgrade that state or trigger a customer-facing reply.",
            "Untrusted message text claiming to be system routing metadata does not acquire privileged routing authority."
          ],
          "implementationNotes": [
            "Distinguish server-owned intake fields from user-provided body text.",
            "Do not infer incident severity from writing style or personal attributes."
          ],
          "verification": [
            "Submit a short login message through the trusted security form and confirm mandatory review without classification.",
            "Put a forged security-source object in ordinary message text and confirm it remains untrusted content."
          ],
          "deliverables": [
            "Deterministic escalation policy and metadata-spoofing tests"
          ],
          "rollout": "Enable mandatory routing before model suggestions; keep a manual queue available when source metadata is missing.",
          "skills": [
            "Trust boundaries",
            "Safety rules",
            "Workflow design"
          ],
          "fieldMix": [
            {
              "field": "Applied AI",
              "percentage": 50
            },
            {
              "field": "Security",
              "percentage": 30
            },
            {
              "field": "Backend",
              "percentage": 20
            }
          ],
          "patterns": []
        },
        {
          "id": "a2c6a249-2a59-46d4-8fd8-c27c0ab2c264",
          "key": "TRIAGE-104",
          "title": "Accept only bounded suggestions from the classifier",
          "type": "STORY",
          "priority": "HIGH",
          "difficulty": "ADVANCED",
          "estimateMinutes": 150,
          "phaseId": "suggest",
          "dependsOn": [
            "TRIAGE-103"
          ],
          "scenario": "The provider returns a queue that no longer exists and a reason containing a link to an unrelated customer record. Validate suggestions against the exact taxonomy and source message.",
          "acceptanceCriteria": [
            "Output contains only permitted queue IDs, a review flag, and bounded supporting spans from the input.",
            "Every supporting span matches the normalized message exactly.",
            "Malformed, out-of-taxonomy, or unsupported outputs become NEEDS_REVIEW with no partial suggestion."
          ],
          "implementationNotes": [
            "Do not treat a model-supplied confidence number as a calibrated probability.",
            "Use strict schemas and plain text rendering."
          ],
          "verification": [
            "Accept a valid suggestion supported by an exact message span.",
            "Reject invented queues, fabricated spans, extra action fields, and markup payloads."
          ],
          "deliverables": [
            "Suggestion validator and malformed-provider fixtures"
          ],
          "rollout": "Require the validator on every adapter; fall back to the unassigned review queue on rejection.",
          "skills": [
            "Structured output",
            "Validation",
            "AI integration"
          ],
          "fieldMix": [
            {
              "field": "Applied AI",
              "percentage": 80
            },
            {
              "field": "Security",
              "percentage": 20
            }
          ],
          "patterns": []
        },
        {
          "id": "8507ab9e-ccf0-49b7-bd59-ff6907a6f363",
          "key": "TRIAGE-105",
          "title": "Show a suggested queue as an explicit agent action",
          "type": "STORY",
          "priority": "MEDIUM",
          "difficulty": "FOUNDATIONAL",
          "estimateMinutes": 90,
          "phaseId": "suggest",
          "dependsOn": [
            "TRIAGE-104"
          ],
          "scenario": "Agents cannot tell whether a ticket was assigned by a person or by the prototype. Display the suggestion alongside Accept and Choose another queue actions.",
          "acceptanceCriteria": [
            "A suggestion never changes the assigned queue by itself.",
            "The view labels provider version, suggestion time, and supporting message text.",
            "Keyboard users can accept, dismiss, or choose another permitted queue."
          ],
          "implementationNotes": [
            "Do not describe the suggestion as a verified conclusion."
          ],
          "verification": [
            "Load a suggestion and verify persisted assignment remains unchanged until acceptance.",
            "Dismiss it by keyboard and confirm no queue transition or customer message is created."
          ],
          "deliverables": [
            "Accessible suggestion panel and interaction tests"
          ],
          "rollout": "Release to an opt-in local agent view; disable the panel without changing existing queue assignment behavior.",
          "skills": [
            "Human-in-the-loop UX",
            "Accessibility",
            "State handling"
          ],
          "fieldMix": [
            {
              "field": "Frontend",
              "percentage": 60
            },
            {
              "field": "Applied AI",
              "percentage": 20
            },
            {
              "field": "Accessibility",
              "percentage": 20
            }
          ],
          "patterns": []
        },
        {
          "id": "81fb5168-f889-4f3c-9c41-062ed3ea70ec",
          "key": "TRIAGE-106",
          "title": "Discard a suggestion when the ticket changed while classification ran",
          "type": "BUG",
          "priority": "HIGH",
          "difficulty": "EXPERT",
          "estimateMinutes": 210,
          "phaseId": "suggest",
          "dependsOn": [
            "TRIAGE-104",
            "TRIAGE-105"
          ],
          "scenario": "A customer adds a security-relevant reply while an older billing suggestion is in flight. The old suggestion must not become actionable against the new message revision.",
          "acceptanceCriteria": [
            "A suggestion binds ticket ID, message revision, taxonomy version, and provider configuration.",
            "Persisting or accepting a stale suggestion fails with an explicit revision conflict.",
            "Concurrent acceptance by two agents creates at most one assignment transition and preserves both attempted-action outcomes."
          ],
          "implementationNotes": [
            "Enforce revision checks in the service/repository transaction, not only the UI.",
            "Keep assignment audit records append-only."
          ],
          "verification": [
            "Pause classification, append a reply, then release the provider and confirm the suggestion is stale.",
            "Race two acceptance requests and assert one transition with an explicit conflict for the loser."
          ],
          "deliverables": [
            "Revision-safe suggestion lifecycle and race tests"
          ],
          "rollout": "Enable acceptance only after revision checks are active; stale suggestions are regenerated or sent to manual review.",
          "skills": [
            "Optimistic concurrency",
            "Transactions",
            "Auditability",
            "Workflow integrity"
          ],
          "fieldMix": [
            {
              "field": "Backend",
              "percentage": 40
            },
            {
              "field": "Database engineering",
              "percentage": 30
            },
            {
              "field": "Applied AI",
              "percentage": 30
            }
          ],
          "patterns": []
        },
        {
          "id": "049c2db0-6496-4a77-bbc9-204201c1b43d",
          "key": "TRIAGE-107",
          "title": "Keep provider outages from blocking the support inbox",
          "type": "STORY",
          "priority": "HIGH",
          "difficulty": "INTERMEDIATE",
          "estimateMinutes": 120,
          "phaseId": "feedback",
          "dependsOn": [
            "TRIAGE-104"
          ],
          "scenario": "The classifier stalls and newly submitted tickets disappear until its call completes. Decouple intake from classification and make failure an observable review state.",
          "acceptanceCriteria": [
            "Ticket intake commits before asynchronous classification starts.",
            "Jobs use deterministic identities and bounded timeout/retry settings.",
            "Exhausted jobs leave tickets visible in manual review with a safe failure category."
          ],
          "implementationNotes": [
            "Use a transactional outbox or equivalent local transactional queue boundary.",
            "The default provider is deterministic and requires no credentials."
          ],
          "verification": [
            "Simulate provider timeout and verify immediate ticket visibility plus eventual review state.",
            "Deliver the same job twice and confirm it does not create duplicate suggestions."
          ],
          "deliverables": [
            "Asynchronous suggestion job and outage scenarios"
          ],
          "rollout": "Enable queued suggestions behind a feature flag; disable workers while preserving manual inbox intake.",
          "skills": [
            "Outbox",
            "Idempotent jobs",
            "Failure isolation"
          ],
          "fieldMix": [
            {
              "field": "Distributed systems",
              "percentage": 40
            },
            {
              "field": "Applied AI",
              "percentage": 30
            },
            {
              "field": "Backend",
              "percentage": 30
            }
          ],
          "patterns": []
        },
        {
          "id": "1c46e7de-584c-4bf0-97ca-5f48dce032b9",
          "key": "TRIAGE-108",
          "title": "Record corrections without turning agent clicks into automatic training data",
          "type": "STORY",
          "priority": "MEDIUM",
          "difficulty": "ADVANCED",
          "estimateMinutes": 150,
          "phaseId": "feedback",
          "dependsOn": [
            "TRIAGE-106"
          ],
          "scenario": "A corrected queue overwrites the original suggestion, making disagreement impossible to investigate. Preserve the proposal, decision, actor, and reason as separate records.",
          "acceptanceCriteria": [
            "Each correction links the original suggestion, selected queue, actor, time, and optional bounded reason.",
            "Corrections are append-only and readable only within the ticket tenant and permitted support role.",
            "No correction triggers external training or sends message text to a provider automatically."
          ],
          "implementationNotes": [
            "Treat corrections as operational feedback, not unquestionable ground truth."
          ],
          "verification": [
            "Correct one suggestion twice and inspect the complete ordered history.",
            "Attempt to read another tenant correction and confirm denial with no message text leakage."
          ],
          "deliverables": [
            "Correction audit model and scoped history endpoint"
          ],
          "rollout": "Start collecting local operational feedback with retention controls; any later training export requires a separate governed workflow.",
          "skills": [
            "Audit logs",
            "Tenant authorization",
            "Data governance"
          ],
          "fieldMix": [
            {
              "field": "Privacy engineering",
              "percentage": 40
            },
            {
              "field": "Backend",
              "percentage": 30
            },
            {
              "field": "Applied AI",
              "percentage": 30
            }
          ],
          "patterns": []
        },
        {
          "id": "cc59f8e1-fca8-4f53-90f8-b467c9b03d13",
          "key": "TRIAGE-109",
          "title": "Compare two routing revisions on the same ambiguous-ticket set",
          "type": "TASK",
          "priority": "MEDIUM",
          "difficulty": "ADVANCED",
          "estimateMinutes": 150,
          "phaseId": "feedback",
          "dependsOn": [
            "TRIAGE-107",
            "TRIAGE-108"
          ],
          "scenario": "A new prompt moves more messages to Billing, but the team cannot tell whether it improved routing or merely reduced abstention. Compare both revisions on a fixed synthetic case set.",
          "acceptanceCriteria": [
            "Cases include mixed issues, short messages, quoted text, injection attempts, and explicit security intake.",
            "Reports show per-queue outcomes, review rate, rule violations, invalid outputs, and changed decisions.",
            "A mandatory-review violation blocks adopting the new revision regardless of aggregate routing accuracy."
          ],
          "implementationNotes": [
            "Pin normalization, taxonomy, provider-double, and case-set versions.",
            "Keep abstentions visible rather than counting them as successful classifications."
          ],
          "verification": [
            "Run both revisions on identical inputs and reproduce the decision diff.",
            "Inject a security downgrade into one revision and confirm it fails the adoption gate."
          ],
          "deliverables": [
            "Routing comparison harness and adoption report"
          ],
          "rollout": "Keep the current revision active while evaluating the new one; switch by versioned configuration after category gates pass.",
          "skills": [
            "AI evaluation",
            "Regression analysis",
            "Release criteria"
          ],
          "fieldMix": [
            {
              "field": "Applied AI",
              "percentage": 60
            },
            {
              "field": "Quality engineering",
              "percentage": 40
            }
          ],
          "patterns": []
        },
        {
          "id": "1cd44396-8d43-4da8-b5bd-1699887c4b8b",
          "key": "TRIAGE-110",
          "title": "Explain routing delays using metadata instead of customer messages",
          "type": "CHORE",
          "priority": "MEDIUM",
          "difficulty": "INTERMEDIATE",
          "estimateMinutes": 105,
          "phaseId": "feedback",
          "dependsOn": [
            "TRIAGE-109"
          ],
          "scenario": "Support leads need to diagnose slow suggestions, while logs currently include full complaint text. Add safe operational measures and an immediate suggestion kill switch.",
          "acceptanceCriteria": [
            "Metrics expose queue delay, provider duration, timeout count, validation failures, and manual-review count without message bodies.",
            "Audit metadata includes trace ID and exact provider/template/schema versions.",
            "Disabling suggestions stops new provider calls while tickets and existing audit history remain accessible."
          ],
          "implementationNotes": [
            "Represent unavailable provider cost as unavailable, not zero.",
            "Keep privileged access to source messages outside generic analytics."
          ],
          "verification": [
            "Run a delayed provider fixture and trace intake-to-review timing from metadata.",
            "Toggle the kill switch with queued work and confirm no new calls and no lost tickets."
          ],
          "deliverables": [
            "Safe operations dashboard data and disable/recovery runbook"
          ],
          "rollout": "Enable metrics before activating suggestions; use the kill switch for unexpected routing changes while retaining manual service.",
          "skills": [
            "Observability",
            "Privacy",
            "Operational controls"
          ],
          "fieldMix": [
            {
              "field": "Applied AI",
              "percentage": 40
            },
            {
              "field": "Site reliability",
              "percentage": 30
            },
            {
              "field": "Privacy engineering",
              "percentage": 30
            }
          ],
          "patterns": []
        }
      ]
    }
  ]
}
