things-api 0.9.0 → 0.10.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 +30 -11
- package/dist/audit/log.js +56 -2
- package/dist/audit/log.js.map +1 -1
- package/dist/audit/schema.d.ts +26 -8
- package/dist/audit/schema.js +42 -1
- package/dist/audit/schema.js.map +1 -1
- package/dist/cli/commands/area.d.ts +26 -3
- package/dist/cli/commands/area.js +125 -70
- package/dist/cli/commands/area.js.map +1 -1
- package/dist/cli/commands/doctor.d.ts +1 -1
- package/dist/cli/commands/doctor.js +44 -5
- package/dist/cli/commands/doctor.js.map +1 -1
- package/dist/cli/commands/mcp.js +23 -4
- package/dist/cli/commands/mcp.js.map +1 -1
- package/dist/cli/commands/project.d.ts +18 -1
- package/dist/cli/commands/project.js +69 -31
- package/dist/cli/commands/project.js.map +1 -1
- package/dist/cli/commands/reads.js +423 -157
- package/dist/cli/commands/reads.js.map +1 -1
- package/dist/cli/commands/repeat-flags.d.ts +20 -0
- package/dist/cli/commands/repeat-flags.js +76 -0
- package/dist/cli/commands/repeat-flags.js.map +1 -0
- package/dist/cli/commands/setup.js +2 -3
- package/dist/cli/commands/setup.js.map +1 -1
- package/dist/cli/commands/show.js +47 -24
- package/dist/cli/commands/show.js.map +1 -1
- package/dist/cli/commands/todo.d.ts +1 -1
- package/dist/cli/commands/todo.js +7 -6
- package/dist/cli/commands/todo.js.map +1 -1
- package/dist/cli/commands/writes.js +378 -148
- package/dist/cli/commands/writes.js.map +1 -1
- package/dist/cli/did-you-mean.d.ts +1 -1
- package/dist/cli/excess-args.d.ts +15 -0
- package/dist/cli/excess-args.js +51 -0
- package/dist/cli/excess-args.js.map +1 -0
- package/dist/cli/glyphs.d.ts +39 -2
- package/dist/cli/glyphs.js +91 -21
- package/dist/cli/glyphs.js.map +1 -1
- package/dist/cli/help.d.ts +54 -0
- package/dist/cli/help.js +355 -0
- package/dist/cli/help.js.map +1 -0
- package/dist/cli/main.js +32 -25
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/period.d.ts +7 -0
- package/dist/cli/period.js +12 -0
- package/dist/cli/period.js.map +1 -1
- package/dist/cli/read-driver.d.ts +26 -19
- package/dist/cli/read-driver.js +67 -33
- package/dist/cli/read-driver.js.map +1 -1
- package/dist/cli/render.d.ts +92 -28
- package/dist/cli/render.js +318 -97
- package/dist/cli/render.js.map +1 -1
- package/dist/cli/resolve-invocation.d.ts +42 -4
- package/dist/cli/resolve-invocation.js +97 -14
- package/dist/cli/resolve-invocation.js.map +1 -1
- package/dist/cli/tag-filters.d.ts +59 -0
- package/dist/cli/tag-filters.js +57 -0
- package/dist/cli/tag-filters.js.map +1 -0
- package/dist/cli/verb-hint.d.ts +25 -0
- package/dist/cli/verb-hint.js +138 -0
- package/dist/cli/verb-hint.js.map +1 -0
- package/dist/cli/width.d.ts +135 -0
- package/dist/cli/width.js +313 -0
- package/dist/cli/width.js.map +1 -0
- package/dist/client.d.ts +137 -24
- package/dist/client.js +105 -16
- package/dist/client.js.map +1 -1
- package/dist/config.d.ts +11 -0
- package/dist/config.js +3 -0
- package/dist/config.js.map +1 -1
- package/dist/contracts.d.ts +87 -17
- package/dist/contracts.js +44 -1
- package/dist/contracts.js.map +1 -1
- package/dist/db/fingerprint.d.ts +12 -0
- package/dist/db/fingerprint.js +15 -1
- package/dist/db/fingerprint.js.map +1 -1
- package/dist/db/locate.js +1 -1
- package/dist/db/locate.js.map +1 -1
- package/dist/diagnose.d.ts +63 -0
- package/dist/diagnose.js +38 -1
- package/dist/diagnose.js.map +1 -1
- package/dist/index.d.ts +30 -4
- package/dist/index.js +35 -2
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.d.ts +9 -1
- package/dist/mcp/server.js +691 -133
- package/dist/mcp/server.js.map +1 -1
- package/dist/model/entities.d.ts +31 -7
- package/dist/model/entities.js.map +1 -1
- package/dist/model/mappers.d.ts +7 -0
- package/dist/model/mappers.js +7 -2
- package/dist/model/mappers.js.map +1 -1
- package/dist/model/serialize.d.ts +28 -0
- package/dist/model/serialize.js +80 -0
- package/dist/model/serialize.js.map +1 -0
- package/dist/model/when-sugar.d.ts +47 -0
- package/dist/model/when-sugar.js +45 -0
- package/dist/model/when-sugar.js.map +1 -0
- package/dist/read/area-view.d.ts +8 -1
- package/dist/read/area-view.js +49 -13
- package/dist/read/area-view.js.map +1 -1
- package/dist/read/filter-contract.d.ts +117 -0
- package/dist/read/filter-contract.js +78 -0
- package/dist/read/filter-contract.js.map +1 -0
- package/dist/read/predicates.d.ts +30 -0
- package/dist/read/predicates.js +30 -0
- package/dist/read/predicates.js.map +1 -1
- package/dist/read/project-view.d.ts +12 -1
- package/dist/read/project-view.js +39 -8
- package/dist/read/project-view.js.map +1 -1
- package/dist/read/queries.d.ts +149 -6
- package/dist/read/queries.js +250 -31
- package/dist/read/queries.js.map +1 -1
- package/dist/read/sections.d.ts +51 -0
- package/dist/read/sections.js +37 -0
- package/dist/read/sections.js.map +1 -0
- package/dist/read/sidebar-order.js +2 -1
- package/dist/read/sidebar-order.js.map +1 -1
- package/dist/read/tags.d.ts +27 -3
- package/dist/read/tags.js +83 -12
- package/dist/read/tags.js.map +1 -1
- package/dist/read/truncation.d.ts +71 -0
- package/dist/read/{pagination.js → truncation.js} +103 -94
- package/dist/read/truncation.js.map +1 -0
- package/dist/read/views.d.ts +140 -16
- package/dist/read/views.js +264 -67
- package/dist/read/views.js.map +1 -1
- package/dist/surface-copy.d.ts +19 -0
- package/dist/surface-copy.js +32 -0
- package/dist/surface-copy.js.map +1 -1
- package/dist/sync-health.d.ts +78 -0
- package/dist/sync-health.js +312 -0
- package/dist/sync-health.js.map +1 -0
- package/dist/write/accessibility-probe.d.ts +12 -0
- package/dist/write/accessibility-probe.js +63 -0
- package/dist/write/accessibility-probe.js.map +1 -0
- package/dist/write/automation-probe.d.ts +7 -0
- package/dist/write/automation-probe.js +8 -1
- package/dist/write/automation-probe.js.map +1 -1
- package/dist/write/batch.js +4 -2
- package/dist/write/batch.js.map +1 -1
- package/dist/write/capabilities.d.ts +8 -0
- package/dist/write/capabilities.js +13 -6
- package/dist/write/capabilities.js.map +1 -1
- package/dist/write/commands.d.ts +2 -0
- package/dist/write/commands.js +562 -48
- package/dist/write/commands.js.map +1 -1
- package/dist/write/edit-checklist.js +3 -2
- package/dist/write/edit-checklist.js.map +1 -1
- package/dist/write/guards.d.ts +2 -7
- package/dist/write/guards.js +64 -6
- package/dist/write/guards.js.map +1 -1
- package/dist/write/heading.js +2 -0
- package/dist/write/heading.js.map +1 -1
- package/dist/write/lock.d.ts +40 -2
- package/dist/write/lock.js +91 -14
- package/dist/write/lock.js.map +1 -1
- package/dist/write/make-repeating-project.d.ts +4 -0
- package/dist/write/make-repeating-project.js +253 -0
- package/dist/write/make-repeating-project.js.map +1 -0
- package/dist/write/operations.d.ts +145 -1
- package/dist/write/operations.js +48 -0
- package/dist/write/operations.js.map +1 -1
- package/dist/write/pipeline.d.ts +19 -0
- package/dist/write/pipeline.js +109 -26
- package/dist/write/pipeline.js.map +1 -1
- package/dist/write/pre-state.d.ts +68 -3
- package/dist/write/pre-state.js +102 -3
- package/dist/write/pre-state.js.map +1 -1
- package/dist/write/reopen.js +3 -2
- package/dist/write/reopen.js.map +1 -1
- package/dist/write/reorder.js +27 -17
- package/dist/write/reorder.js.map +1 -1
- package/dist/write/repeat-rule.d.ts +22 -0
- package/dist/write/repeat-rule.js +258 -0
- package/dist/write/repeat-rule.js.map +1 -0
- package/dist/write/reversibility.js +49 -0
- package/dist/write/reversibility.js.map +1 -1
- package/dist/write/tag-refs.d.ts +47 -0
- package/dist/write/tag-refs.js +126 -0
- package/dist/write/tag-refs.js.map +1 -0
- package/dist/write/undo.d.ts +74 -5
- package/dist/write/undo.js +493 -80
- package/dist/write/undo.js.map +1 -1
- package/dist/write/vectors/registry.d.ts +17 -1
- package/dist/write/vectors/registry.js +18 -2
- package/dist/write/vectors/registry.js.map +1 -1
- package/dist/write/vectors/types.d.ts +119 -3
- package/dist/write/vectors/ui-certification.d.ts +48 -0
- package/dist/write/vectors/ui-certification.js +46 -0
- package/dist/write/vectors/ui-certification.js.map +1 -0
- package/dist/write/vectors/ui-drag.d.ts +188 -0
- package/dist/write/vectors/ui-drag.js +1095 -0
- package/dist/write/vectors/ui-drag.js.map +1 -0
- package/dist/write/vectors/ui-recipes.d.ts +70 -0
- package/dist/write/vectors/ui-recipes.js +558 -0
- package/dist/write/vectors/ui-recipes.js.map +1 -0
- package/dist/write/vectors/ui.d.ts +137 -0
- package/dist/write/vectors/ui.js +656 -0
- package/dist/write/vectors/ui.js.map +1 -0
- package/dist/write/verify/delta.d.ts +31 -3
- package/dist/write/verify/delta.js +22 -6
- package/dist/write/verify/delta.js.map +1 -1
- package/dist/write/verify/poller.js +1 -0
- package/dist/write/verify/poller.js.map +1 -1
- package/package.json +1 -1
- package/dist/cli/exit-codes.d.ts +0 -26
- package/dist/cli/exit-codes.js +0 -26
- package/dist/cli/exit-codes.js.map +0 -1
- package/dist/cli/output.d.ts +0 -42
- package/dist/cli/output.js +0 -16
- package/dist/cli/output.js.map +0 -1
- package/dist/read/pagination.d.ts +0 -104
- package/dist/read/pagination.js.map +0 -1
|
@@ -1,5 +1,12 @@
|
|
|
1
|
+
import { localToday } from "../model/dates.js";
|
|
2
|
+
import { isActiveProjectRow } from "./area-view.js";
|
|
1
3
|
import { AREA_PREVIEW_LIMIT, DEFAULT_LIST_LIMIT, PROJECT_PREVIEW_LIMIT } from "../surface-copy.js";
|
|
4
|
+
import { partitionSomedaySection, splitSectionBlocks } from "./sections.js";
|
|
5
|
+
// The per-block cap shape and the structural section splitters live in
|
|
6
|
+
// ./sections.ts (imported for capping here). Re-exported so existing importers
|
|
7
|
+
// — and the truncation unit test — keep one import site.
|
|
2
8
|
export { AREA_PREVIEW_LIMIT, DEFAULT_LIST_LIMIT, PROJECT_PREVIEW_LIMIT };
|
|
9
|
+
export { partitionSomedaySection, splitSectionBlocks };
|
|
3
10
|
const whole = (total, limit) => ({
|
|
4
11
|
shown: total,
|
|
5
12
|
total,
|
|
@@ -7,50 +14,50 @@ const whole = (total, limit) => ({
|
|
|
7
14
|
truncated: false,
|
|
8
15
|
});
|
|
9
16
|
/** Flat list: slice to the limit; total is the full filtered length. */
|
|
10
|
-
export function
|
|
17
|
+
export function truncateList(items, limit) {
|
|
11
18
|
const total = items.length;
|
|
12
19
|
if (limit === null || total <= limit)
|
|
13
|
-
return { data: items,
|
|
20
|
+
return { data: items, truncation: whole(total, limit) };
|
|
14
21
|
return {
|
|
15
22
|
data: items.slice(0, limit),
|
|
16
|
-
|
|
23
|
+
truncation: { shown: limit, total, limit, truncated: true },
|
|
17
24
|
};
|
|
18
25
|
}
|
|
19
26
|
/**
|
|
20
27
|
* Today split: the cut runs across Today then This Evening in render order,
|
|
21
28
|
* so a limit smaller than the Today block trims Evening to nothing. The badge
|
|
22
|
-
* (a whole-view count summary) is preserved unchanged.
|
|
29
|
+
* (a whole-view count summary) is preserved unchanged. The truncation carries
|
|
30
|
+
* a per-section (`today`/`evening`) shown/total breakdown so a renderer can
|
|
31
|
+
* keep This Evening honest under the single global cap without a pre-cap copy.
|
|
23
32
|
*/
|
|
24
|
-
export function
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
33
|
+
export function truncateToday(view, limit) {
|
|
34
|
+
const todayTotal = view.today.length;
|
|
35
|
+
const eveningTotal = view.evening.length;
|
|
36
|
+
const total = todayTotal + eveningTotal;
|
|
37
|
+
const sections = (shownToday, shownEvening) => [
|
|
38
|
+
{ key: "today", shown: shownToday, total: todayTotal },
|
|
39
|
+
{ key: "evening", shown: shownEvening, total: eveningTotal },
|
|
40
|
+
];
|
|
41
|
+
if (limit === null || total <= limit) {
|
|
42
|
+
return {
|
|
43
|
+
data: view,
|
|
44
|
+
truncation: { ...whole(total, limit), sections: sections(todayTotal, eveningTotal) },
|
|
45
|
+
};
|
|
46
|
+
}
|
|
28
47
|
const today = view.today.slice(0, limit);
|
|
29
48
|
const evening = view.evening.slice(0, Math.max(0, limit - today.length));
|
|
30
49
|
const shown = today.length + evening.length;
|
|
31
50
|
return {
|
|
32
51
|
data: { today, evening, badge: view.badge },
|
|
33
|
-
|
|
52
|
+
truncation: {
|
|
53
|
+
shown,
|
|
54
|
+
total,
|
|
55
|
+
limit,
|
|
56
|
+
truncated: true,
|
|
57
|
+
sections: sections(today.length, evening.length),
|
|
58
|
+
},
|
|
34
59
|
};
|
|
35
60
|
}
|
|
36
|
-
export function splitSectionBlocks(section) {
|
|
37
|
-
const direct = [];
|
|
38
|
-
const projects = [];
|
|
39
|
-
let cur = null;
|
|
40
|
-
for (const item of section.items) {
|
|
41
|
-
if (item.type === "project") {
|
|
42
|
-
cur = { project: item, items: [] };
|
|
43
|
-
projects.push(cur);
|
|
44
|
-
}
|
|
45
|
-
else if (cur === null) {
|
|
46
|
-
direct.push(item);
|
|
47
|
-
}
|
|
48
|
-
else {
|
|
49
|
-
cur.items.push(item);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
return { direct, projects };
|
|
53
|
-
}
|
|
54
61
|
const takeUpTo = (items, limit) => limit === null ? items : items.slice(0, limit);
|
|
55
62
|
/**
|
|
56
63
|
* Anytime: the block skeleton is ALWAYS complete — every area header and
|
|
@@ -67,57 +74,42 @@ export function previewSections(sections, limits) {
|
|
|
67
74
|
for (const section of sections) {
|
|
68
75
|
const { direct, projects } = splitSectionBlocks(section);
|
|
69
76
|
const shownDirect = takeUpTo(direct, limits.area);
|
|
70
|
-
if (direct.length >
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
kind: section.area === null ? "loose" : "area",
|
|
75
|
-
uuid: section.area?.uuid ?? null,
|
|
76
|
-
title: section.area?.title ?? null,
|
|
77
|
-
shown: shownDirect.length,
|
|
78
|
-
total: direct.length,
|
|
79
|
-
limit: limits.area,
|
|
80
|
-
});
|
|
81
|
-
}
|
|
77
|
+
if (direct.length > shownDirect.length)
|
|
78
|
+
truncated = true;
|
|
79
|
+
// Project item-lists nest inside their area/loose block.
|
|
80
|
+
const children = [];
|
|
82
81
|
const items = [...shownDirect];
|
|
83
|
-
for (const { project, items:
|
|
84
|
-
const shownChildren = takeUpTo(
|
|
85
|
-
if (
|
|
86
|
-
if (
|
|
82
|
+
for (const { project, items: kids } of projects) {
|
|
83
|
+
const shownChildren = takeUpTo(kids, limits.project);
|
|
84
|
+
if (kids.length > 0) {
|
|
85
|
+
if (kids.length > shownChildren.length)
|
|
87
86
|
truncated = true;
|
|
88
|
-
|
|
87
|
+
children.push({
|
|
89
88
|
kind: "project",
|
|
90
|
-
|
|
89
|
+
ref: project.uuid,
|
|
91
90
|
title: project.title,
|
|
92
91
|
shown: shownChildren.length,
|
|
93
|
-
total:
|
|
92
|
+
total: kids.length,
|
|
94
93
|
limit: limits.project,
|
|
95
94
|
});
|
|
96
95
|
}
|
|
97
96
|
items.push(project, ...shownChildren);
|
|
98
97
|
}
|
|
98
|
+
if (direct.length > 0 || children.length > 0) {
|
|
99
|
+
blocks.push({
|
|
100
|
+
kind: section.area === null ? "loose" : "area",
|
|
101
|
+
ref: section.area?.uuid ?? null,
|
|
102
|
+
title: section.area?.title ?? null,
|
|
103
|
+
shown: shownDirect.length,
|
|
104
|
+
total: direct.length,
|
|
105
|
+
limit: limits.area,
|
|
106
|
+
...(children.length > 0 && { children }),
|
|
107
|
+
});
|
|
108
|
+
}
|
|
99
109
|
outSections.push({ area: section.area, items });
|
|
100
110
|
}
|
|
101
111
|
return { data: outSections, grouped: { truncated, blocks } };
|
|
102
112
|
}
|
|
103
|
-
export function partitionSomedaySection(section) {
|
|
104
|
-
const own = [];
|
|
105
|
-
const byProject = new Map();
|
|
106
|
-
for (const item of section.items) {
|
|
107
|
-
const container = item.type === "to-do" ? (item.project ?? item.headingProject ?? null) : null;
|
|
108
|
-
if (container === null) {
|
|
109
|
-
own.push(item);
|
|
110
|
-
continue;
|
|
111
|
-
}
|
|
112
|
-
let group = byProject.get(container.uuid);
|
|
113
|
-
if (group === undefined) {
|
|
114
|
-
group = { project: container, items: [] };
|
|
115
|
-
byProject.set(container.uuid, group);
|
|
116
|
-
}
|
|
117
|
-
group.items.push(item);
|
|
118
|
-
}
|
|
119
|
-
return { own, children: [...byProject.values()] };
|
|
120
|
-
}
|
|
121
113
|
/**
|
|
122
114
|
* Someday preview: every group survives; `limits.area` (null = no cap)
|
|
123
115
|
* applies independently to each section's own block (project rows + direct
|
|
@@ -132,29 +124,18 @@ export function previewSomedaySections(sections, limits) {
|
|
|
132
124
|
for (const section of sections) {
|
|
133
125
|
const { own, children } = partitionSomedaySection(section);
|
|
134
126
|
const shownOwn = takeUpTo(own, limits.area);
|
|
135
|
-
if (own.length >
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
blocks.push({
|
|
140
|
-
kind: section.area === null ? "loose" : "area",
|
|
141
|
-
uuid: section.area?.uuid ?? null,
|
|
142
|
-
title: section.area?.title ?? null,
|
|
143
|
-
shown: shownOwn.length,
|
|
144
|
-
total: own.length,
|
|
145
|
-
limit: limits.area,
|
|
146
|
-
totalProjects,
|
|
147
|
-
totalTodos: own.length - totalProjects,
|
|
148
|
-
});
|
|
149
|
-
}
|
|
127
|
+
if (own.length > shownOwn.length)
|
|
128
|
+
truncated = true;
|
|
129
|
+
// The active-project child groups nest inside this section's own block.
|
|
130
|
+
const childBlocks = [];
|
|
150
131
|
const items = [...shownOwn];
|
|
151
132
|
for (const group of children) {
|
|
152
133
|
const shown = takeUpTo(group.items, limits.project);
|
|
153
134
|
if (group.items.length > shown.length)
|
|
154
135
|
truncated = true;
|
|
155
|
-
|
|
136
|
+
childBlocks.push({
|
|
156
137
|
kind: "project",
|
|
157
|
-
|
|
138
|
+
ref: group.project.uuid,
|
|
158
139
|
title: group.project.title,
|
|
159
140
|
shown: shown.length,
|
|
160
141
|
total: group.items.length,
|
|
@@ -162,6 +143,20 @@ export function previewSomedaySections(sections, limits) {
|
|
|
162
143
|
});
|
|
163
144
|
items.push(...shown);
|
|
164
145
|
}
|
|
146
|
+
if (own.length > 0 || childBlocks.length > 0) {
|
|
147
|
+
const totalProjects = own.filter((i) => i.type === "project").length;
|
|
148
|
+
blocks.push({
|
|
149
|
+
kind: section.area === null ? "loose" : "area",
|
|
150
|
+
ref: section.area?.uuid ?? null,
|
|
151
|
+
title: section.area?.title ?? null,
|
|
152
|
+
shown: shownOwn.length,
|
|
153
|
+
total: own.length,
|
|
154
|
+
limit: limits.area,
|
|
155
|
+
totalProjects,
|
|
156
|
+
totalTodos: own.length - totalProjects,
|
|
157
|
+
...(childBlocks.length > 0 && { children: childBlocks }),
|
|
158
|
+
});
|
|
159
|
+
}
|
|
165
160
|
outSections.push({ area: section.area, items });
|
|
166
161
|
}
|
|
167
162
|
return { data: outSections, grouped: { truncated, blocks } };
|
|
@@ -169,24 +164,38 @@ export function previewSomedaySections(sections, limits) {
|
|
|
169
164
|
/**
|
|
170
165
|
* Sectioned cap for the `area show` detail view: its sections are containers,
|
|
171
166
|
* so there is no strict total limit — instead `limits.project` bounds the
|
|
172
|
-
* project-ROWS section and `limits.area` the direct-to-dos section
|
|
173
|
-
* uncapped). The
|
|
174
|
-
*
|
|
175
|
-
*
|
|
167
|
+
* ACTIVE project-ROWS section and `limits.area` the direct-to-dos section
|
|
168
|
+
* (null = uncapped). The cap is render-aware: only the area's ACTIVE project
|
|
169
|
+
* rows are capped, while its future-scheduled and someday project rows always
|
|
170
|
+
* survive (the card renders them under its uncapped Upcoming/Someday sections),
|
|
171
|
+
* so the human view derives entirely from this bounded shape. The toggled
|
|
172
|
+
* later/logged lists and the trashed bucket pass through untouched. Counts ride
|
|
173
|
+
* the same grouped-block shape the sidebar catalogues emit (kind "projects" =
|
|
174
|
+
* the active project-rows section). `now` classifies the schedule split.
|
|
176
175
|
*/
|
|
177
|
-
export function capAreaSections(view, limits) {
|
|
176
|
+
export function capAreaSections(view, limits, now) {
|
|
177
|
+
const todayIso = localToday(now);
|
|
178
178
|
const blocks = [];
|
|
179
179
|
let truncated = false;
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
180
|
+
// Cap the ACTIVE project rows in place; scheduled/someday rows always survive.
|
|
181
|
+
const activeTotal = view.projects.filter((p) => isActiveProjectRow(p, todayIso)).length;
|
|
182
|
+
const shownActive = limits.project === null ? activeTotal : Math.min(activeTotal, limits.project);
|
|
183
|
+
let activeSeen = 0;
|
|
184
|
+
const projects = view.projects.filter((p) => {
|
|
185
|
+
if (!isActiveProjectRow(p, todayIso))
|
|
186
|
+
return true;
|
|
187
|
+
activeSeen += 1;
|
|
188
|
+
return limits.project === null || activeSeen <= limits.project;
|
|
189
|
+
});
|
|
190
|
+
if (activeTotal > 0) {
|
|
191
|
+
if (shownActive < activeTotal)
|
|
183
192
|
truncated = true;
|
|
184
193
|
blocks.push({
|
|
185
194
|
kind: "projects",
|
|
186
|
-
|
|
195
|
+
ref: view.area.uuid,
|
|
187
196
|
title: view.area.title,
|
|
188
|
-
shown:
|
|
189
|
-
total:
|
|
197
|
+
shown: shownActive,
|
|
198
|
+
total: activeTotal,
|
|
190
199
|
limit: limits.project,
|
|
191
200
|
});
|
|
192
201
|
}
|
|
@@ -196,7 +205,7 @@ export function capAreaSections(view, limits) {
|
|
|
196
205
|
truncated = true;
|
|
197
206
|
blocks.push({
|
|
198
207
|
kind: "area",
|
|
199
|
-
|
|
208
|
+
ref: view.area.uuid,
|
|
200
209
|
title: view.area.title,
|
|
201
210
|
shown: active.length,
|
|
202
211
|
total: view.active.length,
|
|
@@ -205,4 +214,4 @@ export function capAreaSections(view, limits) {
|
|
|
205
214
|
}
|
|
206
215
|
return { data: { ...view, projects, active }, grouped: { truncated, blocks } };
|
|
207
216
|
}
|
|
208
|
-
//# sourceMappingURL=
|
|
217
|
+
//# sourceMappingURL=truncation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"truncation.js","sourceRoot":"","sources":["../../src/read/truncation.ts"],"names":[],"mappings":"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"}
|
package/dist/read/views.d.ts
CHANGED
|
@@ -20,7 +20,18 @@
|
|
|
20
20
|
* overdue bucket=1 items roll back into Today proper (live-
|
|
21
21
|
* verified against the UI, 2026-07-02).
|
|
22
22
|
* Sidebar badge split: red = items with deadline <= today,
|
|
23
|
-
* gray = the rest (exact 270/122 reconciliation on live data).
|
|
23
|
+
* gray = the rest (exact 270/122 reconciliation on live data). The
|
|
24
|
+
* badge counts OPEN members only — a checked-but-unswept row is in
|
|
25
|
+
* the list but out of the count (the GUI badge is remaining work).
|
|
26
|
+
* CHECKED-BUT-UNSWEPT (GUI-parity ruling 2026-07-14, Mike — "this
|
|
27
|
+
* is the behavior of the Things GUI and I like it"): membership is
|
|
28
|
+
* OPEN_OR_UNSWEPT, not OPEN — a completed/canceled row the log-move
|
|
29
|
+
* sweep has NOT yet passed (completion ≠ logged; see
|
|
30
|
+
* log-boundary.ts) stays in Today IN PLACE, keeping the exact
|
|
31
|
+
* comparator slot (startBucket / referenceDate / todayIndex) it held
|
|
32
|
+
* open. It leaves when the sweep boundary advances past its stopDate
|
|
33
|
+
* (boundary-relative, no new state). Mixed-context resolved styling
|
|
34
|
+
* (dim / dim+strike) applies automatically in formatItem.
|
|
24
35
|
* - anytime: ALL active items — unscheduled PLUS Today members (the UI
|
|
25
36
|
* renders Today members with a star; live-verified via screenshot
|
|
26
37
|
* 2026-07-02: starred = in Today, unstarred = unscheduled).
|
|
@@ -29,7 +40,29 @@
|
|
|
29
40
|
* project that is not itself anytime-visible (someday/future/
|
|
30
41
|
* logged/trashed) are excluded — the project row represents
|
|
31
42
|
* them. Result is grouped in sidebar order (SidebarSection[]).
|
|
32
|
-
* -
|
|
43
|
+
* CHECKED-BUT-UNSWEPT (GUI-parity ruling 2026-07-14, Mike): like
|
|
44
|
+
* Today, membership is OPEN_OR_UNSWEPT — a closed row the sweep has
|
|
45
|
+
* not passed keeps its index slot until the boundary moves past its
|
|
46
|
+
* stopDate. A closed-but-unswept PROJECT row shows in place and its
|
|
47
|
+
* children stay cascade-excluded (PROJECT_ANYTIME_ACTIVE still tests
|
|
48
|
+
* p.status = 0): the checked project row represents its children,
|
|
49
|
+
* the same precedent as a logged/someday container.
|
|
50
|
+
* - upcoming: TWO cohorts merged, grouped/sorted by COALESCE(startDate,
|
|
51
|
+
* deadline) (UPC1, GUI-verified, docs/lab/upcoming-research.md):
|
|
52
|
+
* (1) SCHEDULED — start=2 AND startDate > today, grouped under its
|
|
53
|
+
* when-date (a deadline it also carries rides along as a flag);
|
|
54
|
+
* (2) DEADLINE-FORECAST — startDate IS NULL AND start IN (1, 2)
|
|
55
|
+
* AND deadline > today AND (deadlineSuppressionDate IS NULL OR
|
|
56
|
+
* deadlineSuppressionDate < deadline), grouped under its DEADLINE
|
|
57
|
+
* date (both to-dos and projects). INBOX (start=0) is EXCLUDED — a
|
|
58
|
+
* future deadline does not forecast an Inbox item into Upcoming,
|
|
59
|
+
* though a DUE one still pulls it into Today. The suppression guard
|
|
60
|
+
* drops a dismissed-nag deadline (supp == deadline) and lets a
|
|
61
|
+
* re-armed one (supp < deadline) reappear — the todayView clause
|
|
62
|
+
* one step earlier (deadline > today). A when+deadline row appears
|
|
63
|
+
* ONCE under its when-date, never double-emitted (the forecast
|
|
64
|
+
* cohort requires startDate IS NULL). Forecast rows keep
|
|
65
|
+
* startDate=null (no faked when-date). PLUS each fixed repeating
|
|
33
66
|
* template's next occurrence synthesized from
|
|
34
67
|
* rt1_nextInstanceStartDate (UI parity; opt out via
|
|
35
68
|
* repeats:false). Occurrence deadline = start − rule.ts
|
|
@@ -53,18 +86,76 @@ export type ListItem = Todo | Project;
|
|
|
53
86
|
/** Optional list-view filters. */
|
|
54
87
|
export interface ViewFilter {
|
|
55
88
|
/**
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
* child-tagged items; not lab-oracled).
|
|
89
|
+
* Convenience shorthand for a single-element {@link tags} — a lone
|
|
90
|
+
* inheritance-inclusive tag ref. Production surfaces (CLI `--tag`, MCP
|
|
91
|
+
* `tag`) always pass the array form; this exists for internal/test callers.
|
|
60
92
|
*/
|
|
61
93
|
tag?: string;
|
|
62
94
|
/**
|
|
63
|
-
*
|
|
95
|
+
* Tag refs (uuid or unique title). In FLAT views (today/inbox/anytime/
|
|
96
|
+
* someday/upcoming/search/logbook) this is direct OR inherited membership (UI
|
|
97
|
+
* semantics), INCLUDING items tagged with a hierarchy descendant of each
|
|
98
|
+
* given tag (documented app behavior — the UI's tag filter matches
|
|
99
|
+
* child-tagged items; not lab-oracled). In CONTAINER views (`project show`,
|
|
100
|
+
* `area show`, the `projects` list) the same ref instead matches rows carrying
|
|
101
|
+
* the tag DIRECTLY (still with descendant expansion) — the view's own
|
|
102
|
+
* container-inheritance hop is suppressed, since every child inherits the
|
|
103
|
+
* container's tags and an inheritance-inclusive filter there is vacuous. The
|
|
104
|
+
* host view selects the behavior via {@link tagFilter}'s `container` option.
|
|
105
|
+
* Multiple refs AND together — an item must match EVERY ref (each
|
|
106
|
+
* independently expanded to its descendant set, OR-matched within,
|
|
107
|
+
* AND-combined across).
|
|
108
|
+
*/
|
|
109
|
+
tags?: string[];
|
|
110
|
+
/**
|
|
111
|
+
* Match each given tag ref ONLY — no hierarchy descendants. Useful when a
|
|
64
112
|
* parent tag has its own direct assignments distinct from its children's.
|
|
65
113
|
*/
|
|
66
114
|
exactTag?: boolean;
|
|
115
|
+
/**
|
|
116
|
+
* Only items with NO tag (the GUI's "No Tag"). In FLAT views this negates the
|
|
117
|
+
* WHOLE direct+inherited membership relation — an item is untagged iff no
|
|
118
|
+
* possible `tag` value could ever match it. In CONTAINER views it instead
|
|
119
|
+
* means "no DIRECT tag" (the container's own inherited tags are suppressed,
|
|
120
|
+
* matching the container `tag` semantics). Mutually exclusive with
|
|
121
|
+
* `tag`/`exactTag` (the surfaces reject the combination).
|
|
122
|
+
*/
|
|
123
|
+
untagged?: boolean;
|
|
124
|
+
/**
|
|
125
|
+
* Only OPEN items whose deadline is strictly BEFORE today (due-today is NOT
|
|
126
|
+
* overdue — it mirrors the app's Today badge, where an equal-to-today
|
|
127
|
+
* deadline is "due" and only an earlier one is "overdue"). A content scope
|
|
128
|
+
* like `tag`: it narrows, never lifts a default, and composes as AND with
|
|
129
|
+
* `tag`/`untagged`. The boundary rides the view's injected clock (see
|
|
130
|
+
* {@link OVERDUE}). Honored by the current-work views (today, inbox, anytime,
|
|
131
|
+
* someday, search); the forward-looking `upcoming` and the closed-item
|
|
132
|
+
* `logbook` deliberately do not accept it (see docs/design/cli-grammar.md).
|
|
133
|
+
*/
|
|
134
|
+
overdue?: boolean;
|
|
67
135
|
}
|
|
136
|
+
/**
|
|
137
|
+
* Compose the tag scope for a filter into an AND-chained SQL fragment plus its
|
|
138
|
+
* binds. Every clause AND-combines: the `untagged` negation and each `--tag`
|
|
139
|
+
* ref (each ref independently resolved and descendant-expanded per `exactTag`).
|
|
140
|
+
* The mutually-exclusive combination (`untagged` with a tag-presence flag) is
|
|
141
|
+
* refused at the CLI/MCP surfaces; here it would simply AND to an empty result.
|
|
142
|
+
* Splices in before {@link overdueFilter} so the tag binds precede the overdue
|
|
143
|
+
* bind.
|
|
144
|
+
*
|
|
145
|
+
* `options.container` selects the CONTAINER semantics (`project show` /
|
|
146
|
+
* `area show` / the `projects` list): the view's own inheritance hop is dropped,
|
|
147
|
+
* so `--tag` matches a DIRECT assignment (still descendant-expanded) and
|
|
148
|
+
* `--untagged` means "no direct tag". Every child inherits its container's tags,
|
|
149
|
+
* so an inheritance-inclusive filter there is vacuous — direct-on-the-row is the
|
|
150
|
+
* useful, GUI-faithful behavior. FLAT views omit the option and keep the
|
|
151
|
+
* inheritance-inclusive relation.
|
|
152
|
+
*/
|
|
153
|
+
export declare function tagFilter(db: DatabaseSync, filter: ViewFilter | undefined, options?: {
|
|
154
|
+
container?: boolean;
|
|
155
|
+
}): {
|
|
156
|
+
sql: string;
|
|
157
|
+
binds: string[];
|
|
158
|
+
};
|
|
68
159
|
export interface TodayView {
|
|
69
160
|
today: ListItem[];
|
|
70
161
|
evening: ListItem[];
|
|
@@ -74,8 +165,28 @@ export interface TodayView {
|
|
|
74
165
|
other: number;
|
|
75
166
|
};
|
|
76
167
|
}
|
|
77
|
-
export
|
|
78
|
-
|
|
168
|
+
export interface TodayFilter extends ViewFilter {
|
|
169
|
+
/**
|
|
170
|
+
* Restrict to the This-Evening section: the Today section is filtered out
|
|
171
|
+
* (returned empty) and the badge counts only the evening members. A section
|
|
172
|
+
* visibility toggle, not a volume change — the row limit still applies.
|
|
173
|
+
*/
|
|
174
|
+
eveningOnly?: boolean;
|
|
175
|
+
}
|
|
176
|
+
export declare function todayView(db: DatabaseSync, now?: Date, filter?: TodayFilter): TodayView;
|
|
177
|
+
export interface InboxFilter extends ViewFilter {
|
|
178
|
+
/**
|
|
179
|
+
* Only captures created at/after this instant. Keyed on the item's CREATION
|
|
180
|
+
* timestamp (the raw Cocoa/Unix-epoch creationDate, compared like
|
|
181
|
+
* `changes`/`logbook` do their epoch columns — NOT the packed startDate
|
|
182
|
+
* encoding). A demoted item keeps its original creation date, so this is
|
|
183
|
+
* arrival-into-Things, not arrival-into-the-Inbox.
|
|
184
|
+
*/
|
|
185
|
+
since?: Date;
|
|
186
|
+
/** Only captures created at/before this instant (creation timestamp). */
|
|
187
|
+
until?: Date;
|
|
188
|
+
}
|
|
189
|
+
export declare function inboxView(db: DatabaseSync, now?: Date, filter?: InboxFilter): ListItem[];
|
|
79
190
|
/**
|
|
80
191
|
* One sidebar-ordered block of a grouped view (anytime/someday): the area
|
|
81
192
|
* (null = the top-level, area-less block, which the UI renders first) and its
|
|
@@ -87,7 +198,19 @@ export interface SidebarSection {
|
|
|
87
198
|
items: ListItem[];
|
|
88
199
|
}
|
|
89
200
|
export declare function anytimeView(db: DatabaseSync, now?: Date, filter?: ViewFilter): SidebarSection[];
|
|
90
|
-
/**
|
|
201
|
+
/**
|
|
202
|
+
* The UI's star marker in Anytime: the item is also a Today member. Mirrors
|
|
203
|
+
* {@link todayView}'s two membership arms so an unscheduled item pulled into
|
|
204
|
+
* Today by a due deadline stars exactly like a scheduled one:
|
|
205
|
+
* - SCHEDULED — a When-date that has arrived (startDate <= today); or
|
|
206
|
+
* - DEADLINE-DRIVEN — no When-date, but a due/overdue deadline (deadline <=
|
|
207
|
+
* today) pulls it into Today (the todayView arm that lets a bare deadline
|
|
208
|
+
* surface an item). Only reached for anytime-visible rows (start=1,
|
|
209
|
+
* startDate NULL), so it never over-stars someday/inbox rows.
|
|
210
|
+
* KNOWN LIMITATION: todayView's deadline arm also drops a DISMISSED-nag
|
|
211
|
+
* deadline (deadlineSuppressionDate >= deadline); that column is not surfaced
|
|
212
|
+
* on the entity, so a suppressed unscheduled overdue row is over-starred here.
|
|
213
|
+
*/
|
|
91
214
|
export declare function isTodayMember(item: ListItem, now?: Date): boolean;
|
|
92
215
|
export interface UpcomingFilter extends ViewFilter {
|
|
93
216
|
/** Include repeating templates' next occurrences (UI parity; default true). */
|
|
@@ -140,15 +263,16 @@ export interface LogbookFilter extends ViewFilter {
|
|
|
140
263
|
/** Only entries logged at/before this instant. */
|
|
141
264
|
until?: Date;
|
|
142
265
|
}
|
|
143
|
-
export declare function logbookView(db: DatabaseSync, options?: LogbookFilter): ListItem[];
|
|
144
|
-
export declare function trashView(db: DatabaseSync, options?: {
|
|
266
|
+
export declare function logbookView(db: DatabaseSync, now?: Date, options?: LogbookFilter): ListItem[];
|
|
267
|
+
export declare function trashView(db: DatabaseSync, now?: Date, options?: {
|
|
145
268
|
limit?: number | null;
|
|
146
269
|
}): ListItem[];
|
|
147
270
|
export declare function projectsView(db: DatabaseSync, options?: {
|
|
148
271
|
areaUuid?: string;
|
|
149
272
|
later?: boolean;
|
|
273
|
+
overdue?: boolean;
|
|
150
274
|
now?: Date;
|
|
151
|
-
}): Project[];
|
|
275
|
+
} & ViewFilter): Project[];
|
|
152
276
|
export interface SearchOptions extends ViewFilter {
|
|
153
277
|
/** Row cap; `null` returns every match (surfaces slice for display). */
|
|
154
278
|
limit?: number | null;
|
|
@@ -176,7 +300,7 @@ export type ChangedItem = ListItem & {
|
|
|
176
300
|
* carry no modification dates, and checklist-item edits do not bump the
|
|
177
301
|
* parent task — those changes are invisible here.
|
|
178
302
|
*/
|
|
179
|
-
export declare function changesView(db: DatabaseSync, options: {
|
|
303
|
+
export declare function changesView(db: DatabaseSync, now: Date | undefined, options: {
|
|
180
304
|
since: Date;
|
|
181
305
|
limit?: number | null;
|
|
182
306
|
}): ChangedItem[];
|
|
@@ -197,7 +321,7 @@ export interface LiteSearchResult {
|
|
|
197
321
|
export declare function liteTitleSearch(db: DatabaseSync, query: string, options?: {
|
|
198
322
|
type?: "to-do" | "project" | "area";
|
|
199
323
|
limit?: number;
|
|
200
|
-
}): LiteSearchResult;
|
|
324
|
+
}, now?: Date): LiteSearchResult;
|
|
201
325
|
/** A search result annotated with WHY it surfaced (additive; `matchedVia` present only for heading-credited projects). */
|
|
202
326
|
export type SearchResultItem = ListItem & {
|
|
203
327
|
matchedVia?: {
|
|
@@ -205,4 +329,4 @@ export type SearchResultItem = ListItem & {
|
|
|
205
329
|
title: string;
|
|
206
330
|
};
|
|
207
331
|
};
|
|
208
|
-
export declare function searchView(db: DatabaseSync, query: string, options?: SearchOptions): SearchResultItem[];
|
|
332
|
+
export declare function searchView(db: DatabaseSync, query: string, options?: SearchOptions, now?: Date): SearchResultItem[];
|