refactor: tighten LuaCATS annotations and canonicalize metadata fields (#141)

* refactor: tighten LuaCATS annotations across modules

Problem: type annotations repeated inline unions with no aliases,
used `table<string, any>` where structured types exist, and had
loose `string` where union types should be used.

Solution: add `pending.TaskStatus`, `pending.RecurMode`,
`pending.TaskExtra`, `pending.ForgeType`, `pending.ForgeState`,
`pending.ForgeAuthStatus` aliases and `pending.SyncBackend`
interface. Replace inline unions and loose types with the new
aliases in `store.lua`, `forge.lua`, `config.lua`, `diff.lua`,
`views.lua`, `parse.lua`, `init.lua`, and `oauth.lua`.

* refactor: canonicalize internal metadata field names

Problem: `pending.Metadata` used shorthand field names (`cat`, `rec`,
`rec_mode`) matching user-facing token syntax, coupling internal
representation to config. `RecurSpec.from_completion` used a boolean
where a `pending.RecurMode` alias exists. `category_syntax` was
hardcoded to `'cat'` with no config option.

Solution: rename `Metadata` fields to `category`/`recur`/`recur_mode`,
add `category_syntax` config option (default `'cat'`), rename
`ParsedEntry` fields to match, replace `RecurSpec.from_completion`
with `mode: pending.RecurMode`, and restore `[string]` indexer on
`pending.ForgeConfig` alongside explicit fields.
This commit is contained in:
Barrett Ruth 2026-03-11 12:55:36 -04:00 committed by Barrett Ruth
parent 46b5d52b60
commit 939251f629
Signed by: barrett
GPG key ID: A6C96C9349D2FC81
16 changed files with 144 additions and 80 deletions

View file

@ -2,7 +2,7 @@
---@field freq 'daily'|'weekly'|'monthly'|'yearly'
---@field interval integer
---@field byday? string[]
---@field from_completion boolean
---@field mode pending.RecurMode
---@field _raw? string
---@class pending.recur
@ -10,29 +10,29 @@ local M = {}
---@type table<string, pending.RecurSpec>
local named = {
daily = { freq = 'daily', interval = 1, from_completion = false },
daily = { freq = 'daily', interval = 1, mode = 'scheduled' },
weekdays = {
freq = 'weekly',
interval = 1,
byday = { 'MO', 'TU', 'WE', 'TH', 'FR' },
from_completion = false,
mode = 'scheduled',
},
weekly = { freq = 'weekly', interval = 1, from_completion = false },
biweekly = { freq = 'weekly', interval = 2, from_completion = false },
monthly = { freq = 'monthly', interval = 1, from_completion = false },
quarterly = { freq = 'monthly', interval = 3, from_completion = false },
yearly = { freq = 'yearly', interval = 1, from_completion = false },
annual = { freq = 'yearly', interval = 1, from_completion = false },
weekly = { freq = 'weekly', interval = 1, mode = 'scheduled' },
biweekly = { freq = 'weekly', interval = 2, mode = 'scheduled' },
monthly = { freq = 'monthly', interval = 1, mode = 'scheduled' },
quarterly = { freq = 'monthly', interval = 3, mode = 'scheduled' },
yearly = { freq = 'yearly', interval = 1, mode = 'scheduled' },
annual = { freq = 'yearly', interval = 1, mode = 'scheduled' },
}
---@param spec string
---@return pending.RecurSpec?
function M.parse(spec)
local from_completion = false
local mode = 'scheduled' ---@type pending.RecurMode
local s = spec
if s:sub(1, 1) == '!' then
from_completion = true
mode = 'completion'
s = s:sub(2)
end
@ -44,7 +44,7 @@ function M.parse(spec)
freq = base.freq,
interval = base.interval,
byday = base.byday,
from_completion = from_completion,
mode = mode,
}
end
@ -58,7 +58,7 @@ function M.parse(spec)
return {
freq = freq_map[unit],
interval = num,
from_completion = from_completion,
mode = mode,
}
end
@ -66,7 +66,7 @@ function M.parse(spec)
return {
freq = 'daily',
interval = 1,
from_completion = from_completion,
mode = mode,
_raw = s,
}
end
@ -134,7 +134,7 @@ end
---@param base_date string
---@param spec string
---@param mode 'scheduled'|'completion'
---@param mode pending.RecurMode
---@return string
function M.next_due(base_date, spec, mode)
local parsed = M.parse(spec)