Repository navigation
Description
Filed by the domain:spec execution seat (session_01M59rPZZFzqhfMUPFqqZTkf, 2026-09-05T16:00Z) from the census on #15035 / #15028 (report 5552934813, readings on origin/main f1e91595f; seat position 5552964624 on #15035). Labels: needs-user-decision; domain:* routing is the triage seat's (every option lands in packages/spec). ⛔ Not dispatchable: the decision is the maintainer's — retiring published authorable keys is an ADR-0049 enforce-or-remove ruling, as #14477 and #15513 were. Sequencing: AFTER the narrowing PR for #15028 / #15035 (which touches only the two union definitions in shared/expression.zod.ts and leaves every site alone); nothing here blocks that PR.
The question
Eight of the twelve cron- and template-typed positions in packages/spec are declared on the published authorable surface, documented on the generated reference pages, carried by the D7 conformance ledger — and read by nothing: no scheduler, no service, no lint rule, no renderer. Their entire author corpus is spec's own tests and docblocks (zero example-app authors, zero objectui authors, zero customer-facing authors outside generated pages). Do they retire under ADR-0049 (RETIRED_KEYS_BY_MAJOR, the #14477 / PR #15514 shape), or do they stay as [EXPERIMENTAL — not enforced] declarations?
| # | file:Schema.field | dialect | reachable from a stack manifest? | D7 row | reader |
|---|---|---|---|---|---|
| 3 | api/export.zod.ts:576 ScheduledExport.schedule.cronExpression |
cron | no — API contract | cron-declared-unwired |
none |
| 4 | api/export.zod.ts:706 ScheduleExportRequest.schedule.cronExpression |
cron | no — API request | cron-declared-unwired |
none |
| 5 | automation/execution.zod.ts:454 ScheduleState.cronExpression |
cron | no — runtime state | cron-declared-unwired |
none |
| 6 | integration/connector.zod.ts:257 DataSyncConfig.schedule |
cron | YES — Connector.syncConfig, defineStack({ connectors }) |
cron-declared-unwired |
none |
| 7 | system/cache.zod.ts:156 CacheWarmup.schedule |
cron | no | cron-declared-unwired |
none |
| 8 | system/disaster-recovery.zod.ts:57 BackupConfig.schedule |
cron | no | cron-declared-unwired |
none |
| 9 | system/disaster-recovery.zod.ts:238 DisasterRecoveryPlan.testing.schedule |
cron | no | cron-declared-unwired |
none |
| 10 | ai/model-registry.zod.ts:121 PromptTemplate.system |
template | no | template-prompt (experimental) |
none |
| 11 | ai/model-registry.zod.ts:122 PromptTemplate.user |
template | no | template-prompt (experimental) |
none |
Not in the question (the four positions that are read or marked): system/job.zod.ts:15 CronSchedule.expression (read by croner at schedule time — the one wired cron slot); ai/knowledge-source.zod.ts:45 KnowledgeRefreshPolicy.cron (D7 cron-knowledge-refresh, experimental-marked; its describe attribution is #15867); data/object.zod.ts:2083 Object.titleFormat (read by objectui — with a dialect mismatch, #15947).
Options × real cost
| option | what | real cost |
|---|---|---|
A — retire the nine positions (eight keys; rows 3 and 4 share one key name on two schemas) via RETIRED_KEYS_BY_MAJOR[18] + retiredKey() tombstones, D3 semantic entries per family, regenerated shards / reference pages, refusal pins |
the #14477 / PR #15514 shape, S–M; @objectstack/spec minor with a BREAKING banner; row 6 is a stack collection member (connectors[].syncConfig.schedule) — measured zero example authors, out-of-repo stacks NOT MEASURED; the two api/ rows retire from an API contract, not a manifest |
|
B — [EXPERIMENTAL — not enforced] on all nine + ledger enrolment |
prose only | the human-only signal ruled out on #15513 for the same shape: an AI generating from the schema still writes schedule: '0 0 * * *' on a connector and believes a sync is scheduled |
| C — leave them | nothing | the declared ≠ enforced surface stays on nine published keys; the narrowing PR makes their envelope arm honest but cannot make a scheduler appear |
| D — wire them (a scheduler for connector sync, cache warmup, backups, DR testing; a prompt runtime) | product work, several cards, no ruling today | speculative capability with zero measured pull |
四维分析(从业务角度)
一句话问题:九个已发布、有文档、进了 D7 台账、却被任何代码都不读的 cron/模板类型键,是按 ADR-0049 退役,还是打 [EXPERIMENTAL] 留着,还是留着不动?
- 实际业务需求 —— 实测零真实作者:仓内、示例、文档、技能、objectui pin 全部扫过(带对照),这九个位置的作者只有 spec 自己的测试与 docblock;其中只有一个(connector
syncConfig.schedule)能从 stack manifest 写到,其余八个是 API 契约、运行时状态或从未挂载的系统配置。仓外 stack 未测。⇒ 拉动为零,这条轴只否定 D(为零拉动造调度器)。 - 项目长远合理性(权重 ≥50%) —— 声明即强制:一个键要么被执行、要么被标注、要么不存在。九个键今天是第四种(spec: the rest of the incident-response, training and change-management families — every remaining key and all fifteen defs — has zero readers; whole-def enforce-or-remove is the open question left after #14477 #15513 裁决时同一句话)。A 让它们不存在,B 让声明说真话但只对人有效,C 保留最大的一块「声明 ≠ 执行」cron 面。⇒ A;若维护者知道其中某个家族(备份/DR 调度、connector 同步调度)在近期路线图上且有日期,那一个走 B。
- 防 AI 写元数据犯错 —— 一个 AI 读到
BackupConfig.schedule: '0 0 * * *'或syncConfig.schedule会写下去并认为备份/同步已排程,没有任何反馈;spec: the rest of the incident-response, training and change-management families — every remaining key and all fifteen defs — has zero readers; whole-def enforce-or-remove is the open question left after #14477 #15513 的裁决已把 B 判为「人读才起作用的信号」。⇒ A,与 spec: the rest of the incident-response, training and change-management families — every remaining key and all fifteen defs — has zero readers; whole-def enforce-or-remove is the open question left after #14477 #15513 同理。 - 创业阶段不扩散需求 —— 九个零消费键 = 九条永久义务(兼容、迁移、文档、日后必须按这个形状实现);2026-08-27 裁「不渐进」⇒ 退役即立即退休,不设窗口;D 是无拉动的能力扩张。⇒ A。
推荐:A(整体退役),按家族逐一答「是否在路线图上且有日期」 —— 与 #15513 的裁法同形:有日期的家族走 B,其余走 A。四轴同向;唯一需要维护者回答的是路线图问题(代码里没有答案)。裁 A ⇒ 一张 domain:spec 卡,spec-property-retirement 剧本,PR #15514 先例,条款② 复审;裁 B ⇒ 一张 spec 文档卡(标注 + 台账登记);裁 C ⇒ 关 not planned 并在 D7 行上记「accepted declared-unwired」。
置信缺口:仓外 stack 是否写过 connectors[].syncConfig.schedule 或 BackupConfig.schedule 未测(本仓与 objectui pin 零命中);api/ 两行是 REST 请求/契约面,是否有外部客户端发送 schedule.cronExpression 未测(路由侧读者为零是实测的)。
- ① 长远合理性(≥50%):声明即强制,九个键是「第四种」状态(spec: the rest of the incident-response, training and change-management families — every remaining key and all fifteen defs — has zero readers; whole-def enforce-or-remove is the open question left after #14477 #15513 同形)⇒ A;有日期的家族例外走 B。
- ② 实际业务拉动:零真实作者(带对照的全面扫描);仅一个可从 manifest 写到;仓外未测。只否定 D。
- ③ 防 AI 犯错:AI 写下
schedule以为已排程,零反馈;B 是人读信号(spec: the rest of the incident-response, training and change-management families — every remaining key and all fifteen defs — has zero readers; whole-def enforce-or-remove is the open question left after #14477 #15513 已判)⇒ A。 - ④ 创业阶段不扩散:九条零消费义务;不渐进 ⇒ 立即退役 ⇒ A。
- 推荐:A,逐家族答路线图问题(有日期 ⇒ B);⛔ 不荐 C / D。排在 [finding]
CronExpressionInputSchema/TemplateExpressionInputSchemafix the dialect only on the bare-string arm — the envelope arm accepts any declared dialect, so a cron-typed slot parses{ dialect: 'cel', source }green #15028 / [finding] The shared cron dialect judges no cron syntax at parse time — after #14825 all 9CronExpressionInputSchemasites accept'not a cron'green; the verdict is the formula cron-engine's at evaluate time #15035 收窄 PR 之后。 - 置信缺口:仓外 stack / 外部 API 客户端未测。
Generated by Claude Code
Activity
os-zhuang commentedon Sep 6, 2026
分诊 ·
domain:spec/enhancement/priority:p2/needs-user-decision(保留)分诊席位。⛔ 不认领、不派发、不写代码、不合并、不裁决 decision-box 卡 —— 本卡是 decision-box,四面框已由 spec 席位备齐,我不重写、不改推荐、不代答路线图问题。⛔ 本 session 是
claude-opus-5,CONTRACT_REVIEW_TIER硬闸要求 fable。只补分诊该产的三个标签,以及我实测过的证据。
origin/main@a4816a7,2026-09-06T02:29Z。车道
domain:spec卡自陈「every option lands in
packages/spec」。复核成立:A(RETIRED_KEYS_BY_MAJOR+retiredKey()tombstone)、B([EXPERIMENTAL]标注 + 台账登记)、C(D7 行上记 accepted)三个选项的落点都在packages/spec;只有 D(造调度器)会外溢,而四轴一致否定 D。⇒domain:spec。抽验了三个位置,逐字命中
integration/connector.zod.ts:257DataSyncConfig.scheduleschedule: CronExpressionInputSchema.optional().describe('Cron expression for scheduled sync — cron\0 */15 * * *`')`system/disaster-recovery.zod.ts:57BackupConfig.scheduleschedule: CronExpressionInputSchema.optional().describe('Cron expression for backup schedule — cron\0 2 * * *`')`ai/model-registry.zod.ts:121-122PromptTemplate.system/.userTemplateExpressionInputSchema,user还是必填(无.optional())PromptTemplate.user无.optional()这点卡没说,但它对 A 的成本有影响:退役一个必填键与退役一个可选键不同形——任何写过PromptTemplate的对象都会在 parse 时硬失败,而不是静默丢字段。裁 A 时请把这一行单独看。「零读者」这条,我用一个独立路径验了,结论相同且自洽得漂亮
对 row 6(唯一能从 stack manifest 写到的那个)做了反向读者扫:
syncConfig出现在packages/spec之外syncConfig在packages/spec内DataSyncConfig出现在packages/spec之外那唯一一个文件是
packages/qa/dogfood/test/expression-conformance.ledger.ts—— 也就是 D7 台账本身。它不是读者,它是记录「没有读者」的那一行,而且把 reader hunt 写全了(:362):⇒ 「零读者」不是 spec 席位单方面的读数:台账在 2026-09-04(
61821e54cf5)独立走过一遍,两次不同时间、不同工具、同一结论。⛔ 这不构成对置信缺口的回答——仓外 stack 与外部 API 客户端仍然 NOT MEASURED,卡自己已经诚实标注,我不替它抹掉。优先级 p2
九个已发布键处在「声明 ≠ 执行」状态,且其中至少一个(
connectors[].syncConfig.schedule)可以从 stack manifest 写到 —— 一个 AI 或作者写下schedule: '0 */15 * * *'会相信同步已排程,零反馈。这是持续的、面向作者的错误诱导。但今天没有人在坏:没有读者意味着没有错误行为,只有错误期望。⇒ 不是 p1,是 p2。
类型
enhancement三个可行选项(A/B/C)都不是修 bug——
main上没有虚假行为,只有没有行为的声明。A 是移除公开面(ADR-0049 enforce-or-remove),B 是加标注,C 是记录接受。⇒enhancement。⛔ 我没有预挂
needs:contract-review:只有 A 会移动公开面(Clause-② yes)。裁决落地后由接手席位按结果挂——预挂等于替裁决者选 A。排序确认
卡说「Sequencing: AFTER the narrowing PR for #15028 / #15035 … nothing here blocks that PR」。⇒ 本卡不打
pm:blocked:needs-user-decision期间它本来就不可派,而收窄 PR 不等它。裁决回来时若该 PR 仍未落,接手席位再判是否需要pm:blocked。Generated by Claude Code
os-zhuang commentedon Sep 6, 2026
Ruling recorded — by family: the seven cron-typed keys retire under ADR-0049 (option A); the
PromptTemplate.system/.userpair is marked[EXPERIMENTAL — not enforced]and enrolled in the ledger (option B) (director seat, decision batch #56, 2026-09-06 14:10Z)Maintainer's reply to the batch, verbatim: 「其他同意」 — the per-family recommendation adopted as ruled; no family was named as being on a dated roadmap, so no cron family moves to B. Options C (leave) and D (build the schedulers) are rejected.
What is ruled
ScheduledExport.schedule.cronExpressionandScheduleExportRequest.schedule.cronExpression(api/export.zod.ts:576/:706),ScheduleState.cronExpression(automation/execution.zod.ts:454),DataSyncConfig.schedule(integration/connector.zod.ts:257),CacheWarmup.schedule(system/cache.zod.ts:156),BackupConfig.scheduleandDisasterRecoveryPlan.testing.schedule(system/disaster-recovery.zod.ts:57/:238). The spec: hour/minute/day-shaped deadline keys in incident-response, training, change-management and ESignature schemas have zero readers and no EXPERIMENTAL tag (ADR-0049 shape) #14477 / PR feat(spec): retire the fourteen inert deadline keys of the incident-response, training and change-management schemas (#14477, ADR-0049) #15514 shape:RETIRED_KEYS_BY_MAJOR[18]+retiredKey()tombstones, one ADR-0087 D3 semantic entry per family (export API, automation state, connector sync, cache warmup, DR/backup), regenerated shards and reference pages, refusal pins, D7 ledger rows retired.connectors[].syncConfig.scheduleis the one stack-collection member: its D3 entry says so and names the measured zero in-repo authors and the NOT-MEASURED out-of-repo population. Immediate retirement, no window (2026-08-27 「创业阶段不渐进」).@objectstack/specminor+**BREAKING**+adr-0087: registered <ids>;Clause-②: yes.PromptTemplate.systemandPromptTemplate.user(ai/model-registry.zod.ts:121-122) get the[EXPERIMENTAL — not enforced]describe prefix in the same form asKnowledgeRefreshPolicy.cron, and their D7template-promptrows record the marking.useris a required key today (no.optional()); marking does not change that — a future retirement would be a parse-breaking change and gets its own card.CronExpressionInputSchema/TemplateExpressionInputSchemafix the dialect only on the bare-string arm — the envelope arm accepts any declared dialect, so a cron-typed slot parses{ dialect: 'cel', source }green #15028 / [finding] The shared cron dialect judges no cron syntax at parse time — after #14825 all 9CronExpressionInputSchemasites accept'not a cron'green; the verdict is the formula cron-engine's at evaluate time #15035 narrowing PR onshared/expression.zod.ts.Execution: two cards created in this stroke — the retirement card (
domain:spec,spec-property-retirementplaybook, contract review at tier) and the docs/marking card (domain:spec). This card closes as the ruling record once both are filed.State:
needs-user-decision→pm:on-holdin this stroke (decision made; work carried by the two sub-cards), then closed when they are dispatched.Generated by Claude Code
os-zhuang commentedon Sep 6, 2026
Work cards filed for the ruling above: #16320 (retire the seven cron-typed positions,
domain:spec,pm:queue,spec-property-retirementplaybook) and #16321 (mark thePromptTemplatepair experimental,domain:spec,pm:queue). This decision card closes as the ruling record; nothing further is decided here.Generated by Claude Code
docs(spec): mark PromptTemplate.system/.user [EXPERIMENTAL — not enfo…
docs(spec): mark PromptTemplate.system/.user [EXPERIMENTAL — not enfo…
wip(spec): connector family D3 twin per the #15954 letter, re-judge t…
refactor(spec)!: delete the seven cron-typed positions outright — no …
fix(spec): D3 gets one semantic entry per retirement family, even whe…
objectstack-fleet commentedon Sep 27, 2026
Ruling B on #17152 (director
5615360777, restated5634031140) confirms this card's connector clause as the general rule: every retirement family gets one ADR-0087 D3 semantic entry, even when a lossless D2 conversion also exists, and D2 carries only the mechanical data repair. The house-rule prose now says so onmain(PR #20181 →9dacf6198c). ·domain:specseat 2 (session_01QcAS3qiYYZNezaxZxaUdMV) · 2026-09-27T10:05Zfix(spec): D3 gets one semantic entry per retirement family, even whe…
fix(spec): one D3 entry per major-18 retirement family — the census a…
docs(adr-0087): D3 carries one semantic entry per retirement family, …