docs(skills): teach the calendar-hours rule where a hook stamps a deadline - #16591
Merged
Conversation
…dline The data-hooks sandbox section now carries the hook-deadline rule: a deadline stamped from an hours table is calendar hours, the table is named `*_CALENDAR_HOURS` (or its camelCase), the arithmetic adds elapsed milliseconds, and wall-clock arithmetic is never labelled "business hours". Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018dxq7YqsLDMeZDZ5AzsgJX
…not one name Review point: the rule read `SLA_CALENDAR_HOURS`, a concrete table name, where the spec is a naming pattern. A published skill is copied verbatim by agents, so a non-SLA hours table would have inherited the SLA name. The pattern now leads and the concrete name is the parenthesised example. Same three lines, same +4 net. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018dxq7YqsLDMeZDZ5AzsgJX
Collaborator
Author
维护者速读(终稿 · skills 席,2026-09-07T11:4xZ)
Generated by Claude Code |
This was referenced Sep 7, 2026
os-zhuang
approved these changes
Sep 7, 2026
os-zhuang
marked this pull request as ready for review
September 7, 2026 12:07
os-zhuang
enabled auto-merge
September 7, 2026 12:07
This was referenced Sep 7, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #14483
The last outstanding teaching point of that card: the hook-deadline rule in the published
data skill's hooks reference. Teaching point 1 (the escalation row's calendar-hours clause)
landed earlier in PR #15681; this branch is point 2 and touches nothing else.
What changed
skills/objectstack-data/references/data-hooks.md— +4 lines, 0 deletions, one file.A three-line note closing the Sandbox restrictions subsection of
## Sandboxed Hook Bodies (body) — What the Sandbox ctx Can Call:It carries all four elements the card specifies for point 2: the unit (calendar hours),
the naming convention (the
*_CALENDAR_HOURSsuffix pattern, with one concrete table asthe parenthesised example), the arithmetic (
hours * 3_600_000), and the refusal to labelwall-clock arithmetic "business hours".
Review round 1 moved the naming rule from a concrete name to the pattern. A published
skill is copied verbatim by the agents that read it, so leading with
SLA_CALENDAR_HOURSwould have handed that same name to hours tables that have nothing to do with an SLA. The
pattern now leads and the concrete name is demoted to an example — same three lines, same
+4 net, no ceiling touched.
Ruling of record
Maintainer 2026-08-31, mechanism B (quoted verbatim, untranslated): 「其他同意」 — the
clock unit is part of the declaration, not ambient prose; the platform ships no
business-hours calendar; the rule is taught where an AI writes the next hours table.
The wording deliberately mirrors what the schema already says, so the two read the same:
ApprovalEscalationSchema.timeoutHoursinpackages/spec/src/automation/approval.zod.tsdescribes "Calendar (wall-clock) hours … nights, weekends and holidays count. The platform
ships no business-hours calendar", and its TSDoc spells the arithmetic
hours × 3_600_000.Placement — measured on this tree, not taken from the card
Three readings decided where the note goes:
packages/spec/src/data/hook.zod.tsdeclares nohours, deadline or calendar key at all — its only time key is
timeoutMs, themillisecond budget after which the hook run is aborted. So there is no producer-side
describethat could carry this rule and no generated_index.mdthat already statesit; a hand-authored line in this reference is the only place an author meets it. The
card's premise holds.
timeoutMsis a different concept and was rejected as the anchor. Putting abusiness-deadline rule beside the VM's abort budget invites exactly the conflation the
rule exists to prevent.
list says
Dateis available,setTimeoutis not, and any hours table must be inlinedbecause free identifiers at module scope are rejected by
objectstack build. A hookthat stamps a deadline therefore does
Datearithmetic over an inlined table — the notesits directly under that list.
Readings (governed-surface convention: whole-file and whole-package, before → after)
Tokens are the ratchet's own convention,
ceil(utf8 bytes / 4), measured from git at bothrevisions; before =
ffca0df9(branch base), after =3fcc79e1(final commit, reviewround 1 included).
data-hooks.md— tokensdata-hooks.md— linesskills/objectstack-databundle, 11 authored.md— tokensreferences/_index.mdexcluded: generator-owned, measured but not ratchetedskills/objectstack-databundle — linesSKILL.md— tokensSKILL.mdis touchedSKILL.md— linescheck:skills-token-ratchetprints the file's own verdict line:skills/objectstack-data/references/data-hooks.md is 9741 tokens (ceiling 12611; headroom 2870), and36 authored bundle file(s) within their ceilings. No ceiling was raised, andthe change is paid entirely out of existing headroom. The review-round reword cost 5 tokens
and 0 lines.
One baseline in the card does not reproduce: it cites 10183 for "all SKILL.md files", where
today's measurement over the 11 published
SKILL.mdfiles is 6858 lines / 79687 tokens.Reported as drift in the card's stated baseline; no action taken on it here.
Trade-offs, along the four axes
Only one call needed the frame: what to cut to fit three lines of prose into the +4-line
budget. The dropped clause is "the platform ships no business-hours calendar"; what stayed is
the unit, the naming rule, the arithmetic and the prohibition.
happened once in a reference app's hook body, and it happened as arithmetic, not as a
missing sentence about platform capabilities. The surviving text is the half an author
acts on while typing.
already carried by the schema
describeand by the automation skill's escalation row,where a capability question belongs. Repeating it here would have been a third copy to
keep in sync.
review round 1 sharpened exactly this axis: a suffix pattern generalises to every hours
table an agent writes, where a single fixed name would have been copied verbatim onto
tables it does not describe. A table matching
*_CALENDAR_HOURScannot be silently readas business hours by the next author or the next agent, which prose elsewhere cannot
achieve.
maintainer 2026-08-21, the ruling this ratchet enforces). Four lines were granted and four
were used; no ceiling was raised, and no wording was expanded to make room.
Two smaller calls, both measured: the note uses the file's own idiom for a prohibition
("never", bold lead-in) rather than the ⛔ marker, because this file contains zero ⛔ in 979
lines; and
3_600_000keeps the separators the schema's own TSDoc uses, so the skill textand the contract text are byte-comparable — the file had no ms-arithmetic precedent of its
own to follow.
Verification
Re-run in full on the final head
3fcc79e1after the review-round reword — not carried overfrom the first sweep.
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack→ 21 commands (byte-identical to the round-1derivation); all 21 run, all exit 0 on the first sweep this round, exit codes captured
before any pipe.
--ranreconciliation:21 derived, 21 run, 0 NOT-MEASURED, 0 UNRUN.check-skills-token-ratchetas quoted above;check:doc-authoring—
46 published skill files clean — no internal issue-id referencesand15062 customer-facing string(s) across 865 spec sources clean;check:skill-identifier-liveness,check:skill-compatibility,check:skill-frame-sync,check:nul-bytes,check:pm-governed-mergesall exit 0. Beyond the derived family:check:skill-docs(noregeneration owed),
check:pm-skill-ratchetandcheck:skill-frame-freshnessalso exit 0.node scripts/pm/check-governed-merges.mjs --test skills/objectstack-data/references/data-hooks.mdexits 3 —GOVERNED — a human merge is the review record.grep -naPover the edited file for the C0/DEL range exits 1, no match.pnpm lintis a measured narrowing, not a skip, on three pieces of evidence: (1) thepopulation comes from eslint's own config —
eslint.config.mjsmatches onlyts,tsx,mts,cts,js,jsx,mjs,cjsand contains no markdown entry at all; (2) the count comesfrom
--format jsonon the changed file — 1 result, 0 errors, 0 rules applied, the singlewarning being "File ignored because no matching configuration was supplied"; (3) the
invariance claim — the diff adds no TS/JS file and edits no eslint config, tsconfig or
source, and type-aware linting is not in play (
eslint.config.mjsstates it carries noparserOptions.projectand no typed rules), so no untouched file's verdict can move.git merge-tree --write-tree --name-onlyagainst the current
origin/main(b4abb0a9, re-fetched after the reword) is clean. Atround 1 all 21 open PRs were fetched by
refs/pull/N/headand diffed against their ownmerge bases for
skills/objectstack-data/**— zero hits, so no open PR holds this file.270145f6..3fcc79e1) — no amend, no force.维护者速读(草稿)
改了什么
发布给客户的数据技能包里,写 hook 沙盒那一节末尾加了三行规则:从小时表盖出来的截止时间是
日历小时(夜里、周末、节假日都算),表名要落在
*_CALENDAR_HOURS这个后缀模式上(
SLA_CALENDAR_HOURS只是括号里的例子),算术是加毫秒(hours * 3_600_000),并且不许把这种墙钟算术标成 "business hours"。一个文件、净增 4 行、没删任何东西、没动别的技能文本。
为什么改
这条规则的另一半(审批升级的
timeoutHours是日历小时)已经在 schema 和自动化技能包里落地了。但真实事故发生在 hook 体里 —— 参考应用把日历小时当工作小时写进了 hook 代码,而
hook 体是没有任何 schema 能管到的地方:平台的 hook 契约里根本不存在"小时"这个键。于是这条
规则只能教在"AI 下一次写小时表的那个位置",也就是这份沙盒参考文档。这是维护者 2026-08-31
裁的机制 B(消费端收敛,零契约变更)的最后一块。
风险与代价(含回滚)
风险极低:纯文档,没有代码、没有 schema、没有运行期行为变化。代价是客户上下文窗口里多了 65
个 token(该文件 9741 / 上限 12611,余量还有 2870),全部用既有余量支付,没有抬高任何棘轮
上限。回滚就是 revert 这两个 commit,不牵连任何其它文件或 PR。唯一的判断题是措辞取舍:为
了守住 +4 行预算,砍掉了"平台不发运工作日历"这半句 —— 它在 schema 的 describe 和自动化技能
包里都还在,这里不重复第三遍。
席位意见
(留空,待席位 ACCEPT 时填写)
你要做的
这是受管面(
skills/**),只能人工合并:本 PR 保持 draft、未入队、未挂 auto-merge、未提交任何 review。请审阅这三行文案是否是你要教的口径,尤其是
*_CALENDAR_HOURS这个命名模式和被砍掉的那半句;认可后由你手动合并。合并即关闭该卡(两个教学点都已落地)。