{
  "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": "bfc97100-c9a8-4478-a42d-c6ce2bc2c384",
      "key": "AINGEST",
      "title": "Recover a partner telemetry ingestion pipeline",
      "field": "Data engineering",
      "summary": "Ingest compressed telemetry with explicit quarantine, lineage and replay.",
      "context": "A fictional energy dashboard receives hourly device batches. Corrupt archives and late corrections leave operators unsure which readings reached reports.",
      "stack": [
        "Python",
        "PostgreSQL",
        "Object storage"
      ],
      "prerequisites": [
        "Create synthetic device batches and local object-store fixtures.",
        "Understand checksums and bounded streaming."
      ],
      "developerValue": "Practice batch integrity, replay and data-quality boundaries.",
      "companyValue": "Review whether operational data can be traced, corrected and recovered.",
      "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": "input",
          "title": "Validate batch boundaries",
          "goal": "Reject unsafe or ambiguous inputs before loading."
        },
        {
          "id": "load",
          "title": "Load traceable records",
          "goal": "Preserve lineage and deterministic corrections."
        },
        {
          "id": "recover",
          "title": "Recover ingestion gaps",
          "goal": "Reconcile committed batches and repair derived data."
        }
      ],
      "tickets": [
        {
          "id": "dbe4c1e7-0a39-4017-aa04-855a89b29bf0",
          "key": "AINGEST-101",
          "title": "Record a manifest before decoding a telemetry batch",
          "type": "TASK",
          "priority": "MEDIUM",
          "difficulty": "FOUNDATIONAL",
          "estimateMinutes": 90,
          "phaseId": "input",
          "dependsOn": [],
          "scenario": "Operators see a failed file name but cannot identify the original bytes or the parser version used.",
          "acceptanceCriteria": [
            "Record object version, byte hash and declared format.",
            "Bind each ingestion attempt to one manifest.",
            "Reject a changed object version on retry."
          ],
          "implementationNotes": [
            "Use synthetic object metadata; avoid storing credentials in manifests."
          ],
          "verification": [
            "Retry unchanged bytes against the same manifest.",
            "Replace bytes under the same object key and report identity mismatch."
          ],
          "deliverables": [
            "Manifest schema and identity checks"
          ],
          "rollout": "Start manifests for new batches; retain earlier records as explicitly untracked.",
          "skills": [
            "Lineage",
            "Checksums"
          ],
          "fieldMix": [
            {
              "field": "Data engineering",
              "percentage": 60
            },
            {
              "field": "Storage systems",
              "percentage": 40
            }
          ],
          "patterns": []
        },
        {
          "id": "1c4b8c6f-0a9e-49a6-a018-47666eb210a7",
          "key": "AINGEST-102",
          "title": "Cap decompressed telemetry bytes before archive expansion",
          "type": "BUG",
          "priority": "HIGH",
          "difficulty": "ADVANCED",
          "estimateMinutes": 180,
          "phaseId": "input",
          "dependsOn": [
            "AINGEST-101"
          ],
          "scenario": "A tiny compressed batch expands far beyond the ingestion worker's memory budget.",
          "acceptanceCriteria": [
            "Enforce compressed, expanded-byte and row limits.",
            "Stop streaming as soon as a bound is crossed.",
            "Quarantine with a reason without loading partial rows."
          ],
          "implementationNotes": [
            "Do not unpack paths or execute files from archives."
          ],
          "verification": [
            "Ingest a valid compressed synthetic batch.",
            "Exercise excessive expansion and path-like entry names without writing outside staging."
          ],
          "deliverables": [
            "Bounded decoder and hostile archive fixtures"
          ],
          "rollout": "Enable bounded decoding before partner intake; keep rejected objects quarantined.",
          "skills": [
            "Streaming",
            "Resource limits"
          ],
          "fieldMix": [
            {
              "field": "Data engineering",
              "percentage": 40
            },
            {
              "field": "Performance engineering",
              "percentage": 30
            },
            {
              "field": "Security",
              "percentage": 30
            }
          ],
          "patterns": []
        },
        {
          "id": "b5b1edec-a484-4f3b-bb4d-004abc509f0f",
          "key": "AINGEST-103",
          "title": "Normalize sensor units through a versioned conversion table",
          "type": "TASK",
          "priority": "MEDIUM",
          "difficulty": "INTERMEDIATE",
          "estimateMinutes": 150,
          "phaseId": "input",
          "dependsOn": [
            "AINGEST-101"
          ],
          "scenario": "Two device models emit watt-hours and kilowatt-hours under the same field name.",
          "acceptanceCriteria": [
            "Require a known unit and conversion version.",
            "Preserve raw numeric value and declared unit in lineage.",
            "Reject unsupported units and nonfinite measurements."
          ],
          "implementationNotes": [
            "Use decimal arithmetic for documented conversions."
          ],
          "verification": [
            "Convert synthetic Wh and kWh to equal canonical readings.",
            "Reject missing units and nonfinite input."
          ],
          "deliverables": [
            "Unit conversion contract and cases"
          ],
          "rollout": "Publish conversion revisions for new runs; retain old mappings for replay.",
          "skills": [
            "Data normalization",
            "Versioning"
          ],
          "fieldMix": [
            {
              "field": "Data engineering",
              "percentage": 100
            }
          ],
          "patterns": []
        },
        {
          "id": "8e01b627-5d45-47c7-95c0-883ccd390b12",
          "key": "AINGEST-104",
          "title": "Commit telemetry rows and the batch checkpoint atomically",
          "type": "STORY",
          "priority": "HIGH",
          "difficulty": "ADVANCED",
          "estimateMinutes": 240,
          "phaseId": "load",
          "dependsOn": [
            "AINGEST-102",
            "AINGEST-103"
          ],
          "scenario": "A process dies after inserting rows but before marking the file complete; replay doubles reported usage.",
          "acceptanceCriteria": [
            "Persist rows and committed checkpoint in one transaction.",
            "Use source reading identity to reject duplicate insertion.",
            "Retries return committed counts without adding readings."
          ],
          "implementationNotes": [
            "Bound transaction size; larger batches require explicit sub-batch identities."
          ],
          "verification": [
            "Kill the test process at modeled commit boundaries.",
            "Replay a completed sub-batch and compare row counts and totals."
          ],
          "deliverables": [
            "Atomic batch loader and crash probe"
          ],
          "rollout": "Canary small batches; pause loading and inspect manifests if reconciliation diverges.",
          "skills": [
            "Transactions",
            "Idempotency"
          ],
          "fieldMix": [
            {
              "field": "Data engineering",
              "percentage": 50
            },
            {
              "field": "Database engineering",
              "percentage": 50
            }
          ],
          "patterns": []
        },
        {
          "id": "9672c565-9395-4de8-be20-67bf9e01d74d",
          "key": "AINGEST-105",
          "title": "Quarantine malformed readings with usable row coordinates",
          "type": "STORY",
          "priority": "MEDIUM",
          "difficulty": "FOUNDATIONAL",
          "estimateMinutes": 90,
          "phaseId": "load",
          "dependsOn": [
            "AINGEST-102",
            "AINGEST-103"
          ],
          "scenario": "A malformed timestamp makes the ingestion job fail with a stack trace and no indication of the source row.",
          "acceptanceCriteria": [
            "Report manifest ID, row number and stable reason code.",
            "Keep rejected values out of generic logs.",
            "Publish accepted and rejected counts under the declared partial-load policy."
          ],
          "implementationNotes": [
            "Choose and document all-or-nothing versus row quarantine for this dataset."
          ],
          "verification": [
            "Load a batch containing valid rows under the chosen policy.",
            "Insert malformed timestamps and verify coordinates and count invariants."
          ],
          "deliverables": [
            "Quarantine report and policy tests"
          ],
          "rollout": "Enable reports before changing load policy; replay corrected manifests as new attempts.",
          "skills": [
            "Data quality",
            "Error reporting"
          ],
          "fieldMix": [
            {
              "field": "Data engineering",
              "percentage": 100
            }
          ],
          "patterns": []
        },
        {
          "id": "28a89991-18da-45dd-adf5-cb036ab83a8c",
          "key": "AINGEST-106",
          "title": "Apply corrected readings without overwriting source history",
          "type": "STORY",
          "priority": "MEDIUM",
          "difficulty": "EXPERT",
          "estimateMinutes": 300,
          "phaseId": "load",
          "dependsOn": [
            "AINGEST-104",
            "AINGEST-105"
          ],
          "scenario": "A device sends a corrected cumulative reading two days late; a blind upsert destroys the value used in yesterday's report.",
          "acceptanceCriteria": [
            "Append corrections linked to source reading and revision.",
            "Define the effective reading deterministically.",
            "Reject contradictory equal-revision corrections for review."
          ],
          "implementationNotes": [
            "Preserve original ingestion time separately from measurement time."
          ],
          "verification": [
            "Apply a higher revision and inspect both historical values.",
            "Submit equal revision with changed value and retain the last valid projection."
          ],
          "deliverables": [
            "Correction model and conflict cases"
          ],
          "rollout": "Enable corrections for one synthetic device; rebuild projections from retained history on rollback.",
          "skills": [
            "Temporal data",
            "Append-only design"
          ],
          "fieldMix": [
            {
              "field": "Data engineering",
              "percentage": 70
            },
            {
              "field": "Database engineering",
              "percentage": 30
            }
          ],
          "patterns": []
        },
        {
          "id": "888265ca-96f7-436b-9a1d-ccd6c538ecd4",
          "key": "AINGEST-107",
          "title": "Use event-time watermarks without discarding late telemetry silently",
          "type": "TASK",
          "priority": "MEDIUM",
          "difficulty": "ADVANCED",
          "estimateMinutes": 210,
          "phaseId": "load",
          "dependsOn": [
            "AINGEST-106"
          ],
          "scenario": "The hourly aggregate closes by arrival time and quietly ignores a delayed batch from an offline device.",
          "acceptanceCriteria": [
            "Define watermark advancement and allowed lateness.",
            "Route late readings to a visible correction path.",
            "Report aggregate revision when late data changes a result."
          ],
          "implementationNotes": [
            "Test with a controlled clock and explicit event timestamps."
          ],
          "verification": [
            "Deliver an in-window late reading and update the expected aggregate.",
            "Deliver beyond the lateness window and verify visible deferred correction."
          ],
          "deliverables": [
            "Watermark logic and late-arrival fixtures"
          ],
          "rollout": "Run alongside the prior aggregate; switch readers only after discrepancy review.",
          "skills": [
            "Event time",
            "Aggregation"
          ],
          "fieldMix": [
            {
              "field": "Data engineering",
              "percentage": 70
            },
            {
              "field": "Real-time systems",
              "percentage": 30
            }
          ],
          "patterns": []
        },
        {
          "id": "b4d16852-2af9-4ddc-805b-c11703ae73cc",
          "key": "AINGEST-108",
          "title": "Reconcile uploaded telemetry manifests against committed checkpoints",
          "type": "CHORE",
          "priority": "MEDIUM",
          "difficulty": "INTERMEDIATE",
          "estimateMinutes": 180,
          "phaseId": "recover",
          "dependsOn": [
            "AINGEST-104",
            "AINGEST-107"
          ],
          "scenario": "Object storage contains yesterday's batches, but dashboard totals are low and no worker currently owns the missing jobs.",
          "acceptanceCriteria": [
            "List missing, pending and committed manifests by bounded window.",
            "Schedule replay only for eligible uncommitted identities.",
            "Make repeated reconciliation produce no duplicate committed data."
          ],
          "implementationNotes": [
            "Require explicit organization and time bounds."
          ],
          "verification": [
            "Find a synthetic uploaded batch without a checkpoint.",
            "Rerun reconciliation after commit and schedule nothing additional."
          ],
          "deliverables": [
            "Manifest reconciler and bounded replay command"
          ],
          "rollout": "Dry-run first; stop replay dispatch while preserving the discrepancy report.",
          "skills": [
            "Reconciliation",
            "Operations"
          ],
          "fieldMix": [
            {
              "field": "Data engineering",
              "percentage": 50
            },
            {
              "field": "Storage systems",
              "percentage": 30
            },
            {
              "field": "Site reliability",
              "percentage": 20
            }
          ],
          "patterns": []
        },
        {
          "id": "01df221c-4c69-4a4b-9911-f61f1a45f241",
          "key": "AINGEST-109",
          "title": "Verify a telemetry backfill against immutable aggregate snapshots",
          "type": "TASK",
          "priority": "MEDIUM",
          "difficulty": "EXPERT",
          "estimateMinutes": 360,
          "phaseId": "recover",
          "dependsOn": [
            "AINGEST-106",
            "AINGEST-107",
            "AINGEST-108"
          ],
          "scenario": "A conversion fix requires rebuilding a week of energy totals without obscuring what the previous dashboard showed.",
          "acceptanceCriteria": [
            "Build a new aggregate generation from named manifests.",
            "Compare counts, units and totals against frozen previous output.",
            "Atomically select the generation only after review."
          ],
          "implementationNotes": [
            "Use a synthetic seven-day corpus with declared correction cases."
          ],
          "verification": [
            "Backfill the corpus and reconcile every changed aggregate.",
            "Interrupt before activation and keep previous dashboard reads consistent."
          ],
          "deliverables": [
            "Backfill runner and generation difference report"
          ],
          "rollout": "Activate one synthetic tenant; restore the old generation pointer on discrepancy.",
          "skills": [
            "Backfills",
            "Data reconciliation"
          ],
          "fieldMix": [
            {
              "field": "Data engineering",
              "percentage": 80
            },
            {
              "field": "Database engineering",
              "percentage": 20
            }
          ],
          "patterns": []
        },
        {
          "id": "fbd82c12-737c-45fa-9646-d863e0dc4d19",
          "key": "AINGEST-110",
          "title": "Add an ingestion freshness report that distinguishes missing data from zero",
          "type": "TASK",
          "priority": "MEDIUM",
          "difficulty": "FOUNDATIONAL",
          "estimateMinutes": 90,
          "phaseId": "recover",
          "dependsOn": [
            "AINGEST-108",
            "AINGEST-109"
          ],
          "scenario": "A site with no recent readings is displayed as consuming zero energy, misleading dashboard consumers.",
          "acceptanceCriteria": [
            "Show last event time and last committed arrival separately.",
            "Represent missing intervals as unknown rather than numeric zero.",
            "Define stale thresholds from a documented expected schedule."
          ],
          "implementationNotes": [
            "Do not claim zero consumption without a reading."
          ],
          "verification": [
            "Report a genuine zero reading as zero.",
            "Remove a scheduled batch and show unknown with stale status."
          ],
          "deliverables": [
            "Freshness projection and missing-data cases"
          ],
          "rollout": "Introduce freshness beside existing totals; revert display wiring while preserving unknown semantics.",
          "skills": [
            "Data semantics",
            "Observability"
          ],
          "fieldMix": [
            {
              "field": "Data engineering",
              "percentage": 60
            },
            {
              "field": "Site reliability",
              "percentage": 40
            }
          ],
          "patterns": []
        }
      ]
    }
  ]
}
