{
  "generated": "2026-07-27T03:00:36.756Z",
  "unique_phrases": 103,
  "total_occurrences": 112,
  "phrases": [
    {
      "phrase": "the problem, requirements,",
      "phrase_norm": "the problem, requirements",
      "max_ratio": 1363,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 3
      },
      "last_seen": {
        "phase": "p#1",
        "try": 3
      },
      "replacements_used": [
        "D1 documents the use case, the HTTP routes I'll build, and my Go/Fiber choice — not working code yet."
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "the problem, requirements,",
        "D1 documents the use case, the HTTP routes I'll build, and my Go/Fiber choice — not working code yet."
      ]
    },
    {
      "phrase": "input handling The",
      "phrase_norm": "input handling the",
      "max_ratio": 1108,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#2",
        "try": 1
      },
      "last_seen": {
        "phase": "p#2",
        "try": 1
      },
      "replacements_used": [
        "Rename the section to *\"Error responses for bad requests\" and open with: When a request fails validation, the server answers with JSON instead of crashing.*"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "input handling The",
        "Rename the section to *\"Error responses for bad requests\" and open with: When a request fails validation, the server answers with JSON instead of crashing.*"
      ]
    },
    {
      "phrase": "amount must be positive",
      "phrase_norm": "amount must be positive",
      "max_ratio": 379,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#2",
        "try": 2
      },
      "last_seen": {
        "phase": "p#2",
        "try": 2
      },
      "replacements_used": [
        "Table *Message* column: charge amount must exceed zero (or non-positive amount rejected) — update the fenced JSON example to match only if your Go handler returns the same string; otherwise drop the example and describe the rejection in prose."
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "amount must be positive",
        "Table *Message* column: charge amount must exceed zero (or non-positive amount rejected) — update the fenced JSON example to match only if your Go handler returns the same string; otherwise drop the example and describe the rejection in prose."
      ]
    },
    {
      "phrase": "MVP scope and",
      "phrase_norm": "mvp scope and",
      "max_ratio": 273,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 2
      },
      "last_seen": {
        "phase": "p#1",
        "try": 2
      },
      "replacements_used": [
        "State the HTTP-only boundary once in a short *Security / transport* note near the top, then drop repeated “MVP scope” wording elsewhere — e.g. “Local dev uses plain HTTP; TLS is a later deployment concern.”"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "MVP scope and",
        "State the HTTP-only boundary once in a short *Security / transport* note near the top, then drop repeated “MVP scope” wording elsewhere — e.g. “Local dev uses plain HTTP; TLS is a later deployment concern.”"
      ]
    },
    {
      "phrase": "curl, Postman, or",
      "phrase_norm": "curl, postman, or",
      "max_ratio": 235,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [
        "You can hit the endpoints from the command line or from a REST client — no UI required yet."
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "curl, Postman, or",
        "You can hit the endpoints from the command line or from a REST client — no UI required yet."
      ]
    },
    {
      "phrase": "Step 2: split into",
      "phrase_norm": "step 2: split into",
      "max_ratio": 157,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [
        "Next, separate members who are owed money from members who owe money."
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "Step 2: split into",
        "Next, separate members who are owed money from members who owe money."
      ]
    },
    {
      "phrase": "Next steps: implement",
      "phrase_norm": "next steps: implement",
      "max_ratio": 110,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [
        "What comes after D1: code the API, publish the Swagger file, and tag milestones in the repo."
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "Next steps: implement",
        "What comes after D1: code the API, publish the Swagger file, and tag milestones in the repo."
      ]
    },
    {
      "phrase": "with Postman (or curl).",
      "phrase_norm": "with postman (or curl",
      "max_ratio": 110,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [
        "using manual HTTP requests (terminal or REST client)."
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "with Postman (or curl).",
        "using manual HTTP requests (terminal or REST client)."
      ]
    },
    {
      "phrase": "OpenAPI Specification 3 (OAS",
      "phrase_norm": "openapi specification 3 (oas",
      "max_ratio": 90,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [
        "a Swagger / OAS 3 spec"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "OpenAPI Specification 3 (OAS",
        "a Swagger / OAS 3 spec"
      ]
    },
    {
      "phrase": "with instructors or peers",
      "phrase_norm": "with instructors or peers",
      "max_ratio": 83,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [
        "with my professor and classmates"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "with instructors or peers",
        "with my professor and classmates"
      ]
    },
    {
      "phrase": "Common status codes:",
      "phrase_norm": "common status codes",
      "max_ratio": 76,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [
        "Typical HTTP responses include:"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "Common status codes:",
        "Typical HTTP responses include:"
      ]
    },
    {
      "phrase": "as needed // Step",
      "phrase_norm": "as needed // step",
      "max_ratio": 64,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [
        "if rounding leaves tiny leftovers // Second phase:"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "as needed // Step",
        "if rounding leaves tiny leftovers // Second phase:"
      ]
    },
    {
      "phrase": "simple RESTful API",
      "phrase_norm": "simple restful api",
      "max_ratio": 52,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [
        "JSON-over-HTTP API"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "simple RESTful API",
        "JSON-over-HTTP API"
      ]
    },
    {
      "phrase": "the request body as JSON;",
      "phrase_norm": "the request body as json",
      "max_ratio": 46,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#2",
        "try": 2
      },
      "last_seen": {
        "phase": "p#2",
        "try": 2
      },
      "replacements_used": [
        "Step 1 → Decode the incoming payload with json.Unmarshal; syntax errors return 400 BAD_REQUEST."
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "the request body as JSON;",
        "Step 1 → Decode the incoming payload with json.Unmarshal; syntax errors return 400 BAD_REQUEST."
      ]
    },
    {
      "phrase": "SQLAlchemy / Django ORM",
      "phrase_norm": "sqlalchemy / django orm",
      "max_ratio": 35,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [
        "Python ORM libraries (e.g. SQLAlchemy)"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "SQLAlchemy / Django ORM",
        "Python ORM libraries (e.g. SQLAlchemy)"
      ]
    },
    {
      "phrase": "invalid input is",
      "phrase_norm": "invalid input is",
      "max_ratio": 35,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#2",
        "try": 1
      },
      "last_seen": {
        "phase": "p#2",
        "try": 1
      },
      "replacements_used": [
        "Retitle *\"Error-handling pipeline (summary)\"*"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "invalid input is",
        "Retitle *\"Error-handling pipeline (summary)\"*"
      ]
    },
    {
      "phrase": "Structure of Programming Language",
      "phrase_norm": "structure of programming language",
      "max_ratio": 32,
      "status": "persistent",
      "times_flagged": 5,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#2",
        "try": 1
      },
      "replacements_used": [
        "Shorten the header to *Course:* CMSC501-1 — Summer 2026 (drop the long official title)."
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "Structure of Programming Language",
        "Shorten the header to *Course:* CMSC501-1 — Summer 2026 (drop the long official title)."
      ]
    },
    {
      "phrase": "or REST client).",
      "phrase_norm": "or rest client",
      "max_ratio": 31,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 2
      },
      "last_seen": {
        "phase": "p#1",
        "try": 2
      },
      "replacements_used": [
        "“using manual HTTP requests from a terminal or API testing tool).”"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "or REST client).",
        "“using manual HTTP requests from a terminal or API testing tool).”"
      ]
    },
    {
      "phrase": "or a REST client;",
      "phrase_norm": "or a rest client",
      "max_ratio": 31,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 2
      },
      "last_seen": {
        "phase": "p#1",
        "try": 2
      },
      "replacements_used": [
        "“from the command line or an HTTP client app;”"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "or a REST client;",
        "“from the command line or an HTTP client app;”"
      ]
    },
    {
      "phrase": "input. It returns",
      "phrase_norm": "input. it returns",
      "max_ratio": 28,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#2",
        "try": 1
      },
      "last_seen": {
        "phase": "p#2",
        "try": 1
      },
      "replacements_used": [
        "When validation fails, the handler sends a JSON error object and the matching status code."
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "input. It returns",
        "When validation fails, the handler sends a JSON error object and the matching status code."
      ]
    },
    {
      "phrase": "on the problem definition,",
      "phrase_norm": "on the problem definition",
      "max_ratio": 27,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [
        "on scoping the problem, the API design, and why I picked Go/Fiber"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "on the problem definition,",
        "on scoping the problem, the API design, and why I picked Go/Fiber"
      ]
    },
    {
      "phrase": "`{\"error\": \"name is required\",`",
      "phrase_norm": "error\": \"name is required",
      "max_ratio": 27,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#2",
        "try": 1
      },
      "last_seen": {
        "phase": "p#2",
        "try": 1
      },
      "replacements_used": [
        "In the error table, split into columns *Message | Code* (e.g. name is required | VALIDATION) instead of repeating the full JSON blob on every row."
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "`{\"error\": \"name is required\",`",
        "In the error table, split into columns *Message | Code* (e.g. name is required | VALIDATION) instead of repeating the full JSON blob on every row."
      ]
    },
    {
      "phrase": "Validate required fields",
      "phrase_norm": "validate required fields",
      "max_ratio": 27,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#2",
        "try": 1
      },
      "last_seen": {
        "phase": "p#2",
        "try": 1
      },
      "replacements_used": [
        "Check that required values are present and within allowed ranges"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "Validate required fields",
        "Check that required values are present and within allowed ranges"
      ]
    },
    {
      "phrase": "Overkill for a simple",
      "phrase_norm": "overkill for a simple",
      "max_ratio": 25,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [
        "More stack than I need for a"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "Overkill for a simple",
        "More stack than I need for a"
      ]
    },
    {
      "phrase": "type system / checks",
      "phrase_norm": "type system / checks",
      "max_ratio": 20,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 2
      },
      "last_seen": {
        "phase": "p#1",
        "try": 2
      },
      "replacements_used": [
        "“Static typing at compile time” (Go column) vs “Dynamic typing; bugs may surface at runtime” (Python) vs “Static types on the CLR” (C#)."
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "type system / checks",
        "“Static typing at compile time” (Go column) vs “Dynamic typing; bugs may surface at runtime” (Python) vs “Static types on the CLR” (C#)."
      ]
    },
    {
      "phrase": "empty list i = 0 j = 0 while",
      "phrase_norm": "empty list i = 0 j = 0 while",
      "max_ratio": 19,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [],
      "replacements_failed": [],
      "do_not_suggest": [
        "empty list i = 0 j = 0 while"
      ]
    },
    {
      "phrase": "validation, the server",
      "phrase_norm": "validation, the server",
      "max_ratio": 18,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#2",
        "try": 2
      },
      "last_seen": {
        "phase": "p#2",
        "try": 2
      },
      "replacements_used": [
        "Opening under *Error responses for bad requests → Bad input never kills the process—I write a structured error object back to the client.*"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "validation, the server",
        "Opening under *Error responses for bad requests → Bad input never kills the process—I write a structured error object back to the client.*"
      ]
    },
    {
      "phrase": "Go garbage collector",
      "phrase_norm": "go garbage collector",
      "max_ratio": 17,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [
        "Go's built-in GC"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "Go garbage collector",
        "Go's built-in GC"
      ]
    },
    {
      "phrase": "on the parsed",
      "phrase_norm": "on the parsed",
      "max_ratio": 17,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#2",
        "try": 3
      },
      "last_seen": {
        "phase": "p#2",
        "try": 3
      },
      "replacements_used": [
        "Step 2 → After unmarshaling, enforce handler rules on the struct (empty names, amount > 0, etc.) → 400 VALIDATION"
      ],
      "replacements_failed": [
        "Step 2 → After unmarshaling, enforce handler rules on the struct (empty names, amount > 0, etc.) → 400 VALIDATION"
      ],
      "do_not_suggest": [
        "on the parsed",
        "Step 2 → After unmarshaling, enforce handler rules on the struct (empty names, amount > 0, etc.) → 400 VALIDATION"
      ]
    },
    {
      "phrase": "rather than crashing the",
      "phrase_norm": "rather than crashing the",
      "max_ratio": 17,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#2",
        "try": 3
      },
      "last_seen": {
        "phase": "p#2",
        "try": 3
      },
      "replacements_used": [
        "Opening under *Rejecting bad payloads → Invalid payloads get a JSON error body—the process keeps running.*"
      ],
      "replacements_failed": [
        "Opening under *Rejecting bad payloads → Invalid payloads get a JSON error body—the process keeps running.*"
      ],
      "do_not_suggest": [
        "rather than crashing the",
        "Opening under *Rejecting bad payloads → Invalid payloads get a JSON error body—the process keeps running.*"
      ]
    },
    {
      "phrase": "person p in people",
      "phrase_norm": "person p in people",
      "max_ratio": 15,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [
        "each member in the group"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "person p in people",
        "each member in the group"
      ]
    },
    {
      "phrase": "could use Python",
      "phrase_norm": "could use python",
      "max_ratio": 15,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 2
      },
      "last_seen": {
        "phase": "p#1",
        "try": 2
      },
      "replacements_used": [
        "“FastAPI would work for a small API, but…”"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "could use Python",
        "“FastAPI would work for a small API, but…”"
      ]
    },
    {
      "phrase": "cloud load balancer",
      "phrase_norm": "cloud load balancer",
      "max_ratio": 15,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 2
      },
      "last_seen": {
        "phase": "p#1",
        "try": 2
      },
      "replacements_used": [
        "“a hosted reverse proxy in front of the app).”"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "cloud load balancer",
        "“a hosted reverse proxy in front of the app).”"
      ]
    },
    {
      "phrase": "via terminal commands",
      "phrase_norm": "via terminal commands",
      "max_ratio": 15,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 3
      },
      "last_seen": {
        "phase": "p#1",
        "try": 3
      },
      "replacements_used": [
        "call the routes with raw JSON over HTTP — e.g. PowerShell Invoke-RestMethod or a desktop JSON tool"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "via terminal commands",
        "call the routes with raw JSON over HTTP — e.g. PowerShell Invoke-RestMethod or a desktop JSON tool"
      ]
    },
    {
      "phrase": "fairly? For instance:",
      "phrase_norm": "fairly? for instance",
      "max_ratio": 15,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 4
      },
      "last_seen": {
        "phase": "p#1",
        "try": 4
      },
      "replacements_used": [
        "End the question without \"fairly\", then break before examples — e.g. \"which members still owe money once shares are applied?\" Add a blank line, then *Two examples:* (not \"For instance:\")."
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "fairly? For instance:",
        "End the question without \"fairly\", then break before examples — e.g. \"which members still owe money once shares are applied?\" Add a blank line, then *Two examples:* (not \"For instance:\")."
      ]
    },
    {
      "phrase": "`\"amount must be greater than`",
      "phrase_norm": "amount must be greater than",
      "max_ratio": 15,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#2",
        "try": 1
      },
      "last_seen": {
        "phase": "p#2",
        "try": 1
      },
      "replacements_used": [
        "Table row: *Message: amount must be positive · Code:* VALIDATION (no quoted JSON string)."
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "`\"amount must be greater than`",
        "Table row: *Message: amount must be positive · Code:* VALIDATION (no quoted JSON string)."
      ]
    },
    {
      "phrase": "Strong fit for",
      "phrase_norm": "strong fit for",
      "max_ratio": 13,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [
        "Works well for"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "Strong fit for",
        "Works well for"
      ]
    },
    {
      "phrase": "API testing tool.",
      "phrase_norm": "api testing tool",
      "max_ratio": 12,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 3
      },
      "last_seen": {
        "phase": "p#1",
        "try": 3
      },
      "replacements_used": [
        "hand-sent JSON over HTTP from PowerShell or a desktop JSON viewer."
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "API testing tool.",
        "hand-sent JSON over HTTP from PowerShell or a desktop JSON viewer."
      ]
    },
    {
      "phrase": "API in Go",
      "phrase_norm": "api in go",
      "max_ratio": 12,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#2",
        "try": 1
      },
      "last_seen": {
        "phase": "p#2",
        "try": 1
      },
      "replacements_used": [
        "bill-splitting HTTP service written in Go"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "API in Go",
        "bill-splitting HTTP service written in Go"
      ]
    },
    {
      "phrase": "code VALIDATION and",
      "phrase_norm": "code validation and",
      "max_ratio": 12,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#2",
        "try": 3
      },
      "last_seen": {
        "phase": "p#2",
        "try": 3
      },
      "replacements_used": [
        "Replace the long sample sentence with: A zero-amount charge returns HTTP 400; the body carries a VALIDATION code and a short amount-related message."
      ],
      "replacements_failed": [
        "Replace the long sample sentence with: A zero-amount charge returns HTTP 400; the body carries a VALIDATION code and a short amount-related message."
      ],
      "do_not_suggest": [
        "code VALIDATION and",
        "Replace the long sample sentence with: A zero-amount charge returns HTTP 400; the body carries a VALIDATION code and a short amount-related message."
      ]
    },
    {
      "phrase": "Version control: GitHub",
      "phrase_norm": "version control: github",
      "max_ratio": 11,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [
        "Repo hosting: GitHub"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "Version control: GitHub",
        "Repo hosting: GitHub"
      ]
    },
    {
      "phrase": "versions, and dependencies",
      "phrase_norm": "versions, and dependencies",
      "max_ratio": 11,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [
        "Python installs, virtualenvs, and package pins"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "versions, and dependencies",
        "Python installs, virtualenvs, and package pins"
      ]
    },
    {
      "phrase": "to manage and collaborate on.",
      "phrase_norm": "to manage and collaborate on",
      "max_ratio": 11,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [
        "when more than one person touches the repo."
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "to manage and collaborate on.",
        "when more than one person touches the repo."
      ]
    },
    {
      "phrase": "with HTTP status codes.",
      "phrase_norm": "with http status codes",
      "max_ratio": 11,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#2",
        "try": 1
      },
      "last_seen": {
        "phase": "p#2",
        "try": 1
      },
      "replacements_used": [
        "along with the right status code (400, 404, and so on)"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "with HTTP status codes.",
        "along with the right status code (400, 404, and so on)"
      ]
    },
    {
      "phrase": "requests When a request",
      "phrase_norm": "requests when a request",
      "max_ratio": 11,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#2",
        "try": 2
      },
      "last_seen": {
        "phase": "p#2",
        "try": 2
      },
      "replacements_used": [
        "Rename section *Rejecting bad payloads and open with Failed checks return JSON errors rather than crashing the process* (drops “request” repetition)."
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "requests When a request",
        "Rename section *Rejecting bad payloads and open with Failed checks return JSON errors rather than crashing the process* (drops “request” repetition)."
      ]
    },
    {
      "phrase": "for the chosen language",
      "phrase_norm": "for the chosen language",
      "max_ratio": 10,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [
        "for picking Go over Python and C#"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "for the chosen language",
        "for picking Go over Python and C#"
      ]
    },
    {
      "phrase": "coursework and personal",
      "phrase_norm": "coursework and personal",
      "max_ratio": 10,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [
        "class projects and side repos I already use"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "coursework and personal",
        "class projects and side repos I already use"
      ]
    },
    {
      "phrase": "for everyone? Examples:",
      "phrase_norm": "for everyone? examples",
      "max_ratio": 10,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 2
      },
      "last_seen": {
        "phase": "p#1",
        "try": 2
      },
      "replacements_used": [
        "Split into two sentences: “…what balance remains for each person?” then start examples on the next line with “For instance,” or “Two cases:”."
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "for everyone? Examples:",
        "Split into two sentences: “…what balance remains for each person?” then start examples on the next line with “For instance,” or “Two cases:”."
      ]
    },
    {
      "phrase": "Typing Static typing",
      "phrase_norm": "typing static typing",
      "max_ratio": 10,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 3
      },
      "last_seen": {
        "phase": "p#1",
        "try": 3
      },
      "replacements_used": [
        "Replace the Typing row with a bullet list under *Type checking:* — Go: compile-time checks; Python: types resolved when code runs; C#: CLR static types."
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "Typing Static typing",
        "Replace the Typing row with a bullet list under *Type checking:* — Go: compile-time checks; Python: types resolved when code runs; C#: CLR static types."
      ]
    },
    {
      "phrase": "if CI is",
      "phrase_norm": "if ci is",
      "max_ratio": 9,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [
        "if I add automated tests later,"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "if CI is",
        "if I add automated tests later,"
      ]
    },
    {
      "phrase": "harder to maintain and",
      "phrase_norm": "harder to maintain and",
      "max_ratio": 9,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [
        "tougher to keep consistent and"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "harder to maintain and",
        "tougher to keep consistent and"
      ]
    },
    {
      "phrase": "Build the API",
      "phrase_norm": "build the api",
      "max_ratio": 9,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [
        "Implement the HTTP service"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "Build the API",
        "Implement the HTTP service"
      ]
    },
    {
      "phrase": "Share progress with",
      "phrase_norm": "share progress with",
      "max_ratio": 9,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [
        "Track milestones using"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "Share progress with",
        "Track milestones using"
      ]
    },
    {
      "phrase": "each member in the group",
      "phrase_norm": "each member in the group",
      "max_ratio": 9,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 2
      },
      "last_seen": {
        "phase": "p#1",
        "try": 2
      },
      "replacements_used": [
        "“for every person loaded from the database”"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "each member in the group",
        "“for every person loaded from the database”"
      ]
    },
    {
      "phrase": "Check that required",
      "phrase_norm": "check that required",
      "max_ratio": 9,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#2",
        "try": 2
      },
      "last_seen": {
        "phase": "p#2",
        "try": 2
      },
      "replacements_used": [
        "Step 2 → Run field and range checks on the parsed struct → 400 VALIDATION"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "Check that required",
        "Step 2 → Run field and range checks on the parsed struct → 400 VALIDATION"
      ]
    },
    {
      "phrase": "simplicity and familiarity",
      "phrase_norm": "simplicity and familiarity",
      "max_ratio": 8,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [
        "I'm already comfortable with it"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "simplicity and familiarity",
        "I'm already comfortable with it"
      ]
    },
    {
      "phrase": "How it works (high",
      "phrase_norm": "how it works (high",
      "max_ratio": 8,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [
        "Flow (high level)"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "How it works (high",
        "Flow (high level)"
      ]
    },
    {
      "phrase": "would work for a small",
      "phrase_norm": "would work for a small",
      "max_ratio": 8,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 3
      },
      "last_seen": {
        "phase": "p#1",
        "try": 3
      },
      "replacements_used": [
        "Python's FastAPI could handle this scope, but managing environments…"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "would work for a small",
        "Python's FastAPI could handle this scope, but managing environments…"
      ]
    },
    {
      "phrase": "small REST API",
      "phrase_norm": "small rest api",
      "max_ratio": 7,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [
        "compact HTTP bill-splitter service"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "small REST API",
        "compact HTTP bill-splitter service"
      ]
    },
    {
      "phrase": "and a clear path to",
      "phrase_norm": "and a clear path to",
      "max_ratio": 7,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [
        "and room to grow into"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "and a clear path to",
        "and room to grow into"
      ]
    },
    {
      "phrase": "the product grows",
      "phrase_norm": "the product grows",
      "max_ratio": 7,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [
        "I need multi-user hosting"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "the product grows",
        "I need multi-user hosting"
      ]
    },
    {
      "phrase": "\"person not found",
      "phrase_norm": "person not found",
      "max_ratio": 7,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [
        "\"member not in this group\""
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "\"person not found",
        "\"member not in this group\""
      ]
    },
    {
      "phrase": "the API design, and",
      "phrase_norm": "the api design, and",
      "max_ratio": 7,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 2
      },
      "last_seen": {
        "phase": "p#1",
        "try": 2
      },
      "replacements_used": [
        "“requirements, endpoint layout, and why I chose Go/Fiber”"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "the API design, and",
        "“requirements, endpoint layout, and why I chose Go/Fiber”"
      ]
    },
    {
      "phrase": "each person still",
      "phrase_norm": "each person still",
      "max_ratio": 6,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [
        "what balance remains for everyone"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "each person still",
        "what balance remains for everyone"
      ]
    },
    {
      "phrase": "still efficient for",
      "phrase_norm": "still efficient for",
      "max_ratio": 6,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [
        "fast enough for"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "still efficient for",
        "fast enough for"
      ]
    },
    {
      "phrase": "easier to deploy and",
      "phrase_norm": "easier to deploy and",
      "max_ratio": 6,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [
        "simpler to hand off and"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "easier to deploy and",
        "simpler to hand off and"
      ]
    },
    {
      "phrase": "Python can also",
      "phrase_norm": "python can also",
      "max_ratio": 6,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [
        "I could use Python (FastAPI)"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "Python can also",
        "I could use Python (FastAPI)"
      ]
    },
    {
      "phrase": "if needed later,",
      "phrase_norm": "if needed later",
      "max_ratio": 6,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [
        "down the road,"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "if needed later,",
        "down the road,"
      ]
    },
    {
      "phrase": ".NET runtime environment",
      "phrase_norm": "net runtime environment",
      "max_ratio": 6,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [
        "installed .NET SDK/runtime"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        ".NET runtime environment",
        "installed .NET SDK/runtime"
      ]
    },
    {
      "phrase": "group and returns",
      "phrase_norm": "group and returns",
      "max_ratio": 6,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [
        "group, then outputs"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "group and returns",
        "group, then outputs"
      ]
    },
    {
      "phrase": "at runtime Static",
      "phrase_norm": "at runtime static",
      "max_ratio": 6,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 3
      },
      "last_seen": {
        "phase": "p#1",
        "try": 3
      },
      "replacements_used": [
        "Python cell → \"Dynamic types — errors often surface when the service is running\" (keep C# cell separate)."
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "at runtime Static",
        "Python cell → \"Dynamic types — errors often surface when the service is running\" (keep C# cell separate)."
      ]
    },
    {
      "phrase": "not found\", \"code\":",
      "phrase_norm": "not found\", \"code",
      "max_ratio": 6,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#2",
        "try": 1
      },
      "last_seen": {
        "phase": "p#2",
        "try": 1
      },
      "replacements_used": [
        "Use table columns *Message / Code* for 404 rows (e.g. group not found | NOT_FOUND)."
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "not found\", \"code\":",
        "Use table columns *Message / Code* for 404 rows (e.g. group not found | NOT_FOUND)."
      ]
    },
    {
      "phrase": "and range checks",
      "phrase_norm": "and range checks",
      "max_ratio": 6,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#2",
        "try": 3
      },
      "last_seen": {
        "phase": "p#2",
        "try": 3
      },
      "replacements_used": [
        "Covered by phrase #1 rewrites (remove “range checks” entirely)."
      ],
      "replacements_failed": [
        "Covered by phrase #1 rewrites (remove “range checks” entirely)."
      ],
      "do_not_suggest": [
        "and range checks",
        "Covered by phrase #1 rewrites (remove “range checks” entirely)."
      ]
    },
    {
      "phrase": "the API. Backend",
      "phrase_norm": "the api. backend",
      "max_ratio": 5,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [
        "the HTTP layer. Server-side"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "the API. Backend",
        "the HTTP layer. Server-side"
      ]
    },
    {
      "phrase": "the program Task",
      "phrase_norm": "the program task",
      "max_ratio": 5,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [
        "*Problem / What it solves*"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "the program Task",
        "*Problem / What it solves*"
      ]
    },
    {
      "phrase": "end function Example",
      "phrase_norm": "end function example",
      "max_ratio": 5,
      "status": "persistent",
      "times_flagged": 2,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 2
      },
      "replacements_used": [
        "Separate example from code — use a paragraph after the closing end function instead of inline \"Example:\".",
        "Close the code block, add a blank line, then a separate paragraph: *Worked example:* Dinner $90…"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "end function Example",
        "Separate example from code — use a paragraph after the closing end function instead of inline \"Example:\".",
        "Close the code block, add a blank line, then a separate paragraph: *Worked example:* Dinner $90…"
      ]
    },
    {
      "phrase": "on the version and",
      "phrase_norm": "on the version and",
      "max_ratio": 5,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [
        "about Python/runtime versions and"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "on the version and",
        "about Python/runtime versions and"
      ]
    },
    {
      "phrase": "end if // Step",
      "phrase_norm": "end if // step",
      "max_ratio": 5,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [],
      "replacements_failed": [],
      "do_not_suggest": [
        "end if // Step"
      ]
    },
    {
      "phrase": "as the project grows",
      "phrase_norm": "as the project grows",
      "max_ratio": 5,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [
        "as I add milestones"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "as the project grows",
        "as I add milestones"
      ]
    },
    {
      "phrase": "(name or ID) and",
      "phrase_norm": "name or id) and",
      "max_ratio": 5,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [
        "(display name plus DB id) and"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "(name or ID) and",
        "(display name plus DB id) and"
      ]
    },
    {
      "phrase": "REST client or",
      "phrase_norm": "rest client or",
      "max_ratio": 5,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 2
      },
      "last_seen": {
        "phase": "p#1",
        "try": 2
      },
      "replacements_used": [
        "“HTTP client or”"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "REST client or",
        "“HTTP client or”"
      ]
    },
    {
      "phrase": "HTTP client or",
      "phrase_norm": "http client or",
      "max_ratio": 5,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 3
      },
      "last_seen": {
        "phase": "p#1",
        "try": 3
      },
      "replacements_used": [
        "settlement-pairs list you can read in a JSON viewer or later in a browser UI."
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "HTTP client or",
        "settlement-pairs list you can read in a JSON viewer or later in a browser UI."
      ]
    },
    {
      "phrase": "What each package",
      "phrase_norm": "what each package",
      "max_ratio": 5,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#2",
        "try": 1
      },
      "last_seen": {
        "phase": "p#2",
        "try": 1
      },
      "replacements_used": [
        "*Package and type roles*"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "What each package",
        "*Package and type roles*"
      ]
    },
    {
      "phrase": "Python and C#)· Go:",
      "phrase_norm": "python and c#)· go",
      "max_ratio": 4,
      "status": "persistent",
      "times_flagged": 2,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 2
      },
      "replacements_used": [
        "(Presentation slide only — rewrite slide bullets as full sentences, not compressed )· Go: notation.)",
        "Rewrite the slide as full sentences under headings *Go, Python, C#* — no compressed )· notation."
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "Python and C#)· Go:",
        "(Presentation slide only — rewrite slide bullets as full sentences, not compressed )· Go: notation.)",
        "Rewrite the slide as full sentences under headings *Go, Python, C#* — no compressed )· notation."
      ]
    },
    {
      "phrase": "who owes whom",
      "phrase_norm": "who owes whom",
      "max_ratio": 4,
      "status": "blocklist",
      "times_flagged": 2,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [
        "who should pay whom",
        "(settlement pairs)"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "who owes whom",
        "who should pay whom",
        "(who owes whom)",
        "(settlement pairs)"
      ]
    },
    {
      "phrase": "reverse proxy / load balancer).",
      "phrase_norm": "reverse proxy / load balancer",
      "max_ratio": 4,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [
        "nginx or a cloud load balancer in front of the app)."
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "reverse proxy / load balancer).",
        "nginx or a cloud load balancer in front of the app)."
      ]
    },
    {
      "phrase": "merged into main",
      "phrase_norm": "merged into main",
      "max_ratio": 4,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [
        "merged back to main"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "merged into main",
        "merged back to main"
      ]
    },
    {
      "phrase": "harder to manage and",
      "phrase_norm": "harder to manage and",
      "max_ratio": 4,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [
        "trickier to package and"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "harder to manage and",
        "trickier to package and"
      ]
    },
    {
      "phrase": "in memory. 5. Use",
      "phrase_norm": "in memory. 5. use",
      "max_ratio": 4,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [
        "only in RAM between restarts. For persistence I'll use GORM —"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "in memory. 5. Use",
        "only in RAM between restarts. For persistence I'll use GORM —"
      ]
    },
    {
      "phrase": "as the ORM",
      "phrase_norm": "as the orm",
      "max_ratio": 4,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [
        "for database access"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "as the ORM",
        "for database access"
      ]
    },
    {
      "phrase": "(and optionally add",
      "phrase_norm": "and optionally add",
      "max_ratio": 4,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [
        "(and add a UI later if I want)"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "(and optionally add",
        "(and add a UI later if I want)"
      ]
    },
    {
      "phrase": "each id in",
      "phrase_norm": "each id in",
      "max_ratio": 4,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [
        "every participant id in"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "each id in",
        "every participant id in"
      ]
    },
    {
      "phrase": "Implement the HTTP",
      "phrase_norm": "implement the http",
      "max_ratio": 4,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 2
      },
      "last_seen": {
        "phase": "p#1",
        "try": 2
      },
      "replacements_used": [
        "“Stand up the Go web layer with *Fiber v2*”"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "Implement the HTTP",
        "“Stand up the Go web layer with *Fiber v2*”"
      ]
    },
    {
      "phrase": "Parse JSON → if",
      "phrase_norm": "parse json → if",
      "max_ratio": 4,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#2",
        "try": 1
      },
      "last_seen": {
        "phase": "p#2",
        "try": 1
      },
      "replacements_used": [
        "Read the request body as JSON; malformed syntax yields 400 BAD_REQUEST"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "Parse JSON → if",
        "Read the request body as JSON; malformed syntax yields 400 BAD_REQUEST"
      ]
    },
    {
      "phrase": "Point at 1-2",
      "phrase_norm": "point at 1-2",
      "max_ratio": 4,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#2",
        "try": 1
      },
      "last_seen": {
        "phase": "p#2",
        "try": 1
      },
      "replacements_used": [
        "Highlight one or two functions on the slide (e.g. CreateCharge, settle.Compute)"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "Point at 1-2",
        "Highlight one or two functions on the slide (e.g. CreateCharge, settle.Compute)"
      ]
    },
    {
      "phrase": "group not found",
      "phrase_norm": "group not found",
      "max_ratio": 4,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#2",
        "try": 2
      },
      "last_seen": {
        "phase": "p#2",
        "try": 2
      },
      "replacements_used": [
        "Table *Message* column: no group with that ID / unknown group ID (only if you are willing to change handler copy; otherwise keep API truth and accept the flag)."
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "group not found",
        "Table *Message* column: no group with that ID / unknown group ID (only if you are willing to change handler copy; otherwise keep API truth and accept the flag)."
      ]
    },
    {
      "phrase": "this project plan).",
      "phrase_norm": "this project plan",
      "max_ratio": 3,
      "status": "blocklist",
      "times_flagged": 3,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [
        "the MVP scope).",
        "MVP scope)",
        "the MVP write-up"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "this project plan).",
        "the MVP scope).",
        "this project plan)",
        "MVP scope)",
        "this project plan",
        "the MVP write-up"
      ]
    },
    {
      "phrase": "for lower memory",
      "phrase_norm": "for lower memory",
      "max_ratio": 3,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [
        "with smaller per-request allocations"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "for lower memory",
        "with smaller per-request allocations"
      ]
    },
    {
      "phrase": "apps are often",
      "phrase_norm": "apps are often",
      "max_ratio": 3,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 1
      },
      "last_seen": {
        "phase": "p#1",
        "try": 1
      },
      "replacements_used": [
        "real services are usually"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "apps are often",
        "real services are usually"
      ]
    },
    {
      "phrase": "or nginx or",
      "phrase_norm": "or nginx or",
      "max_ratio": 3,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 2
      },
      "last_seen": {
        "phase": "p#1",
        "try": 2
      },
      "replacements_used": [
        "“Fiber ListenTLS, a reverse proxy, or platform-managed TLS).”"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "or nginx or",
        "“Fiber ListenTLS, a reverse proxy, or platform-managed TLS).”"
      ]
    },
    {
      "phrase": "remains for each",
      "phrase_norm": "remains for each",
      "max_ratio": 3,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#1",
        "try": 3
      },
      "last_seen": {
        "phase": "p#1",
        "try": 3
      },
      "replacements_used": [
        "who still owes money after splitting fairly?"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "remains for each",
        "who still owes money after splitting fairly?"
      ]
    },
    {
      "phrase": "response body: [\"error\":",
      "phrase_norm": "response body: [\"error",
      "max_ratio": 3,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#2",
        "try": 1
      },
      "last_seen": {
        "phase": "p#2",
        "try": 1
      },
      "replacements_used": [
        "*Sample validation failure:*"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "response body: [\"error\":",
        "*Sample validation failure:*"
      ]
    },
    {
      "phrase": "from different inputs",
      "phrase_norm": "from different inputs",
      "max_ratio": 3,
      "status": "blocklist",
      "times_flagged": 1,
      "first_seen": {
        "phase": "p#2",
        "try": 1
      },
      "last_seen": {
        "phase": "p#2",
        "try": 1
      },
      "replacements_used": [
        "*Sample runs — good requests and failures*"
      ],
      "replacements_failed": [],
      "do_not_suggest": [
        "from different inputs",
        "*Sample runs — good requests and failures*"
      ]
    }
  ]
}
