Repository navigation
Upgrade to @objectstack 9.7.0 + fix time-relative flows (#1874) & metric rollups (#1870) - #62
Merged
Merged
Conversation
…1874); upgrade @objectstack 9.7.0 #1874 — nine flows used a `record_change` trigger with `daysFromNow`/`daysAgo` date criteria. A record-change trigger only fires on row mutation, so an untouched record sails past its threshold and the flow (almost) never fires on the right day. Each is now a daily `schedule` that QUERIES the population: - contracts: renewal_alert, renewal_draft, obligation_overdue - helpdesk: auto_close_resolved - compliance: evidence_auto_expire, evidence_expiring - expense: expense_approval_overdue - procurement: po_overdue - hr: document_expiring_soon Idempotency is declarative (charter-friendly, zero new fields): lifecycle flows transition status (bulk update self-guards); overdue flows scope the query to the open status; discrete T-N alerts hit one calendar day via the daily schedule; renewal_draft guards on the existing-draft title. Date equality replaced with range (`<=`/`<`) where it fits; `$in`/`==` kept for discrete-day tiers (with a date/timestamp caveat noted inline). Also: bump all @objectstack deps 9.5.1 -> 9.7.0, and unpin the `minimumReleaseAgeExclude` entries (just-published 9.7.0 was age-gated). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…_rollup flow (#1870)
`publication_rollup` used `type:'script'` nodes with an `aggregations` config to
sum child metrics — but the automation engine has no aggregate node, so script
nodes only run a named callable. The aggregations never ran: publication/piece
`total_*` were silently never updated (they only looked right in seed data). The
9.7.0 build validator now flags this ("script node declares neither actionType
nor function").
A hook can't fix it either — a cross-object rollup write from a hook is
unsupported in the standalone QuickJS runtime (the repo's own note in
content/src/hooks/index.ts). The correct mechanism is the engine's native
`Field.summary` roll-up, recomputed server-side on child insert/update/delete:
- content_publication.total_{views,clicks,signups,revenue} = sum over content_metric
- content_publication.last_metric_at = max(content_metric.period_end)
- content_piece.total_* = sum over content_publication.total_*
Removed the broken flow + its registration; refreshed the now-stale notes in
hooks/index.ts and record_metric_snapshot.action.ts.
Also fixes a second pre-existing bug the 9.7.0 validator caught: the lifecycle
flow used `ISCHANGED(status)` (no such CEL function) — replaced with the
`status != previous.status` change check.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ity (#1874) Field.date stores a full timestamp (verified: '2026-07-15T17:24:56.533Z'), so `end_date == daysFromNow(N)` compares two independently-computed timestamps and never matches — the discrete-tier alerts (renewal_alert, evidence_expiring, document_expiring_soon) would have silently never fired. Replace exact equality / $in with abutting one-day windows [daysFromNow(N), daysFromNow(N+1)) via $gte/$lt (+ $or for multi-tier): the windows tile the timeline so each record falls in exactly one — fires once per tier, still idempotent, no guard field. Range date-filtering against a cel timestamp is engine-verified. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
os-zhuang
added a commit
that referenced
this pull request
Jun 16, 2026
* chore(deps): upgrade @objectstack to 9.8.0 Bumps all @objectstack/* deps 9.7.0 → 9.8.0 (CEL stdlib catalog alignment + date-equality/phantom-aggregation flow lints). Validated: all 9 template stacks `objectstack build` clean on 9.8.0 with zero new lint warnings (the #62 discrete-tier range conversions stay clean under the new filter lint). Also adds @objectstack/setup, /studio, /trigger-api, /trigger-record-change, /trigger-schedule to `minimumReleaseAgeExclude` — they were missing from the first-party bypass list and tripped the release-age gate on local resolution. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(content,todo): drop pruned `colorFormat` knob (9.8.0 spec) 9.8.0 pruned dead per-type display knobs from FieldInput (ADR-0049 enforce-or- remove): `color`'s `colorFormat`/`allowAlpha`/`presetColors` had no runtime reader and renderers ignored them. `Field.color({ colorFormat: 'hex' })` no longer type-checks. Remove it — Field.color stores a hex string regardless. (Caught by the Verify typecheck job, which `objectstack build` doesn't run.) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.
Upgrades the template suite to @objectstack 9.7.0 and fixes the runtime-correctness issues the new build-time validators surfaced.
#1874 — time-relative flows were on the wrong trigger
Nine flows used a
record_changetrigger withdaysFromNow/daysAgodate criteria. A record-change trigger only fires when the row is mutated, so an untouched record sails past its threshold and the flow (almost) never fires on the right day. Each is now a dailyschedulethat QUERIES the population:renewal_alert,renewal_draft,obligation_overdue(contracts);auto_close_resolved(helpdesk);evidence_auto_expire,evidence_expiring(compliance);expense_approval_overdue(expense);po_overdue(procurement);document_expiring_soon(hr).Idempotency is declarative — zero new fields (charter-friendly): lifecycle flows transition status (bulk update self-guards); overdue flows scope the query to the open status; discrete T-N alerts hit one calendar day via the daily schedule;
renewal_draftguards on an existing-draft title check. Date equality (==) is replaced with range (<=/<) where it fits;$in/==kept for discrete-day tiers, with a date/timestamp-matching caveat noted inline for engine verification.#1870 —
publication_rollupaggregations never ranpublication_rollupusedtype:'script'nodes with anaggregationsconfig, but the automation engine has no aggregate node — script nodes only run a named callable, so the sums never executed andtotal_*were silently never updated. A hook can't fix it (cross-object rollup write is unsupported in the standalone QuickJS runtime — the repo's own note). Replaced with nativeField.summaryroll-ups (recomputed server-side on child change) oncontent_publicationandcontent_piece; removed the broken flow. Also fixedISCHANGED(status)(no such CEL function) →status != previous.statusin the lifecycle flow.Upgrade mechanics
@objectstack/*deps9.5.1 → 9.7.0.minimumReleaseAgeExcludeentries unpinned from@9.0.0(the just-published 9.7.0 was age-gated by the supply-chain policy).Verification
objectstack build), including the new ADR-0032 expression validation.Follow-ups (noted, not blocking)
$in/==date matching (end_date == daysFromNow(N)on adatefield vs atimestamp) should be confirmed against the engine's date coercion; widen to a one-day range if too strict.content/CHARTER.md's "no cron in spec v6" line is stale (trigger-schedule ships in 9.x; project templates already use cron) — worth reconciling.🤖 Generated with Claude Code