diff --git a/.claude/skills/pm-dispatch/SKILL.md b/.claude/skills/pm-dispatch/SKILL.md index 8b0d4f8150..ac5eb1ffc5 100644 --- a/.claude/skills/pm-dispatch/SKILL.md +++ b/.claude/skills/pm-dispatch/SKILL.md @@ -119,6 +119,7 @@ PM 的工作是循环:选卡 → 认领 → 派发 → 收集 → 复核 → 报 | `pm:epic`(父单或 sub-issue) | 已由 epic PM 保留;其它 PM 永不取;⛔ 永不与 `pm:queue` 同挂 | | `pm:seat` | 座位登记贴:协议载体,不是待分诊的工作 | | `priority:p0` | 插队:可超 `batch`、破轮次立即派发;⛔ 不豁免同文件串行、深度等待与认领协议 | +| `area:*` | 功能轴:每卡恰一个;分诊首触打,与 `domain:*` 同笔;工具卡打它所护的轴;⛔ 不回填存量。四读者:维护者按轴看板;定级继承该轴清单项;父单分组;候选顺序,即「功能点位次」= 父单在「路上的功能点」上的次序;同轴至多一个在飞,除非文件面不相交 | | open PR 引用该单 | 已实现,复核中 | | merged PR 带 `Fixes #n` | 完成(GitHub 关单) | @@ -133,7 +134,7 @@ PM 的工作是循环:选卡 → 认领 → 派发 → 收集 → 复核 → 报 - declared≠enforced 观察类 ⇒ 转 enforce-or-remove 通道;真 won't-fix 候选 ⇒ 逐卡进决策箱。 - 派发与折叠检查时读半状态巡查锚的 H17 触发文件索引,与本次派发文件面求交。 - 相交 ⇒ 按该 hold 评论的 rider/restart 条款处置:点名该单,顺手活列为申报过的增项。 -- 关闭即在同一笔摘掉 `pm:*` 状态标;`domain:*` 与类型标签留下,归属不是状态。 +- 关闭即在同一笔摘掉 `pm:*` 状态标;`domain:*`、`area:*` 与类型标签留下,归属不是状态。 - `state_reason` 与关闭理由一致:撤单/不做 ⇒ `not_planned`,重复 ⇒ `duplicate` + `duplicate_of`。 - `Blocked-by:` 行是机器可 grep 的反向索引,一遍读喂三个职责,⛔ 只做第一件。 - 三职责:上游关单放回解锁卡;按解锁扇出排序;在合并后的 ref 上重验回队卡文件面。 @@ -214,7 +215,7 @@ PM 的工作是循环:选卡 → 认领 → 派发 → 收集 → 复核 → 报 - transfer 不可用时重建:出处头 + 裸 `#N` 改全名 + 关源单为 moved。 - 缝卡收窄为真协调卡:留 objectstack 带 `repo:*`,正文点名读者(哪个座位、哪一步)。 - 决策收件箱按仓:平台在 objectstack / objectui,元数据项目在本仓;在飞卡 ⛔ 不中途转仓。 -- 规则 2:跨仓 feature 或 objectui 消费的 `Seam:` 卡恒由分诊立父单 + 每仓一子单,spec/后端先行。 +- 规则 2:跨层功能点或 objectui 消费的 `Seam:` 卡恒由分诊立父单 + 逐层子单,spec/后端先行。 - 下游带 `Blocked-by: #`;`Blocked-by` 未关闭/未合并的不派发,对 GitHub 现验。 - 被链接或同父的两单永不同批。 - pin 滞后是盲区:本仓 pin 是否已覆盖该 commit 是第二读数,派发前用 REST `compare` 核祖先。 @@ -242,7 +243,7 @@ PM 的工作是循环:选卡 → 认领 → 派发 → 收集 → 复核 → 报 ## 域车道 - 锚定规则:每个包恰属一个域;`domain:*` = 修复落地包的域;`Seam:` 卡归 spec 席,默认纵向派发。 -- 唯一例外 `packages/lint` 等与 spec 相交的 devx 面:围着 spec 契约转的归 `domain:spec`,余留 devx。 +- `domain:*` 只决定文件归属:锚定、热文件串行、单认领路径;⛔ 不是队列或优先级单位。 - `Seam:` 卡认领申报两端;验收 = 消费端读该键(活性账本行离开 `planned`)或键随账本行退役。 - 域由分诊读代码判定,⛔ 绝不从 issue 标题的词汇猜域;说不出修复碰哪个文件就还不可标。 @@ -258,7 +259,6 @@ PM 的工作是循环:选卡 → 认领 → 派发 → 收集 → 复核 → 报 | (无固定归属,按落点分诊) | `packages/apps/*`、`packages/console`(dist 由脚本生成 ⛔ 不手改;UI 缺陷走 `repo:objectui`)、`examples/*`(归它演练的子系统)、`docs/audits/**` | - 表未覆盖的包首次分诊时归类并走 PR 更新本表;新增或退役 `domain:*` 必须同批改本表。 -- 座位在编以 `label:pm:seat` 索引为准,每车道(`domain:*`/`repo:*`)一组座位贴、每席恰一张。 - `domain:*` 只由分诊席产出,例外仅在飞卡衍生 sub-issue 承父卡域;无标签的卡 ⛔ 不得认领。 - 跨域例外路径:拆不动的跨域单 PR 由分诊席指定一个车道 PM 认领,认领评论申报文件面。 - 派发前在飞检查:读本车道 `pm:dispatched` 卡认领评论申报的文件面,本地求交、不另发查询。 @@ -294,7 +294,7 @@ PM 的工作是循环:选卡 → 认领 → 派发 → 收集 → 复核 → 报 ## Epic 子树车道 -- 大开发(父单 + sub-issue 树)整体委托一个专职 PM 会话:`/pm-dispatch epic:#`。 +- 大开发与跨层功能点(spec/运行时/前端)整体委托一个专职 PM 会话:`/pm-dispatch epic:#`。 - 委托信号成对落地:父单打 `pm:epic` + 正文写会话 ID 与声明的文件领地。 - epic 立卡挂父单、打 `pm:epic`,⛔ 永不 `pm:queue`;`label:pm:epic` 即父子保留全集,域座位不取。 - 队列 = 子树 open 未认领 sub-issue,每轮重读不缓存;其它 PM 候选获取跳过整棵子树。 @@ -310,7 +310,6 @@ PM 的工作是循环:选卡 → 认领 → 派发 → 收集 → 复核 → 报 ## 分诊座位职责 -- sweep 与首触定级只对多车道仓,单车道仓机械三务自理。 - 发版板(无板仓跳过)、查重/shadow 检查与代裁通道全仓照跑。 - fire 开局只按名加载互斥检查所需工具,`ToolSearch` 用 `select:`;判定本轮有活才加载其余。 - ⛔ 分诊 fresh session 开局不做泛关键词 ToolSearch;可验判据:空转轮 ~4 万 token 以内。 @@ -372,6 +371,7 @@ PM 的工作是循环:选卡 → 认领 → 派发 → 收集 → 复核 → 报 - 产品仓 P0/P1 开着时,无解锁对象的 p2/p3 `tooling` 卡同样关。 - 路由是分诊的技术判断,⛔ 永不升级哪个仓的问题;父单是协调节点,永不派发。 - 父单已有子结构的:父单队列标签即可,分诊逐个展开路由、补 `Blocked-by:` 排序。 +- 跨层功能点(≥2 层)立父单带 `area:*`+`pm:epic`+清单项级,逐层子单按 `Blocked-by:` 排。 - 每张留一条英文审计评论(`Triage: lands in …; rationale: …`),可选带 `Size/model suggestion:` 行。 - 查重/shadow 检查先按文件/机制查本仓与姊妹仓 open 卡(含 `pm:dispatched`),再跟引用与关键词。 - 同文件同机制 = 同一发现,不分车道,首触定级即并:证据搬先卡,后卡关 `duplicate_of`。 @@ -470,9 +470,9 @@ PM 的工作是循环:选卡 → 认领 → 派发 → 收集 → 复核 → 报 - 阻塞项在飞 ⇒ 等:`pm:blocking` 在其车道排最前、等待者写该卡;p0/p1 优先级沿链传递。 - 取卡前置 = `docs/NORTH-STAR.md`「优先级」第 3 条:产品仓开放 P0/P1 每次取卡现读。 - 取卡全序:维护者直派插队卡(出处三件)> 契约面卡(判据见 `references/lanes/spec.md`)> 标签序。 -- 标签序:`priority:p0` > `pm:blocking` > `target:` 板上项 > p1 > p2 > p3 > 无级;同级先 `Bug` 再卡龄。 +- 标签序:`priority:p0` > `pm:blocking` > 功能点位次 > `target:` 板上项 > p1 > p2 > p3 > 无级。 - `pm:blocking` 级内先按解锁扇出(从 `Blocked-by:` 反向索引现算,⛔ 扇出数不落标签)。 -- 全序每级取既有信号现读/现算,零逐卡维护;优先非豁免;无级/缺 `Path:` 轮报记分诊缺口。 +- 全序每级现读/现算,零逐卡维护;同级先 `Bug` 再卡龄;无级/缺 `Path:` 轮报记分诊缺口。 - 解锁那一刻 PM 自己的判断最不可信:裁决收窄或关掉了那张卡是假设不是前提。 - 该假设以机制假设身份进派发令,被证伪就在同一张卡公开更正。 diff --git a/.claude/skills/pm-dispatch/references/core-rules.md b/.claude/skills/pm-dispatch/references/core-rules.md index 163058ab2a..030185679b 100644 --- a/.claude/skills/pm-dispatch/references/core-rules.md +++ b/.claude/skills/pm-dispatch/references/core-rules.md @@ -55,15 +55,15 @@ - 多车道仓的域标签、type、定级与查重只由中央分诊生产,单车道仓自理三务不产域标签。 - 跨仓查重与 shadow 检查恒归中央 ⛔ 不下放;决策卡入本仓收件箱,在飞卡 ⛔ 不中途转仓。 - issue 住在修复落地的仓,抽掉 objectstack 仍成立的当场转仓;缝卡须带仓标签并点名读者。 -- 跨仓 feature 或跨仓 `Seam:` 卡拆成父单加每仓子单,下游带 `Blocked-by:`,上游未关 ⛔ 不派发。 +- 跨层功能点或跨仓 `Seam:` 卡拆成父单加逐层子单,下游带 `Blocked-by:`,上游未关 ⛔ 不派发。 - pin 消费的仓派发前核 pin 是否已覆盖那个提交,发布包消费的仓判据是消费方可安装。 - 上游未发版时转 hold ⛔ 不回队列;已验收产物流向另一仓由接受席立即立后续单。 - 跨座位请求即立卡进目标车道,自卡翻 `pm:blocked`;阻塞项无主由被挡席认领,在飞即等。 - 认领席跟到 MERGED,派发后的跨车道面不移卡、借隔离复核;新 spec 工作由 spec 席收口。 ## 域车道 -- 每个包恰好属于一个域,域标签 = 修复落地包的域;例外与 `Seam:` 卡见 SKILL.md 锚定规则。 +- 每个包恰好属于一个域,域标签 = 修复落地包的域,只决文件归属 ⛔ 非队列非优先级单位。 - 域由分诊读代码判定,⛔ 绝不从 issue 标题的词汇猜域;说不出修复碰哪个文件就还不可标。 -- 域到包家族的对照表住 SKILL.md,增删一个域标签必须同批改那张表。 +- 域到包家族的对照表住 SKILL.md,增删一个域标签同批改那张表;`area:*` 是功能轴,首触打。 - 域标签只由分诊席产出,例外仅在飞卡衍生 sub-issue 承父卡域;无标签的卡 ⛔ 不得认领。 - 跨域单 PR 由分诊席指定一个车道 PM 认领并申报完整文件面,在飞检查同域跨域皆跑。 - 合并队列是共享串行资源,谁发现 flake 谁修或立单,⛔ 不绕行。 @@ -106,7 +106,7 @@ - 家族派发须过五门:同缺陷同修法、同包区域、成员皆已裁、逐成员可核、点名排除清单。 - 两张以上排队卡共享热文件时,必须以五门为判据显式回答折叠还是串行。 - 取卡全序:维护者直派插队卡(出处三件)> 契约面卡(判据见 `references/lanes/spec.md`)> 标签序。 -- 标签序:`priority:p0` > `pm:blocking` > `target:` 板上项 > p1 > p2 > p3 > 无级;同级先 `Bug` 再卡龄。 +- 标签序:`priority:p0` > `pm:blocking` > 功能点位次 > `target:` 板上项 > p1 > p2 > p3 > 无级。 - 认领原子对:一次标签写入完成认领与状态对调,随后留 `Claim:` 开头的评论并重读全线程。 - 更早的他会话认领即让行并交出已诊断的一切;认领人不可达即接管,⛔ 不判死活。 - dev 自死不等于维护者中止,需显式信号;接管一条评论四件齐,只救已 push 的分支。 diff --git a/docs/NORTH-STAR.md b/docs/NORTH-STAR.md index 15ee9de826..50d7aecacd 100644 --- a/docs/NORTH-STAR.md +++ b/docs/NORTH-STAR.md @@ -10,9 +10,107 @@ **唯一的度量,那条路**:一个新的 AI 开发者(人在旁验收)从 `npm create objectstack` 出发:写元数据 → 本地跑起来、看到 → 验证响亮拒绝错的、放行对的 → 发布并装进一个环境 → 接一个 Agent(社区版走 MCP),让它在应用里完成一次真实业务操作 → 按客户一句话需求迭代一次。每周真走一遍,结果落一张 run record。第一个断掉的步骤就是当前的 P0;跑得通但结果错的是 P2。 +**路上的功能点**:平台要做出来的功能点,一行一个,按那条路的步骤排;自上而下就是顺序 —— 这张表就是路线图,改它即改优先级。每行 `轴 · 功能点(业务语言) · 清单区 · 项 id`,一个功能点从协议到运行时到前端是一整条;`docs/qa/platform-checklist/` 里的每一项都恰好属于这里的一行(未写的项标「清单项待写」)。id 不带前缀时属于它前面那个清单区,跨区的写全名。 + +**① 出发:`npm create objectstack` 起项目,写元数据** + +- devpath · 一条命令起一个项目:脚手架、装好、验证通过、控制台首屏画得出来 · cli · scaffold-first-run, scaffold-console-first-paint +- devpath · 构建是作者的第一道关:错误带位置,产物与统计出得来 · cli · build-own-contract +- devpath · 写进元数据的代码片段有边界:钩子与动作体拒绝越界写法 · cli · hook-body-extraction-gates +- studio · 不写代码建对象、字段、列表、表单与记录页 · studio-authoring · object-designer-roundtrip, view-authoring-live, record-page-roundtrip +- studio · 自定义页面:块组合、页面变量与页面级动作、三档源码 · studio-authoring · custom-page-render-and-blocks, page-variables-and-actions, custom-page-source-tiers +- studio · 先草稿后发布:发布是原子的,冲突与非法草稿当场被拒 · studio-authoring · draft-publish-lifecycle, authoring-validation-not-persisted +- studio · Studio 的判定与边界:表达式与引擎一致、权限矩阵编得动、注册表决定什么能在运行中改 · studio-authoring · expression-editors, permission-matrix-editor-ux, org-override-registry-gate +- studio · 管理员在界面里写 Markdown 文档并加到菜单(含 book),按受众发布成门户 · studio-authoring + platform-core · 清单项待写, platform-core.docs-audience-gate, platform-core.docs-portal-render + +**② 本地跑起来、看到 —— 终端用户在应用里用到的能力,都在这一步第一次被需要** + +- devpath · 一条命令把应用跑起来:健康与就绪都通、数据库选择诚实、端口与陈旧都说出来 · cli + platform-core · dev-boot-contract, platform-core.boot-health, platform-core.runtime-config-boot-read +- devpath · 种子数据原样落库,重放不多不少 · platform-core · seed-integrity, seed-mode-matrix +- devpath · 登得进去,外壳记得住:导航、自带应用、收藏与最近、主题、快捷键、返回键 · platform-core · console-login, nav-surfaces-render, builtin-apps-nav-render, shell-nav-personalization, theme-mode-persistence, keyboard-shortcut-surface, url-overlay-contract, home-admin-cluster-links, console-installability-indicators, app-management-toggle +- devpath · 平台设置在界面里改:改完真的生效、留痕、密钥只存句柄 · platform-core · settings-hub-roundtrip +- devpath · 遥测与生命周期数据按保留期回收,声明了归档的对象绝不热删 · platform-core · lifecycle-retention-sweep +- devpath · 元数据注册表对外可读,只有可写的包改得动 · platform-core · metadata-registry-serving, metadata-authoring-roundtrip +- records · 一条记录建出来、看见、改掉、删掉,也能照着再建一条 · records-forms · crud-roundtrip, record-clone-contract +- records · 每种字段都渲染得出、收得下、存得住,错的当场拒 · records-forms · field-type-matrix, field-type-constraints, field-unique-enforcement, encrypted-field-behavior +- records · 列表能干活:筛选、搜索、排序、分页、保存视图、行内编辑、导出、批量 · records-forms · list-view-capabilities, view-type-gallery, adhoc-filter-sort-builder, grid-personalization, saved-view-management, bulk-select-all-matching +- records · 看板、日历、甘特是能拖的,不是图片 · records-forms · kanban-drag-persistence, calendar-interactions, gantt-interactions +- records · 表单能用:布局、脏数据守卫、联动显示与必填、级联选项 · records-forms · form-view-gallery, form-dirty-guard, conditional-rules-header, conditional-rules-grid, cascading-options, cascading-multilevel-and-clear, field-group-visible-when +- records · 主从一起存、相关列表在服务端分页、查找框里顺手新建 · records-forms · master-detail-atomic-save, related-list-server-pagination, lookup-picker-create-new +- records · 写入规则在服务端兑现,撞车响亮、后悔得了、改过什么看得见 · records-forms · validation-rule-type-matrix, object-hook-lifecycle, delete-behavior-matrix, concurrent-edit-conflict, record-edit-undo, field-history-tracking +- records · 记录上的动作与协作:按钮在声明的位置、参数契约在派发时兑现、讨论与 @ 提醒 · records-forms · action-location-matrix, action-param-widgets, upload-guard-blocks-confirm, record-discussion-mentions +- records · 搜得到:跨字段、字段限定、权限一致、拼音、即时新鲜;全局搜索与命令面板同一条路 · search · cross-field-object-search, field-scoped-narrowing, rls-both-personas, pinyin-flag-both-sides, freshness-and-empty, console-global-search, command-palette-navigation +- access · 行级与字段级权限两边都对:受限成员只看自己的,该只读的只读、该看不见的不回给前端 · access-security · rls-both-sides, scope-depth-asymmetry, fls-mask-and-strip +- access · 增删改查逐格兑现,改完权限立刻换脸,自查接口与服务端一致 · access-security · crud-permission-matrix, permission-matrix-edit-loop, me-permissions-aggregation-parity +- access · 写入路径挡得住:只读剥离、伪造与转移 owner 被拒、默认可见度只能收紧 · access-security · write-path-guards, owd-save-gate +- access · 共享:默认基线、规则放宽、单条手工共享、建议的绑定 · access-security · owd-sharing-matrix, sharing-rules-widen, record-share-grant-revoke, sharing-rule-authoring-ui, suggested-binding-loop +- access · 匿名进不来:每个 API 家族统一拒,且先于任何资源解析;没有活跃组织也是合法状态 · access-security · anonymous-deny-surfaces, no-active-org-session-semantics +- access · 对外开的小门:公开表单与分享链接,能收回、不泄露 · access-security · public-form-intake, share-link-capability-tokens, share-link-landing-page +- access · 说得清也查得到:逐层归因的访问解释、审计浏览、记录查看留痕、平台管理员身份本身挡得住 · access-security · record-access-explain, audit-log-browser, record-view-read-audit, platform-owner-email-anchor +- identity · 登录方式按配置开关,广告出来的就是真能用的 · identity-auth · auth-method-matrix, sso-enforced-first-paint, phone-signin-surfaces +- identity · 第一次装好就有主人:零用户首跑、注册闸门、邮箱验证 · identity-auth · first-run-owner-bootstrap, self-signup-gate, email-verification-loop +- identity · 自己回得来、自己改得动:忘了密码、改资料、看得见也收得回会话 · identity-auth · self-service-password-reset, self-service-profile-password, session-list-revoke +- identity · 两步验证:开启、验证、备份码、关闭 · identity-auth · two-factor-enrollment-reveal, two-factor-verify-to-activate, two-factor-backup-codes, two-factor-disable-lifecycle +- identity · 组织、团队与业务单元,以及管理员的用户运维 · identity-auth · org-membership-team-management, teams-bu-membership, invitation-scope-gates, workspace-org-switch, admin-lifecycle-operations, identity-import-wizard +- identity · 对外身份:OAuth 授权与社交账号绑定 · identity-auth · oauth-app-consent-loop, linked-accounts-social +- workflow · 审批走得完:会签、法定人数、动态审批人、超时升级、请假代理 · approvals · per-group-signoff, quorum-m-of-n, dynamic-approver-routing, sla-escalation, ooo-delegation-reroute, approver-resolution-matrix +- workflow · 审批在界面里做:收件箱、记录页按钮、键盘流、待办计数、通知直达 · approvals · inbox-metadata-actions, viewer-gating-submitter-side, record-page-decisions, inbox-keyboard-flow, pending-count-surfaces, account-app-entry, setup-nav-entry, notification-deep-link +- workflow · 审批的每个动作都由服务端状态机兜底,邮件一键也是同一条路 · approvals · decision-action-matrix, decision-only-via-service, status-mirror-field, email-action-token-door +- workflow · 流程跑得起来:节点类型、触发类型、运行树与日志 · automation · flow-node-type-matrix, trigger-type-matrix, flow-run-step-nesting, flow-runs-page-test-trigger, trigger-status-contract +- workflow · 流程的出错、暂停与定时:try/catch、屏幕流、冷重启接着跑、汇总与时间触发、开关即刹车 · automation · flow-error-handling, screen-flow-roundtrip, durable-suspend-restart, rollup-summary-filter, time-relative-trigger, flow-toggle-kill-switch +- reports · 图表画得出来、类型齐、空数据体面、写错的键响亮;钻得下去、全局筛选重新取数 · dashboards · chart-first-paint, chart-type-matrix, empty-null-bucket-boundaries, strict-widget-rejects-stray-keys, drill-through-range, global-filters-rescope +- reports · 报表自己建、自己存、只归自己,还能按时自己发出去 · dashboards · dataset-report-authoring, saved-report-ownership, report-schedule-dispatch-delivery +- reports · 经营数字对得上:系统总览与分析立方体 · dashboards · system-overview-live-counts, cube-query +- files · 传得上、下得来,权限跟着父记录走 · attachments-storage · presigned-upload-roundtrip, download-authz-both-sides, read-inherits-parent-rls, attach-requires-parent-edit +- files · 文件的一生与表单里的文件格:提交、墓碑、回收、续传,大小与类型服务端再验一次 · attachments-storage · sys-file-status-pipeline, orphan-tombstone-reap, upload-session-abort, inline-grid-receipt-cells, field-accept-maxsize-server-enforced +- i18n · 整个应用说客户的语言,Studio 跟着切,通知也落到对的语言 · i18n · surface-matrix, studio-follows-app-locale, notification-localized-and-clears +- api · 查询契约:算子、参数、聚合、日期窗口都有已知答案 · api-backend · query-contract-matrix, aggregate-contract-matrix, date-range-preset-matrix, filter-comparand-conformance +- api · 批量与写入门逐行有结果;错误信封与路由台账:码是登记过的,挂出来的就是真在跑的 · api-backend · bulk-write-contract, batch-transactional-discovery, error-envelope-ledger, route-ledger-live-parity +- api · 自己声明的 API 端点挂成真 URL,开发者控制台里当场试得通 · api-backend · declarative-endpoint-execution, api-console-discovery-execute +- api · REST 面的构造契约:开关决定挂什么、哪些动词准过,计时只对管理员开 · api-backend · rest-crud-config-contract, rest-batch-config-contract, rest-metadata-config-contract, rest-route-generation-tombstones, api-methods-verb-gate, server-timing-admin-gated +- api · 公式引擎:标准库函数逐个给出已知答案,写错的表达式在构建时就被挡下 · api-backend · formula-stdlib-matrix, formula-gates +- api · 连上外部系统:连接器声明式落地、坏了只降级一个、鉴权与命令白名单、流程里调得到 · integration-system + automation · connector-declarative-boot, connector-degraded-recovery, connector-stdio-default-deny, connector-spec-path-no-escape, connector-descriptor-audit, connector-auth-kind-application, flow-connector-picker, automation.connector-dispatch-matrix +- api · 外部数据源接进来当自己的对象用,密钥写不进也读不出 · integration-system + cli · external-datasource-federated-read, external-schema-introspection, external-schema-drift-gate, external-schema-browser-ui, datasource-admin-lifecycle, datasource-credential-refusal-matrix, cli.datasource-introspect-codegen +- api · 往外发、往里收:webhook、定时任务、邮件模板、收件箱投递与订阅偏好、铃铛已读 · integration-system + platform-core · webhook-lifecycle, job-scheduled-run, email-template-render, notify-inbox-delivery, notification-preference-suppression, platform-core.notification-center + +**③ 验证:响亮拒绝错的,放行对的** + +- devpath · `objectstack verify` 的判词是封闭的,失败才非零退出;质量套件跑在真应用上 · cli · verify-verdict-exit-mapping, qa-suite-execution +- devpath · 体检与弃用扫描:每项都有归属,说得出处方 · cli · doctor-health-report, doctor-deprecation-scan +- devpath · lint 的严重度是封闭的,只有错误才拦;命令用错了要响亮 · cli · lint-severity-exit-contract, flag-command-error-ux +- api · 写错的元数据在作者的门口就被拒,并给处方 · api-backend · enforce-or-remove-authoring-gates, retired-def-refusal +- i18n · 翻译键写错了两个门都拒,构建门禁能变红 · i18n · strict-translation-key-rejection, build-gates-hold +- studio · 存量元数据的体检:逐条报出不合规与位置 · studio-authoring · metadata-diagnostics-sweep + +**④ 发布并装进一个环境** + +- devpath · 打成插件:清单在打包边界就被强制 · cli · plugin-manifest-build-contract +- devpath · 装进来:兼容性、命名空间、启停与卸载,REST 侧同一套生命周期 · platform-core + api-backend · manifest-install-contract, package-lifecycle-enable-disable, api-backend.package-rest-lifecycle +- devpath · 从市场装:有没有控制面都装得上,界面不说谎 · platform-core · marketplace-install-local-lifecycle, marketplace-console-honesty +- devpath · 迁移:先看计划再动手,中断了说得出下一步,老写法给得出改法 · cli + platform-core · migrate-plan-apply-json, migrate-meta-codemod, migrate-duplicates-inventory, platform-core.interrupted-migration-boot-report +- devpath · 随包发来的对象只能扩不能改,启停逐条记在激活台账上 · platform-core + access-security · packaged-object-extend-only, activation-ledger-registration-home, activation-ledger-row-contract, access-security.activation-write-operator-gate +- workflow · 随包发的流程与动作:停用要持久、被依赖时拒绝、可克隆、两道门一样严 · automation + api-backend + access-security · packaged-flow-disable-durable, packaged-flow-subflow-disable-refusal, packaged-flow-clone-contract, setup-packaged-automation-board, api-backend.packaged-action-disabled-dispatch, api-backend.action-activation-door-contract, access-security.packaged-flow-write-door-parity +- access · 装进来的包带着它声明的能力与权限集,只读的包锁住 Studio · access-security + studio-authoring · capability-declaration-lifecycle, packaged-permission-set-lifecycle, readonly-package-locks-studio, studio-authoring.packaged-automation-studio-lock +- studio · 随包发来的视图与仪表盘,是可以直接改的那一类 · studio-authoring · packaged-display-class-direct-edit + +**⑤ 接一个 Agent(社区版走 MCP),让它完成一次真实业务操作** + +- ai · agent / tool / skill 元数据写得进、列得出,退役键给处方 · ai · agent-tool-skill-metadata-roundtrip +- ai · MCP 面按文档开关:HTTP 与 stdio 两条路都失败向关 · ai · mcp-http-surface, mcp-stdio-fail-closed +- ai · Agent 能做的就是应用真能做的:动作先开口子,表达式当场校验 · ai · mcp-run-action-exposure-gate, mcp-validate-expression +- ai · 技能说明书投到 MCP 的提示上 · ai · skill-instructions-mcp-prompts +- ai · 社区版没有的就诚实说没有,界面也不摆空架子 · ai · open-edition-honest-degradation, console-ai-surface-gating +- identity · 给 Agent 一把个人密钥:只显示一次,能撤也能恢复 · identity-auth · api-key-ui-lifecycle + +**⑥ 按客户一句话需求迭代一次** + +- studio · 首跑闭环:建包 → 建对象 → 记录 → 应用 → 发布 → 终端用户,零代码零重启 · studio-authoring · first-run-loop +- records · 把客户的存量数据搬进来:编码、映射、转换、撤销与取消 · records-forms · import-wizard-encoding-and-hints, named-import-mapping, import-job-undo-cancel, import-transform-matrix +- devpath · 迭代带来的结构变化:dev 启动只自愈安全的那部分,生产不自作主张 · cli · dev-automigrate-policy + **优先级**: 1. 安全与数据完整性永远最高,不等路。 -2. 路断了、或清单上的能力断了 ⇒ P0/P1;能跑但出错 ⇒ P2;不在路上、不在清单上 ⇒ p3 或不做。 +2. 路断了、或清单上的能力断了 ⇒ P0/P1;能跑但出错 ⇒ P2;不在路上、不在清单上 ⇒ p3 或不做。定级读「路上的功能点」:改那张表即改优先级,⛔ 不逐卡改档。 3. 产品仓还有开放的 P0/P1 时,任何车道不派 p2/p3 的工具卡、契约卫生卡;解锁产品 P0/P1 的仪器卡沿链继承其优先级。 4. 因为写的是 AI、用的也是 AI:元数据既要 AI 能写——错的必须被响亮拒绝并给处方,永不静默落库;也要 AI 能用——声明了的对象、动作、agent / tool / skill 元数据在运行时兑现,MCP 面暴露的就是应用真能做的。写给 AI 的文档与 skills 说错一句,等于产品缺陷。 diff --git a/docs/qa/platform-checklist/areas/access-security.json b/docs/qa/platform-checklist/areas/access-security.json index 717400791d..895864a0fa 100644 --- a/docs/qa/platform-checklist/areas/access-security.json +++ b/docs/qa/platform-checklist/areas/access-security.json @@ -1,6 +1,7 @@ { "$comment": "Standing platform test checklist — area ledger. Hand-edited, append-only; validated by scripts/check-platform-checklist.mjs (pnpm check:platform-checklist). Authoring rules: docs/qa/platform-checklist/README.md · execution protocol: RUNNER.md.", "area": "access-security", + "axis": "access", "title": "Access, permissions, RLS/FLS, write-path guards", "items": [ { diff --git a/docs/qa/platform-checklist/areas/ai.json b/docs/qa/platform-checklist/areas/ai.json index c31bd6ba72..a87053463d 100644 --- a/docs/qa/platform-checklist/areas/ai.json +++ b/docs/qa/platform-checklist/areas/ai.json @@ -1,6 +1,7 @@ { "$comment": "Standing platform test checklist — area ledger. Hand-edited, append-only; validated by scripts/check-platform-checklist.mjs (pnpm check:platform-checklist). Authoring rules: docs/qa/platform-checklist/README.md · execution protocol: RUNNER.md. NOTE: AI is deliberately absent from the showcase app (ADR-0063 — platform-owned), so most items here carry explicit fixture requirements instead of assuming showcase seeds. BOUNDARY: the in-product agent runtime (`@objectstack/service-ai`) is Cloud/EE (cloud repo) — the OPEN framework serves the metadata surface, the MCP surface (packages/mcp), and honest 501s on /ai/** (route-ledger '* /ai/**' row); items below only assert what the open framework actually runs.", "area": "ai", + "axis": "ai", "title": "AI — agents, tools, skills, MCP", "items": [ { diff --git a/docs/qa/platform-checklist/areas/api-backend.json b/docs/qa/platform-checklist/areas/api-backend.json index de1da6a79d..81e3e69f6a 100644 --- a/docs/qa/platform-checklist/areas/api-backend.json +++ b/docs/qa/platform-checklist/areas/api-backend.json @@ -1,6 +1,7 @@ { "$comment": "Standing platform test checklist — area ledger. Hand-edited, append-only; validated by scripts/check-platform-checklist.mjs (pnpm check:platform-checklist). Authoring rules: docs/qa/platform-checklist/README.md · execution protocol: RUNNER.md.", "area": "api-backend", + "axis": "api", "title": "REST / batch / formula / build-time gates", "items": [ { diff --git a/docs/qa/platform-checklist/areas/approvals.json b/docs/qa/platform-checklist/areas/approvals.json index 2e7e6a8f1f..11c32cef70 100644 --- a/docs/qa/platform-checklist/areas/approvals.json +++ b/docs/qa/platform-checklist/areas/approvals.json @@ -1,6 +1,7 @@ { "$comment": "Standing platform test checklist — area ledger. Hand-edited, append-only; validated by scripts/check-platform-checklist.mjs (pnpm check:platform-checklist). Authoring rules: docs/qa/platform-checklist/README.md · execution protocol: RUNNER.md.", "area": "approvals", + "axis": "workflow", "title": "Approvals — quorum, per-group sign-off (会签), inbox", "items": [ { diff --git a/docs/qa/platform-checklist/areas/attachments-storage.json b/docs/qa/platform-checklist/areas/attachments-storage.json index d33d74bfd4..6d1ee43863 100644 --- a/docs/qa/platform-checklist/areas/attachments-storage.json +++ b/docs/qa/platform-checklist/areas/attachments-storage.json @@ -1,6 +1,7 @@ { "$comment": "Standing platform test checklist — area ledger. Hand-edited, append-only; validated by scripts/check-platform-checklist.mjs (pnpm check:platform-checklist). Authoring rules: docs/qa/platform-checklist/README.md · execution protocol: RUNNER.md.", "area": "attachments-storage", + "axis": "files", "title": "Attachments & storage — presigned/chunked upload, signed-URL downloads, parent-derived access, sys_file lifecycle", "fixtures": { "$comment": "AREA-LEVEL standing fixtures. An item opts in with fixtures.provisioning = { use: \"\", why: \"…\" }; the recipe is written ONCE here so four items do not carry four drifting copies of the same twenty-call sequence. Recipes are runtime-provisioned (no repo file is touched, nothing to seed, nothing to un-seed beyond the teardown line) and every call below is grounded in framework source at the cited file:line — replay them literally, and if one 4xxs, re-read the citation before assuming the recipe rotted.", diff --git a/docs/qa/platform-checklist/areas/automation.json b/docs/qa/platform-checklist/areas/automation.json index 27f5fd0203..19cc7e43b9 100644 --- a/docs/qa/platform-checklist/areas/automation.json +++ b/docs/qa/platform-checklist/areas/automation.json @@ -1,6 +1,7 @@ { "$comment": "Standing platform test checklist — area ledger. Hand-edited, append-only; validated by scripts/check-platform-checklist.mjs (pnpm check:platform-checklist). Authoring rules: docs/qa/platform-checklist/README.md · execution protocol: RUNNER.md.", "area": "automation", + "axis": "workflow", "title": "Automation — flows, triggers, roll-ups", "fixtures": { "$comment": "AREA-LEVEL standing fixtures. An item opts in with fixtures.provisioning = { use: \"\", why: \"…\" }; the recipe is written ONCE here so several items do not carry drifting copies of the same call sequence. Recipes are runtime-provisioned (no repo file is touched, nothing to seed) and every call is grounded in framework source at the cited file:line — replay them literally, and if one 4xxs, re-read the citation before assuming the recipe rotted. Shape copied from qa-scratch-authz in areas/attachments-storage.json (#7716/#7670).", diff --git a/docs/qa/platform-checklist/areas/cli.json b/docs/qa/platform-checklist/areas/cli.json index 67ca79f5cd..1dd4608414 100644 --- a/docs/qa/platform-checklist/areas/cli.json +++ b/docs/qa/platform-checklist/areas/cli.json @@ -1,6 +1,7 @@ { "$comment": "Standing platform test checklist — area ledger. Hand-edited, append-only; validated by scripts/check-platform-checklist.mjs (pnpm check:platform-checklist). Authoring rules: docs/qa/platform-checklist/README.md · execution protocol: RUNNER.md.", "area": "cli", + "axis": "devpath", "title": "CLI — os dev/build/migrate/verify/test boot, load, execution & exit-code contracts, scaffold first-run, flag/command error UX", "items": [ { diff --git a/docs/qa/platform-checklist/areas/dashboards.json b/docs/qa/platform-checklist/areas/dashboards.json index 7c402bacb0..ada007d90e 100644 --- a/docs/qa/platform-checklist/areas/dashboards.json +++ b/docs/qa/platform-checklist/areas/dashboards.json @@ -1,6 +1,7 @@ { "$comment": "Standing platform test checklist — area ledger. Hand-edited, append-only; validated by scripts/check-platform-checklist.mjs (pnpm check:platform-checklist). Authoring rules: docs/qa/platform-checklist/README.md · execution protocol: RUNNER.md.", "area": "dashboards", + "axis": "reports", "title": "Dashboards, reports, analytics", "items": [ { diff --git a/docs/qa/platform-checklist/areas/i18n.json b/docs/qa/platform-checklist/areas/i18n.json index b7f612656d..4400ea7f3c 100644 --- a/docs/qa/platform-checklist/areas/i18n.json +++ b/docs/qa/platform-checklist/areas/i18n.json @@ -1,6 +1,7 @@ { "$comment": "Standing platform test checklist — area ledger. Hand-edited, append-only; validated by scripts/check-platform-checklist.mjs (pnpm check:platform-checklist). Authoring rules: docs/qa/platform-checklist/README.md · execution protocol: RUNNER.md.", "area": "i18n", + "axis": "i18n", "title": "Internationalization", "items": [ { diff --git a/docs/qa/platform-checklist/areas/identity-auth.json b/docs/qa/platform-checklist/areas/identity-auth.json index f6baec3c23..e23fba2eea 100644 --- a/docs/qa/platform-checklist/areas/identity-auth.json +++ b/docs/qa/platform-checklist/areas/identity-auth.json @@ -1,6 +1,7 @@ { "$comment": "Standing platform test checklist — area ledger. Hand-edited, append-only; validated by scripts/check-platform-checklist.mjs (pnpm check:platform-checklist). Authoring rules: docs/qa/platform-checklist/README.md · execution protocol: RUNNER.md.", "area": "identity-auth", + "axis": "identity", "title": "Auth, login, identity", "items": [ { diff --git a/docs/qa/platform-checklist/areas/integration-system.json b/docs/qa/platform-checklist/areas/integration-system.json index e7a03c9013..8c5d0ea43d 100644 --- a/docs/qa/platform-checklist/areas/integration-system.json +++ b/docs/qa/platform-checklist/areas/integration-system.json @@ -1,6 +1,7 @@ { "$comment": "Standing platform test checklist — area ledger. Hand-edited, append-only; validated by scripts/check-platform-checklist.mjs (pnpm check:platform-checklist). Authoring rules: docs/qa/platform-checklist/README.md · execution protocol: RUNNER.md. FIXTURE MAP for this area (all in-repo, CI-deterministic): the showcase ships four declarative connectors (examples/app-showcase/src/system/connectors/index.ts — rest/openapi/mcp provider-bound instances + one enabled:false catalog descriptor), an outbound webhook (src/automation/webhooks — shipped inactive), a cron job (src/automation/jobs — showcase_health_sweep), an email template (src/system/emails — showcase_task_done_email) and two notify flows (src/automation/flows).", "area": "integration-system", + "axis": "api", "title": "Integration & system services — connectors, webhooks, jobs, email templates, notifications", "items": [ { diff --git a/docs/qa/platform-checklist/areas/platform-core.json b/docs/qa/platform-checklist/areas/platform-core.json index 54047bdf3a..0e4b222fa3 100644 --- a/docs/qa/platform-checklist/areas/platform-core.json +++ b/docs/qa/platform-checklist/areas/platform-core.json @@ -1,6 +1,7 @@ { "$comment": "Standing platform test checklist — area ledger. Hand-edited, append-only; validated by scripts/check-platform-checklist.mjs (pnpm check:platform-checklist). Authoring rules: docs/qa/platform-checklist/README.md · execution protocol: RUNNER.md.", "area": "platform-core", + "axis": "devpath", "title": "Platform core — boot, health, console shell, metadata pipeline", "items": [ { diff --git a/docs/qa/platform-checklist/areas/records-forms.json b/docs/qa/platform-checklist/areas/records-forms.json index f05cbe5fbe..611bb7d610 100644 --- a/docs/qa/platform-checklist/areas/records-forms.json +++ b/docs/qa/platform-checklist/areas/records-forms.json @@ -1,6 +1,7 @@ { "$comment": "Standing platform test checklist — area ledger. Hand-edited, append-only; validated by scripts/check-platform-checklist.mjs (pnpm check:platform-checklist). Authoring rules: docs/qa/platform-checklist/README.md · execution protocol: RUNNER.md.", "area": "records-forms", + "axis": "records", "title": "Records, lists, detail pages, forms", "fixtures": { "$comment": "AREA-LEVEL standing fixtures. An item opts in with fixtures.provisioning = { use: \"\", why: \"…\" }; the recipe is written ONCE here so several items do not carry drifting copies of the same sequence. Recipes are runtime-provisioned (no repo file is touched, nothing to seed, nothing to un-seed beyond the teardown line) and every call below is grounded in framework source at the cited file:line — replay them literally, and if one 4xxs, re-read the citation before assuming the recipe rotted.", diff --git a/docs/qa/platform-checklist/areas/search.json b/docs/qa/platform-checklist/areas/search.json index 8462ecaa0e..2e6b2e4c6e 100644 --- a/docs/qa/platform-checklist/areas/search.json +++ b/docs/qa/platform-checklist/areas/search.json @@ -1,6 +1,7 @@ { "$comment": "Standing platform test checklist — area ledger. Hand-edited, append-only; validated by scripts/check-platform-checklist.mjs (pnpm check:platform-checklist). Authoring rules: docs/qa/platform-checklist/README.md · execution protocol: RUNNER.md.", "area": "search", + "axis": "records", "title": "Record search — $search executor, field scoping, RLS composition, pinyin recall, freshness", "fixtures": { "$comment": "AREA-LEVEL standing fixtures. An item opts in with fixtures.provisioning = { use: \"\", why: \"…\" }; the recipe is written ONCE here so several items do not carry drifting copies of the same call sequence. Recipes are runtime-provisioned (no repo file is touched, nothing to seed) and every call is grounded in framework source at the cited file:line — replay them literally, and if one 4xxs, re-read the citation before assuming the recipe rotted. Shape copied from qa-scratch-authz in areas/attachments-storage.json (#7716/#7670).", diff --git a/docs/qa/platform-checklist/areas/studio-authoring.json b/docs/qa/platform-checklist/areas/studio-authoring.json index 7d734fa6cb..fe97323e93 100644 --- a/docs/qa/platform-checklist/areas/studio-authoring.json +++ b/docs/qa/platform-checklist/areas/studio-authoring.json @@ -1,6 +1,7 @@ { "$comment": "Standing platform test checklist — area ledger. Hand-edited, append-only; validated by scripts/check-platform-checklist.mjs (pnpm check:platform-checklist). Authoring rules: docs/qa/platform-checklist/README.md · execution protocol: RUNNER.md.", "area": "studio-authoring", + "axis": "studio", "title": "Studio authoring — the admin/maker loop: packages, objects, views, record pages, draft→publish", "items": [ { diff --git a/scripts/pm/ensure-pm-labels.sh b/scripts/pm/ensure-pm-labels.sh index 5fa9b65154..dcf30c754a 100644 --- a/scripts/pm/ensure-pm-labels.sh +++ b/scripts/pm/ensure-pm-labels.sh @@ -484,6 +484,58 @@ gh label create domain:devx -R objectstack-ai/objectui -c bfd4f2 -d "objectui de gh label create domain:spec -R objectstack-ai/objectui -c bfd4f2 -d "objectui spec stream: fix lands on packages/types, schema corpus or spec pin coupling — spec lane" 2>/dev/null || true gh label create domain:ui -R objectstack-ai/objectui -c bfd4f2 -d "objectui ui stream: fix lands on the published library or apps — objectui execution seat" 2>/dev/null || true +# The FEATURE AXIS — `area:*`, one per card, eleven values. It is the PLANNING +# axis: priority is judged on it, and `domain:*` beside it decides only which +# seat may claim which files. The eleven values are the North Star definition +# line (「做出来的是什么」) plus the road it measures, so the axis and the +# product definition cannot drift apart without one of them being edited. +# The eleven were put to the maintainer on the charter card and confirmed there +# (2026-09-21) with ONE amendment: the API/integration value was shortened to +# `area:api`, its customer capability (可对外的 API 与集成) unchanged. ⛔ The +# longer spelling this replaced is deliberately NOT written here — the retired +# name must not survive a `git grep` as though it were still a value. The +# maintainer's sentence is quoted verbatim on that card's ruling comment. +# +# Triage applies it at FIRST GRADING, in the same label write as `domain:*` and +# `priority:*`; a filer may pre-apply it; a tooling card carries the area it +# PROTECTS (a card that protects no area is not filed at all). ⛔ No backfill of +# the existing backlog — a card gets its area when it is next touched. +# +# Four named consumers (SKILL.md 状态模型, 「一个标签存在当且仅当有具名读者」): +# the maintainer's board view by area; triage grading, where the card's priority +# is inherited from the checklist item in that area; the parent-card grouping +# for a cross-layer feature point; and the execution seat's candidate order. +# The checklist end of that inheritance is machine-readable: every +# docs/qa/platform-checklist/areas/*.json carries a top-level `axis` naming one +# of these eleven values. +# +# TWO repos, deliberately, and not the five-repo loop above: a feature point +# spans 协议 → 运行时 → 前端, which is objectstack plus objectui. cloud is +# parked (北极星「现在不做」), objectos is the docs/site repo, and hotcrm is the +# exemplar APP — its cards are app cards, and a platform gap found there is +# filed in the platform repo, where it gets its area. Widening the loop is a +# vocabulary decision, not a maintenance edit. +# +# ⚠️ Every -d below is ≤100 characters (`check:pm-label-desc-cap`), and each +# names the CUSTOMER capability rather than the packages that implement it — +# the axis is read by the maintainer planning product, not by a seat routing +# files. One colour family (`c2e0c6` … `0e8a16` are taken; the axis uses one +# shade of its own, `d2dae2`, so an area label is recognisable at a glance in a +# label list that already carries `domain:*` in `bfd4f2`). +for R in objectstack-ai/objectstack objectstack-ai/objectui; do + gh label create area:records -R "$R" -c d2dae2 -d "Business objects, records, the views that show data, usable forms, search" 2>/dev/null || true + gh label create area:access -R "$R" -c d2dae2 -d "Permissions that actually hold — RLS/FLS, sharing model, write-path guards" 2>/dev/null || true + gh label create area:workflow -R "$R" -c d2dae2 -d "Approvals and automation — the work that runs without a person driving it" 2>/dev/null || true + gh label create area:reports -R "$R" -c d2dae2 -d "Business reporting — dashboards, reports, the numbers a manager reads" 2>/dev/null || true + gh label create area:identity -R "$R" -c d2dae2 -d "Login and identity — sign-up, sessions, organization membership, SSO" 2>/dev/null || true + gh label create area:api -R "$R" -c d2dae2 -d "The API a customer can call, and integrations — REST, connectors, webhooks, jobs" 2>/dev/null || true + gh label create area:files -R "$R" -c d2dae2 -d "Files — upload, download, signed URLs, access derived from the parent record" 2>/dev/null || true + gh label create area:i18n -R "$R" -c d2dae2 -d "The customer's own language, across UI, metadata and notifications" 2>/dev/null || true + gh label create area:studio -R "$R" -c d2dae2 -d "Changing a running app without code — authoring, publish, docs and the portal" 2>/dev/null || true + gh label create area:ai -R "$R" -c d2dae2 -d "AI-native — agent / tool / skill metadata, and the MCP surface an agent drives" 2>/dev/null || true + gh label create area:devpath -R "$R" -c d2dae2 -d "The road — create, dev, verify, publish/install, connect an agent, iterate" 2>/dev/null || true +done + # Release board — `target:` marks a release BLOCKER for that major # (SKILL.md "发版板"). Its consumer is a named query, one per backlog: # `label:target: is:open`, and all three boards reading empty IS the