Files
TehRiehlDeal 66a44354cd
CI / security (push) Failing after 4s
CI / test (push) Failing after 17s
CI / static (push) Failing after 19s
chore: session 4 polish — CI, lint, prestige UI, balance pass
Adds the CI workflow, ESLint flat config, basic prestige action,
and tunes three off-balance numbers in the day-1 content.

CI runs three parallel jobs: `static` (lint, typecheck, prettier,
build), `test` (unit + Postgres-backed integration via service
container, with coverage gate), and `security` (gitleaks + trivy).
Scratch crypto keys are generated per-run from openssl so the
server can boot in CI without any committed secrets.

Prestige UI: a "git commit" / "git tag -a" button in each
prestigeable layer's canvas header, gated on the upstream `best`
threshold. Displays projected gain inline (`// +N `) so the
trade is visible before clicking.

Balance fixes:
- Releases requirement was 1000 commits (≈5B LoC, unreachable)
  with a gain formula that returned 0 at the threshold. Aligned
  both at 100 commits with prestigePoints exponent 0.5.
- Tech Debt accrual was 0.0005 × code/s (500 debt/s at 1M LoC).
  Reduced to 0.0001 — still meaningful, no longer punitive.
- Pay-Down Debt was effect=-10 per buyable, instantly turning the
  production multiplier to -9. Changed to -0.1 (each pay-down
  slows accrual by 10%; 10 pay-downs stops it; further buys
  reverse the flow). Also corrected costLayer to "code" so it
  spends LoC, not Debt.

Schema: added `costLayer` to Buyable to match Upgrade (needed for
the Tech Debt fix). RightPanel now honors `costLayer` for both
upgrades and buyables — the cost-side affordability check and the
spendAmount target both follow the override.

Verification:
- pnpm -r typecheck: clean
- pnpm -r lint: clean
- pnpm format:check: clean
- pnpm -r test: 73 unit tests pass
- pnpm --filter @teh-riehl/server test:integration: 7/7 pass
- 80 tests total

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 12:50:45 -07:00

52 lines
1.5 KiB
JavaScript

// @ts-check
import js from '@eslint/js';
import tseslint from 'typescript-eslint';
import globals from 'globals';
/**
* Single ESLint config for the whole monorepo. Flat config (ESLint 9+).
* Per-package configs would just duplicate rules; the only divergence
* across packages is the environment globals (node vs browser), which
* we infer from the file path below.
*/
export default tseslint.config(
{
ignores: [
'**/dist/**',
'**/node_modules/**',
'**/coverage/**',
'**/.turbo/**',
'**/prisma/migrations/**',
'**/*.config.{ts,js,mjs,cjs}',
// The generated Prisma client lives in node_modules; nothing to lint anyway.
],
},
js.configs.recommended,
...tseslint.configs.recommended,
{
languageOptions: {
ecmaVersion: 2022,
sourceType: 'module',
globals: { ...globals.node, ...globals.browser },
},
rules: {
'@typescript-eslint/no-unused-vars': [
'warn',
{ argsIgnorePattern: '^_', varsIgnorePattern: '^_', caughtErrorsIgnorePattern: '^_' },
],
'@typescript-eslint/no-explicit-any': 'warn',
'@typescript-eslint/no-non-null-assertion': 'off',
'no-empty': ['error', { allowEmptyCatch: true }],
'no-console': ['warn', { allow: ['warn', 'error'] }],
},
},
// Tests can be loose about console + any.
{
files: ['**/test/**', '**/*.test.{ts,tsx}', '**/*.spec.{ts,tsx}'],
rules: {
'no-console': 'off',
'@typescript-eslint/no-explicit-any': 'off',
},
},
);