configuration/principle/data/anti-pattern.data.json

configuration/principle/data/anti-pattern.data.json continued, part 2 of 2.

            "formed_by": "Build deep request-time chains across services or modules, making latency, availability, and failure behavior multiplicative.",
            "detected_by": [
                "sync_depth_above_threshold",
                "request_path_many_remote_calls",
                "cascading_timeout"
            ],
            "measured_by": ["synchronous call depth per request path"],
            "refactored_by": [
                "lexicon:coarse-grained-endpoint",
                "lexicon:introduce-async-event",
                "lexicon:query-projection",
                "architecture:timeout-pattern",
                "architecture:bulkhead-pattern"
            ],
            "enforced_by": [
                "call-depth limits in architecture review",
                "timeout and bulkhead policies"
            ],
            "severity": "discouraged",
            "exemplar": {
                "before": "const foo = await a();\nconst bar = await b(foo);\nconst baz = await c(bar);\nreturn slowSyncCall(a, b, c);",
                "after": "const [foo, bar, baz] = await Promise.all([a(), b(), c()]);",
                "lang": "ts"
            }
        },
        {
            "id": "chatty-interface",
            "name": "Chatty Interface",
            "definition": "A defect in which one operation needs many small remote calls.",
            "type": "anti-pattern",
            "scope": [
                "modularity",
                "contract_compatibility"
            ],
            "requires": [],
            "reinforces": [],
            "enables": [],
            "conflicts_with": [],
            "tensions_with": [],
            "formed_by": "Require many small remote calls to complete one user or business operation.",
            "detected_by": [
                "N_plus_1_API_calls",
                "many_calls_per_screen",
                "loop_contains_remote_call"
            ],
            "measured_by": ["remote calls per user operation"],
            "refactored_by": [
                "lexicon:coarse-grained-endpoint",
                "lexicon:query-projection",
                "lexicon:batch-fetch"
            ],
            "enforced_by": [
                "API review",
                "performance tests that bound call counts"
            ],
            "severity": "discouraged",
            "exemplar": {
                "before": "const results = [];\nfor (const id of fooIds) results.push(await fooApi.get(id));",
                "after": "const results = await fooApi.getMany(fooIds);",
                "lang": "ts"
            }
        },
        {
            "id": "n-plus-one-query",
            "name": "N Plus One Query",
            "aliases": ["N+1 Query"],
            "definition": "A defect in which a collection is fetched and then one further query is issued per item.",
            "type": "anti-pattern",
            "scope": ["architecture_evolution"],
            "requires": [],
            "reinforces": [],
            "enables": [],
            "conflicts_with": [],
            "tensions_with": [],
            "formed_by": "Fetch a collection, then issue one query or remote call per item rather than fetching required related data intentionally.",
            "detected_by": [
                "query_inside_loop",
                "remote_call_inside_loop",
                "query_count_scales_with_rows"
            ],
            "measured_by": ["queries per request as the row count grows"],
            "refactored_by": [
                "lexicon:batch-fetch",
                "lexicon:query-projection"
            ],
            "enforced_by": ["query-count assertions in integration tests"],
            "severity": "discouraged",
            "exemplar": {
                "before": "const foos = await fooStore.all();\nfor (const foo of foos) foo.bar = await barStore.find(foo.barId);",
                "after": "const foos = await fooStore.all();\nconst bars = await barStore.findMany(foos.map(f => f.barId));",
                "lang": "ts"
            }
        },
        {
            "id": "cache-poisoning-by-design",
            "name": "Cache Poisoning by Design",
            "definition": "A defect in which a cache key omits an input the entry depends on, so one request is served another's result.",
            "type": "anti-pattern",
            "scope": [
                "correctness_verification",
                "security_governance"
            ],
            "requires": [],
            "reinforces": [],
            "enables": [],
            "conflicts_with": [],
            "tensions_with": [],
            "formed_by": "Cache data without key correctness, tenant isolation, authorization context, invalidation, or schema version, or key the entry by time or lifetime alone.",
            "detected_by": [
                "cache_key_missing_user_or_tenant",
                "cache_without_version",
                "cache_keyed_by_time",
                "no_invalidation",
                "authorization_not_in_cache_key"
            ],
            "measured_by": [
                "cache keys missing tenant",
                "identity or version"
            ],
            "refactored_by": [
                "lexicon:cache-contract",
                "lexicon:context-keyed-cache",
                "lexicon:cache-invalidation-on-write",
                "architecture:versioning"
            ],
            "enforced_by": [
                "cache-key review",
                "tests that vary tenant and version"
            ],
            "severity": "discouraged",
            "exemplar": {
                "before": "fooCache.set(request.path, response);",
                "after": "if (response.ok && response.cacheable) {\n  fooCache.set(cacheKey(request.identity, request.path, fingerprint(request.inputs, SCHEMA_VERSION)), response);\n}",
                "lang": "ts"
            }
        },
        {
            "id": "retry-storm",
            "name": "Retry Storm",
            "definition": "A defect in which clients retry a failing dependency so aggressively that the retries prolong the failure.",
            "type": "anti-pattern",
            "scope": ["resilience_recovery"],
            "requires": [],
            "reinforces": [],
            "enables": [],
            "conflicts_with": [],
            "tensions_with": [],
            "formed_by": "Allow many clients or workers to retry failed dependencies aggressively and synchronously, increasing pressure on the failing system.",
            "detected_by": [
                "no_backoff",
                "no_jitter",
                "unbounded_retries",
                "retry_on_non_idempotent_operation"
            ],
            "measured_by": [
                "retries per failed call",
                "retry share of load during incidents"
            ],
            "refactored_by": [
                "lexicon:bounded-retry",
                "lexicon:backoff",
                "lexicon:jitter",
                "architecture:circuit-breaker-pattern",
                "lexicon:idempotency-key"
            ],
            "enforced_by": ["a resilience policy that requires bounded retries with backoff and jitter"],
            "severity": "discouraged",
            "exemplar": {
                "before": "while (true) { try { return await call(); } catch { } }",
                "after": "return retry(call, { attempts: 5, backoff: exponentialJitter(), giveUp: dlq });",
                "lang": "ts"
            }
        },
        {
            "id": "timeout-omission",
            "name": "Timeout Omission",
            "definition": "A defect in which calls to external systems carry no timeout, cancellation or deadline, so a caller can wait for ever on work that never completes.",
            "aliases": ["Infinite Wait"],
            "type": "anti-pattern",
            "scope": ["resilience_recovery"],
            "requires": [],
            "reinforces": [],
            "enables": [],
            "conflicts_with": [],
            "tensions_with": [],
            "formed_by": "Call external systems without explicit timeouts, cancellation, or deadline propagation.",
            "detected_by": [
                "HTTP_call_without_timeout",
                "DB_query_without_timeout",
                "missing_cancellation_token",
                "no_deadline_propagation"
            ],
            "measured_by": ["outbound calls without a timeout"],
            "refactored_by": [
                "architecture:timeout-pattern",
                "lexicon:deadline-propagation",
                "lexicon:cancellation",
                "lexicon:fail-fast-or-fall-back"
            ],
            "enforced_by": ["a lint rule that requires a timeout on outbound calls"],
            "severity": "discouraged",
            "exemplar": {
                "before": "const foo = await fetch(fooUrl);",
                "after": "const foo = await fetch(fooUrl, { signal: AbortSignal.timeout(5000) });",
                "lang": "ts"
            }
        },
        {
            "id": "missing-backpressure",
            "name": "Missing Backpressure",
            "definition": "A defect in which a system accepts work faster than it can process it, with no limit or shedding.",
            "aliases": ["Unbounded Ingestion"],
            "type": "anti-pattern",
            "scope": ["resilience_recovery"],
            "requires": [],
            "reinforces": [],
            "enables": [],
            "conflicts_with": [],
            "tensions_with": [],
            "formed_by": "Accept work faster than the system can process it without queue limits, admission control, rate limits, or shedding.",
            "detected_by": [
                "unbounded_queue",
                "no_rate_limit",
                "no_admission_control",
                "memory_grows_with_load"
            ],
            "measured_by": ["queue depth and memory growth under load"],
            "refactored_by": [
                "lexicon:bounded-queue",
                "architecture:rate-limiting",
                "lexicon:load-shedding",
                "architecture:backpressure"
            ],
            "enforced_by": [
                "load tests",
                "checks that every queue is configured with a bound"
            ],
            "severity": "discouraged",
            "exemplar": {
                "before": "stream.on(\"data\", d => queue.push(process(d)));",
                "after": "stream.pipe(new BoundedFooProcessor({ highWaterMark: 100 }));",
                "lang": "ts"
            }
        },
        {
            "id": "silent-data-corruption",
            "name": "Silent Data Corruption",
            "definition": "A defect in which invalid data is accepted, transformed or stored without any check noticing.",
            "type": "anti-pattern",
            "scope": [
                "contract_compatibility",
                "correctness_verification"
            ],
            "requires": [],
            "reinforces": [],
            "enables": [],
            "conflicts_with": [],
            "tensions_with": [],
            "formed_by": "Accept, transform, or persist invalid data without validation, checksums, invariants, reconciliation, or audit.",
            "detected_by": [
                "missing_boundary_validation",
                "no_invariant_check",
                "impossible_state_in_database",
                "reconciliation_failures"
            ],
            "measured_by": ["invariant violations and reconciliation mismatches"],
            "refactored_by": [
                "lexicon:validate-at-the-boundary",
                "lexicon:invariant-check",
                "lexicon:reconciliation-job",
                "lexicon:data-change-audit"
            ],
            "enforced_by": [
                "boundary validation",
                "invariant checks",
                "reconciliation jobs"
            ],
            "severity": "discouraged",
            "exemplar": {
                "before": "const total = Number(a) + Number(b);\nsave(total);",
                "after": "const total = Money.add(Money.parse(a), Money.parse(b));\nsave(total);",
                "lang": "ts"
            }
        },
        {
            "id": "lost-update",
            "name": "Lost Update",
            "aliases": ["Whole-File Write Race"],
            "definition": "A defect in which concurrent writers overwrite each other's changes without a version check.",
            "type": "anti-pattern",
            "scope": ["state_transaction"],
            "requires": [],
            "reinforces": [],
            "enables": [],
            "conflicts_with": [],
            "tensions_with": [],
            "formed_by": "Allow concurrent writers to overwrite each other without version checks, locks, compare-and-swap, or transaction isolation.",
            "detected_by": [
                "last_write_wins_without_version",
                "no_optimistic_lock",
                "concurrent_update_defects"
            ],
            "measured_by": ["concurrent update conflicts found in tests"],
            "refactored_by": [
                "architecture:optimistic-locking",
                "architecture:pessimistic-locking",
                "lexicon:merge-policy",
                "lexicon:transaction-isolation-level"
            ],
            "enforced_by": [
                "optimistic-locking checks",
                "concurrency tests"
            ],
            "severity": "discouraged",
            "exemplar": {
                "before": "const foo = await load(id);\nfoo.count += 1;\nawait save(foo);",
                "after": "await fooStore.update(id, { count: increment(1) }, { expectedVersion: foo.version });",
                "lang": "ts"
            }
        },
        {
            "id": "dual-write",
            "name": "Dual Write",
            "definition": "A defect in which related state is written to two systems with no atomicity or compensation.",
            "type": "anti-pattern",
            "scope": ["event_messaging"],
            "requires": [],
            "reinforces": [],
            "enables": [],
            "conflicts_with": [],
            "tensions_with": [],
            "formed_by": "Write related state to two systems without atomicity, outbox, saga, reconciliation, or compensation.",
            "detected_by": [
                "database_write_then_message_publish",
                "two_databases_updated_without_transaction_or_outbox",
                "manual_repair_needed"
            ],
            "measured_by": ["writes to two systems outside one transaction or outbox"],
            "refactored_by": [
                "architecture:outbox-pattern",
                "architecture:saga-pattern",
                "architecture:idempotent-consumer",
                "lexicon:reconciliation-job"
            ],
            "enforced_by": [
                "an outbox or saga",
                "verified by integration tests"
            ],
            "severity": "discouraged",
            "exemplar": {
                "before": "await db.save(foo);\nawait searchIndex.add(foo);",
                "after": "await db.save(foo);\nawait outbox.append(fooCreatedEvent(foo));",
                "lang": "ts"
            }
        },
        {
            "id": "read-your-writes-violation",
            "name": "Read-Your-Writes Violation",
            "definition": "A defect in which a writer reads back a stale copy of what it has just written.",
            "type": "anti-pattern",
            "scope": ["contract_compatibility"],
            "requires": [],
            "reinforces": [],
            "enables": [],
            "conflicts_with": [],
            "tensions_with": [],
            "formed_by": "Let users or processes perform a write and then read from a stale replica, cache, projection, or eventually consistent view without explicit consistency contract.",
            "detected_by": [
                "write_then_stale_read_defect",
                "cache_not_invalidated_after_write",
                "replica_read_after_write"
            ],
            "measured_by": ["stale reads observed after writes"],
            "refactored_by": [
                "lexicon:read-from-primary-after-write",
                "lexicon:cache-invalidation-on-write",
                "lexicon:consistency-contract"
            ],
            "enforced_by": ["consistency-contract tests that read after a write"],
            "severity": "discouraged",
            "exemplar": {
                "before": "await primaryDb.write(foo);\nconst view = await replicaDb.read(foo.id);",
                "after": "await primaryDb.write(foo);\nconst view = await readAfterWrite(foo.id, { consistency: \"read-your-writes\" });",
                "lang": "ts"
            }
        },
        {
            "id": "security-theater",
            "name": "Security Theater",
            "definition": "A defect in which visible security controls leave the real threat unreduced, or can be bypassed.",
            "type": "anti-pattern",
            "scope": [
                "security_governance",
                "model_governance"
            ],
            "requires": [],
            "reinforces": [],
            "enables": [],
            "conflicts_with": [],
            "tensions_with": [],
            "formed_by": "Add visible security controls that do not reduce the actual threat model or can be bypassed by alternate paths.",
            "detected_by": [
                "control_not_linked_to_threat",
                "bypass_endpoint",
                "client_only_security",
                "audit_passes_but_attack_succeeds"
            ],
            "measured_by": [
                "controls not linked to a threat",
                "bypass paths found"
            ],
            "refactored_by": [
                "architecture:threat-modeling",
                "lexicon:server-side-enforcement",
                "lexicon:penetration-testing",
                "architecture:policy-as-code"
            ],
            "enforced_by": [
                "threat-model review",
                "penetration tests"
            ],
            "severity": "discouraged",
            "exemplar": {
                "before": "if (password.length > 0) grantFooAccess(user);",
                "after": "const verified = await verifyPassword(password, user.passwordHash);\nif (!verified) throw new UnauthorizedError();\ngrantFooAccess(user);",
                "lang": "ts"
            }
        },
        {
            "id": "authorization-scattering",
            "name": "Authorization Scattering",
            "definition": "A defect in which authorization checks are spread across layers with no central policy.",
            "type": "anti-pattern",
            "scope": [
                "security_governance",
                "model_governance"
            ],
            "requires": [],
            "reinforces": [],
            "enables": [],
            "conflicts_with": [],
            "tensions_with": [],
            "formed_by": "Spread authorization checks across controllers, services, repositories, UI, and ad hoc conditionals without a central policy model.",
            "detected_by": [
                "repeated_role_checks",
                "missing_policy_engine",
                "endpoint_without_authz",
                "inconsistent_resource_access"
            ],
            "measured_by": [
                "endpoints without a policy check",
                "duplicated role checks"
            ],
            "refactored_by": [
                "lexicon:centralize-policy",
                "architecture:policy-as-code",
                "architecture:attribute-based-access-control",
                "architecture:role-based-access-control",
                "lexicon:authorization-tests"
            ],
            "enforced_by": ["a policy engine, with authorization tests per endpoint"],
            "severity": "discouraged",
            "exemplar": {
                "before": "if (user.role === \"admin\") deleteFoo();\nif (user.role === \"admin\" || user.id === foo.owner) editFoo();",
                "after": "if (policy.can(user, \"delete\", foo)) deleteFoo();\nif (policy.can(user, \"edit\", foo)) editFoo();",
                "lang": "ts"
            }
        },
        {
            "id": "secret-sprawl",
            "name": "Secret Sprawl",
            "definition": "A defect in which credentials and keys are stored across code, logs and configuration.",
            "type": "anti-pattern",
            "scope": [
                "modularity",
                "security_governance"
            ],
            "requires": [],
            "reinforces": [],
            "enables": [],
            "conflicts_with": [],
            "tensions_with": [],
            "formed_by": "Store credentials, tokens, keys, certificates, or sensitive configuration across code, config files, logs, tickets, and local environments.",
            "detected_by": [
                "secret_in_repo",
                "secret_in_log",
                "shared_static_token",
                "manual_secret_distribution"
            ],
            "measured_by": ["secrets found in source and logs"],
            "refactored_by": [
                "architecture:secrets-management",
                "lexicon:secret-rotation",
                "lexicon:repository-secret-scan",
                "lexicon:least-privilege-credential"
            ],
            "enforced_by": [
                "secret scanning in the build",
                "a secret store"
            ],
            "severity": "discouraged",
            "exemplar": {
                "before": "const key = \"sk_live_abc123\";\nconst dbPass = \"hunter2\";",
                "after": "const key = await secrets.get(\"foo.api.key\");\nconst dbPass = await secrets.get(\"foo.db.password\");",
                "lang": "ts"
            }
        },
        {
            "id": "personal-data-oversharing",
            "name": "Personal Data Oversharing",
            "definition": "A defect in which more personal data is collected, kept, logged or exposed than the declared purpose needs.",
            "aliases": ["Unbounded Data Collection"],
            "type": "anti-pattern",
            "scope": ["architecture_evolution"],
            "requires": [],
            "reinforces": [],
            "enables": [],
            "conflicts_with": [],
            "tensions_with": [],
            "formed_by": "Collect, store, log, transmit, or expose more personal data than needed for the declared purpose.",
            "detected_by": [
                "personal_data_in_logs",
                "unused_sensitive_fields",
                "broad_export",
                "missing_data_minimization"
            ],
            "measured_by": ["personal-data fields in logs and exports"],
            "refactored_by": [
                "lexicon:purpose-binding",
                "lexicon:field-redaction",
                "lexicon:retention-policy"
            ],
            "enforced_by": [
                "privacy review",
                "log redaction rules"
            ],
            "severity": "discouraged",
            "exemplar": {
                "before": "logger.info(\"created foo\", { email: user.email, ssn: user.ssn });",
                "after": "logger.info(\"created foo\", { userId: user.id });",
                "lang": "ts"
            }
        },
        {
            "id": "observability-noise",
            "name": "Observability Noise",
            "definition": "A defect in which logs, metrics and alerts are too many and too low in signal to act on.",
            "type": "anti-pattern",
            "scope": ["observability_traceability"],
            "requires": [],
            "reinforces": [],
            "enables": [],
            "conflicts_with": [],
            "tensions_with": [],
            "formed_by": "Emit excessive, low-signal logs, metrics, traces, or alerts without severity, ownership, cardinality control, or actionability.",
            "detected_by": [
                "high_alert_ack_without_action",
                "high_cardinality_metrics",
                "logs_without_context",
                "duplicate_alerts"
            ],
            "measured_by": [
                "alerts acknowledged without action",
                "high-cardinality metrics"
            ],
            "refactored_by": [
                "lexicon:define-signal-quality",
                "lexicon:cardinality-reduction",
                "lexicon:runbook-owner",
                "lexicon:sampling-and-aggregation"
            ],
            "enforced_by": [
                "alert-ownership rules",
                "metric cardinality limits"
            ],
            "severity": "discouraged",
            "exemplar": {
                "before": "logger.info(\"entering loop\");\nfor (const f of foos) logger.info(\"iter\", f);",
                "after": "logger.info(\"foo.batch.processed\", { count: foos.length, durationMs });",
                "lang": "ts"
            }
        },
        {
            "id": "log-as-control-flow",
            "name": "Log-as-Control-Flow",
            "definition": "A defect in which a failure is logged as though logging handled it, and execution continues.",
            "type": "anti-pattern",
            "scope": [
                "correctness_verification",
                "resilience_recovery"
            ],
            "requires": [],
            "reinforces": [],
            "enables": [],
            "conflicts_with": [],
            "tensions_with": [],
            "formed_by": "Log errors or warnings as if logging itself handles the failure, while the system continues without recovery, propagation, or safe fallback.",
            "detected_by": [
                "catch_log_continue",
                "logged_error_without_return_or_throw",
                "critical_log_no_alert"
            ],
            "measured_by": ["catch blocks that log and continue"],
            "refactored_by": [
                "lexicon:introduce-typed-result",
                "lexicon:fail-fast-or-fall-back",
                "lexicon:recovery-policy",
                "lexicon:alert-on-critical-failure"
            ],
            "enforced_by": ["a lint rule against catch blocks that only log"],
            "severity": "discouraged",
            "exemplar": {
                "before": "try { await chargeFoo(foo); } catch (error) { logger.error(\"foo.charge.failed\", error); }\nshipFoo(foo);",
                "after": "const outcome = await chargeFoo(foo);\nif (!outcome.ok) throw new ChargeFailedError(foo.id, outcome.error);\nshipFoo(foo);",
                "lang": "ts"
            }
        },
        {
            "id": "manual-runbook-dependency",
            "name": "Manual Runbook Dependency",
            "definition": "A defect in which repeatable operational steps, such as detecting a failure and recovering from it, are performed by hand during incidents and deploys, so recovery waits on a person.",
            "aliases": [
                "Manual-Only Recovery",
                "Manual Intervention Dependency"
            ],
            "type": "anti-pattern",
            "scope": ["resilience_recovery"],
            "requires": [],
            "reinforces": [],
            "enables": [],
            "conflicts_with": [],
            "tensions_with": [],
            "formed_by": "Perform by hand the repeatable operational actions during incidents, deploys, migrations, or recovery.",
            "detected_by": [
                "same_manual_incident_steps",
                "manual_migration_sequence",
                "operator_specific_knowledge"
            ],
            "measured_by": ["manual steps repeated across incidents"],
            "refactored_by": [
                "lexicon:automate-the-runbook",
                "lexicon:guardrails",
                "lexicon:precondition-check",
                "lexicon:execution-log"
            ],
            "enforced_by": ["operations review of manual steps repeated across incidents"],
            "severity": "discouraged",
            "exemplar": {
                "before": "const RUNBOOK = \"on failure, ssh in and run restart-foo.sh\";",
                "after": "health.onUnhealthy(() => orchestrator.restart(\"foo\"));",
                "lang": "ts"
            }
        },
        {
            "id": "big-bang-release",
            "name": "Big-Bang Release",
            "definition": "A defect in which a large, irreversible change reaches every user at once, with no staged rollout.",
            "aliases": ["Big-Bang Deployment"],
            "type": "anti-pattern",
            "scope": ["state_transaction"],
            "requires": [],
            "reinforces": [],
            "enables": [],
            "conflicts_with": [],
            "tensions_with": [],
            "formed_by": "Ship a large, irreversible, all-user change without staged rollout, feature flags, canary, rollback, or blast-radius control.",
            "detected_by": [
                "no_canary",
                "no_feature_flag",
                "no_rollback_plan",
                "large_release_batch"
            ],
            "measured_by": [
                "release batch size",
                "releases without a rollback path"
            ],
            "refactored_by": [
                "architecture:feature-toggle",
                "architecture:canary-deployment",
                "architecture:blue-green-deployment",
                "lexicon:rollback-plan",
                "lexicon:small-batch-release"
            ],
            "enforced_by": ["release gates that require a canary or a feature flag and a rollback plan"],
            "severity": "discouraged",
            "exemplar": {
                "before": "deployEverything(\"foo\", \"bar\", \"baz\");",
                "after": "release(\"foo\", { strategy: canary(0.1) });",
                "lang": "ts"
            }
        },
        {
            "id": "irreversible-migration",
            "name": "Irreversible Migration",
            "definition": "A defect in which a schema or data change can neither run beside the old version nor be rolled back.",
            "type": "anti-pattern",
            "scope": [
                "contract_compatibility",
                "architecture_evolution"
            ],
            "requires": [],
            "reinforces": [],
            "enables": [],
            "conflicts_with": [],
            "tensions_with": [],
            "formed_by": "Apply schema, data, or infrastructure changes that cannot safely run alongside old versions or be rolled back.",
            "detected_by": [
                "drop_column_before_consumers_removed",
                "destructive_data_transform_no_backup",
                "no_backward_compatible_phase"
            ],
            "measured_by": ["migrations without a down step or a compatible phase"],
            "refactored_by": [
                "lexicon:expand-contract-migration",
                "lexicon:backup",
                "lexicon:dual-read-and-write",
                "lexicon:rollback-plan"
            ],
            "enforced_by": [
                "migration review",
                "rollback tests"
            ],
            "severity": "discouraged",
            "exemplar": {
                "before": "await db.exec(\"ALTER TABLE foo DROP COLUMN legacy_name\");",
                "after": "await migrate({ up: addFooName, down: restoreFooName });",
                "lang": "ts"
            }
        },
        {
            "id": "big-upfront-frozen-architecture",
            "distinctFrom": [
                {
                    "id": "architecture:lava-flow",
                    "reason": "Frozen architecture fixes decisions too early, while lava flow keeps obsolete code too long."
                },
                {
                    "id": "architecture:premature-abstraction",
                    "reason": "Frozen architecture fixes system-level decisions early, while premature abstraction extracts one shared abstraction early."
                },
                {
                    "id": "architecture:zombie-code",
                    "reason": "Frozen architecture is a decision made too early, while zombie code is dead code left behind."
                }
            ],
            "name": "Big-Upfront Frozen Architecture",
            "definition": "A defect in which major architectural decisions are fixed before the forces they answer are known.",
            "type": "anti-pattern",
            "scope": ["domain_boundary"],
            "requires": [],
            "reinforces": [],
            "enables": [],
            "conflicts_with": [],
            "tensions_with": [],
            "formed_by": "Lock in major architectural decisions before validating domain forces, quality attributes, operational realities, and change vectors.",
            "detected_by": [
                "heavy_architecture_before_usage",
                "ADR_without_evidence",
                "future-proofing_without_feedback"
            ],
            "measured_by": ["decisions recorded without evidence"],
            "refactored_by": [
                "architecture:minimum-viable-architecture",
                "architecture:evolutionary-architecture",
                "architecture:fitness-functions",
                "lexicon:decision-review"
            ],
            "enforced_by": [
                "decision records that require evidence",
                "periodic decision review"
            ],
            "severity": "discouraged",
            "exemplar": {
                "before": "const ARCHITECTURE = designAllModulesForNextFiveYears();",
                "after": "const foo = defineModule(\"foo\", { exports: { createFoo } });\nregistry.add(foo);",
                "lang": "ts"
            }
        },
        {
            "id": "architecture-astronaut",
            "distinctFrom": [
                {
                    "id": "architecture:over-abstraction",
                    "reason": "An astronaut builds frameworks for needs that have not arrived, while over-abstraction adds layers beyond the variation that exists."
                },
                {
                    "id": "architecture:speculative-generality",
                    "reason": "An astronaut builds whole frameworks and meta-models, while speculative generality is one abstraction built for variation with no evidence of arriving."
                }
            ],
            "name": "Architecture Astronaut",
            "definition": "A defect in which abstract frameworks, meta-models and architectural structure are built ahead of the concrete needs they should serve.",
            "aliases": ["Over-Architecture"],
            "type": "anti-pattern",
            "scope": [
                "model_governance",
                "domain_boundary"
            ],
            "requires": [],
            "reinforces": [],
            "enables": [],
            "conflicts_with": [],
            "tensions_with": [],
            "formed_by": "Prefer abstract frameworks, taxonomies, meta-models, and generic engines over concrete user, domain, and operational needs.",
            "detected_by": [
                "generic_platform_before_product_need",
                "few_real_consumers",
                "high_framework_workaround_count"
            ],
            "measured_by": ["generic components with few real consumers"],
            "refactored_by": [
                "lexicon:anchor-to-use-cases",
                "lexicon:vertical-slice-proof",
                "lexicon:inline-abstraction",
                "lexicon:measure-delivery-cost"
            ],
            "enforced_by": ["design review against real use cases"],
            "severity": "discouraged",
            "exemplar": {
                "before": "class AbstractFooMetaStrategyOrchestrationEngineFactory {}",
                "after": "class CreateFoo { execute(input: CreateFooInput): Foo {} }",
                "lang": "ts"
            }
        },
        {
            "id": "feature-only-design",
            "name": "Feature-Only Design",
            "definition": "A defect in which architecture serves immediate features while its quality attributes go unaddressed.",
            "type": "anti-pattern",
            "scope": [
                "security_governance",
                "performance_scaling"
            ],
            "requires": [],
            "reinforces": [],
            "enables": [],
            "conflicts_with": [],
            "tensions_with": [],
            "formed_by": "Optimize architecture for immediate feature delivery while ignoring quality attributes such as security, operability, scalability, maintainability, and evolvability.",
            "detected_by": [
                "no_SLOs",
                "no_security_review",
                "no_operability_requirements",
                "quality_attribute_absent_from_ADR"
            ],
            "measured_by": [
                "quality attributes absent from decisions",
                "services without SLOs"
            ],
            "refactored_by": [
                "lexicon:quality-scenarios",
                "architecture:fitness-functions",
                "architecture:architecture-review",
                "lexicon:risk-register"
            ],
            "enforced_by": [
                "architecture review with quality scenarios",
                "SLO gates"
            ],
            "severity": "discouraged",
            "exemplar": {
                "before": "function addFooFeature() { hack(); patch(); bypassLint(); }",
                "after": "function addFooFeature(input: CreateFooInput) { return createFoo.execute(input); }",
                "lang": "ts"
            }
        },
        {
            "id": "test-pyramid-inversion",
            "name": "Test Pyramid Inversion",
            "definition": "A defect in which a test suite relies mainly on slow end-to-end tests, with few unit and contract tests.",
            "type": "anti-pattern",
            "scope": ["contract_compatibility"],
            "requires": [],
            "reinforces": [],
            "enables": [],
            "conflicts_with": [],
            "tensions_with": [],
            "formed_by": "Rely mainly on slow, brittle end-to-end tests while unit, contract, component, and property tests are sparse.",
            "detected_by": [
                "high_E2E_ratio",
                "slow_CI",
                "flaky_integration_tests",
                "low_unit_contract_coverage"
            ],
            "measured_by": [
                "share of end-to-end tests",
                "suite duration"
            ],
            "refactored_by": [
                "lexicon:unit-tests",
                "lexicon:contract-testing",
                "lexicon:component-tests",
                "architecture:property-based-testing"
            ],
            "enforced_by": [
                "test-suite composition review",
                "limits on CI duration"
            ],
            "severity": "discouraged",
            "exemplar": {
                "before": "test.e2e(\"create foo\", fullBrowserFlow);\ntest.e2e(\"rename foo\", fullBrowserFlow);\ntest.e2e(\"delete foo\", fullBrowserFlow);",
                "after": "test.unit(\"FooValidator rejects an empty name\", () => expect(() => validateFoo({ name: \"\" })).toThrow());\ntest.integration(\"FooRepository persists a Foo\", async () => {\n  await fooRepository.save(foo);\n  expect(await fooRepository.find(foo.id)).toEqual(foo);\n});\ntest.e2e(\"the critical signup path\", criticalPathOnly);",
                "lang": "ts"
            }
        },
        {
            "id": "mock-mirage",
            "name": "Mock Mirage",
            "definition": "A defect in which tests assert calls on mocks rather than observable behavior or contracts.",
            "type": "anti-pattern",
            "scope": [
                "contract_compatibility",
                "correctness_verification",
                "observability_traceability"
            ],
            "requires": [],
            "reinforces": [],
            "enables": [],
            "conflicts_with": [],
            "tensions_with": [],
            "formed_by": "Overuse mocks so tests verify internal calls rather than observable behavior or contracts.",
            "detected_by": [
                "tests_fail_on_refactor_without_behavior_change",
                "assert_called_everywhere",
                "no_contract_tests"
            ],
            "measured_by": ["tests that break on refactors with no change in behavior"],
            "refactored_by": [
                "lexicon:test-observable-behavior",
                "lexicon:contract-testing",
                "lexicon:fake-at-the-boundary"
            ],
            "enforced_by": [
                "contract tests",
                "review of mock usage"
            ],
            "severity": "discouraged",
            "exemplar": {
                "before": "const store = { save: fn(), find: fn().returns(foo) };",
                "after": "const store = new InMemoryFooStore();\nrunFooStoreContract(store);",
                "lang": "ts"
            }
        },
        {
            "id": "flaky-test-normalization",
            "name": "Flaky Test Normalization",
            "definition": "A defect in which intermittent test failures are accepted and rerun until they pass.",
            "type": "anti-pattern",
            "scope": [
                "semantic_consistency",
                "correctness_verification"
            ],
            "requires": [],
            "reinforces": [],
            "enables": [],
            "conflicts_with": [],
            "tensions_with": [],
            "formed_by": "Accept intermittent test failures as normal and rerun until green instead of fixing nondeterminism or isolation defects.",
            "detected_by": [
                "rerun_to_pass",
                "quarantined_tests_never_fixed",
                "time_order_random_test_failures"
            ],
            "measured_by": [
                "rerun rate",
                "quarantined tests past their fix date"
            ],
            "refactored_by": [
                "lexicon:isolate-test-state",
                "lexicon:inject-clock-and-randomness",
                "lexicon:fix-the-race",
                "lexicon:fake-at-the-boundary"
            ],
            "enforced_by": ["a CI policy that fails on a retried test and tracks every quarantined one"],
            "severity": "discouraged",
            "exemplar": {
                "before": "test.retry(5)(\"foo works sometimes\", async () => { await sleep(random()); expect(await getFoo()).toBeTruthy(); });",
                "after": "test(\"foo is created deterministically\", async () => { const foo = await createFoo.execute(input); expect(foo.id).toBe(expectedId); });",
                "lang": "ts"
            }
        },
        {
            "id": "prompt-sprawl",
            "name": "Prompt Sprawl",
            "definition": "A defect in which prompts, model parameters and output schemas are scattered through code without versions or evaluation.",
            "type": "anti-pattern",
            "scope": [
                "contract_compatibility",
                "model_governance"
            ],
            "requires": [],
            "reinforces": [],
            "enables": [],
            "conflicts_with": [],
            "tensions_with": [],
            "formed_by": "Scatter prompts, retrieval rules, model parameters, safety instructions, and output schemas across code without versioning, evaluation, or ownership.",
            "detected_by": [
                "prompt_literals_in_many_files",
                "no_prompt_registry",
                "no_eval_for_prompt_change",
                "model_params_scattered"
            ],
            "measured_by": ["prompt literals outside the registry"],
            "refactored_by": [
                "lexicon:prompt-registry",
                "lexicon:prompt-versioning",
                "lexicon:evaluation-suite",
                "lexicon:centralized-model-configuration"
            ],
            "enforced_by": ["a prompt registry, with an evaluation required on every change"],
            "severity": "discouraged",
            "exemplar": {
                "before": "const a = model.run(\"summarize this foo: \" + foo);\nconst b = model.run(\"pls summarize foo \" + foo);",
                "after": "const summary = model.run(FOO_PROMPTS.summarize({ foo }));",
                "lang": "ts"
            }
        },
        {
            "id": "ungrounded-content",
            "name": "Ungrounded Content",
            "definition": "A defect in which the model produces answers or decisions without retrieved evidence or disclosed uncertainty.",
            "type": "anti-pattern",
            "scope": ["model_governance"],
            "requires": [],
            "reinforces": [],
            "enables": [],
            "conflicts_with": [],
            "tensions_with": [],
            "formed_by": "Generate answers, classifications, plans, or decisions without evidence retrieval, source references, confidence limits, or unsupported-claim handling.",
            "detected_by": [
                "answer_without_sources_when_sources_required",
                "no_retrieval_trace",
                "unsupported_claims",
                "confidence_not_disclosed"
            ],
            "measured_by": ["answers without a source where one is required"],
            "refactored_by": [
                "architecture:retrieval-augmented-generation",
                "lexicon:evidence-citation",
                "lexicon:claim-validation",
                "lexicon:abstain-or-disclose-uncertainty"
            ],
            "enforced_by": [
                "retrieval evaluation",
                "claim validation against the retrieved sources"
            ],
            "severity": "discouraged",
            "exemplar": {
                "before": "const answer = await model.run(question);\nreturn answer;",
                "after": "const context = await retrieve(question);\nconst answer = await model.run(FOO_PROMPTS.answer({ question, context }));\nreturn withCitations(answer, context);",
                "lang": "ts"
            }
        },
        {
            "id": "model-version-ambiguity",
            "name": "Model Version Ambiguity",
            "definition": "A defect in which models, prompts or indexes are used without recording their version and configuration.",
            "type": "anti-pattern",
            "scope": ["model_governance"],
            "requires": [],
            "reinforces": [],
            "enables": [],
            "conflicts_with": [],
            "tensions_with": [],
            "formed_by": "Use models, embeddings, prompts, or evaluation artifacts without recording version, configuration, dataset, or inference context.",
            "detected_by": [
                "model_name_missing_version",
                "embedding_index_unversioned",
                "eval_results_without_config",
                "prompt_not_versioned"
            ],
            "measured_by": ["inferences logged without a model version"],
            "refactored_by": [
                "lexicon:model-registry",
                "lexicon:prompt-versioning",
                "lexicon:inference-context-record",
                "lexicon:governance-log"
            ],
            "enforced_by": [
                "a model registry",
                "inference logging that requires a version"
            ],
            "severity": "discouraged",
            "exemplar": {
                "before": "const result = await model.run(prompt);",
                "after": "const result = await model.run(prompt, { model: \"foo-llm-2024-06\", temperature: 0 });\nlogger.info(\"foo.inference\", { model: result.model });",
                "lang": "ts"
            }
        }
    ]
}