main
55 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
e6cf2818f9 |
Merge pull request 'perf: pre-index cross-layer effects + Performance Mode toggle; v0.1.24' (#14) from feature/performance into main
CI / secrets-scan (push) Successful in 6s
CI / sast (push) Successful in 13s
CI / vuln-scan (push) Successful in 14s
CI / build-images (push) Successful in 3m22s
CI / push (push) Successful in 22s
CI / test (push) Successful in 25s
CI / lint (push) Successful in 26s
CI / image-scan (push) Successful in 25s
Reviewed-on: #14 |
||
|
|
e250991fe2 |
perf: pre-index cross-layer effects + Performance Mode toggle; v0.1.24
CI / test (push) Has been skipped
CI / build-images (push) Has been skipped
CI / push (push) Has been skipped
CI / secrets-scan (push) Successful in 6s
CI / sast (push) Successful in 13s
CI / vuln-scan (push) Successful in 14s
CI / lint (push) Successful in 28s
CI / image-scan (push) Has been skipped
CI / secrets-scan (pull_request) Successful in 6s
CI / sast (pull_request) Successful in 13s
CI / build-images (pull_request) Successful in 3m28s
CI / push (pull_request) Has been skipped
CI / vuln-scan (pull_request) Successful in 15s
CI / test (pull_request) Successful in 25s
CI / lint (pull_request) Successful in 27s
CI / image-scan (pull_request) Successful in 24s
The tick engine used to walk every layer's upgrades on every buyable on every layer per tick (O(L² × U), ~10K predicate checks/sec at 10 Hz). Now built once per tick into a Map-backed index and read from there. Numbers, breakdown order, and entry detail are unchanged — pinned by new equivalence tests across production, click power, requirement, gain, buyable, wildcard fan-out, and the three challenge debuffs. Pairs with an opt-in display.performance_mode toggle that halves the tick rate (10 Hz → 5 Hz) and skips cosmetic animations (resource pulse, code-scroll backdrop, click-pop floaters) for older hardware. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
89642e6a19 |
Merge pull request 'fix: cloud save reconciliation + 401 handling; v0.1.23' (#13) from bugfix/save-sync-and-401-handling into main
CI / test (push) Successful in 25s
CI / secrets-scan (push) Successful in 5s
CI / sast (push) Successful in 13s
CI / vuln-scan (push) Successful in 14s
CI / lint (push) Successful in 28s
CI / build-images (push) Successful in 3m22s
CI / push (push) Successful in 23s
CI / image-scan (push) Successful in 26s
Reviewed-on: #13 |
||
|
|
35abc6a34e |
fix: cloud save reconciliation + 401 handling; v0.1.23
CI / test (push) Has been skipped
CI / secrets-scan (push) Successful in 7s
CI / lint (push) Successful in 26s
CI / secrets-scan (pull_request) Successful in 6s
CI / test (pull_request) Successful in 25s
CI / lint (pull_request) Successful in 27s
CI / image-scan (pull_request) Successful in 26s
CI / sast (push) Successful in 13s
CI / vuln-scan (push) Successful in 15s
CI / build-images (push) Has been skipped
CI / image-scan (push) Has been skipped
CI / push (push) Has been skipped
CI / sast (pull_request) Successful in 13s
CI / vuln-scan (pull_request) Successful in 15s
CI / build-images (pull_request) Successful in 3m21s
CI / push (pull_request) Has been skipped
Cross-device login no longer wipes progress. The boot loader now distinguishes empty cloud from cloud-error, autosave is gated on an explicit reconciliation step, and divergent local/cloud saves prompt the player with a side-by-side modal instead of silently clobbering. Adds a server-side optimistic-lock so stale clients can't overwrite newer cloud saves even if future client code regresses. 401s with failed refresh route to /login?reason=expired with a friendly banner and clear all in-memory state on the way out. localStorage save key is now per-user (`trk.save.v1.<userId>`) with a one-shot migration for the legacy key. |
||
|
|
1496272362 |
fix: cross-layer production mults now multiply buyables; v0.1.22
CI / secrets-scan (push) Successful in 6s
CI / sast (push) Successful in 12s
CI / vuln-scan (push) Successful in 14s
CI / test (push) Successful in 25s
CI / lint (push) Successful in 27s
CI / build-images (push) Successful in 3m23s
CI / image-scan (push) Successful in 25s
CI / push (push) Successful in 20s
productionBreakdown applied cross-layer 'production' multipliers (CI/CD's ×3, commit-amend's +50%/Commit, caffeine-tolerance's +sqrt(Cups), and the per-ticket Code bonus) BEFORE the buyable loop, so additive buyable contributions (Intern +0.5/sec, Junior +2/sec) were summed in AFTER the multipliers and never got tripled. With own ×6, CI/CD ×3, and 5 Interns the player was getting 6·3 + 2.5 = 20.5/sec instead of the (6 + 2.5)·3 = 25.5/sec that "All production ×3" implies. Same shortfall on every cross-layer mult. Fix: reorder the breakdown so own-upgrades → buyables → cross-layer mults → tickets bonus → preNet. Multipliers now cover the full mult. Regression test pins Code/sec at 4.5 with 1 Intern + CI/CD (would have been 3.5 with the old ordering). Side effect: commit-amend / caffeine-tolerance / closed-tickets all get slightly stronger because they now reach buyable contribution too — which was the wording's intent the whole time. |
||
|
|
3ace63acfb |
Merge pull request 'fix: Releases tab stays after spend; CI/CD upgrade actually multiplies; v0.1.20' (#12) from bugfix/release-visibility into main
CI / build-images (push) Successful in 3m24s
CI / image-scan (push) Successful in 25s
CI / push (push) Successful in 21s
CI / secrets-scan (push) Successful in 5s
CI / sast (push) Successful in 14s
CI / vuln-scan (push) Successful in 15s
CI / test (push) Successful in 26s
CI / lint (push) Successful in 27s
Reviewed-on: #12 |
||
|
|
e3dbf02c7a |
fix: Semantic Versioning actually boosts Commit gain; v0.1.21
CI / test (push) Has been skipped
CI / secrets-scan (push) Successful in 6s
CI / sast (push) Successful in 11s
CI / vuln-scan (push) Successful in 15s
CI / lint (push) Successful in 25s
CI / build-images (push) Has been skipped
CI / image-scan (push) Has been skipped
CI / push (push) Has been skipped
CI / secrets-scan (pull_request) Successful in 6s
CI / sast (pull_request) Successful in 13s
CI / vuln-scan (pull_request) Successful in 14s
CI / test (pull_request) Successful in 25s
CI / lint (pull_request) Successful in 26s
CI / build-images (pull_request) Successful in 3m25s
CI / image-scan (pull_request) Successful in 25s
CI / push (pull_request) Has been skipped
The Semantic Versioning Releases upgrade advertised +sqrt(R) to Commit
gain but had no `affects` block — same shape as the v0.1.20 CI/CD bug.
Without affects the upgrade was treated as an own-layer (Releases)
multiplier, and Releases has no production or gain to multiply.
Adds a new cross-layer `affects.target = "gain"` that mirrors the
existing `requirement` modifier. requirement cheapens the formula
input; gain multiplies the formula output. Applied AFTER the gain
formula and floored so prestige currencies stay integer.
Wires semantic-versioning as `affects: { layer: "commits", target:
"gain", scaling: "add" }`, which evaluates to `1 + sqrt(R)` — same
curve caffeine-tolerance uses for Coffee → Code, so the multiplier
shape is recognisable.
Updates nextPrestigeThreshold to divide the projected next-tier amount
by gainMult, keeping the git commit tooltip honest when the upgrade
is owned.
|
||
|
|
02cfb92b0d |
fix: Releases tab stays after spend; CI/CD upgrade actually multiplies; v0.1.20
Two Releases-layer bugs:
1. v0.1.19 made the tab sticky on `amountAtLeast(releases, 1)`, but
buying CI/CD costs 1 Release Tag and drops the amount back to 0,
re-hiding the tab. `total` only ever increments, so
`totalAtLeast(releases, 1)` keeps the tab visible as long as the
player has ever earned a release (equivalent in practice to
"has ever bought a Release upgrade", since one implies the other).
2. The CI/CD Pipeline upgrade advertised "All production ×3" but did
nothing — without an `affects` block, the tick engine treats the
upgrade as own-layer (releases), and Releases has no `production`
formula to multiply. Declared `affects: { layer: "*", target:
"production", scaling: "mult" }` so the existing wildcard cross-
layer path picks it up. Inspector now surfaces a `Releases.CI/CD
Pipeline ×3.00` row for Code / Commits / Coffee.
|
||
|
|
612d37e4aa |
fix: Releases tab sticky after first release; v0.1.19
CI / sast (push) Successful in 13s
CI / vuln-scan (push) Successful in 15s
CI / test (push) Successful in 24s
CI / lint (push) Successful in 26s
CI / secrets-scan (push) Successful in 5s
CI / build-images (push) Successful in 3m23s
CI / image-scan (push) Successful in 25s
CI / push (push) Successful in 22s
Same shape as v0.1.11 (Commits). Unlock predicate was `amountAtLeast(tickets, 3)`, but the Releases prestige wipes tickets in its resetsLayers — so cutting your first release immediately dropped tickets to 0 and hid the tab. If the player closed the layer without banking CI/CD first, there was no path back in. Fix: anyOf(amountAtLeast(tickets, 3), amountAtLeast(releases, 1)) — sticky once the player has at least one Release Tag, which (unlike tickets) is never reset by anything currently in the game. |
||
|
|
0440842a86 |
Merge pull request 'feat: OG/Twitter Card metadata for chat link previews; v0.1.18' (#11) from feature/link-prettier into main
CI / secrets-scan (push) Successful in 6s
CI / sast (push) Successful in 14s
CI / vuln-scan (push) Successful in 15s
CI / test (push) Successful in 26s
CI / lint (push) Successful in 28s
CI / build-images (push) Successful in 3m23s
CI / image-scan (push) Successful in 25s
CI / push (push) Successful in 21s
Reviewed-on: #11 |
||
|
|
4359955c51 |
feat: OG/Twitter Card metadata for chat link previews; v0.1.18
CI / test (push) Has been skipped
CI / secrets-scan (push) Successful in 5s
CI / sast (push) Successful in 13s
CI / vuln-scan (push) Successful in 14s
CI / lint (push) Successful in 26s
CI / build-images (push) Has been skipped
CI / image-scan (push) Has been skipped
CI / push (push) Has been skipped
CI / secrets-scan (pull_request) Successful in 6s
CI / sast (pull_request) Successful in 14s
CI / vuln-scan (pull_request) Successful in 15s
CI / test (pull_request) Successful in 25s
CI / lint (pull_request) Successful in 27s
CI / build-images (pull_request) Successful in 5m7s
CI / image-scan (pull_request) Successful in 24s
CI / push (pull_request) Has been skipped
index.html grows the Open Graph and Twitter Card meta tags (title, description, type, site_name, url, image + dimensions, alt) plus a plain `<meta name="description">` for SEO. Same copy as the README one-liner so every surface stays in sync. Absolute URLs are required for Facebook+Twitter and strongly preferred elsewhere, but the deployment URL isn't known at build time. Solved with the same pattern config.js already uses: a `__OG_BASE_URL__` token in index.html gets sed-substituted by the nginx entrypoint from a new `APP_PUBLIC_URL` env var. Trailing-slash trim and sed-meta escaping are both handled. Unset env = relative URLs (Slack/Discord/iMessage still render fine, Facebook won't). README gains a paragraph under Runtime Config documenting the new var. |
||
|
|
348a6f65ea |
Merge pull request 'feat: closed tickets buff Code; totals strip moves to MenuBar; v0.1.17' (#10) from refactor/ticket-benefits into main
CI / secrets-scan (push) Successful in 6s
CI / sast (push) Successful in 13s
CI / vuln-scan (push) Successful in 16s
CI / test (push) Successful in 26s
CI / lint (push) Successful in 27s
CI / build-images (push) Successful in 3m22s
CI / image-scan (push) Successful in 26s
CI / push (push) Successful in 33s
Reviewed-on: #10 |
||
|
|
cee7e375f9 |
feat: closed tickets buff Code; totals strip moves to MenuBar; v0.1.17
CI / test (push) Has been skipped
CI / secrets-scan (push) Successful in 5s
CI / sast (push) Successful in 12s
CI / vuln-scan (push) Successful in 15s
CI / lint (push) Successful in 24s
CI / build-images (push) Has been skipped
CI / image-scan (push) Has been skipped
CI / push (push) Has been skipped
CI / secrets-scan (pull_request) Successful in 5s
CI / build-images (pull_request) Has been cancelled
CI / image-scan (pull_request) Has been cancelled
CI / push (pull_request) Has been cancelled
CI / sast (pull_request) Has been cancelled
CI / vuln-scan (pull_request) Has been cancelled
CI / test (pull_request) Has been cancelled
CI / lint (pull_request) Has been cancelled
Two related changes: Closed tickets are now mechanically rewarding. Each ticket adds +25% to Code production (additive), so 1 ticket = ×1.25, 10 = ×3.5, stacking with own-layer + commit-amend + coffee multipliers. Shows in the production inspector as `Tickets.N closed ×1.X` with `+25% Code/sec per ticket` underneath, so the player can see why their /sec jumped the moment a P0 Bug closes. InfoModal copy updated to advertise the mechanic; stale `ticket-master` milestone description (which promised a separate +50% at 10 tickets that was never implemented) replaced with text reflecting the per-ticket bonus. Totals strip moved from the resource hero strip into the top MenuBar — the previous placement was a misread of "top bar". Restored the hero strip's original single-headline layout. The strip is now compact inline `[symbol] [amount]` chips sized for the 28px MenuBar row, sitting between the breadcrumb and the save/info/debug buttons. |
||
|
|
8ac1bd793d |
Merge pull request 'fix: Tickets tab stays put during active challenge; v0.1.14' (#9) from bugfix/tickets into main
CI / secrets-scan (push) Successful in 6s
CI / sast (push) Successful in 14s
CI / vuln-scan (push) Successful in 15s
CI / lint (push) Successful in 26s
CI / test (push) Successful in 27s
CI / build-images (push) Successful in 3m23s
CI / image-scan (push) Successful in 26s
CI / push (push) Successful in 21s
Reviewed-on: #9 |
||
|
|
5c3bbb99b6 |
feat: always-on layer-totals strip + click rate limit; v0.1.16
CI / test (push) Has been skipped
CI / sast (push) Successful in 13s
CI / vuln-scan (push) Successful in 14s
CI / lint (push) Successful in 25s
CI / build-images (push) Has been skipped
CI / secrets-scan (push) Successful in 6s
CI / image-scan (push) Has been skipped
CI / push (push) Has been skipped
CI / secrets-scan (pull_request) Successful in 6s
CI / sast (pull_request) Successful in 14s
CI / vuln-scan (pull_request) Successful in 15s
CI / test (pull_request) Successful in 24s
CI / lint (pull_request) Successful in 26s
CI / build-images (pull_request) Successful in 3m22s
CI / image-scan (pull_request) Successful in 26s
CI / push (pull_request) Has been skipped
Top bar gets a compact running-totals strip on the left — one chip per unlocked layer with current amount, tinted in the layer's color, and click-to-focus. Sits beside the existing headline so you can read every resource without flipping tabs. ClickButton enforces a 10/s cap on accepted clicks (100ms min interval, measured with performance.now()). Above sustainable human speed so real players don't notice; an autoclicker at 50-200 Hz gets throttled to the same 10/s. Silent by design — a visible "throttled" indicator would just teach the cap. |
||
|
|
c320a77bd9 |
feat: prestige tooltip shows next-tier threshold; v0.1.15
The git commit (and git tag -a) tooltip now shows the upstream amount needed to bump the gain by one tier — "next +2 ★ 20K LoC (8K more)" — so players don't have to back-solve prestigePoints by hand. Closed-form inverse from prestigePoints(req, pow): the next-integer gain G+1 needs amount ≥ (G+1)^(1/pow) · req · reqMult, so any requirement-modifier upgrade (force-push) flows through automatically. Bails out for unknown formulas instead of guessing. |
||
|
|
956d1476bc |
fix: Tickets tab stays put during active challenge; v0.1.14
Entering a Tickets challenge wipes Commits to 0, and goals like P0 Bug (reach 1M LoC) intentionally require commit prestiges to ramp back up. But each commit reset Commits to 1, which fails Tickets' `commits >= 5` predicate — so the tab vanished mid-run and the player had no Exit button to escape the challenge they were still inside. Fix: LeftRail treats the layer hosting the active challenge as unlocked regardless of its predicate. Surgical one-spot override; the underlying unlock condition still gates first-time access. |
||
|
|
d6813c9182 |
Merge pull request 'fix: Commits tab sticky after prestige; Coffee unlock fires; v0.1.11' (#8) from bugfix/commit-display-and-tickets into main
CI / secrets-scan (push) Successful in 5s
CI / build-images (push) Successful in 3m25s
CI / image-scan (push) Successful in 24s
CI / sast (push) Successful in 13s
CI / vuln-scan (push) Successful in 14s
CI / test (push) Successful in 24s
CI / lint (push) Successful in 28s
CI / push (push) Successful in 21s
Reviewed-on: #8 |
||
|
|
720fc29fc0 |
Added autoComplete to props
CI / test (push) Has been skipped
CI / secrets-scan (push) Successful in 8s
CI / sast (push) Successful in 17s
CI / vuln-scan (push) Successful in 19s
CI / secrets-scan (pull_request) Successful in 5s
CI / test (pull_request) Successful in 30s
CI / lint (push) Successful in 31s
CI / sast (pull_request) Successful in 10s
CI / vuln-scan (pull_request) Successful in 14s
CI / build-images (push) Has been skipped
CI / lint (pull_request) Successful in 28s
CI / image-scan (push) Has been skipped
CI / push (push) Has been skipped
CI / image-scan (pull_request) Successful in 24s
CI / build-images (pull_request) Successful in 4m25s
CI / push (pull_request) Has been skipped
|
||
|
|
acf3771a70 |
fix: signup password field gets autoComplete; v0.1.13
CI / test (push) Has been skipped
CI / secrets-scan (push) Successful in 5s
CI / secrets-scan (pull_request) Successful in 8s
CI / sast (push) Successful in 14s
CI / vuln-scan (push) Successful in 15s
CI / test (pull_request) Successful in 26s
CI / lint (push) Successful in 29s
CI / sast (pull_request) Successful in 14s
CI / vuln-scan (pull_request) Successful in 15s
CI / lint (pull_request) Successful in 30s
CI / build-images (push) Has been skipped
CI / image-scan (push) Has been skipped
CI / push (push) Has been skipped
CI / build-images (pull_request) Successful in 4m54s
CI / image-scan (pull_request) Successful in 25s
CI / push (pull_request) Has been skipped
Signup.tsx already passed `autoComplete="new-password"` on the password Field, but the local Field wrapper's typed props didn't list the key, so the destructured `...rest` silently dropped it before reaching the input. Password managers therefore didn't see a new-password field to suggest into. Login's Field already had the right shape — mirrored it here. |
||
|
|
f2342722f8 |
feat: active-challenge runtime for the Tickets layer; v0.1.12
CI / test (push) Has been skipped
CI / secrets-scan (push) Successful in 6s
CI / sast (push) Successful in 13s
CI / vuln-scan (push) Successful in 14s
CI / lint (push) Successful in 25s
CI / build-images (push) Has been skipped
CI / image-scan (push) Has been skipped
CI / push (push) Has been skipped
CI / secrets-scan (pull_request) Successful in 5s
CI / sast (pull_request) Successful in 13s
CI / vuln-scan (pull_request) Successful in 14s
CI / test (pull_request) Successful in 25s
CI / lint (pull_request) Successful in 25s
CI / build-images (pull_request) Successful in 3m25s
CI / image-scan (pull_request) Successful in 25s
CI / push (pull_request) Has been skipped
Tickets challenges used to be read-only preview cards — the runtime was acknowledged-missing in the info modal. Now fully wired: - gameSlice owns the active challenge (layerId, challengeId, seed). Serialized so it survives a reload mid-run. - New challenges.ts thunks: enterChallenge wipes Code/Commits/Tech Debt per Challenge.resetsLayers, exitChallenge wipes again with no reward, completeChallenge awards the reward + bumps the completion counter and re-runs the milestone evaluator, evaluateActiveChallenge checks the goal predicate each tick. - Tick engine threads ChallengeMods (debuffs + seed) through every production / cost / click calc, so the headline /sec matches what actually accumulates mid-challenge. Same productionBreakdown that powers the debug inspector picks up debuff lines too. - Debuffs implemented: P0 Bug halves Code production; Legacy Codebase silences buyables (effect labels marked "(disabled this run)"); Flaky Test jitters owned upgrade effectiveness with a seeded per-upgrade factor in [0.5, 1.5] that's stable within the run so the display doesn't strobe. - ChallengeCard grows Enter / Exit buttons, an "active" pill, and dimmed-when-another-is-running state. InfoModal drops the preview badge and the "Blocked on the Tickets runtime" line on Releases. - Schema: Challenge gains optional resetsLayers; defaults to the owning layer's branches. |
||
|
|
20ef25daff |
fix: Commits tab sticky after prestige; Coffee unlock fires; v0.1.11
Commits unlock was `bestAtLeast(code,5000)`, which v0.1.6 deliberately wipes on prestige — so the tab hid itself the moment you used it. New `anyOf`/`allOf` predicate combinators let the gate be "first-time LoC threshold OR any commits ever held", which sticks across the reset. Coffee's `hasMilestone(commits, first-commit)` predicate was correct, but nothing in the runtime ever dispatched `completeMilestone` — the reducer was dead code. Added `evaluateMilestones` that runs each tick and after prestige, awarding any layer milestone whose requirement flipped true. Idempotent; covers all future milestone gates too. |
||
|
|
de8cdabd66 |
Merge pull request 'feat: debug-mode production breakdown inspector; v0.1.10' (#6) from feature/generation-info into main
CI / secrets-scan (push) Successful in 5s
CI / sast (push) Successful in 14s
CI / vuln-scan (push) Successful in 16s
CI / test (push) Successful in 28s
CI / lint (push) Successful in 29s
CI / build-images (push) Successful in 3m23s
CI / image-scan (push) Successful in 25s
CI / push (push) Successful in 21s
Reviewed-on: #6 |
||
|
|
2f50267e34 |
feat: debug-mode production breakdown inspector; v0.1.10
CI / test (push) Has been skipped
CI / secrets-scan (push) Successful in 6s
CI / sast (push) Successful in 12s
CI / vuln-scan (push) Successful in 15s
CI / image-scan (push) Has been skipped
CI / lint (push) Successful in 25s
CI / build-images (push) Has been skipped
CI / secrets-scan (pull_request) Successful in 5s
CI / push (push) Has been skipped
CI / sast (pull_request) Successful in 13s
CI / vuln-scan (pull_request) Successful in 15s
CI / test (pull_request) Successful in 24s
CI / lint (pull_request) Successful in 26s
CI / image-scan (pull_request) Has been cancelled
CI / push (pull_request) Has been cancelled
CI / build-images (pull_request) Has been cancelled
Adds a `debug` toggle in the menu bar that makes values inspectable. With it on, hover the headline +X/s rate to see every contribution to it grouped by source — own-layer multipliers, cross-layer multipliers with their scaling rule and current owner amount, additive buyables, and the Tech Debt penalty if active. Refactors `computeProductionPerSec` to delegate to a new `productionBreakdown` walk so the headline number, the tick reducer, and the inspector tooltip all read from one source of truth. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
b2a9d7aa30 |
Merge pull request 'feat: manual click button + wipe-save fix; v0.1.9' (#5) from feature/clicking into main
CI / secrets-scan (push) Successful in 5s
CI / sast (push) Successful in 14s
CI / vuln-scan (push) Successful in 15s
CI / test (push) Successful in 25s
CI / lint (push) Successful in 26s
CI / build-images (push) Successful in 3m23s
CI / image-scan (push) Successful in 26s
CI / push (push) Successful in 20s
Reviewed-on: #5 |
||
|
|
2782c64102 |
feat: manual click button + wipe-save fix; v0.1.9
CI / test (push) Has been skipped
CI / secrets-scan (push) Successful in 5s
CI / sast (push) Successful in 11s
CI / vuln-scan (push) Successful in 14s
CI / lint (push) Successful in 24s
CI / build-images (push) Has been skipped
CI / image-scan (push) Has been skipped
CI / push (push) Has been skipped
CI / secrets-scan (pull_request) Successful in 6s
CI / sast (pull_request) Successful in 14s
CI / vuln-scan (pull_request) Successful in 15s
CI / test (pull_request) Successful in 24s
CI / lint (pull_request) Successful in 26s
CI / build-images (pull_request) Successful in 3m24s
CI / image-scan (pull_request) Successful in 25s
CI / push (pull_request) Has been skipped
Wipe-save was leaving the game in a zombie state: SettingsModal wrote
`layers: {}` to the cloud, and on reload `replaceLayers({})` clobbered
the slice's freshly-initialized layer state. The tick reducer then
silently no-op'd because `state.layers['code']` was undefined while
the headline still computed per-sec from content.
`replaceAll` in the layers slice now hydrates any missing content
layer back to its default `startData`. Side effect: old saves missing
a newly-added layer get default state on load, so future content
additions are forward-compatible.
Also adds a clicker button on layers that define `clickPower`. Click
value flows through the same cross-layer multiplier pipeline as
production, so new click-efficiency upgrades (Mechanical Keyboard,
Caffeinated Typing) compose cleanly. Tech Debt penalty intentionally
NOT applied to clicks — clicking is the player's escape hatch.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
0b4f227047 |
Merge pull request 'fix: prestige resets Tech Debt; favicon; v0.1.8' (#4) from bugfix/scaling-pacing into main
CI / secrets-scan (push) Successful in 5s
CI / sast (push) Successful in 13s
CI / vuln-scan (push) Successful in 14s
CI / test (push) Successful in 24s
CI / lint (push) Successful in 25s
CI / build-images (push) Successful in 2m44s
CI / image-scan (push) Successful in 22s
CI / push (push) Successful in 20s
Reviewed-on: #4 |
||
|
|
232c5a1c1d |
fix: prestige resets Tech Debt; favicon; v0.1.8
CI / test (push) Has been skipped
CI / secrets-scan (push) Successful in 6s
CI / sast (push) Successful in 11s
CI / vuln-scan (push) Successful in 13s
CI / lint (push) Successful in 25s
CI / build-images (push) Has been skipped
CI / image-scan (push) Has been skipped
CI / push (push) Has been skipped
CI / secrets-scan (pull_request) Successful in 4s
CI / sast (pull_request) Successful in 11s
CI / vuln-scan (pull_request) Successful in 14s
CI / test (pull_request) Successful in 24s
CI / lint (pull_request) Successful in 26s
CI / build-images (pull_request) Successful in 3m15s
CI / image-scan (pull_request) Successful in 23s
CI / push (pull_request) Has been skipped
Commit/Releases prestige now wipe Tech Debt along with the other upstream layers. Without this, the v0.1.7 global debt penalty survived prestige and silently divided post-prestige production, making commit upgrades look broken. Also wires up the new TehRiehlIncremental.png as the browser favicon. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
2511e9e97a |
Merge pull request 'feat: prestige reads current LoC; tiered CI; v0.1.6' (#3) from bugfix/scaling-pacing into main
CI / secrets-scan (push) Successful in 7s
CI / sast (push) Successful in 13s
CI / vuln-scan (push) Successful in 14s
CI / test (push) Successful in 24s
CI / lint (push) Successful in 26s
CI / build-images (push) Successful in 3m20s
CI / image-scan (push) Successful in 26s
CI / push (push) Successful in 21s
Reviewed-on: #3 |
||
|
|
3202275dd6 |
feat: info modal + Tech Debt redesign; v0.1.7
CI / test (push) Has been skipped
CI / secrets-scan (push) Successful in 6s
CI / sast (push) Successful in 13s
CI / vuln-scan (push) Successful in 15s
CI / lint (push) Successful in 25s
CI / build-images (push) Has been skipped
CI / image-scan (push) Has been skipped
CI / push (push) Has been skipped
CI / secrets-scan (pull_request) Successful in 6s
CI / sast (pull_request) Successful in 13s
CI / vuln-scan (pull_request) Successful in 14s
CI / test (pull_request) Successful in 24s
CI / lint (pull_request) Successful in 26s
CI / build-images (pull_request) Successful in 3m22s
CI / image-scan (pull_request) Successful in 26s
CI / push (pull_request) Has been skipped
Info modal
- New BookOpen button in the top menu bar (between breadcrumb and
save) opens ~/MANUAL.md — a per-layer overview. Hand-authored copy
in InfoModal.tsx, keyed by layer.id, with status badges for layers
that aren't fully wired yet (Tickets: preview, Releases: unreachable).
- uiSlice gains infoOpen state + setInfoOpen reducer.
Tech Debt — actually a mechanic now
- Global production penalty: Code/sec ÷ (1 + debt/500). Every
production-bearing layer except techdebt is divided by this. 500 Δ
halves production, 5,000 Δ cuts it 10×. Debt can no longer be
ignored — it actively slows everything else down.
- Pay-down rebalanced from additive (-0.1 per buy, useless after 10)
to multiplicative (×0.9 per buy via the new cumulative-mult applyMode).
Asymptotic — never reaches zero, so the player keeps managing it.
- Schema: Buyable.applyMode: 'additive' | 'cumulative-mult'. The
tick engine switches between mult += effect(count) and
mult *= effect(0)^count based on this flag.
- RightPanel's BuyableCard rendering: cumulative-mult buyables show
"×0.90/buy · now ×0.122" instead of a nonsensical "+X/s" delta.
Both package versions bumped to 0.1.7; patch notes entry added.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
7d3476f946 |
feat: prestige reads current LoC; tiered CI; v0.1.6
Prestige loop
- prestigeGain + canPrestige now read state.layers[primary].amount instead
of .best. The threshold is "do you currently hold N LoC", not "have you
ever held N LoC", and the gain reflects what's actually being traded.
- resetLayer wipes best and total too. Each prestige is a fresh slate;
nothing rides through to bias the next run's gain calculation.
- PrestigeButton tooltip: "current/threshold" line and explanatory copy
now reference current upstream amount.
CI
- Tiered gating via job-level `if:`. Non-main branch pushes run only the
pre-build set (lint, secrets-scan, vuln-scan, sast). Pull requests AND
main pushes additionally run test + build-images + image-scan. Main
pushes alone run the Harbor push + cosign + per-package git tags.
- `needs:` cascades skipped upstream jobs to dependents, so we don't
duplicate the condition on every downstream job.
Both package versions bumped to 0.1.6; patch notes entry added.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
5477c0be4c |
Merge pull request 'feat: balance pass, layer wiring, reset save, modal fixes; v0.1.5' (#2) from bugfix/scaling-pacing into main
CI / secrets-scan (push) Successful in 6s
CI / sast (push) Successful in 13s
CI / vuln-scan (push) Successful in 14s
CI / test (push) Successful in 24s
CI / lint (push) Successful in 26s
CI / build-images (push) Successful in 3m30s
CI / image-scan (push) Successful in 25s
CI / push (push) Successful in 23s
Reviewed-on: #2 |
||
|
|
0c79235c72 |
feat: balance pass, layer wiring, reset save, modal fixes; v0.1.5
CI / secrets-scan (push) Successful in 5s
CI / sast (push) Successful in 13s
CI / vuln-scan (push) Successful in 14s
CI / test (push) Successful in 24s
CI / lint (push) Successful in 26s
CI / build-images (push) Successful in 3m24s
CI / image-scan (push) Successful in 24s
CI / push (push) Has been skipped
CI / secrets-scan (pull_request) Successful in 5s
CI / sast (pull_request) Successful in 13s
CI / vuln-scan (pull_request) Successful in 15s
CI / test (pull_request) Successful in 25s
CI / lint (pull_request) Successful in 26s
CI / build-images (pull_request) Successful in 3m23s
CI / image-scan (pull_request) Successful in 25s
CI / push (pull_request) Has been skipped
Scaling
- commit-amend's exponential 1.5^commits is gone — replaced with linear
+50%/commit via a new addPerOwnAmount scaling mode. Past a few hundred
commits the old curve overflowed to Infinity and trivialized the game.
- schema's affects.scaling is now a closed enum: 'mult' / 'addPerOwnAmount'
/ 'add'. The old 'powOwnAmount' (and its uncommented 'flat') are out.
- affects.layer: '*' wildcard added for "all production" effects (techdebt
excluded so it can't become a self-inflicted penalty).
- computeProductionPerSec() exported from tick-engine. Game.tsx uses it
for the headline readout, so the displayed LoC/sec is the SAME number
the tick loop credits — cross-layer multipliers included.
- Infinity/NaN clamp in computeProductionPerSec — degenerate combos can't
accumulate non-finite state any more.
Layer wiring
- coffee.caffeine-tolerance now actually adds sqrt(Cups) to Code production.
- coffee.third-wave actually doubles the Espresso shot's per-unit rate.
- rebase + force-push moved to explicit 'mult' scaling for clarity.
UX
- UpgradeCard renders the upgrade's rule AND current contribution for
cross-layer upgrades — "+50%/Commit · now x4.5" instead of a flat "x1.50"
that lied about the live value.
- BuyableCard's "+X/s" now reflects per-buyable boosts from other layers.
- Settings has a save.reset row: two-click confirm, wipes local storage,
PUTs an empty blob to cloud, hard-reloads. Recovers from a corrupt save.
- Dialog centering fixed — the open animation was overwriting the
-translate-x/y centering transform via its own translate keyframe. Added
an opacity-only 'fade-in' animation, switched DialogContent + Overlay
to use it.
- DialogBody gets flex-1 min-h-0 so long content (patch notes) scrolls
inside the fixed-height dialog instead of pushing it past the viewport.
Deferred
- Active-challenge runtime (debuffs/rewards). Releases reachability
depends on this.
- releases.ci-cd 'All production x3' is mechanically wired (via '*') but
can't fire until Releases is reachable.
- Milestone effectTags still don't drive behavior.
Both package versions bumped to 0.1.5; patch notes entry added.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
2ae75da5f9 |
Merge pull request 'feat: cross-layer upgrades, prestige tooltip, ticket previews; v0.1.4' (#1) from bugfix/multipliers into main
CI / secrets-scan (push) Successful in 5s
CI / sast (push) Successful in 13s
CI / vuln-scan (push) Successful in 14s
CI / test (push) Successful in 24s
CI / lint (push) Successful in 26s
CI / push (push) Successful in 22s
CI / build-images (push) Successful in 3m23s
CI / image-scan (push) Successful in 25s
Reviewed-on: #1 |
||
|
|
f7b43602da |
chore: prettier --write to match repo-root format config
CI / secrets-scan (push) Successful in 6s
CI / sast (push) Successful in 13s
CI / vuln-scan (push) Successful in 15s
CI / test (push) Successful in 24s
CI / lint (push) Successful in 26s
CI / build-images (push) Successful in 3m25s
CI / secrets-scan (pull_request) Successful in 6s
CI / sast (pull_request) Successful in 16s
CI / vuln-scan (pull_request) Successful in 17s
CI / image-scan (push) Successful in 23s
CI / test (pull_request) Successful in 26s
CI / lint (pull_request) Successful in 27s
CI / push (push) Has been skipped
CI / build-images (pull_request) Successful in 3m24s
CI / image-scan (pull_request) Successful in 25s
CI / push (pull_request) Has been skipped
Targeted prettier --check on the same files passed locally but root pnpm format:check (what CI runs) failed on different printWidth rules. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
3d7d73ee6a |
feat: cross-layer upgrades, prestige tooltip, ticket previews; v0.1.4
CI / secrets-scan (push) Successful in 5s
CI / vuln-scan (push) Successful in 16s
CI / sast (push) Successful in 18s
CI / test (push) Successful in 25s
CI / lint (push) Failing after 26s
CI / build-images (push) Has been skipped
CI / image-scan (push) Has been skipped
CI / push (push) Has been skipped
Three player-visible fixes plus the schema work behind them.
Schema: new optional `affects` field on Upgrade lets an upgrade target a
different layer than its home (production / requirement / buyable), with
a powOwnAmount scaling for the "x1.5 per Commit owned" pattern and a
single-upgrade `requires` guard for conditional bonuses.
Wiring:
- tick-engine pulls cross-layer production + buyable multipliers via a
new crossLayerMultiplier() that walks every layer's upgrades.
- prestige.ts gains effectiveRequirement() and divides the gainFormula
input by the requirement multiplier, so a reduced threshold doesn't
leave the player in a "can prestige but gain is 0" window.
- commits.json: commit-amend / rebase / force-push gain matching
`affects` entries — they finally apply the bonuses their descriptions
promise.
UX:
- TooltipProvider mounted at the app root with delayDuration=0 so all
Radix tooltips appear instantly. PrestigeButton swaps its native
title= for a rich Tooltip showing gain, threshold, current best, and
any upgrade-modified requirement.
- RightPanel now renders a Challenges section using a new ChallengeCard
component so the Tickets layer isn't a blank panel. Cards are marked
"preview" since the active-challenge runtime is still future work.
Patch notes: retroactive entries for 0.1.1 through 0.1.3, plus the
current 0.1.4 entry. Future commits should keep this in sync.
Both package versions bumped to 0.1.4 to stay in lockstep for the
Harbor push job.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
b442f5eb15 |
chore(server): bump to v0.1.3 to track client release
CI / secrets-scan (push) Successful in 5s
CI / sast (push) Successful in 14s
CI / vuln-scan (push) Successful in 15s
CI / test (push) Successful in 24s
CI / lint (push) Successful in 26s
CI / build-images (push) Successful in 3m21s
CI / image-scan (push) Successful in 25s
CI / push (push) Successful in 20s
Keeps the client and server image tags in lockstep so v0.1.3 means the same release on both sides of the Harbor push. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
082f2fca3f |
feat(client): manual save via IDE-style top menu bar; bump v0.1.3
CI / secrets-scan (push) Successful in 6s
CI / sast (push) Successful in 12s
CI / vuln-scan (push) Successful in 15s
CI / test (push) Successful in 24s
CI / lint (push) Successful in 26s
CI / image-scan (push) Has been cancelled
CI / push (push) Has been cancelled
CI / build-images (push) Has been cancelled
Adds a 28px menu bar above the resource hero strip. Left edge is a faux file-path breadcrumb (~/tehriehl-incremental/layers/<id>.ts) to reinforce the "game lives inside an editor" concept; right edge is a Save button with the floppy icon and a Ctrl/Cmd+S shortcut hint. Button cycles idle -> saving -> saved (1.5s) with a cloud-failed state when only the local write lands. saveNow() in save-manager bypasses the autosave throttling and returns per-target outcome so the button can give honest feedback without conflating a cloud blip with a full save failure. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
c47a15f248 |
fix(client): gate autosave on boot-complete; bump v0.1.2
CI / secrets-scan (push) Successful in 6s
CI / sast (push) Successful in 13s
CI / vuln-scan (push) Successful in 14s
CI / test (push) Successful in 24s
CI / lint (push) Successful in 26s
CI / build-images (push) Successful in 3m22s
CI / image-scan (push) Successful in 26s
CI / push (push) Successful in 20s
Autosave middleware fired the moment auth landed because lastLocal and lastCloud were both 0, so any current timestamp tripped the threshold. The empty initial state then raced the boot effect's loadCloud() and sometimes won, overwriting an existing save with zeros before the load could replace state. Added a `game.loaded` flag — false at boot, flipped to true after the load attempt finishes (success or 404). The autosave gate now refuses to write while loaded is false, and replaceAll() forces loaded back to false so a state restore can't accidentally leave it set. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
9ee4869042 |
feat(server): self-applying migrations on container start; bump v0.1.1
CI / secrets-scan (push) Successful in 5s
CI / sast (push) Successful in 13s
CI / vuln-scan (push) Successful in 14s
CI / test (push) Successful in 26s
CI / lint (push) Successful in 27s
CI / build-images (push) Successful in 3m38s
CI / image-scan (push) Successful in 24s
CI / push (push) Successful in 22s
Three coordinated changes so the deployed image is operationally ready to roll into prod: 1. Keep Prisma CLI in the production bundle. Moved `prisma` from devDependencies into dependencies in packages/server/package.json so `pnpm deploy --prod` includes it. Version pin matches @prisma/client (^5.20.0) so the CLI's bundled engine and the client's stay aligned. 2. Container entrypoint that runs migrations before booting. Added packages/server/docker/entrypoint.sh: it invokes `/app/node_modules/.bin/prisma migrate deploy` against the live DATABASE_URL, then `exec "$@"` drops into the CMD (node dist/main.js). `migrate deploy` is the production-safe verb — only applies committed migrations from prisma/migrations, never generates new ones, idempotent on already-applied state. Invoked through tini in ENTRYPOINT so SIGTERM still flows cleanly to Node when the container is stopped. Uses the `.bin/prisma` symlink directly because we deleted npm/npx from the runtime image earlier (for the trivy gate). DATABASE_URL is redacted in the entrypoint's log line so the credentials don't end up in container logs. 3. Version bump: both packages 0.1.0 → 0.1.1 so Harbor's "refuse to overwrite existing tag" check accepts the push. Verification: - prisma CLI present at /app/node_modules/.bin/prisma in the runtime image. - Empty DB boot: entrypoint applies 20260517191555_init, creates users + saves + _prisma_migrations tables, server reaches "listening", /api/health returns ok. - Already-applied DB boot: entrypoint logs "No pending migrations to apply", server boots, no-op as expected. - 80 unit tests + 7 integration tests pass. - Trivy: 0 new findings; only the pre-existing lodash CVE remains (already in .trivyignore). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
781356a254 |
fix(ci): install trivy as binary; add AGPL-3.0 LICENSE
CI / secrets-scan (push) Successful in 5s
CI / sast (push) Successful in 14s
CI / vuln-scan (push) Successful in 15s
CI / test (push) Successful in 24s
CI / lint (push) Successful in 26s
CI / build-images (push) Successful in 3m18s
CI / image-scan (push) Successful in 26s
CI / push (push) Successful in 1m2s
Two unrelated changes that landed together: 1. Trivy image-scan was failing with "ignore file not found: /src/.trivyignore" — classic docker-in-docker mount issue. The runner's job container has the workspace at /workspace/<owner>/<repo>, but `docker run -v "$PWD:/src"` goes through the docker socket, where the daemon (running on the host) tries to mount /workspace/... — which only exists inside the job container, not on the host. The mount silently creates an empty dir, so trivy can't find the file. Install trivy as a binary on the runner directly and invoke it without docker. Now `.trivyignore` resolves against the workspace cwd. Applies to both server and client image scans plus both SBOM steps for consistency. 2. License added: AGPL-3.0-or-later. Restricts forks (including network/SaaS deployments) to also be AGPL — recognized as open source but with a meaningful copyleft. SPDX identifier set in root package.json. Canonical FSF text in LICENSE. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
efd073ebe1 |
fix(ci): pass trivy image scans
CI / secrets-scan (push) Successful in 6s
CI / sast (push) Successful in 13s
CI / vuln-scan (push) Successful in 15s
CI / build-images (push) Successful in 3m22s
CI / test (push) Successful in 26s
CI / lint (push) Successful in 28s
CI / push (push) Has been skipped
CI / image-scan (push) Failing after 16s
Three independent issues caused 35 + 15 HIGH/CRITICAL findings: 1. Client base — nginx:1.27-alpine pulled Alpine 3.21.3, which carries old libcrypto3/libssl3/libpng/libxml2/musl/nghttp2/zlib. Bumped to nginx:1.29-alpine and added `apk update && apk upgrade --no-cache` so the layer pulls every available patch in the current Alpine repo. Verified: 0 findings. 2. Server runtime — npm/yarn/corepack ship bundled inside the node:20-alpine image at /usr/local/lib/node_modules/npm/... They drag in cross-spawn, glob, minimatch, tar, and friends — all of which had HIGH CVEs. We never invoke them at runtime (CMD is `node dist/main.js`); deleting them in the runtime stage cuts 11 of the 15 findings. Also added `apk upgrade` for parity with the client. 3. Multer transitive — @nestjs/platform-express pulls in multer 2.0.2 which has three HIGH CVEs (fixed in 2.1.1). Added a pnpm `overrides` entry to pin it. For the remaining lodash CVE-2026-4800: Trivy lists 4.18.0 as the fixed version, but that release isn't published on npm. Added .trivyignore + wired --ignorefile into the trivy invocations, with a comment explaining why and when to re-evaluate. Verification (local builds + trivy scans): - teh-riehl-server: 0 HIGH/CRITICAL across all targets. - teh-riehl-client: 0 vulnerabilities (alpine 3.23.4). - Server boots, /api/health returns ok. - Client serves /config.js with APP_API_BASE_URL override. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
d31b2c6dc7 |
fix(ci): use postgres service name as DATABASE_URL host
CI / secrets-scan (push) Successful in 5s
CI / sast (push) Successful in 13s
CI / vuln-scan (push) Successful in 15s
CI / build-images (push) Successful in 3m22s
CI / lint (push) Successful in 26s
CI / test (push) Successful in 26s
CI / image-scan (push) Failing after 50s
CI / push (push) Has been skipped
Gitea Actions runs jobs in their own Docker network, so service containers are reachable by their YAML key — `postgres` — rather than `localhost` the way GitHub-hosted runners would. Prisma migrate deploy was failing with P1001 (can't reach DB) on this exact line. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
c1d4113370 |
fix(ci): move workflow to .gitea/, install pnpm via corepack
CI / push (push) Has been skipped
CI / secrets-scan (push) Successful in 5s
CI / sast (push) Successful in 12s
CI / vuln-scan (push) Successful in 15s
CI / test (push) Failing after 19s
CI / lint (push) Successful in 28s
CI / build-images (push) Has been skipped
CI / image-scan (push) Has been skipped
Two fixes for the runner:
1. Gitea Actions reads .gitea/workflows/, not .github/workflows/.
Renamed the file (git mv) so it actually fires.
2. pnpm/action-setup@v4 was failing with `exitcode '1'` on this
runner regardless of ordering vs setup-node. Switched to
corepack (built into Node 16+) which downloads the pinned
pnpm version on demand without needing a third-party action:
corepack enable
corepack prepare pnpm@9.12.0 --activate
Same caching strategy as before (actions/cache@v4 keyed on
the lockfile hash for the pnpm store directory).
Applied to both `test` and `lint` jobs.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
7f2e157cf6 |
fix(ci): install Node before pnpm, manual store cache
CI / sast (push) Successful in 11s
CI / secrets-scan (push) Successful in 5s
CI / lint (push) Failing after 33s
CI / test (push) Failing after 35s
CI / build-images (push) Has been skipped
CI / image-scan (push) Has been skipped
CI / vuln-scan (push) Successful in 14s
CI / push (push) Has been skipped
Gitea runners (unlike GitHub-hosted ones) don't ship with Node pre-installed, so pnpm/action-setup's self-installer fails with "exitcode '1': failure" when it runs first — npm isn't on PATH yet for it to do the global install. Swap the ordering: actions/setup-node first, then pnpm-setup with run_install: false, then actions/cache@v4 keyed on the lockfile hash for the store directory. Same caching benefit as setup-node's built-in cache: pnpm, just without the chicken- and-egg dependency on pnpm existing first. Applied to both `test` and `lint` jobs. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
5a2c6885e9 |
feat: runtime config + Dockerfiles + CI overhaul
CI / sast (push) Successful in 19s
CI / secrets-scan (push) Successful in 5s
CI / vuln-scan (push) Successful in 20s
CI / lint (push) Failing after 5s
CI / test (push) Failing after 7s
CI / image-scan (push) Has been skipped
CI / build-images (push) Has been skipped
CI / push (push) Has been skipped
Three coupled changes the deployable build pipeline needed:
1. Runtime config (window.__APP_CONFIG__)
Vite bakes env vars at build time, which means one image per
deploy target. Switched to a runtime-config pattern: the nginx
container's entrypoint writes /config.js from env vars before
serving, and index.html loads it before the React bundle. The
client reads window.__APP_CONFIG__.apiBaseUrl via the new
runtimeConfig.apiUrl() helper instead of hardcoding /api. One
image, any backend.
2. Dockerfiles
- packages/server/Dockerfile: multi-stage with `pnpm deploy
--prod` for a flat node_modules. tini for PID 1, non-root
user, alpine base. The `.prisma/client/` generated artifacts
aren't tracked by `pnpm deploy` (not a declared dep) so we
manually copy them from the builder's pnpm store into the
same .pnpm@prisma+client+... directory that deploy preserved
— without this, PrismaClient instantiation throws "did not
initialize yet."
- packages/client/Dockerfile: vite build + nginx:alpine
runtime, custom nginx.conf with no-cache on /config.js and
long-cache on hashed assets, /docker-entrypoint.d/40-app-
config.sh materializes config.js at startup.
- Added tsconfig.build.json on the server so `nest build` emits
dist/main.js (the existing tsconfig included test/, which
made tsc pick the package root as common prefix and produce
dist/src/main.js).
3. CI overhaul (.github/workflows/ci.yml)
Switched to the per-project pattern used elsewhere: parallel
test / lint / secrets-scan / vuln-scan / sast jobs, then
build-images, image-scan, and a gated push job. Push is
main-only, checks Harbor for an existing version tag before
pushing, signs images with cosign, and back-pushes per-package
git tags (server-vX.Y.Z, client-vX.Y.Z). Renamed Harbor
project to tehriehlincremental and the auth secrets to
INCREMENTAL_USERNAME / INCREMENTAL_PASSWORD per request. Test
job retains the Postgres service container so integration
tests still run.
Verification:
- Server image: builds, boots, mounts all routes, "listening on
:3001" — confirmed Prisma client initializes properly.
- Client image: builds, entrypoint generates /config.js with
APP_API_BASE_URL=https://api.example.com/api confirmed via
curl, index.html loads config.js before main bundle.
- pnpm -r typecheck / test / lint / format:check: all clean.
- 80 unit tests pass + 7 integration tests.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
a8210067d0 |
refactor(client): remove SVG tree; keep code backdrop as the canvas
The SVG tree was redundant — every upgrade is already addressable through the right-panel cards (with diff-gutter state, cost, effect, and click-to-buy), and tree nodes weren't even wired for interaction. Drops a lot of visual noise from the center pane and lets the scrolling code be the actual editor view. Removed: - The <svg> + TreeEdge/TreeNode rendering inside LayerCanvas. - The layoutLayer / isUpgradeUnlocked helpers (only the SVG consumed them). - packages/client/src/components/game/TreeNode.tsx (now dead). - The ownedUpgrades prop on LayerCanvas + its caller in Game.tsx. Bumped CodeBackdrop visibility: - main text rgba(148, 163, 184, 0.7), up from 0.45 - line numbers rgba(100, 116, 139, 0.7), up from 0.65 with a brighter base tone so they don't disappear next to the brighter main text Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
2e872983d5 |
fix(client): give LayerCanvas a real height; tone CodeBackdrop subtle
Root cause of the invisible code backdrop: the middle div in Game.tsx wasn't a flex container, so LayerCanvas's `flex-1 min-h-0` had no effect and the canvas collapsed to content height (zero — every child of LayerCanvas is absolutely positioned). The CodeBackdrop sat inside a 0-height parent and its absolute inset-0 box rendered at 0×width. Why the tree was still visible at 0 height: SVG with viewBox and preserveAspectRatio retains its drawn area even when the host element's box-model height is 0, because most browsers don't clip SVG content via the parent's overflow when the SVG has explicit w-full h-full. The CodeBackdrop is a regular block, so it followed the parent's 0 height and disappeared. Fix: add `flex flex-col` to the middle div so LayerCanvas's existing flex-1 correctly stretches to fill the row. Also reverted the debug styling that was on the CodeBackdrop: - removed the red dashed outline - color back to slate-400 @ 45% (subtle, not bright cyan) - font size back to 12px - animation back to 90s - line-number color toned to a darker slate Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
a3e1811c3a |
fix(client): make CodeBackdrop unmissable (debug); fix Dialog a11y
CodeBackdrop visibility:
The previous version used Tailwind opacity-modifier classes
(text-slate-400/70) that might not be getting picked up by the
JIT scanner in some environments. Switched the critical text
styles to inline CSS so they're immune to Tailwind class-
detection issues. Also: a high-visibility red dashed outline on
the backdrop container as a debug aid — if the user can see the
outline, the component is mounting and we know any remaining
issue is a styling tweak. The bright cyan text + 60s scroll
cycle should make motion obvious. Both the outline and the
bright color will be tuned back down once we confirm visibility.
Dialog a11y warnings:
Radix wants DialogContent children to include a `DialogTitle`
primitive (for screen-reader announcement) and either a
`DialogDescription` or an explicit `aria-describedby={undefined}`
(to suppress the missing-description warning). Made DialogHeader
wrap its children in `DialogPrimitive.Title asChild` so the
visual styling stays in the wrapper but the a11y semantic is
correct. Added `aria-describedby={undefined}` as the default on
DialogContent — our modals don't have a meaningful one-sentence
description, and callers that want one can override.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
b45f0d347c |
fix(client): make HMR explicit; brighten code backdrop
Two unrelated fixes the user hit: 1) Vite HMR websocket failing in Firefox. Likely autodetect landing on the wrong host (dual-stack IPv4/IPv6 issue). Pin server.host to 127.0.0.1 and declare server.hmr explicitly (host=localhost, port=5173, protocol=ws, clientPort=5173). 2) CodeBackdrop was effectively invisible. text-fg-muted/40 on the deep bg-elev surface combined to about 0xff-equivalent alpha of ~10%, well below readable threshold. Bumped color token to text-slate-400/70 and font-size to 12px. Added a bottom-edge gradient so the scrolling code dims into the buyables strip rather than getting hard-cut. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |