Skip to content

Commit ad7975f

Browse files
committed
Merge remote-tracking branch 'origin/main' into claude/project-thread-8hqiya
2 parents 2d1b522 + d0a1361 commit ad7975f

57 files changed

Lines changed: 2009 additions & 426 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
---
2+
'@objectstack/spec': minor
3+
'@objectstack/lint': minor
4+
'@objectstack/cli': minor
5+
---
6+
7+
feat(spec,lint): a bulk action's `confirmText` is a `template` slot over `count` and the action's params
8+
9+
Clause-②: yes (widening)
10+
Metadata-protocol: semantic
11+
12+
- **Before.** `bulkActionDefs[].confirmText` was a plain `z.string()` that declared no hole. A sentence such as `'Update tier on {{count}} account(s) to {{tier}}?'` parsed, nothing judged its holes, and the console showed them as literal text.
13+
- **Now.** `confirmText` is an ADR-0032 `template` slot (Decisions 2–3). A bare string is shorthand for `{ dialect: 'template', source }`, and the envelope form is accepted too. Holes are `{{ path }}` and `{{ path | formatter[:arg] }}`, with formatters from the template engine's whitelist and no logic inside a hole. They read a closed scope, and `bulkConfirmTemplateRoots(def)` (`@objectstack/spec/ui`) declares its roots: `count` (`BULK_CONFIRM_COUNT_ROOT`, the number of records the run covers) and each of the def's params by `name`. The roots are written bare: `{{ tier }}`, never `{{ params.tier }}`. That matches how the flow text slots spell their roots and how shipped sentences already spell them, and `count` wins over a param of that name. A param hole renders the param's display value: the chosen option's `label` (labels joined with `', '` for a multi-value param), the picked record's display name for a lookup or user param, and the entered value otherwise, so number, date and currency values take a formatter.
14+
- **Parsed shape.** A parsed `confirmText` is now the `{ dialect: 'template', source }` envelope rather than a string, as `titleFormat` and a notify node's `title` already are. A reader of the parsed or served def takes the text from `source` (`templateSlotSource` in `@objectstack/spec/automation` reads both forms). A stored sentence with no hole parses as before, its text unchanged.
15+
- **Judged by the one template judge.** `objectstack validate`, `objectstack compile` and the runtime publish gate (now also on `view` writes, and on an object's own `listViews` at an object write) judge each bulk `confirmText` through `closedScopeTemplateRefusal`. That is the closed-scope entry of the judge the flow text slots use (`automation/flow-text-slot-template.ts`). A hole over an unbound root and a single-brace `{x}` token are named, the latter with its `{{ }}` spelling. A text carrying neither is then compiled as a template, which names a hole holding logic or an unknown formatter.
16+
- **A warning, not a refusal.** Each of those texts parsed while `confirmText` was a plain string, so refusing it is a narrowing that no ADR-0087 conversion carries. This release ships every finding above as a **warning**: an advisory at the publish gate, never a refusal, so no command's exit code changes. A blank `confirmText` (`''`) still parses, and the doors warn on it.
17+
- **`os i18n extract`.** A bulk `confirmText` written as the envelope is seeded exactly as the bare string: the extractor reads the slot's text through `templateSlotSource`, so the envelope form no longer records as an absent key with nothing to translate.
18+
- **Served translations.** The catalog overlay on a served view or an object's `listViews` compares a bulk `confirmText` with its packaged base by the slot's text, whichever form either side holds: an unchanged envelope still takes the catalog's sentence, and an edited one keeps the authored sentence.
19+
- **Unchanged.** The `confirm` / `confirmmessage` near-misses still name `confirmText`. Every other bulk-def key, the default confirm sentence and the flow text slots' verdicts are unchanged.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
'@objectstack/plugin-approvals': patch
3+
---
4+
5+
fix: a new out-of-office delegation opens with the Delegator already set to the signed-in user, and the field's help says why no one else can be chosen
6+
7+
Clause-②: no
8+
Metadata-protocol: none
9+
10+
The Delegator of `sys_approval_delegation` (Setup → Delegations) only ever offers the signed-in user, because the delegation write guard admits nobody else. The field still opened empty, and a search for a colleague answered "No options found" with no reason.
11+
12+
- `delegator_id` now declares `defaultValue: 'current_user'`, the spec's runtime token for a `sys_user` lookup, so the one admissible value is filled in from the start. The write guard is unchanged and stays the enforcement.
13+
- The field's help now reads: "The user going out of office. You can delegate only your own approvals, so this is always you: it starts as you and offers no one else." The `es-ES`, `ja-JP` and `zh-CN` bundles carry the translated text.

‎.claude/agents/os-dev.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,6 @@ model: opus
125125
- objectui 把 typecheck 拼作 `type-check`(连字符);核对输出里确实回显了脚本名。
126126
- 浏览器验证:Chromium 已预装,`PLAYWRIGHT_BROWSERS_PATH` 指向 `/opt/pw-browsers`。
127127
- launch 传 `executablePath: '/opt/pw-browsers/chromium'`;⛔ 永不跑 `playwright install`。
128-
- `cdn.playwright.dev` 的 403 不是没有浏览器的证据:下载被拦不证明产物缺席,先找产物。
129128

130129
## 本地验证范围 —— 本地只跑定向门禁,全农场归 CI
131130

@@ -278,7 +277,7 @@ model: opus
278277
- 命令同 CI:按 ① 建闭包,锁下 `pnpm --filter @objectstack/dogfood test`;⛔ 无 `OS_TEST_SHARD`、无路径。
279278
- 红 = 本改动的后果(陈旧 fixture)同 PR 修,余照报;⛔ 永不跳过或收窄;计数记 `dogfood_battery`。
280279
- 认领的 `Clause-②:`、`Metadata-protocol:` 两行照抄进 PR 正文行首;无则零写,⛔ 不自造。
281-
- 两行同抄进每个 changeset 正文行首,`Check Changeset` 读:有 kind 即 `minor`,`none` 即 `patch`。
280+
- 两行同抄进 changeset 正文行首;`Check Changeset` 读 PR 正文:kind 即 `minor`,`none` 即 `patch`。
282281
- ⛔ 永不 `Fixes` 一张还在决策箱的卡:合并会静默关掉它,而收件箱过滤只读 open。
283282
- ⛔ 不写否定式的关单句,它照样关掉点名的卡:解析器无视否定,只匹配关键词 + `#<n>`。
284283
- 关键词是 `fix/fixes/fixed/close/closes/closed` 与 `resolve/resolves/resolved`;让它们远离其它卡号。
@@ -321,6 +320,7 @@ model: opus
321320

322321
- 全文 ⛔ 不出现 HTML 注释:sanitizer 落库后吃短尖括号片段,连反引号里的也吃。
323322
- 被吃掉标记的评论对 PM 扫描不可见;HTML 注释形不是等价写法,是坏写法。
323+
- 例外:harness 自写的 PR 正文首行归属注释原样留、只报;`Fixes #<n>` 紧随其后;dev 自写仍禁。
324324
- 凡要上 GitHub 的文本,尖括号形状片段一律改占位词拼写(`FIELD`、`IDENT.MEMBER` 一类)。
325325
- 各派发模式(`mode:subagent`、`mode:cloud`、`mode:thread`)下 GitHub 都是报告的权威源。
326326
- 写完读回那条评论到尾部:只认首行标记保不住正文,sanitizer 可从首个 tag 形片段吃到尾。

‎.claude/skills/pm-dispatch/SKILL.md‎

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ PM 的工作是循环:选卡 → 认领 → 派发 → 收集 → 复核 → 报
5454
| `<domain>`(如 `spec`、`skills`) | 以该 `domain:*` 车道的执行座位身份运行 | — |
5555
| `epic:#<n>` | 以父单 #n 的 epic PM 身份运行(见 `references/seat-lifecycle.md` 〈Epic 子树车道〉) | — |
5656
| `director` | 以项目总监席身份运行(人工召唤;三职与章程见 `references/lanes/director.md`) | — |
57+
| `coordinator` | 以项目协调者身份运行(项目会话:开席位线程与卡线程、跨车道调度;接口见 `references/coordinator.md`) | — |
5758
| `label:<name>` | backlog 过滤标签;`label:all` = 全部 open 未认领 | `pm:queue` |
5859
| `repo:<owner/name>` | 扫哪个仓的 backlog(单 issue 的落地仓看它自己的 `repo:*` 标签) | `objectstack-ai/objectstack` |
5960
| `batch:<n>` | 席位同时在飞的子代理总上限,按 `Agent` 调用、`create_session` 与卡线程计:dev、复核、普查皆计,⛔ 只读不豁免 | 默认 `3`;`n` 的维护者天花板 `5` |
@@ -158,16 +159,15 @@ PM 的工作是循环:选卡 → 认领 → 派发 → 收集 → 复核 → 报
158159

159160
| 标签 | 包家族 |
160161
|:--|:--|
161-
| `domain:engine` | `packages/objectql`、`packages/core`、`packages/formula`(CEL / `matches-filter` / RLS 谓词求值)、`plugin-pinyin-search`;`packages/metadata*`、`packages/platform-objects`;`packages/drivers/driver-*`;退役标签 `domain:engine-core` / `domain:metadata` / `domain:drivers` 只退出流通,GitHub 标签对象保留 |
162-
| `domain:services` | `packages/services/*`、`packages/connectors/*`、`packages/triggers/*`、`plugin-approvals`、`plugin-webhooks`、`plugin-email`、`plugin-reports`、`embedder-openai`、`knowledge-*`;`plugin-auth`、`plugin-security`、`plugin-sharing`、`plugin-audit`;退役标签 `domain:identity` 同上只退流通 |
163-
| `domain:devx` | `sdui-parser`、`content/docs/**`、`apps/docs`、`docs/qa/**`、`.githooks/`、`docker/README.md`、`examples/**` 仅测试基建面;`packages/lint`、`scripts/`(门禁类)、`.github/workflows/`(接线)三者按锚定规则例外归 `domain:spec`,门禁按 SUBJECT:governed 面归 skills,代码/文档质量归本域 |
162+
| `domain:server` | 服务端:引擎 + 服务插件 + CLI/运行时;`objectql core formula metadata* platform-objects drivers/* services/* connectors/* triggers/* plugin-* embedder-openai knowledge-* cli runtime verify types rest mcp observability client* cloud-connection create-objectstack adapters/*`;详见 `references/lanes/server.md` |
163+
| `domain:devx` | `sdui-parser`、`packages/qa`、`content/docs`、`apps/docs`、`docs/qa`、`.githooks`、`docker/README.md`、`examples/**` 仅测试基建面;`packages/lint`、`scripts`(门禁类)、`.github/workflows`(接线)三者按锚定规则归 `domain:spec`,门禁按 SUBJECT:governed 面归 skills,代码/文档质量归本域 |
164164
| `domain:skills` | governed 面全量(含本文件;统一定义见「governed 面统一定义」行);非门禁的 `scripts/pm/**`(PM 循环工具);governed 面的治理执行文件:`.github/CODEOWNERS` + SUBJECT 是 governed 面本身的门禁/审计(现为 `scripts/pm/check-governed-merges.mjs`) |
165165
| `domain:spec` | `packages/spec` 整包:schema 形状、`contracts/**`、退役行为半边、strictness 台账;describe/JSDoc/墓碑散文/错误 guidance 与 alias 表;`packages/spec/scripts/**`、`packages/spec/docs/**` 及按锚定规则的例外归本域的工具链(域边界枚举与席内分派见 `references/lanes/spec.md`) |
166-
| `domain:cli` | `packages/cli`、`runtime`、`verify`、`packages/qa`、`types`、`packages/rest`、`packages/mcp`、`packages/observability`、`packages/client*`、`cloud-connection`、`create-objectstack`、`packages/adapters/*`、`plugin-hono-server`、`plugin-dev` |
167166
| `domain:cloud` | 云服务旅程,停放(加 `status:parked`,sweep 免扫)待 cloud PM 迁移,本仓不派 |
168167
| (无固定归属,按落点分诊) | `packages/apps/*`、`packages/console`(dist 由脚本生成 ⛔ 不手改;UI 缺陷走 `repo:objectui`)、`examples/*`(归它演练的子系统)、`docs/audits/**` |
169168

170169
- 表未覆盖的包首次分诊时归类并走 PR 更新本表;新增或退役 `domain:*` 必须同批改本表。
170+
- 退役 `domain:*` 只退流通,对象保留;`domain:engine`/`domain:services`/`domain:cli` 读作 `domain:server`。
171171
- `domain:*` 只由分诊席产出,例外一:在飞卡衍生 sub-issue 承父卡域;无标签的卡 ⛔ 不得认领。
172172
- 例外二:立卡人自贴而车道合上表、正文齐立卡门三件 ⇒ 执行席直接认领,分诊事后抽查。
173173
- 跨域例外路径:拆不动的跨域单 PR 由分诊席指定一个车道 PM 认领,认领评论申报文件面。
@@ -272,7 +272,6 @@ PM 的工作是循环:选卡 → 认领 → 派发 → 收集 → 复核 → 报
272272
- 每问必带推荐项,被 Skip 或长挂即转卡通道,⛔ 不重弹。
273273
- 推送维护者:受管 PR 待批合、决策卡待字、发版、仅其可解之阻 ⇒ 另发 `PushNotification`。
274274
- 一行 ≤200 字,先写动作与编号;每项恰一次,例行进展、刚问刚答与在场即见的不推。
275-
- 项目总监席:维护者在所在仓召唤 `/pm-dispatch director`;⛔ 无 Routine/cron;未回字 = 不在 = 停。
276275
- 总监席档位由维护者按项目人工定,每场记入摘要台账;⛔ 无档位硬门、无免档整理态。
277276
- 总监席是唯一呈裁席:决策箱只经本席呈维护者人工裁;⛔ 无代裁无自裁无子代理。
278277

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# 项目协调者(Project Coordinator)
2+
3+
项目会话里开席位线程与卡线程、跨车道调度的那一席读本文。
4+
它不是 `domain:*` 席:不坐座位贴、不认领卡;席位线程照 SKILL.md 与 `execution-duties.md` 跑循环。
5+
项目指令只写「按仓库规则执行;管 X、Y 车道」;规则住本仓,⛔ 不在项目指令里转贴。
6+
本文只写 coordinator 与席位线程之间的接口,七节各注明读者。
7+
8+
## 一、车道归属登记在座位贴(coordinator 开席位线程前读;席位线程坐席时读)
9+
10+
- 项目管哪些车道只由项目指令声明;每条车道开一个席位线程,坐该车道空着的座位贴。
11+
- 席位线程在贴的说明段写「由 X 账户的项目负责」;贴协议与互斥照 `seat-lifecycle.md`。
12+
- 一条车道恒归一个项目:车道任一座位贴 🟢 标着另一项目 ⇒ 车道已有主,⛔ 不坐别席。
13+
- 仲裁者是座位贴,⛔ 不是项目记忆;另一项目在飞卡由其席跟完,其收班简报在即可坐。
14+
15+
## 二、跨车道取卡(coordinator 每次唤醒读)
16+
17+
- 取卡面 = 本项目各车道 open 的 `priority:p1`/`priority:p2` 卡;候选判据照 `execution-duties.md`。
18+
- 每张卡交其车道的席位线程;车道无席位线程而座位贴空着 ⇒ 先开席位线程再交卡。
19+
- 维护者 ⛔ 不逐卡点名车道:车道读卡的 `domain:*`;S/M 分流见 `dispatch-runbook.md` 卡线程节。
20+
21+
## 三、全项目一个上限,p1 先(coordinator 调度读;席位交候选时读)
22+
23+
- 卡线程上限全项目一个数,由维护者按项目言明;未言明取各席 `batch` 之和。
24+
- 席位随时交候选:卡号、优先级、派发令文件、建议 effort;⛔ 不等自己的槽位。
25+
- coordinator 排队开线程:p1 先于 p2,同级先到先开;满即排队,线程交回或 PR 合入即释放。
26+
- 槽位只算在建的线程:等人(授权批准、决策卡)或等席位复核的卡线程不占槽。
27+
- S 卡的席内子代理只计该席 `batch`,不计本上限。
28+
29+
## 四、effort 与档位按难度(coordinator 开线程时读;席位请线程时读)
30+
31+
- 档位与 effort 的定法住 `execution-duties.md` 派发节:档位引 `dispatch-gates --tier`,effort 按卡难度。
32+
- 改技能(协议语义面)的卡恒契约复审档 `CONTRACT_REVIEW_TIER`;⛔ 不抄模型名。
33+
- 席位请线程附维护者原话,coordinator 开线程那一笔同设 model 与 effort(`dispatch-runbook.md`)。
34+
35+
## 五、卡线程的 `needs_decision`(coordinator 收到时读;席位写分析时读)
36+
37+
- 规则一处:`lanes/director.md` 与 `dispatch-runbook.md` 卡线程节;本文只指不抄。
38+
- 席位写四维分析加推荐,卡并入决裁批次由维护者人工裁;⛔ 无裁决线程、无代裁。
39+
- 等裁的卡线程不占槽(见第三节);裁决记录 = 卡上裁决评论,⛔ 不落项目文件或记忆。
40+
41+
## 六、额度压力(coordinator 每次开线程前读)
42+
43+
- 账号用量墙将近(墙信号与重置读法见 `seat-lifecycle.md`)⇒ 停开新卡线程,在飞的跑完。
44+
- 向维护者说一次即可,⛔ 不逐线程重复;墙过后照常。
45+
46+
## 七、语言与汇报(coordinator 与席位线程皆读)
47+
48+
- 项目内对维护者用维护者的语言;GitHub 内容英文,照 SKILL.md 全体座位不变量。
49+
- 只在结果、阻塞或待裁决时向维护者汇报,与席位同规;例行进展进线程清单。

‎.claude/skills/pm-dispatch/references/dispatch-runbook.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@
133133
- 披露纪律卡(私密细节不得离开席位会话)也留席内,认领写明;卡线程照计 `batch`。
134134
- 项目的 coordinator 跨席位统一调度卡线程;每席一个线程跑 PM 循环,卡线程即 dev。
135135
- 席位随时把候选卡交 coordinator,附优先级、派发令文件与建议 effort,⛔ 不等自己的槽位。
136-
- coordinator 按优先级开线程,p1 先;全项目上限 = 各席 `batch` 之和,满即排队。
136+
- coordinator 按优先级开线程,p1 先;全项目上限由维护者按项目定(`coordinator.md`),满即排队。
137137
- 卡线程交回或其 PR 合入,席位当即告知 coordinator 释放槽位。
138138
- 请 coordinator 开线程附维护者原话消息:它只凭维护者明言设线程的 model 与 effort。
139139
- 席位留认领文本、派发令、契约复核、ACCEPT 与落地;线程实施、开 draft PR、驱动 CI。

‎.claude/skills/pm-dispatch/references/lanes/cli.md‎

Lines changed: 0 additions & 29 deletions
This file was deleted.

‎.claude/skills/pm-dispatch/references/lanes/engine.md‎

Lines changed: 0 additions & 32 deletions
This file was deleted.

0 commit comments

Comments
 (0)