@tashks/core 0.1.5 → 0.2.3

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.
@@ -1 +1 @@
1
- {"version":3,"file":"id.d.ts","sourceRoot":"","sources":["../../src/id.ts"],"names":[],"mappings":"AAwBA,eAAO,MAAM,cAAc,GAAI,OAAO,MAAM,KAAG,MACF,CAAC"}
1
+ {"version":3,"file":"id.d.ts","sourceRoot":"","sources":["../../src/id.ts"],"names":[],"mappings":"AA2BA,eAAO,MAAM,cAAc,GAAI,OAAO,MAAM,KAAG,MACF,CAAC"}
package/dist/src/id.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { randomBytes } from "node:crypto";
2
2
  const idSuffixAlphabet = "abcdefghijklmnopqrstuvwxyz0123456789";
3
3
  const idSuffixLength = 6;
4
+ const maxSlugLength = 30;
4
5
  const slugifyTitle = (title) => {
5
6
  const slug = title
6
7
  .toLowerCase()
@@ -8,7 +9,8 @@ const slugifyTitle = (title) => {
8
9
  .replace(/[\u0300-\u036f]/g, "")
9
10
  .replace(/[^a-z0-9]+/g, "-")
10
11
  .replace(/^-+|-+$/g, "");
11
- return slug.length > 0 ? slug : "task";
12
+ const base = slug.length > 0 ? slug : "task";
13
+ return base.slice(0, maxSlugLength).replace(/-+$/, "");
12
14
  };
13
15
  const randomIdSuffix = () => {
14
16
  const random = randomBytes(idSuffixLength);
@@ -1 +1 @@
1
- {"version":3,"file":"proseql-repository.d.ts","sourceRoot":"","sources":["../../src/proseql-repository.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AA4BtC,OAAO,EACN,cAAc,EAMd,MAAM,iBAAiB,CAAC;AA2CzB,MAAM,WAAW,wBAAwB;IACxC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACrC;AAyWD,eAAO,MAAM,qBAAqB,GACjC,SAAS,wBAAwB,KAC/B,KAAK,CAAC,KAAK,CAAC,cAAc,EAAE,MAAM,CACwB,CAAC"}
1
+ {"version":3,"file":"proseql-repository.d.ts","sourceRoot":"","sources":["../../src/proseql-repository.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAmCtC,OAAO,EACN,cAAc,EAUd,MAAM,iBAAiB,CAAC;AA8CzB,MAAM,WAAW,wBAAwB;IACxC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACrC;AAsgBD,eAAO,MAAM,qBAAqB,GACjC,SAAS,wBAAwB,KAC/B,KAAK,CAAC,KAAK,CAAC,cAAc,EAAE,MAAM,CACwB,CAAC"}
@@ -1,18 +1,21 @@
1
1
  import { dirname, join } from "node:path";
2
- import { mkdir, writeFile } from "node:fs/promises";
2
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
3
3
  import * as Effect from "effect/Effect";
4
4
  import * as Layer from "effect/Layer";
5
5
  import * as Schema from "effect/Schema";
6
6
  import { createNodeDatabase } from "@proseql/node";
7
7
  import YAML from "yaml";
8
- import { Task as TaskSchema, WorkLogCreateInput as WorkLogCreateInputSchema, WorkLogEntry as WorkLogEntrySchema, } from "./schema.js";
9
- import { byUpdatedDescThenTitle, isStalerThan, } from "./query.js";
8
+ import { Task as TaskSchema, WorkLogCreateInput as WorkLogCreateInputSchema, WorkLogEntry as WorkLogEntrySchema, Project as ProjectSchema, ProjectCreateInput as ProjectCreateInputSchema, ProjectPatch as ProjectPatchSchema, } from "./schema.js";
9
+ import { byUpdatedDescThenTitle, isStalerThan, listContexts as listContextsFromTasks, } from "./query.js";
10
10
  import { runCreateHooks, runModifyHooks, runNonMutatingHooks, } from "./hooks.js";
11
11
  import { buildCompletionRecurrenceTask, buildNextClockRecurrenceTask, isClockRecurrenceDue, } from "./recurrence.js";
12
- import { TaskRepository, applyListTaskFilters, todayIso, applyTaskPatch, applyWorkLogPatch, createTaskFromInput, } from "./repository.js";
12
+ import { TaskRepository, applyListTaskFilters, applyListProjectFilters, todayIso, applyTaskPatch, applyWorkLogPatch, applyProjectPatch, buildInstanceFromTemplate, createTaskFromInput, createProjectFromInput, } from "./repository.js";
13
13
  const decodeTask = Schema.decodeUnknownSync(TaskSchema);
14
14
  const decodeWorkLogCreateInput = Schema.decodeUnknownSync(WorkLogCreateInputSchema);
15
15
  const decodeWorkLogEntry = Schema.decodeUnknownSync(WorkLogEntrySchema);
16
+ const decodeProject = Schema.decodeUnknownSync(ProjectSchema);
17
+ const decodeProjectCreateInput = Schema.decodeUnknownSync(ProjectCreateInputSchema);
18
+ const decodeProjectPatch = Schema.decodeUnknownSync(ProjectPatchSchema);
16
19
  const toErrorMessage = (error) => {
17
20
  if (error !== null && typeof error === "object" && "_tag" in error) {
18
21
  const tagged = error;
@@ -58,6 +61,11 @@ const makeDbConfig = (options) => ({
58
61
  : {}),
59
62
  relationships: {},
60
63
  },
64
+ projects: {
65
+ schema: ProjectSchema,
66
+ file: join(dirname(options.tasksFile), "projects.yaml"),
67
+ relationships: {},
68
+ },
61
69
  });
62
70
  const makeProseqlRepository = (options) => Effect.gen(function* () {
63
71
  const config = makeDbConfig(options);
@@ -112,6 +120,28 @@ const makeProseqlRepository = (options) => Effect.gen(function* () {
112
120
  try: () => db.workLog.delete(id).runPromise,
113
121
  catch: (error) => `ProseqlRepository failed to delete work log entry ${id}: ${toErrorMessage(error)}`,
114
122
  });
123
+ const collectProjects = () => Effect.tryPromise({
124
+ try: () => db.projects.query().runPromise.then((results) => results),
125
+ catch: (error) => `ProseqlRepository.listProjects failed: ${toErrorMessage(error)}`,
126
+ });
127
+ const findProject = (id) => Effect.tryPromise({
128
+ try: () => db.projects.findById(id).runPromise,
129
+ catch: (error) => `ProseqlRepository failed to read project ${id}: ${toErrorMessage(error)}`,
130
+ });
131
+ const saveProject = (project) => Effect.tryPromise({
132
+ try: () => db.projects
133
+ .upsert({
134
+ where: { id: project.id },
135
+ create: project,
136
+ update: project,
137
+ })
138
+ .runPromise.then((r) => r),
139
+ catch: (error) => `ProseqlRepository failed to write project ${project.id}: ${toErrorMessage(error)}`,
140
+ });
141
+ const removeProject = (id) => Effect.tryPromise({
142
+ try: () => db.projects.delete(id).runPromise,
143
+ catch: (error) => `ProseqlRepository failed to delete project ${id}: ${toErrorMessage(error)}`,
144
+ });
115
145
  const writeDailyHighlight = (id) => Effect.tryPromise({
116
146
  try: async () => {
117
147
  const highlightPath = join(dataDir, "daily-highlight.yaml");
@@ -127,6 +157,32 @@ const makeProseqlRepository = (options) => Effect.gen(function* () {
127
157
  }
128
158
  return a.id.localeCompare(b.id);
129
159
  };
160
+ const readDailyHighlight = () => Effect.gen(function* () {
161
+ const highlightPath = join(dataDir, "daily-highlight.yaml");
162
+ const source = yield* Effect.tryPromise({
163
+ try: () => readFile(highlightPath, "utf8").catch((error) => {
164
+ if (error !== null &&
165
+ typeof error === "object" &&
166
+ "code" in error &&
167
+ error.code === "ENOENT") {
168
+ return null;
169
+ }
170
+ throw error;
171
+ }),
172
+ catch: (error) => `ProseqlRepository failed to read daily highlight: ${toErrorMessage(error)}`,
173
+ });
174
+ if (source === null || source.trim().length === 0) {
175
+ return null;
176
+ }
177
+ const parsed = YAML.parse(source);
178
+ if (parsed === null ||
179
+ typeof parsed !== "object" ||
180
+ typeof parsed.id !== "string") {
181
+ return null;
182
+ }
183
+ const result = yield* Effect.catchAll(Effect.map(findTask(parsed.id), (t) => t), () => Effect.succeed(null));
184
+ return result;
185
+ });
130
186
  const service = {
131
187
  listTasks: (filters) => Effect.map(collectTasks(), (tasks) => applyListTaskFilters(tasks, filters)),
132
188
  getTask: (id) => findTask(id),
@@ -206,6 +262,7 @@ const makeProseqlRepository = (options) => Effect.gen(function* () {
206
262
  yield* writeDailyHighlight(id);
207
263
  return existing;
208
264
  }),
265
+ getDailyHighlight: () => readDailyHighlight(),
209
266
  listStale: (days) => Effect.map(collectTasks(), (tasks) => {
210
267
  const stalePredicate = isStalerThan(days, todayIso());
211
268
  return tasks
@@ -249,6 +306,45 @@ const makeProseqlRepository = (options) => Effect.gen(function* () {
249
306
  yield* saveWorkLogEntry(entry);
250
307
  return entry;
251
308
  }),
309
+ listProjects: (filters) => Effect.map(collectProjects(), (projects) => applyListProjectFilters(projects, filters)),
310
+ getProject: (id) => findProject(id),
311
+ createProject: (input) => Effect.gen(function* () {
312
+ const created = createProjectFromInput(input);
313
+ yield* saveProject(created);
314
+ return created;
315
+ }),
316
+ updateProject: (id, patch) => Effect.gen(function* () {
317
+ const existing = yield* findProject(id);
318
+ const updated = applyProjectPatch(existing, patch);
319
+ yield* saveProject(updated);
320
+ return updated;
321
+ }),
322
+ deleteProject: (id) => Effect.gen(function* () {
323
+ yield* removeProject(id);
324
+ return { deleted: true };
325
+ }),
326
+ importProject: (project) => Effect.gen(function* () {
327
+ yield* saveProject(project);
328
+ return project;
329
+ }),
330
+ listContexts: () => Effect.map(collectTasks(), (tasks) => listContextsFromTasks(tasks)),
331
+ getRelated: (id) => Effect.gen(function* () {
332
+ const target = yield* findTask(id);
333
+ const allTasks = yield* collectTasks();
334
+ const targetRelated = new Set(target.related);
335
+ return allTasks.filter((t) => t.id !== id &&
336
+ (targetRelated.has(t.id) || t.related.includes(id)));
337
+ }),
338
+ instantiateTemplate: (templateId, overrides) => Effect.gen(function* () {
339
+ const template = yield* findTask(templateId);
340
+ if (!template.is_template) {
341
+ return yield* Effect.fail(`Task ${templateId} is not a template`);
342
+ }
343
+ const instance = buildInstanceFromTemplate(template, overrides);
344
+ const taskFromHooks = yield* runCreateHooks(instance, hookRuntimeOptions);
345
+ yield* saveTask(taskFromHooks);
346
+ return taskFromHooks;
347
+ }),
252
348
  };
253
349
  return service;
254
350
  });
@@ -1,14 +1,17 @@
1
1
  import * as Effect from "effect/Effect";
2
2
  import * as Schema from "effect/Schema";
3
- import { type Task, type TaskEnergy } from "./schema.js";
3
+ import { type Task, type Project } from "./schema.js";
4
4
  export declare const isBlocked: (task: Task, allTasks: Task[]) => boolean;
5
5
  export declare const isUnblocked: (task: Task, allTasks: Task[]) => boolean;
6
6
  export declare const isDueBefore: (date: string) => (task: Task) => boolean;
7
7
  export declare const isDueThisWeek: (today: string) => (task: Task) => boolean;
8
8
  export declare const isDeferred: (today: string) => (task: Task) => boolean;
9
- export declare const hasEnergy: (level: TaskEnergy) => (task: Task) => boolean;
9
+ export declare const hasEnergy: (level: string) => (task: Task) => boolean;
10
10
  export declare const hasTag: (tag: string) => (task: Task) => boolean;
11
11
  export declare const hasProject: (project: string) => (task: Task) => boolean;
12
+ export declare const hasDurationMin: (min: number) => (task: Task) => boolean;
13
+ export declare const hasDurationMax: (max: number) => (task: Task) => boolean;
14
+ export declare const hasContext: (context: string) => (task: Task) => boolean;
12
15
  export declare const isStalerThan: (days: number, today: string) => (task: Task) => boolean;
13
16
  export declare const wasCompletedOn: (date: string) => (task: Task) => boolean;
14
17
  export declare const wasCompletedBetween: (start: string, end: string) => (task: Task) => boolean;
@@ -18,10 +21,10 @@ export declare const byCreatedAsc: (a: Task, b: Task) => number;
18
21
  export declare const byUpdatedDescThenTitle: (a: Task, b: Task) => number;
19
22
  export declare const resolveRelativeDate: (value: string, today: string) => string | null;
20
23
  export declare const PerspectiveFilters: Schema.Struct<{
21
- status: Schema.optionalWith<Schema.Literal<["active", "backlog", "blocked", "done", "dropped", "on-hold"]>, {
24
+ status: Schema.optionalWith<typeof Schema.String, {
22
25
  exact: true;
23
26
  }>;
24
- area: Schema.optionalWith<Schema.Literal<["health", "infrastructure", "work", "personal", "blog", "code", "home", "side-projects"]>, {
27
+ area: Schema.optionalWith<typeof Schema.String, {
25
28
  exact: true;
26
29
  }>;
27
30
  project: Schema.optionalWith<typeof Schema.String, {
@@ -39,7 +42,7 @@ export declare const PerspectiveFilters: Schema.Struct<{
39
42
  unblocked_only: Schema.optionalWith<typeof Schema.Boolean, {
40
43
  exact: true;
41
44
  }>;
42
- energy: Schema.optionalWith<Schema.Literal<["low", "medium", "high"]>, {
45
+ energy: Schema.optionalWith<typeof Schema.String, {
43
46
  exact: true;
44
47
  }>;
45
48
  stale_days: Schema.optionalWith<typeof Schema.Number, {
@@ -48,16 +51,28 @@ export declare const PerspectiveFilters: Schema.Struct<{
48
51
  completed_on: Schema.optionalWith<typeof Schema.String, {
49
52
  exact: true;
50
53
  }>;
54
+ duration_min: Schema.optionalWith<typeof Schema.Number, {
55
+ exact: true;
56
+ }>;
57
+ duration_max: Schema.optionalWith<typeof Schema.Number, {
58
+ exact: true;
59
+ }>;
60
+ context: Schema.optionalWith<typeof Schema.String, {
61
+ exact: true;
62
+ }>;
63
+ include_templates: Schema.optionalWith<typeof Schema.Boolean, {
64
+ exact: true;
65
+ }>;
51
66
  }>;
52
67
  export type PerspectiveFilters = Schema.Schema.Type<typeof PerspectiveFilters>;
53
68
  export declare const PerspectiveSort: typeof Schema.String;
54
69
  export type PerspectiveSort = Schema.Schema.Type<typeof PerspectiveSort>;
55
70
  export declare const Perspective: Schema.Struct<{
56
71
  filters: Schema.Struct<{
57
- status: Schema.optionalWith<Schema.Literal<["active", "backlog", "blocked", "done", "dropped", "on-hold"]>, {
72
+ status: Schema.optionalWith<typeof Schema.String, {
58
73
  exact: true;
59
74
  }>;
60
- area: Schema.optionalWith<Schema.Literal<["health", "infrastructure", "work", "personal", "blog", "code", "home", "side-projects"]>, {
75
+ area: Schema.optionalWith<typeof Schema.String, {
61
76
  exact: true;
62
77
  }>;
63
78
  project: Schema.optionalWith<typeof Schema.String, {
@@ -75,7 +90,7 @@ export declare const Perspective: Schema.Struct<{
75
90
  unblocked_only: Schema.optionalWith<typeof Schema.Boolean, {
76
91
  exact: true;
77
92
  }>;
78
- energy: Schema.optionalWith<Schema.Literal<["low", "medium", "high"]>, {
93
+ energy: Schema.optionalWith<typeof Schema.String, {
79
94
  exact: true;
80
95
  }>;
81
96
  stale_days: Schema.optionalWith<typeof Schema.Number, {
@@ -84,6 +99,18 @@ export declare const Perspective: Schema.Struct<{
84
99
  completed_on: Schema.optionalWith<typeof Schema.String, {
85
100
  exact: true;
86
101
  }>;
102
+ duration_min: Schema.optionalWith<typeof Schema.Number, {
103
+ exact: true;
104
+ }>;
105
+ duration_max: Schema.optionalWith<typeof Schema.Number, {
106
+ exact: true;
107
+ }>;
108
+ context: Schema.optionalWith<typeof Schema.String, {
109
+ exact: true;
110
+ }>;
111
+ include_templates: Schema.optionalWith<typeof Schema.Boolean, {
112
+ exact: true;
113
+ }>;
87
114
  }>;
88
115
  sort: Schema.optionalWith<typeof Schema.String, {
89
116
  exact: true;
@@ -92,10 +119,10 @@ export declare const Perspective: Schema.Struct<{
92
119
  export type Perspective = Schema.Schema.Type<typeof Perspective>;
93
120
  export declare const PerspectiveConfig: Schema.Record$<typeof Schema.String, Schema.Struct<{
94
121
  filters: Schema.Struct<{
95
- status: Schema.optionalWith<Schema.Literal<["active", "backlog", "blocked", "done", "dropped", "on-hold"]>, {
122
+ status: Schema.optionalWith<typeof Schema.String, {
96
123
  exact: true;
97
124
  }>;
98
- area: Schema.optionalWith<Schema.Literal<["health", "infrastructure", "work", "personal", "blog", "code", "home", "side-projects"]>, {
125
+ area: Schema.optionalWith<typeof Schema.String, {
99
126
  exact: true;
100
127
  }>;
101
128
  project: Schema.optionalWith<typeof Schema.String, {
@@ -113,7 +140,7 @@ export declare const PerspectiveConfig: Schema.Record$<typeof Schema.String, Sch
113
140
  unblocked_only: Schema.optionalWith<typeof Schema.Boolean, {
114
141
  exact: true;
115
142
  }>;
116
- energy: Schema.optionalWith<Schema.Literal<["low", "medium", "high"]>, {
143
+ energy: Schema.optionalWith<typeof Schema.String, {
117
144
  exact: true;
118
145
  }>;
119
146
  stale_days: Schema.optionalWith<typeof Schema.Number, {
@@ -122,6 +149,18 @@ export declare const PerspectiveConfig: Schema.Record$<typeof Schema.String, Sch
122
149
  completed_on: Schema.optionalWith<typeof Schema.String, {
123
150
  exact: true;
124
151
  }>;
152
+ duration_min: Schema.optionalWith<typeof Schema.Number, {
153
+ exact: true;
154
+ }>;
155
+ duration_max: Schema.optionalWith<typeof Schema.Number, {
156
+ exact: true;
157
+ }>;
158
+ context: Schema.optionalWith<typeof Schema.String, {
159
+ exact: true;
160
+ }>;
161
+ include_templates: Schema.optionalWith<typeof Schema.Boolean, {
162
+ exact: true;
163
+ }>;
125
164
  }>;
126
165
  sort: Schema.optionalWith<typeof Schema.String, {
127
166
  exact: true;
@@ -132,4 +171,13 @@ export declare const parsePerspectiveConfig: (record: unknown) => PerspectiveCon
132
171
  export declare const resolvePerspectiveConfigRelativeDates: (config: PerspectiveConfig, today: string) => PerspectiveConfig | null;
133
172
  export declare const applyPerspectiveToTasks: (tasks: ReadonlyArray<Task>, perspective: Perspective, today?: string) => Array<Task>;
134
173
  export declare const loadPerspectiveConfig: (dataDir: string, today?: string) => Effect.Effect<PerspectiveConfig, string>;
174
+ export declare const listAreas: (tasks: ReadonlyArray<Task>, projects: ReadonlyArray<Project>) => Array<string>;
175
+ export declare const byUrgencyDesc: (a: Task, b: Task) => number;
176
+ export interface DependencyChain {
177
+ readonly ancestors: Task[];
178
+ readonly target: Task | null;
179
+ readonly descendants: Task[];
180
+ }
181
+ export declare const buildDependencyChain: (targetId: string, allTasks: ReadonlyArray<Task>) => DependencyChain;
182
+ export declare const listContexts: (tasks: ReadonlyArray<Task>) => Array<string>;
135
183
  //# sourceMappingURL=query.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/query.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/query.ts"],"names":[],"mappings":"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"}
package/dist/src/query.js CHANGED
@@ -4,7 +4,7 @@ import * as Effect from "effect/Effect";
4
4
  import * as Either from "effect/Either";
5
5
  import * as Schema from "effect/Schema";
6
6
  import YAML from "yaml";
7
- import { TaskArea as TaskAreaSchema, TaskEnergy as TaskEnergySchema, TaskStatus as TaskStatusSchema, } from "./schema.js";
7
+ import { TaskEnergy as TaskEnergySchema, TaskStatus as TaskStatusSchema, } from "./schema.js";
8
8
  const addDays = (date, days) => {
9
9
  const next = new Date(`${date}T00:00:00.000Z`);
10
10
  next.setUTCDate(next.getUTCDate() + days);
@@ -58,7 +58,10 @@ export const isDueThisWeek = (today) => {
58
58
  export const isDeferred = (today) => (task) => task.defer_until !== null && task.defer_until > today;
59
59
  export const hasEnergy = (level) => (task) => task.energy === level;
60
60
  export const hasTag = (tag) => (task) => task.tags.includes(tag);
61
- export const hasProject = (project) => (task) => task.project === project;
61
+ export const hasProject = (project) => (task) => task.projects.includes(project);
62
+ export const hasDurationMin = (min) => (task) => task.estimated_minutes !== null && task.estimated_minutes >= min;
63
+ export const hasDurationMax = (max) => (task) => task.estimated_minutes !== null && task.estimated_minutes <= max;
64
+ export const hasContext = (context) => (task) => task.context === context;
62
65
  export const isStalerThan = (days, today) => (task) => {
63
66
  const updated = dateToUtcMidnight(task.updated);
64
67
  const now = dateToUtcMidnight(today);
@@ -76,10 +79,9 @@ export const wasCompletedBetween = (start, end) => (task) => {
76
79
  }
77
80
  return completed >= start && completed <= end;
78
81
  };
79
- const energyRank = {
80
- low: 0,
81
- medium: 1,
82
- high: 2,
82
+ const energyRank = (e) => {
83
+ const ranks = { low: 0, medium: 1, high: 2 };
84
+ return ranks[e] ?? -1;
83
85
  };
84
86
  export const byDueAsc = (a, b) => {
85
87
  if (a.due === null && b.due === null) {
@@ -93,7 +95,7 @@ export const byDueAsc = (a, b) => {
93
95
  }
94
96
  return a.due.localeCompare(b.due);
95
97
  };
96
- export const byEnergyAsc = (a, b) => energyRank[a.energy] - energyRank[b.energy];
98
+ export const byEnergyAsc = (a, b) => energyRank(a.energy) - energyRank(b.energy);
97
99
  export const byCreatedAsc = (a, b) => a.created.localeCompare(b.created);
98
100
  export const byUpdatedDescThenTitle = (a, b) => {
99
101
  const byUpdatedDesc = b.updated.localeCompare(a.updated);
@@ -145,7 +147,7 @@ export const resolveRelativeDate = (value, today) => {
145
147
  };
146
148
  export const PerspectiveFilters = Schema.Struct({
147
149
  status: Schema.optionalWith(TaskStatusSchema, { exact: true }),
148
- area: Schema.optionalWith(TaskAreaSchema, { exact: true }),
150
+ area: Schema.optionalWith(Schema.String, { exact: true }),
149
151
  project: Schema.optionalWith(Schema.String, { exact: true }),
150
152
  tags: Schema.optionalWith(Schema.Array(Schema.String), { exact: true }),
151
153
  due_before: Schema.optionalWith(Schema.String, { exact: true }),
@@ -154,6 +156,10 @@ export const PerspectiveFilters = Schema.Struct({
154
156
  energy: Schema.optionalWith(TaskEnergySchema, { exact: true }),
155
157
  stale_days: Schema.optionalWith(Schema.Number, { exact: true }),
156
158
  completed_on: Schema.optionalWith(Schema.String, { exact: true }),
159
+ duration_min: Schema.optionalWith(Schema.Number, { exact: true }),
160
+ duration_max: Schema.optionalWith(Schema.Number, { exact: true }),
161
+ context: Schema.optionalWith(Schema.String, { exact: true }),
162
+ include_templates: Schema.optionalWith(Schema.Boolean, { exact: true }),
157
163
  });
158
164
  export const PerspectiveSort = Schema.String;
159
165
  export const Perspective = Schema.Struct({
@@ -207,7 +213,20 @@ export const applyPerspectiveToTasks = (tasks, perspective, today = currentIsoDa
207
213
  const completedOnPredicate = perspective.filters.completed_on !== undefined
208
214
  ? wasCompletedOn(perspective.filters.completed_on)
209
215
  : null;
216
+ const durationMinPredicate = perspective.filters.duration_min !== undefined
217
+ ? hasDurationMin(perspective.filters.duration_min)
218
+ : null;
219
+ const durationMaxPredicate = perspective.filters.duration_max !== undefined
220
+ ? hasDurationMax(perspective.filters.duration_max)
221
+ : null;
222
+ const contextPredicate = perspective.filters.context !== undefined
223
+ ? hasContext(perspective.filters.context)
224
+ : null;
210
225
  const filtered = taskList.filter((task) => {
226
+ if (perspective.filters.include_templates !== true &&
227
+ task.is_template === true) {
228
+ return false;
229
+ }
211
230
  if (perspective.filters.status !== undefined &&
212
231
  task.status !== perspective.filters.status) {
213
232
  return false;
@@ -217,7 +236,7 @@ export const applyPerspectiveToTasks = (tasks, perspective, today = currentIsoDa
217
236
  return false;
218
237
  }
219
238
  if (perspective.filters.project !== undefined &&
220
- task.project !== perspective.filters.project) {
239
+ !task.projects.includes(perspective.filters.project)) {
221
240
  return false;
222
241
  }
223
242
  if (perspective.filters.tags !== undefined &&
@@ -246,6 +265,15 @@ export const applyPerspectiveToTasks = (tasks, perspective, today = currentIsoDa
246
265
  if (completedOnPredicate !== null && !completedOnPredicate(task)) {
247
266
  return false;
248
267
  }
268
+ if (durationMinPredicate !== null && !durationMinPredicate(task)) {
269
+ return false;
270
+ }
271
+ if (durationMaxPredicate !== null && !durationMaxPredicate(task)) {
272
+ return false;
273
+ }
274
+ if (contextPredicate !== null && !contextPredicate(task)) {
275
+ return false;
276
+ }
249
277
  return true;
250
278
  });
251
279
  switch (perspective.sort) {
@@ -301,3 +329,63 @@ export const loadPerspectiveConfig = (dataDir, today = currentIsoDate()) => Effe
301
329
  },
302
330
  catch: (error) => `Perspective config loader failed: ${toErrorMessage(error)}`,
303
331
  });
332
+ export const listAreas = (tasks, projects) => {
333
+ const areas = new Set();
334
+ for (const task of tasks) {
335
+ areas.add(task.area);
336
+ }
337
+ for (const project of projects) {
338
+ areas.add(project.area);
339
+ }
340
+ return Array.from(areas).sort();
341
+ };
342
+ export const byUrgencyDesc = (a, b) => {
343
+ const urgencyRanks = { low: 0, medium: 1, high: 2 };
344
+ const aRank = urgencyRanks[a.urgency] ?? -1;
345
+ const bRank = urgencyRanks[b.urgency] ?? -1;
346
+ return bRank - aRank;
347
+ };
348
+ export const buildDependencyChain = (targetId, allTasks) => {
349
+ const taskById = new Map(allTasks.map((t) => [t.id, t]));
350
+ const target = taskById.get(targetId) ?? null;
351
+ const ancestors = [];
352
+ const visitedUp = new Set();
353
+ const walkUp = (id) => {
354
+ const task = taskById.get(id);
355
+ if (task === undefined)
356
+ return;
357
+ for (const blockerId of task.blocked_by) {
358
+ if (visitedUp.has(blockerId))
359
+ continue;
360
+ visitedUp.add(blockerId);
361
+ const blocker = taskById.get(blockerId);
362
+ if (blocker !== undefined) {
363
+ walkUp(blockerId);
364
+ ancestors.push(blocker);
365
+ }
366
+ }
367
+ };
368
+ walkUp(targetId);
369
+ const descendants = [];
370
+ const visitedDown = new Set();
371
+ const walkDown = (id) => {
372
+ for (const task of allTasks) {
373
+ if (task.blocked_by.includes(id) && !visitedDown.has(task.id)) {
374
+ visitedDown.add(task.id);
375
+ descendants.push(task);
376
+ walkDown(task.id);
377
+ }
378
+ }
379
+ };
380
+ walkDown(targetId);
381
+ return { ancestors, target, descendants };
382
+ };
383
+ export const listContexts = (tasks) => {
384
+ const contexts = new Set();
385
+ for (const task of tasks) {
386
+ if (task.context.length > 0) {
387
+ contexts.add(task.context);
388
+ }
389
+ }
390
+ return Array.from(contexts).sort();
391
+ };
@@ -1 +1 @@
1
- {"version":3,"file":"recurrence.d.ts","sourceRoot":"","sources":["../../src/recurrence.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAIxC,OAAO,EAAsB,KAAK,IAAI,EAAE,MAAM,aAAa,CAAC;AAQ5D,MAAM,WAAW,4BAA4B;IAC5C,QAAQ,CAAC,SAAS,EAAE,OAAO,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAC;IAC9D,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC1B;AAYD,eAAO,MAAM,iCAAiC,GAC7C,YAAY,MAAM,KAChB,MAAM,CAAC,MAAM,CAAC,4BAA4B,EAAE,MAAM,CA8BlD,CAAC;AAEJ,eAAO,MAAM,qBAAqB,GACjC,MAAM,IAAI,EACV,oBAAoB,4BAA4B,KAC9C,IAmBF,CAAC;AAEF,eAAO,MAAM,gCAAgC,GAC5C,MAAM,MAAM,EACZ,oBAAoB,4BAA4B,KAC9C,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAc5B,CAAC;AAEJ,eAAO,MAAM,0CAA0C,GACtD,UAAU,MAAM,EAChB,oBAAoB,4BAA4B,KAC9C,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAc5B,CAAC;AAEJ,eAAO,MAAM,aAAa,GACzB,OAAO,IAAI,EACX,OAAO,MAAM,KACX,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAW5B,CAAC;AAEJ,eAAO,MAAM,sBAAsB,GAClC,OAAO,MAAM,EACb,OAAO,MAAM,KACX,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAW1B,CAAC;AAEJ,eAAO,MAAM,gBAAgB,GAC5B,OAAO,MAAM,EACb,OAAO,MAAM,KACX,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAW1B,CAAC;AAEJ,eAAO,MAAM,6BAA6B,GACzC,eAAe,IAAI,EACnB,aAAa,MAAM,KACjB,MAAM,CAAC,MAAM,CAAC,IAAI,GAAG,IAAI,EAAE,MAAM,CAwCnC,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAChC,MAAM,IAAI,EACV,KAAK,IAAI,KACP,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CA8B7B,CAAC;AAEJ,eAAO,MAAM,4BAA4B,GACxC,cAAc,IAAI,EAClB,aAAa,IAAI,KACf,MAAM,CAAC,MAAM,CACf;IACC,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC;IACxB,QAAQ,CAAC,cAAc,EAAE,IAAI,GAAG,IAAI,CAAC;IACrC,QAAQ,CAAC,oBAAoB,EAAE,OAAO,CAAC;CACvC,EACD,MAAM,CAuDJ,CAAC"}
1
+ {"version":3,"file":"recurrence.d.ts","sourceRoot":"","sources":["../../src/recurrence.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAIxC,OAAO,EAAsB,KAAK,IAAI,EAAE,MAAM,aAAa,CAAC;AAQ5D,MAAM,WAAW,4BAA4B;IAC5C,QAAQ,CAAC,SAAS,EAAE,OAAO,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAC;IAC9D,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC1B;AAYD,eAAO,MAAM,iCAAiC,GAC7C,YAAY,MAAM,KAChB,MAAM,CAAC,MAAM,CAAC,4BAA4B,EAAE,MAAM,CA8BlD,CAAC;AAEJ,eAAO,MAAM,qBAAqB,GACjC,MAAM,IAAI,EACV,oBAAoB,4BAA4B,KAC9C,IAmBF,CAAC;AAEF,eAAO,MAAM,gCAAgC,GAC5C,MAAM,MAAM,EACZ,oBAAoB,4BAA4B,KAC9C,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAc5B,CAAC;AAEJ,eAAO,MAAM,0CAA0C,GACtD,UAAU,MAAM,EAChB,oBAAoB,4BAA4B,KAC9C,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAc5B,CAAC;AAEJ,eAAO,MAAM,aAAa,GACzB,OAAO,IAAI,EACX,OAAO,MAAM,KACX,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAW5B,CAAC;AAEJ,eAAO,MAAM,sBAAsB,GAClC,OAAO,MAAM,EACb,OAAO,MAAM,KACX,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAW1B,CAAC;AAEJ,eAAO,MAAM,gBAAgB,GAC5B,OAAO,MAAM,EACb,OAAO,MAAM,KACX,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAW1B,CAAC;AAEJ,eAAO,MAAM,6BAA6B,GACzC,eAAe,IAAI,EACnB,aAAa,MAAM,KACjB,MAAM,CAAC,MAAM,CAAC,IAAI,GAAG,IAAI,EAAE,MAAM,CAwCnC,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAChC,MAAM,IAAI,EACV,KAAK,IAAI,KACP,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CA8B7B,CAAC;AAEJ,eAAO,MAAM,4BAA4B,GACxC,cAAc,IAAI,EAClB,aAAa,IAAI,KACf,MAAM,CAAC,MAAM,CACf;IACC,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC;IACxB,QAAQ,CAAC,cAAc,EAAE,IAAI,GAAG,IAAI,CAAC;IACrC,QAAQ,CAAC,oBAAoB,EAAE,OAAO,CAAC;CACvC,EACD,MAAM,CA6DJ,CAAC"}
@@ -151,6 +151,9 @@ export const isClockRecurrenceDue = (task, now) => Effect.gen(function* () {
151
151
  return (nextOccurrence !== null && nextOccurrence.getTime() <= nowDate.getTime());
152
152
  });
153
153
  export const buildNextClockRecurrenceTask = (existingTask, generatedAt) => Effect.gen(function* () {
154
+ if (existingTask.is_template) {
155
+ return yield* Effect.fail(`TaskRepository failed to generate next recurrence for ${existingTask.id}: task is a template (use instantiation instead)`);
156
+ }
154
157
  const recurrence = existingTask.recurrence;
155
158
  if (recurrence === null) {
156
159
  return yield* Effect.fail(`TaskRepository failed to generate next recurrence for ${existingTask.id}: task is not recurring`);
@@ -1,7 +1,7 @@
1
1
  import * as Context from "effect/Context";
2
2
  import * as Effect from "effect/Effect";
3
3
  import * as Layer from "effect/Layer";
4
- import { type Task, type TaskCreateInput, type TaskPatch, type WorkLogCreateInput, type WorkLogEntry, type WorkLogPatch } from "./schema.js";
4
+ import { type Task, type TaskCreateInput, type TaskPatch, type WorkLogCreateInput, type WorkLogEntry, type WorkLogPatch, type Project, type ProjectCreateInput, type ProjectPatch } from "./schema.js";
5
5
  export { discoverHooksForEvent } from "./hooks.js";
6
6
  export type { HookEvent, HookDiscoveryOptions } from "./hooks.js";
7
7
  export { generateTaskId } from "./id.js";
@@ -15,7 +15,17 @@ export interface ListTasksFilters {
15
15
  readonly due_after?: string;
16
16
  readonly unblocked_only?: boolean;
17
17
  readonly date?: string;
18
+ readonly duration_min?: number;
19
+ readonly duration_max?: number;
20
+ readonly context?: string;
21
+ readonly include_templates?: boolean;
22
+ readonly stale_days?: number;
18
23
  }
24
+ export interface ListProjectsFilters {
25
+ readonly status?: string;
26
+ readonly area?: string;
27
+ }
28
+ export declare const applyListProjectFilters: (projects: Array<Project>, filters?: ListProjectsFilters) => Array<Project>;
19
29
  export interface ListWorkLogFilters {
20
30
  readonly date?: string;
21
31
  }
@@ -42,6 +52,22 @@ export interface TaskRepositoryService {
42
52
  readonly deleteWorkLogEntry: (id: string) => Effect.Effect<DeleteResult, string>;
43
53
  readonly importTask: (task: Task) => Effect.Effect<Task, string>;
44
54
  readonly importWorkLogEntry: (entry: WorkLogEntry) => Effect.Effect<WorkLogEntry, string>;
55
+ readonly listProjects: (filters?: ListProjectsFilters) => Effect.Effect<Array<Project>, string>;
56
+ readonly getProject: (id: string) => Effect.Effect<Project, string>;
57
+ readonly createProject: (input: ProjectCreateInput) => Effect.Effect<Project, string>;
58
+ readonly updateProject: (id: string, patch: ProjectPatch) => Effect.Effect<Project, string>;
59
+ readonly deleteProject: (id: string) => Effect.Effect<DeleteResult, string>;
60
+ readonly importProject: (project: Project) => Effect.Effect<Project, string>;
61
+ readonly getDailyHighlight: () => Effect.Effect<Task | null, string>;
62
+ readonly listContexts: () => Effect.Effect<Array<string>, string>;
63
+ readonly getRelated: (id: string) => Effect.Effect<Array<Task>, string>;
64
+ readonly instantiateTemplate: (templateId: string, overrides?: {
65
+ readonly title?: string;
66
+ readonly due?: string;
67
+ readonly defer_until?: string;
68
+ readonly status?: string;
69
+ readonly projects?: ReadonlyArray<string>;
70
+ }) => Effect.Effect<Task, string>;
45
71
  }
46
72
  declare const TaskRepository_base: Context.TagClass<TaskRepository, "TaskRepository", TaskRepositoryService>;
47
73
  export declare class TaskRepository extends TaskRepository_base {
@@ -51,6 +77,13 @@ export interface TaskRepositoryLiveOptions {
51
77
  readonly hooksDir?: string;
52
78
  readonly hookEnv?: NodeJS.ProcessEnv;
53
79
  }
80
+ export declare const buildInstanceFromTemplate: (template: Task, overrides?: {
81
+ readonly title?: string;
82
+ readonly due?: string;
83
+ readonly defer_until?: string;
84
+ readonly status?: string;
85
+ readonly projects?: ReadonlyArray<string>;
86
+ }) => Task;
54
87
  export declare const TaskRepositoryLive: (options?: TaskRepositoryLiveOptions) => Layer.Layer<TaskRepository>;
55
88
  export declare const todayIso: () => string;
56
89
  export declare const parseTaskRecord: (record: unknown) => Task | null;
@@ -58,4 +91,8 @@ export declare const parseWorkLogRecord: (record: unknown) => WorkLogEntry | nul
58
91
  export declare const createTaskFromInput: (input: TaskCreateInput) => Task;
59
92
  export declare const applyTaskPatch: (task: Task, patch: TaskPatch) => Task;
60
93
  export declare const applyWorkLogPatch: (entry: WorkLogEntry, patch: WorkLogPatch) => WorkLogEntry;
94
+ export declare const parseProjectRecord: (record: unknown) => Project | null;
95
+ export declare const createProjectFromInput: (input: ProjectCreateInput) => Project;
96
+ export declare const promoteSubtask: (repository: TaskRepositoryService, taskId: string, subtaskIndex: number) => Effect.Effect<Task, string>;
97
+ export declare const applyProjectPatch: (project: Project, patch: ProjectPatch) => Project;
61
98
  //# sourceMappingURL=repository.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../../src/repository.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../../src/repository.ts"],"names":[],"mappings":"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"}