Repository navigation
Commit 383c353
Part of #31155 — card 1 of 4 of the objectstack-ai/cloud#3659 ruling-A
split; this is the second per-domain port (`objectstack-automation`),
after #31223 (`objectstack-data`). The `objectstack-ui` port follows as
its own PR on the same card, so the card stays open.
Clause-②: no
Metadata-protocol: none
**Rework round 1** (contract review 6718050728, FAIL on 2ab1ee0):
`origin/main` 77a675d merged by merge commit b73f140 (no rebase, no
force-push); `main` c0068ed (#31322) had added 24 bytes to
`references/state-machines-and-approvals.md` under the first pin, so CI
measured the merge result at 5844 against a 5838 row. The row is
re-pinned AT the merged measurement after a same-file pay-down (the
three legacy "(the old …)" glosses), its comment and the tables below
carry `main`'s true base 22908; SKILL.md item 4 now states the two legs'
different consequences; the two pre-existing one-word errors the
reviewer listed in that file are corrected in the same pass.
## 维护者速读
- 改了什么:把云端私有搭建语料里「自动化」这一块、schema 表达不了的三条判断搬进公开的 `objectstack-automation`
skill:① 流程条件和写入里的下拉值一律用选项的 `value`,不用用户嘴里说的标签(写在触发条件里:流程能过校验但永远不触发;写在
`fields` / `filter` 里:运行时以 `invalid_option` 拒绝);② 用户说「早上 9 点」就写 `'0 9 *
* *'` 加 `timezone: 'Asia/Shanghai'`,不要自己换算成 UTC 裸写(裸写按 UTC
跑、也没记录你指的是哪个时区);③ 对审批结果做出反应的流程以「做出决定的那个人」的身份运行,保持 `runAs: 'user'`;只有 SLA
自动裁决和死亡运行释放这两种机器转换没有用户,要对它们也起反应的流程才声明 `runAs: 'system'`。外加 3 条 eval
用例。顺手把该 skill 一个参考文件里残留的 3 处中文注释改成英文(对外 skill
全英文),并改正该文件里两处原有小错(审批状态镜像值漏了 `returned`;一处示例条件缺 `record.` 前缀)。净增 71
行。返工第 1 轮:合并了 `main`(#31322 给同一文件加了 24 字节),体积上限按合并后实测重新钉住。
- 为什么改:执行 cloud#3659 裁决 A(一个知识源:本地开发与云端 AI 用同一套公开 skills)。第 ③
条云端原文写的是「审批服务以系统身份回写,所以下游流程必须声明 system」,对照 `main`
上的审批服务是错的(回写带着决定人的身份),本 PR 按运行时的真实行为搬入,并在卡上记了更正。
- 风险与回滚:只改文档与 eval 夹具,无运行时改动;三个文件的体积上限按实测钉住(依据 cloud#3659 A
与「先削重复,余额按实测提高」,同文件先删了重复)。回滚 = revert 本 PR。
-
先看:`skills/objectstack-automation/references/state-machines-and-approvals.md`(Approval
Best Practices 第 4 条——身份判断,对照
`packages/plugins/plugin-approvals/src/approval-service.ts` 的
`mirrorStatusField`)、`skills/objectstack-automation/references/examples-flows.md`(示例里新增的
`timezone`)、`skills/objectstack-automation/SKILL.md`(Valid-but-silently-wrong
第 4 条)。
- 两分钟验证:`node scripts/check-skills-token-ratchet.mjs`,预期全绿且
objectstack-automation 三行 headroom 0;`python3 -c "import
json;json.load(open('skills/objectstack-automation/evals/flows-triggers-approvals.json'))"`
不报错。
- 需要你做的:Tier H 受管面(`skills/**`),需要你的 APPROVED review 后由席位落地;本 PR 保持
draft。
## What changes
Four files under `skills/objectstack-automation/`, one changeset, three
token-ratchet rows.
- `SKILL.md` § Valid-but-silently-wrong — item 4: a `select` is compared
and written by its option `value`, never the label the request speaks,
in the start `condition` AND every `fields` / `filter` entry. The two
legs fail differently and the item says so: a label in the `condition`
parses, matches no row, and the flow stages clean and never fires; a
label in `fields` / `filter` fails the run at the write as
`invalid_option`
(`packages/objectql/src/validation/record-validator.ts`).
- `references/examples-flows.md` — the schedule example writes
`schedule: { type: 'cron', expression: '0 9 * * *', timezone:
'Asia/Shanghai' }` with the rule beside it: a bare expression runs in
UTC; a wall-clock hour the request names is written as said with its
IANA `timezone`, never converted to UTC by hand (nothing then records
which zone was meant). The time-relative cadence comment shows the same
shape. Same-file pay-down: the `requires: ['automation', 'triggers']` /
always-on `job` sentence, restated from SKILL.md § Prerequisite, is a
pointer.
- `references/state-machines-and-approvals.md` § Approval Best Practices
— item 4: a flow reacting to the mirrored `approvalStatusField` runs as
the person who acted (submit carries the submitter; approve / reject /
recall / send-back the decider) and stays `runAs: 'user'`; only the SLA
`escalation` auto-decision and the dead-run release carry no user, so a
flow that must react to those too declares `runAs: 'system'`. Same-file
pay-downs: the discount-approval example's four-line trigger comment (a
restatement of SKILL.md § Trigger Configuration) is one pointer line;
the three Chinese glosses (lines 145, 293, 366 on `main`) are gone; the
three legacy "(the old `entryCriteria` / `back_to_previous` /
`reject_process`)" glosses in § Branching, side-effects & rejection —
approval-process keys with no author since ADR-0019 — are gone. Two
one-word corrections of pre-existing text in the same file (the
reviewer's optional items): the `approvalStatusField` row lists
`returned` among the mirrored statuses (send-back writes it,
approval-service.ts send-back path), and the dynamic-approval example's
start condition reads `record.status == 'submitted'` like the rest of
the file.
- `evals/flows-triggers-approvals.json` — cases 17 (option value, never
label; CEL envelopes, no single-brace token), 18 (a named hour with its
zone, never a hand-converted UTC cron), 19 (an approval-outcome cascade
stays `runAs: 'user'`).
- `.changeset/31155-port-authoring-rules-automation.md` —
`@objectstack/skills` patch, `Clause-②: no`, `Metadata-protocol: none`.
- `scripts/check-skills-token-ratchet.mjs` — three rows re-pinned AT the
measurement (table below).
**Language scope (the approver's review on #31223, verbatim 「skills
对外发布的版本应该全部用英文」; the account owner's 「同意」):** every non-eval `skills/**`
file this PR touches holds 0 CJK code points at the head (Python scan
over the CJK, kana, fullwidth and CJK-punctuation blocks); eval prompt
strings keep their Chinese under exemption (a); `objectstack-i18n` is
untouched (exemption (b)). The touched reference file was one of the six
pre-existing CJK carriers the delta reviewer listed on #31223; it is
English now. The other five (`objectstack-formula/SKILL.md`,
`objectstack-ui/rules/navigation.md`,
`objectstack-ui/rules/record-page.md`, `objectstack-upgrade/SKILL.md`,
`objectui/guides/i18n.md`) are not this PR's.
### Line readings (`skills/**`, vs `origin/main` 77a675d, merged in)
| reading | before | after |
|:--|:--|:--|
| `SKILL.md` | 445 | 452 |
| `references/examples-flows.md` | 134 | 136 |
| `references/state-machines-and-approvals.md` | 399 | 404 |
| `evals/flows-triggers-approvals.json` | 298 | 355 |
| every `skills/*/SKILL.md` summed | 4517 | 4524 |
| whole shipped `skills/` tree | 20060 | 20131 |
Net **+71** lines against the dispatch's +250 budget (evals included).
### Token-ratchet rows (priced bytes; a SKILL.md's stamp line excluded)
| row | `main` 77a675d | head | ceil/4 | ceiling (was → now) |
same-file pay-down shown |
|:--|:--|:--|:--|:--|:--|
| `SKILL.md` | 25654 | 26108 (+454) | 6527 | 6426 → 6527 (+101) | none
to cut; the row comment says so |
| `references/examples-flows.md` | 5685 | 5976 (+291) | 1494 | 1436 →
1494 (+58) | the `requires` restatement |
| `references/state-machines-and-approvals.md` | 22908 (after #31322's
+24) | 23299 (+391) | 5825 | 5730 → 5825 (+95) | the trigger comment;
three Chinese glosses; three legacy "(the old …)" glosses |
All three pinned AT the measurement, headroom 0 (the reference file's
row is pinned 19 below the first round's 5838 and 19 below the
merge-result reading CI rejected, 5844). Authority: the ruling of record
that orders this text into the published skills,
objectstack-ai/cloud#3659 letter A (ruling comment 6682024726,
2026-11-06: "How to write valid, working metadata lives in the public
skills … The private corpus's rules of that kind move there"), via the
standing 2026-10-27 ruling, verbatim and untranslated: 「A:先削重复,余额按实测提高」
(ruling record 6513306068).
## No-loss mapping — the automation rows (v1 ledger 6711215678;
corrections 6711710289, 6715112987; this PR's note on the card)
Classes as in the ledger: CLOUD (orchestration / hosted-only, stays),
SPEC (restates `packages/spec`), E/R (parses clean, dead at runtime —
the spec lane, #31224), STATED (the published skill already says it),
PORT (judgment, ported here).
| private rule id | clause | class | target → this PR | regression kept
|
|:--|:--|:--|:--|:--|
| 14 | trigger on the START node; one `triggerType` string;
`record-after-write` for create-or-update; `previous` null on the create
leg; no array of trigger types; bare CEL condition; `fields` / `filter`
keys; no `recordId`; CEL value envelopes, no `{…}` tokens; `isoDate` /
`current_user` envelopes | SPEC + STATED | `automation/flow.zod.ts`
(top-level `triggerType` / `trigger` refused with the start-node
prescription; node configs `strictObject`),
`automation/flow-template-token.ts` (single-brace tokens refused at
save); SKILL.md § Trigger Types / § Trigger Configuration / § Flow
Variables / § Filter operands / § Valid-but-silently-wrong 1;
objectstack-formula § 5 (`previous` is `null` on insert) | cloud
`flow-value-envelope.test.ts` (9 cases) pins the envelope teaching — the
spec refusal and SKILL.md § Valid-but-silently-wrong 1 are its
equivalent; eval 17 now pins the envelope shape too (`dialect: 'cel'`,
no single-brace token) |
| 14 | the user speaks the label; the stored value is the option `value`
— map it in the condition AND every `fields` entry | **PORT** | SKILL.md
§ Valid-but-silently-wrong item 4 | eval 17 (`== 'lost'` must_contain;
`== '已流失'`, `status: '已流失'` must_not_contain) |
| 14 | edges connect everything (an orphan action node never runs) | E/R
| #31224 C | — |
| 14b | `timeRelative` on the start node; `offsetDays` vs `withinDays`;
`filter` INSIDE the descriptor; never a date-equality condition | SPEC +
STATED | `automation/time-relative-trigger.zod.ts`;
`references/examples-flows.md` § Time-relative triggers | cloud
`flow-value-envelope.test.ts` "rule 14b writes a time-relative flow
value the same way" — same equivalent as 14 |
| 14b | daily cadence only; a sibling `filter` beside `timeRelative`;
`runAs: 'user'` on a swept flow | E/R / already enforced | #31224 B
(cadence, sibling `filter`); `runAs` is lint `flow-runas-unscoped`
(already enforced, 6711340388); the `runAs: 'system'` sweep is STATED in
`examples-flows.md` | — |
| 14b | write the user's wall-clock hour with its `timezone`, never a
silent UTC conversion | **PORT** | `references/examples-flows.md` — the
schedule example and the time-relative cadence comment. Verified on
`main`: `system/job.zod.ts` `CronScheduleSchema.timezone` (described,
IANA-checked); `trigger-schedule/src/schedule-trigger.ts`
`normalizeSchedule` carries `timezone` onto the job (both the schedule
and the time-relative trigger call it);
`service-job/src/cron-job-adapter.ts` hands it to the cron library |
eval 18 (`timezone: 'Asia/Shanghai'`, `0 9 * * *` must_contain; `0 1 * *
*`, `UTC+8` must_not_contain) |
| 14b | clock-arming honesty (`CLOCK_TRIGGER_*` warnings), the tier's
record-driven way out | CLOUD | hosted / restriction profile | stays in
cloud |
| 14c | approval is a NODE: `approvers: [{ type, value }]`, approver
types, `behavior`; out-edges labelled `approve` / `reject`; `manager`
resolves only when the directory is filled | SPEC + STATED |
`automation/approval.zod.ts`;
`references/state-machines-and-approvals.md` (approver table, `behavior`
row, labelled edges in the example) | — |
| 14c | "the approval service writes the outcome back with a SYSTEM
write, which carries no user: a record-change flow reacting to it must
declare `runAs: 'system'`" | **PORT, corrected** — the cloud sentence
conflicts with the runtime on `main`:
`packages/plugins/plugin-approvals/src/approval-service.ts`
`mirrorStatusField` is elevated but attributed (submit passes
`submitter_id`; approve / reject / recall / send-back / revision-limit
auto-reject pass `actingUserId(context)`); only the SLA auto-decision
and the dead-run release pass `null`. Lint `flow-runas-unscoped` leaves
`record_change` undecidable by design ("caught at run time") |
`references/state-machines-and-approvals.md` § Approval Best Practices
item 4, stating what the runtime does | eval 19 (`runAs: 'user'`, the
cascade's trigger shape must_contain; an approval node or a
`sys_approval_request` read must_not_contain) |
| flow-node-types | node `type` is the engine's vocabulary; a tool-named
node = `NO_EXECUTOR` | E/R + STATED | SKILL.md § Flow Node Types + §
Valid-but-silently-wrong 3; the `test_flow` / `toggle_flow` half is
CLOUD. The E/R half (`os validate` / `os build` refusing a node `type`
outside the composed registry) is in the ledger's row but NOT among
#31224's four candidates — named on the card for the spec lane | cloud
`authoring-rules.test.ts` corpus integrity — stays in cloud |
| flow-node-tier, 14b-tier, 13-tier | the tier's vocabulary | CLOUD |
restriction profile (#31156 / cloud#3713) | stay in cloud |
| process-approval-flow (solution_design) | proactively draft the
approval flow after the blueprint; its shape pointers are 14 / 14c / 17
| CLOUD | orchestration | stays in cloud |
Coverage decision the v1 ledger left to this PR: cloud
`flow-value-envelope.test.ts` stays in cloud pointing at the moved text;
eval 17 is the automation-side equivalent of its "every envelope the
skill teaches passes clean" case (an envelope per field, no single-brace
token), beside the spec refusal at save.
**Conflicts with spec on `main`:** none in the three ported clauses. One
conflict with the runtime, resolved by porting the true statement (14c
above); the cloud corpus's own sentence is for cloud to correct (card 4
of the split rewires that corpus).
## Tests
Docs and eval fixtures only, no runtime change ⇒ no ablation owed. The
eval file parses (`json.load`), ids 1–19 contiguous; a per-case
cross-check over cases 17–19 finds no `must_not_contain` string inside
its own `expected_output`. Prerequisite build for the skill gates under
the shared verify lock: `pnpm --filter '@objectstack/lint...' build` —
`os-verify-lock: VERDICT command-exit 0 · held the lock 71s`.
## Acceptance notes
- **Cloud corpus text that is false against this repo's runtime
(carrier: cloud, card 4 cloud#3714 or a cloud card):** rule 14c's last
sentence (quoted in the table). The hosted agent today over-elevates
every approval cascade; the published skill now says what the service
does.
- **Enforce-or-remove rows not in #31224 (for the seat, not filed
here):** (i) `flow-node-types`' E/R half — a node `type` outside the
composed registry parses (open string by contract, ADR-0018) and fails
every run `NO_EXECUTOR`; the runtime audits it at boot
(`sealNodeTypeVocabulary`), `os validate` does not; (ii) the mechanical
half of rule 14's value-vs-label — a literal compared to a `select`
field in a start `condition`, or written to one in `fields` / `filter`,
that is none of the field's option `value`s; cloud's graph-lint has
`flow_condition_uses_label` / `flow_field_value_uses_label`, this repo's
lint has no equivalent. The judgment half (the request speaks the label)
is the prose ported here.
- **Pre-existing CJK on `main` in five other shipped non-i18n files**
(listed above): not this PR's; a separate card if the English-only rule
is to cover the catalog.
- Eval `must_contain` tokens `== 'lost'` and `approval_status ==
'approved'` are prompt-specific values, as `applicant_email` /
`signed_copy` / `hotcrm.custom` are in cases 6, 8 and 13; the root
catalog has no taught-token oracle (that gate scans `ui/skills` only).
## Verification
Head cited: `874185a4` (the rework commit on top of merge commit
b73f140 of `origin/main` 77a675d; the union below ran on it). Derived
with `node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` — 64 families; every exit code captured to a
file before any pipe (`COMMAND > LOG 2>&1; status=$?`); reconciled with
`--ran`.
- `✓ dispatch-gates --ran: 64 derived famil(ies) accounted for — 63 run,
1 NOT-MEASURED (1 DERIVED from a recorded exit 3)`.
- 63 families exit 0, among them: `node
scripts/check-skills-token-ratchet.mjs :: exit 0` —
`skills/objectstack-automation/SKILL.md is 6527 tokens (ceiling 6527;
headroom 0)`, `references/examples-flows.md is 1494 tokens (ceiling
1494; headroom 0)`, `references/state-machines-and-approvals.md is 5825
tokens (ceiling 5825; headroom 0)`, `evals/flows-triggers-approvals.json
is 5153 tokens — eval fixture, measured but not ratcheted`; `--self-test
:: exit 0` (`97 cases pass`); `pnpm check:role-word :: exit 0`; `pnpm
--filter @objectstack/spec run check:skill-docs :: exit 0`;
`check:skill-refs :: exit 0`; `pnpm --filter @objectstack/lint run
check:doc-formula-expressions :: exit 0`; `pnpm check:lean-entry-closure
:: exit 0`; `pnpm check:dts-closure :: exit 0`; `pnpm
check:pm-dispatch-gates :: exit 0` (detached, `tail --pid`);
`check:nul-bytes`, `check:doc-authoring`,
`check:closing-keyword-parity`, `check:skill-frame-sync`,
`check:skill-identifier-liveness`, `check:skill-compatibility`,
`check:pm-skill-id-lint` and the rest exit 0.
- NOT MEASURED locally: `pnpm check:dual-build-cjs-loads :: exit 3`
(PREREQUISITE NOT MET — needs every package's dist, a full `pnpm build`;
CI's `Lint & Repo Gates` reads it).
- Beyond the derived list, because the diff edits two `os:check` blocks
(the schedule example; the dynamic-approval flow's condition): `pnpm
--filter @objectstack/spec run check:skill-examples :: exit 0` — `285
prose examples type-check across 3 surface(s)`.
- Prerequisite builds under the shared verify lock, after the merge
(AGENTS.md §9: `packages/spec`, `lint` and `objectql` sources moved on
`main`): `pnpm --filter '@objectstack/lint...' --filter
'@objectstack/objectql...' --filter '@objectstack/client-react...'
build` — `VERDICT command-exit 0 · held the lock 232s` (round 0: 71s +
242s).
- CJK scan (Python, the blocks named above) over every non-eval file in
the three-dot diff — `SKILL.md`, `references/examples-flows.md`,
`references/state-machines-and-approvals.md`, the changeset, and the
lines this PR adds to the ratchet script: 0 lines. Eval fixture: parses,
ids 1–19 contiguous.
- Round-0 CI red (`Type Check · source gates`, job 128644219285:
`state-machines-and-approvals.md is 5844 tokens; the ratchet ceiling is
5838`) is the must-fix above; the row now reads 5825 on the merged tree.
- `test:repo` not run locally (no test file in the diff; CI `Test
Core`). Governed `skills/**` ⇒ Tier H: draft kept; landing waits for an
APPROVED review from `GOVERNED_APPROVERS`; no seat arms, queues or
readies it. CI check-runs: read by the seat at hand-over, not awaited by
the dev.
---
_Generated by [Claude
Code](https://claude.ai/code/session_012dn2AdARJtc4RgABPH7PHk)_
<!-- signed: repo:cloud#1 · os-bob · session_012dn2AdARJtc4RgABPH7PHk
-->
---------
Co-authored-by: Claude <noreply@anthropic.com>
1 parent db50231 commit 383c353
6 files changed
Lines changed: 154 additions & 23 deletions
File tree
- .changeset
- scripts
- skills/objectstack-automation
- evals
- references
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
501 | 501 | | |
502 | 502 | | |
503 | 503 | | |
504 | | - | |
| 504 | + | |
| 505 | + | |
| 506 | + | |
| 507 | + | |
| 508 | + | |
| 509 | + | |
| 510 | + | |
| 511 | + | |
| 512 | + | |
| 513 | + | |
| 514 | + | |
| 515 | + | |
| 516 | + | |
| 517 | + | |
| 518 | + | |
| 519 | + | |
505 | 520 | | |
506 | 521 | | |
507 | 522 | | |
| |||
934 | 949 | | |
935 | 950 | | |
936 | 951 | | |
937 | | - | |
| 952 | + | |
| 953 | + | |
| 954 | + | |
| 955 | + | |
| 956 | + | |
| 957 | + | |
| 958 | + | |
| 959 | + | |
| 960 | + | |
| 961 | + | |
| 962 | + | |
| 963 | + | |
| 964 | + | |
938 | 965 | | |
939 | 966 | | |
940 | 967 | | |
| |||
1026 | 1053 | | |
1027 | 1054 | | |
1028 | 1055 | | |
1029 | | - | |
| 1056 | + | |
| 1057 | + | |
| 1058 | + | |
| 1059 | + | |
| 1060 | + | |
| 1061 | + | |
| 1062 | + | |
| 1063 | + | |
| 1064 | + | |
| 1065 | + | |
| 1066 | + | |
| 1067 | + | |
| 1068 | + | |
| 1069 | + | |
| 1070 | + | |
| 1071 | + | |
| 1072 | + | |
| 1073 | + | |
| 1074 | + | |
| 1075 | + | |
| 1076 | + | |
| 1077 | + | |
| 1078 | + | |
| 1079 | + | |
1030 | 1080 | | |
1031 | 1081 | | |
1032 | 1082 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
288 | 288 | | |
289 | 289 | | |
290 | 290 | | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
291 | 298 | | |
292 | 299 | | |
293 | 300 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
293 | 293 | | |
294 | 294 | | |
295 | 295 | | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
296 | 353 | | |
297 | 354 | | |
298 | 355 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
25 | 25 | | |
26 | 26 | | |
27 | 27 | | |
28 | | - | |
| 28 | + | |
29 | 29 | | |
30 | 30 | | |
31 | | - | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
32 | 35 | | |
33 | 36 | | |
34 | 37 | | |
| |||
98 | 101 | | |
99 | 102 | | |
100 | 103 | | |
101 | | - | |
102 | | - | |
| 104 | + | |
| 105 | + | |
103 | 106 | | |
104 | 107 | | |
105 | 108 | | |
| |||
128 | 131 | | |
129 | 132 | | |
130 | 133 | | |
131 | | - | |
132 | | - | |
133 | | - | |
| 134 | + | |
| 135 | + | |
134 | 136 | | |
0 commit comments