From 5b2f37956e72a6c341011da057d3df391504cd50 Mon Sep 17 00:00:00 2001 From: ghbvf <104540935+ghbvf@users.noreply.github.com> Date: Thu, 18 Jun 2026 02:05:58 +0800 Subject: [PATCH] =?UTF-8?q?fix(devboard):=20cell-manifest=20=E6=BA=90?= =?UTF-8?q?=E8=B7=AF=E5=BE=84=E9=9A=8F=E5=90=8E=E7=AB=AF=20cells=E2=86=92c?= =?UTF-8?q?orecells=20=E8=BF=81=E7=A7=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 后端 ghbvf/gocell 将生产 cells 从顶层 cells/ 迁到 corecells/(4 个: accesscore/auditcore/configcore/syscore),cell-manifest 默认源路径 ../gocell/cells 失效 → cell-manifest-readonly CI 在所有 PR 上红 (codegen 读 ../gocell/contracts 未受影响)。 - tools/cell-manifest 默认路径 + generatedFrom/Source 注释 → corecells - derive.spec 断言同步 - 重新生成 cells.generated.ts(现含 4 cell,syscore 新纳入) - useCellsStore.spec:cell 数 3 → 4 - README / workflow 注释同步 注:源路径仍是 unpinned sibling checkout(追后端默认分支),属同类 脆弱性根因;后续优化(pin 后端 ref / 发布契约包)另议。 Closes #71 Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/cell-manifest-diff.yml | 2 +- packages/devboard/README.md | 4 +- .../devboard/src/manifest/cells.generated.ts | 156 +++++++++++++++++- .../devboard/src/stores/useCellsStore.spec.ts | 4 +- tools/cell-manifest/README.md | 4 +- tools/cell-manifest/src/derive.spec.ts | 4 +- tools/cell-manifest/src/derive.ts | 4 +- tools/cell-manifest/src/index.ts | 4 +- 8 files changed, 166 insertions(+), 16 deletions(-) diff --git a/.github/workflows/cell-manifest-diff.yml b/.github/workflows/cell-manifest-diff.yml index d7f7e39..845a291 100644 --- a/.github/workflows/cell-manifest-diff.yml +++ b/.github/workflows/cell-manifest-diff.yml @@ -17,7 +17,7 @@ jobs: path: gocell-web # 后端 cells 源(公开仓库 ghbvf/gocell),checkout 为 gocell-web 的同级目录 - # (cell-manifest 默认读 ../gocell/cells)。 + # (cell-manifest 默认读 ../gocell/corecells)。 - name: Checkout gocell (backend cells) uses: actions/checkout@v4 with: diff --git a/packages/devboard/README.md b/packages/devboard/README.md index 6fbdb6c..26f0cff 100644 --- a/packages/devboard/README.md +++ b/packages/devboard/README.md @@ -2,7 +2,7 @@ > 开发者平台聚合视图:Cells / Groups / Coverage / Contracts / Deps(Batch 5/6) > -> **对应后端 cell**:无(聚合派生视图)。Cells 数据由构建期从后端 `../gocell/cells/*/cell.yaml` + `slices/*/slice.yaml` 派生(见下)。 +> **对应后端 cell**:无(聚合派生视图)。Cells 数据由构建期从后端 `../gocell/corecells/*/cell.yaml` + `slices/*/slice.yaml` 派生(见下)。 ## 对外 exports @@ -35,7 +35,7 @@ PDP 门:后端无 `contract`/`dep`/`group` resource,路由守卫降级到 `r `tools/cell-manifest/` 镜像 `tools/codegen` 模式:构建期读后端 `cell.yaml` + `slice.yaml` → 派生 `src/manifest/cells.generated.ts`(`/* eslint-disable */` + DO-NOT-EDIT banner,prettier-ignored)。 - 单源派生 + CI `git diff --exit-code`(`.github/workflows/cell-manifest-diff.yml`)守门,业务包手改生成物即红 → 违反不可表达(Hard)。 -- 本地重跑:`GOCELL_CELLS_DIR=../gocell/cells pnpm cell-manifest`(CI 把 `ghbvf/gocell` checkout 为同级目录,默认路径生效)。 +- 本地重跑:`GOCELL_CELLS_DIR=../gocell/corecells pnpm cell-manifest`(CI 把 `ghbvf/gocell` checkout 为同级目录,默认路径生效)。 - `slice.yaml` 的 `contractUsages[].role`:`serve`/`publish` → cell **produces**;`call`/`subscribe` → **consumes**;跨 cell 的 consume→produce 解析出 `dependsOnCells` / `requiredByCells`。 - **不可派生字段**(运行时 QPS/p95/健康分、tasks、SLOC、version、oncall)→ 显式降级为 "—" / `UnavailablePanel`,**绝不伪造**。需后端健康端点(BR-001)才补。 diff --git a/packages/devboard/src/manifest/cells.generated.ts b/packages/devboard/src/manifest/cells.generated.ts index 3709d16..c8576a1 100644 --- a/packages/devboard/src/manifest/cells.generated.ts +++ b/packages/devboard/src/manifest/cells.generated.ts @@ -1,6 +1,6 @@ /* eslint-disable */ // AUTO-GENERATED by tools/cell-manifest — DO NOT EDIT BY HAND. -// Source: gocell/cells/** +// Source: gocell/corecells/** // Regenerate: pnpm cell-manifest (CI guards via git diff --exit-code) import type { CellManifest } from './types' @@ -149,6 +149,50 @@ export const CELL_MANIFEST: CellManifest = { ], "waivers": [] }, + { + "id": "policymanage", + "belongsToCell": "accesscore", + "consistencyLevel": "L2", + "lifecycle": "asset", + "contractUsages": [ + { + "contract": "event.policy.updated.v1", + "role": "publish" + }, + { + "contract": "http.policy.create.v1", + "role": "serve" + }, + { + "contract": "http.policy.get.v1", + "role": "serve" + }, + { + "contract": "http.policy.update.v1", + "role": "serve" + }, + { + "contract": "http.policy.delete.v1", + "role": "serve" + }, + { + "contract": "http.policy.list.v1", + "role": "serve" + } + ], + "unitTests": [ + "unit.policymanage.service" + ], + "contractTests": [ + "contract.event.policy.updated.v1.publish", + "contract.http.policy.create.v1.serve", + "contract.http.policy.get.v1.serve", + "contract.http.policy.update.v1.serve", + "contract.http.policy.delete.v1.serve", + "contract.http.policy.list.v1.serve" + ], + "waivers": [] + }, { "id": "rbacassign", "belongsToCell": "accesscore", @@ -328,6 +372,25 @@ export const CELL_MANIFEST: CellManifest = { "contractTests": [], "waivers": [] }, + { + "id": "sessionverifyrpc", + "belongsToCell": "accesscore", + "consistencyLevel": "L0", + "lifecycle": "experimental", + "contractUsages": [ + { + "contract": "grpc.auth.session.verify.v1", + "role": "serve" + } + ], + "unitTests": [ + "unit.sessionverifyrpc.server" + ], + "contractTests": [ + "contract.grpc.auth.session.verify.v1.serve" + ], + "waivers": [] + }, { "id": "setup", "belongsToCell": "accesscore", @@ -368,6 +431,10 @@ export const CELL_MANIFEST: CellManifest = { "contract": "event.auth.bootstrap-failed.v1", "role": "publish" }, + { + "contract": "event.policy.updated.v1", + "role": "publish" + }, { "contract": "event.role.assigned.v1", "role": "publish" @@ -404,6 +471,10 @@ export const CELL_MANIFEST: CellManifest = { "contract": "event.user.updated.v1", "role": "publish" }, + { + "contract": "grpc.auth.session.verify.v1", + "role": "serve" + }, { "contract": "http.auth.login.v1", "role": "serve" @@ -471,6 +542,26 @@ export const CELL_MANIFEST: CellManifest = { { "contract": "http.auth.user.update.v1", "role": "serve" + }, + { + "contract": "http.policy.create.v1", + "role": "serve" + }, + { + "contract": "http.policy.delete.v1", + "role": "serve" + }, + { + "contract": "http.policy.get.v1", + "role": "serve" + }, + { + "contract": "http.policy.list.v1", + "role": "serve" + }, + { + "contract": "http.policy.update.v1", + "role": "serve" } ], "consumes": [ @@ -697,13 +788,18 @@ export const CELL_MANIFEST: CellManifest = { { "contract": "http.audit.list.v1", "role": "serve" + }, + { + "contract": "http.audit.get.v1", + "role": "serve" } ], "unitTests": [ "unit.auditquery.service" ], "contractTests": [ - "contract.http.audit.list.v1.serve" + "contract.http.audit.list.v1.serve", + "contract.http.audit.get.v1.serve" ], "waivers": [] } @@ -713,6 +809,10 @@ export const CELL_MANIFEST: CellManifest = { "contract": "event.audit.appended.v1", "role": "publish" }, + { + "contract": "http.audit.get.v1", + "role": "serve" + }, { "contract": "http.audit.list.v1", "role": "serve" @@ -1106,7 +1206,57 @@ export const CELL_MANIFEST: CellManifest = { "accesscore", "auditcore" ] + }, + { + "id": "syscore", + "name": "SysCore", + "domain": "Sys", + "type": "support", + "consistencyLevel": "L1", + "lifecycle": "asset", + "durabilityMode": "durable", + "owner": { + "team": "platform", + "role": "cell-owner" + }, + "goStructName": "SysCore", + "schemaPrimary": "cell_syscore", + "requires": [], + "l0Dependencies": [], + "smokeTests": [ + "smoke.syscore.startup" + ], + "slices": [ + { + "id": "healthread", + "belongsToCell": "syscore", + "consistencyLevel": "L0", + "lifecycle": "asset", + "contractUsages": [ + { + "contract": "http.admin.health.cells.v1", + "role": "serve" + } + ], + "unitTests": [ + "unit.healthread.service" + ], + "contractTests": [ + "contract.http.admin.health.cells.v1.serve" + ], + "waivers": [] + } + ], + "produces": [ + { + "contract": "http.admin.health.cells.v1", + "role": "serve" + } + ], + "consumes": [], + "dependsOnCells": [], + "requiredByCells": [] } ], - "generatedFrom": "gocell/cells/**/{cell.yaml,slices/*/slice.yaml}" + "generatedFrom": "gocell/corecells/**/{cell.yaml,slices/*/slice.yaml}" } diff --git a/packages/devboard/src/stores/useCellsStore.spec.ts b/packages/devboard/src/stores/useCellsStore.spec.ts index 52722e8..f7c1f9c 100644 --- a/packages/devboard/src/stores/useCellsStore.spec.ts +++ b/packages/devboard/src/stores/useCellsStore.spec.ts @@ -13,10 +13,10 @@ describe('useCellsStore', () => { expect(store.selectedId).toBeNull() }) - it('cells returns all manifest cells (length 3)', () => { + it('cells returns all manifest cells (length 4)', () => { const store = useCellsStore() expect(store.cells).toBe(CELL_MANIFEST.cells) - expect(store.cells.length).toBe(3) + expect(store.cells.length).toBe(4) }) it('byId returns a known cell entry', () => { diff --git a/tools/cell-manifest/README.md b/tools/cell-manifest/README.md index 7956241..1c22ac5 100644 --- a/tools/cell-manifest/README.md +++ b/tools/cell-manifest/README.md @@ -1,6 +1,6 @@ # @gocell/cell-manifest -> Cell manifest 单向派生器:后端 `gocell/cells/*/cell.yaml` + `slices/*/slice.yaml` → `packages/devboard/src/manifest/cells.generated.ts`。 +> Cell manifest 单向派生器:后端 `gocell/corecells/*/cell.yaml` + `slices/*/slice.yaml` → `packages/devboard/src/manifest/cells.generated.ts`。 是 AI-robust「Hard」约束的执行体(`ai-robust.md` §载体决策原则 第 1 条):单源 YAML 派生 + CI `git diff --exit-code` 守门(`.github/workflows/cell-manifest-diff.yml`),业务包手改生成物在 CI 不可表达。生成文件带 `: CellManifest` 类型注解(来自 devboard 的规范 `./types`),任何形状漂移在 `@gocell/devboard typecheck` 失败。 @@ -10,7 +10,7 @@ pnpm cell-manifest # = pnpm -F @gocell/cell-manifest generate ``` -- **源路径**:默认 `/../gocell/cells`(gocell-web 与后端 gocell 同级 checkout;CI 亦如此布局)。可经环境变量 `GOCELL_CELLS_DIR` 覆盖(如 git worktree 本地开发:`GOCELL_CELLS_DIR=../gocell/cells pnpm cell-manifest`)。 +- **源路径**:默认 `/../gocell/corecells`(gocell-web 与后端 gocell 同级 checkout;CI 亦如此布局)。可经环境变量 `GOCELL_CELLS_DIR` 覆盖(如 git worktree 本地开发:`GOCELL_CELLS_DIR=../gocell/corecells pnpm cell-manifest`)。 - **产物**:`packages/devboard/src/manifest/cells.generated.ts`,带 `/* eslint-disable */` + DO-NOT-EDIT banner(已加入 `eslint.config.js` ignores + `.prettierignore`)。 ## 派生规则 diff --git a/tools/cell-manifest/src/derive.spec.ts b/tools/cell-manifest/src/derive.spec.ts index a4279ad..b0d9cfa 100644 --- a/tools/cell-manifest/src/derive.spec.ts +++ b/tools/cell-manifest/src/derive.spec.ts @@ -563,7 +563,7 @@ describe('buildManifest', () => { it('generatedFrom is the static note (deterministic, no timestamp)', () => { const manifest = buildManifest([]) - expect(manifest.generatedFrom).toBe('gocell/cells/**/{cell.yaml,slices/*/slice.yaml}') + expect(manifest.generatedFrom).toBe('gocell/corecells/**/{cell.yaml,slices/*/slice.yaml}') }) it('[blind-spot] determinism: buildManifest twice on same input → deep-equal', () => { @@ -657,7 +657,7 @@ describe('renderManifestModule', () => { it('produces a TS module string with CELL_MANIFEST export', () => { const manifest: CellManifest = { cells: [], - generatedFrom: 'gocell/cells/**/{cell.yaml,slices/*/slice.yaml}', + generatedFrom: 'gocell/corecells/**/{cell.yaml,slices/*/slice.yaml}', } const output = renderManifestModule(manifest) expect(output).toContain('/* eslint-disable */') diff --git a/tools/cell-manifest/src/derive.ts b/tools/cell-manifest/src/derive.ts index d13b4bd..8e86504 100644 --- a/tools/cell-manifest/src/derive.ts +++ b/tools/cell-manifest/src/derive.ts @@ -313,7 +313,7 @@ export function buildManifest(rawCells: RawCellWithSlices[]): CellManifest { return { cells: finalEntries, - generatedFrom: 'gocell/cells/**/{cell.yaml,slices/*/slice.yaml}', + generatedFrom: 'gocell/corecells/**/{cell.yaml,slices/*/slice.yaml}', } } @@ -327,7 +327,7 @@ export function renderManifestModule(m: CellManifest): string { return [ '/* eslint-disable */', '// AUTO-GENERATED by tools/cell-manifest — DO NOT EDIT BY HAND.', - '// Source: gocell/cells/**', + '// Source: gocell/corecells/**', '// Regenerate: pnpm cell-manifest (CI guards via git diff --exit-code)', "import type { CellManifest } from './types'", '', diff --git a/tools/cell-manifest/src/index.ts b/tools/cell-manifest/src/index.ts index 0755842..8f8828e 100644 --- a/tools/cell-manifest/src/index.ts +++ b/tools/cell-manifest/src/index.ts @@ -2,7 +2,7 @@ * @gocell/cell-manifest — IO orchestration layer. * * Reads cell.yaml + slices/[x]/slice.yaml from GOCELL_CELLS_DIR (defaults to - * ../gocell/cells relative to repo root), derives CellManifest via pure + * ../gocell/corecells relative to repo root), derives CellManifest via pure * derive.ts functions, and writes the generated TS module to * packages/devboard/src/manifest/cells.generated.ts. * @@ -18,7 +18,7 @@ import { buildManifest, renderManifestModule } from './derive' const SCRIPT_DIR = dirname(fileURLToPath(import.meta.url)) const REPO_ROOT = resolve(SCRIPT_DIR, '../../..') -const CELLS_DIR = resolve(process.env['GOCELL_CELLS_DIR'] ?? join(REPO_ROOT, '../gocell/cells')) +const CELLS_DIR = resolve(process.env['GOCELL_CELLS_DIR'] ?? join(REPO_ROOT, '../gocell/corecells')) const OUT = join(REPO_ROOT, 'packages/devboard/src/manifest/cells.generated.ts') function main(): void {