things-api 0.16.0 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/deputy/VERSION +1 -0
- package/deputy/helpers-Info.plist +23 -0
- package/deputy/prebuilt/Things API Helper.app/Contents/CodeResources +0 -0
- package/deputy/prebuilt/Things API Helper.app/Contents/Helpers/things-reader.app/Contents/Info.plist +20 -0
- package/deputy/prebuilt/Things API Helper.app/Contents/Helpers/things-reader.app/Contents/MacOS/things-reader +0 -0
- package/deputy/prebuilt/Things API Helper.app/Contents/Helpers/things-reader.app/Contents/_CodeSignature/CodeResources +115 -0
- package/deputy/prebuilt/Things API Helper.app/Contents/Info.plist +23 -0
- package/deputy/prebuilt/Things API Helper.app/Contents/MacOS/things-deputy +0 -0
- package/deputy/prebuilt/Things API Helper.app/Contents/_CodeSignature/CodeResources +125 -0
- package/deputy/reader/Info.plist +20 -0
- package/deputy/reader/entitlements.plist +15 -0
- package/deputy/reader/main.swift +491 -0
- package/deputy/src/main.swift +133 -0
- package/deputy/src/osascript.swift +102 -0
- package/deputy/src/server.swift +350 -0
- package/deputy/src/sqlite.swift +121 -0
- package/dist/cli/commands/doctor.js +55 -2
- package/dist/cli/commands/doctor.js.map +1 -1
- package/dist/cli/commands/helpers.d.ts +17 -0
- package/dist/cli/commands/helpers.js +148 -0
- package/dist/cli/commands/helpers.js.map +1 -0
- package/dist/cli/commands/op-result.d.ts +15 -0
- package/dist/cli/commands/op-result.js +39 -0
- package/dist/cli/commands/op-result.js.map +1 -0
- package/dist/cli/commands/repeat-flags.d.ts +3 -3
- package/dist/cli/commands/repeat-flags.js +90 -33
- package/dist/cli/commands/repeat-flags.js.map +1 -1
- package/dist/cli/commands/writes.js +79 -6
- package/dist/cli/commands/writes.js.map +1 -1
- package/dist/cli/help.js +13 -2
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/helpers-check.d.ts +10 -0
- package/dist/cli/helpers-check.js +59 -0
- package/dist/cli/helpers-check.js.map +1 -0
- package/dist/cli/interrupt.d.ts +42 -0
- package/dist/cli/interrupt.js +105 -0
- package/dist/cli/interrupt.js.map +1 -0
- package/dist/cli/main.js +27 -1
- package/dist/cli/main.js.map +1 -1
- package/dist/client.js +19 -2
- package/dist/client.js.map +1 -1
- package/dist/config.d.ts +70 -0
- package/dist/config.js +25 -1
- package/dist/config.js.map +1 -1
- package/dist/contracts.d.ts +9 -2
- package/dist/contracts.js +1 -1
- package/dist/contracts.js.map +1 -1
- package/dist/db/baselines/db-v26.js +8 -4
- package/dist/db/baselines/db-v26.js.map +1 -1
- package/dist/db/baselines/db-v27.d.ts +42 -0
- package/dist/db/baselines/db-v27.js +47 -0
- package/dist/db/baselines/db-v27.js.map +1 -0
- package/dist/db/baselines/index.js +2 -1
- package/dist/db/baselines/index.js.map +1 -1
- package/dist/db/locate.d.ts +4 -1
- package/dist/db/locate.js +3 -1
- package/dist/db/locate.js.map +1 -1
- package/dist/db/schema.d.ts +1 -1
- package/dist/db/schema.js +9 -0
- package/dist/db/schema.js.map +1 -1
- package/dist/deputy/bridge-worker.d.ts +1 -0
- package/dist/deputy/bridge-worker.js +79 -0
- package/dist/deputy/bridge-worker.js.map +1 -0
- package/dist/deputy/bridge.d.ts +14 -0
- package/dist/deputy/bridge.js +70 -0
- package/dist/deputy/bridge.js.map +1 -0
- package/dist/deputy/client.d.ts +19 -0
- package/dist/deputy/client.js +104 -0
- package/dist/deputy/client.js.map +1 -0
- package/dist/deputy/db-facade.d.ts +18 -0
- package/dist/deputy/db-facade.js +71 -0
- package/dist/deputy/db-facade.js.map +1 -0
- package/dist/deputy/files.d.ts +1 -0
- package/dist/deputy/files.js +16 -0
- package/dist/deputy/files.js.map +1 -0
- package/dist/deputy/install.d.ts +105 -0
- package/dist/deputy/install.js +467 -0
- package/dist/deputy/install.js.map +1 -0
- package/dist/deputy/notice.d.ts +6 -0
- package/dist/deputy/notice.js +28 -0
- package/dist/deputy/notice.js.map +1 -0
- package/dist/deputy/notices.d.ts +31 -0
- package/dist/deputy/notices.js +94 -0
- package/dist/deputy/notices.js.map +1 -0
- package/dist/deputy/osa.d.ts +21 -0
- package/dist/deputy/osa.js +72 -0
- package/dist/deputy/osa.js.map +1 -0
- package/dist/deputy/protocol.d.ts +86 -0
- package/dist/deputy/protocol.js +106 -0
- package/dist/deputy/protocol.js.map +1 -0
- package/dist/deputy/routing.d.ts +63 -0
- package/dist/deputy/routing.js +338 -0
- package/dist/deputy/routing.js.map +1 -0
- package/dist/deputy/shortcuts-exec.d.ts +10 -0
- package/dist/deputy/shortcuts-exec.js +50 -0
- package/dist/deputy/shortcuts-exec.js.map +1 -0
- package/dist/diagnose.d.ts +43 -1
- package/dist/diagnose.js +64 -2
- package/dist/diagnose.js.map +1 -1
- package/dist/index.d.ts +16 -2
- package/dist/index.js +17 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.js +25 -7
- package/dist/mcp/server.js.map +1 -1
- package/dist/model/mappers.d.ts +12 -3
- package/dist/model/mappers.js +6 -1
- package/dist/model/mappers.js.map +1 -1
- package/dist/model/occurrences.d.ts +14 -1
- package/dist/model/occurrences.js +20 -4
- package/dist/model/occurrences.js.map +1 -1
- package/dist/model/recurrence.d.ts +64 -9
- package/dist/model/recurrence.js +94 -19
- package/dist/model/recurrence.js.map +1 -1
- package/dist/model/template-projection.d.ts +26 -0
- package/dist/model/template-projection.js +113 -0
- package/dist/model/template-projection.js.map +1 -0
- package/dist/op-result.d.ts +46 -0
- package/dist/op-result.js +156 -0
- package/dist/op-result.js.map +1 -0
- package/dist/paths.d.ts +8 -0
- package/dist/paths.js +10 -0
- package/dist/paths.js.map +1 -1
- package/dist/read/detail.js +7 -1
- package/dist/read/detail.js.map +1 -1
- package/dist/read/queries.js +8 -1
- package/dist/read/queries.js.map +1 -1
- package/dist/read/views.d.ts +6 -4
- package/dist/read/views.js +60 -18
- package/dist/read/views.js.map +1 -1
- package/dist/sync-health.js +8 -3
- package/dist/sync-health.js.map +1 -1
- package/dist/trace/tracer.d.ts +87 -0
- package/dist/trace/tracer.js +167 -0
- package/dist/trace/tracer.js.map +1 -0
- package/dist/write/accessibility-probe.js +4 -2
- package/dist/write/accessibility-probe.js.map +1 -1
- package/dist/write/automation-probe.js +5 -1
- package/dist/write/automation-probe.js.map +1 -1
- package/dist/write/availability.js +7 -3
- package/dist/write/availability.js.map +1 -1
- package/dist/write/clear-reminder.js +24 -21
- package/dist/write/clear-reminder.js.map +1 -1
- package/dist/write/commands.js +95 -45
- package/dist/write/commands.js.map +1 -1
- package/dist/write/completion-context.d.ts +57 -0
- package/dist/write/completion-context.js +49 -0
- package/dist/write/completion-context.js.map +1 -0
- package/dist/write/experimental.d.ts +19 -0
- package/dist/write/experimental.js +50 -0
- package/dist/write/experimental.js.map +1 -1
- package/dist/write/failure-hints.d.ts +10 -1
- package/dist/write/failure-hints.js +8 -0
- package/dist/write/failure-hints.js.map +1 -1
- package/dist/write/guards.d.ts +1 -1
- package/dist/write/guards.js +10 -0
- package/dist/write/guards.js.map +1 -1
- package/dist/write/move.js +14 -6
- package/dist/write/move.js.map +1 -1
- package/dist/write/operations.d.ts +40 -7
- package/dist/write/pipeline.d.ts +41 -0
- package/dist/write/pipeline.js +289 -19
- package/dist/write/pipeline.js.map +1 -1
- package/dist/write/pre-state.d.ts +1 -1
- package/dist/write/pre-state.js +35 -17
- package/dist/write/pre-state.js.map +1 -1
- package/dist/write/promote-clone.js +434 -19
- package/dist/write/promote-clone.js.map +1 -1
- package/dist/write/reorder.js +76 -27
- package/dist/write/reorder.js.map +1 -1
- package/dist/write/repeat-anchor.d.ts +140 -0
- package/dist/write/repeat-anchor.js +403 -0
- package/dist/write/repeat-anchor.js.map +1 -0
- package/dist/write/repeat-asserts.d.ts +28 -0
- package/dist/write/repeat-asserts.js +169 -0
- package/dist/write/repeat-asserts.js.map +1 -0
- package/dist/write/repeat-rule.js +37 -12
- package/dist/write/repeat-rule.js.map +1 -1
- package/dist/write/vectors/applescript.js +7 -16
- package/dist/write/vectors/applescript.js.map +1 -1
- package/dist/write/vectors/session-reachability.d.ts +133 -0
- package/dist/write/vectors/session-reachability.js +151 -0
- package/dist/write/vectors/session-reachability.js.map +1 -0
- package/dist/write/vectors/shortcuts.js +5 -14
- package/dist/write/vectors/shortcuts.js.map +1 -1
- package/dist/write/vectors/simulator.d.ts +16 -1
- package/dist/write/vectors/simulator.js +122 -32
- package/dist/write/vectors/simulator.js.map +1 -1
- package/dist/write/vectors/types.d.ts +183 -10
- package/dist/write/vectors/ui-recipes.d.ts +8 -0
- package/dist/write/vectors/ui-recipes.js +246 -58
- package/dist/write/vectors/ui-recipes.js.map +1 -1
- package/dist/write/vectors/ui.d.ts +156 -14
- package/dist/write/vectors/ui.js +846 -84
- package/dist/write/vectors/ui.js.map +1 -1
- package/dist/write/verify/delta.d.ts +12 -14
- package/dist/write/verify/delta.js +35 -34
- package/dist/write/verify/delta.js.map +1 -1
- package/dist/write/verify/poller.d.ts +13 -0
- package/dist/write/verify/poller.js +38 -0
- package/dist/write/verify/poller.js.map +1 -1
- package/package.json +8 -1
- package/schema/envelope.schema.json +22 -0
- package/scripts/build-helpers.sh +104 -0
- package/scripts/deputy-cert-setup.sh +60 -0
- package/skills/things-cli/SKILL.md +11 -3
- package/skills/things-cli/references/errors.md +4 -0
- package/skills/things-cli/references/repeating.md +69 -0
package/dist/model/mappers.d.ts
CHANGED
|
@@ -3,8 +3,18 @@
|
|
|
3
3
|
* the schema manifest; encodings per docs/atlas/schema-v26.md.
|
|
4
4
|
*/
|
|
5
5
|
import { type ChecklistItem, type Heading, type Project, type Ref, type Todo } from "./entities.ts";
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
import { type TemplateProjectionRow } from "./template-projection.ts";
|
|
7
|
+
/**
|
|
8
|
+
* Raw TMTask row shape (subset per schema manifest) PLUS the aliased template
|
|
9
|
+
* projection inputs ({@link TemplateProjectionRow}) every read query splices in
|
|
10
|
+
* (queries.ts `fetchTaskRows`). The raw `rt1_nextInstanceStartDate` is
|
|
11
|
+
* deliberately absent from this shape: a template's next occurrence is read
|
|
12
|
+
* ONLY through {@link templateProjectionDay} (the app's cached day where the
|
|
13
|
+
* template carries one, the derived day where it does not — the paused /
|
|
14
|
+
* trashed / never-populated cohort every app version has, GV4 §2.1), never off
|
|
15
|
+
* the raw column.
|
|
16
|
+
*/
|
|
17
|
+
export interface TaskRow extends TemplateProjectionRow {
|
|
8
18
|
uuid: string;
|
|
9
19
|
type: number;
|
|
10
20
|
status: number;
|
|
@@ -39,7 +49,6 @@ export interface TaskRow {
|
|
|
39
49
|
openChecklistItemsCount: number | null;
|
|
40
50
|
rt1_repeatingTemplate: string | null;
|
|
41
51
|
rt1_recurrenceRule: unknown;
|
|
42
|
-
rt1_nextInstanceStartDate: number | null;
|
|
43
52
|
rt1_instanceCreationPaused: number | null;
|
|
44
53
|
repeater: unknown;
|
|
45
54
|
}
|
package/dist/model/mappers.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { START_STATE_FROM_DB, TASK_STATUS_FROM_DB, } from "./entities.js";
|
|
6
6
|
import { decodeEpochReal, decodePackedDate, decodeReminderTime } from "./dates.js";
|
|
7
|
+
import { templateProjectionDay } from "./template-projection.js";
|
|
7
8
|
import { reminderIsLive } from "../read/stage.js";
|
|
8
9
|
export class EnumDomainError extends RangeError {
|
|
9
10
|
constructor(field, value, uuid) {
|
|
@@ -29,7 +30,11 @@ function mapRepeating(row) {
|
|
|
29
30
|
const templateUuid = row.rt1_repeatingTemplate;
|
|
30
31
|
const info = { isTemplate, isInstance: templateUuid !== null, templateUuid };
|
|
31
32
|
if (isTemplate) {
|
|
32
|
-
|
|
33
|
+
// The projection day — the app's own cache while it maintains it (Things
|
|
34
|
+
// ≤ 3.22), else derived from the rule + spawn cursor (3.23 retired the
|
|
35
|
+
// cache). Null when the series projects nowhere: paused, after-completion
|
|
36
|
+
// between instances, ended, or underivable. Never a guessed date.
|
|
37
|
+
info.nextOccurrence = decodePackedDate(templateProjectionDay(row));
|
|
33
38
|
info.paused = row.rt1_instanceCreationPaused === 1;
|
|
34
39
|
// A deadlined template carries a far-future sentinel (4001-01-01) in its
|
|
35
40
|
// own `deadline` column; a deadline-less one carries NULL. This — NOT the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mappers.js","sourceRoot":"","sources":["../../src/model/mappers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EACL,mBAAmB,EACnB,mBAAmB,GASpB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACnF,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"mappers.js","sourceRoot":"","sources":["../../src/model/mappers.ts"],"names":[],"mappings":"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"}
|
|
@@ -28,8 +28,21 @@ export interface OccurrenceWindow {
|
|
|
28
28
|
}
|
|
29
29
|
/**
|
|
30
30
|
* Event dates of a FIXED rule from `anchor` (an app-materialized event date,
|
|
31
|
-
* INCLUDED as the first result), honoring the rule's endDate/
|
|
31
|
+
* INCLUDED as the first result), honoring the rule's endDate/occurrenceCount
|
|
32
32
|
* bounds and the window's count/until. Throws on after-completion rules.
|
|
33
|
+
*
|
|
34
|
+
* ⚠ occurrenceCount is the CONFIGURED TOTAL "ends after N", not a remaining
|
|
35
|
+
* tally (RRX1) — and the anchor is the app cursor, i.e. an occurrence PARTWAY
|
|
36
|
+
* through the series (the app has already spawned `rt1_instanceCreationCount` of
|
|
37
|
+
* them). Capping the from-anchor projection at the total therefore OVER-counts
|
|
38
|
+
* the tail by the already-spawned count for a partway ends-after series; the
|
|
39
|
+
* true remaining = occurrenceCount − icCount, and icCount is a template-column
|
|
40
|
+
* value not carried by the (rule-only) RepeatRule, so it cannot be applied
|
|
41
|
+
* here. This is a bounded, benign over-estimate (extra dates are still valid
|
|
42
|
+
* rule dates that simply will not spawn), consistent with this file's
|
|
43
|
+
* best-effort-extrapolation contract; only reachable for horizon > 1 on a
|
|
44
|
+
* count-bounded series. A tight fix would thread the template's icCount into
|
|
45
|
+
* the projection (a read-model addition — see docs/lab/rrx1-rc-and-reminder.md).
|
|
33
46
|
*/
|
|
34
47
|
export declare function generateEventDates(rule: RepeatRule, anchor: IsoDate, window: OccurrenceWindow): IsoDate[];
|
|
35
48
|
/** One projected occurrence in instance terms (start/deadline split by ts). */
|
|
@@ -48,17 +48,33 @@ function dayInMonth(year, month1, offset) {
|
|
|
48
48
|
// ------------------------------------------------------------- generation
|
|
49
49
|
/**
|
|
50
50
|
* Event dates of a FIXED rule from `anchor` (an app-materialized event date,
|
|
51
|
-
* INCLUDED as the first result), honoring the rule's endDate/
|
|
51
|
+
* INCLUDED as the first result), honoring the rule's endDate/occurrenceCount
|
|
52
52
|
* bounds and the window's count/until. Throws on after-completion rules.
|
|
53
|
+
*
|
|
54
|
+
* ⚠ occurrenceCount is the CONFIGURED TOTAL "ends after N", not a remaining
|
|
55
|
+
* tally (RRX1) — and the anchor is the app cursor, i.e. an occurrence PARTWAY
|
|
56
|
+
* through the series (the app has already spawned `rt1_instanceCreationCount` of
|
|
57
|
+
* them). Capping the from-anchor projection at the total therefore OVER-counts
|
|
58
|
+
* the tail by the already-spawned count for a partway ends-after series; the
|
|
59
|
+
* true remaining = occurrenceCount − icCount, and icCount is a template-column
|
|
60
|
+
* value not carried by the (rule-only) RepeatRule, so it cannot be applied
|
|
61
|
+
* here. This is a bounded, benign over-estimate (extra dates are still valid
|
|
62
|
+
* rule dates that simply will not spawn), consistent with this file's
|
|
63
|
+
* best-effort-extrapolation contract; only reachable for horizon > 1 on a
|
|
64
|
+
* count-bounded series. A tight fix would thread the template's icCount into
|
|
65
|
+
* the projection (a read-model addition — see docs/lab/rrx1-rc-and-reminder.md).
|
|
53
66
|
*/
|
|
54
67
|
export function generateEventDates(rule, anchor, window) {
|
|
55
68
|
if (rule.type !== "fixed") {
|
|
56
69
|
throw new RangeError("after-completion rules cannot be projected — the next date depends on when the " +
|
|
57
70
|
"prior instance resolves");
|
|
58
71
|
}
|
|
59
|
-
//
|
|
60
|
-
//
|
|
61
|
-
|
|
72
|
+
// Bound the projection by the rule's configured total (a safety ceiling for a
|
|
73
|
+
// count-bounded series). NB occurrenceCount is the TOTAL, not the remaining —
|
|
74
|
+
// see the header caveat: this over-counts the tail by icCount for a partway
|
|
75
|
+
// ends-after series (the pure rule math has no access to the template's
|
|
76
|
+
// spawned count).
|
|
77
|
+
const cap = Math.min(Math.max(1, window.count), rule.occurrenceCount === null ? Number.POSITIVE_INFINITY : rule.occurrenceCount);
|
|
62
78
|
const inBounds = (iso) => (window.until === undefined || iso <= window.until) &&
|
|
63
79
|
(rule.endDate === null || iso <= rule.endDate);
|
|
64
80
|
// Every unit generates in ascending date order, so the first out-of-bounds
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"occurrences.js","sourceRoot":"","sources":["../../src/model/occurrences.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"occurrences.js","sourceRoot":"","sources":["../../src/model/occurrences.ts"],"names":[],"mappings":"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"}
|
|
@@ -28,8 +28,16 @@
|
|
|
28
28
|
* discriminator.
|
|
29
29
|
* of occurrence offsets: dy (0-based day; -1 = last day of month),
|
|
30
30
|
* mo (0-based month), wd (weekday, 0=Sunday), wdo (nth weekday, -1=last)
|
|
31
|
-
* ed end date (unix seconds; distant-future sentinel = no end)
|
|
32
|
-
*
|
|
31
|
+
* ed end date (unix seconds; distant-future sentinel = no end). An
|
|
32
|
+
* ends-after rule OMITS this key entirely (RRX1); an ends-on rule sets
|
|
33
|
+
* it to the chosen date.
|
|
34
|
+
* rc the configured "ends after N times" TOTAL occurrence count. IMMUTABLE:
|
|
35
|
+
* it does NOT decrement as instances spawn (RRX1 — a daily ends-after-3
|
|
36
|
+
* series held rc=3 through all three spawns and past exhaustion; the app
|
|
37
|
+
* counts spawns in the template's rt1_instanceCreationCount column and
|
|
38
|
+
* stops by clearing the cursor rt1_nextInstanceStartDate, never by
|
|
39
|
+
* touching rc). 0/absent = unlimited. NOT "remaining" — it never counts
|
|
40
|
+
* down, so it is decoded as `occurrenceCount`, not a remaining tally.
|
|
33
41
|
* rrv rule schema version (4 observed)
|
|
34
42
|
* sr/ia anchor timestamps (not needed for reads)
|
|
35
43
|
*/
|
|
@@ -59,20 +67,67 @@ export interface RepeatRule {
|
|
|
59
67
|
startOffsetDays: number;
|
|
60
68
|
offsets: RepeatOffset[];
|
|
61
69
|
endDate: IsoDate | null;
|
|
62
|
-
|
|
70
|
+
/**
|
|
71
|
+
* The rule's "ends after N times" TOTAL occurrence count (`null` when the
|
|
72
|
+
* series is unlimited). This is the CONFIGURED bound, NOT a live tally: it
|
|
73
|
+
* never decrements as instances spawn (RRX1). The app tracks progress in the
|
|
74
|
+
* template's `rt1_instanceCreationCount` column (not in this rule blob) and
|
|
75
|
+
* ends the series by clearing its next-occurrence cursor once that count
|
|
76
|
+
* reaches this total — so an exhausted ends-after series still decodes with
|
|
77
|
+
* `occurrenceCount` = its original N. Reading how MANY remain therefore
|
|
78
|
+
* requires the template's icCount, which is outside this rule.
|
|
79
|
+
*/
|
|
80
|
+
occurrenceCount: number | null;
|
|
63
81
|
version: number;
|
|
64
82
|
}
|
|
65
83
|
/**
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
84
|
+
* Decode ONE `of` offset entry (the plist grammar `dy`/`mo`/`wd`/`wdo`) into a
|
|
85
|
+
* {@link RepeatOffset}. Shared by {@link decodeRecurrenceRule} (reading a stored
|
|
86
|
+
* rule) and the write-side full-fidelity assert builder (which composes the
|
|
87
|
+
* expected numeric offsets and round-trips them through this SAME decode so the
|
|
88
|
+
* canonical anchor key it compares against is byte-consistent with what a real
|
|
89
|
+
* read produces). Accepts any record; non-numeric fields are ignored.
|
|
90
|
+
*/
|
|
91
|
+
export declare function decodeOffsetEntry(e: Record<string, unknown>): RepeatOffset;
|
|
92
|
+
/**
|
|
93
|
+
* A canonical, ORDER-INSENSITIVE string key of a rule's calendar anchor (its
|
|
94
|
+
* `offsets`) — the comparison surface for full-fidelity recurrence assertions.
|
|
95
|
+
* Each offset renders to a compact token (`m` month · `d` day · `w` weekday ·
|
|
96
|
+
* `o` weekday-ordinal, all decoded values), and the tokens are sorted so a
|
|
97
|
+
* weekly rule that fires Tue+Thu keys identically regardless of the order the
|
|
98
|
+
* app happened to store the two weekday offsets in. Two rules share a key iff
|
|
99
|
+
* they name the SAME set of calendar placements. Empty offsets (or all-nominal
|
|
100
|
+
* after-completion offsets) yield "".
|
|
101
|
+
*/
|
|
102
|
+
export declare function anchorKeyOfOffsets(offsets: RepeatOffset[]): string;
|
|
103
|
+
/**
|
|
104
|
+
* The GUI's status word for a repeating template with no set next occurrence:
|
|
105
|
+
* `paused` (instance creation paused), `ended` (the series will spawn no more
|
|
106
|
+
* instances — its end date has passed or its occurrence count is exhausted),
|
|
107
|
+
* else `waiting` (an after-completion rule between instances).
|
|
108
|
+
*
|
|
109
|
+
* Exhaustion is read from the CURSOR, not the rule's count. A FIXED series
|
|
110
|
+
* always carries a next-occurrence cursor while live; the app clears it
|
|
111
|
+
* (`rt1_nextInstanceStartDate` → NULL) the moment the series ends — whether by
|
|
112
|
+
* an ends-ON date passing OR an ends-AFTER count being reached (RRX1: a daily
|
|
113
|
+
* ends-after-3 series went cursor-NULL after its 3rd spawn with rc still 3, and
|
|
114
|
+
* a past ends-on template was born cursor-NULL). So a fixed rule with no next
|
|
115
|
+
* occurrence has ended. The rule's occurrence count is NOT the signal — it is
|
|
116
|
+
* the immutable configured total (never 0 at exhaustion), which is why the old
|
|
117
|
+
* `remainingCount === 0` test was unreachable. After-completion rules rest with
|
|
118
|
+
* no next occurrence BETWEEN instances (that is `waiting`, not `ended`), so the
|
|
119
|
+
* cursor test is gated on fixed rules. `nextOccurrence` is the template's
|
|
120
|
+
* PROJECTION DAY (model/template-projection.ts), so the same reading holds when
|
|
121
|
+
* the cached column is absent: the derivation itself returns nothing for an
|
|
122
|
+
* exhausted ends-after or a past ends-on series (RRX1), exactly as the cleared
|
|
123
|
+
* column does. Live-verified 2026-07-11 (Ended = fixed
|
|
124
|
+
* rule with a past endDate; Waiting = after-completion rule) + RRX1 2026-08-15
|
|
125
|
+
* (ends-after / ends-on exhaustion end-states, golden-v2 / 3.22.12).
|
|
72
126
|
*/
|
|
73
127
|
export declare function templateStatus(repeating: {
|
|
74
128
|
paused?: boolean;
|
|
75
129
|
rule?: RepeatRule;
|
|
130
|
+
nextOccurrence?: IsoDate | null;
|
|
76
131
|
}, todayIso: string): "waiting" | "paused" | "ended";
|
|
77
132
|
export declare function decodeRecurrenceRule(blob: unknown): RepeatRule;
|
|
78
133
|
/** The rule schema version the 91-rule corpus + instance validation covered. */
|
package/dist/model/recurrence.js
CHANGED
|
@@ -4,24 +4,93 @@ const UNITS = {
|
|
|
4
4
|
8: "monthly",
|
|
5
5
|
4: "yearly",
|
|
6
6
|
};
|
|
7
|
+
/**
|
|
8
|
+
* Decode ONE `of` offset entry (the plist grammar `dy`/`mo`/`wd`/`wdo`) into a
|
|
9
|
+
* {@link RepeatOffset}. Shared by {@link decodeRecurrenceRule} (reading a stored
|
|
10
|
+
* rule) and the write-side full-fidelity assert builder (which composes the
|
|
11
|
+
* expected numeric offsets and round-trips them through this SAME decode so the
|
|
12
|
+
* canonical anchor key it compares against is byte-consistent with what a real
|
|
13
|
+
* read produces). Accepts any record; non-numeric fields are ignored.
|
|
14
|
+
*/
|
|
15
|
+
export function decodeOffsetEntry(e) {
|
|
16
|
+
const offset = {};
|
|
17
|
+
if (typeof e["dy"] === "number")
|
|
18
|
+
offset.day = e["dy"] === -1 ? -1 : e["dy"] + 1;
|
|
19
|
+
if (typeof e["mo"] === "number")
|
|
20
|
+
offset.month = e["mo"] + 1;
|
|
21
|
+
if (typeof e["wd"] === "number")
|
|
22
|
+
offset.weekday = e["wd"];
|
|
23
|
+
if (typeof e["wdo"] === "number")
|
|
24
|
+
offset.weekdayOrdinal = e["wdo"];
|
|
25
|
+
return offset;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* A canonical, ORDER-INSENSITIVE string key of a rule's calendar anchor (its
|
|
29
|
+
* `offsets`) — the comparison surface for full-fidelity recurrence assertions.
|
|
30
|
+
* Each offset renders to a compact token (`m` month · `d` day · `w` weekday ·
|
|
31
|
+
* `o` weekday-ordinal, all decoded values), and the tokens are sorted so a
|
|
32
|
+
* weekly rule that fires Tue+Thu keys identically regardless of the order the
|
|
33
|
+
* app happened to store the two weekday offsets in. Two rules share a key iff
|
|
34
|
+
* they name the SAME set of calendar placements. Empty offsets (or all-nominal
|
|
35
|
+
* after-completion offsets) yield "".
|
|
36
|
+
*/
|
|
37
|
+
export function anchorKeyOfOffsets(offsets) {
|
|
38
|
+
return offsets
|
|
39
|
+
.map((o) => {
|
|
40
|
+
const parts = [];
|
|
41
|
+
if (o.month !== undefined)
|
|
42
|
+
parts.push(`m${o.month}`);
|
|
43
|
+
if (o.day !== undefined)
|
|
44
|
+
parts.push(`d${o.day}`);
|
|
45
|
+
if (o.weekday !== undefined)
|
|
46
|
+
parts.push(`w${o.weekday}`);
|
|
47
|
+
if (o.weekdayOrdinal !== undefined)
|
|
48
|
+
parts.push(`o${o.weekdayOrdinal}`);
|
|
49
|
+
return parts.join("");
|
|
50
|
+
})
|
|
51
|
+
.filter((t) => t.length > 0)
|
|
52
|
+
.toSorted()
|
|
53
|
+
.join(",");
|
|
54
|
+
}
|
|
7
55
|
/** Unix seconds this far out (year ≥ 3000) mean "repeats forever". */
|
|
8
56
|
const DISTANT_FUTURE_EPOCH = 32503680000;
|
|
9
57
|
/**
|
|
10
|
-
* The GUI's status word for a repeating template with no set next
|
|
11
|
-
*
|
|
12
|
-
* date has passed or its
|
|
13
|
-
* after-completion rule between instances).
|
|
14
|
-
*
|
|
15
|
-
* rule
|
|
58
|
+
* The GUI's status word for a repeating template with no set next occurrence:
|
|
59
|
+
* `paused` (instance creation paused), `ended` (the series will spawn no more
|
|
60
|
+
* instances — its end date has passed or its occurrence count is exhausted),
|
|
61
|
+
* else `waiting` (an after-completion rule between instances).
|
|
62
|
+
*
|
|
63
|
+
* Exhaustion is read from the CURSOR, not the rule's count. A FIXED series
|
|
64
|
+
* always carries a next-occurrence cursor while live; the app clears it
|
|
65
|
+
* (`rt1_nextInstanceStartDate` → NULL) the moment the series ends — whether by
|
|
66
|
+
* an ends-ON date passing OR an ends-AFTER count being reached (RRX1: a daily
|
|
67
|
+
* ends-after-3 series went cursor-NULL after its 3rd spawn with rc still 3, and
|
|
68
|
+
* a past ends-on template was born cursor-NULL). So a fixed rule with no next
|
|
69
|
+
* occurrence has ended. The rule's occurrence count is NOT the signal — it is
|
|
70
|
+
* the immutable configured total (never 0 at exhaustion), which is why the old
|
|
71
|
+
* `remainingCount === 0` test was unreachable. After-completion rules rest with
|
|
72
|
+
* no next occurrence BETWEEN instances (that is `waiting`, not `ended`), so the
|
|
73
|
+
* cursor test is gated on fixed rules. `nextOccurrence` is the template's
|
|
74
|
+
* PROJECTION DAY (model/template-projection.ts), so the same reading holds when
|
|
75
|
+
* the cached column is absent: the derivation itself returns nothing for an
|
|
76
|
+
* exhausted ends-after or a past ends-on series (RRX1), exactly as the cleared
|
|
77
|
+
* column does. Live-verified 2026-07-11 (Ended = fixed
|
|
78
|
+
* rule with a past endDate; Waiting = after-completion rule) + RRX1 2026-08-15
|
|
79
|
+
* (ends-after / ends-on exhaustion end-states, golden-v2 / 3.22.12).
|
|
16
80
|
*/
|
|
17
81
|
export function templateStatus(repeating, todayIso) {
|
|
18
82
|
if (repeating.paused === true)
|
|
19
83
|
return "paused";
|
|
20
84
|
const rule = repeating.rule;
|
|
21
85
|
if (rule !== undefined) {
|
|
86
|
+
// An ends-on rule whose end date has passed is ended — an authoritative
|
|
87
|
+
// signal that also covers a "born already ended" past ends-on template.
|
|
22
88
|
if (rule.endDate !== null && rule.endDate < todayIso)
|
|
23
89
|
return "ended";
|
|
24
|
-
|
|
90
|
+
// A fixed series with no next occurrence has exhausted its bound (count OR
|
|
91
|
+
// date) — the app cleared the cursor. (After-completion cursor-NULL is a
|
|
92
|
+
// normal resting state, so this is fixed-only.)
|
|
93
|
+
if (rule.type === "fixed" && repeating.nextOccurrence == null)
|
|
25
94
|
return "ended";
|
|
26
95
|
}
|
|
27
96
|
return "waiting";
|
|
@@ -52,17 +121,7 @@ export function decodeRecurrenceRule(blob) {
|
|
|
52
121
|
for (const entry of of) {
|
|
53
122
|
if (typeof entry !== "object" || entry === null || Array.isArray(entry))
|
|
54
123
|
continue;
|
|
55
|
-
|
|
56
|
-
const offset = {};
|
|
57
|
-
if (typeof e["dy"] === "number")
|
|
58
|
-
offset.day = e["dy"] === -1 ? -1 : e["dy"] + 1;
|
|
59
|
-
if (typeof e["mo"] === "number")
|
|
60
|
-
offset.month = e["mo"] + 1;
|
|
61
|
-
if (typeof e["wd"] === "number")
|
|
62
|
-
offset.weekday = e["wd"];
|
|
63
|
-
if (typeof e["wdo"] === "number")
|
|
64
|
-
offset.weekdayOrdinal = e["wdo"];
|
|
65
|
-
offsets.push(offset);
|
|
124
|
+
offsets.push(decodeOffsetEntry(entry));
|
|
66
125
|
}
|
|
67
126
|
}
|
|
68
127
|
const ed = typeof dict["ed"] === "number" ? dict["ed"] : null;
|
|
@@ -84,7 +143,9 @@ export function decodeRecurrenceRule(blob) {
|
|
|
84
143
|
startOffsetDays: typeof dict["ts"] === "number" ? dict["ts"] : 0,
|
|
85
144
|
offsets,
|
|
86
145
|
endDate: ed === null || ed >= DISTANT_FUTURE_EPOCH ? null : epochToIso(ed),
|
|
87
|
-
|
|
146
|
+
// rc = the "ends after N" TOTAL (immutable, never decrements — RRX1);
|
|
147
|
+
// 0/absent = unlimited. See RepeatRule.occurrenceCount.
|
|
148
|
+
occurrenceCount: rc === 0 ? null : rc,
|
|
88
149
|
version: rrv,
|
|
89
150
|
};
|
|
90
151
|
}
|
|
@@ -169,6 +230,20 @@ class Parser {
|
|
|
169
230
|
return true;
|
|
170
231
|
case "false/":
|
|
171
232
|
return false;
|
|
233
|
+
// Self-closing EMPTY collections. Things writes `<array/>` for a rule with
|
|
234
|
+
// no calendar offsets — every AFTER-COMPLETION template, which has no
|
|
235
|
+
// anchor to list (RDLG2e: `things doctor` reported "1 undecodable" against
|
|
236
|
+
// a real 3.23 library holding one, and the whole rule then failed to
|
|
237
|
+
// decode, costing that template its occurrence projections and its rule
|
|
238
|
+
// read-back). `<dict/>` and `<string/>` are the same shape, so all three
|
|
239
|
+
// are accepted rather than leaving the next empty collection to rediscover
|
|
240
|
+
// this the same way.
|
|
241
|
+
case "array/":
|
|
242
|
+
return [];
|
|
243
|
+
case "dict/":
|
|
244
|
+
return {};
|
|
245
|
+
case "string/":
|
|
246
|
+
return "";
|
|
172
247
|
case "dict": {
|
|
173
248
|
const dict = {};
|
|
174
249
|
while (!this.peekClose("dict")) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recurrence.js","sourceRoot":"","sources":["../../src/model/recurrence.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"recurrence.js","sourceRoot":"","sources":["../../src/model/recurrence.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The TMTask columns {@link templateProjectionDay} reads, aliased to the
|
|
3
|
+
* {@link TemplateProjectionRow} field names. Splice into any SELECT that needs a
|
|
4
|
+
* template's projection day (one fetch — the rule blob is selected once here, so
|
|
5
|
+
* callers alias `rt1_recurrenceRule` from `tpRule` rather than again).
|
|
6
|
+
*/
|
|
7
|
+
export declare const TEMPLATE_PROJECTION_COLUMNS: string;
|
|
8
|
+
/** A template row's projection inputs (see {@link TEMPLATE_PROJECTION_COLUMNS}). */
|
|
9
|
+
export interface TemplateProjectionRow {
|
|
10
|
+
/** `rt1_nextInstanceStartDate` — packed; NULL on paused/trashed/never-populated templates. */
|
|
11
|
+
tpNext: number | null;
|
|
12
|
+
/** `rt1_instanceCreationStartDate` — the packed spawn cursor. */
|
|
13
|
+
tpCursor: number | null;
|
|
14
|
+
/** `rt1_recurrenceRule` — the XML plist blob. */
|
|
15
|
+
tpRule: unknown;
|
|
16
|
+
/** `rt1_instanceCreationPaused`. */
|
|
17
|
+
tpPaused: number | null;
|
|
18
|
+
/** `rt1_instanceCreationCount` — spawns so far (RRX1). */
|
|
19
|
+
tpCount: number | null;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* The packed day a repeating template projects into, or `null` when it projects
|
|
23
|
+
* nowhere. Callers apply their own strictly-future / day-equality gate; this
|
|
24
|
+
* returns the day only.
|
|
25
|
+
*/
|
|
26
|
+
export declare function templateProjectionDay(row: TemplateProjectionRow): number | null;
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A repeating template's PROJECTION DAY — the packed day its rendered projection
|
|
3
|
+
* row occupies on the Upcoming day-block todayIndex axis (the TMPLSORT/PTMPL
|
|
4
|
+
* placement laws). Placement math (move/reorder pre-state) groups a template with
|
|
5
|
+
* the scheduled and deadline-forecast rows sharing that day.
|
|
6
|
+
*
|
|
7
|
+
* TWO SOURCES, in order:
|
|
8
|
+
*
|
|
9
|
+
* 1. `rt1_nextInstanceStartDate` when it is non-NULL. Things ≤ 3.22 maintains
|
|
10
|
+
* this per-row next-instance cache on every live template, and it is the
|
|
11
|
+
* column every projection law was probed against — so when the running app
|
|
12
|
+
* still keeps it, it IS the answer (live-version support, not a legacy
|
|
13
|
+
* shim).
|
|
14
|
+
* 2. DERIVED from the decoded rule + the `rt1_instanceCreationStartDate` cursor
|
|
15
|
+
* otherwise. The NULL-cache case is real but narrower than first measured:
|
|
16
|
+
* the dbv-27 migration (Things 3.23) nulled the column on NON-template rows
|
|
17
|
+
* only and left every template's cached value byte-identical (GV4 in-lab
|
|
18
|
+
* re-measurement + live-host confirmation — docs/lab/gv4-323-campaign.md,
|
|
19
|
+
* correcting docs/lab/dbv27-migration-diff.md). What actually lacks the
|
|
20
|
+
* cache is a PRE-EXISTING template cohort (~a quarter of the live library:
|
|
21
|
+
* paused, trashed, or never populated) — plus whatever a future app version
|
|
22
|
+
* chooses to stop maintaining. The cursor is the app's own anchor for the
|
|
23
|
+
* next occurrence, so the projection is the first rule occurrence on or
|
|
24
|
+
* after it. The projection runs through the ONE occurrence generator
|
|
25
|
+
* ({@link projectOccurrences}), never a second rule evaluator: for an
|
|
26
|
+
* on-grid cursor it returns the cursor itself; for an off-rule first
|
|
27
|
+
* occurrence (ANCH2 — a typed "Next:" the grid does not contain) it returns
|
|
28
|
+
* the first rule-ALIGNED occurrence at or after it — exactly what the
|
|
29
|
+
* cached column holds when present.
|
|
30
|
+
*
|
|
31
|
+
* FAIL CLOSED — the helper returns `null` (never a guess) whenever the app would
|
|
32
|
+
* not render a projection or the derivation is not sound:
|
|
33
|
+
*
|
|
34
|
+
* - no rule blob (a bare legacy `repeater` template), or an undecodable /
|
|
35
|
+
* unknown-`rrv` rule (a Things update changed the format);
|
|
36
|
+
* - an AFTER-COMPLETION rule: it has no calendar until the prior instance
|
|
37
|
+
* resolves, so nothing is derivable from the cursor;
|
|
38
|
+
* - a PAUSED series (`rt1_instanceCreationPaused = 1`): pause clears the cursor
|
|
39
|
+
* column but RETAINS the anchor (SERDEL S3), so deriving would resurrect a
|
|
40
|
+
* projection the app does not render;
|
|
41
|
+
* - an ENDED series — an ends-ON date already past (the generator's own bound)
|
|
42
|
+
* or an ends-AFTER total reached (`rt1_instanceCreationCount` ≥ the rule's
|
|
43
|
+
* immutable `rc` total, RRX1);
|
|
44
|
+
* - a missing or out-of-domain cursor.
|
|
45
|
+
*
|
|
46
|
+
* Every consumer treats `null` exactly as it treats a NULL column: the template
|
|
47
|
+
* contributes no day, so it is not a day-block member and no placement leg is
|
|
48
|
+
* compiled for it.
|
|
49
|
+
*/
|
|
50
|
+
import { decodePackedDate, encodePackedDate } from "./dates.js";
|
|
51
|
+
import { projectOccurrences } from "./occurrences.js";
|
|
52
|
+
import { decodeRecurrenceRule } from "./recurrence.js";
|
|
53
|
+
/**
|
|
54
|
+
* The TMTask columns {@link templateProjectionDay} reads, aliased to the
|
|
55
|
+
* {@link TemplateProjectionRow} field names. Splice into any SELECT that needs a
|
|
56
|
+
* template's projection day (one fetch — the rule blob is selected once here, so
|
|
57
|
+
* callers alias `rt1_recurrenceRule` from `tpRule` rather than again).
|
|
58
|
+
*/
|
|
59
|
+
export const TEMPLATE_PROJECTION_COLUMNS = "rt1_nextInstanceStartDate AS tpNext, rt1_instanceCreationStartDate AS tpCursor, " +
|
|
60
|
+
"rt1_recurrenceRule AS tpRule, rt1_instanceCreationPaused AS tpPaused, " +
|
|
61
|
+
"rt1_instanceCreationCount AS tpCount";
|
|
62
|
+
/**
|
|
63
|
+
* The packed day a repeating template projects into, or `null` when it projects
|
|
64
|
+
* nowhere. Callers apply their own strictly-future / day-equality gate; this
|
|
65
|
+
* returns the day only.
|
|
66
|
+
*/
|
|
67
|
+
export function templateProjectionDay(row) {
|
|
68
|
+
// The app's own cache is authoritative whenever it exists (3.23 still
|
|
69
|
+
// maintains it on templates — GV4 correction).
|
|
70
|
+
if (row.tpNext !== null)
|
|
71
|
+
return row.tpNext;
|
|
72
|
+
// No cache: derive. A paused series renders no projection (its cursor
|
|
73
|
+
// column was cleared while the anchor stayed) — never resurrect one.
|
|
74
|
+
if (row.tpPaused === 1)
|
|
75
|
+
return null;
|
|
76
|
+
if (row.tpRule === null || row.tpRule === undefined)
|
|
77
|
+
return null;
|
|
78
|
+
let cursorIso;
|
|
79
|
+
try {
|
|
80
|
+
cursorIso = decodePackedDate(row.tpCursor);
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
return null; // out-of-domain packed value — fail closed
|
|
84
|
+
}
|
|
85
|
+
if (cursorIso === null)
|
|
86
|
+
return null;
|
|
87
|
+
let rule;
|
|
88
|
+
try {
|
|
89
|
+
rule = decodeRecurrenceRule(row.tpRule);
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
return null; // undecodable / unknown rrv — fail closed
|
|
93
|
+
}
|
|
94
|
+
// After-completion series have no calendar to project from.
|
|
95
|
+
if (rule.type !== "fixed")
|
|
96
|
+
return null;
|
|
97
|
+
// Ends-after exhaustion: rc is the immutable configured TOTAL and the app
|
|
98
|
+
// counts spawns in icCount (RRX1), so count >= total means the series ended.
|
|
99
|
+
if (rule.occurrenceCount !== null && (row.tpCount ?? 0) >= rule.occurrenceCount)
|
|
100
|
+
return null;
|
|
101
|
+
// The first occurrence on or after the cursor (the generator bounds itself by
|
|
102
|
+
// the rule's endDate, so a past ends-on series yields nothing).
|
|
103
|
+
const first = projectOccurrences(rule, cursorIso, { count: 1 }, false)[0];
|
|
104
|
+
if (first === undefined)
|
|
105
|
+
return null;
|
|
106
|
+
try {
|
|
107
|
+
return encodePackedDate(first.startDate);
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=template-projection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template-projection.js","sourceRoot":"","sources":["../../src/model/template-projection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAChE,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAEvD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,2BAA2B,GACtC,kFAAkF;IAClF,wEAAwE;IACxE,sCAAsC,CAAC;AAgBzC;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CAAC,GAA0B;IAC9D,sEAAsE;IACtE,+CAA+C;IAC/C,IAAI,GAAG,CAAC,MAAM,KAAK,IAAI;QAAE,OAAO,GAAG,CAAC,MAAM,CAAC;IAC3C,sEAAsE;IACtE,qEAAqE;IACrE,IAAI,GAAG,CAAC,QAAQ,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACpC,IAAI,GAAG,CAAC,MAAM,KAAK,IAAI,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACjE,IAAI,SAAS,CAAC;IACd,IAAI,CAAC;QACH,SAAS,GAAG,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC7C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC,CAAC,2CAA2C;IAC1D,CAAC;IACD,IAAI,SAAS,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IACpC,IAAI,IAAI,CAAC;IACT,IAAI,CAAC;QACH,IAAI,GAAG,oBAAoB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC1C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC,CAAC,0CAA0C;IACzD,CAAC;IACD,4DAA4D;IAC5D,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO;QAAE,OAAO,IAAI,CAAC;IACvC,0EAA0E;IAC1E,6EAA6E;IAC7E,IAAI,IAAI,CAAC,eAAe,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,eAAe;QAAE,OAAO,IAAI,CAAC;IAC7F,8EAA8E;IAC9E,gEAAgE;IAChE,MAAM,KAAK,GAAG,kBAAkB,CAAC,IAAI,EAAE,SAAS,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1E,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACrC,IAAI,CAAC;QACH,OAAO,gBAAgB,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IAC3C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
|