You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[finding] The shared cron dialect judges no cron syntax at parse time — after #14825 all 9 CronExpressionInputSchema sites accept 'not a cron' green; the verdict is the formula cron-engine's at evaluate time #15035
Recorded by the domain:spec seat (session_0174WZTU6XcFcS7g2kykC53i, seat post #6017) during the contract review of PR #15029 (#14825). Bare, for triage; the landing file is packages/spec/src/shared/expression.zod.ts (spec lane) if anything lands at all.
What
packages/spec/src/shared/expression.zod.ts lines 110-113 on origin/maina4e4d2d7 (read 2026-09-03T18:00Z):
The only parse-time refusals are an empty string, a non-string, and an envelope naming an undeclared dialect. Measured by the #14825 dev (M2, zod 4.4.3, through z.object({ cron: CronExpressionInputSchema.optional() })): '0 9 * * 1-5', the 6-field '0 0 9 * * *' and 'not a cron' all normalize to { dialect: 'cron', source }. No cron parser exists in the spec layer; the syntax verdict (5- or 6-field, or an @yearly…@reboot alias) belongs to the @objectstack/formula cron-engine when the expression is evaluated.
Sites carrying the schema: 8 positions in 7 files before #14825 (api/export.zod.ts, automation/execution.zod.ts, integration/connector.zod.ts, system/cache, system/disaster-recovery twice, system/job, per the #14825 dev's count) plus ai/knowledge-source.zod.tsrefresh.cron once PR #15029 lands — 9 in total.
Why it matters
#14825's headline symptom — "an AI author writes a cron, os validate accepts anything, and the failure surfaces at the scheduler" — is closed for that one field by making its describe promise exactly what the parse enforces, not by refusing bad syntax. The symptom stays true at every cron-typed site, by the shared dialect's design. PR #15029's pin file deliberately asserts the non-refusal so that a later change to the shared dialect surfaces there; this card is where that change, if any, gets decided.
Not a decision — three shapes for triage
(a) A parse-time syntax refinement in spec, on the bare-string arm and on source when dialect === 'cron': a 5- or 6-field grammar plus the @ aliases. Spec cannot import formula (dependency direction), so the grammar would be restated; all 9 sites' pins and describes move in the same PR (Clause ② — accept-set narrowing on 9 published keys).
Recorded by the
domain:specseat (session_0174WZTU6XcFcS7g2kykC53i, seat post #6017) during the contract review of PR #15029 (#14825). Bare, for triage; the landing file ispackages/spec/src/shared/expression.zod.ts(spec lane) if anything lands at all.What
packages/spec/src/shared/expression.zod.tslines 110-113 onorigin/maina4e4d2d7(read 2026-09-03T18:00Z):The only parse-time refusals are an empty string, a non-string, and an envelope naming an undeclared dialect. Measured by the #14825 dev (M2, zod 4.4.3, through
z.object({ cron: CronExpressionInputSchema.optional() })):'0 9 * * 1-5', the 6-field'0 0 9 * * *'and'not a cron'all normalize to{ dialect: 'cron', source }. No cron parser exists in the spec layer; the syntax verdict (5- or 6-field, or an@yearly…@rebootalias) belongs to the@objectstack/formulacron-engine when the expression is evaluated.Sites carrying the schema: 8 positions in 7 files before #14825 (
api/export.zod.ts,automation/execution.zod.ts,integration/connector.zod.ts,system/cache,system/disaster-recoverytwice,system/job, per the #14825 dev's count) plusai/knowledge-source.zod.tsrefresh.crononce PR #15029 lands — 9 in total.Why it matters
#14825's headline symptom — "an AI author writes a cron,
os validateaccepts anything, and the failure surfaces at the scheduler" — is closed for that one field by making its describe promise exactly what the parse enforces, not by refusing bad syntax. The symptom stays true at every cron-typed site, by the shared dialect's design. PR #15029's pin file deliberately asserts the non-refusal so that a later change to the shared dialect surfaces there; this card is where that change, if any, gets decided.Not a decision — three shapes for triage
sourcewhendialect === 'cron': a 5- or 6-field grammar plus the@aliases. Spec cannot import formula (dependency direction), so the grammar would be restated; all 9 sites' pins and describes move in the same PR (Clause ② — accept-set narrowing on 9 published keys).os validateor the lint run the cron-engine's parse on cron-typed positions — which needs the D7 ledger to know where they are (ADR-0058 D7 expression conformance ledger discovers onlyExpressionInputSchema/SettingsVisibilityInputSchemapositions — the 8CronExpressionInputSchemaand 3TemplateExpressionInputSchemasites sit outside the ratchet, unclassified #15027).Verified
search_issues): zero results for parse-time cron syntax validation; positive control returned [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, ADR-0058 D7 expression conformance ledger discovers onlyExpressionInputSchema/SettingsVisibilityInputSchemapositions — the 8CronExpressionInputSchemaand 3TemplateExpressionInputSchemasites sit outside the ratchet, unclassified #15027 and [finding]KnowledgeSourceSchema.cronis documented as a 5-field cron expression but typedz.string()— the spec's ownCronExpressionInputSchemais not used, so'not a cron'parses green #14825, so the zero is a reading, not a failure mode.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 (the envelope arm accepts any declared dialect), ADR-0058 D7 expression conformance ledger discovers onlyExpressionInputSchema/SettingsVisibilityInputSchemapositions — the 8CronExpressionInputSchemaand 3TemplateExpressionInputSchemasites sit outside the ratchet, unclassified #15027 (the D7 conformance ledger's discovery excludes Cron/Template-typed sites).Refs: #14825 · PR #15029 · #15028 · #15027 · ADR-0049 · ADR-0058.