things-api 0.11.0 → 0.13.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 +16 -5
- package/dist/audit/schema.d.ts +7 -0
- package/dist/audit/schema.js.map +1 -1
- package/dist/cli/canonical-ref.d.ts +21 -0
- package/dist/cli/canonical-ref.js +23 -0
- package/dist/cli/canonical-ref.js.map +1 -0
- package/dist/cli/commands/area.d.ts +18 -11
- package/dist/cli/commands/area.js +81 -77
- package/dist/cli/commands/area.js.map +1 -1
- package/dist/cli/commands/doctor.d.ts +1 -2
- package/dist/cli/commands/doctor.js +11 -1
- package/dist/cli/commands/doctor.js.map +1 -1
- package/dist/cli/commands/install-skill.d.ts +19 -4
- package/dist/cli/commands/install-skill.js +130 -52
- package/dist/cli/commands/install-skill.js.map +1 -1
- package/dist/cli/commands/mcp.js +21 -1
- package/dist/cli/commands/mcp.js.map +1 -1
- package/dist/cli/commands/project.d.ts +1 -0
- package/dist/cli/commands/project.js +92 -48
- package/dist/cli/commands/project.js.map +1 -1
- package/dist/cli/commands/reads.d.ts +5 -1
- package/dist/cli/commands/reads.js +110 -31
- package/dist/cli/commands/reads.js.map +1 -1
- package/dist/cli/commands/setup.js +11 -4
- package/dist/cli/commands/setup.js.map +1 -1
- package/dist/cli/commands/show.js +75 -36
- package/dist/cli/commands/show.js.map +1 -1
- package/dist/cli/commands/todo.js +2 -2
- package/dist/cli/commands/todo.js.map +1 -1
- package/dist/cli/commands/writes.js +795 -144
- package/dist/cli/commands/writes.js.map +1 -1
- package/dist/cli/did-you-mean.d.ts +14 -3
- package/dist/cli/did-you-mean.js +44 -7
- package/dist/cli/did-you-mean.js.map +1 -1
- package/dist/cli/dry-run.d.ts +55 -0
- package/dist/cli/dry-run.js +92 -0
- package/dist/cli/dry-run.js.map +1 -0
- package/dist/cli/glyphs.d.ts +16 -2
- package/dist/cli/glyphs.js +60 -12
- package/dist/cli/glyphs.js.map +1 -1
- package/dist/cli/help.js +69 -13
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/main.js +8 -1
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/move-hint.d.ts +3 -2
- package/dist/cli/move-hint.js +2 -2
- package/dist/cli/move-hint.js.map +1 -1
- package/dist/cli/read-driver.d.ts +53 -5
- package/dist/cli/read-driver.js +82 -15
- package/dist/cli/read-driver.js.map +1 -1
- package/dist/cli/ref-render.d.ts +14 -0
- package/dist/cli/ref-render.js +9 -0
- package/dist/cli/ref-render.js.map +1 -0
- package/dist/cli/render.d.ts +40 -14
- package/dist/cli/render.js +128 -55
- package/dist/cli/render.js.map +1 -1
- package/dist/cli/resolve-invocation.d.ts +7 -5
- package/dist/cli/resolve-invocation.js +16 -7
- package/dist/cli/resolve-invocation.js.map +1 -1
- package/dist/cli/skill-check.d.ts +12 -6
- package/dist/cli/skill-check.js +31 -14
- package/dist/cli/skill-check.js.map +1 -1
- package/dist/cli/skill.d.ts +8 -0
- package/dist/cli/skill.js +10 -0
- package/dist/cli/skill.js.map +1 -1
- package/dist/cli/verb-hint.js +1 -1
- package/dist/cli/verb-hint.js.map +1 -1
- package/dist/client.d.ts +158 -26
- package/dist/client.js +254 -38
- package/dist/client.js.map +1 -1
- package/dist/config.d.ts +66 -2
- package/dist/config.js +120 -12
- package/dist/config.js.map +1 -1
- package/dist/contracts.d.ts +187 -28
- package/dist/contracts.js +22 -1
- package/dist/contracts.js.map +1 -1
- package/dist/db/baselines/db-v26.js +4 -1
- package/dist/db/baselines/db-v26.js.map +1 -1
- package/dist/diagnose.d.ts +34 -2
- package/dist/diagnose.js +36 -1
- package/dist/diagnose.js.map +1 -1
- package/dist/index.d.ts +21 -8
- package/dist/index.js +26 -3
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.d.ts +9 -0
- package/dist/mcp/server.js +790 -322
- package/dist/mcp/server.js.map +1 -1
- package/dist/model/entities.d.ts +57 -4
- package/dist/model/entities.js.map +1 -1
- package/dist/model/mappers.d.ts +2 -0
- package/dist/model/mappers.js +44 -2
- package/dist/model/mappers.js.map +1 -1
- package/dist/model/recurrence.d.ts +8 -1
- package/dist/model/recurrence.js.map +1 -1
- package/dist/model/serialize.js +15 -3
- package/dist/model/serialize.js.map +1 -1
- package/dist/read/area-filter.d.ts +76 -0
- package/dist/read/area-filter.js +58 -0
- package/dist/read/area-filter.js.map +1 -0
- package/dist/read/area-view.d.ts +22 -11
- package/dist/read/area-view.js +54 -28
- package/dist/read/area-view.js.map +1 -1
- package/dist/read/detail.js +15 -8
- package/dist/read/detail.js.map +1 -1
- package/dist/read/predicates.d.ts +18 -0
- package/dist/read/predicates.js +19 -0
- package/dist/read/predicates.js.map +1 -1
- package/dist/read/project-view.d.ts +91 -15
- package/dist/read/project-view.js +135 -37
- package/dist/read/project-view.js.map +1 -1
- package/dist/read/pseudo-area.d.ts +29 -0
- package/dist/read/pseudo-area.js +27 -0
- package/dist/read/pseudo-area.js.map +1 -0
- package/dist/read/queries.d.ts +175 -19
- package/dist/read/queries.js +376 -32
- package/dist/read/queries.js.map +1 -1
- package/dist/read/scope.d.ts +126 -0
- package/dist/read/scope.js +161 -0
- package/dist/read/scope.js.map +1 -0
- package/dist/read/search-rank.d.ts +2 -5
- package/dist/read/shape.d.ts +181 -0
- package/dist/read/shape.js +737 -0
- package/dist/read/shape.js.map +1 -0
- package/dist/read/show-target.d.ts +9 -1
- package/dist/read/show-target.js +77 -17
- package/dist/read/show-target.js.map +1 -1
- package/dist/read/stage.d.ts +199 -0
- package/dist/read/stage.js +125 -0
- package/dist/read/stage.js.map +1 -0
- package/dist/read/truncation.d.ts +7 -12
- package/dist/read/truncation.js +56 -21
- package/dist/read/truncation.js.map +1 -1
- package/dist/read/views.d.ts +68 -16
- package/dist/read/views.js +206 -52
- package/dist/read/views.js.map +1 -1
- package/dist/surface-copy.d.ts +16 -0
- package/dist/surface-copy.js +16 -0
- package/dist/surface-copy.js.map +1 -1
- package/dist/write/batch.d.ts +49 -10
- package/dist/write/batch.js +423 -71
- package/dist/write/batch.js.map +1 -1
- package/dist/write/commands.js +268 -55
- package/dist/write/commands.js.map +1 -1
- package/dist/write/guards.d.ts +1 -1
- package/dist/write/guards.js +71 -10
- package/dist/write/guards.js.map +1 -1
- package/dist/write/heading.d.ts +10 -1
- package/dist/write/heading.js +35 -5
- package/dist/write/heading.js.map +1 -1
- package/dist/write/make-repeating-project.d.ts +2 -2
- package/dist/write/make-repeating-project.js +9 -9
- package/dist/write/make-repeating-project.js.map +1 -1
- package/dist/write/move.d.ts +134 -0
- package/dist/write/move.js +1874 -0
- package/dist/write/move.js.map +1 -0
- package/dist/write/operations.d.ts +105 -19
- package/dist/write/operations.js +56 -7
- package/dist/write/operations.js.map +1 -1
- package/dist/write/opid.d.ts +31 -0
- package/dist/write/opid.js +30 -0
- package/dist/write/opid.js.map +1 -0
- package/dist/write/pipeline.d.ts +70 -3
- package/dist/write/pipeline.js +198 -33
- package/dist/write/pipeline.js.map +1 -1
- package/dist/write/pre-state.d.ts +172 -8
- package/dist/write/pre-state.js +467 -25
- package/dist/write/pre-state.js.map +1 -1
- package/dist/write/reorder.d.ts +23 -3
- package/dist/write/reorder.js +2106 -86
- package/dist/write/reorder.js.map +1 -1
- package/dist/write/reversibility.js +19 -7
- package/dist/write/reversibility.js.map +1 -1
- package/dist/write/scope-guard.d.ts +31 -0
- package/dist/write/scope-guard.js +162 -0
- package/dist/write/scope-guard.js.map +1 -0
- package/dist/write/undo.js +120 -13
- package/dist/write/undo.js.map +1 -1
- package/dist/write/vectors/applescript.js +16 -7
- package/dist/write/vectors/applescript.js.map +1 -1
- package/dist/write/vectors/shortcuts.js +1 -1
- package/dist/write/vectors/shortcuts.js.map +1 -1
- package/dist/write/vectors/simulator.js +83 -27
- package/dist/write/vectors/simulator.js.map +1 -1
- package/dist/write/vectors/types.d.ts +11 -0
- package/dist/write/vectors/ui-certification.d.ts +3 -3
- package/dist/write/vectors/ui-certification.js +41 -5
- package/dist/write/vectors/ui-certification.js.map +1 -1
- package/dist/write/vectors/ui-drag.d.ts +21 -1
- package/dist/write/vectors/ui-drag.js +138 -27
- package/dist/write/vectors/ui-drag.js.map +1 -1
- package/dist/write/vectors/ui-recipes.d.ts +21 -1
- package/dist/write/vectors/ui-recipes.js +166 -7
- package/dist/write/vectors/ui-recipes.js.map +1 -1
- package/dist/write/vectors/ui.d.ts +25 -1
- package/dist/write/vectors/ui.js +142 -33
- package/dist/write/vectors/ui.js.map +1 -1
- package/dist/write/verify/delta.d.ts +17 -1
- package/dist/write/verify/delta.js +106 -29
- package/dist/write/verify/delta.js.map +1 -1
- package/package.json +7 -1
- package/schema/envelope.schema.json +397 -0
- package/skills/things-cli/SKILL.md +36 -17
- package/skills/things-cli/references/banner.md +35 -0
- package/skills/things-cli/references/contracts.md +32 -9
- package/skills/things-cli/references/errors.md +57 -0
- package/skills/things-cli/references/gui.md +1 -1
- package/skills/things-cli/references/model.md +18 -7
- package/skills/things-cli/references/ordering.md +88 -0
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Composite project view mirroring the native UI (validated T17 + "later
|
|
3
3
|
* items" findings): active items, headings with their children, later
|
|
4
|
-
* (scheduled by date / repeating templates / someday), logged
|
|
4
|
+
* (scheduled by date / repeating templates / someday), logged. Trashed
|
|
5
|
+
* children are excluded entirely (GUI-faithful — the app filters trashed
|
|
6
|
+
* children out of the project view, §6½/PLOG1-a).
|
|
5
7
|
*
|
|
6
8
|
* Child membership: `project = ? OR heading IN (project's headings)` — the
|
|
7
9
|
* DB invariant is that headed to-dos have project = NULL (atlas §TMTask).
|
|
@@ -10,24 +12,88 @@
|
|
|
10
12
|
import type { DatabaseSync } from "node:sqlite";
|
|
11
13
|
import type { Heading, IsoDateGroup, Project, Todo } from "../model/entities.ts";
|
|
12
14
|
import { type ViewFilter } from "./views.ts";
|
|
15
|
+
/**
|
|
16
|
+
* A heading group inside a project view. Mirrors the GUI: the heading owns its
|
|
17
|
+
* OWN display sub-buckets (§1 of the demotion/move design) — the anytime/current
|
|
18
|
+
* `items`, its future-dated `scheduled` children grouped per day, its resting
|
|
19
|
+
* `repeating` templates, and its `someday` children. The project-level buckets
|
|
20
|
+
* (below) hold ONLY the UNHEADED members; a headed child lives here, under its
|
|
21
|
+
* heading, never pooled at the project level.
|
|
22
|
+
*/
|
|
23
|
+
export interface ProjectHeadingGroup {
|
|
24
|
+
heading: Heading;
|
|
25
|
+
/** Open/current children under this heading, by index. */
|
|
26
|
+
items: Todo[];
|
|
27
|
+
/** This heading's future-dated children grouped by date ascending. */
|
|
28
|
+
scheduled: IsoDateGroup<Todo>[];
|
|
29
|
+
/** This heading's someday (incubated, undated) children. */
|
|
30
|
+
someday: Todo[];
|
|
31
|
+
/** This heading's repeating template rows (invisible in list views). */
|
|
32
|
+
repeating: Todo[];
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* An ARCHIVED heading rendered inside the logged region (HEADARC2-A). Unlike a
|
|
36
|
+
* live {@link ProjectHeadingGroup}, an archived heading is itself a logged item,
|
|
37
|
+
* and its children — ALL of them, whatever their own state — nest beneath it as
|
|
38
|
+
* a grouped section (most-recently-completed first). That includes any odd OPEN
|
|
39
|
+
* child a GUI "Put Back" left stranded under the archived heading (HEADARC2-C):
|
|
40
|
+
* the group renders what is there, it does NOT filter to status=3.
|
|
41
|
+
*/
|
|
42
|
+
export interface LoggedHeadingGroup {
|
|
43
|
+
/** The archived heading (status "completed"); the wire emits its `archived`. */
|
|
44
|
+
heading: Heading;
|
|
45
|
+
/** Every child of the archived heading, most-recently-completed first. */
|
|
46
|
+
items: Todo[];
|
|
47
|
+
}
|
|
13
48
|
export interface ProjectView {
|
|
14
49
|
project: Project;
|
|
15
|
-
/**
|
|
50
|
+
/**
|
|
51
|
+
* ALL live (non-logbook, non-trash) children of the project — unheaded AND
|
|
52
|
+
* headed — in project `index` order, each headed row carrying its `heading`
|
|
53
|
+
* ref (and `headingProject`). This is the flat wire representation (the read
|
|
54
|
+
* doctrine's project-view `items[]`): membership in a heading is a per-row
|
|
55
|
+
* attribute, not a bucket. The structured buckets below (`active`, `headings`,
|
|
56
|
+
* `scheduled`, …) are the SAME children re-grouped into the GUI's render layout
|
|
57
|
+
* for the TTY projection — the library owns the clock + `todayIndex`, so the
|
|
58
|
+
* renderer reconstructs the exact GUI placement from them without re-deriving
|
|
59
|
+
* dates. The two are always consistent (built from one child fetch).
|
|
60
|
+
*/
|
|
61
|
+
items: Todo[];
|
|
62
|
+
/**
|
|
63
|
+
* The full heading catalog — EVERY heading (live AND swept archived) in project
|
|
64
|
+
* `index` order (read-shape doctrine §3.12 / #C3). This is the flat wire
|
|
65
|
+
* representation of `headings[]` (`[{uuid,title,archived?}]`): which headings
|
|
66
|
+
* exist, in what order, and whether each is archived — the ORDER axis that
|
|
67
|
+
* earns the bucket its place. A live-group's row membership rides the flat
|
|
68
|
+
* `items[]` refs; a swept archived heading's children ride the flat `logbook`
|
|
69
|
+
* refs. The structured `headings` / `loggedHeadings` below re-group the SAME
|
|
70
|
+
* headings + children into the GUI render layout for the byte-stable TTY.
|
|
71
|
+
*/
|
|
72
|
+
headingCatalog: Heading[];
|
|
73
|
+
/** Open, unscheduled/current UNHEADED children, by index. */
|
|
16
74
|
active: Todo[];
|
|
17
|
-
/**
|
|
18
|
-
headings:
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
75
|
+
/** OPEN headings in project order, each with its own sub-buckets. An archived heading never renders here. */
|
|
76
|
+
headings: ProjectHeadingGroup[];
|
|
77
|
+
/** UNHEADED future-dated children grouped by date ascending. */
|
|
78
|
+
scheduled: IsoDateGroup<Todo>[];
|
|
79
|
+
/** UNHEADED someday (incubated, undated) children. */
|
|
80
|
+
someday: Todo[];
|
|
81
|
+
/** UNHEADED repeating template rows owned by this project (invisible in list views). */
|
|
82
|
+
repeating: Todo[];
|
|
83
|
+
/**
|
|
84
|
+
* The flat logged region: swept children of OPEN headings (each carrying its
|
|
85
|
+
* heading ref) plus swept un-headed children, most-recently-completed first.
|
|
86
|
+
* Children of ARCHIVED headings are NOT here — they group under their heading
|
|
87
|
+
* in {@link ProjectView.loggedHeadings}.
|
|
88
|
+
*/
|
|
29
89
|
logged: Todo[];
|
|
30
|
-
|
|
90
|
+
/**
|
|
91
|
+
* The archived-heading GROUPS of the logged region (HEADARC2-A), in project
|
|
92
|
+
* (heading `index`) order — each an archived heading with its children nested.
|
|
93
|
+
* Rendered only under `--show-logged`, after the flat {@link ProjectView.logged}
|
|
94
|
+
* rows (the flat-then-grouped ordering is a defensible choice, not GUI-probed).
|
|
95
|
+
*/
|
|
96
|
+
loggedHeadings: LoggedHeadingGroup[];
|
|
31
97
|
/**
|
|
32
98
|
* PLOG1 (additive): count of untrashed OPEN (status=0) children this project
|
|
33
99
|
* still holds while it is ITSELF completed or canceled — including once swept
|
|
@@ -38,6 +104,16 @@ export interface ProjectView {
|
|
|
38
104
|
* child.
|
|
39
105
|
*/
|
|
40
106
|
openChildrenWhileResolved: number;
|
|
107
|
+
/**
|
|
108
|
+
* HEADARC2-C (additive): count of untrashed OPEN (status=0) children buried
|
|
109
|
+
* under an ARCHIVED heading of this project — the heading analog of the §6¾
|
|
110
|
+
* odd state. The GUI's "Put Back" of a trashed open child restores it in place
|
|
111
|
+
* under the archived heading WITHOUT reopening the heading, leaving an open,
|
|
112
|
+
* actionable to-do invisible to every live view (reachable only by expanding
|
|
113
|
+
* this card's logged region). Counted regardless of the PROJECT's own status.
|
|
114
|
+
* 0 when no archived heading holds an open child.
|
|
115
|
+
*/
|
|
116
|
+
openChildrenUnderArchivedHeading: number;
|
|
41
117
|
}
|
|
42
118
|
export declare class ProjectNotFoundError extends Error {
|
|
43
119
|
constructor(uuid: string);
|
|
@@ -11,6 +11,24 @@ export class ProjectNotFoundError extends Error {
|
|
|
11
11
|
this.name = "ProjectNotFoundError";
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
|
+
/** Append `value` to the list at `key`, creating it on first use. */
|
|
15
|
+
function pushInto(map, key, value) {
|
|
16
|
+
const list = map.get(key) ?? [];
|
|
17
|
+
list.push(value);
|
|
18
|
+
map.set(key, list);
|
|
19
|
+
}
|
|
20
|
+
/** Group scheduled rows into per-day buckets (date ASC, within-day todayIndex ASC). */
|
|
21
|
+
function groupByDate(rows) {
|
|
22
|
+
const out = [];
|
|
23
|
+
for (const { date, todo } of rows.toSorted((a, b) => a.date.localeCompare(b.date) || a.ti - b.ti)) {
|
|
24
|
+
const last = out[out.length - 1];
|
|
25
|
+
if (last && last.date === date)
|
|
26
|
+
last.items.push(todo);
|
|
27
|
+
else
|
|
28
|
+
out.push({ date, items: [todo] });
|
|
29
|
+
}
|
|
30
|
+
return out;
|
|
31
|
+
}
|
|
14
32
|
export function projectView(db, uuid, now, filter = {}, zone) {
|
|
15
33
|
const overdue = filter.overdue === true;
|
|
16
34
|
const projectRow = fetchTaskByUuid(db, uuid);
|
|
@@ -43,7 +61,7 @@ export function projectView(db, uuid, now, filter = {}, zone) {
|
|
|
43
61
|
// the two uuid binds and lead the overdue bind, matching their left-to-right
|
|
44
62
|
// order in the SQL.
|
|
45
63
|
const tf = tagFilter(db, filter, { container: true });
|
|
46
|
-
const childRows = fetchTaskRows(db, `t.type = 0 AND (t.project = ? OR t.heading IN (
|
|
64
|
+
const childRows = fetchTaskRows(db, `t.type = 0 AND t.trashed = 0 AND (t.project = ? OR t.heading IN (
|
|
47
65
|
SELECT uuid FROM TMTask WHERE type = 2 AND project = ?
|
|
48
66
|
))${tf.sql}${overdueSql}
|
|
49
67
|
ORDER BY t."index" ASC`, [uuid, uuid, ...tf.binds, ...overdueBinds]);
|
|
@@ -54,24 +72,68 @@ export function projectView(db, uuid, now, filter = {}, zone) {
|
|
|
54
72
|
todo: mapTodo(r, refs, childTags.get(r.uuid) ?? [], packedToday),
|
|
55
73
|
}));
|
|
56
74
|
markLogged([project, ...todos.map((t) => t.todo)], boundary);
|
|
75
|
+
// TRINARY heading split (the completion≠logged law, applied to headings): an
|
|
76
|
+
// OPEN heading — or an archived one NOT yet past the log-move boundary — stays
|
|
77
|
+
// a LIVE group IN PLACE (an archived-unswept heading carries `archived` yet
|
|
78
|
+
// renders among the live groups, exactly as a completed-unswept to-do row
|
|
79
|
+
// stays checked in place, §above / log-boundary.ts). Only a SWEPT archived
|
|
80
|
+
// heading moves into the logged region as a grouped section (HEADARC2-A).
|
|
81
|
+
const headingSwept = (h) => h.status !== "open" && h.stopped !== null && h.stopped <= boundary;
|
|
82
|
+
const liveHeadings = headings.filter((h) => !headingSwept(h));
|
|
83
|
+
const sweptHeadings = headings.filter((h) => headingSwept(h));
|
|
84
|
+
const liveHeadingSet = new Set(liveHeadings.map((h) => h.uuid));
|
|
85
|
+
const sweptHeadingSet = new Set(sweptHeadings.map((h) => h.uuid));
|
|
86
|
+
// The owning-project ref stamped on every headed child — so the heading ref a
|
|
87
|
+
// flat logged row carries promotes its `headingUuid` in the project's scope
|
|
88
|
+
// (the round-trip predicate is project-scoped), mirroring the list views.
|
|
89
|
+
const projectRef = { uuid: project.uuid, title: project.title };
|
|
90
|
+
// Project-level (UNHEADED) buckets.
|
|
57
91
|
const active = [];
|
|
58
|
-
const byHeading = new Map();
|
|
59
92
|
const scheduledRows = [];
|
|
60
93
|
const repeating = [];
|
|
61
94
|
const someday = [];
|
|
62
95
|
const logged = [];
|
|
63
|
-
|
|
96
|
+
// Children of a SWEPT archived heading — grouped under their heading in the
|
|
97
|
+
// logged region (keyed by heading uuid), ALL of them regardless of state.
|
|
98
|
+
const sweptHeadingChildren = new Map();
|
|
99
|
+
// Per-heading LIVE sub-buckets, keyed by heading uuid (§9 fidelity fix): a
|
|
100
|
+
// headed scheduled/someday/repeating child nests under its heading, NOT at the
|
|
101
|
+
// project level.
|
|
102
|
+
const headingItems = new Map();
|
|
103
|
+
const headingScheduled = new Map();
|
|
104
|
+
const headingSomeday = new Map();
|
|
105
|
+
const headingRepeating = new Map();
|
|
106
|
+
// A child whose heading FK is not a LIVE heading (an unknown/trashed heading,
|
|
107
|
+
// OR a swept archived heading handled above) falls back to the project-level
|
|
108
|
+
// (unheaded) buckets rather than vanishing (mirrors the render's loose fallback).
|
|
109
|
+
const liveHeadingUuidOf = (row) => row.heading !== null && liveHeadingSet.has(row.heading) ? row.heading : null;
|
|
64
110
|
// Every untrashed, non-template OPEN child, regardless of which bucket it
|
|
65
111
|
// lands in below — surfaced (only when the project is itself resolved) as
|
|
66
112
|
// the PLOG1 stranded-open-child count.
|
|
67
113
|
let openChildren = 0;
|
|
114
|
+
// Open children buried under a SWEPT archived heading — the §6¾ odd state for
|
|
115
|
+
// headings (HEADARC2-C), surfaced regardless of the project's own status.
|
|
116
|
+
let openChildrenUnderArchivedHeading = 0;
|
|
68
117
|
for (const { row, todo } of todos) {
|
|
69
|
-
if (
|
|
70
|
-
|
|
118
|
+
if (todo.heading !== null)
|
|
119
|
+
todo.headingProject = projectRef;
|
|
120
|
+
// A child of a SWEPT archived heading groups under it in the logged region,
|
|
121
|
+
// WHATEVER its own state — including the odd OPEN child a GUI Put-Back
|
|
122
|
+
// stranded (HEADARC2-C): render what is there, do NOT filter to status=3.
|
|
123
|
+
if (row.heading !== null && sweptHeadingSet.has(row.heading)) {
|
|
124
|
+
pushInto(sweptHeadingChildren, row.heading, todo);
|
|
125
|
+
if (row.status === 0 && !todo.repeating.isTemplate) {
|
|
126
|
+
openChildren += 1; // also stranded when the project itself is resolved
|
|
127
|
+
openChildrenUnderArchivedHeading += 1;
|
|
128
|
+
}
|
|
71
129
|
continue;
|
|
72
130
|
}
|
|
131
|
+
const h = liveHeadingUuidOf(row);
|
|
73
132
|
if (todo.repeating.isTemplate) {
|
|
74
|
-
|
|
133
|
+
if (h !== null)
|
|
134
|
+
pushInto(headingRepeating, h, todo);
|
|
135
|
+
else
|
|
136
|
+
repeating.push(todo);
|
|
75
137
|
continue;
|
|
76
138
|
}
|
|
77
139
|
if (row.status === 0)
|
|
@@ -84,62 +146,98 @@ export function projectView(db, uuid, now, filter = {}, zone) {
|
|
|
84
146
|
logged.push(todo);
|
|
85
147
|
continue;
|
|
86
148
|
}
|
|
87
|
-
if (
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
byHeading.set(row.heading, list);
|
|
91
|
-
}
|
|
92
|
-
else {
|
|
149
|
+
if (h !== null)
|
|
150
|
+
pushInto(headingItems, h, todo);
|
|
151
|
+
else
|
|
93
152
|
active.push(todo);
|
|
94
|
-
}
|
|
95
153
|
continue;
|
|
96
154
|
}
|
|
97
155
|
if (row.start === 2 && row.startDate === null) {
|
|
98
|
-
|
|
156
|
+
if (h !== null)
|
|
157
|
+
pushInto(headingSomeday, h, todo);
|
|
158
|
+
else
|
|
159
|
+
someday.push(todo);
|
|
99
160
|
continue;
|
|
100
161
|
}
|
|
101
162
|
if (row.startDate !== null && row.startDate > packedToday) {
|
|
102
|
-
|
|
163
|
+
const sr = {
|
|
103
164
|
date: decodePackedDate(row.startDate) ?? "",
|
|
104
165
|
ti: row.todayIndex ?? 0,
|
|
105
166
|
todo,
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
list.push(todo);
|
|
112
|
-
byHeading.set(row.heading, list);
|
|
167
|
+
};
|
|
168
|
+
if (h !== null)
|
|
169
|
+
pushInto(headingScheduled, h, sr);
|
|
170
|
+
else
|
|
171
|
+
scheduledRows.push(sr);
|
|
113
172
|
continue;
|
|
114
173
|
}
|
|
115
|
-
|
|
174
|
+
if (h !== null)
|
|
175
|
+
pushInto(headingItems, h, todo);
|
|
176
|
+
else
|
|
177
|
+
active.push(todo);
|
|
116
178
|
}
|
|
117
179
|
logged.sort((a, b) => (b.stopped?.getTime() ?? 0) - (a.stopped?.getTime() ?? 0));
|
|
118
|
-
const scheduled = [];
|
|
119
180
|
// Within a day the UI sorts by todayIndex ASC (Upcoming drag order).
|
|
120
|
-
|
|
121
|
-
const last = scheduled[scheduled.length - 1];
|
|
122
|
-
if (last && last.date === date)
|
|
123
|
-
last.items.push(todo);
|
|
124
|
-
else
|
|
125
|
-
scheduled.push({ date, items: [todo] });
|
|
126
|
-
}
|
|
181
|
+
const scheduled = groupByDate(scheduledRows);
|
|
127
182
|
// Under any content scope (`--overdue` or a tag filter), a heading whose
|
|
128
183
|
// children were all filtered out collapses rather than rendering an empty
|
|
129
|
-
// section; a heading with
|
|
130
|
-
// every heading renders (its own empty state).
|
|
184
|
+
// section; a heading with any surviving child (in ANY sub-bucket) is kept.
|
|
185
|
+
// With no scope active every heading renders (its own empty state).
|
|
131
186
|
const contentScoped = overdue || tf.sql !== "";
|
|
132
|
-
const headingGroups =
|
|
133
|
-
.map((heading) => ({
|
|
187
|
+
const headingGroups = liveHeadings
|
|
188
|
+
.map((heading) => ({
|
|
189
|
+
heading,
|
|
190
|
+
items: headingItems.get(heading.uuid) ?? [],
|
|
191
|
+
scheduled: groupByDate(headingScheduled.get(heading.uuid) ?? []),
|
|
192
|
+
someday: headingSomeday.get(heading.uuid) ?? [],
|
|
193
|
+
repeating: headingRepeating.get(heading.uuid) ?? [],
|
|
194
|
+
}))
|
|
195
|
+
.filter((g) => !contentScoped ||
|
|
196
|
+
g.items.length > 0 ||
|
|
197
|
+
g.scheduled.length > 0 ||
|
|
198
|
+
g.someday.length > 0 ||
|
|
199
|
+
g.repeating.length > 0);
|
|
200
|
+
// The logged-region archived-heading groups, in project (heading index) order;
|
|
201
|
+
// each group's children most-recently-completed first (open odd children, with
|
|
202
|
+
// no stopDate, sort last — the same null-last convention the flat logged list
|
|
203
|
+
// uses). Under a content scope (--overdue / --tag) an empty group collapses.
|
|
204
|
+
const loggedHeadings = sweptHeadings
|
|
205
|
+
.map((heading) => ({
|
|
206
|
+
heading,
|
|
207
|
+
items: (sweptHeadingChildren.get(heading.uuid) ?? []).toSorted((a, b) => (b.stopped?.getTime() ?? 0) - (a.stopped?.getTime() ?? 0)),
|
|
208
|
+
}))
|
|
134
209
|
.filter((g) => !contentScoped || g.items.length > 0);
|
|
210
|
+
// The flat wire `items[]`: every LIVE child in project index order (the
|
|
211
|
+
// `todos` fetch is already `ORDER BY index ASC`). Excludes swept logged rows
|
|
212
|
+
// (→ `logged`) and children of swept archived headings (→ `loggedHeadings`) —
|
|
213
|
+
// exactly the rows that leave the live region. Each headed row already carries
|
|
214
|
+
// its `heading` ref + `headingProject` (stamped in the loop above).
|
|
215
|
+
const items = todos
|
|
216
|
+
.map((t) => t.todo)
|
|
217
|
+
.filter((td) => !td.logged && !(td.heading !== null && sweptHeadingSet.has(td.heading.uuid)));
|
|
218
|
+
// The catalog: every heading (live + swept archived) in index order — but under
|
|
219
|
+
// a content scope (`--overdue` / `--tag`) a heading whose children were all
|
|
220
|
+
// filtered out COLLAPSES, exactly as it does for the live groups + logged groups
|
|
221
|
+
// and the TTY. With no scope every heading survives (empty ones included), so
|
|
222
|
+
// this is a no-op there. Built from the SAME survivors the render layout uses.
|
|
223
|
+
const survivingHeadings = new Set([
|
|
224
|
+
...headingGroups.map((g) => g.heading.uuid),
|
|
225
|
+
...loggedHeadings.map((g) => g.heading.uuid),
|
|
226
|
+
]);
|
|
227
|
+
const headingCatalog = headings.filter((h) => survivingHeadings.has(h.uuid));
|
|
135
228
|
return {
|
|
136
229
|
project,
|
|
230
|
+
items,
|
|
231
|
+
headingCatalog,
|
|
137
232
|
active,
|
|
138
233
|
headings: headingGroups,
|
|
139
|
-
|
|
234
|
+
scheduled,
|
|
235
|
+
someday,
|
|
236
|
+
repeating,
|
|
140
237
|
logged,
|
|
141
|
-
|
|
238
|
+
loggedHeadings,
|
|
142
239
|
openChildrenWhileResolved: project.status === "open" ? 0 : openChildren,
|
|
240
|
+
openChildrenUnderArchivedHeading,
|
|
143
241
|
};
|
|
144
242
|
}
|
|
145
243
|
//# sourceMappingURL=project-view.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project-view.js","sourceRoot":"","sources":["../../src/read/project-view.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"project-view.js","sourceRoot":"","sources":["../../src/read/project-view.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `loose` pseudo-area: a reserved, case-insensitive ref that addresses the
|
|
3
|
+
* NULL area (area-less items) as if it were an area, on READ surfaces only. It
|
|
4
|
+
* mirrors the GUI sidebar's leading loose block — area-less projects, then loose
|
|
5
|
+
* direct to-dos — plus the "Later Projects" someday/scheduled block under
|
|
6
|
+
* `--show-later`. The reserved word ALWAYS wins over a real area that happens to
|
|
7
|
+
* be named "Loose" (that area is reachable only by uuid); when one shadows, the
|
|
8
|
+
* read surfaces a resolution disclosure. Every WRITE verb and the `open` command
|
|
9
|
+
* refuse the reserved word by name — the pseudo-area is a derived view, not a
|
|
10
|
+
* mutable container.
|
|
11
|
+
*/
|
|
12
|
+
import type { DatabaseSync } from "node:sqlite";
|
|
13
|
+
/** The reserved ref (lowercase canonical form) that names the loose pseudo-area. */
|
|
14
|
+
export declare const LOOSE_REF = "loose";
|
|
15
|
+
/** True when a ref names the reserved `loose` pseudo-area (case-insensitive, trimmed). */
|
|
16
|
+
export declare function isLooseRef(ref: string): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* The uuid of a real area whose title case-insensitively equals the reserved
|
|
19
|
+
* word, if any — for the resolution-shadow disclosure. Lowest sidebar index
|
|
20
|
+
* wins on the (pathological) chance of duplicates. Returns undefined when no
|
|
21
|
+
* real area shadows the reserved word.
|
|
22
|
+
*/
|
|
23
|
+
export declare function shadowingLooseArea(db: DatabaseSync): string | undefined;
|
|
24
|
+
/** The disclosure appended to a loose read when a real area shadows the reserved word. */
|
|
25
|
+
export declare function looseShadowNotice(uuid: string): string;
|
|
26
|
+
/** Refusal for opening the loose pseudo-area — it is a derived view, not an app screen. */
|
|
27
|
+
export declare const LOOSE_OPEN_REFUSAL = "the loose pseudo-area is a derived view \u2014 it cannot be opened; open a specific project or area by ref";
|
|
28
|
+
/** Refusal for `--to-area loose` — the reserved word is a read-only view, not a destination. */
|
|
29
|
+
export declare const LOOSE_TO_AREA_REFUSAL = "the loose pseudo-area is a derived view \u2014 it cannot be modified; to leave a to-do area-less use --loose (a project: --no-area), or target a real area named \"Loose\" by uuid";
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/** The reserved ref (lowercase canonical form) that names the loose pseudo-area. */
|
|
2
|
+
export const LOOSE_REF = "loose";
|
|
3
|
+
/** True when a ref names the reserved `loose` pseudo-area (case-insensitive, trimmed). */
|
|
4
|
+
export function isLooseRef(ref) {
|
|
5
|
+
return ref.trim().toLowerCase() === LOOSE_REF;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* The uuid of a real area whose title case-insensitively equals the reserved
|
|
9
|
+
* word, if any — for the resolution-shadow disclosure. Lowest sidebar index
|
|
10
|
+
* wins on the (pathological) chance of duplicates. Returns undefined when no
|
|
11
|
+
* real area shadows the reserved word.
|
|
12
|
+
*/
|
|
13
|
+
export function shadowingLooseArea(db) {
|
|
14
|
+
const row = db
|
|
15
|
+
.prepare(`SELECT uuid FROM TMArea WHERE lower(title) = ? ORDER BY "index" ASC LIMIT 1`)
|
|
16
|
+
.get(LOOSE_REF);
|
|
17
|
+
return row?.uuid;
|
|
18
|
+
}
|
|
19
|
+
/** The disclosure appended to a loose read when a real area shadows the reserved word. */
|
|
20
|
+
export function looseShadowNotice(uuid) {
|
|
21
|
+
return `resolved to the loose pseudo-area; an area named "Loose" exists (uuid ${uuid}) — target it by uuid`;
|
|
22
|
+
}
|
|
23
|
+
/** Refusal for opening the loose pseudo-area — it is a derived view, not an app screen. */
|
|
24
|
+
export const LOOSE_OPEN_REFUSAL = "the loose pseudo-area is a derived view — it cannot be opened; open a specific project or area by ref";
|
|
25
|
+
/** Refusal for `--to-area loose` — the reserved word is a read-only view, not a destination. */
|
|
26
|
+
export const LOOSE_TO_AREA_REFUSAL = 'the loose pseudo-area is a derived view — it cannot be modified; to leave a to-do area-less use --loose (a project: --no-area), or target a real area named "Loose" by uuid';
|
|
27
|
+
//# sourceMappingURL=pseudo-area.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pseudo-area.js","sourceRoot":"","sources":["../../src/read/pseudo-area.ts"],"names":[],"mappings":"AAaA,oFAAoF;AACpF,MAAM,CAAC,MAAM,SAAS,GAAG,OAAO,CAAC;AAEjC,0FAA0F;AAC1F,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,KAAK,SAAS,CAAC;AAChD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,EAAgB;IACjD,MAAM,GAAG,GAAG,EAAE;SACX,OAAO,CAAC,6EAA6E,CAAC;SACtF,GAAG,CAAC,SAAS,CAAiC,CAAC;IAClD,OAAO,GAAG,EAAE,IAAI,CAAC;AACnB,CAAC;AAED,0FAA0F;AAC1F,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,OAAO,yEAAyE,IAAI,uBAAuB,CAAC;AAC9G,CAAC;AAED,2FAA2F;AAC3F,MAAM,CAAC,MAAM,kBAAkB,GAC7B,uGAAuG,CAAC;AAE1G,gGAAgG;AAChG,MAAM,CAAC,MAAM,qBAAqB,GAChC,6KAA6K,CAAC"}
|