# Changelog / 更新日志 All notable changes to this repository should be documented in this file. 本仓库的重要变更建议统一记录在此文件中。 The format loosely follows Keep a Changelog and can be adapted to the team's habits. 本文档参考了 Keep a Changelog 的思路,也可以根据团队习惯调整。 ## [0.3.3] - 2026-10-01 ### Done / 完成 - P9-B UX batch-2 (accessibility & keyboard-efficiency pack) delivered: crearte `338acbf` (0.24.0, merge-base `ee4edf7`) — five tasks closing seven measured a11y gaps, T1-T4 dispatched to subagents and T5 written by the controller, each through implement → task-level review → adjudication (four reviews, all PASS), plus a whole-branch final review on the strongest available model cross-checking spec §1-§6 in full, the cross-task integration seams, and mutation-testing three guards. **Contrast to WCAG AA**: `--color-success` deepened `#2fa46a` → `#1f7a4d` (paper-on 2.83 → 4.76; the success toast is 12px bold, not large text) and the error toast switched `bg-accent` → `bg-accent-ink` (3.64 → 4.87, reusing an existing token rather than adding a colour). **Toast announcer restructured** (closing P10 final-review item T1(d), an interactive control living inside a live region): visual and announcement layers split the way Radix Toast / Headless UI do it — one persistent `sr-only p[role=status][aria-live=polite]` whose text a watch drives, no announcement semantics on the visible toasts, so the dismiss button is a sibling of the live region rather than a descendant. **Skip link** as the root div's first child before ``, `sr-only` until focused then `focus:not-sr-only` with `focus:z-[80]` above the toast layer. **Focus management after SPA navigation**: `
` plus an exported `focusMain()` called from the router's `afterEach` only when `to.path !== from.path` — query-only changes (P10's clickable tags, `/games?tag=x`) deliberately do not steal focus, `preventScroll` avoids double-scrolling against `scrollBehavior`, and a missing `#main` no-ops via the optional chain. **Table column headers**: all 24 `` elements across the three admin views get `scope="col"`, and the two previously empty 操作 headers gain `操作` (they were unnamed columns to a screen reader). **Rating accessible names**: each star button gets `aria-label="评 N 星"` with its glyph `aria-hidden`, and the existing group span becomes `role="group"` with a dynamic label — deliberately not `radiogroup`/`aria-checked` (the control supports click-current-star-to-unrate, which radio cannot express) and not per-star `aria-pressed` (lighting is a continuous run, so pressed would announce four stars as all-pressed). **Two source-level guards** following the existing `no-gradient.test.ts` pattern: `lib/contrast.test.ts` parses `@theme` tokens out of `main.css` and asserts WCAG 2.1 ratios for eleven pairs (ten ≥4.5 plus the focus ring ≥3 per 1.4.11), `lib/tableScope.test.ts` scans every `app/**/*.vue` asserting each `` occurrences are not flagged; opening-tag slice taken across newlines). **New e2e** `a11y.spec.ts`: real keyboard Tab path, admin `columnheader` names, star accessible names via `toHaveAccessibleName`. Zero server/deploy changes. Acceptance (five legs, green on merge tip, independently re-run six-for-six by the final reviewer): vitest **626** (baseline 601, +25) / vue-tsc clean / build + build-runtime OK / main e2e **80+1skip** (baseline 77+1skip) / noauth 4. Final verdict APPROVE with notes — zero critical, zero important. Two spec-layer corrections landed mid-wave: ① the T1 implementer caught a real defect in the spec's initial D-I design (a `role=status` mounted *together with* its text is not reliably announced by several screen-reader/browser combinations, trading button noise for total silence) → re-pinned to D-I′, fixed by the controller in `f01baae`, which also pinned the saturation trap (the watch must key on the last entry's **id**, not the array length — at `MAX_VISIBLE=3` a push evicts and appends in one assignment so the length stays 3 while a fourth message still has to be announced). ② Two quantity slips in the controller's own briefs (contrast 3.16 vs the real 2.83 for paper; "19 ``" was a line count, the element count is 24) were both corrected by implementers deferring to the spec and to measurement; spec §1 was amended to match. Lesson recorded: quantities quoted in dispatch briefs must be verified at element level, never inferred from `grep -c` or from an adjacent number in the spec. Four items parked in the polish batch (re-check a weak router-test assertion on vue-router upgrade; surface unrate semantics in the accessible name; the announcer re-reads an older message when the newest toast is manually dismissed; spec wording already fixed). C (dark mode), OG social cards, play count, mobile header and later batches remain parked pending owner go-ahead. - P9-B UX 第二批(可访问与键盘效率包)交付:crearte `338acbf`(0.24.0,merge-base `ee4edf7`)——五任务闭合七处实测可访问缺口,T1-T4 派发子代理、T5 由控制者本人写,每任务经实现→任务级审查→裁定(四次审查全 PASS),另加最强可用模型的全分支终审,对 spec §1-§6 全量对照、跨任务集成缝隙、并对三处守卫做 mutation 式抽查。**色彩对比达 WCAG AA**:`--color-success` 由 `#2fa46a` 加深为 `#1f7a4d`(paper-on 2.83 → 4.76;成功 toast 是 12px 粗体,不属大字号),错误 toast 由 `bg-accent` 改为 `bg-accent-ink`(3.64 → 4.87,复用既有令牌而非新增颜色)。**toast 播报区重构**(收口 P10 终审转办项 T1(d):交互控件位于实时区内):按 Radix Toast / Headless UI 的做法把视觉层与播报层解耦——一个常驻的 `sr-only p[role=status][aria-live=polite]` 由 watch 驱动其文字,可见 toast 不带任何播报语义,于是关闭按钮成为实时区的兄弟而非后代。**跳转链接**作根 div 首子、在 `` 之前,未聚焦时 `sr-only`、聚焦后 `focus:not-sr-only` 且 `focus:z-[80]` 压过 toast 层。**SPA 导航后焦点管理**:`
` + 导出的 `focusMain()`,仅当 `to.path !== from.path` 时由路由 `afterEach` 调用——只改 query(P10 的可点标签 `/games?tag=x`)有意不抢焦点,`preventScroll` 避免与 `scrollBehavior` 双重滚动,`#main` 缺失时由可选链静默 no-op。**表格列头**:三个管理视图全部 24 个 `` 元素加 `scope="col"`,两个此前为空的「操作」表头补上 `操作`(它们在读屏里曾是无名列)。**评分可访问名**:每颗星 `aria-label="评 N 星"` 且字形 `aria-hidden`,既有分组 span 成为 `role="group"` 并带动态标签——有意不用 `radiogroup`/`aria-checked`(本控件支持点当前分撤评,radio 无法表达取消选中),也不用逐星 `aria-pressed`(点亮是连续区间,pressed 会把四分播报成四颗星都按下)。**两个源码级守卫**沿用既有 `no-gradient.test.ts` 范式:`lib/contrast.test.ts` 从 `main.css` 解析 `@theme` 令牌并对十一个配对断言 WCAG 2.1 比值(十个 ≥4.5 加焦点环 ≥3,依 1.4.11),`lib/tableScope.test.ts` 扫描全部 `app/**/*.vue` 断言每个 `` 不被误判;起始标签片段跨换行截取)。**新增 e2e** `a11y.spec.ts`:真实键盘 Tab 路径、管理端 `columnheader` 可访问名、经 `toHaveAccessibleName` 验证的星标可访问名。零后端/部署改动。验收(五腿,合并 tip 全绿,终审者六腿独立实跑逐条一致):vitest **626**(基线 601,+25)/ vue-tsc 零错 / build+build-runtime OK / 主 e2e **80+1skip**(基线 77+1skip)/ noauth 4。终审裁定 APPROVE with notes——零关键、零重要。波次内落两处 spec 层修正:① T1 实现者抓出 spec 初稿 D-I 的真缺陷(与文字**同时创建**的 `role=status` 在多个读屏+浏览器组合下不被可靠播报,等于用按钮噪音换来彻底静默)→ re-pin 为 D-I′,控制者于 `f01baae` 直修,并顺带钉死饱和态陷阱(watch 必须以末尾条目的 **id** 而非数组长度为源——`MAX_VISIBLE=3` 时 push 会「逐最旧+append」一次赋值完成,长度停在 3 而第四条消息仍需播报)。② 控制者自己简报里的两处数量笔误(对比度 3.16 与 paper 的真实值 2.83、「19 个 ``」是行计数而元素实为 24)均由实现者以 spec 与实测为准纠正,spec §1 已同步修正。教训已入账:派发简报里引用的数量必须元素级核实,不得由 `grep -c` 或 spec 中相邻数字推断。四条转入打磨批(vue-router 升级时复看一处弱断言、撤评语义进可访问名、手动关掉最新 toast 时播报区会重念一条旧消息、spec 口径已修)。C(暗色模式)、OG 社交卡片、播放计数、移动端页头及后续批仍挂账待 owner 启动。 ## [0.3.2] - 2026-10-01 ### Done / 完成 - P10 UX batch-1 (daily-interaction pack) delivered: crearte `ee4edf7` (0.23.0, merge-base `26cd625`) — six user-facing capabilities across six tasks, each through implement → task-level review → adjudication, plus a whole-branch final review cross-checking spec §3/§4/§5 in full. **Toast system** (`composables/useToast.ts` module singleton: success/info 3s, error 5s, max 3 visible oldest-dropped, silent quota/private-mode failures; `ToastHost.vue` mounted in `App.vue`, bottom-right `role=status`/`aria-live=polite`, per-kind hard-shadow styling, TransitionGroup folded into the global reduced-motion branch). **Dirty-form leave guard** on `/submit/new` and `/submit/:id` (`onBeforeRouteLeave` confirm + `beforeunload`; deep-watch of form/kind/both upload ids; edit-mode prefill suppressed in the same window as the existing AAD watcher, manual prefill deliberately counts as an edit; save-success disarms before its `router.push`). **Clickable tags** (game-page + game-card tags → `RouterLink` to `/games?tag=`, card tags keep `relative z-10` above the stretched link, `+N` fold badge stays a span). **Copy-link share** (game detail page writes the canonical in-site URL — `location.origin + router.resolve(...)`, never `location.href` — to clipboard, confirmed via toast, single try/catch also absorbing a missing `navigator.clipboard`). **Recently played** (`lib/recent.ts` local `crearte.recent.v1`: dedup-to-front, cap 12, corrupt JSON reads empty; `GameHost` records on frame phase `ready` via a sync-flush watch so a hosted-target restart that folds booting→ready in one tick still re-bubbles; external works never recorded; landing page renders a 继续游玩 strip between hero and featured, resolving ids against the live catalog, capping at 6, and rendering nothing at all when history is empty so the landing DOM is unchanged for first-time visitors). **Header dropdown** now closes on outside-click and Escape (returning focus to the summary toggle), preserving the existing route-change auto-close. Zero server/deploy changes. Acceptance (five legs, green on merge tip): vitest 601 (baseline 551) / vue-tsc clean / build + build-runtime OK / main e2e 77+1skip (baseline 72+1skip) / noauth 4. Four review pins landed on the branch: `fc0270e` (AppHeader unmount cleanup asserted via removeEventListener spy), `dbf4bf0` (hosted restart re-records via sync-flush phase watch; spec D-H re-pinned), `bb9bb35` (e2e acceptance fixes — the spec's own test plan had picked external-runtime fixtures 2048/a-dark-room that never reach GameHost ready; switched to abs-paths/storage, plus a latent optional-fields pre-navigation race pinned by h1 level), `836b2fb` (AppHeader route-change collapse regression, a spec §5 listed item). Final review verdict 「需修复后合并」 — both closing conditions met before merge. B (keyboard/skip-link/mobile header), C (dark mode), OG social cards, play-count and later batches parked pending owner go-ahead. - P10 UX 第一批(日常交互包)交付:crearte `ee4edf7`(0.23.0,merge-base `26cd625`)——六任务落地六个用户可感能力,每任务经实现→任务级审查→裁定,另加全分支终审对 spec §3/§4/§5 全量对照。**Toast 体系**(`composables/useToast.ts` 模块单例:success/info 3s、error 5s、同屏上限 3 条超限移最旧、配额/隐私模式写失败静默;`ToastHost.vue` 挂入 `App.vue`,右下角 `role=status`/`aria-live=polite`、按 kind 配色硬阴影、TransitionGroup 折入全局 reduced-motion 分支)。**投稿表单脏数据离开守卫**(`/submit/new` 与 `/submit/:id`:`onBeforeRouteLeave` confirm + `beforeunload`;深度观察 form/kind/两个 upload id;编辑回填与既有 AAD watcher 同窗抑制、手动 prefill 有意计为修改;save 成功先解除守卫再 `router.push`)。**标签可点**(作品页+作品卡 tags → `/games?tag=` 的 `RouterLink`,卡内标签保留 `relative z-10` 浮于拉伸链接之上,`+N` 折叠角标维持 span)。**复制链接分享**(作品详情页写入规范站内 URL——`location.origin + router.resolve(...)`,绝不用 `location.href`——经 toast 确认,单一 try/catch 同时兜住 `navigator.clipboard` 缺失)。**最近玩过**(`lib/recent.ts` 本地 `crearte.recent.v1`:去重前插、上限 12、损坏 JSON 读回空;`GameHost` 在 frame phase `ready` 时经 sync-flush watch 记录,hosted 目标重开同 tick 折叠的 booting→ready 仍会重新冒泡;external 作品不记;落地页在 hero 与精选之间渲染「继续游玩」条带,id 对实时目录解析、上限 6、无记录时整段不渲染使首访者落地页 DOM 零变化)。**页头下拉**现支持外点与 Esc 关闭(焦点回 summary),保留既有路由变化自动收起。零后端/部署改动。验收(五腿,合并 tip 全绿):vitest 601(基线 551)/ vue-tsc 零错 / build+build-runtime OK / 主 e2e 77+1skip(基线 72+1skip)/ noauth 4。分支上落四处审查补钉:`fc0270e`(AppHeader 卸载清理经 removeEventListener spy 钉桩)、`dbf4bf0`(hosted 重开经 sync-flush phase watch 再记;spec D-H re-pin)、`bb9bb35`(e2e 验收修正——spec 测试计划自身误选 external-runtime 夹具 2048/a-dark-room 永达不到 GameHost ready,换 abs-paths/storage,另钉住 optional-fields 一处潜伏的导航前竞态)、`836b2fb`(AppHeader 路由变化收起回归,spec §5 明列项)。终审裁定「需修复后合并」——两个闭合条件均在合并前满足。B(键盘/skip-link/移动端页头)、C(暗色模式)、OG 社交卡片、播放计数及后续批挂账待 owner 启动。 ## [0.3.0] - 2026-10-01 ### Done / 完成 - Roadmap closing wave delivered — P8 batch-2 (③ account deletion + ④ static fallback catalog) and P3 reland (backup + observability), per owner's third directive 「实现 roadmap 所有待办事项」. Sub-repo commits: crearte-server `12b8ffb` (0.15.0 — migration 0011 tombstone column; AccountService deletion kernel: password re-check, works delisted, drafts removed with best-effort object delete, pending submissions auto-rejected, sessions invalidated via token_version, email/username rewritten to `deleted-@deleted.invalid`/`gone-` so the original address is immediately reusable, sole-admin self-deletion refused 409 `last_admin` shared with the P7 demote guard; `DELETE /api/auth/account` (204/400/401/409/410, `Cache-Control: no-store`); CLI `user delete ` passwordless operator path; CLI `catalog export --out DIR [--pretty]` emitting the exact StaticContentRepository contract — `index.json` schemaVersion 2 + `games/__.json`, virtual entries carry the bundle object, external entries omit it, cover/bundle.url empty when `STORAGE_S3_*` unset; `user set-role` gets `--by-id`) and crearte `7d5f338` (0.21.0 — AccountView fourth 「危险区:注销账号」 section: password + acknowledgement checkbox gate, busy lock, success → invalidate session → home, failure → alert row; `auth/client.ts` `deleteAccount` with the code-branching `toUserMessage`; AdminUsersView now localizes validation/not_found/internal (P7 copy tail pinned by tests, `7a54152`) and the 409 last_admin echo stays on the admin side — the account view deliberately shows the generic internal copy because the auth client normalizes unknown codes to `internal` and drops the backend message; review note about `AuthApiError` vs `UserManagementApiError` shape resolved in-test). crearte-deploy `12f7c10` (0.6.0) and crearte-server `d627e12` (0.16.0) reland P3 byte-for-byte via cherry-picks `7fcfe0e`/`6ffd1ee`/`93a3c70` whose originals had drifted off master during the rollback window: prod backup tooling (`scripts/backup.sh` pg_dump + mc-mirror with retention and manifest, `restore-drill.sh` against `db-test` only, `docs/BACKUP-RUNBOOK.md`, CI dry-run leg, compose `LOG_FORMAT`/`LOG_LEVEL` passthrough) and observability (stdlib `log` → `slog` mechanical migration across 30 sites incl. the P7/P8b2-new-surface files, per-request `http_request` middleware wired outside `gin.Recovery` so panic paths log status=500, hand-rolled `/metrics` exposition with http/go/pgpool families, `/healthz`+`/metrics` double-skipped, single-instance rate-limit tradeoff documented). P3M merge commit `cecfae1` reconciled the observability branch with the P8b2 surface (CHANGELOG top order 0.16.0→0.15.0, router/serve both-side wiring). Acceptance: server container four-green + fresh real-DB `-p 1 -count=1` (skip-guard grep 0, deletion-chain + observability suites PASS) on every leg; independent reviews PASS (P3S reviewer verified byte-level identity against `6ffd1ee`/`93a3c70`; frontend review returned PASS with two minor notes, pinned before merge as `7a54152`; server-side LOG_LEVEL case-sensitivity divergence between `config.applyLogging` and `observability.newLogger` deferred as a documented nit); branch-build curl smoke 14/14 PASS (wrong-pw 401 `invalid_credentials`, missing-pw 400, sole-admin 409 `last_admin` after verifying token rotation on role change, correct-pw 204 + `no-store`, old token 401, tombstone row fields, original email re-register 201, CLI `user delete` output shape, double-delete rejected, export schemaVersion 2); live-stack metrics smoke on the merged tree (request/duration counters with `nomatch` bucket, pgpool + go families, HELP/TYPE headers, both skips, slog JSON request lines). FE vitest 512 / vue-tsc clean / main e2e 71+1skip / noauth 4. Remaining manual tail for the owner: schedule `backup.sh` (cron or the runbook's systemd timer) and run `restore-drill.sh` against the real prod stack once it is up — this host has no prod stack running, so the drill leg ran against throwaway containers only. Roadmap: P0–P8 all closed; P8 remainder is ④'s render-side consumption (on demand) and nothing else is 待启动. - 路线图收口波次交付——P8 第二批(③账号注销 + ④静态兜底目录导出)与 P3 重落(备份 + 可观测),依 owner 第三条指令「实现 roadmap 所有待办事项」。子仓提交:crearte-server `12b8ffb`(0.15.0——迁移 0011 墓碑列;AccountService 注销内核:密码复核、名下作品全部下架、草稿删除含对象 best-effort、pending 投稿自动驳回、token_version 递增废全部会话、email/username 改写为 `deleted-@deleted.invalid`/`gone-` 使原邮箱即刻可复用、唯一 admin 自拒 409 `last_admin`(与 P7 降级护栏同源);`DELETE /api/auth/account`(204/400/401/409/410,`Cache-Control: no-store`);CLI `user delete ` 免密码运维通道;CLI `catalog export --out DIR [--pretty]` 按 StaticContentRepository 契约出 `index.json`(schemaVersion 2)+ `games/__.json`,virtual 带 bundle、external 省略、未配 `STORAGE_S3_*` 时 cover/bundle.url 置空仍可浏览;`user set-role` 加 `--by-id`)与 crearte `7d5f338`(0.21.0——AccountView 第四段「危险区:注销账号」:密码 + 知晓勾选双闸门、busy 锁、成功即清会话回首页、失败出 alert 行;`auth/client.ts` 加 `deleteAccount` 并分支 `toUserMessage` 文案;AdminUsersView 补齐 validation/not_found/internal 中文化(P7 文案尾,`7a54152` 钉桩),409 原文回显留在管理侧——账号页有意展示通用 internal 文案,因 auth client 将未知码归一并丢弃后端原文;审查提出的错误类型形状问题已在测试内钉清)。crearte-deploy `12f7c10`(0.6.0)与 crearte-server `d627e12`(0.16.0)以 cherry-pick `7fcfe0e`/`6ffd1ee`/`93a3c70` 字节级重放 P3——原提交在回滚窗口脱离 master:prod 备份件(`scripts/backup.sh` pg_dump + mc-mirror + 保留策略 + manifest、`restore-drill.sh` 只连 `db-test`、`docs/BACKUP-RUNBOOK.md`、CI dry-run 腿、compose 透传 `LOG_FORMAT`/`LOG_LEVEL`)与可观测(stdlib `log` 机械迁 `slog` 共 30 处含 P7/P8b2 新面、每请求 `http_request` 中间件挂在 `gin.Recovery` 外层使 panic 路径记 status=500、手写 `/metrics` 出 http/go/pgpool 三族、`/healthz` 与 `/metrics` 双跳过、限流单实例权衡入档)。P3M 合流提交 `cecfae1` 把可观测分支与 P8b2 面调和(CHANGELOG 顶序 0.16.0→0.15.0、router/serve 双侧接线保留)。验收:每腿容器四连绿 + 全新真库 `-p 1 -count=1`(skip 守卫 grep 0,注销链与 observability 套件 PASS);独立审查 PASS(P3S 审查员逐文件对 `6ffd1ee`/`93a3c70` 核到字节级一致;前端审查 PASS with notes——两条次要已合主前钉桩 `7a54152`;server 侧 `config.applyLogging` 与 `observability.newLogger` 的 LOG_LEVEL 大小写策略不一致按次要 deferred);分支真产物 curl 冒烟 14/14 PASS(错密码 401 `invalid_credentials`、缺密码 400、角色变更后先验 token 轮换再证唯一 admin 409 `last_admin`、对密码 204 + `no-store`、旧 token 401、墓碑行字段、原邮箱重注册 201、CLI `user delete` 输出形状、二次注销被拒、导出 schemaVersion 2);合主树实栈 metrics 冒烟(请求/耗时计数含 `nomatch` 桶、pgpool 与 go 族、HELP/TYPE 头、双跳过、slog JSON 请求行)。FE vitest 512 / vue-tsc 零错 / 主 e2e 71+1skip / noauth 4。留给 owner 的手动尾巴:按 runbook 给 `backup.sh` 排定时(cron 或 systemd timer),并在真 prod 栈起来后跑一次 `restore-drill.sh`——本机无 prod 栈在跑,演练腿只对一次性容器做过。路线图:P0–P8 全部闭合;P8 仅剩④的 render 端消费(按需),无待启动项。 ## [0.3.1] - 2026-10-01 ### Done / 完成 - P9 UX batch-1 (browser feedback pack) delivered: crearte `26cd625` (0.22.0 — two-phase router-level `document.title`: `afterEach` static baseline over the full 19-name route table + refinement watches on exactly four data pages (game/catalog/docs/author), home deliberately kept as the bare `crearte 创艺` string so the existing e2e pin never moved; game-page `meta description` with 120-codepoint clipping, DEFAULT fallback and per-navigation reset back to default (review ISSUE-1 patched pre-merge, pinned by a router test); `StatePanel` skeletons honest at last — card variant 3→6 (≥1.5 rows at each 2/3/4-column breakpoint), new `lines` variant on the six non-grid consumers (eight instances incl. AdminView ×3), index.html gains the default description meta). Zero server/deploy changes. Acceptance: vitest 551 (baseline 512 + 39 new) / vue-tsc clean / build OK / main e2e 72+1skip incl. a new title leg / noauth 4. Independent review PASS with notes — ISSUE-1 (leave-game description not restored, spec D-C sub-clause) and ISSUE-2 (spec §1 said "seven non-grid pages", CreatorCenterView does not consume StatePanel — count is six; wording fixed in spec and changelog) both resolved before merge. B (keyboard/skip-link/mobile header) and C (dark mode) batches parked pending owner go-ahead. - P9 UX 第一批(浏览器反馈包)交付:crearte `26cd625`(0.22.0——两段式路由级 `document.title`:`afterEach` 按 19 个路由名全表设静态基线 + 恰好四个数据页(作品/目录/文档/作者)watch 精化;home 有意保持裸 `crearte 创艺` 整串,既有 e2e 钉桩一字未动;作品页 `meta description` 截 120 码点、默认回落、每次导航复位(审查 ISSUE-1 合主前补钉并以 router 测试钉桩);`StatePanel` 骨架终诚实——cards 变体 3→6(2/3/4 列断点各≥1.5 行)、新增 `lines` 变体给六个非网格消费页(八实例含 AdminView×3);index.html 补默认 description)。server/deploy 零改动。验收:vitest 551(基线 512+新增 39)/ vue-tsc 零错 / build OK / 主 e2e 72+1skip(含新增标题腿)/ noauth 4。独立审查 PASS with notes——ISSUE-1(离开作品页 description 未恢复默认,spec D-C 子项)与 ISSUE-2(spec §1 写「7 个非网格页」,实际 CreatorCenterView 不消费 StatePanel,应为六个;spec 与 CHANGELOG 措辞已修正)均合主前处置。B(键盘/skip-link/移动端页头)与 C(暗色模式)两批挂账待 owner 发令。 ## [0.2.9] - 2026-10-01 ### Chores / 杂务 - crearte-deploy `150927e` (0.5.2): `.gitignore` gains `backups/` so P3 backup-script snapshots (e.g. `backups/prod/20260930T095727Z/`) stop polluting `git status`; the on-disk snapshot is untouched. - crearte-deploy `150927e`(0.5.2):`.gitignore` 新增 `backups/`,P3 备份脚本的本机快照(如 `backups/prod/20260930T095727Z/`)不再污染 `git status`;盘上既有快照原样保留。 ## [0.2.8] - 2026-10-01 ### Done / 完成 - P8 batch-1 (triage + copy + feature-switch UI) delivered: crearte-server `921443a` (0.14.0 — `games.Detail` 400 messages split into `user: invalid format` / `slug: invalid format` with user precedence pinned by assertion (status/error codes unchanged); four admin work routes (unpublish/republish/features/revoke) validate :user/:slug at handler entry via shared `validWorkParams`, malformed ids now 400 `invalid work id` instead of a misleading 404 (`adminWorkID` untouched); new gated concurrency test `TestApproveSameWorkIDConcurrent` — two same-work_id new_work approvals, exactly one winner, loser gets ErrWorkIDTaken/ErrSubmissionConflict, one row; CHANGELOG header de-templatized) and crearte `70ba10c` (0.20.0 — CSP editing UI opened to the full seven-key set: inlineStyle/wasm/coop/fullscreen/gamepad added to EditableFeatures/EMPTY_FEATURES/FEATURE_ITEMS/collectFeatures/featuresToForm/hasAnyFeature with Chinese label+hint per switch (risk + scenario spelled out); all three surfaces stay driven by the single FEATURE_ITEMS list — submission form, AdminView expanded row, AdminSubmissionView read-only; payload always carries seven keys preserving the missing-key-keeps-stored-value semantics; features/SubmitFormView/AdminSubmissionView tests rewritten and added; CHANGELOG header de-templatized). Zero deploy changes, zero migrations, zero new deps; runtime flag consumers untouched. Acceptance: server container four-green + fresh-empty-DB -count=1 integration (race test ran, skip-guard grep 0) + `-race` leg PASS (two concurrency tests, no data races — needed the Debian golang:1.24 image, alpine lacks gcc for cgo); curl smoke on a live branch build: detail 400s distinguished, both-bad → user wins, all four admin routes 400 on malformed slug/user, legal-but-missing id still 404; FE vitest 499 / typecheck / admin-flow 7 / main suite 70+1skip (first main-suite decrypt failure was a stale serve-runtime process left by a dead subagent — killed it, rerun green). Dual independent review: crearte PASS (notes: gamepad hint leans on its label for the “what is loosened” clause, accepted); server PASS with notes (only note — user-precedence not pinned by test — fixed as `ee5b960` before merge). Lesson landed: reviewers briefed with an explicit “spec §1–§3 full-text, not just the task brief” clause (P6 D-D gap). Task-2 implementer died mid-run; its uncommitted worktree was verified against spec, pinned as `54b1f82` with a full-message commit rather than redispatched. Roadmap: P8 second batch (③ account deletion awaiting product call, ④ static fallback dir on-demand) remains. - P8 第一批(triage 小项 + 文案 + 权限开关 UI)交付:crearte-server `921443a`(0.14.0——`games.Detail` 400 文案拆为 `user: invalid format` / `slug: invalid format`,双非法 user 优先已用断言钉桩(状态码/错误码不变);四条 admin 作品路由(unpublish/republish/features/revoke)handler 入口经共享 `validWorkParams` 校验 :user/:slug,非法 id 改返 400 `invalid work id` 不再误导成 404(`adminWorkID` 未动);新增门控并发测试 `TestApproveSameWorkIDConcurrent`——同 work_id 两份 new_work 并发审批,恰一条成功、败者 ErrWorkIDTaken/ErrSubmissionConflict、库中恰一行;CHANGELOG 头部去模板腔)与 crearte `70ba10c`(0.20.0——CSP 编辑 UI 开放七键全集:inlineStyle/wasm/coop/fullscreen/gamepad 入 EditableFeatures/EMPTY_FEATURES/FEATURE_ITEMS/collectFeatures/featuresToForm/hasAnyFeature,每开关中文 label+hint 写清风险与适用场景;三处界面仍由单一 FEATURE_ITEMS 驱动——投稿表单、AdminView 展开行、AdminSubmissionView 只读;载荷恒含七键,保住「缺键→保留原值」语义;三套测试改写/新增;CHANGELOG 头部去模板腔)。deploy 零改动、零迁移、零新依赖,运行时 flag 消费端未碰。验收:server 容器四连绿 + 空库 -count=1 集成全绿(竞态测试实跑,skip 守卫 grep 0)+ `-race` 腿 PASS(两并发测试零数据竞争;alpine 无 gcc 需换 Debian golang:1.24 镜像);分支真产物 curl 冒烟全中:detail 400 可区分、双非法 user 赢、admin 四路非法 slug/user 全 400、合法格式不存在仍 404;FE vitest 499 / typecheck / admin-flow 7 / 主套件 70+1skip(首轮 decrypt 一腿失败系夭折子代理残留的旧 serve-runtime 进程污染环境,杀进程复跑绿)。双路独立审查:crearte PASS(注:gamepad hint 的「放宽了什么」靠 label 承载,可接受);server PASS with notes——唯一 note(user 优先缺钉桩)已以 `ee5b960` 在合主前补齐。教训落地:审查员任务书显式要求「对照 spec §1–§3 全文而非仅任务书」(P6 D-D 漏项的根治)。Task2 实现者中途夭折——其未提交工作树经逐条对 spec 核验后以完整提交信息钉成 `54b1f82`,未盲重跑。路线图:P8 第二批(③账号注销待产品决策、④静态兜底目录按需)仍待启动。 ## [0.2.7] - 2026-09-30 ### Done / 完成 - P6 hosted submission delivered as plan A (owner call: author-hosted https URL, embedded play; no file hosting): crearte-server `3e11446` (0.13.0 — D-B runtime immutable on metadata_change, D-C hosted works cannot carry a bundle, unit + fresh-empty-DB integration incl. real-HTTP draft→submit→approve→hosted_url/play_origin/fallback readback and public payload runtime/hostedUrl; zero migrations, zero new deps, Approve mapping untouched — the feared hosted_url write gap was a false alarm, PayloadToWork at import.go:39 already covers it) and crearte `fee5f3b` (0.19.0 — content-layer WorkRuntime three modes with hostedUrl/fallback aligned to server json names, submit-form third radio 自托管内嵌 w/ https + fallback=external⇒url mirror validation, prefill refusal removed and hosted fields backfilled, new_version stays virtual-only; playback side zero changes per spec; vitest 492 / typecheck / admin-flow 6 / main suite 69 green; e2e hosted draft-payload flow added). Dual independent review PASS with notes; six-leg host acceptance green (incl. branch-backend full-loop 1 passed; first admin-flow 1-passed reading was stack-contention false alarm, rerun 6 passed RC=0). T5 CSP probe: deploy templates carry no main-site frame-src (the two `frame-src 'none'` hits belong to runtime-subdomain pages only) — zero deploy changes on record. Known gaps: D-D (admin hostedUrl display row) delivered same day as crearte 0.19.1 `9bd9372` — maintainer-direct follow-up patch (Task 2 brief had omitted the row; reviews passed against the brief rather than full spec §3 — lesson: review against the spec). Plain-text row, deliberately no anchor, plus fallback label row; four legs rerun green (vitest 492 / typecheck / admin-flow 7 / main suite 70). Remaining: new_version hosted rejection is server-side only (FE no hard check, spec-accepted). See spec D-A…D-F. - P6 hosted 作品投稿以方案 A 交付(owner 拍板:作者自部署、投稿只存 https URL、站内沙箱 iframe 播;不做文件托管):crearte-server `3e11446`(0.13.0——D-B metadata_change 禁改 runtime、D-C hosted 禁带 bundle;单测 + 空库集成含真 HTTP 草稿→提交→过审→hosted_url/play_origin/fallback 读回与公开载荷 runtime/hostedUrl;零迁移零新依赖,Approve 落库未动——此前担心的 hosted_url 落库缺口系误报,PayloadToWork 本就覆盖)与 crearte `fee5f3b`(0.19.0——内容层三档 + hostedUrl/fallback 字段与 server json 名逐字对齐;表单第三 radio「自托管内嵌」+ https 校验 + fallback 默认 external 镜像校验;预填拒绝分支删除并回填;new_version 仍 virtual-only;播放端零改动;vitest 492 / typecheck / admin-flow 6 / 主套件 69 绿;e2e 新增 hosted 草稿载荷流)。双路独立审查 PASS with notes;六腿本机验收全绿(含分支后端真栈 full-loop 1 passed;admin-flow 首轮 1 passed 为栈腿争用假警报,复跑 6 passed RC=0 坐实)。T5:deploy 模板无主站 frame-src 下发(两处 'none' 属运行时子域页),零改动记录。遗留:D-D(审核面 hostedUrl 展示行)当日补交 crearte 0.19.1 `9bd9372`——控制者直改小补丁(Task 2 任务书漏列该条;审查按任务书对照未扯出——教训:审查依据应为 spec §3 全量)。纯文本无锚点行+降级中文标签行,四腿复跑全绿(vitest 492 / typecheck / admin-flow 7 / 主套件 70)。仅剩:new_version 拒 hosted 仅 server 拦(前端无硬校验,spec 已接受)。选型见 spec D-A…D-F。 ## [0.2.6] - 2026-09-30 ### Done / 完成 - P7 admin console delivered: crearte-server `ca24805` (0.12.0 — audit_log table via migration 0010, audit middleware on a consolidated admin route group (owner call: no more per-route RequireAdmin), gin FullPath templates recorded for every admin request incl. GETs and failed attempts while unauthorized 401/403 stays unrecorded; user list / PATCH role / audit query endpoints; last-admin demotion guard 409 enforced in the shared service so CLI and API both obey; token invalidation on role change verified end-to-end) and crearte `900f13a` (0.18.0 — /admin/users with search/pagination/demote-confirm dual-point copy incl. 409 echo, /admin/audit with localized time, zh action labels w/ fallback, status coloring, route filter; apiRepo admin trio with AdminApiError; e2e admin-flow extended w/ self-recording semantics; vitest 488 / main suite 68 green). Host acceptance: six legs all green incl. fresh-empty-DB -count=1 integration (10 ok, zero FAIL/skip) and real-stack full-loop 1 passed ×2 against the branch backend. See spec §2 decisions D-A…D-D. - P7 管理后台增强交付:crearte-server `ca24805`(0.12.0——迁移 0010 audit_log;审计中间件挂收敛后的 admin 路由组(owner 定稿:不再逐条手挂),admin 面全请求入史含 GET 与失败尝试(FullPath 模板),未遂 401/403 不入史;用户列表/PATCH 角色/审计查询三端点;唯一 admin 降级 409 护栏落在共享 service,CLI/API 双覆盖;角色变更废 token 端到端验证)与 crearte `900f13a`(0.18.0——/admin/users(搜索/分页/降级确认双要点文案含 409 原文回显)+ /admin/audit(本地化时间/中文动作标签+未知回退/状态着色/route 过滤);apiRepo 管理面三方法+AdminApiError;e2e admin-flow 扩两流含自记录语义;vitest 488 / 主套件 68 绿)。本机验收六腿全绿:容器四连、空库 -count=1 集成 10 ok 零 FAIL 零 skip、护栏矩阵(非唯一降级 OK / 唯一降级 CLI 拒 + API 409)、废 token 401、审计流水含失败尝试、分支后端真栈 full-loop 1 passed ×2。选型见 spec §2 D-A…D-D。 ## [0.2.5] - 2026-09-30 ### Docs / 文档 - Creator center `/creator` delivered (maintainer-direct need, plan 2026-09-30-creator-center.md executed): pure-frontend crearte 0.17.0 — new route + homepage-style view (hero, auth-state-aware work-data placeholder card, tutorial placeholder card linking to the submission guide) and a third header nav tab; merged & pushed as crearte `e2fab8a` after TDD e2e (4 new default cases + 1 appended noauth case) and a 6-lens review; server/deploy untouched by design. - 创作者中心 `/creator` 交付(维护者直接需求,计划 2026-09-30-creator-center.md 已执行):纯前端 crearte 0.17.0——新路由 + 首页样式视图(hero、按登录态分流的作品数据占位卡、链向现有投稿指南的教程占位卡)与页头第三个导航 tab;TDD e2e(默认配置新增 4 用例 + noauth 追加 1 断言)与 6 透镜审查后以 crearte `e2fab8a` 合并推送;后端/部署仓按设计零改动。 ## [0.2.4] - 2026-09-30 ### Docs / 文档 - Roadmap P2 delivered: GitHub Actions baseline in all three repos — crearte-server `validate.yml` (check + empty-DB Postgres integration with a silent-skip guard + real-stack e2e-stack hosting the cross-repo checkout pair), crearte `validate.yml` (push:master trigger) plus `e2e-stack.sh` GO/REQUIRED env knobs, crearte-deploy `validate.yml` (compose config across four profiles with a negative empty-password guard test). First real-stack run uncovered a serve-runtime defect: the runtime triple (/__bootstrap, /sw.js, /agent.js) was gated behind the fixtures subdomain table, so live-registered games could never install the SW — fixed with a position-only move (crearte `5e0fb2e`). Merged & pushed 2026-09-30: server `7b97108` / crearte `711b6de` / deploy `522545d`; Actions enablement and branch protection are owner-manual tails (spec §2.4). - 路线图 P2 交付:三仓 GitHub Actions 基线——crearte-server `validate.yml`(check + 空库 Postgres 集成层带静默 skip 守卫 + e2e-stack 真栈 job 宿主双仓 checkout)、crearte `validate.yml`(push:master 触发)及 `e2e-stack.sh` 的 GO/REQUIRED 环境变量开关、crearte-deploy `validate.yml`(四 profile compose config 正路 + 空密码反路守卫断言)。真栈首跑拓出 serve-runtime 缺陷:运行时三件套(/__bootstrap、/sw.js、/agent.js)被卡在夹具子域表门槛之后,活体注册的作品永远装不上 SW——已以纯位置搬移修复(crearte `5e0fb2e`)。2026-09-30 合并推送:server `7b97108` / crearte `711b6de` / deploy `522545d`;Actions 启用确认与分支保护为 owner 手动尾巴(spec §2.4)。 ## [0.2.3] - 2026-09-30 ### Docs / 文档 - Roadmap P5 delivered: favorites & 5-star ratings went full-stack — server `favorites`/`ratings` tables + `ReactionRepository` with reaction-watermark ETag invalidation and user-space endpoints (crearte-server `e3da246`), and frontend hot sort (Bayesian prior mean + favorite log weight), game-page reaction widget, card badges, account my-reactions section (crearte `eb5fbed`), merged & pushed 2026-09-30 after a 9-step live prod-stack smoke; crearte-deploy untouched by design (scope revision recorded in spec). - 路线图 P5 交付:收藏与五星评分全栈落地——服务端 `favorites`/`ratings` 新表 + `ReactionRepository`(反应水位驱动 ETag 失效)与用户态端点(crearte-server `e3da246`);前端热门排序(贝叶斯先验均分 + 收藏对数权重)、详情页反应组件、卡片徽标、账号页我的反应(crearte `eb5fbed`),2026-09-30 经 prod 演练栈 9 步冒烟后合并推送;crearte-deploy 按设计零改动(范围修订已记入 spec)。 ## [0.2.2] - 2026-09-29 ### Docs / 文档 - Roadmap P1 delivered: prod write side went live in the compose drill — minio-prod + api-prod storage/games env + templated nginx wildcard block (crearte `63bb96d` / crearte-deploy `4d53d58`), POSTGRES_PASSWORD default retired, TLS deferred by design with a real-server checklist in README. - 路线图 P1 交付:prod 写侧在本机演练栈完整启用——minio-prod、api-prod 存储/游玩域名环境、nginx 通配块模板化(crearte `63bb96d` / crearte-deploy `4d53d58`);POSTGRES_PASSWORD 默认值退役;TLS 按设计缓做,真机清单已入 README。 ## [0.2.1] - 2026-09-29 ### Fixed / 修复 - `clone_all.sh` pins `master` for `crearte` and `crearte-server` instead of the stale `feat/submission-preview` work branch — fresh clones and updates land on the integration branch that carries the merged roadmap work. (Note: `update_repo` switches clean checkouts to the pinned branch; dirty ones are skipped.) - `clone_all.sh` 中 `crearte` 与 `crearte-server` 的引导分支由过时的 `feat/submission-preview` 工作分支改为 `master` —— 全新克隆与更新落在承载路线图已合并工作的集成分支上。(注意:`update_repo` 会把干净的 checkout 切到钉子分支,脏工作树自动跳过切换。) ## [0.2.0] - 2026-09-29 ### Changed / 变更 - Roadmap delivered: P0 (known-defect cleanup — CORS `If-None-Match` fix in crearte-server `a8ea755`, compose key-store drift cleanup in crearte-deploy `27044be`) and P4 (author page `/users/:user`, crearte `f12cbf1`) are merged to their repos' master and pushed; roadmap statuses updated. - 路线图交付:P0(已知缺陷清理——crearte-server `a8ea755` 的 CORS `If-None-Match` 修复、crearte-deploy `27044be` 的 compose 密钥库遗留清理)与 P4(作者主页 `/users/:user`,crearte `f12cbf1`)均已合并至各仓 master 并推送;路线图状态已更新。 ## [0.1.0] - 2026-09-29 ### Added / 新增 - Added `docs/ROADMAP.md`: the cross-repo roadmap decomposed into sub-projects P0–P8 (ops foundation → product value → governance), with ordering rationale and a doc index for future specs and plans. - 新增 `docs/ROADMAP.md`:跨仓库路线图,分解为 P0–P8 子项目(上线底座 → 产品价值 → 治理长尾),含排序理由与后续 spec/计划的文档索引。 ### Changed / 变更 - Doc convention: all specs, implementation plans and cross-repo coordination docs now live in the monorepo `docs/` instead of per-repo `docs/superpowers/`; this supersedes the crearte-deploy 0.3.0 "canonical home" convention. Commits in the monorepo wrapper may go directly to `master` (user-approved); the three inner repos keep their own branch rules. - 文档约定:所有 spec、实现计划与跨仓库协作文档统一收归 monorepo `docs/`,不再散落各内层仓库的 `docs/superpowers/`;此约定取代 crearte-deploy 0.3.0 的「canonical home」约定。monorepo wrapper 可直接提交 `master`(维护者确认),内层三仓仍遵循各自分支规范。