{
  "version": "https://jsonfeed.org/version/1.1",
  "title": "James M — Project Releases",
  "home_page_url": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/",
  "feed_url": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/feed.json",
  "icon": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/apple-touch-icon.png",
  "favicon": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/favicon.png",
  "description": "Release notes across 19 projects in James M's portfolio, shipped continuously by an autonomous burndown fleet.",
  "language": "en",
  "authors": [
    {
      "name": "James M",
      "url": "https://github.com/virtualhealthcitizen"
    }
  ],
  "items": [
    {
      "id": "lrge@v0.3.0",
      "url": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/#/project/lrge",
      "title": "LRGQ v0.3.0",
      "content_text": "- chore: bump version to 0.3.0\n- chore(release): correct the build system's self-description + v0.3.0 notes\n- [GD-2] Bug hunt: a nested link crashed the app — and my first fix silently did nothing\n- fix(text): substitute glyphs the face cannot draw, instead of drawing a box\n- fix(gfx): the raylib Manual said \"File ? Save\" — and SFML said \"File [] Save\"\n- chore(validation): editor-validation pass — 2 delivered, 0 reopened, 0 skipped\n- fix(gfx): a >16-point polygon drew nothing on raylib — and one lead that was wrong\n- [GD-2] Bug hunt: no new defect — a dissolved candidate and a confirmed lead\n- chore(ci): build the raylib backend and its probe — the guard nothing was building\n- fix(input): holding Escape to leave Play no longer closes the application\n- [GD-2] Bug hunt: the raylib editor maximised over the Windows taskbar\n- chore(validation): editor-validation pass — 2 delivered, 0 reopened, 0 skipped",
      "image": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/og/lrge.svg",
      "date_published": "2026-07-19T14:48:08.000Z",
      "tags": [
        "C++"
      ]
    },
    {
      "id": "pipeworks@v0.10.0",
      "url": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/#/project/pipeworks",
      "title": "Pipeworks v0.10.0",
      "content_text": "- chore(release): cut v0.10.0 \"AAA UI & Juice\"; open Release 11 \"Mastery\"\n- feat(sim): per-pipeline execution history — and reconcile a backlog that had drifted (#118) (#118)\n- chore(render): pin the renderer to WebGL, and retire the atlas half of the graphics-foundation item (#116)\n- feat(mastery): percentile bars — the scorecard says where a run SITS, not just its number (#117)\n- feat(render): BitmapText on-board labels — crisp under zoom (#113) (#113)\n- feat(render): per-lane dirty-tracking — the board stops redrawing what hasn't changed (#114)\n- fix(mastery): a personal best has to be earned — two of three axes were free 100s (#115)\n- hunt(rating): the personal best is warm-up-dominated — and only profile-fair by accident (#112)\n- hunt(render): the board was contradicting the HUD (#111) (#111)\n- feat(audio): sound one-shots — the interaction layer gets a voice (#110)\n- chore(release): roadmap to v1.0.0 + an automated, event-driven release cadence (#109)\n- feat(render): glow/bloom layer — the board emits light (#108) (#108)",
      "image": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/og/pipeworks.svg",
      "date_published": "2026-07-18T21:48:07.000Z",
      "tags": [
        "TypeScript"
      ]
    },
    {
      "id": "pipeworks@v0.9.0",
      "url": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/#/project/pipeworks",
      "title": "Pipeworks v0.9.0",
      "content_text": "- chore(release): cut v0.8.0 \"Dependencies\" + v0.9.0 \"Onboarding & Teach\"; open v0.10.0 (#105)\n- hunt(ui): probe the R10 UI surface — no defect found (#104) (#104)\n- feat(ui): context menu on stage nodes — quick actions at the cursor (#103) (#103)\n- feat(ui): type scale — 15 ad-hoc font sizes collapse onto named steps (#102) (#102)\n- feat(ui): density toggle — density is a setting, not a fixed choice (#101) (#101)\n- hunt(onboarding): the tutorial was taxing the player who took it (#100) (#100)\n- feat(onboarding): invert the opening — hand-deploy, then get handed the machine (#99) (#99)\n- feat(ui): progressive UI disclosure — the HUD earns its complexity (#98) (#98)\n- feat(ui): glass surfaces — the design language's signature move (#97) (#97)\n- feat(ui): a held service explains itself — name the blocking dependency (#96) (#96)\n- feat(render): impact juice — failure cue + event-driven screen shake (#95) (#95)\n- feat(render): board juice — a success pop + a homegrown easing helper (#94) (#94)",
      "image": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/og/pipeworks.svg",
      "date_published": "2026-07-18T19:09:48.000Z",
      "tags": [
        "TypeScript"
      ]
    },
    {
      "id": "processing-sandbox@v0.6.1",
      "url": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/#/project/processing-sandbox",
      "title": "sketchbook v0.6.1",
      "content_text": "- docs(roadmap): GFX-067 (reduced-motion) now complete across all 7 reel sketches\n- gfx(G4·GFX-067): extend reduced-motion to the rest of the reel (Tree Heights + 2 generative)\n- docs(roadmap): GFX-067 (reduced-motion) opened — done on the 4 spring reel sketches\n- gfx(G4·GFX-067): prefers-reduced-motion support on the 4 spring reel sketches\n- docs(roadmap): GFX-061 spring physics now on 4 sketches (+ Dijkstra node-settle pop)\n- gfx(G4·GFX-061): node-settle spring-pop on Dijkstra 3D\n- docs(roadmap): GFX-061 spring physics now on 3 sketches (+ Hanoi landing squash); GFX-063 overshoot has a 3rd case\n- gfx(G4·GFX-061/063/068): landing squash-spring on Hanoi disk placement\n- fix(collection): auto-run 3 more interaction-gated sketches — 0 passive-viewer blanks left\n- gfx(GFX-001): antialiasing sweep — MSAA on all 96 remaining WEBGL sketches\n- fix(collection): auto-run the 7 interaction-gated sketches (passive-viewer fix)\n- fix(collection): clear the last 4 hard-broken sketches — collection now 0 errors (111 sketches)",
      "image": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/og/processing-sandbox.svg",
      "date_published": "2026-07-18T17:06:46.000Z",
      "tags": [
        "JavaScript"
      ]
    },
    {
      "id": "processing-sandbox@v0.6.0",
      "url": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/#/project/processing-sandbox",
      "title": "sketchbook v0.6.0",
      "content_text": "- docs(roadmap): GFX-061 spring physics now on 2 sketches (N-Queens + Consistent Hashing); GFX-063 overshoot started — pending v0.6.0\n- gfx(G4·GFX-061/063): spring-pop on Consistent Hashing node join/leave\n- docs(roadmap): G4 opened — spring physics (GFX-061) done on N-Queens; pending reel deploy\n- gfx(G4·GFX-061): spring-physics motion on N-Queens — the G4 opener",
      "image": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/og/processing-sandbox.svg",
      "date_published": "2026-07-18T06:25:23.000Z",
      "tags": [
        "JavaScript"
      ]
    },
    {
      "id": "processing-sandbox@v0.5.0",
      "url": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/#/project/processing-sandbox",
      "title": "sketchbook v0.5.0",
      "content_text": "- docs(roadmap): GFX-050 IBL now on 3 sketches (Hanoi + N-Queens + Dijkstra) — pending v0.5.0 deploy\n- gfx(G3): image-based lighting + auto-run on Dijkstra 3D — third G3 sketch\n- docs(roadmap): GFX-050 IBL now on 2 sketches (Hanoi + N-Queens) — both pending the v0.5.0 reel deploy\n- gfx(G3): image-based lighting on N-Queens — second G3 sketch\n- docs(roadmap): G3 opened — IBL done on Hanoi (GFX-050/051); feasibility correction: IBL/materials are 1.7-safe, not needs-2.x (only shader hooks need 2.0)\n- gfx(G3): image-based lighting on Hanoi Rings — the G3 (lighting & materials) opener",
      "image": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/og/processing-sandbox.svg",
      "date_published": "2026-07-18T05:35:44.000Z",
      "tags": [
        "JavaScript"
      ]
    },
    {
      "id": "processing-sandbox@v0.4.2",
      "url": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/#/project/processing-sandbox",
      "title": "sketchbook v0.4.2",
      "content_text": "- docs(roadmap): GFX-036 chromatic aberration done (Shader Sphere composite) — built 8042061, pending reel deploy\n- gfx(G2·GFX-036): chromatic aberration on the Shader Sphere composite\n- docs(roadmap): GFX-033 DoF done (tilt-shift on Tree Heights; screen-Y depth proxy for the fixed camera) — built 538eddd, pending reel deploy\n- gfx(G2·GFX-033): tilt-shift depth-of-field on Tree Heights",
      "image": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/og/processing-sandbox.svg",
      "date_published": "2026-07-18T04:25:45.000Z",
      "tags": [
        "JavaScript"
      ]
    },
    {
      "id": "processing-sandbox@v0.4.1",
      "url": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/#/project/processing-sandbox",
      "title": "sketchbook v0.4.1",
      "content_text": "- perf(hashing): pixelDensity(1) on Consistent Hashing — the \"slows my computer\" fix\n- docs(roadmap): GFX-035 — broad grade-via-filter() deferred (subtle on dark bgs + adds a pass); keep it in-composite (sphere) or via the Bench post() chain\n- gfx(G2): reusable cinematic grade (vignette + film grain + cool grade) on the bloom composite",
      "image": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/og/processing-sandbox.svg",
      "date_published": "2026-07-18T03:36:31.000Z",
      "tags": [
        "JavaScript"
      ]
    },
    {
      "id": "pipeworks@v0.8.0",
      "url": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/#/project/pipeworks",
      "title": "Pipeworks v0.8.0",
      "content_text": "- feat(deps): dependency cycle guard — reject a loop that would deadlock (v0.8.0 slice 2a) (#83)",
      "image": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/og/pipeworks.svg",
      "date_published": "2026-07-18T02:57:42.000Z",
      "tags": [
        "TypeScript"
      ]
    },
    {
      "id": "processing-sandbox@v0.4.0",
      "url": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/#/project/processing-sandbox",
      "title": "sketchbook v0.4.0",
      "content_text": "- docs(roadmap): GFX-032 bloom done @ 60fps (2-pass; FBO-bind-count was the cost)\n- perf(G2): bloom to 60fps — collapse the pipeline from 8 framebuffer passes to 2\n- perf(G2): HALF_FLOAT bloom buffers + fewer blur iterations\n- gfx(G2): real framebuffer BLOOM on the Shader Sphere (post-processing proof)",
      "image": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/og/processing-sandbox.svg",
      "date_published": "2026-07-18T02:21:49.000Z",
      "tags": [
        "JavaScript"
      ]
    },
    {
      "id": "pipeworks@v0.7.0",
      "url": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/#/project/pipeworks",
      "title": "Pipeworks v0.7.0",
      "content_text": "- chore(release): cut v0.6.0 \"Optimization\" + v0.7.0 \"Legibility & Playability\" (#80) (#80)\n- feat(techtree): two play-changing research nodes — a real progression fork (#79) (#79)\n- hunt(pressure): lock the demand-pressure antagonist at fixed, scarce capacity (#78)\n- feat(game): execution history — an audit log of run outcomes (#77) (#77)\n- feat(game): Concourse wallboard — a zoomed-out overview of every service's health (#76) (#76)\n- feat(a11y): colour-blind-safe status — a shape/glyph channel on every status cue (#75) (#75)\n- feat(game): demand pressure — a mounting antagonist so standing still loses (#74) (#74)\n- docs(manual): a comprehensive Player's Manual (#73) (#73)\n- feat(game): HUD alert strip — the one thing to fix now (+ fix the stale version footer) (#72) (#72)\n- feat(game): onboarding — a first-run welcome/coach + a help & glossary overlay (#71) (#71)\n- feat(game): juice + audio — a deploy that ships finally sounds and pops (#70) (#70)\n- feat(game): directives — a milestone ladder that gives the session a north star (#69) (#69)",
      "image": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/og/pipeworks.svg",
      "date_published": "2026-07-18T01:29:01.000Z",
      "tags": [
        "TypeScript"
      ]
    },
    {
      "id": "processing-sandbox@v0.3.0",
      "url": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/#/project/processing-sandbox",
      "title": "sketchbook v0.3.0",
      "content_text": "- gfx(G0a): bump p5 1.6.0 → 1.11.13 across all sketches — v0.3.0 (the upgrade unlock)\n- tools: add the smoke-test harness (GFX-020) + p5 1.6.0 baseline\n- docs(roadmap): G0 upgrade-readiness audit — split the p5 upgrade, 1.7.x first\n- Add 8 WIP sketches + regenerate the launcher (106 → 114)",
      "image": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/og/processing-sandbox.svg",
      "date_published": "2026-07-18T01:05:39.000Z",
      "tags": [
        "JavaScript"
      ]
    },
    {
      "id": "pipeworks@v0.6.0",
      "url": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/#/project/pipeworks",
      "title": "Pipeworks v0.6.0",
      "content_text": "- feat(promotion): environments as board zones — group a cross-env service's lanes into a framed zone (slice 2) (#68) (#68)\n- feat(promotion): cross-execution promotion — pipeline triggers, dev→staging→prod as linked pipelines (slice 1) (#67) (#67)\n- feat(agents): agent specialisation — a compute-optimised class (concurrency vs compute) (#66) (#66)\n- hunt(upgrades): lock the upgrade economy — no dominant upgrade, no runaway (#65) (#65)\n- feat(quality): build-reliability tiers — invest to roll better builds (#64) (#64)\n- hunt(integration): lock the v0.5.0/v0.6.0 stack under aggressive combined play (#63) (#63)\n- feat(upgrades): speed modules — cut stage duration at a compute cost (#62) (#62)",
      "image": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/og/pipeworks.svg",
      "date_published": "2026-07-17T22:51:36.000Z",
      "tags": [
        "TypeScript"
      ]
    },
    {
      "id": "pipeworks@v0.5.0",
      "url": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/#/project/pipeworks",
      "title": "Pipeworks v0.5.0",
      "content_text": "- chore(release): cut v0.5.0 \"Promotion\" + open Release 6 — v0.6.0 \"Optimization\" (#61) (#61)\n- feat(canary): automated canary analysis — a scored, non-dominant promotion gate (#60) (#60)\n- hunt(regions): per-region queue cap — one unstaffed region no longer starves the org (#59) (#59)\n- feat(regions): per-region agent pools — staff the regions you open (slice 2c) (#58) (#58)\n- hunt(promotion): balance probe — a real tradeoff, with sound coverage (#57) (#57)\n- feat(promotion): multi-environment promotion — dev → staging → prod trains (#56) (#56)",
      "image": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/og/pipeworks.svg",
      "date_published": "2026-07-17T18:16:47.000Z",
      "tags": [
        "TypeScript"
      ]
    },
    {
      "id": "pipeworks@v0.4.0",
      "url": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/#/project/pipeworks",
      "title": "Pipeworks v0.4.0",
      "content_text": "- chore(release): cut v0.4.0 \"Consequence\" + open Release 5 — v0.5.0 \"Promotion\" (#55) (#55)\n- feat(rating): session rating history — the last few runs, not just a peak (#54) (#54)\n- feat(promotion): artifact promotion — bake once, deploy many (#53) (#53)\n- hunt(regions): the throttle hint misdirected after per-region capacity (#52) (#52)\n- feat(regions): per-region capacity + relocate — placement that throttles (slice 2b) (#51) (#51)\n- feat(techtree): capability-gate the catalog — progression with teeth (slice 2) (#50)",
      "image": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/og/pipeworks.svg",
      "date_published": "2026-07-17T14:08:10.000Z",
      "tags": [
        "TypeScript"
      ]
    },
    {
      "id": "processing-sandbox@v0.2.0",
      "url": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/#/project/processing-sandbox",
      "title": "sketchbook v0.2.0",
      "content_text": "- gfx(creative): Harmonic Particle Text glow-up (G1)\n- gfx(permutations): rebuild Fibonacci Spiral — the real golden spiral (G1)\n- gfx(dynamicprogramming): rebuild Tree Heights DP viz + correct a 1.6 fact (G1)\n- gfx(hashing): rebuild Consistent Hashing — correct, legible, and light (G1)\n- gfx(surface_drift): make the Shader Sphere a churning nebula (G1/G5 flex)\n- gfx(surface_drift): evolve Shader Sphere to reel-ready (G1 fidelity)",
      "image": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/og/processing-sandbox.svg",
      "date_published": "2026-07-17T00:52:45.000Z",
      "tags": [
        "JavaScript"
      ]
    },
    {
      "id": "processing-sandbox@v0.1.0",
      "url": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/#/project/processing-sandbox",
      "title": "sketchbook v0.1.0",
      "content_text": "- Add graphics & animation quality roadmap (research-backed, phased, cadenced)\n- Stop tracking node_modules (already in .gitignore)\n- Add a real launcher index.html — filterable catalog of all sketches (CAT-120/122)\n- Add CATHODE improvement backlog — non-breaking, opt-in 'The Bench'\n- Adding scripts\n- Fibonacci spiral\n- Tree height visualization\n- Fibonacci spiral\n- Max subarray sum\n- Max subarray sum\n- Add animations\n- Add .gitignore",
      "image": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/og/processing-sandbox.svg",
      "date_published": "2026-07-16T22:07:39.000Z",
      "tags": [
        "JavaScript"
      ]
    },
    {
      "id": "pipeworks@v0.3.0",
      "url": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/#/project/pipeworks",
      "title": "Pipeworks v0.3.0",
      "content_text": "- chore(release): cut v0.3.0 \"Scale & Progression\" + open Release 4 — v0.4.0 \"Consequence\" (#49)\n- feat(loadout): on-call auto-defense — the standby-less critical mop-up (#48) (#48)\n- feat(regions): regionalise the board (slice 2a) — placement + spatial fuel (#47) (#47)\n- hunt(regions): fix an inescapable depletion trap + the trap-feeding hint (#46) (#46)\n- feat(rating): session rating + the game's first cross-session persisted best (#45) (#45)\n- feat(techtree): the technology tree — ship to unlock capability (#44) (#44)\n- hunt(integration): lock the v0.2.0 depth features against each other (#43) (#43)\n- feat(stages): Restrict Execution During Time Window — a recurring deploy freeze (#42)",
      "image": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/og/pipeworks.svg",
      "date_published": "2026-07-16T21:55:08.000Z",
      "tags": [
        "TypeScript"
      ]
    },
    {
      "id": "nebula-drift@v0.5.0",
      "url": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/#/project/nebula-drift",
      "title": "PH1 v0.5.0",
      "content_text": "- chore(release): 0.5.0 — Two Sandboxes (#347)\n- feat(brand): remove the broadcasting theme — no CRT chrome, no broadcast voice (only earthy palette + pixellation) (#346)\n- feat(loot): the loot engine core — rolled rarity + affixes, per-area density (Diablo × Soulslike) (#345)\n- fix(look): de-neon the space backdrop — the starfield & nebula clouds still shimmered pre-earthy neon (#344)\n- rename(brand): the display name is PH1, not GRAVEYARD SLOT — operator correction of #342 (#343)\n- feat(brand): rename the game RINGED AND RUINOSE → GRAVEYARD SLOT + establish the design canon (#342)\n- feat(eve): the combat fit is buildable — industry blueprints for a weapon, tackle and the armor repairer (#341)\n- feat(surface): prospecting reach scales with the Survey Scope — the recon upgrade finally pays on the surface (#340)\n- fix(eve): a cap-starved afterburner/web kept its sustained effect for free — gate on running, not toggled (#339)\n- feat(eve): armor repairer — an active rep for the armor layer, completing the shield/armor tank symmetry (#338)\n- feat(surface): prospecting scan — press P to surface rich ground pockets and chase a vein (#337)\n- feat(surface): plasma lamps light the night — day-pace work beside a lamp, with a warm glow (#336)",
      "image": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/og/nebula-drift.svg",
      "date_published": "2026-07-16T05:51:31.000Z",
      "tags": [
        "TypeScript"
      ]
    },
    {
      "id": "pipeworks@v0.2.0",
      "url": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/#/project/pipeworks",
      "title": "Pipeworks v0.2.0",
      "content_text": "- chore(release): cut v0.2.0 \"Depth\" + open Release 3 — v0.3.0 (#41) (#41)\n- feat(loadout): operator capability loadout — progression without a character (#40) (#40)\n- feat(regions): finite compute budgets — depletion forces expansion (#39) (#39)\n- hunt(validate): lock the rules kernel against degenerate + malformed input (#38)\n- hunt(balance): lock automation-as-relief — powered parallelism beats per-deploy speed (#37) (#37)\n- feat(observability): fog-of-war — instrument to see, or fly blind (#36) (#36)\n- feat(stages): Run Job — an external-call stage with its own latency, no local compute (#35)\n- feat(hud): show where a run failed in the executions feed — an audit detail (#34)\n- docs(release): define the v0.2.0 milestone — burn-up + burn-down (#33) (#33)\n- feat(stages): Check Preconditions — a minimum-soak gate before deploy (#32)\n- feat(triggers): tune each service's commit cadence — a demand lever (#31)\n- hunt(balance): retune Red/Black out of a strictly-dominated dead zone (#30) (#30)",
      "image": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/og/pipeworks.svg",
      "date_published": "2026-07-16T04:33:05.000Z",
      "tags": [
        "TypeScript"
      ]
    },
    {
      "id": "pipeworks@v0.1.0",
      "url": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/#/project/pipeworks",
      "title": "Pipeworks v0.1.0",
      "content_text": "- feat: Pipeworks v0.1.0 — Factorio-inspired Spinnaker CI/CD delivery-factory sim",
      "image": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/og/pipeworks.svg",
      "date_published": "2026-07-15T03:39:34.000Z",
      "tags": [
        "TypeScript"
      ]
    },
    {
      "id": "nebula-drift@v0.4.0",
      "url": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/#/project/nebula-drift",
      "title": "PH1 v0.4.0",
      "content_text": "- chore(release): 0.4.0 — Groundfall (#216)\n- hunt(surface): refund mined blocks + cap builds to the collision window (#215)\n- feat(a11y): reduced-motion mode — mute camera shake + full-screen flashes (#214)\n- feat(eve): HUD sec-status readout — highsec/lowsec/nullsec at a glance (#213)\n- feat(surface): persist per-planet dig/build edits + bank ore on leave (#212)\n- feat(surface): wire progressive mining into SurfaceScene — the tactile loop (#211)\n- feat(surface): progressive tool-gated tile mining — tedious but worth it (pure) (#210)\n- feat(eve): ship fitting — modules into hull slots vs CPU/PG/cap budgets (pure) (#209)\n- feat(survive): Evade Dash — an active dodge with i-frames on a cooldown (#206)\n- feat(surface): effective-ground model — dig/build affect where you stand (pure) (#208)\n- feat(eve): capacitor — the module-energy resource with EVE recharge (pure) (#207)\n- feat(surface): placement & building model — the inverse of digging (pure) (#205)",
      "image": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/og/nebula-drift.svg",
      "date_published": "2026-07-14T18:17:26.000Z",
      "tags": [
        "TypeScript"
      ]
    },
    {
      "id": "nebula-drift@v0.3.0",
      "url": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/#/project/nebula-drift",
      "title": "PH1 v0.3.0",
      "content_text": "- chore(release): v0.3.0 — The Deep Field (#153)\n- feat(survive): the Coil — a spiraler that winds its orbit in to the kill (#152)\n- hunt: freeze the descent star-field under the Survey Scope soft-pause (#151)\n- docs(todo): burndown + descent-scenery status for POI-by-altitude (#150)\n- feat(descent): surface POIs resolve by altitude — distant lights → silhouettes → features (#150)\n- feat(descent): parallax cloud layers driven by the planet's atmosphere (#149)\n- feat(survive): survival milestones — punctuation + reward for the endless run (#148)\n- hunt: consume the run seed so it can't leak into later random runs (#147)\n- hunt: freeze Prospect's asteroid respawn while the Survey Scope is up (#146)\n- feat(survive): the Phantom — a telegraphed blink-stalker (#145)\n- feat(survive): per-hull signatures — Interceptor pierce, Bulwark orbital (#144)\n- hunt: freeze Prospect's mission clock while the Survey Scope is up (#142)",
      "image": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/og/nebula-drift.svg",
      "date_published": "2026-07-13T23:27:31.000Z",
      "tags": [
        "TypeScript"
      ]
    },
    {
      "id": "nebula-drift@v0.2.0",
      "url": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/#/project/nebula-drift",
      "title": "PH1 v0.2.0",
      "content_text": "- chore(release): v0.2.0 — \"The Big Turn\" (#67)\n- hunt(survive): soft-cap the enemy HP scaling so endless runs stay killable (#66)\n- feat(universe): jump-gates — the universe is navigable, flown sector to sector (#65)\n- feat(universe): Prospect is sector-aware — mine your universe's home sector (#64)\n- feat(survive): the Splitter — a foe that bursts into Seekers on death (#63)\n- feat(universe): surface survey — the descent tells you what you're landing on (#62)\n- hunt(prospect): drone mine-hover uses the asteroid's scaled radius, not the base (#61)\n- feat(survive): kill-combo credit multiplier — streak juice (#60)\n- feat(universe): per-sector state — the pure model for depletion & discovery (#59)\n- feat(universe): sector navigation & fog-of-war — the pure model for a navigable universe (#58)\n- polish(universe): the planet descent is genuinely reversible — abort to orbit (#57)\n- feat(universe): the planet descent is playable — a real DescentScene (#56)",
      "image": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/og/nebula-drift.svg",
      "date_published": "2026-07-12T23:45:42.000Z",
      "tags": [
        "TypeScript"
      ]
    },
    {
      "id": "lrge@v0.2.23",
      "url": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/#/project/lrge",
      "title": "LRGQ v0.2.23",
      "content_text": "- [GD-2] ImGui composition bridge: RAII scope guards\n- [GD-2] Bug hunt: guard default-floor row against int overflow\n- feat(bp): add String To Upper / To Lower Event Graph nodes\n- feat(bp): add Exp2 (float) Event Graph node\n- feat(bp): add String Starts With / Ends With Event Graph nodes\n- [GD-2] Bug hunt: restore runAction switch exhaustiveness for Min/Max/WrapVector\n- [GD-2] Bug hunt: keep a <br> in a table cell from overflowing the row\n- feat(bp): add Log10 (float) Event Graph node\n- [GD-2] Bug hunt: reject case-insensitive profile-name collisions\n- feat(bp): add Log2 (float) Event Graph node\n- feat(bp): add Asinh / Acosh (float) Event Graph nodes\n- feat(bp): add Atanh (float) Event Graph node",
      "image": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/og/lrge.svg",
      "date_published": "2026-07-08T03:27:21.000Z",
      "tags": [
        "C++"
      ]
    },
    {
      "id": "gcp-terraform-labs@v0.1.1",
      "url": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/#/project/gcp-terraform-labs",
      "title": "GCP Terraform Labs v0.1.1",
      "content_text": "- feat(jm-likes): swappable Discord webhook secret for like notifications (#23)\n- feat(jm-likes): salt secret + Firestore TTL for the Like-counter hardening (#22)\n- feat(jm-likes): Firestore + SA/IAM + invoker for the jm portfolio Like backend (#21)\n- fix(desktop-updates): stream large installer downloads (Cloud Run 32 MiB cap) (#20)\n- feat(dev): private token-gated auto-update feed for the jm desktop app + adopt WIF/fleet infra into state (#19)\n- feat(cloud-functions-demo): ephemeral Gen2 HTTP function (source->build->run) + public invoker (#18)\n- feat(cloud-run-demo): ephemeral Cloud Run v2 service + dedicated runtime SA + invoker IAM (#17)\n- feat(secret-manager-demo): ephemeral SM secret + version + secret-scoped reader SA (#16)\n- feat(artifact-registry-demo): ephemeral AR Docker repo + repo-scoped CI push SA (#15)\n- feat(scheduler-demo): ephemeral Cloud Scheduler job + Pub/Sub topic + scheduler->topic IAM (#14)\n- feat(dev): Terraform for jm portfolio infra, deploy SA perms & Burn Fleet bucket (#3)\n- feat(bigquery-demo): ephemeral BigQuery dataset + inline-schema table (#13)",
      "image": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/og/gcp-terraform-labs.svg",
      "date_published": "2026-07-07T15:50:25.000Z",
      "tags": [
        "HCL"
      ]
    },
    {
      "id": "netsentry@v0.1.1",
      "url": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/#/project/netsentry",
      "title": "NetSentry v0.1.1",
      "content_text": "- docs(todo): backlog the deferred remediation items from the 2026-07-07 sweep\n- feat(alert): NS-ALERT-6 acknowledge/snooze findings via Confirm-Finding.ps1 (#87)\n- hunt(lib): guard ConvertTo-NSMask against a negative fill count on malformed IPv6 (#86)\n- feat(sec): NS-SEC-8 ready-to-install pre-commit secrets guard (#85)\n- hunt(gui): fix Findings Log tab pill never reading REVIEW on real anomalies (#84)\n- hunt(det): mask the matched external IP in Watch-IOCMatch's CSV/console (#83)\n- docs(NS-DOC-2): add THREAT-MODEL.md (#82)\n- feat(det): NS-DET-1 extend UA signatures from real Cloud Run log evidence (#81)\n- feat(det): NS-DET-2 signature-pack versioning (#80)\n- feat(net): NS-NET-7 passive mDNS/SSDP/Bonjour service enumeration (#79)\n- feat(perf): NS-PERF-1 wire gcloud retry into Audit-CloudRunIAM (#78)\n- feat(ops): NS-OPS-5 GitHub Actions CI (PSScriptAnalyzer + Pester) (#77)",
      "image": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/og/netsentry.svg",
      "date_published": "2026-07-07T15:17:26.000Z",
      "tags": [
        "PowerShell"
      ]
    },
    {
      "id": "ue5-experiments@v0.1.2",
      "url": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/#/project/ue5-experiments",
      "title": "ue5-experiments v0.1.2",
      "content_text": "- feat(MirrorGrid): kaleidoscope reflection component over a source mesh (#139)\n- hunt(Vortex): floor MinRadius at the point of use so the ω=BaseRate/r divisor can't NaN (#138)\n- feat(Terminal): theme builtin over the palette registry + 4 preset palettes (#137)\n- hunt(DirectionalMovementComponent): drop dead store + brace Oscillate case (#136)\n- feat(FlockingFormation): spring-damped agents converging on formation slots (#135)\n- feat(PhoenixEnigmaComponent): terminal-driven death/rebirth ember ring (#134)\n- feat(Terminal): help / man builtins over the command registry (#133)\n- feat(DistanceLods): pure-logic distance-LOD driver with edge-triggered OnLodChanged (#132)\n- hunt(Pulsar): floor PulseFrequency in the phase term too so a sub-clamp write can't freeze the pulse (#131)\n- feat(Terminal): command registry + dispatcher foundation (#130)\n- feat(ArchimedeanSpiralSwarm): arithmetic-spiral swarm with inward flow (#129)\n- hunt(SwarmComponent): weight boids separation by 1/distance so the closest neighbours dominate (#128)",
      "image": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/og/ue5-experiments.svg",
      "date_published": "2026-07-06T18:34:09.000Z",
      "tags": [
        "C++"
      ]
    },
    {
      "id": "smol@v0.1.3",
      "url": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/#/project/smol",
      "title": "Forge Engine v0.1.3",
      "content_text": "- feat(render): froxel light assignment — binLightsToClusters crosses tiles with depth slices (M3-6 advance) (#283)\n- hunt(editor): guard gizmo snap against an infinite step (no NaN'd coordinate) (#282)\n- feat(nav): flow-field path extraction — flowFieldPath follows the field downhill to the goal (nav advance) (#281)\n- hunt(blueprint): dedup a duplicated sequence exec-out pin so it fires once (#280)\n- hunt(material): length-guard codegen normalize to match the CPU eval (no NaN) (#279)\n- feat(material): elementary material nodes — divide / negate / round (M4-5 advance) (#278)\n- hunt(physics): pin capsuleVsMesh zero-distance normal to the triangle winding (#277)\n- feat(render): clustered lighting depth-slice core — clusterZSlice / clusterZSliceRange / lightZSliceSpan / clusterIndex (M3-6 advance) (#276)\n- hunt(editor): refresh the Inspector undo baseline on every focus (#275)\n- hunt(blueprint): coerce add codegen operands to Number, matching the VM (#274)\n- feat(physics): anisotropic principal-frame angular acceleration — bodyAngularAcceleration with the gyroscopic term (M5-3 advance) (#273)\n- hunt(blueprint): coerce ordering-comparison codegen operands to Number, matching the VM (#272)",
      "image": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/og/smol.svg",
      "date_published": "2026-07-06T18:20:32.000Z",
      "tags": [
        "TypeScript"
      ]
    },
    {
      "id": "adk-sandbox@v0.1.3",
      "url": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/#/project/adk-sandbox",
      "title": "adk-sandbox v0.1.3",
      "content_text": "- burn: record PR #92 in BURNDOWN/BURN_LOG\n- hunt(project_builder_agent): add Windows venv activation command to Flask/FastAPI READMEs\n- burn: record PR #90 in BURNDOWN/BURN_LOG\n- hunt(project_builder_agent): fix run_project's inconsistent return shape on timeout\n- burn: record PR #89 in BURNDOWN/BURN_LOG\n- hunt(youtube_shorts_assistant): fix README's pip install instruction inconsistent with repo convention\n- burn: record PR #88 in BURNDOWN/BURN_LOG\n- hunt(youtube_shorts_assistant): fix suggest_hashtags overpromising \"up to 15\" hashtags\n- burn: record PR #87 in BURNDOWN/BURN_LOG\n- hunt(docs): fix _extract_tools silently corrupting docs on nested-fn name collision\n- burn: record PR #86 in BURNDOWN/BURN_LOG\n- hunt(docs): fix stale \"80+ cities\" claim to match the real count (76)",
      "image": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/og/adk-sandbox.svg",
      "date_published": "2026-07-06T18:19:24.000Z",
      "tags": [
        "Python"
      ]
    },
    {
      "id": "ffmpeg-util@v0.1.4",
      "url": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/#/project/ffmpeg-util",
      "title": "ffmpeg-util v0.1.4",
      "content_text": "- hunt(sidecar): stop /run/stream leaking the chapters ffmetadata manifest\n- hunt(chapters): guard chapter start times past the input duration\n- hunt(renderer): fix dead Ctrl+Enter/Batch mode on Scene thumbs tab\n- hunt(renderer): add missing inline validator for scene_thumbs threshold field\n- hunt(cli): auto-probe xfade-concat offset from clip 1 like the UI sidecar\n- hunt(concat): guard reencode path against fewer than two inputs\n- hunt(renderer): add missing inline validator for fps-fps field\n- hunt(sidecar): guard /run/stream poster-frame against unprobeable duration\n- hunt(renderer): add missing inline validator for xfade-concat duration\n- hunt(renderer): add missing inline validators for blur sigma fields\n- hunt(cli): fix concat --reencode --dry-run assuming no audio in every input\n- hunt(commands): guard waveform against video-only input",
      "image": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/og/ffmpeg-util.svg",
      "date_published": "2026-07-06T18:04:53.000Z",
      "tags": [
        "Python"
      ]
    },
    {
      "id": "terraform-aws@v0.1.3",
      "url": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/#/project/terraform-aws",
      "title": "AWS Terraform Infra v0.1.3",
      "content_text": "- hunt(bootstrap): align verify-vpc-endpoints.sh with sibling verify scripts (#118)\n- hunt(docs): fix verify-bootstrap.sh doc drift (missing DynamoDB + CloudTrail sections) (#117)\n- hunt(monitoring): wire threshold vars into examples/monitoring (#116)\n- hunt(bootstrap): add missing cloudtrail_access_logs_bucket_name output (#115)\n- hunt(bootstrap): add missing logs:AssociateKmsKey IAM grant (#114)\n- hunt(compute): add tmpfs mounts for ECS Exec under a read-only root filesystem (#113)\n- hunt(bootstrap): add DynamoDB + CloudTrail checks to verify-bootstrap.sh (#112)\n- hunt(bootstrap): check all 6 S3 buckets in verify-teardown.sh (#111)\n- hunt(bootstrap): add missing S3 bucket-ownership-controls IAM grants (#110)\n- hunt(iam): add missing SSM/ECS-Exec row to modules/iam README's Policy design table (#109)\n- hunt(bootstrap): check all 3 TerraformDeploy IAM policies in verify-teardown.sh (#108)\n- feat(docs): refresh infrastructure.md structure + next-steps (#107)",
      "image": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/og/terraform-aws.svg",
      "date_published": "2026-07-06T17:56:32.000Z",
      "tags": [
        "HCL"
      ]
    },
    {
      "id": "spinnaker-sandbox@v0.1.0",
      "url": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/#/project/spinnaker-sandbox",
      "title": "Spinnaker Sandbox v0.1.0",
      "content_text": "- Fix: null element in a stage config array no longer crashes the Lab Console (#69)\n- Add lab 54: Traffic management (progressive SMI/Istio traffic shift) (#68)\n- Fix: non-array judgmentInputs no longer crashes the console in pause mode (#67)\n- Add lab 53: Rollout management (rolling restart, pause/resume, undo) (#66)\n- Add lab 52: Kustomize bake + deploy (#65)\n- docs: add Halyard/Minikube quickstart to run a lab for real (#213) (#64)\n- Fix: canary render's threshold label no longer contradicts its verdict (#63)\n- Add lab 51: Helm3 bake + deploy (bake a chart, then apply & verify the rollout) (#62)\n- docs(readme): list all 32 labs grouped by track (#61)\n- chore(coverage): publish Lab Console engine coverage for the jm portfolio\n- Fix: non-array `regions` crashed the Lab Console engine (#59)\n- docs: add a Lab Console demo.gif to the README (#58)",
      "image": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/og/spinnaker-sandbox.svg",
      "date_published": "2026-07-06T17:52:32.000Z",
      "tags": [
        "JavaScript"
      ]
    },
    {
      "id": "nebula-drift@v0.1.0",
      "url": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/#/project/nebula-drift",
      "title": "PH1 v0.1.0",
      "content_text": "- feat(survive): Second Barrel augment — a rear-facing volley each shot (#19)\n- feat(survive): off-screen hostile indicators — edge arrows at nearby foes (#18)\n- hunt(combat): the player's contact-hit shove was inert (never moved the ship) (#17)\n- feat(prospect): airbrake — hold Space for a retro-burn that kills drift (#16)\n- feat(mine): drones steer clear of the player's hull and asteroid cores (#15)\n- hunt(prospect): honour the cracked-node respawn delay (it warped back instantly) (#14)\n- feat(mine): camera leads ahead at speed + a high-velocity hull rumble (#13)\n- feat(prospect): boost-energy meter — the afterburner can't be held forever (#12)\n- feat(prospect): cargo hold — capacity, resource identity & a Tab cargo panel (#11)\n- hunt(pickups): stop a magnetised pickup fleeing when the player outruns it (#10)\n- feat(mine): drifting size-varied asteroids in belts + clusters (#9)\n- hunt(entities): stop charger knockback compounding during its dash (#8)",
      "image": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/og/nebula-drift.svg",
      "date_published": "2026-07-06T14:39:50.000Z",
      "tags": [
        "TypeScript"
      ]
    },
    {
      "id": "cloud-portfolio@v0.1.2",
      "url": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/#/project/cloud-portfolio",
      "title": "cloud-portfolio v0.1.2",
      "content_text": "- chore(coverage): publish src coverage report for the jm portfolio\n- docs: cache-bust the README demo.gif reference\n- chore: update demo.gif to a full-site walkthrough\n- fix(certs): correct Spring Certified Professional issuer to Broadcom\n- fix(skills): remove proficiency progress bars under each skill\n- feat: redesign /projects, migrate CRA→Vite, remove Resume/Art/Blog",
      "image": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/og/cloud-portfolio.svg",
      "date_published": "2026-07-06T01:21:46.000Z",
      "tags": [
        "TypeScript"
      ]
    },
    {
      "id": "go-labs@v0.1.2",
      "url": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/#/project/go-labs",
      "title": "go-labs v0.1.2",
      "content_text": "- chore(coverage): publish util library coverage report for the jm portfolio\n- docs(readme): regenerate demo.gif from a GUI playground runner (#7)\n- feat(errors): add 13_error_handling topic with runnable examples\n- docs(topics): add per-topic READMEs across the curriculum\n- feat(sandbox): self-contained web UI with live code execution\n- hunt(util): size Banner border by rune count, not bytes (#6)",
      "image": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/og/go-labs.svg",
      "date_published": "2026-07-06T00:38:41.000Z",
      "tags": [
        "Go"
      ]
    },
    {
      "id": "ffmpeg-util@v0.1.3",
      "url": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/#/project/ffmpeg-util",
      "title": "ffmpeg-util v0.1.3",
      "content_text": "- Update README.md\n- hunt(ui): queue runner attributes results to the on-screen tab, not the queued item's\n- feat(trim): trim multiple segments from one clip and join them\n- feat(ui): operation queue — line up ops from several tabs, run them in sequence\n- hunt(ui): fix Save-As default ignoring the active tab when no output history exists\n- feat(cli): read global-flag defaults from a config file\n- feat(ui): chain-to-tab — send output to another tab as input after a run\n- feat(metadata): add chapters from a list — core/CLI/sidecar/UI\n- feat(ui): job history strip — recent runs with re-run / reveal buttons\n- hunt(pip): label overlay output [v] and map it so video is included\n- feat(ui): before/after compare slider (drag a divider over input↔output)\n- hunt(concat): bound silent-input re-encode with -shortest so it can't hang",
      "image": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/og/ffmpeg-util.svg",
      "date_published": "2026-07-04T23:09:33.000Z",
      "tags": [
        "Python"
      ]
    },
    {
      "id": "terraform-aws@v0.1.2",
      "url": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/#/project/terraform-aws",
      "title": "AWS Terraform Infra v0.1.2",
      "content_text": "- hunt(network): guard the ingestion NLB against accidental deletion (#37)\n- hunt(network): scope SNS/SQS/Logs interface VPC endpoint policies to this account (#36)\n- hunt(messaging): enforce HTTPS-only access on the SNS alerts topic (#35)\n- hunt(network): restrict S3 gateway VPC endpoint to own-account buckets (#34)\n- hunt(messaging): enforce HTTPS-only access on SQS queues (#33)\n- feat(messaging): add S3 lifecycle expiration to the telemetry access-logs bucket (#32)\n- hunt(messaging): enforce HTTPS-only access on the telemetry access-logs bucket (#31)\n- feat(bootstrap): add AWS Budgets monthly-cost alarm (#30)\n- feat(messaging): add S3 server access logging to telemetry bucket (#29)\n- feat(monitoring): add CloudWatch operator dashboard via modules/monitoring (#28)\n- feat(network): add CloudWatch NLB unhealthy-host alarm (#27)\n- feat(compute): add ECS auto-scaling with CPU target-tracking policy (#26)",
      "image": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/og/terraform-aws.svg",
      "date_published": "2026-07-04T22:54:37.000Z",
      "tags": [
        "HCL"
      ]
    },
    {
      "id": "ue5-experiments@v0.1.1",
      "url": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/#/project/ue5-experiments",
      "title": "ue5-experiments v0.1.1",
      "content_text": "- feat(PolygonLibrary): 2-D polygon geometry BlueprintPure library (#76)\n- feat(InventoryComponent): slot-based stacking inventory (#75)\n- feat(ShockwaveRingComponent): expanding evaporating shockwave ring (#74)\n- hunt(PulsarComponent): guard divide-by-zero in pulse-period computation (#73)\n- feat(DistanceFieldLibrary): pure BlueprintPure SDF primitives and boolean operators (#72)\n- feat(SplineLibrary): Catmull-Rom spline evaluation library (#71)\n- feat(WaveformLibrary): pure BlueprintPure periodic waveform generators (#70)\n- feat(SquishStretchComponent): squish-stretch anticipation animation component (#69)\n- hunt(DirectionalMovementComponent): cap DeltaTime in TickComponent (#68)\n- hunt(MagneticFieldComponent): fix Euler speed drift with Boris rotation (#67)\n- feat(VerletRopeComponent): verlet rope with moveable anchor and wind force (#66)\n- feat(MagneticFieldComponent): charged particles gyrating in a magnetic field (#65)",
      "image": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/og/ue5-experiments.svg",
      "date_published": "2026-07-04T22:49:56.000Z",
      "tags": [
        "C++"
      ]
    },
    {
      "id": "lrge@v0.2.22",
      "url": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/#/project/lrge",
      "title": "LRGQ v0.2.22",
      "content_text": "- [GD-2] Bug hunt: guard Animator against an out-of-range frame index\n- [GD-2] Markdown: render <angle-bracket> URL autolinks\n- [GD-2] Bug hunt: reject a non-finite tile collision box on load\n- [GD-2] Bug hunt: keep a maximized dock panel's restore size when minimizing\n- [GD-2] chore(editor): tooltip the dock-panel header chrome buttons\n- [GD-2] chore(settings): tooltip the appearance-profile + splash-image buttons\n- [GD-2] chore(editor): tooltip the Console Output panel's Clear + Auto-scroll controls\n- [GD-2] Bug hunt: keep Console auto-scroll following output past the buffer cap\n- [GD-2] feat(editor): add Console Output panel and route Print nodes to it\n- [GD-2] Bug hunt: expire coyote time on an upward impulse launch\n- [GD-2] Bug hunt: add smoke tests for OnOverlapBegin and OnOverlapEnd nodes\n- ﻿[GD-2] feat(editor): add node-body hover tooltip in the Event Graph",
      "image": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/og/lrge.svg",
      "date_published": "2026-07-04T22:48:54.000Z",
      "tags": [
        "C++"
      ]
    },
    {
      "id": "smol@v0.1.2",
      "url": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/#/project/smol",
      "title": "Forge Engine v0.1.2",
      "content_text": "- feat(asset): gamma-correct sRGB mip generation (M9-3 advance) (#194)\n- hunt(material): mix node collapsed a vec3 t to its first component (#193)\n- feat(audio): distance-attenuation models (linear/inverse/exponential) for spatial gain (M10-2 advance) (#192)\n- chore(docs): burndown log Sprint 180 — dry hunt (no new defects) (#191)\n- feat(anim): morph-target NORMAL deltas — blend + renormalize, glTF import (M6-7 advance) (#190)\n- feat(material): add sqrt/exp/log/tan, radians/degrees, atan2, distance, reflect graph nodes (M4-5 advance) (#189)\n- hunt(scene): default a partial transform doc's missing TRS channel instead of crashing (#188)\n- feat(editor): dock splitter handles + drag-resize math (M8-1 advance) (#187)\n- hunt(ecs): retire entity ids instead of recycling them (#186)\n- hunt(physics): stop dynamic boxes being double-resolved as phantom spheres (#185)\n- feat(render): frame-graph core -- pass ordering, culling, resource lifetimes (M3-2 advance) (#181)\n- feat(m3-9): TAA history buffer + temporal resolve pass — Sprint 173 (#180)",
      "image": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/og/smol.svg",
      "date_published": "2026-07-04T22:48:53.000Z",
      "tags": [
        "TypeScript"
      ]
    },
    {
      "id": "adk-sandbox@v0.1.2",
      "url": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/#/project/adk-sandbox",
      "title": "adk-sandbox v0.1.2",
      "content_text": "- burn: log PR #48 (hunt: api false-match fix) in BURNDOWN/BURN_LOG\n- hunt(youtube_shorts_assistant): fix bare \"api\" false-match in _NICHE_KEYWORDS[\"tech\"]\n- hunt(youtube_shorts_assistant): fix \"code\"/\"web\" false-match in _NICHE_KEYWORDS[\"tech\"]\n- hunt(city_data): strip whitespace in format_city before display\n- feat(tools): extract shared city_data module from multi_tool_agent\n- burn(docs): add Sphinx extension auto-listing root_agent tools per agent\n- burn(docs): add per-agent README with adk run + adk web entry points\n- burn(sandbox): strip credentials from run_project subprocess env\n- feat(deps): pin google-adk>=1.18.0 and google-genai>=1.49.0 in pyproject.toml\n- burn: add happy-path tool tests for every agent",
      "image": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/og/adk-sandbox.svg",
      "date_published": "2026-07-04T22:22:07.000Z",
      "tags": [
        "Python"
      ]
    },
    {
      "id": "netsentry@v0.1.0",
      "url": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/#/project/netsentry",
      "title": "NetSentry v0.1.0",
      "content_text": "- hunt(net): fix Get-NSMaskedIp unmasking compressed IPv6 WAN addresses (#47)\n- feat(cloud): NS-CLOUD-9 Audit-IAMDrift.ps1 - GCP project IAM member-drift baseline (#46)\n- feat(docs): NS-DOC-1 split Install-Schedule.ps1 SYNOPSIS/DESCRIPTION (#45)\n- hunt(secrets): fix AclReadable never consulted in credential-file severity (#44)\n- hunt(alerting): fix single-quoted backtick-r-n replace never matching CRLF in Audit-LLMNRSpooler (#43)\n- feat(host): NS-HOST-4 Audit-LLMNRSpooler.ps1 - LLMNR + Spooler advisory (#42)\n- feat(host): NS-HOST-8 Audit-SoftwareInventory.ps1 - installed-software + hotfix inventory (#41)\n- feat(alerting): NS-ALERT-2 severity levels on Send-NSAlert (CRIT/WARN/INFO) (#40)\n- feat(detection): NS-DET-4 Watch-NewPersistence.ps1 - service + task creation watch (#39)\n- feat(net): NS-NET-8 Watch-WANAddress.ps1 - WAN/public-IP change detection (#38)\n- hunt(net): fix Scan-HomeNetwork false anomaly when no baseline exists (#37)\n- feat(secrets): NS-SEC-6 Scan-CredentialFiles.ps1 - home-dir credential-file sweep (#36)",
      "image": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/og/netsentry.svg",
      "date_published": "2026-07-04T22:14:32.000Z",
      "tags": [
        "PowerShell"
      ]
    },
    {
      "id": "gcp-terraform-labs@v0.1.0",
      "url": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/#/project/gcp-terraform-labs",
      "title": "GCP Terraform Labs v0.1.0",
      "content_text": "- ci: add Terraform CI + release workflows and CI badge (#6)\n- feat(translate-demo): ephemeral Cloud Translation API env + seed todo.md\n- Cloud Run service IAM member\n- feat(gemini-demo): ephemeral free-tier Gemini env for adk-sandbox demo (#4)\n- BigQuery permissions\n- Update TF configs for technical demo backend services\n- Add Google Cloud SQL endpoints\n- Configuring Cloud SQL / PostgreSQL\n- Upgrade provider\n- Renaming\n- Update README.md\n- Edit documentation",
      "image": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/og/gcp-terraform-labs.svg",
      "date_published": "2026-07-01T00:56:54.000Z",
      "tags": [
        "HCL"
      ]
    },
    {
      "id": "cicd-frontend-react-ts@v0.1.1",
      "url": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/#/project/cicd-frontend-react-ts",
      "title": "Workflow Dispatcher v0.1.1",
      "content_text": "- ci: add build/lint CI workflow, README status badges, and burndown todo (#3)",
      "image": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/og/cicd-frontend-react-ts.svg",
      "date_published": "2026-07-01T00:56:02.000Z",
      "tags": [
        "TypeScript"
      ]
    },
    {
      "id": "lrge@v0.2.21",
      "url": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/#/project/lrge",
      "title": "LRGQ v0.2.21",
      "content_text": "- ci: add build+test workflow and burndown todo backlog (#189)\n- [GD-2] Bug hunt: fix jump-buffer not cleared on player respawn\n- ﻿[GD-2] Event Graph: add description tooltips to add-node popup\n- [GD-2] feat(editor): add search filter to Blueprint node-add popup\n- [GD-2] Event Graph: add Reset exec-in to Do Once node\n- [GD-2] Bug hunt: add smoke tests for 16 untested node types\n- ﻿[GD-2] Event Graph: Atan2Float + VectorFromAngle nodes\n- ﻿[GD-2] Event Graph: StringEquals / StringLength / StringContains nodes\n- [GD-2] Bug hunt: fix Print using stale float cache after preceding action\n- ﻿[GD-2] Event Graph: wire 11 missing nodes into add-node popup\n- [GD-2] Bug hunt: scale bp wire-drop snap radius with canvas zoom\n- [GD-2] Bug hunt: fix IsKey pure nodes ignoring wired String key inputs",
      "image": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/og/lrge.svg",
      "date_published": "2026-07-01T00:55:53.000Z",
      "tags": [
        "C++"
      ]
    },
    {
      "id": "recall@v0.1.1",
      "url": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/#/project/recall",
      "title": "Recall v0.1.1",
      "content_text": "- ci: add CI workflow, README badge, and burndown backlog (#8)",
      "image": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/og/recall.svg",
      "date_published": "2026-07-01T00:55:30.000Z",
      "tags": [
        "JavaScript"
      ]
    },
    {
      "id": "go-labs@v0.1.1",
      "url": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/#/project/go-labs",
      "title": "go-labs v0.1.1",
      "content_text": "- docs(readme): add CI + release status badges (#5)",
      "image": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/og/go-labs.svg",
      "date_published": "2026-07-01T00:55:20.000Z",
      "tags": [
        "Go"
      ]
    },
    {
      "id": "token-validator-service@v0.1.1",
      "url": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/#/project/token-validator-service",
      "title": "Token Validator v0.1.1",
      "content_text": "- docs(todo): add burndown backlog (High/Medium/Later + log) (#10)\n- feat(desktop): add Electron token-validator desktop UI (#9)",
      "image": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/og/token-validator-service.svg",
      "date_published": "2026-07-01T00:55:18.000Z",
      "tags": [
        "Python"
      ]
    },
    {
      "id": "adk-sandbox@v0.1.1",
      "url": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/#/project/adk-sandbox",
      "title": "adk-sandbox v0.1.1",
      "content_text": "- chore(infra): add CI badge to README + seed todo.md burndown (#39)\n- hunt(youtube_shorts_assistant): fix \"data\" false-match in _NICHE_KEYWORDS[\"tech\"]\n- hunt(youtube_shorts_assistant): fix first-match niche priority in suggest_hashtags\n- hunt(youtube_shorts_assistant): fix \"app\" false-match in _NICHE_KEYWORDS\n- hunt(multi_tool_agent): fix deprecated IANA tz name for Yangon\n- hunt(project_builder_agent): strip leading . and _ from npm name\n- hunt(conf): exclude BURNDOWN.md and BURN_LOG.md from Sphinx build\n- ﻿hunt(project_builder_agent): use sys.executable in run_project\n- hunt(claude-readme): fix stale directory-tree comments\n- hunt(readme): fix stale agent catalog descriptions\n- hunt(project_builder_agent): add __main__ uvicorn entry point to FastAPI template\n- hunt(youtube_shorts_assistant): guard estimate_speaking_time against negative word_count",
      "image": "https://jm-portfolio-5afqr6ijoq-uc.a.run.app/og/adk-sandbox.svg",
      "date_published": "2026-07-01T00:55:15.000Z",
      "tags": [
        "Python"
      ]
    }
  ]
}
