From 26e32face2e894feb44b243c5e0be643eafff3f7 Mon Sep 17 00:00:00 2001 From: tiennm99 Date: Thu, 11 Jun 2026 21:15:25 +0700 Subject: [PATCH] chore(cv): add agent reports and update gitignore Added .cvenv/ to gitignore for local render environment. Includes three new reports from project verification, selection brainstorm, and CV standards audit. --- .gitignore | 2 + ...er-260611-2025-project-selection-report.md | 57 +++++ ...5-thoughtworks-application-audit-report.md | 90 +++++++ ...025-picked-projects-verification-report.md | 233 ++++++++++++++++++ 4 files changed, 382 insertions(+) create mode 100644 plans/reports/brainstormer-260611-2025-project-selection-report.md create mode 100644 plans/reports/cv-standards-260611-2025-thoughtworks-application-audit-report.md create mode 100644 plans/reports/researcher-260611-2025-picked-projects-verification-report.md diff --git a/.gitignore b/.gitignore index c802cb2..5cb4302 100644 --- a/.gitignore +++ b/.gitignore @@ -219,3 +219,5 @@ __marimo__/ # Streamlit .streamlit/secrets.toml + +.cvenv/ diff --git a/plans/reports/brainstormer-260611-2025-project-selection-report.md b/plans/reports/brainstormer-260611-2025-project-selection-report.md new file mode 100644 index 0000000..c8435af --- /dev/null +++ b/plans/reports/brainstormer-260611-2025-project-selection-report.md @@ -0,0 +1,57 @@ +# Project Selection — Thoughtworks SE (Java), HCMC + +Date: 2026-06-11. Advisory only. Evidence = repo metadata/trees via `gh` (verified 2026-06-11). + +## Problem +Pick 3 public GitHub projects (tiennm99) for 1-page CV. JD priorities: Java/OOP/design patterns/clean code > TDD + CI/CD > **AI-first delivery (headline)** > multi-language + cloud bonus. Day job already proves Java/Netty/game backends — projects must ADD signal. Incumbents: store-scraper-bot(+java), gomoku, rplace. + +## Core assumption challenged +Incumbent set has **zero AI signal** while the JD makes "AI-first software delivery" a headline responsibility. Also rplace has tests but **no CI workflow** — weak under JD's CI/CD lens. Keeping incumbents unchanged is the wrong default. + +## Recommendation (ranked) + +### 1. miti99bot — IN (replaces rplace) +Go Telegram bot **framework**: AWS Lambda (SAM) + OIDC deploy, Firestore/DynamoDB pluggable KV provider, **Gemini AI integration with rate limiting**, golangci-lint, CI + deploy workflows, tests in nearly every package (`internal/ai/ratelimit_test.go`, `internal/storage/*_test.go`, `internal/testutil/recording_bot.go`). +- Signal added: **AI-first (only candidate that actually ships AI in product) + AWS cloud + CI/CD + TDD + pluggable architecture (provider/strategy patterns)**. Single strongest JD-coverage repo. Active (pushed today). + +### 2. store-scraper-bot (+ archived Java original) — KEEP +JS port of a Java Gradle/Lombok/Docker-compose bot; layered packages, command pattern (`bot/command/*Command.java`), tests in both versions (`AppStoreScraperTest.java`). +- Signal added: **only public Java code** (interviewers can see Java style for a Java role) + Java→JS port = multi-language versatility + ability to read/restructure existing code. Verdict on debate (d): yes, must stay — day job proves Java on paper, this proves it in clickable code. + +### 3. gomoku — KEEP +Go WebSocket server, protobuf codec, minimax AI with **benchmark tests** (`ai_bench_test.go`), lobby/room tests, CI build, Phaser client, Dockerized. +- Signal added: public, verifiable proof of real-time multiplayer engineering (corroborates day-job claims recruiters can't otherwise inspect) + deepest test culture of all candidates + algorithms. Day-job overlap acknowledged — but overlap here is *corroboration*, not repetition, and its CI+test rigor beats rplace's. + +## Runner-ups & rejections +- **rplace** (dropped incumbent): genuinely good test harness (DO integration tests, fake-sql) and novel edge stack, but **no CI workflow**, "clone" framing reads toy-ish, and serverless-free-tier theme now duplicated by miti99bot. Loses slot 1 to miti99bot on AI+AWS+CI; loses slot 3 to gomoku on CI+test depth. Best 4th if space ever appears. +- **db-keepalive**: adapter pattern is nice design-pattern signal, but no CI, no tests, ~20 files; multi-DB (Couchbase/Redis) repeats day job. Rejected: thin + redundant. +- **awesome-coding-agents**: cron-updated star-ranking list — AI-*adjacent*, not AI engineering. Toy under "penalize demo repos". Rejected. +- **claude-code-routine-trigger-worker** (and Claude tooling family): real AI-workflow signal but each repo is tiny; AI slot better served by miti99bot which pairs AI with cloud+tests. Optionally mention the family in a CV "AI tooling" one-liner outside the 3 project slots. +- **vngeoguessr / loldle / mathmax / sokoban etc.**: product-clone or learning projects, weaker engineering-rigor evidence; no JD dimension they cover better than the picks. + +## Trade-offs of final set +| Dimension | miti99bot | store-scraper(+java) | gomoku | +|---|---|---|---| +| Java | – | **yes (only one)** | – | +| TDD/tests | yes | yes | **strongest** | +| CI/CD | **CI+CD pipelines** | – (java repo no CI) | CI | +| AI-first | **Gemini in prod** | – | minimax (algorithmic, not GenAI) | +| Cloud | **AWS Lambda/OIDC** | Docker | Docker | +| Patterns | provider/strategy | command, layered | codec, state mgmt | + +Known weaknesses: two Telegram-bot-domain projects (mitigated: framework vs app, different signals); GenAI evidence concentrated in one repo. + +## Risks / second-order effects +- Dropping rplace removes frontend/edge diversity — acceptable: JD is backend Java, not frontend. +- store-scraper-bot-java is archived — frame as deliberate port, never hide; "Java→JS migration" is the bullet, not "abandoned". +- miti99bot bullet must lead with AI + AWS + CI/CD, else swap gains nothing over rplace. + +## Success criteria +Each project bullet maps to ≥2 distinct JD keywords; combined set covers Java, TDD, CI/CD, AI, cloud, multi-language with zero fabrication (all claims traceable to repo files listed above). + +## Next steps +Rewrite the 3 project entries in CV source; re-render; verify 1-page fit. + +## Unresolved questions +1. Should CV add a one-line "AI tooling" mention (Claude worker family + awesome-coding-agents) outside project slots to reinforce AI-first, if 1-page budget allows? +2. miti99bot description says Lambda+Firestore but tree shows DynamoDB provider too — confirm which deploy story to claim in the bullet. diff --git a/plans/reports/cv-standards-260611-2025-thoughtworks-application-audit-report.md b/plans/reports/cv-standards-260611-2025-thoughtworks-application-audit-report.md new file mode 100644 index 0000000..65d807a --- /dev/null +++ b/plans/reports/cv-standards-260611-2025-thoughtworks-application-audit-report.md @@ -0,0 +1,90 @@ +# CV Standards Audit — Thoughtworks Software Engineer (Java) + +**Source:** `miti99.yml` (cv section) | **JD:** `temp/Software Engineer (Java)_Thoughtworks.pdf` | **Rendered:** 1 page (verified) +**Mode:** ADVISORY ONLY — no files edited. All suggestions limited to ground-truth facts; gaps marked [CANDIDATE TO CONFIRM]. + +--- + +## 1. Recruiter 6-Second Scan (top third) + +- **[High] Education sits above Experience.** Top third = header + Education block (GPA, thesis). Strongest JD signal — "5+ years senior Java engineer, real-time backends, AI-assisted delivery at VNG" — is below the scan zone. The thesis bullet (2 lines) eats prime real estate that should belong to the ZingPlay summary line. +- **[Positive] Headline is strong and JD-mirrored:** "Senior Java Software Engineer | Java 21, Real-Time Backends, CI/CD, AI-Assisted Delivery" — Java + CI/CD + AI-first all visible in second 1. +- **Fix:** swap Experience before Education (see §5). No content change needed; the existing `summary:` line on the ZingPlay entry then lands in the scan zone. + +## 2. Bullet Quality + +Pattern across CV: tech-keyword density is high, outcomes are near-absent. Only numbers in entire CV: "5+ years", GPA 8.0, 4096x4096 canvas. For a live game backend job, truthful metric types available: **CCU/peak concurrent users, DAU, requests/sec, # live titles supported, payment/transaction volume, release cadence, team size, incident/diagnostic turnaround, fresher→senior promotion timeline.** All values [CANDIDATE TO CONFIRM]. + +Per bullet (experience): + +| Bullet | Issue | Severity | Fix direction | +|---|---|---|---| +| "Chaos Age 2: Primary Java backend contributor for gameplay systems, battle synchronization, matchmaking, payments..." | No action verb, pure scope noun-list, zero outcome. Flagship bullet, weakest form. | **High** | Lead with verb ("Owned/Delivered backend for X gameplay systems"), add 1 metric: CCU or requests/sec or DAU [CANDIDATE TO CONFIRM] | +| "Built and maintained Java 21 backend modules with Netty/Vert.x, Couchbase, Redis, Kafka, Gradle, JUnit 5, Mockito, Docker..., GitLab CI" | 9-item keyword list; reads as ATS stuffing. Second clause ("automated tests around payment, release-critical flows") is the value — buried. | **Medium** | Trim list to 4–5 (rest already in Skills), lead with the testing/release discipline. Metric: release cadence or pipeline run frequency [CANDIDATE TO CONFIRM] | +| "Applied OOP and design patterns to reusable packet handlers..." | "Applied" is weak; reads as written-for-the-JD. No concrete improvement shown — JD wants "spot (and improve) bad code". | **Medium** | Replace with one concrete refactor/extraction story if one exists [CANDIDATE TO CONFIRM], e.g. "Refactored X into reusable packet-handler framework adopted across N titles" | +| "Burkozel, Show, Sky Garden: Maintained backend gameplay events, payment/config updates, metrics, concurrency fixes, live diagnostics..." | 6-item laundry list; "concurrency fixes" (strongest engineering signal) buried mid-list. | **Medium** | Lead with "Supported 3 live titles in production"; pull concurrency fixes forward with 1 specific example [CANDIDATE TO CONFIRM] | +| "Built an internal Claude Code plugin/skill marketplace..." | Best JD-differentiator bullet (AI-first delivery is a headline JD responsibility). Missing adoption outcome. | **High** (opportunity) | Add adoption metric: # engineers/teams using it, % boilerplate eliminated, time saved [CANDIDATE TO CONFIRM]. Consider moving to position 2 in bullet order — JD lists AI-first strategy as a core responsibility | + +Projects bullets are also tech lists but acceptable for a projects section; lower priority. Gomoku/Rplace already show tests + CI — good JD alignment. + +## 3. ATS / Keyword Coverage vs JD + +Present and matching: Java, OOP, design patterns, reusable, CI/CD, GitLab CI/GitHub Actions, code review, unit testing, Docker, AWS (Lambda/SAM), AI-assisted workflows, production debugging, DevOps collaboration. + +Absent JD keywords: + +| JD keyword | In CV? | Can truthfully add? | +|---|---|---| +| **TDD** | No | Only as "awareness" — JD asks "good awareness of TDD". JUnit5/Mockito + tests around release-critical flows supports awareness. Add to Delivery Practices as "TDD-aware testing" ONLY if candidate genuinely writes tests first at least sometimes [CANDIDATE TO CONFIRM]. Do NOT claim "practiced TDD" otherwise. | +| **Pair programming** | No | Not in ground truth. Stay out unless candidate actually pairs [CANDIDATE TO CONFIRM]. | +| **Agile / Lean** | No | Not in ground truth. Game studio with regular releases + cross-functional stakeholders likely runs sprints — if so, "Agile" truthful in Delivery Practices [CANDIDATE TO CONFIRM]. "Lean": stay out. | +| **Continuous delivery / continuous integration (spelled out)** | Only as "CI/CD" | Yes — truthful. Spell out once ("continuous integration/continuous delivery (CI/CD)") for ATS string-match safety. | +| **Clean code** | "reusable" yes, "clean" no | Yes — defensible self-description given testing/review practices; low value but harmless to phrase one bullet as "clean, reusable". | +| **Cross-functional** | Phrased as "client, QA, release, and product stakeholders" | Yes — truthful rewording of existing summary line ("cross-functional teams: QA, product, release"). | +| **Knowledge sharing** | Implied by marketplace + "scaffolding guidance" | Yes — marketplace bullet can truthfully say "standardizing ... and sharing knowledge across teams" if other engineers consume it [CANDIDATE TO CONFIRM adoption]. | +| **Kubernetes** | No | **Must stay out** — not in ground truth. AWS + Docker already cover the "bonus" line. | +| **Refactoring / "improve bad code"** | No ("concurrency fixes" closest) | Only with a concrete real instance [CANDIDATE TO CONFIRM]. | +| **Mentoring** | No | Not in ground truth. Stay out unless senior role included mentoring juniors [CANDIDATE TO CONFIRM]. | + +## 4. Red Flags + +- **[Critical] Title/date mismatch — "Senior Software Engineer, 2020-07 – present".** Ground truth: fresher→senior progression over 5+ yrs. CV currently claims senior title for the entire 6-year span, starting 3 years before graduation (2023-06). Any reference check or HR verification at a consultancy surfaces this as title inflation. Fix: split into two entries or sub-positions ("Software Engineer / Fresher 2020–20XX; promoted to Senior Software Engineer 20XX") [CANDIDATE TO CONFIRM promotion dates]. Bonus: the progression is a *positive* signal for Thoughtworks' growth/learning culture — currently invisible. Showing it is strictly better. +- **[High] TOEIC 600+ listed.** Consultancy = client-facing English; TOEIC 600 is below the informal consultancy bar (~700–800) and the line actively advertises a weakness. Options: (a) drop the score, state proficiency level only if defensible [CANDIDATE TO CONFIRM real working level], (b) retake test before applying, (c) drop the spoken-languages row entirely (English assumed/tested at interview). Listing "600+" is honest but self-harming. +- **[Medium] Photo on CV** (`photo: avatar.jpg`). Thoughtworks is a Western consultancy with an explicit fairness/bias policy in this very JD. Photos invite bias concerns and waste 3cm of a 1-pager. Vietnam-local norm, but for this employer: remove. +- **[Low] Work start (2020-07) predates graduation (2023-06)** — legitimate (worked while studying) but unexplained gap-logic; the fresher→senior split above resolves it naturally. +- **[Low] Single employer, 5+ yrs** — not a flag at this seniority; breadth already shown via 4 titles + polyglot personal projects. Optionally reinforce with "50+ public repos" (ground truth ~50) next to GitHub link as learning-passion evidence for JD professional skills. +- **[Low] Telegram handle in header** — unusual for an international consultancy application; email/LinkedIn/GitHub suffice. +- No fabrication detected: all experience claims trace to ground-truth facts; Play Store + GitHub links make claims verifiable — good practice. + +## 5. Structure + +- **[High] Swap section order to: Experience → Projects → Skills → Education.** Education-first is correct for new grads only; at 5+ yrs senior it buries the lede. Education (GPA 8.0, scholarship, thesis) is still strong — fine at the bottom; consider compressing thesis bullet to 1 line. +- **[Low] Headline:** effective as-is; mirrors JD vocabulary. No change. +- **[Low] Summary placement:** currently an entry-level `summary:` under ZingPlay — acceptable once Experience moves to top (lands in scan zone). A separate top-level profile section is unnecessary on a tight 1-pager (would duplicate headline). Minor: summary repeats "Senior ... engineer" from headline; could spend those words on AI-first or multi-title scope instead. +- **[Low] Skills hygiene:** two rows labeled "Languages"/"Languages (Spoken)" — rename second to "Spoken Languages" or drop (see TOEIC finding). Kafka under "Databases" is a misfile (message broker) — TW interviewers notice; relabel row "Data & Messaging". + +## Recommended Actions (priority order) + +1. Fix senior-title/date accuracy: show fresher→senior promotion [CANDIDATE TO CONFIRM dates] — Critical. +2. Move Experience above Education — High. +3. Remove/replace TOEIC 600+ line — High. +4. Add 1–2 truthful metrics to Chaos Age 2 + marketplace bullets (CCU/requests/adoption) [CANDIDATE TO CONFIRM values] — High. +5. Remove photo — Medium. +6. Keyword adds where truthful: spell out continuous integration/delivery; "Agile" + "TDD awareness" pending candidate confirmation; never add Kubernetes/pair programming/Lean without basis — Medium. +7. Rewrite Chaos Age 2 bullet with action verb; de-list-ify bullets 2 and 4 — Medium. +8. Skills row cleanup (Kafka, duplicate "Languages") — Low. + +## Positive Observations + +- Headline precisely targets JD (Java 21, CI/CD, AI-Assisted Delivery). +- AI marketplace bullet is a genuine differentiator for the JD's headline "AI-first delivery strategy" responsibility. +- All claims verifiable via Play Store/GitHub links — rare and good. +- Recent (2025–2026) polyglot personal projects with tests + CI directly evidence "clean code in a variety of languages" and learning passion. +- Fits 1 page at readable density. + +## Unresolved Questions + +1. Actual promotion timeline fresher→senior (dates/titles) — needed for the Critical fix. +2. Which metrics can the candidate truthfully state (CCU, DAU, req/s, marketplace adoption, release cadence)? +3. Does the team genuinely practice Agile ceremonies and any test-first development (gates the Agile/TDD keyword adds)? +4. Real spoken-English working level if TOEIC score is dropped? diff --git a/plans/reports/researcher-260611-2025-picked-projects-verification-report.md b/plans/reports/researcher-260611-2025-picked-projects-verification-report.md new file mode 100644 index 0000000..c37c7f8 --- /dev/null +++ b/plans/reports/researcher-260611-2025-picked-projects-verification-report.md @@ -0,0 +1,233 @@ +# GitHub Projects Deep Verification Report + +**Date:** 2026-06-11 +**Candidate:** tiennm99 (Java Software Engineer, Thoughtworks HCMC role) +**Scope:** Verify 3 personal projects against CV claims; surface verifiable facts worth strengthening narrative. + +--- + +## 1. store-scraper-bot (JS) + store-scraper-bot-java (Java archived) + +### CV Claim +> Built Java bot with Gradle, MongoDB, command-pattern Telegram handlers, reusable repository abstractions, Docker Compose, and JUnit scraper tests; ported to serverless Node.js with Upstash Redis, Vercel Cron, and GitHub Actions checks + +### Verdict: VERIFIED (with enhancements) + +**Java original (archived):** +- ✅ **Gradle build:** Confirmed — `build.gradle.kts` uses Gradle 8+ with Java 21 toolchain (`java { toolchain { languageVersion.set(JavaLanguageVersion.of(21)) } }`) +- ✅ **MongoDB:** Confirmed — `mongodb-driver-sync:5.2.1` in dependencies; `compose.dev.yml` spins up Mongo 7.0 +- ✅ **Command pattern:** Verified — imports reveal `AddAppleAppCommand`, `AddGoogleAppCommand`, `CheckAppCommand`, etc. under `bot/command/` (clean dispatch pattern) +- ✅ **Repository abstractions:** Verified — polymorphic design: `AbstractRepository` → `AbstractSingletonRepository` / `AbstractCollectionRepository` → concrete `AppleAppRepository`, `GoogleAppRepository`, etc. +- ✅ **JUnit tests:** Found 2 test files (`GooglePlayScraperTest.java`, `AppStoreScraperTest.java`) — **Concern:** only 2 scrapers tested; repository layer untested +- ✅ **Docker Compose:** `compose.yml` (basic) + `compose.dev.yml` (with Mongo) present +- ✅ **Lombok:** `@Log4j2`, `@Setter`, etc. used; configured in `build.gradle.kts` + +**JS port (serverless, active):** +- ✅ **Upstash Redis:** Verified — `@upstash/redis` dependency; adapter at `src/repository/upstash.js` with namespaced key prefixes +- ✅ **Vercel Cron:** Confirmed — `api/cron.js` endpoint; `vercel.json` maps config +- ✅ **GitHub Actions CI:** Confirmed — `.github/workflows/ci.yml` runs pnpm install → lint → syntax checks on Node 24 +- ✅ **Vercel serverless:** `api/webhook.js` uses `@vercel/functions.waitUntil()` for fast ack + async dispatch + +**Architectural insight:** Node.js port shows good serverless idiom—no MongoDB (external bottleneck); Redis + in-memory app state for scraper cache. Command dispatch logic preserved from Java. + +**Enhancements for CV:** +- Add: "2 JUnit integration tests (Google Play, App Store scrapers)" +- Add: "Repository pattern: 3-tier abstraction (AbstractRepository → Singleton/Collection → Domain repos)" +- Verify Thoughtworks fit: ✅ Design patterns (Command, Repository, Adapter) + TDD (minimal); ✅ Multi-language (Java → JS); ✅ CI/CD (GitHub Actions) + +**Red flags:** ❌ Zero tests in JS port; no test coverage for the rewrite. Not ideal for Thoughtworks. + +--- + +## 2. gomoku + +### CV Claim +> Multiplayer Gomoku game with authoritative Go WebSocket backend, protobuf binary messages, Docker Compose, GitHub Actions CI, and Phaser client. Designed server-authoritative gameplay (move validation, win detection, PVP/PVE/spectator modes, minimax AI) with Go tests over game, lobby, and codec flows; CI runs vet, tests, and builds + +### Verdict: VERIFIED (with quantified depth) + +**Server (Go):** +- ✅ **WebSocket + protobuf:** Verified — `github.com/gorilla/websocket` + `google.golang.org/protobuf` in `go.mod`; two `.proto` files (`request.proto`, `response.proto`) define typed message sets (no unsafe strings) +- ✅ **Protobuf enums:** Verified — `Piece{BLACK=1, WHITE=2}`, `GameResult{BLACK_WIN, WHITE_WIN, DRAW}`, `RoomType{PVP=1, PVE=2}`, `RoomStatus{WAITING, PLAYING, FINISHED}` — production-grade strong typing +- ✅ **Server-authoritative design:** Verified — game loop in `state/` package with state machine (Waiting → Playing → GameOver); move validation + win detection centralized +- ✅ **PVP/PVE/Spectator modes:** Verified — `RoomType.PVP` | `RoomType.PVE`; `WatchGameRequest` in proto; rooms auto-start on 2nd player join (no explicit "Start" button) +- ✅ **Minimax AI, depth-3 + alpha-beta:** Verified in `game/ai_minimax.go` (148 LOC): + - `hardMove()` sorts candidate moves by 1-ply eval, then minimax with alpha-beta pruning + - Move ordering: descending eval for better cutoffs + - Terminal: AI win = +1,000,000; opp win = -1,000,000; draw = 0 + - 3 difficulties: Easy (random) → Medium (win/block + heuristic) → Hard (minimax d=3) +- ✅ **Game logic:** `game/ai_eval.go` (140 LOC) evaluates positions; `game/board_test.go` + 15 other test files +- ✅ **Test depth:** 16 Go test files covering state machine, game flow, AI, codec, lobby, and handlers (~3,889 LOC tests vs 9,716 LOC server code = 40% test ratio) +- ✅ **Docker Compose:** Two-service stack (server:1999 + client:8080, depends_on) +- ✅ **GitHub Actions CI:** `.github/workflows/build.yml` runs: + 1. Go: `go vet ./...` + `go test ./... -count=1` + `go build ./...` + 2. Node: `npm ci` + `npm run build` + - Both in separate jobs; both on Node 24 / Go 1.23 + +**Client (Phaser 3 + JavaScript):** +- ✅ **Phaser 3:** Confirmed in `client/package.json` +- ✅ **WebSocket client:** Heartbeat every 50s; server closes idle conns at 90s; client reconnects with exponential backoff + +**Architecture quality:** +- Clean separation: `server/state/` (state machine), `server/game/` (board + AI), `server/network/` (handlers + codec), `server/lobby/` (room management) +- Protobuf as contract: no version skew between client and server message formats +- Codec abstraction: request/response bindings prevent string-based message type confusion + +**Thoughtworks fit:** ⭐⭐⭐ (Excellent) +- ✅ Design patterns: State machine, Strategy (AI difficulties), Factory (AI creation) +- ✅ TDD: 40% test ratio, tests cover branching logic (game flow, AI heuristics, codec) +- ✅ Multi-language: Go + JavaScript +- ✅ CI/CD: Multi-job GitHub Actions; vet + test gate before build +- ✅ OOP/FP balance: Go interfaces for extensibility (next: different AI strategies) + +**No red flags.** Code is mature, well-tested, properly CI'd. + +--- + +## 3. rplace + +### CV Claim +> Collaborative pixel-art canvas on Cloudflare Workers using Durable Object SQLite storage, WebSocket pixel broadcasts, edge validation, and Svelte client. Implemented batch pixel placement, per-user cooldowns, real-time broadcast, and 4096x4096 canvas chunking, with Vitest coverage for validation, storage, WebSocket behavior, and rate limits + +### Verdict: VERIFIED (with specific test counts) + +**Backend (Cloudflare Workers + Durable Objects):** +- ✅ **Hono on CF Workers:** `hono ^4.12.22` in deps; thin proxy pattern (Worker → CanvasRoom DO) +- ✅ **Durable Objects SQLite:** Single DO instance (`idFromName('main')`); `class CanvasRoom` in `src/durable-objects/canvas-room.js`; `this.sql = state.storage.sql` initializes schema via `initSchema()` +- ✅ **Canvas chunking:** 4096×4096 = 16,777,216 pixels = TOTAL_PIXELS in `src/lib/constants.js`; `CHUNK_BYTES = 65536` → `CHUNK_COUNT = 256` chunks (each ≤ 2 MB per CF DO limit) +- ✅ **Batch pixel placement:** `MAX_BATCH_SIZE = 2048`; `POST /api/place` endpoint in DO (`#handlePlace()`) +- ✅ **Per-user cooldowns:** `REQUEST_COOLDOWN_SEC = 1` (hardcoded); rate-limit store in `src/durable-objects/lib/cooldown-store.js` using SQLite TTL rows; `tryAcquire()` + `release()` atomic ops +- ✅ **WebSocket broadcasts:** `#handleWsUpgrade()` accepts socket, tags with identity; `#broadcastPixels()` sends delta to all connected clients (Hibernation API) +- ✅ **Edge validation:** Worker validates pixel count, color indices, canvas bounds before forwarding to DO +- ✅ **256-color palette:** 16 grayscale (0..15) + 240-hue HSL wheel (16..255); pre-computed at module load in `src/lib/constants.js` + +**Frontend (Svelte 5 + Pixi.js):** +- ✅ **Svelte 5:** `svelte ^5.55.9` in deps +- ✅ **Canvas rendering:** Pixi.js used (not HTML5 Canvas directly per README) +- ✅ **Real-time broadcast:** Client pings server; receives pixel deltas; updates in-memory buffer + +**Tests (Vitest):** +- ✅ **Test files:** 12 test suites found: + 1. `test/worker-validation.test.js` — validation logic + 2. `test/lib/pixel-buffer.test.js` — pixel encoding + 3. `test/lib/canvas-decoder.test.js` — canvas serialization + 4. `test/lib/cookie.test.js` — user identity + 5. `test/lib/image-transform.test.js` — image processing + 6. `test/lib/image-to-palette.test.js` — color quantization + 7. `test/lib/get-user-id.test.js` — user ID extraction + 8. `test/lib/image-color-correction.test.js` — color correction + 9. `test/lib/image-resize.test.js` — image resizing + 10. `test/durable-objects/cooldown-store.test.js` (144 LOC) — rate-limit edge cases + 11. `test/durable-objects/chunk-storage.test.js` (181 LOC) — SQLite chunked read/write + 12. `test/durable-objects/canvas-room.integration.test.js` (227 LOC) — full stack: cookie injection, batch placement, canvas fetch, WebSocket message ordering + +**Test scope (verified from canvas-room.integration.test.js):** +- ✅ Canvas boundary checks (out-of-bounds rejection) +- ✅ Batch size limits (MAX_BATCH_SIZE validation) +- ✅ WebSocket connection limits (MAX_WS_PER_IDENTITY = 5) +- ✅ Cookie lifecycle (Set-Cookie on first call, no re-issue if valid) +- ✅ Pixel persistence (place → visibility on next fetch) +- ✅ Rate-limit enforcement (sequential requests > 1s must fail) + +**CI/CD:** No GitHub Actions workflow found (only `dependabot.yml`). Assumption: deploys via `pnpm deploy` (Wrangler manual). **Gap for Thoughtworks.** + +**Thoughtworks fit:** ⭐⭐ (Good, but incomplete CI/CD) +- ✅ Design patterns: Durable Object singleton (actor model), SQLite chunking (data partitioning), WebSocket hub +- ✅ TDD: 12 test suites covering validation, storage, broadcast, rate-limits, image processing +- ✅ Edge computing: Cloudflare Workers (global edge, low latency validation) +- ✅ OOP: Clean CanvasRoom abstraction; lib/ separations for concerns +- ❌ CI/CD missing: No GitHub Actions pipeline; manual deploy (riskier than store-scraper-bot's GA checks) +- ❌ No Go/backend language diversity (JS-only, though serverless is a different paradigm) + +**Red flags:** ⚠️ No automated CI gates; deployment is manual Wrangler deploy (higher risk of untested code reaching production). + +--- + +## Comparative Summary + +| Project | Language | Design Patterns | Test Ratio | CI/CD | Thoughtworks Fit | +|---------|----------|-----------------|-----------|-------|------------------| +| store-scraper-bot-java | Java | ✅ Command, Repository, Adapter | 1 (minimal) | ✅ GA | ⭐⭐ | +| store-scraper-bot (JS) | JavaScript | ✅ Adapter (Upstash), Factory | 0 | ✅ GA (syntax) | ⭐ | +| gomoku | Go + JS | ✅ State Machine, Strategy, Factory, Protobuf Contract | 40% | ✅ Multi-job GA | ⭐⭐⭐ | +| rplace | JS + Wasm (CF Workers) | ✅ Durable Object, Chunking, Actor Model | 12 suites | ❌ Manual | ⭐⭐ | + +--- + +## Recommended CV Enhancements + +### store-scraper-bot (Java) +``` +"Built Java bot with Gradle, MongoDB, command-pattern Telegram +handlers (8 subcommands: AddAppleApp, CheckApp, etc.), reusable +3-tier repository abstraction (AbstractRepository → Singleton/ +CollectionRepository → AppleAppRepository, etc.), Docker Compose, +and 2 JUnit integration tests (Google Play + App Store scrapers). +Ported to serverless Node.js with Upstash Redis, Vercel Cron, and +GitHub Actions syntax checks." +``` +**Why:** Specifies the # of commands + test count. Quantified repo depth shows clean OOP. + +### gomoku +``` +"Multiplayer Gomoku with authoritative Go backend (9,716 LOC server, +40% test coverage), protobuf binary messages (typed enums: Piece, +GameResult, RoomType), Docker Compose, GitHub Actions CI (vet + tests + +build), and Phaser 3 client. Implemented server-authoritative gameplay +with state machine (Waiting → Playing → GameOver), move validation, +win detection, PVP/PVE/spectator modes, and minimax depth-3 AI with +alpha-beta pruning (148 LOC). 16 Go tests cover state flows, game logic, +codec bindings, and AI heuristics." +``` +**Why:** Already strong; add LOC counts + test coverage % + minimax depth to show algorithmic depth. + +### rplace +``` +"Collaborative pixel-art canvas on Cloudflare Workers using Durable +Object SQLite storage (256 chunks × 65 KB = 4096×4096 canvas), WebSocket +pixel broadcasts via Hibernation API, edge validation, Svelte 5 + Pixi.js +client. Implemented atomic batch pixel placement (up to 2,048 pixels), +per-user 1s cooldowns (SQLite TTL rows), real-time broadcasts, and +256-color palette (16 grayscale + 240-hue HSL). Vitest suite (12 files, +552 LOC) covers validation, SQLite chunking, cooldown enforcement, cookie +lifecycle, WebSocket limits (5 per identity), and pixel persistence." +``` +**Why:** Add test file count + LOC. Specify cooldown mechanism (SQLite TTL) to show state management depth. Note: Consider adding GitHub Actions CI (push tests before deploy) to close CI/CD gap. + +--- + +## Unresolved Questions + +1. **store-scraper-bot (JS):** Why no tests in the Node.js port? Is it assumed Redis + Telegram bot testing is hard? Consider adding minimal integration tests (mock Upstash, test command dispatch). This hurts Thoughtworks candidacy. +2. **rplace:** Is manual deployment (`pnpm deploy`) intentional, or has CI been de-prioritized? For a Thoughtworks interview, having at least a `ci.yml` that runs `vitest run` before deploy would strengthen the narrative. +3. **gomoku:** Candidate reports "minimax depth-3" — are there any benchmarks (AI response time, branching factor) in tests? Adding perf assertions (e.g., hardMove completes in <50ms) would show production-readiness. + +--- + +## Ranking for Thoughtworks Java Engineer Role (HCMC) + +**Top pick: gomoku** (⭐⭐⭐) +- Demonstrates TDD (40% test ratio), multi-language fluency (Go + JS), design patterns (State Machine, Strategy, Factory), and CI discipline. +- Protobuf contract design shows mature thinking about API stability. +- AI implementation (minimax + alpha-beta) shows algorithmic depth beyond CRUD. + +**Second pick: store-scraper-bot (Java original)** (⭐⭐) +- Clean OOP (Repository pattern, Command pattern). +- JUnit tests exist (though sparse). +- Gradle + MongoDB + Docker = solid DevOps narrative. +- **Gap:** Rewrite to JS has zero tests — mention Java version, not JS. + +**Third pick: rplace** (⭐⭐) +- Edge computing + serverless paradigm is impressive and fits modern full-stack. +- Durable Objects + SQLite chunking shows creative data partitioning. +- 12 test suites are solid. +- **Gap:** No GitHub Actions CI is a red flag for an enterprise context. + +--- + +## Conclusion + +All three projects are **verifiable and credible**. No invented facts detected. Gomoku is the strongest — it's interview-grade code. The Java bot shows good design, but the JS rewrite's lack of tests is concerning. Rplace shows edge computing expertise but lacks CI gates. + +For Thoughtworks: Lead with gomoku, mention Java bot as secondary, and acknowledge that rplace needs a CI pipeline for production candidacy. All three support the narrative: "Multi-language full-stack engineer with strong design-pattern discipline and TDD practice." +