clawvault 2.4.6 → 2.5.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/bin/clawvault.js +5 -0
- package/bin/command-registration.test.js +1 -1
- package/bin/help-contract.test.js +1 -0
- package/bin/register-config-route-commands.test.js +8 -1
- package/bin/register-core-commands.js +3 -3
- package/bin/register-project-commands.js +209 -0
- package/bin/register-project-commands.test.js +201 -0
- package/bin/register-query-commands.js +40 -0
- package/bin/register-task-commands.js +2 -18
- package/bin/register-task-commands.test.js +3 -4
- package/bin/test-helpers/cli-command-fixtures.js +5 -0
- package/dist/{chunk-3PJIGGWV.js → chunk-2CDEETQN.js} +1 -0
- package/dist/{chunk-FD2ZA65C.js → chunk-2RK2AG32.js} +5 -5
- package/dist/chunk-5GZFTAL7.js +340 -0
- package/dist/{chunk-P2ZH6AN5.js → chunk-6RQPD7X6.js} +3 -4
- package/dist/{chunk-HNMFXFYP.js → chunk-7OHQFMJK.js} +2 -1
- package/dist/{chunk-FKQJB6XC.js → chunk-C3PF7WBA.js} +2 -2
- package/dist/{chunk-JXY6T5R7.js → chunk-FW465EEA.js} +1 -1
- package/dist/{chunk-BI6SGGZP.js → chunk-G3OQJ2NQ.js} +1 -1
- package/dist/chunk-GSD4ALSI.js +724 -0
- package/dist/{chunk-6QLRSPLZ.js → chunk-IOALNTAN.js} +268 -47
- package/dist/chunk-ITPEXLHA.js +528 -0
- package/dist/{chunk-LLN5SPGL.js → chunk-J5EMBUPK.js} +1 -1
- package/dist/chunk-K3CDT7IH.js +122 -0
- package/dist/{chunk-AHGUJG76.js → chunk-KCCHROBR.js} +13 -69
- package/dist/{chunk-JTO7NZLS.js → chunk-LMCC5OC7.js} +2 -2
- package/dist/{chunk-QALB2V3E.js → chunk-MQUJNOHK.js} +1 -1
- package/dist/{chunk-H6WQUUNK.js → chunk-TMZMN7OS.js} +334 -457
- package/dist/{chunk-HVTTYDCJ.js → chunk-VR5NE7PZ.js} +1 -1
- package/dist/{chunk-22WE3J4F.js → chunk-WIICLBNF.js} +35 -4
- package/dist/chunk-YCVDVI5B.js +273 -0
- package/dist/{chunk-NAMFB7ZA.js → chunk-Z2XBWN7A.js} +0 -2
- package/dist/commands/archive.js +3 -3
- package/dist/commands/backlog.js +1 -1
- package/dist/commands/blocked.js +1 -1
- package/dist/commands/canvas.d.ts +1 -14
- package/dist/commands/canvas.js +123 -1543
- package/dist/commands/context.js +5 -6
- package/dist/commands/doctor.js +2 -2
- package/dist/commands/inject.d.ts +2 -0
- package/dist/commands/inject.js +14 -0
- package/dist/commands/kanban.js +2 -2
- package/dist/commands/migrate-observations.js +2 -2
- package/dist/commands/observe.js +8 -6
- package/dist/commands/project.d.ts +85 -0
- package/dist/commands/project.js +411 -0
- package/dist/commands/rebuild.js +7 -5
- package/dist/commands/reflect.js +5 -4
- package/dist/commands/replay.js +10 -7
- package/dist/commands/setup.d.ts +1 -1
- package/dist/commands/setup.js +2 -2
- package/dist/commands/sleep.d.ts +1 -1
- package/dist/commands/sleep.js +11 -8
- package/dist/commands/status.js +2 -2
- package/dist/commands/task.d.ts +2 -2
- package/dist/commands/task.js +11 -301
- package/dist/commands/wake.d.ts +1 -1
- package/dist/commands/wake.js +4 -4
- package/dist/index.d.ts +75 -107
- package/dist/index.js +78 -36
- package/dist/inject-x65KXWPk.d.ts +137 -0
- package/dist/lib/project-utils.d.ts +97 -0
- package/dist/lib/project-utils.js +19 -0
- package/dist/lib/task-utils.d.ts +8 -3
- package/dist/lib/task-utils.js +1 -1
- package/dist/{types-DMU3SuAV.d.ts → types-jjuYN2Xn.d.ts} +1 -1
- package/package.json +2 -2
- package/dist/chunk-L3DJ36BZ.js +0 -40
- package/dist/chunk-UMMCYTJV.js +0 -105
package/dist/commands/context.js
CHANGED
|
@@ -3,14 +3,13 @@ import {
|
|
|
3
3
|
contextCommand,
|
|
4
4
|
formatContextMarkdown,
|
|
5
5
|
registerContextCommand
|
|
6
|
-
} from "../chunk-
|
|
7
|
-
import "../chunk-
|
|
6
|
+
} from "../chunk-WIICLBNF.js";
|
|
7
|
+
import "../chunk-7OHQFMJK.js";
|
|
8
8
|
import "../chunk-6B3JWM7J.js";
|
|
9
|
-
import "../chunk-
|
|
10
|
-
import "../chunk-L3DJ36BZ.js";
|
|
11
|
-
import "../chunk-ZZA73MFY.js";
|
|
9
|
+
import "../chunk-2CDEETQN.js";
|
|
12
10
|
import "../chunk-FHFUXL6G.js";
|
|
13
|
-
import "../chunk-
|
|
11
|
+
import "../chunk-ZZA73MFY.js";
|
|
12
|
+
import "../chunk-Z2XBWN7A.js";
|
|
14
13
|
export {
|
|
15
14
|
buildContext,
|
|
16
15
|
contextCommand,
|
package/dist/commands/doctor.js
CHANGED
|
@@ -11,11 +11,11 @@ import {
|
|
|
11
11
|
import {
|
|
12
12
|
ClawVault,
|
|
13
13
|
findVault
|
|
14
|
-
} from "../chunk-
|
|
14
|
+
} from "../chunk-7OHQFMJK.js";
|
|
15
15
|
import {
|
|
16
16
|
hasQmd
|
|
17
17
|
} from "../chunk-6B3JWM7J.js";
|
|
18
|
-
import "../chunk-
|
|
18
|
+
import "../chunk-2CDEETQN.js";
|
|
19
19
|
import {
|
|
20
20
|
loadMemoryGraphIndex
|
|
21
21
|
} from "../chunk-ZZA73MFY.js";
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import {
|
|
2
|
+
buildInjectionResult,
|
|
3
|
+
injectCommand,
|
|
4
|
+
registerInjectCommand
|
|
5
|
+
} from "../chunk-GSD4ALSI.js";
|
|
6
|
+
import "../chunk-K3CDT7IH.js";
|
|
7
|
+
import "../chunk-ITPEXLHA.js";
|
|
8
|
+
import "../chunk-2CDEETQN.js";
|
|
9
|
+
import "../chunk-ZZA73MFY.js";
|
|
10
|
+
export {
|
|
11
|
+
buildInjectionResult,
|
|
12
|
+
injectCommand,
|
|
13
|
+
registerInjectCommand
|
|
14
|
+
};
|
package/dist/commands/kanban.js
CHANGED
|
@@ -2,10 +2,10 @@ import {
|
|
|
2
2
|
migrateObservations,
|
|
3
3
|
migrateObservationsCommand,
|
|
4
4
|
registerMigrateObservationsCommand
|
|
5
|
-
} from "../chunk-
|
|
5
|
+
} from "../chunk-FW465EEA.js";
|
|
6
6
|
import "../chunk-MXSSG3QU.js";
|
|
7
7
|
import "../chunk-FHFUXL6G.js";
|
|
8
|
-
import "../chunk-
|
|
8
|
+
import "../chunk-Z2XBWN7A.js";
|
|
9
9
|
export {
|
|
10
10
|
migrateObservations,
|
|
11
11
|
migrateObservationsCommand,
|
package/dist/commands/observe.js
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
2
|
observeCommand,
|
|
3
3
|
registerObserveCommand
|
|
4
|
-
} from "../chunk-
|
|
5
|
-
import "../chunk-HRLWZGMA.js";
|
|
4
|
+
} from "../chunk-2RK2AG32.js";
|
|
6
5
|
import "../chunk-P5EPF6MB.js";
|
|
7
|
-
import "../chunk-
|
|
6
|
+
import "../chunk-TMZMN7OS.js";
|
|
7
|
+
import "../chunk-5GZFTAL7.js";
|
|
8
|
+
import "../chunk-HRLWZGMA.js";
|
|
9
|
+
import "../chunk-ITPEXLHA.js";
|
|
8
10
|
import "../chunk-MXSSG3QU.js";
|
|
9
|
-
import "../chunk-
|
|
10
|
-
import "../chunk-
|
|
11
|
+
import "../chunk-IOALNTAN.js";
|
|
12
|
+
import "../chunk-2CDEETQN.js";
|
|
11
13
|
import "../chunk-FHFUXL6G.js";
|
|
12
|
-
import "../chunk-
|
|
14
|
+
import "../chunk-Z2XBWN7A.js";
|
|
13
15
|
export {
|
|
14
16
|
observeCommand,
|
|
15
17
|
registerObserveCommand
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { ProjectStatus, Project } from '../lib/project-utils.js';
|
|
2
|
+
import '../lib/task-utils.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Project command for ClawVault
|
|
6
|
+
* Manages project add/update/archive/list/show/tasks/board operations
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
interface ProjectAddOptions {
|
|
10
|
+
status?: ProjectStatus;
|
|
11
|
+
owner?: string;
|
|
12
|
+
team?: string[];
|
|
13
|
+
client?: string;
|
|
14
|
+
tags?: string[];
|
|
15
|
+
description?: string;
|
|
16
|
+
deadline?: string;
|
|
17
|
+
repo?: string;
|
|
18
|
+
url?: string;
|
|
19
|
+
content?: string;
|
|
20
|
+
}
|
|
21
|
+
interface ProjectUpdateOptions {
|
|
22
|
+
status?: ProjectStatus;
|
|
23
|
+
owner?: string | null;
|
|
24
|
+
team?: string[] | null;
|
|
25
|
+
client?: string | null;
|
|
26
|
+
tags?: string[] | null;
|
|
27
|
+
description?: string | null;
|
|
28
|
+
deadline?: string | null;
|
|
29
|
+
repo?: string | null;
|
|
30
|
+
url?: string | null;
|
|
31
|
+
}
|
|
32
|
+
interface ProjectArchiveOptions {
|
|
33
|
+
reason?: string;
|
|
34
|
+
}
|
|
35
|
+
interface ProjectListOptions {
|
|
36
|
+
status?: ProjectStatus;
|
|
37
|
+
owner?: string;
|
|
38
|
+
client?: string;
|
|
39
|
+
tag?: string;
|
|
40
|
+
json?: boolean;
|
|
41
|
+
}
|
|
42
|
+
interface ProjectShowOptions {
|
|
43
|
+
json?: boolean;
|
|
44
|
+
}
|
|
45
|
+
interface ProjectTasksOptions {
|
|
46
|
+
json?: boolean;
|
|
47
|
+
}
|
|
48
|
+
type ProjectBoardGroupBy = 'status' | 'owner' | 'client';
|
|
49
|
+
interface ProjectBoardOptions {
|
|
50
|
+
output?: string;
|
|
51
|
+
groupBy?: ProjectBoardGroupBy | string;
|
|
52
|
+
now?: Date;
|
|
53
|
+
}
|
|
54
|
+
interface ProjectBoardLane {
|
|
55
|
+
name: string;
|
|
56
|
+
cards: string[];
|
|
57
|
+
}
|
|
58
|
+
interface ProjectBoardResult {
|
|
59
|
+
outputPath: string;
|
|
60
|
+
groupBy: ProjectBoardGroupBy;
|
|
61
|
+
markdown: string;
|
|
62
|
+
lanes: ProjectBoardLane[];
|
|
63
|
+
projectCount: number;
|
|
64
|
+
}
|
|
65
|
+
declare function buildProjectBoardLanes(projects: Project[], groupBy: ProjectBoardGroupBy): ProjectBoardLane[];
|
|
66
|
+
declare function generateProjectBoardMarkdown(projects: Project[], options?: {
|
|
67
|
+
groupBy?: ProjectBoardGroupBy | string;
|
|
68
|
+
now?: Date;
|
|
69
|
+
}): string;
|
|
70
|
+
declare function syncProjectBoard(vaultPath: string, options?: ProjectBoardOptions): ProjectBoardResult;
|
|
71
|
+
declare function projectAdd(vaultPath: string, title: string, options?: ProjectAddOptions): Project;
|
|
72
|
+
declare function projectUpdate(vaultPath: string, slug: string, options: ProjectUpdateOptions): Project;
|
|
73
|
+
declare function projectArchive(vaultPath: string, slug: string, options?: ProjectArchiveOptions): Project;
|
|
74
|
+
declare function projectList(vaultPath: string, options?: ProjectListOptions): Project[];
|
|
75
|
+
declare function formatProjectList(projects: Project[]): string;
|
|
76
|
+
declare function formatProjectDetails(vaultPath: string, project: Project, options?: {
|
|
77
|
+
activityLimit?: number;
|
|
78
|
+
}): string;
|
|
79
|
+
declare function projectCommand(vaultPath: string, action: 'add' | 'update' | 'archive' | 'list' | 'show' | 'tasks' | 'board', args: {
|
|
80
|
+
title?: string;
|
|
81
|
+
slug?: string;
|
|
82
|
+
options?: ProjectAddOptions & ProjectUpdateOptions & ProjectArchiveOptions & ProjectListOptions & ProjectShowOptions & ProjectTasksOptions & ProjectBoardOptions;
|
|
83
|
+
}): Promise<void>;
|
|
84
|
+
|
|
85
|
+
export { type ProjectAddOptions, type ProjectArchiveOptions, type ProjectBoardGroupBy, type ProjectBoardLane, type ProjectBoardOptions, type ProjectBoardResult, type ProjectListOptions, type ProjectShowOptions, type ProjectTasksOptions, type ProjectUpdateOptions, buildProjectBoardLanes, formatProjectDetails, formatProjectList, generateProjectBoardMarkdown, projectAdd, projectArchive, projectCommand, projectList, projectUpdate, syncProjectBoard };
|
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
import {
|
|
2
|
+
formatTaskList,
|
|
3
|
+
taskList
|
|
4
|
+
} from "../chunk-YCVDVI5B.js";
|
|
5
|
+
import {
|
|
6
|
+
archiveProject,
|
|
7
|
+
createProject,
|
|
8
|
+
getProjectActivity,
|
|
9
|
+
getProjectTasks,
|
|
10
|
+
listProjects,
|
|
11
|
+
readProject,
|
|
12
|
+
updateProject
|
|
13
|
+
} from "../chunk-5GZFTAL7.js";
|
|
14
|
+
import "../chunk-IOALNTAN.js";
|
|
15
|
+
|
|
16
|
+
// src/commands/project.ts
|
|
17
|
+
import * as fs from "fs";
|
|
18
|
+
import * as path from "path";
|
|
19
|
+
function toDateStr(value) {
|
|
20
|
+
if (!value) return "-";
|
|
21
|
+
return value.includes("T") ? value.split("T")[0] : value;
|
|
22
|
+
}
|
|
23
|
+
function toHashTag(value) {
|
|
24
|
+
return value.trim().replace(/\s+/g, "-").replace(/[^A-Za-z0-9/_-]/g, "");
|
|
25
|
+
}
|
|
26
|
+
function toMention(value) {
|
|
27
|
+
return value.trim().replace(/\s+/g, "-").replace(/[^A-Za-z0-9._-]/g, "");
|
|
28
|
+
}
|
|
29
|
+
function normalizeBoardGroupBy(value) {
|
|
30
|
+
const normalized = String(value || "status").trim().toLowerCase();
|
|
31
|
+
if (normalized === "status" || normalized === "owner" || normalized === "client") {
|
|
32
|
+
return normalized;
|
|
33
|
+
}
|
|
34
|
+
throw new Error(`Unsupported project board group field: ${normalized}`);
|
|
35
|
+
}
|
|
36
|
+
function resolveBoardPath(vaultPath, output) {
|
|
37
|
+
const resolvedVaultPath = path.resolve(vaultPath);
|
|
38
|
+
if (!output) {
|
|
39
|
+
return path.join(resolvedVaultPath, "Projects-Board.md");
|
|
40
|
+
}
|
|
41
|
+
if (path.isAbsolute(output)) {
|
|
42
|
+
return output;
|
|
43
|
+
}
|
|
44
|
+
return path.join(resolvedVaultPath, output);
|
|
45
|
+
}
|
|
46
|
+
function parseDeadlineTimestamp(project) {
|
|
47
|
+
if (!project.frontmatter.deadline) return Number.POSITIVE_INFINITY;
|
|
48
|
+
const timestamp = Date.parse(project.frontmatter.deadline);
|
|
49
|
+
return Number.isNaN(timestamp) ? Number.POSITIVE_INFINITY : timestamp;
|
|
50
|
+
}
|
|
51
|
+
function sortProjectsForCards(projects) {
|
|
52
|
+
return [...projects].sort((left, right) => {
|
|
53
|
+
const deadlineDiff = parseDeadlineTimestamp(left) - parseDeadlineTimestamp(right);
|
|
54
|
+
if (deadlineDiff !== 0) return deadlineDiff;
|
|
55
|
+
return new Date(right.frontmatter.updated).getTime() - new Date(left.frontmatter.updated).getTime();
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
function laneNameForStatus(status) {
|
|
59
|
+
switch (status) {
|
|
60
|
+
case "active":
|
|
61
|
+
return "Active";
|
|
62
|
+
case "paused":
|
|
63
|
+
return "Paused";
|
|
64
|
+
case "completed":
|
|
65
|
+
return "Completed";
|
|
66
|
+
case "archived":
|
|
67
|
+
return "Archived";
|
|
68
|
+
default:
|
|
69
|
+
return "Active";
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
function laneNameForProject(project, groupBy) {
|
|
73
|
+
switch (groupBy) {
|
|
74
|
+
case "status":
|
|
75
|
+
return laneNameForStatus(project.frontmatter.status);
|
|
76
|
+
case "owner":
|
|
77
|
+
return project.frontmatter.owner?.trim() || "Unassigned";
|
|
78
|
+
case "client":
|
|
79
|
+
return project.frontmatter.client?.trim() || "No Client";
|
|
80
|
+
default:
|
|
81
|
+
return laneNameForStatus(project.frontmatter.status);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
function defaultLaneOrder(groupBy, projects) {
|
|
85
|
+
if (groupBy === "status") {
|
|
86
|
+
return ["Active", "Paused", "Completed", "Archived"];
|
|
87
|
+
}
|
|
88
|
+
const fallback = groupBy === "owner" ? "Unassigned" : "No Client";
|
|
89
|
+
const names = /* @__PURE__ */ new Set();
|
|
90
|
+
for (const project of projects) {
|
|
91
|
+
names.add(laneNameForProject(project, groupBy));
|
|
92
|
+
}
|
|
93
|
+
if (names.size === 0) {
|
|
94
|
+
return [fallback];
|
|
95
|
+
}
|
|
96
|
+
const sorted = Array.from(names).sort((left, right) => left.localeCompare(right));
|
|
97
|
+
if (sorted.includes(fallback)) {
|
|
98
|
+
return [...sorted.filter((name) => name !== fallback), fallback];
|
|
99
|
+
}
|
|
100
|
+
return sorted;
|
|
101
|
+
}
|
|
102
|
+
function formatProjectCard(project) {
|
|
103
|
+
const checkbox = project.frontmatter.status === "completed" || project.frontmatter.status === "archived" ? "x" : " ";
|
|
104
|
+
const parts = [`[[projects/${project.slug}|${project.title}]]`];
|
|
105
|
+
if (project.frontmatter.owner) {
|
|
106
|
+
const mention = toMention(project.frontmatter.owner);
|
|
107
|
+
if (mention) parts.push(`@${mention}`);
|
|
108
|
+
}
|
|
109
|
+
if (project.frontmatter.client) {
|
|
110
|
+
const clientTag = toHashTag(project.frontmatter.client);
|
|
111
|
+
if (clientTag) parts.push(`#client/${clientTag}`);
|
|
112
|
+
}
|
|
113
|
+
if (project.frontmatter.tags && project.frontmatter.tags.length > 0) {
|
|
114
|
+
for (const tag of project.frontmatter.tags) {
|
|
115
|
+
const normalizedTag = toHashTag(tag);
|
|
116
|
+
if (normalizedTag) parts.push(`#${normalizedTag}`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (project.frontmatter.deadline) {
|
|
120
|
+
parts.push(`\u{1F4C5} ${toDateStr(project.frontmatter.deadline)}`);
|
|
121
|
+
}
|
|
122
|
+
if (project.frontmatter.description) {
|
|
123
|
+
parts.push(`\u2014 ${project.frontmatter.description}`);
|
|
124
|
+
}
|
|
125
|
+
return `- [${checkbox}] ${parts.join(" ")}`;
|
|
126
|
+
}
|
|
127
|
+
function buildProjectBoardLanes(projects, groupBy) {
|
|
128
|
+
const laneOrder = defaultLaneOrder(groupBy, projects);
|
|
129
|
+
const lanes = /* @__PURE__ */ new Map();
|
|
130
|
+
for (const laneName of laneOrder) {
|
|
131
|
+
lanes.set(laneName, []);
|
|
132
|
+
}
|
|
133
|
+
for (const project of sortProjectsForCards(projects)) {
|
|
134
|
+
const laneName = laneNameForProject(project, groupBy);
|
|
135
|
+
if (!lanes.has(laneName)) {
|
|
136
|
+
lanes.set(laneName, []);
|
|
137
|
+
}
|
|
138
|
+
lanes.get(laneName)?.push(formatProjectCard(project));
|
|
139
|
+
}
|
|
140
|
+
return Array.from(lanes.entries()).map(([name, cards]) => ({ name, cards }));
|
|
141
|
+
}
|
|
142
|
+
function generateProjectBoardMarkdown(projects, options = {}) {
|
|
143
|
+
const groupBy = normalizeBoardGroupBy(options.groupBy);
|
|
144
|
+
const syncedAt = (options.now || /* @__PURE__ */ new Date()).toISOString();
|
|
145
|
+
const lanes = buildProjectBoardLanes(projects, groupBy);
|
|
146
|
+
const sections = lanes.map((lane) => {
|
|
147
|
+
const cardsBlock = lane.cards.length > 0 ? lane.cards.join("\n") : "";
|
|
148
|
+
return `## ${lane.name}
|
|
149
|
+
|
|
150
|
+
${cardsBlock}`.trimEnd();
|
|
151
|
+
}).join("\n\n");
|
|
152
|
+
return [
|
|
153
|
+
"---",
|
|
154
|
+
"kanban-plugin: basic",
|
|
155
|
+
`clawvault-group-by: ${groupBy}`,
|
|
156
|
+
`clawvault-last-sync: '${syncedAt}'`,
|
|
157
|
+
"---",
|
|
158
|
+
"",
|
|
159
|
+
sections,
|
|
160
|
+
"",
|
|
161
|
+
"%% kanban:settings",
|
|
162
|
+
'{"kanban-plugin":"basic","list-collapse":["Completed","Archived"],"show-checkboxes":true}',
|
|
163
|
+
"%%",
|
|
164
|
+
""
|
|
165
|
+
].join("\n");
|
|
166
|
+
}
|
|
167
|
+
function syncProjectBoard(vaultPath, options = {}) {
|
|
168
|
+
const groupBy = normalizeBoardGroupBy(options.groupBy);
|
|
169
|
+
const outputPath = resolveBoardPath(vaultPath, options.output);
|
|
170
|
+
const projects = listProjects(vaultPath);
|
|
171
|
+
const markdown = generateProjectBoardMarkdown(projects, { groupBy, now: options.now });
|
|
172
|
+
fs.writeFileSync(outputPath, markdown);
|
|
173
|
+
return {
|
|
174
|
+
outputPath,
|
|
175
|
+
groupBy,
|
|
176
|
+
markdown,
|
|
177
|
+
lanes: buildProjectBoardLanes(projects, groupBy),
|
|
178
|
+
projectCount: projects.length
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
function projectAdd(vaultPath, title, options = {}) {
|
|
182
|
+
return createProject(vaultPath, title, {
|
|
183
|
+
status: options.status,
|
|
184
|
+
owner: options.owner,
|
|
185
|
+
team: options.team,
|
|
186
|
+
client: options.client,
|
|
187
|
+
tags: options.tags,
|
|
188
|
+
description: options.description,
|
|
189
|
+
deadline: options.deadline,
|
|
190
|
+
repo: options.repo,
|
|
191
|
+
url: options.url,
|
|
192
|
+
content: options.content
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
function projectUpdate(vaultPath, slug, options) {
|
|
196
|
+
return updateProject(vaultPath, slug, {
|
|
197
|
+
status: options.status,
|
|
198
|
+
owner: options.owner,
|
|
199
|
+
team: options.team,
|
|
200
|
+
client: options.client,
|
|
201
|
+
tags: options.tags,
|
|
202
|
+
description: options.description,
|
|
203
|
+
deadline: options.deadline,
|
|
204
|
+
repo: options.repo,
|
|
205
|
+
url: options.url
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
function projectArchive(vaultPath, slug, options = {}) {
|
|
209
|
+
return archiveProject(vaultPath, slug, options.reason);
|
|
210
|
+
}
|
|
211
|
+
function projectList(vaultPath, options = {}) {
|
|
212
|
+
const projects = listProjects(vaultPath, {
|
|
213
|
+
status: options.status,
|
|
214
|
+
owner: options.owner,
|
|
215
|
+
client: options.client,
|
|
216
|
+
tag: options.tag
|
|
217
|
+
});
|
|
218
|
+
if (!options.status) {
|
|
219
|
+
return projects.filter((project) => project.frontmatter.status !== "archived");
|
|
220
|
+
}
|
|
221
|
+
return projects;
|
|
222
|
+
}
|
|
223
|
+
function formatProjectList(projects) {
|
|
224
|
+
if (projects.length === 0) {
|
|
225
|
+
return "No projects found.\n";
|
|
226
|
+
}
|
|
227
|
+
const headers = ["STATUS", "OWNER", "DEADLINE", "TITLE"];
|
|
228
|
+
const widths = [10, 12, 12, 40];
|
|
229
|
+
const truncate = (value, width) => {
|
|
230
|
+
if (value.length <= width) return value;
|
|
231
|
+
return value.slice(0, width - 3) + "...";
|
|
232
|
+
};
|
|
233
|
+
let output = headers.map((header, index) => header.padEnd(widths[index])).join(" ") + "\n";
|
|
234
|
+
for (const project of projects) {
|
|
235
|
+
const row = [
|
|
236
|
+
project.frontmatter.status.padEnd(widths[0]),
|
|
237
|
+
(project.frontmatter.owner || "-").padEnd(widths[1]),
|
|
238
|
+
toDateStr(project.frontmatter.deadline).padEnd(widths[2]),
|
|
239
|
+
truncate(project.title, widths[3])
|
|
240
|
+
];
|
|
241
|
+
output += row.join(" ") + "\n";
|
|
242
|
+
}
|
|
243
|
+
return output;
|
|
244
|
+
}
|
|
245
|
+
function formatFieldValue(value) {
|
|
246
|
+
if (Array.isArray(value)) {
|
|
247
|
+
return value.join(", ");
|
|
248
|
+
}
|
|
249
|
+
if (typeof value === "string") {
|
|
250
|
+
return value;
|
|
251
|
+
}
|
|
252
|
+
if (value === null || value === void 0) {
|
|
253
|
+
return "-";
|
|
254
|
+
}
|
|
255
|
+
return String(value);
|
|
256
|
+
}
|
|
257
|
+
function countTasksByStatus(projectSlug, vaultPath) {
|
|
258
|
+
const tasks = getProjectTasks(vaultPath, projectSlug);
|
|
259
|
+
return {
|
|
260
|
+
open: tasks.filter((task) => task.frontmatter.status === "open").length,
|
|
261
|
+
inProgress: tasks.filter((task) => task.frontmatter.status === "in-progress").length,
|
|
262
|
+
done: tasks.filter((task) => task.frontmatter.status === "done").length
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
function formatProjectDetails(vaultPath, project, options = {}) {
|
|
266
|
+
const lines = [];
|
|
267
|
+
const taskSummary = countTasksByStatus(project.slug, vaultPath);
|
|
268
|
+
const activity = getProjectActivity(vaultPath, project.slug).slice(0, options.activityLimit ?? 5);
|
|
269
|
+
lines.push(`# ${project.title}`);
|
|
270
|
+
lines.push("-".repeat(40));
|
|
271
|
+
const orderedFields = [
|
|
272
|
+
"type",
|
|
273
|
+
"status",
|
|
274
|
+
"owner",
|
|
275
|
+
"team",
|
|
276
|
+
"client",
|
|
277
|
+
"tags",
|
|
278
|
+
"description",
|
|
279
|
+
"started",
|
|
280
|
+
"deadline",
|
|
281
|
+
"repo",
|
|
282
|
+
"url",
|
|
283
|
+
"created",
|
|
284
|
+
"updated",
|
|
285
|
+
"completed",
|
|
286
|
+
"reason"
|
|
287
|
+
];
|
|
288
|
+
for (const field of orderedFields) {
|
|
289
|
+
const value = project.frontmatter[field];
|
|
290
|
+
if (value === void 0) continue;
|
|
291
|
+
lines.push(`${field}: ${formatFieldValue(value)}`);
|
|
292
|
+
}
|
|
293
|
+
lines.push("");
|
|
294
|
+
lines.push(`Linked tasks: ${taskSummary.open} open, ${taskSummary.inProgress} in-progress, ${taskSummary.done} done`);
|
|
295
|
+
if (project.frontmatter.team && project.frontmatter.team.length > 0) {
|
|
296
|
+
lines.push("Team members:");
|
|
297
|
+
for (const member of project.frontmatter.team) {
|
|
298
|
+
lines.push(`- ${member}`);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
lines.push("");
|
|
302
|
+
lines.push("Recent activity:");
|
|
303
|
+
if (activity.length === 0) {
|
|
304
|
+
lines.push("- none");
|
|
305
|
+
} else {
|
|
306
|
+
for (const filePath of activity) {
|
|
307
|
+
lines.push(`- ${path.basename(filePath)}`);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
return lines.join("\n");
|
|
311
|
+
}
|
|
312
|
+
async function projectCommand(vaultPath, action, args) {
|
|
313
|
+
const options = args.options || {};
|
|
314
|
+
switch (action) {
|
|
315
|
+
case "add": {
|
|
316
|
+
if (!args.title) {
|
|
317
|
+
throw new Error("Title is required for project add");
|
|
318
|
+
}
|
|
319
|
+
const project = projectAdd(vaultPath, args.title, options);
|
|
320
|
+
console.log(`\u2713 Created project: ${project.slug}`);
|
|
321
|
+
console.log(` Path: ${path.join(path.resolve(vaultPath), "projects", `${project.slug}.md`)}`);
|
|
322
|
+
break;
|
|
323
|
+
}
|
|
324
|
+
case "update": {
|
|
325
|
+
if (!args.slug) {
|
|
326
|
+
throw new Error("Project slug is required for update");
|
|
327
|
+
}
|
|
328
|
+
const project = projectUpdate(vaultPath, args.slug, options);
|
|
329
|
+
console.log(`\u2713 Updated project: ${project.slug}`);
|
|
330
|
+
break;
|
|
331
|
+
}
|
|
332
|
+
case "archive": {
|
|
333
|
+
if (!args.slug) {
|
|
334
|
+
throw new Error("Project slug is required for archive");
|
|
335
|
+
}
|
|
336
|
+
const project = projectArchive(vaultPath, args.slug, options);
|
|
337
|
+
console.log(`\u2713 Archived project: ${project.slug}`);
|
|
338
|
+
break;
|
|
339
|
+
}
|
|
340
|
+
case "list": {
|
|
341
|
+
const projects = projectList(vaultPath, options);
|
|
342
|
+
if (options.json) {
|
|
343
|
+
console.log(JSON.stringify(projects, null, 2));
|
|
344
|
+
} else {
|
|
345
|
+
console.log(formatProjectList(projects));
|
|
346
|
+
}
|
|
347
|
+
break;
|
|
348
|
+
}
|
|
349
|
+
case "show": {
|
|
350
|
+
if (!args.slug) {
|
|
351
|
+
throw new Error("Project slug is required for show");
|
|
352
|
+
}
|
|
353
|
+
const project = readProject(vaultPath, args.slug);
|
|
354
|
+
if (!project) {
|
|
355
|
+
throw new Error(`Project not found: ${args.slug}`);
|
|
356
|
+
}
|
|
357
|
+
const taskSummary = countTasksByStatus(project.slug, vaultPath);
|
|
358
|
+
const recentActivity = getProjectActivity(vaultPath, project.slug).slice(0, 5);
|
|
359
|
+
if (options.json) {
|
|
360
|
+
console.log(
|
|
361
|
+
JSON.stringify(
|
|
362
|
+
{
|
|
363
|
+
project,
|
|
364
|
+
taskSummary,
|
|
365
|
+
team: project.frontmatter.team || [],
|
|
366
|
+
recentActivity
|
|
367
|
+
},
|
|
368
|
+
null,
|
|
369
|
+
2
|
|
370
|
+
)
|
|
371
|
+
);
|
|
372
|
+
} else {
|
|
373
|
+
console.log(formatProjectDetails(vaultPath, project, { activityLimit: 5 }));
|
|
374
|
+
}
|
|
375
|
+
break;
|
|
376
|
+
}
|
|
377
|
+
case "tasks": {
|
|
378
|
+
if (!args.slug) {
|
|
379
|
+
throw new Error("Project slug is required for tasks");
|
|
380
|
+
}
|
|
381
|
+
const tasks = taskList(vaultPath, { project: args.slug });
|
|
382
|
+
if (options.json) {
|
|
383
|
+
console.log(JSON.stringify(tasks, null, 2));
|
|
384
|
+
} else {
|
|
385
|
+
console.log(formatTaskList(tasks));
|
|
386
|
+
}
|
|
387
|
+
break;
|
|
388
|
+
}
|
|
389
|
+
case "board": {
|
|
390
|
+
const result = syncProjectBoard(vaultPath, options);
|
|
391
|
+
console.log(`\u2713 Synced project board: ${result.outputPath}`);
|
|
392
|
+
console.log(` Grouped by: ${result.groupBy}`);
|
|
393
|
+
console.log(` Projects included: ${result.projectCount}`);
|
|
394
|
+
break;
|
|
395
|
+
}
|
|
396
|
+
default:
|
|
397
|
+
throw new Error(`Unknown project action: ${action}`);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
export {
|
|
401
|
+
buildProjectBoardLanes,
|
|
402
|
+
formatProjectDetails,
|
|
403
|
+
formatProjectList,
|
|
404
|
+
generateProjectBoardMarkdown,
|
|
405
|
+
projectAdd,
|
|
406
|
+
projectArchive,
|
|
407
|
+
projectCommand,
|
|
408
|
+
projectList,
|
|
409
|
+
projectUpdate,
|
|
410
|
+
syncProjectBoard
|
|
411
|
+
};
|
package/dist/commands/rebuild.js
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
rebuildCommand,
|
|
3
3
|
registerRebuildCommand
|
|
4
|
-
} from "../chunk-
|
|
5
|
-
import "../chunk-
|
|
4
|
+
} from "../chunk-LMCC5OC7.js";
|
|
5
|
+
import "../chunk-TMZMN7OS.js";
|
|
6
|
+
import "../chunk-5GZFTAL7.js";
|
|
7
|
+
import "../chunk-ITPEXLHA.js";
|
|
6
8
|
import "../chunk-MXSSG3QU.js";
|
|
7
|
-
import "../chunk-
|
|
8
|
-
import "../chunk-
|
|
9
|
+
import "../chunk-IOALNTAN.js";
|
|
10
|
+
import "../chunk-2CDEETQN.js";
|
|
9
11
|
import "../chunk-FHFUXL6G.js";
|
|
10
|
-
import "../chunk-
|
|
12
|
+
import "../chunk-Z2XBWN7A.js";
|
|
11
13
|
export {
|
|
12
14
|
rebuildCommand,
|
|
13
15
|
registerRebuildCommand
|
package/dist/commands/reflect.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
reflectCommand,
|
|
3
3
|
registerReflectCommand
|
|
4
|
-
} from "../chunk-
|
|
5
|
-
import "../chunk-
|
|
6
|
-
import "../chunk-
|
|
4
|
+
} from "../chunk-G3OQJ2NQ.js";
|
|
5
|
+
import "../chunk-KCCHROBR.js";
|
|
6
|
+
import "../chunk-K3CDT7IH.js";
|
|
7
|
+
import "../chunk-MQUJNOHK.js";
|
|
7
8
|
import "../chunk-MXSSG3QU.js";
|
|
8
9
|
import "../chunk-FHFUXL6G.js";
|
|
9
|
-
import "../chunk-
|
|
10
|
+
import "../chunk-Z2XBWN7A.js";
|
|
10
11
|
export {
|
|
11
12
|
reflectCommand,
|
|
12
13
|
registerReflectCommand
|
package/dist/commands/replay.js
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
import {
|
|
2
2
|
registerReplayCommand,
|
|
3
3
|
replayCommand
|
|
4
|
-
} from "../chunk-
|
|
5
|
-
import "../chunk-
|
|
6
|
-
import "../chunk-
|
|
7
|
-
import "../chunk-
|
|
4
|
+
} from "../chunk-C3PF7WBA.js";
|
|
5
|
+
import "../chunk-KCCHROBR.js";
|
|
6
|
+
import "../chunk-K3CDT7IH.js";
|
|
7
|
+
import "../chunk-TMZMN7OS.js";
|
|
8
|
+
import "../chunk-5GZFTAL7.js";
|
|
9
|
+
import "../chunk-ITPEXLHA.js";
|
|
10
|
+
import "../chunk-MQUJNOHK.js";
|
|
8
11
|
import "../chunk-MXSSG3QU.js";
|
|
9
|
-
import "../chunk-
|
|
10
|
-
import "../chunk-
|
|
12
|
+
import "../chunk-IOALNTAN.js";
|
|
13
|
+
import "../chunk-2CDEETQN.js";
|
|
11
14
|
import "../chunk-FHFUXL6G.js";
|
|
12
|
-
import "../chunk-
|
|
15
|
+
import "../chunk-Z2XBWN7A.js";
|
|
13
16
|
export {
|
|
14
17
|
registerReplayCommand,
|
|
15
18
|
replayCommand
|
package/dist/commands/setup.d.ts
CHANGED