docs(spec): built-ins on longer cycles (sub-project 2)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
a246da1db7
commit
abf3dc8a55
@@ -0,0 +1,136 @@
|
||||
# Built-ins on longer cycles — design
|
||||
|
||||
Sub-project 2 of the owner's "usual repeatable events" request. Sub-project 1 (weekly and monthly
|
||||
built-ins, per-item tracking) is in the [built-in routines spec](2026-10-14-built-in-routines-design.md),
|
||||
whose § Scope item 2 holds the in-game readings this design starts from.
|
||||
|
||||
## Problem
|
||||
|
||||
Many endgame modes and reward pools run on a cycle that is neither a week nor a month: Star Rail's
|
||||
three endgame modes every six weeks, ZZZ's Shiyu Defense and Deadly Assault every two weeks, Wuthering
|
||||
Waves' Tower of Adversity every 28 days, NTE's Beyond the Rails and Tycoon Incentive Fund every 14
|
||||
days. A period today is `{ unit: "week" }` or `{ unit: "month" }` (`src/shared/period.ts`), so none
|
||||
of them can be a built-in, and a reader cannot set one up as their own task either.
|
||||
|
||||
## Decisions
|
||||
|
||||
Approved by the owner in conversation on 2026-10-16.
|
||||
|
||||
1. **A third period kind: every N days from a dated start.**
|
||||
`{ unit: "cycle", days: 2–366, from: "YYYY-MM-DD" }`, where `from` is a game-day key on which a
|
||||
cycle began. `periodOf` finds the cycle holding today as `from + k·days` for the whole number
|
||||
`k` that puts today inside it — before `from` as well as after, so an anchor need not be the
|
||||
first cycle ever. It works on day keys like the other two, so each game's per-server reset
|
||||
carries over unchanged: a Monday anchor rolls at Monday's reset on every server.
|
||||
2. **Readers get it too** (owner chose "Built-ins + form"). *Add a task* gains a third choice,
|
||||
**Every N days**, with the length and a start date. *Make it mine* already copies a built-in's
|
||||
period, so the form must be able to show and edit one anyway.
|
||||
3. **A cycle can follow another server's clock — built-ins only.** `Routine` gains
|
||||
`clock?: Region` (code only, never stored, like `pulls`). When set, the item's day key, its reset
|
||||
countdown and its catch-up days are cut on that server's reset instead of the reader's. Beyond
|
||||
the Rails uses `clock: "asia"`: the owner, on Europe, read it ending Wednesday 21:00 UTC, which is
|
||||
Asia's Thursday 05:00 UTC+8 reset, and GameWith's route tables end at 04:59 UTC+8. America is
|
||||
unverified — TODO.md holds the check. *Make it mine* drops `clock`, since a reader's task has no
|
||||
such field: a copied Beyond the Rails rolls on the reader's own reset, about six hours later on
|
||||
Europe. Giving reader tasks a clock is not worth a stored field for one entry.
|
||||
4. **Tick once unless a figure is stated.** An endgame mode with no single fixed target (Pure
|
||||
Fiction, Memory of Chaos, Apocalyptic Shadow, Shiyu Defense, Deadly Assault, Tower of
|
||||
Adversity, Beyond the Rails) is `measure: { kind: "days", required: 1 }`, as Spiral Abyss is
|
||||
(sub-project 1, decision 2). Stars would rest on our reading of a target that changes.
|
||||
5. **The Tycoon Incentive Fund ships with the base cap and a note** (owner chose "Base + note").
|
||||
1,000,000 fons is the figure the game's guide and allthings.how state; the real cap is higher
|
||||
for most players (Puka Membership Program), so the note says so and points at *Make it mine*.
|
||||
6. **Its own switch.** New pref `showCycleTasks`, on by default and normalised like
|
||||
`showWeeklyTasks` (an absent value reads as on). Offered in *What you see* and the strip's Edit
|
||||
panel only once a cycle task exists, like the other two. The settings group keeps growing; a
|
||||
rework with mockups is in TODO.md (owner, 2026-10-16).
|
||||
7. **Star Rail's Divergent Universe / Currency Wars points are weekly, not a cycle.** Research
|
||||
found the shared pool weekly since 4.2 (Fandom *Version/4.2*: "will restore its weekly
|
||||
rotation"; *Simulated Universe*: "reset every week on Monday at 4:00"). The two pages still
|
||||
saying "every two weeks" are left over from 3.7. So it ships as an ordinary weekly built-in,
|
||||
with the owner's 18,000 cap (in game, 2026-10-14).
|
||||
8. **Fixed lengths only.** Whimpering Wastes ("the last Monday of each month" in one source,
|
||||
"about 26–28 days" in another), Infinity Nikki's Pinnacle Contest (the 1st and 16th of each
|
||||
month) and Merit Arena (no page states it) are not every-N-days and are not shipped; see
|
||||
§ Not shipped.
|
||||
9. **Entries wait on the owner's in-game check**, as in sub-project 1: the entry commit is last on
|
||||
its branch and the branch is not merged until the owner has confirmed § Entries, game by game.
|
||||
|
||||
## Shape and surfaces
|
||||
|
||||
- `src/shared/period.ts` — the `cycle` member of `PeriodSchema`; `periodOf` for it.
|
||||
- `src/shared/goal.ts` — `GoalStatus.scope` gains `"cycle"`. Long forms read "this cycle" /
|
||||
"done this cycle". The chip's short count, which is `1/1 wk` for a week, becomes `1/1 · 9d` for
|
||||
a cycle — the days left in it (`open`), since "cy" means nothing.
|
||||
- `src/shared/task.ts` — `taskStatus` takes an optional `clock`; `taskCaption` reads "every 14
|
||||
days from 16 Oct 2026".
|
||||
- `src/shared/routines.ts` — `clock`, the entries; `mineFrom` unchanged (it already picks fields).
|
||||
- `src/client/components/Dailies.tsx` — `cadence` gains `"cycle"`; an item carries its `clock`
|
||||
for its day key, countdown and catch-up; the lower row's heading names the periods it holds
|
||||
("This week", "This week & month", "This week, month & cycle", …) instead of always "This week
|
||||
& month"; the header tally and the footer count cycles as a third bucket; Catch up says "Last
|
||||
cycle:".
|
||||
- `src/client/components/TaskForm.tsx` — the third choice: a length in days (2–366) and a start
|
||||
date (a plain date input, read as the game's day key). "Days needed" is capped at the cycle
|
||||
length and 31, the measure's own bound.
|
||||
- `src/client/state/usePrefs.ts`, `Controls.tsx`, `EditPanel.tsx`, `App.tsx` — `showCycleTasks`.
|
||||
|
||||
**Stored shape.** `gacha-tracker:v1:tasks` records may now hold `period.unit: "cycle"`, and
|
||||
`gacha-tracker:v1:prefs` gains `showCycleTasks`. Nothing existing is migrated or reinterpreted.
|
||||
An older cached bundle reading a cycle task fails `TaskSchema` and skips it on display; `useTasks`
|
||||
never deletes what it cannot parse, so the task returns when the bundle updates. Ticks stay in
|
||||
`daily` under the task id and numbers in `amounts` under the cycle's start key, as for any period.
|
||||
Reviewed by the schema-guardian agent before merge.
|
||||
|
||||
## Entries
|
||||
|
||||
Anchors are the first game-day of a cycle, from the owner's in-game end dates (built-in routines
|
||||
spec § Scope item 2). All `checked: 2026-10-16`.
|
||||
|
||||
| id | Period | Measure | Source (`asOf`) |
|
||||
|---|---|---|---|
|
||||
| `routine:hsr:pure-fiction` | cycle 42, from 2026-10-19 | tick once | honkai-star-rail.fandom.com/wiki/Interastral_Peace_Guide/Treasures_Lightward (2026-08-15): "each update every six weeks … spaced two weeks apart" |
|
||||
| `routine:hsr:memory-of-chaos` | cycle 42, from 2026-11-02 | tick once | same |
|
||||
| `routine:hsr:apocalyptic-shadow` | cycle 42, from 2026-11-16 | tick once | same |
|
||||
| `routine:hsr:points` | week, Monday | 18,000 points | honkai-star-rail.fandom.com/wiki/Version/4.2 (2026-09-07); the cap is the owner's, in game 2026-10-14 |
|
||||
| `routine:zzz:shiyu-defense` | cycle 14, from 2026-10-16 | tick once | zenless-zone-zero.fandom.com/wiki/Shiyu_Defense/Critical_Node (2026-01-02): "Every 14 days at 04:00" |
|
||||
| `routine:zzz:deadly-assault` | cycle 14, from 2026-10-23 | tick once | zenless-zone-zero.fandom.com/wiki/Deadly_Assault (2026-07-31): "refresh every two weeks" |
|
||||
| `routine:wuwa:tower-of-adversity` | cycle 28, from 2026-11-09 | tick once | gamemarket.gg Tower of Adversity guide (2026-08-25): "a cycle of roughly 28 days" |
|
||||
| `routine:nte:beyond-the-rails` | cycle 14, from 2026-10-22, `clock: "asia"` | tick once | gamewith.net/nte/74216 (2026-08-13): "updated every 14 days" |
|
||||
| `routine:nte:tycoon-fund` | cycle 14, from 2026-10-26 | 1,000,000 fons | allthings.how Tycoon Encouragement Fund (2026-08-15): "1,000,000 Fons per two-week period" |
|
||||
|
||||
The modes' order agrees with the wiki: modes that *update* Apocalyptic Shadow → Pure Fiction →
|
||||
Memory of Chaos, two weeks apart, also *end* in that order, and the owner's ends run PF 19 Oct,
|
||||
MoC 2 Nov, AS 16 Nov. Shiyu's page also says "every 15 days" in one place; the Friday dates the
|
||||
owner read a week apart rule that out. Tower of Adversity's "roughly" goes in its note.
|
||||
|
||||
**Owner checks before merge:** the three Star Rail modes as one tick per cycle; the 18,000 cap still
|
||||
rolling each Monday; Shiyu Defense's new cycle reading about 14 days; Tower of Adversity at about
|
||||
24 days.
|
||||
|
||||
## Not shipped
|
||||
|
||||
| Game | Item | Why |
|
||||
|---|---|---|
|
||||
| Wuwa | Whimpering Wastes (Respawning Waters) | Not a fixed length: gurugamer (2025-09-04) "the last Monday of each month", lootbar (2025-12-26) "roughly 4 weeks (about 26–28 days)" |
|
||||
| Nikki | Pinnacle Contest | The 1st and 16th of each month (infinity-nikki.fandom.com/wiki/Mira_Crown, 2025-12-08) — a half-month, not every N days |
|
||||
| Nikki | Merit Arena | No page states its cycle (Fandom *Mira Crown Merit Arena*, 2026-07-09, says only that arenas "open sequentially") |
|
||||
|
||||
## Testing
|
||||
|
||||
- `period.test.ts`: a cycle's start and days on the anchor, inside, on the last day, the day after,
|
||||
and before the anchor; lengths 2 and 366.
|
||||
- `task.test.ts`: `taskStatus` for a cycle, with and without `clock` — the Beyond the Rails case at
|
||||
Wednesday 20:59 and 21:01 UTC for a Europe reader.
|
||||
- `goal.test.ts`: the cycle's labels and short count.
|
||||
- `routines.test.ts`: the existing per-entry checks cover the new entries; `clock` only on cycles.
|
||||
- `Dailies.test.tsx`: the row heading by cadence, the third tally bucket, a clocked item's day key.
|
||||
- `TaskForm.test.tsx`: the third choice round-trips, and its bounds.
|
||||
- `usePrefs.test.ts`: `showCycleTasks` absent reads as on.
|
||||
- Browser check on a fresh port at phone width: a cycle chip, the heading, the form.
|
||||
|
||||
## Docs
|
||||
|
||||
`docs/DATA-MODEL.md` (the period shape and the new pref), `docs/PRD.md` F17 and the tasks section,
|
||||
TODO.md (sub-project 2 done; Whimpering Wastes and the half-month as follow-ups), changelog entries
|
||||
in a follow-up commit.
|
||||
Reference in New Issue
Block a user