From 18fa79fa43efea2a9da6183b75969b37b943ee6d Mon Sep 17 00:00:00 2001 From: hoelee Date: Sat, 17 Oct 2026 14:36:58 +0800 Subject: [PATCH] =?UTF-8?q?docs(project-state):=202026-10-17=20re-check=20?= =?UTF-8?q?=E2=80=94=20E4/E5=20closed,=20og-default=20rewritten,=20the=20h?= =?UTF-8?q?eld=20churn=20post,=20the=20nginx=20301=20scheme=20fix,=20GitHu?= =?UTF-8?q?b=20mirror=20re-synced?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/project-state.md | 73 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 66 insertions(+), 7 deletions(-) diff --git a/docs/project-state.md b/docs/project-state.md index f9c4fc0..f44e7e5 100644 --- a/docs/project-state.md +++ b/docs/project-state.md @@ -133,7 +133,8 @@ The user asked for the dashboard to be reachable remotely **without** publishing | Rollback | Start the gate again (`sudo /usr/local/bin/docker start umami-gateway`, or start stack 285 in Portainer) → re-point the vhost + `ReverseProxy.json` to `5410` → reload nginx. Backups of both files sit next to the originals. (The gate container is now **`Exited (0)`** — it was stopped once the outpost took over, so port 5410 is free; the stack is kept as the rollback asset) | | Note | The `hermes3` authentik API token expired mid-session (DB says `expires 2026-09-28 22:17:08Z`); the leftover self-test account was removed through authentik's own ORM (`ak shell`), so no admin-group test user is left behind | -**Step E2 — Wire the two sites together (www.hoelee.com → blog).** ⏸ Deferred by user 2026-09-29 +**Step E2 — Wire the two sites together (www.hoelee.com → blog).** ⏸ Recorded and deferred — user decision 2026-10-17: +*先记录 www.hoelee.com 过后再改* (record it now, revisit the main site later) Measured: **all six pages of www.hoelee.com** (home, `/zh-hans/`, `/about-mrhoelee/`, T&C, support, privacy) contain **zero** references to `blog.hoelee.com`, while the blog links out to www.hoelee.com. The older, more established @@ -152,7 +153,7 @@ nothing has ever been syndicated, so the 53 posts only exist for people who alre - [ ] One LinkedIn share per flagship (same photo + name identity as the blog). - **Done when:** each dev.to copy is live with the canonical set, and each has one LinkedIn post. -**Step E4 — Chinese-side routes and nav are broken.** ⬜ (extends Step C4) +**Step E4 — Chinese-side routes and nav are broken.** ✅ Done 2026-10-16 (batch B2), re-verified live 2026-10-17 Live ZH pages: the nav renders 「文章」→ `/zh/` (fallback; `/zh/posts/` **404s**) and 「关于」→ `/zh/` — i.e. the Chinese nav's *About* link is wrong even though `/zh/about/` itself returns 200 and is in the sitemap. `grep @@ -161,14 +162,14 @@ Chinese nav's *About* link is wrong even though `/zh/about/` itself returns 200 `/posts/zh//` return 200 — there is no ZH post-archive route, so that path is answered by something else entirely (CDN/nginx, not the static build). Not a regression from the publish; it is this same missing route. -- [ ] Build the `/zh/posts/` archive; point 「文章」 at it and 「关于」 at `/zh/about/`. -- **Done when:** `/zh/posts/` 200, both ZH nav labels point at the right routes, and `/zh/about/` is reachable by clicking from `/zh/`. +- [x] ✅ Built in batch B2 (`src/pages/zh/posts/index.astro`); nginx `301`s `/posts/zh/` → `/zh/posts/`; the ZH nav points 「文章」 → `/zh/posts/` and 「关于」 → `/zh/about/`. +- **Done when:** ✅ measured 2026-10-17 — `/zh/posts/` **200** (74 KB, the ZH archive with every row), `/zh/about/` 200, `/posts/zh/` 301, and both ZH nav links resolve when clicked. -**Step E5 — `og:locale` is wrong on all 53 Chinese pages.** ⬜ +**Step E5 — `og:locale` is wrong on all 53 Chinese pages.** ✅ Done 2026-10-16 (batch B2), re-verified live 2026-10-17 ZH post pages emit `` with `og:locale:alternate = en_US`. -- **Done when:** ZH pages emit `zh_CN` (`en_US` as the alternate), EN pages unchanged. +- **Done when:** ✅ measured 2026-10-17 — a ZH post page emits `og:locale=zh_CN` with `og:locale:alternate=en_US`. **Step E6 — Cloudflare is not caching the HTML.** ⬜ @@ -176,6 +177,10 @@ A post page returns `cf-cache-status: DYNAMIC` and `strict-transport-security: m should be edge-cached — lower TTFB and less origin traffic through the tunnel. - [ ] Add a cache rule for `blog.hoelee.com` (cache HTML, honour origin `last-modified`) and take a decision on HSTS. + ⚠ **Owner action — the token available to the blog can only purge, it cannot write zone settings** (re-measured + 2026-10-17: `cf-cache-status: DYNAMIC` on every page, `strict-transport-security: max-age=0; includeSubDomains; preload`). + Until the rule exists every page is rendered from the origin across the tunnel on every hit — the same work that shows up + as **1.3–5.7 s** public TTFB while the LAN origin answers in 3–20 ms. - **Done when:** a repeat request shows `cf-cache-status: HIT` **and** a deploy still goes live within ~1 minute. **Step E7 — Content-volume guardrail.** ⬜ ongoing @@ -191,7 +196,11 @@ should be edge-cached — lower TTFB and less origin traffic through the tunnel. - [ ] `scraping-bot-walled-marketplace-warm-browser-session`: OG card exists, **banner 404s** (no `banner:` in frontmatter, no PNG). Generate it or accept it as the one exception. - [x] ✅ `authentik-css-greater-than-bug` (the `>` bug) — **published 2026-10-16 (`2295c0f`)**: `draft: true → false` in EN + ZH, `pubDate` kept at 2026-09-20 with **`updatedDate: 2026-10-16`** so `lastmod` stays honest, OG + banner generated (og `rows=1 overflow=0`; banner `delta=2 overflow=0`), and the CTA's displayed phone corrected (`011-797 2969` → `+60 12-797 2969`). Verified live: EN/ZH/og/banner all **200**, language switch both ways, `/posts/` order still monotonic. The draft bank is now empty. -- [ ] `og-default.png` has **no face**; the homepage and category pages share it. Regenerate after Step A1 (same source asset). +- [x] `og-default.png` rewritten 2026-10-17 (`scripts/og-gen/generate-default.mjs` + `scripts/og-gen/template-default.html`). + The card it replaces had shipped since 2026-09-06 still carrying the **retired brand name `hoelee.dev`** and no face, while the + headshot landed on the site in B4 — i.e. the most-linked share card was the least current asset on the site. New card: + headshot + `Lee Teong Hoe` / `Mr Hoelee` + the JSON-LD job title, measured in the DOM (`overflow=0`, 1200×630). + ⏸ **Not committed yet — waiting for the owner's look.** - **Done when:** no page references a 404 image, the draft bank is empty, and the default share card matches the A1 photo. ### Phase A — Identity (highest ROI, ~2–3 hrs total) @@ -683,6 +692,32 @@ start, so publishing added no pages. The number in that message is wrong; the de carry **no prose links** — every post they would naturally cite is dated later, and a backdated post may only link backwards. Their "related posts" rows are the theme's automatic ones, which every backdated post already has. +**Step B2p — (unplanned) The commit-churn post, held for the read (written 2026-10-17 04:00).** 🔵 + +| Slug | Category | `pubDate` | Source | +|---|---|---|---| +| `why-500000-lines-of-commit-churn-only-left-230000-in-production` | `engineering` | 2026-10-17 | Hermes session 2026-10-17 | + +- **What it argues:** thirty days of autonomous-agent work across five self-hosted Gitea repos = 865 commits, 518,233 + additions, 130,892 deletions — and production kept 235,000 lines. Verification gates and pruning, not generation + speed, are what survive. +- **State (all of it measured 2026-10-17, not carried over from the writing session):** EN + ZH written; + og + banner generated and **measured** (`scripts/measure_og_banner.py` → OG `rows=1 overflow=0`, banner 7 rows + `delta=2 overflow=0`); local build clean at **250 `index.html` pages** with both `dist/` pages present; the generator + changes are **purely additive** (`git diff --numstat` 8/0 and 18/0, `node --check` OK on both). + **Not committed, not pushed** — four files (EN + ZH `.md`, og + banner PNG, plus the generator delta) sit in the working + tree on purpose: publication gate, the owner has not read it. +- ⚠ **This entry is the record of that hold.** Without it the next session reads the untracked files as someone else's + in-flight work (or as already-published) — the same failure the skill warns about. +- **Preview for the owner:** `cd dist && python -m http.server 8899 --bind 127.0.0.1`, then + `/posts/why-500000-lines-of-commit-churn-only-left-230000-in-production/` and its `/posts/zh/…` twin. +- **To publish on his go-ahead:** confirm the real date (`date` + the newest `