Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 18 additions & 2 deletions scripts/check-skills-token-ratchet.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -628,7 +628,17 @@ export const CEILINGS = new Map([

// objectstack-query
['skills/objectstack-query/rules/aggregation.md', 2357],
['skills/objectstack-query/rules/filters.md', 2149],
// 2149 -> 2482: the now-anchored comparand `{ $now: true, addDays }` — the
// shape, the one example (overdue by each record's own grace days, the
// offset column holding negative days), where it is accepted (the six scalar
// comparisons on a date / datetime field) and what is refused — which the
// file did not teach, so an author reached for a stored formula field and a
// hook. +334 tokens on a landed 2148, 1 absorbed by headroom, ceiling +333.
// Nothing duplicated in the file to cut first (measured: no passage of the
// file restates another). Maintainer ruling 2026-10-27 on the decision card
// 「skills 修复卡的教学和 eval 都撞 token 天花板,怎么付?」, tap A, verbatim and
// untranslated: 「A:先削重复,余额按实测提高」.
['skills/objectstack-query/rules/filters.md', 2482],
['skills/objectstack-query/rules/pagination.md', 1382],

// objectstack-automation
Expand Down Expand Up @@ -803,7 +813,13 @@ export const CEILINGS = new Map([
// ceiling +247, pinned AT the measurement.
// ceil($(wc -c < skills/objectstack-platform/evals/config-plugins-ops.json) / 4) == ceil(5831 / 4)
['skills/objectstack-platform/evals/config-plugins-ops.json', 1458],
['skills/objectstack-query/evals/filters-pagination-search.json', 955],
// 955 -> 1175: one regression case for the now-anchored comparand (the
// overdue-by-grace-days prompt) — expected `{ $now: true, addDays: { $field:
// 'grace_days_offset' } }` as the whole comparand of `$lt`, and NO stored
// formula field or `subDays`. +220 tokens, zero headroom to absorb any of
// it, ceiling +220; nothing duplicated in the file to cut first. Same ruling
// as the `rules/filters.md` row above (2026-10-27, tap A: 「A:先削重复,余额按实测提高」).
['skills/objectstack-query/evals/filters-pagination-search.json', 1175],
// 1505 -> 1789 (#26295): two eval prompts — list grouping with `orderBy`, and the copy hole
// + `onSuccess` pair — +284 tokens in the file's shape; fixtures, nothing to delete, the
// whole addition raised and pinned AT the measurement. Maintainer ruling 2026-10-27 (Warren, decision card 「skills 修复卡的教学和 eval 都撞 token 天花板,怎么付?」,
Expand Down
6 changes: 4 additions & 2 deletions skills/objectstack-query/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ procedure and the full tombstone register are **objectstack-upgrade**.

## Quick Reference — Detailed Rules

- **[Filters](./rules/filters.md)** — all operators, logical combinations, filtering by a related record, date macros and session tokens
- **[Filters](./rules/filters.md)** — all operators, logical combinations, filtering by a related record, now-anchored comparands, date macros and session tokens
- **[Aggregation](./rules/aggregation.md)** — groupBy, date bucketing, functions, `having`, per-measure `filter`
- **[Pagination](./rules/pagination.md)** — offset vs keyset, best practices, performance

Expand Down Expand Up @@ -195,7 +195,9 @@ the two-step route past them: **[filter rules → Relation Filters](./rules/filt
### Cross-field comparisons

`{ $field: '...' }` compares two columns of the same row, in a **comparison**
position only — see **[filter rules → Field References](./rules/filters.md)**.
position only; `{ $now: true, addDays: OFFSET }` is the instant the query runs
at, shifted by whole days a number field of the record holds — see **[filter
rules → Field References / Now-Anchored Comparands](./rules/filters.md)**.

## Sorting

Expand Down
10 changes: 10 additions & 0 deletions skills/objectstack-query/evals/filters-pagination-search.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,16 @@
"must_contain": ["context", "isSystem: true", "limit: 1"],
"must_not_contain": []
}
},
{
"id": 6,
"prompt": "Find tasks that are overdue by each record's own grace period: `due_at` is a datetime and `grace_days_offset` is a number field holding the grace period as negative days.",
"expected_output": "`engine.find('task', { where: { due_at: { $lt: { $now: true, addDays: { $field: 'grace_days_offset' } } } } })` — the now-anchored comparand: `$now: true` is the instant the query runs at, `addDays` reads the signed whole-day offset off the same record (`-N` is N days ago). Not a stored formula field plus a hook, not `{N_days_ago}` (a literal N only), not `{ $field: 'due_at', addDays: ... }` (that compares two columns, never now).",
"files": [],
"assertions": {
"must_contain": ["$now: true", "addDays", "$field: 'grace_days_offset'", "$lt"],
"must_not_contain": ["subDays", "type: 'formula'"]
}
}
]
}
26 changes: 26 additions & 0 deletions skills/objectstack-query/rules/filters.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,32 @@ Legal in a **comparison** position only. As an `$in` / `$nin` member or a
`$between` endpoint it is refused at parse — no evaluation path resolves a
reference there.

## Now-Anchored Comparands

> ✅ **Enforced.** `{ $now: true, addDays: OFFSET }` is the instant the query
> runs at, shifted by whole days — legal exactly where a `{ $field }` reference
> is: the whole comparand of `$eq` / `$ne` / `$gt` / `$gte` / `$lt` / `$lte` on
> a `date` or `datetime` field. The engine pins `$now` to ONE instant per query.

```typescript
// ✅ Overdue by each record's own grace period: due_at < now + grace_days_offset,
// the number field holding the grace period as NEGATIVE days
where: {
due_at: { $lt: { $now: true, addDays: { $field: 'grace_days_offset' } } }
}
```

`addDays` is **required** and always ADDED: an integer of any sign (`-30`
is thirty days ago keeping the time of day, where `{30_days_ago}` names a
calendar day; for the bare instant write `{now}`), or a `{ $field }` naming
a **number** field of the same record (NULL counts as zero days). The filter
cannot negate a positive `grace_days` column: store the signed offset. Refused
with `INVALID_FILTER` / 400: an anchor without `addDays`, a fractional or
string offset, any extra key (there is no `subDays`), a target that is not
`date` / `datetime`, and any `$in` / `$nin` / `$between` position; SQL
push-down also refuses a dotted or non-number offset field. The filter alone
answers it — not a stored formula field plus a hook.

## Relation Filters

A condition on a related record's fields beneath a relation field (`lookup`,
Expand Down
Loading