@evref-bl/dev-nexus 0.1.0-alpha.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 +677 -0
- package/dist/browserOpener.d.ts +9 -0
- package/dist/browserOpener.js +47 -0
- package/dist/cli.d.ts +18 -0
- package/dist/cli.js +2374 -0
- package/dist/gitWorktreeService.d.ts +57 -0
- package/dist/gitWorktreeService.js +157 -0
- package/dist/index.d.ts +47 -0
- package/dist/index.js +47 -0
- package/dist/nexusAgentMcpConfig.d.ts +30 -0
- package/dist/nexusAgentMcpConfig.js +228 -0
- package/dist/nexusAutomation.d.ts +103 -0
- package/dist/nexusAutomation.js +390 -0
- package/dist/nexusAutomationAgentLaunch.d.ts +148 -0
- package/dist/nexusAutomationAgentLaunch.js +855 -0
- package/dist/nexusAutomationAgentProfile.d.ts +39 -0
- package/dist/nexusAutomationAgentProfile.js +103 -0
- package/dist/nexusAutomationAgentSurface.d.ts +62 -0
- package/dist/nexusAutomationAgentSurface.js +90 -0
- package/dist/nexusAutomationCommandExecutor.d.ts +29 -0
- package/dist/nexusAutomationCommandExecutor.js +251 -0
- package/dist/nexusAutomationConfig.d.ts +114 -0
- package/dist/nexusAutomationConfig.js +547 -0
- package/dist/nexusAutomationEnqueue.d.ts +37 -0
- package/dist/nexusAutomationEnqueue.js +128 -0
- package/dist/nexusAutomationRunOnce.d.ts +91 -0
- package/dist/nexusAutomationRunOnce.js +586 -0
- package/dist/nexusAutomationScheduler.d.ts +50 -0
- package/dist/nexusAutomationScheduler.js +196 -0
- package/dist/nexusAutomationStatus.d.ts +55 -0
- package/dist/nexusAutomationStatus.js +462 -0
- package/dist/nexusAutomationTarget.d.ts +19 -0
- package/dist/nexusAutomationTarget.js +33 -0
- package/dist/nexusAutomationTargetCycle.d.ts +90 -0
- package/dist/nexusAutomationTargetCycle.js +282 -0
- package/dist/nexusAutomationTargetReport.d.ts +136 -0
- package/dist/nexusAutomationTargetReport.js +504 -0
- package/dist/nexusAutomationWorktreeSetup.d.ts +89 -0
- package/dist/nexusAutomationWorktreeSetup.js +661 -0
- package/dist/nexusCoordination.d.ts +198 -0
- package/dist/nexusCoordination.js +1018 -0
- package/dist/nexusExtension.d.ts +31 -0
- package/dist/nexusExtension.js +1 -0
- package/dist/nexusHomeConfig.d.ts +38 -0
- package/dist/nexusHomeConfig.js +133 -0
- package/dist/nexusMcpServer.d.ts +31 -0
- package/dist/nexusMcpServer.js +1036 -0
- package/dist/nexusPluginCapabilities.d.ts +197 -0
- package/dist/nexusPluginCapabilities.js +201 -0
- package/dist/nexusProjectConfig.d.ts +95 -0
- package/dist/nexusProjectConfig.js +880 -0
- package/dist/nexusProjectHomeService.d.ts +121 -0
- package/dist/nexusProjectHomeService.js +171 -0
- package/dist/nexusProjectLifecycle.d.ts +62 -0
- package/dist/nexusProjectLifecycle.js +205 -0
- package/dist/nexusProjectOperations.d.ts +101 -0
- package/dist/nexusProjectOperations.js +296 -0
- package/dist/nexusProjectRegistry.d.ts +42 -0
- package/dist/nexusProjectRegistry.js +91 -0
- package/dist/nexusProjectScaffold.d.ts +25 -0
- package/dist/nexusProjectScaffold.js +61 -0
- package/dist/nexusProjectTemplate.d.ts +34 -0
- package/dist/nexusProjectTemplate.js +354 -0
- package/dist/nexusSkills.d.ts +134 -0
- package/dist/nexusSkills.js +647 -0
- package/dist/nexusWorkerContextBundle.d.ts +142 -0
- package/dist/nexusWorkerContextBundle.js +375 -0
- package/dist/processSupervisor.d.ts +89 -0
- package/dist/processSupervisor.js +440 -0
- package/dist/vibeKanbanApi.d.ts +11 -0
- package/dist/vibeKanbanApi.js +14 -0
- package/dist/vibeKanbanAuth.d.ts +25 -0
- package/dist/vibeKanbanAuth.js +101 -0
- package/dist/vibeKanbanBoardAdapter.d.ts +36 -0
- package/dist/vibeKanbanBoardAdapter.js +196 -0
- package/dist/vibeKanbanMcpConfig.d.ts +36 -0
- package/dist/vibeKanbanMcpConfig.js +191 -0
- package/dist/vibeKanbanProjectAdapter.d.ts +39 -0
- package/dist/vibeKanbanProjectAdapter.js +113 -0
- package/dist/vibeKanbanWorkspaceSetup.d.ts +1 -0
- package/dist/vibeKanbanWorkspaceSetup.js +96 -0
- package/dist/workItemService.d.ts +60 -0
- package/dist/workItemService.js +163 -0
- package/dist/workTrackingGitHubProvider.d.ts +71 -0
- package/dist/workTrackingGitHubProvider.js +663 -0
- package/dist/workTrackingGitLabProvider.d.ts +62 -0
- package/dist/workTrackingGitLabProvider.js +523 -0
- package/dist/workTrackingJiraProvider.d.ts +67 -0
- package/dist/workTrackingJiraProvider.js +652 -0
- package/dist/workTrackingLocalProvider.d.ts +49 -0
- package/dist/workTrackingLocalProvider.js +463 -0
- package/dist/workTrackingProviderService.d.ts +21 -0
- package/dist/workTrackingProviderService.js +117 -0
- package/dist/workTrackingTypes.d.ts +202 -0
- package/dist/workTrackingTypes.js +1 -0
- package/dist/workTrackingVibeProvider.d.ts +35 -0
- package/dist/workTrackingVibeProvider.js +119 -0
- package/dist/worktreeExecutionMetadata.d.ts +76 -0
- package/dist/worktreeExecutionMetadata.js +239 -0
- package/package.json +37 -0
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
export type WorkTrackingProviderName = "local" | "vibe-kanban" | "github" | "gitlab" | "jira";
|
|
2
|
+
export type WorkStatus = "todo" | "ready" | "in_progress" | "blocked" | "done" | "wont_do";
|
|
3
|
+
export interface WorkTrackingRepositoryConfig {
|
|
4
|
+
owner?: string;
|
|
5
|
+
name?: string;
|
|
6
|
+
id?: string;
|
|
7
|
+
path?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface WorkTrackingBoardConfig {
|
|
10
|
+
kind: string;
|
|
11
|
+
id?: string | null;
|
|
12
|
+
number?: number | null;
|
|
13
|
+
owner?: string | null;
|
|
14
|
+
ownerKind?: string | null;
|
|
15
|
+
projectId?: string | null;
|
|
16
|
+
statusFieldId?: string | null;
|
|
17
|
+
statusOptions?: Record<string, string>;
|
|
18
|
+
}
|
|
19
|
+
export interface BaseWorkTrackingConfig {
|
|
20
|
+
provider: WorkTrackingProviderName;
|
|
21
|
+
host?: string | null;
|
|
22
|
+
repository?: WorkTrackingRepositoryConfig;
|
|
23
|
+
board?: WorkTrackingBoardConfig | null;
|
|
24
|
+
}
|
|
25
|
+
export interface LocalWorkTrackingConfig extends BaseWorkTrackingConfig {
|
|
26
|
+
provider: "local";
|
|
27
|
+
storePath?: string | null;
|
|
28
|
+
}
|
|
29
|
+
export interface VibeKanbanWorkTrackingConfig extends BaseWorkTrackingConfig {
|
|
30
|
+
provider: "vibe-kanban";
|
|
31
|
+
projectId?: string | null;
|
|
32
|
+
repoId?: string | null;
|
|
33
|
+
}
|
|
34
|
+
export interface GitHubWorkTrackingConfig extends BaseWorkTrackingConfig {
|
|
35
|
+
provider: "github";
|
|
36
|
+
repository: WorkTrackingRepositoryConfig & {
|
|
37
|
+
owner: string;
|
|
38
|
+
name: string;
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
export interface GitLabWorkTrackingConfig extends BaseWorkTrackingConfig {
|
|
42
|
+
provider: "gitlab";
|
|
43
|
+
repository: WorkTrackingRepositoryConfig & {
|
|
44
|
+
id: string;
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
export interface JiraWorkTrackingConfig extends BaseWorkTrackingConfig {
|
|
48
|
+
provider: "jira";
|
|
49
|
+
projectKey: string;
|
|
50
|
+
issueType?: string | null;
|
|
51
|
+
}
|
|
52
|
+
export type WorkTrackingConfig = LocalWorkTrackingConfig | VibeKanbanWorkTrackingConfig | GitHubWorkTrackingConfig | GitLabWorkTrackingConfig | JiraWorkTrackingConfig;
|
|
53
|
+
export interface ExternalRef {
|
|
54
|
+
provider: WorkTrackingProviderName | string;
|
|
55
|
+
host?: string | null;
|
|
56
|
+
repositoryId?: string | null;
|
|
57
|
+
repositoryOwner?: string | null;
|
|
58
|
+
repositoryName?: string | null;
|
|
59
|
+
projectId?: string | null;
|
|
60
|
+
boardId?: string | null;
|
|
61
|
+
itemId: string;
|
|
62
|
+
itemNumber?: number | null;
|
|
63
|
+
itemKey?: string | null;
|
|
64
|
+
nodeId?: string | null;
|
|
65
|
+
webUrl?: string | null;
|
|
66
|
+
}
|
|
67
|
+
export interface WorkBoard {
|
|
68
|
+
id: string;
|
|
69
|
+
name: string;
|
|
70
|
+
provider: WorkTrackingProviderName | string;
|
|
71
|
+
externalRef?: ExternalRef;
|
|
72
|
+
webUrl?: string | null;
|
|
73
|
+
}
|
|
74
|
+
export interface WorkComment {
|
|
75
|
+
id: string;
|
|
76
|
+
body: string;
|
|
77
|
+
author?: string | null;
|
|
78
|
+
createdAt?: string | null;
|
|
79
|
+
updatedAt?: string | null;
|
|
80
|
+
externalRef?: ExternalRef;
|
|
81
|
+
}
|
|
82
|
+
export interface WorkItem {
|
|
83
|
+
id: string;
|
|
84
|
+
title: string;
|
|
85
|
+
description?: string | null;
|
|
86
|
+
status: WorkStatus;
|
|
87
|
+
provider: WorkTrackingProviderName | string;
|
|
88
|
+
labels?: string[];
|
|
89
|
+
assignees?: string[];
|
|
90
|
+
milestone?: string | null;
|
|
91
|
+
createdAt?: string | null;
|
|
92
|
+
updatedAt?: string | null;
|
|
93
|
+
closedAt?: string | null;
|
|
94
|
+
webUrl?: string | null;
|
|
95
|
+
externalRef?: ExternalRef;
|
|
96
|
+
}
|
|
97
|
+
export interface WorkItemRef {
|
|
98
|
+
provider?: WorkTrackingProviderName | string;
|
|
99
|
+
id?: string;
|
|
100
|
+
externalRef?: ExternalRef;
|
|
101
|
+
}
|
|
102
|
+
export interface WorkItemQuery {
|
|
103
|
+
projectRoot?: string;
|
|
104
|
+
status?: WorkStatus | WorkStatus[];
|
|
105
|
+
labels?: string[];
|
|
106
|
+
assignees?: string[];
|
|
107
|
+
search?: string;
|
|
108
|
+
limit?: number;
|
|
109
|
+
}
|
|
110
|
+
export interface CreateWorkItemInput {
|
|
111
|
+
projectRoot?: string;
|
|
112
|
+
title: string;
|
|
113
|
+
description?: string | null;
|
|
114
|
+
status?: WorkStatus;
|
|
115
|
+
labels?: string[];
|
|
116
|
+
assignees?: string[];
|
|
117
|
+
milestone?: string | null;
|
|
118
|
+
}
|
|
119
|
+
export interface WorkItemPatch {
|
|
120
|
+
title?: string;
|
|
121
|
+
description?: string | null;
|
|
122
|
+
status?: WorkStatus;
|
|
123
|
+
labels?: string[];
|
|
124
|
+
assignees?: string[];
|
|
125
|
+
milestone?: string | null;
|
|
126
|
+
}
|
|
127
|
+
export interface TrackerCapabilities {
|
|
128
|
+
createItem: boolean;
|
|
129
|
+
listItems: boolean;
|
|
130
|
+
getItem: boolean;
|
|
131
|
+
updateItem: boolean;
|
|
132
|
+
comment: boolean;
|
|
133
|
+
labels: boolean;
|
|
134
|
+
assignees: boolean;
|
|
135
|
+
milestones: boolean;
|
|
136
|
+
board: boolean;
|
|
137
|
+
boardStatus: boolean;
|
|
138
|
+
draftItems: boolean;
|
|
139
|
+
webhooks: boolean;
|
|
140
|
+
}
|
|
141
|
+
export type WorkTrackerCapabilityName = "create" | "list" | "get" | "update" | "comment" | "labels" | "assignees" | "milestones" | "board" | "boardStatus";
|
|
142
|
+
export interface WorkTrackerActionCapabilities {
|
|
143
|
+
create: boolean;
|
|
144
|
+
list: boolean;
|
|
145
|
+
get: boolean;
|
|
146
|
+
update: boolean;
|
|
147
|
+
comment: boolean;
|
|
148
|
+
labels: boolean;
|
|
149
|
+
assignees: boolean;
|
|
150
|
+
milestones: boolean;
|
|
151
|
+
board: boolean;
|
|
152
|
+
boardStatus: boolean;
|
|
153
|
+
}
|
|
154
|
+
export interface WorkTrackerCapabilityReport {
|
|
155
|
+
provider: WorkTrackingProviderName | string;
|
|
156
|
+
capabilities: WorkTrackerActionCapabilities;
|
|
157
|
+
unsupported: WorkTrackerCapabilityName[];
|
|
158
|
+
}
|
|
159
|
+
export interface TrackerProjectRef {
|
|
160
|
+
provider: WorkTrackingProviderName | string;
|
|
161
|
+
id: string;
|
|
162
|
+
name?: string;
|
|
163
|
+
externalRef?: ExternalRef;
|
|
164
|
+
}
|
|
165
|
+
export interface TrackerBoardRef {
|
|
166
|
+
provider: WorkTrackingProviderName | string;
|
|
167
|
+
id: string;
|
|
168
|
+
name?: string;
|
|
169
|
+
externalRef?: ExternalRef;
|
|
170
|
+
}
|
|
171
|
+
export interface DetectedTracker {
|
|
172
|
+
confidence: "low" | "medium" | "high";
|
|
173
|
+
config: WorkTrackingConfig;
|
|
174
|
+
reason?: string;
|
|
175
|
+
}
|
|
176
|
+
export interface DetectTrackerInput {
|
|
177
|
+
projectRoot: string;
|
|
178
|
+
remoteUrl?: string | null;
|
|
179
|
+
}
|
|
180
|
+
export interface NexusProjectContext {
|
|
181
|
+
homePath: string;
|
|
182
|
+
projectRoot: string;
|
|
183
|
+
projectId: string;
|
|
184
|
+
projectName: string;
|
|
185
|
+
componentId?: string;
|
|
186
|
+
componentName?: string;
|
|
187
|
+
sourceRoot?: string;
|
|
188
|
+
workTracking?: WorkTrackingConfig;
|
|
189
|
+
}
|
|
190
|
+
export interface WorkTrackerProvider {
|
|
191
|
+
provider: WorkTrackingProviderName | string;
|
|
192
|
+
capabilities: TrackerCapabilities;
|
|
193
|
+
detect?(input: DetectTrackerInput): Promise<DetectedTracker | undefined>;
|
|
194
|
+
ensureProject?(context: NexusProjectContext): Promise<TrackerProjectRef>;
|
|
195
|
+
ensureBoard?(context: NexusProjectContext): Promise<TrackerBoardRef>;
|
|
196
|
+
createWorkItem(input: CreateWorkItemInput): Promise<WorkItem>;
|
|
197
|
+
listWorkItems(query: WorkItemQuery): Promise<WorkItem[]>;
|
|
198
|
+
getWorkItem(ref: WorkItemRef): Promise<WorkItem>;
|
|
199
|
+
updateWorkItem(ref: WorkItemRef, patch: WorkItemPatch): Promise<WorkItem>;
|
|
200
|
+
addComment(ref: WorkItemRef, body: string): Promise<WorkComment>;
|
|
201
|
+
setStatus?(ref: WorkItemRef, status: WorkStatus): Promise<WorkItem>;
|
|
202
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { type EnsureVibeKanbanBoardResult } from "./vibeKanbanBoardAdapter.js";
|
|
2
|
+
import { type RegisterVibeKanbanProjectResult } from "./vibeKanbanProjectAdapter.js";
|
|
3
|
+
import type { VibeKanbanApiOptions } from "./vibeKanbanApi.js";
|
|
4
|
+
import type { CreateWorkItemInput, NexusProjectContext, TrackerBoardRef, TrackerCapabilities, TrackerProjectRef, VibeKanbanWorkTrackingConfig, WorkComment, WorkItem, WorkItemPatch, WorkItemQuery, WorkItemRef, WorkStatus, WorkTrackerProvider } from "./workTrackingTypes.js";
|
|
5
|
+
export interface VibeWorkTrackerProviderOptions extends VibeKanbanApiOptions {
|
|
6
|
+
config?: VibeKanbanWorkTrackingConfig;
|
|
7
|
+
color?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface VibeTrackerProjectRef extends TrackerProjectRef {
|
|
10
|
+
vibeKanbanRepo: RegisterVibeKanbanProjectResult;
|
|
11
|
+
}
|
|
12
|
+
export interface VibeTrackerBoardRef extends TrackerBoardRef {
|
|
13
|
+
vibeKanbanBoard: EnsureVibeKanbanBoardResult;
|
|
14
|
+
}
|
|
15
|
+
export declare class VibeWorkTrackerProviderError extends Error {
|
|
16
|
+
constructor(message: string);
|
|
17
|
+
}
|
|
18
|
+
export declare const vibeWorkTrackerCapabilities: TrackerCapabilities;
|
|
19
|
+
export declare function createVibeWorkTrackerProvider(options: VibeWorkTrackerProviderOptions): VibeWorkTrackerProvider;
|
|
20
|
+
export declare class VibeWorkTrackerProvider implements WorkTrackerProvider {
|
|
21
|
+
readonly provider = "vibe-kanban";
|
|
22
|
+
readonly capabilities: TrackerCapabilities;
|
|
23
|
+
private readonly options;
|
|
24
|
+
constructor(options: VibeWorkTrackerProviderOptions);
|
|
25
|
+
ensureProject(context: NexusProjectContext): Promise<VibeTrackerProjectRef>;
|
|
26
|
+
ensureBoard(context: NexusProjectContext): Promise<VibeTrackerBoardRef>;
|
|
27
|
+
createWorkItem(_input: CreateWorkItemInput): Promise<WorkItem>;
|
|
28
|
+
listWorkItems(_query: WorkItemQuery): Promise<WorkItem[]>;
|
|
29
|
+
getWorkItem(_ref: WorkItemRef): Promise<WorkItem>;
|
|
30
|
+
updateWorkItem(_ref: WorkItemRef, _patch: WorkItemPatch): Promise<WorkItem>;
|
|
31
|
+
addComment(_ref: WorkItemRef, _body: string): Promise<WorkComment>;
|
|
32
|
+
setStatus(_ref: WorkItemRef, _status: WorkStatus): Promise<WorkItem>;
|
|
33
|
+
private vibeProjectOptions;
|
|
34
|
+
private vibeBoardOptions;
|
|
35
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { ensureVibeKanbanBoard, } from "./vibeKanbanBoardAdapter.js";
|
|
2
|
+
import { registerVibeKanbanProject, } from "./vibeKanbanProjectAdapter.js";
|
|
3
|
+
export class VibeWorkTrackerProviderError extends Error {
|
|
4
|
+
constructor(message) {
|
|
5
|
+
super(message);
|
|
6
|
+
this.name = "VibeWorkTrackerProviderError";
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
export const vibeWorkTrackerCapabilities = {
|
|
10
|
+
createItem: false,
|
|
11
|
+
listItems: false,
|
|
12
|
+
getItem: false,
|
|
13
|
+
updateItem: false,
|
|
14
|
+
comment: false,
|
|
15
|
+
labels: false,
|
|
16
|
+
assignees: false,
|
|
17
|
+
milestones: false,
|
|
18
|
+
board: true,
|
|
19
|
+
boardStatus: false,
|
|
20
|
+
draftItems: false,
|
|
21
|
+
webhooks: false,
|
|
22
|
+
};
|
|
23
|
+
export function createVibeWorkTrackerProvider(options) {
|
|
24
|
+
return new VibeWorkTrackerProvider(options);
|
|
25
|
+
}
|
|
26
|
+
export class VibeWorkTrackerProvider {
|
|
27
|
+
provider = "vibe-kanban";
|
|
28
|
+
capabilities = vibeWorkTrackerCapabilities;
|
|
29
|
+
options;
|
|
30
|
+
constructor(options) {
|
|
31
|
+
this.options = options;
|
|
32
|
+
}
|
|
33
|
+
async ensureProject(context) {
|
|
34
|
+
const projectRoot = sourceRootFor(context);
|
|
35
|
+
const result = await registerVibeKanbanProject({
|
|
36
|
+
...this.vibeProjectOptions(),
|
|
37
|
+
projectRoot,
|
|
38
|
+
name: context.projectName,
|
|
39
|
+
});
|
|
40
|
+
const name = result.project.display_name ?? result.project.name ?? context.projectName;
|
|
41
|
+
return {
|
|
42
|
+
provider: "vibe-kanban",
|
|
43
|
+
id: result.projectId,
|
|
44
|
+
name,
|
|
45
|
+
vibeKanbanRepo: result,
|
|
46
|
+
externalRef: {
|
|
47
|
+
provider: "vibe-kanban",
|
|
48
|
+
host: this.options.host ?? null,
|
|
49
|
+
itemId: result.projectId,
|
|
50
|
+
projectId: result.projectId,
|
|
51
|
+
repositoryId: result.projectId,
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
async ensureBoard(context) {
|
|
56
|
+
const result = await ensureVibeKanbanBoard({
|
|
57
|
+
...this.vibeBoardOptions(),
|
|
58
|
+
name: context.projectName,
|
|
59
|
+
color: this.options.color,
|
|
60
|
+
});
|
|
61
|
+
return {
|
|
62
|
+
provider: "vibe-kanban",
|
|
63
|
+
id: result.boardId,
|
|
64
|
+
name: result.board.name,
|
|
65
|
+
vibeKanbanBoard: result,
|
|
66
|
+
externalRef: {
|
|
67
|
+
provider: "vibe-kanban",
|
|
68
|
+
host: this.options.host ?? null,
|
|
69
|
+
itemId: result.boardId,
|
|
70
|
+
projectId: result.boardId,
|
|
71
|
+
boardId: result.boardId,
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
async createWorkItem(_input) {
|
|
76
|
+
throw unsupportedVibeWorkItemsError("createWorkItem");
|
|
77
|
+
}
|
|
78
|
+
async listWorkItems(_query) {
|
|
79
|
+
throw unsupportedVibeWorkItemsError("listWorkItems");
|
|
80
|
+
}
|
|
81
|
+
async getWorkItem(_ref) {
|
|
82
|
+
throw unsupportedVibeWorkItemsError("getWorkItem");
|
|
83
|
+
}
|
|
84
|
+
async updateWorkItem(_ref, _patch) {
|
|
85
|
+
throw unsupportedVibeWorkItemsError("updateWorkItem");
|
|
86
|
+
}
|
|
87
|
+
async addComment(_ref, _body) {
|
|
88
|
+
throw unsupportedVibeWorkItemsError("addComment");
|
|
89
|
+
}
|
|
90
|
+
async setStatus(_ref, _status) {
|
|
91
|
+
throw unsupportedVibeWorkItemsError("setStatus");
|
|
92
|
+
}
|
|
93
|
+
vibeProjectOptions() {
|
|
94
|
+
return {
|
|
95
|
+
host: this.options.host,
|
|
96
|
+
port: this.options.port,
|
|
97
|
+
fetch: this.options.fetch,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
vibeBoardOptions() {
|
|
101
|
+
return {
|
|
102
|
+
host: this.options.host,
|
|
103
|
+
port: this.options.port,
|
|
104
|
+
fetch: this.options.fetch,
|
|
105
|
+
organizationId: this.options.config?.board?.owner ?? undefined,
|
|
106
|
+
name: "",
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
function sourceRootFor(context) {
|
|
111
|
+
const projectRoot = context.sourceRoot ?? context.projectRoot;
|
|
112
|
+
if (projectRoot.trim().length === 0) {
|
|
113
|
+
throw new VibeWorkTrackerProviderError("projectRoot is required");
|
|
114
|
+
}
|
|
115
|
+
return projectRoot;
|
|
116
|
+
}
|
|
117
|
+
function unsupportedVibeWorkItemsError(operation) {
|
|
118
|
+
return new VibeWorkTrackerProviderError(`Vibe Kanban provider does not support neutral work item operation: ${operation}`);
|
|
119
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
export type WorktreeVerificationStatus = "passed" | "failed" | "not_run";
|
|
2
|
+
export type WorktreePublicationDecisionType = "not_decided" | "local_only" | "direct_integration" | "review_handoff" | "blocked";
|
|
3
|
+
export interface WorktreeVerificationInput {
|
|
4
|
+
command: string;
|
|
5
|
+
status?: WorktreeVerificationStatus;
|
|
6
|
+
summary?: string | null;
|
|
7
|
+
}
|
|
8
|
+
export interface WorktreeVerificationRecord {
|
|
9
|
+
command: string;
|
|
10
|
+
status: WorktreeVerificationStatus;
|
|
11
|
+
summary: string | null;
|
|
12
|
+
recordedAt: string;
|
|
13
|
+
}
|
|
14
|
+
export interface WorktreePublicationDecisionInput {
|
|
15
|
+
type: WorktreePublicationDecisionType;
|
|
16
|
+
targetBranch?: string | null;
|
|
17
|
+
remote?: string | null;
|
|
18
|
+
prUrl?: string | null;
|
|
19
|
+
reason?: string | null;
|
|
20
|
+
}
|
|
21
|
+
export interface WorktreePublicationDecision {
|
|
22
|
+
type: WorktreePublicationDecisionType;
|
|
23
|
+
targetBranch: string | null;
|
|
24
|
+
remote: string | null;
|
|
25
|
+
prUrl: string | null;
|
|
26
|
+
reason: string | null;
|
|
27
|
+
decidedAt: string;
|
|
28
|
+
}
|
|
29
|
+
export interface WorktreeOwnerWorkItem {
|
|
30
|
+
id: string;
|
|
31
|
+
title: string | null;
|
|
32
|
+
}
|
|
33
|
+
export interface WorktreeOwnershipMetadata {
|
|
34
|
+
componentId: string;
|
|
35
|
+
sourceRoot: string;
|
|
36
|
+
worktreesRoot: string;
|
|
37
|
+
worktreePath: string;
|
|
38
|
+
branchName: string;
|
|
39
|
+
baseRef: string | null;
|
|
40
|
+
workItem: WorktreeOwnerWorkItem | null;
|
|
41
|
+
}
|
|
42
|
+
export interface WorktreeExecutionMetadata {
|
|
43
|
+
worktree: WorktreeOwnershipMetadata | null;
|
|
44
|
+
commitIds: string[];
|
|
45
|
+
verification: WorktreeVerificationRecord[];
|
|
46
|
+
publicationDecision: WorktreePublicationDecision | null;
|
|
47
|
+
updatedAt: string | null;
|
|
48
|
+
}
|
|
49
|
+
export interface WorktreeExecutionUpdate {
|
|
50
|
+
worktree?: WorktreeOwnershipMetadata | null;
|
|
51
|
+
commitIds?: string[];
|
|
52
|
+
verification?: WorktreeVerificationInput;
|
|
53
|
+
publicationDecision?: WorktreePublicationDecisionInput;
|
|
54
|
+
}
|
|
55
|
+
export declare const worktreeExecutionMetadataDirectoryName = ".dev-nexus";
|
|
56
|
+
export declare const worktreeExecutionMetadataFileName = "execution.json";
|
|
57
|
+
export declare class WorktreeExecutionMetadataError extends Error {
|
|
58
|
+
constructor(message: string);
|
|
59
|
+
}
|
|
60
|
+
export declare function emptyWorktreeExecutionMetadata(): WorktreeExecutionMetadata;
|
|
61
|
+
export declare function worktreeExecutionMetadataPath(worktreePath: string): string;
|
|
62
|
+
export declare function readWorktreeExecutionMetadata(worktreePath: string): WorktreeExecutionMetadata;
|
|
63
|
+
export declare function writeWorktreeExecutionMetadata(worktreePath: string, metadata: WorktreeExecutionMetadata): string;
|
|
64
|
+
export declare function updateWorktreeExecutionMetadata(worktreePath: string, update: WorktreeExecutionUpdate, now?: Date | string): WorktreeExecutionMetadata;
|
|
65
|
+
export declare function hasWorktreeExecutionUpdate(update: WorktreeExecutionUpdate): boolean;
|
|
66
|
+
export declare function applyWorktreeExecutionUpdate(existing: unknown, update: WorktreeExecutionUpdate, updatedAt: string): WorktreeExecutionMetadata;
|
|
67
|
+
export declare function normalizeWorktreeExecutionMetadata(value: unknown): WorktreeExecutionMetadata;
|
|
68
|
+
export declare function worktreeOwnershipMetadataFromPreparedWorktree(value: {
|
|
69
|
+
componentId: string;
|
|
70
|
+
sourceRoot: string;
|
|
71
|
+
worktreesRoot: string;
|
|
72
|
+
worktreePath: string;
|
|
73
|
+
branchName: string;
|
|
74
|
+
baseRef: string | null;
|
|
75
|
+
workItem: WorktreeOwnerWorkItem | null;
|
|
76
|
+
}): WorktreeOwnershipMetadata;
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
export const worktreeExecutionMetadataDirectoryName = ".dev-nexus";
|
|
4
|
+
export const worktreeExecutionMetadataFileName = "execution.json";
|
|
5
|
+
export class WorktreeExecutionMetadataError extends Error {
|
|
6
|
+
constructor(message) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.name = "WorktreeExecutionMetadataError";
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export function emptyWorktreeExecutionMetadata() {
|
|
12
|
+
return {
|
|
13
|
+
worktree: null,
|
|
14
|
+
commitIds: [],
|
|
15
|
+
verification: [],
|
|
16
|
+
publicationDecision: null,
|
|
17
|
+
updatedAt: null,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
export function worktreeExecutionMetadataPath(worktreePath) {
|
|
21
|
+
return path.join(path.resolve(requiredNonEmptyString(worktreePath, "worktreePath")), worktreeExecutionMetadataDirectoryName, worktreeExecutionMetadataFileName);
|
|
22
|
+
}
|
|
23
|
+
export function readWorktreeExecutionMetadata(worktreePath) {
|
|
24
|
+
const metadataPath = worktreeExecutionMetadataPath(worktreePath);
|
|
25
|
+
if (!fs.existsSync(metadataPath)) {
|
|
26
|
+
return emptyWorktreeExecutionMetadata();
|
|
27
|
+
}
|
|
28
|
+
return normalizeWorktreeExecutionMetadata(JSON.parse(fs.readFileSync(metadataPath, "utf8").replace(/^\uFEFF/, "")));
|
|
29
|
+
}
|
|
30
|
+
export function writeWorktreeExecutionMetadata(worktreePath, metadata) {
|
|
31
|
+
const metadataPath = worktreeExecutionMetadataPath(worktreePath);
|
|
32
|
+
const normalized = normalizeWorktreeExecutionMetadata(metadata);
|
|
33
|
+
fs.mkdirSync(path.dirname(metadataPath), { recursive: true });
|
|
34
|
+
fs.writeFileSync(metadataPath, `${JSON.stringify(normalized, null, 2)}\n`, "utf8");
|
|
35
|
+
return metadataPath;
|
|
36
|
+
}
|
|
37
|
+
export function updateWorktreeExecutionMetadata(worktreePath, update, now = new Date()) {
|
|
38
|
+
const updated = applyWorktreeExecutionUpdate(readWorktreeExecutionMetadata(worktreePath), update, isoString(now));
|
|
39
|
+
writeWorktreeExecutionMetadata(worktreePath, updated);
|
|
40
|
+
return updated;
|
|
41
|
+
}
|
|
42
|
+
export function hasWorktreeExecutionUpdate(update) {
|
|
43
|
+
return Boolean(Object.prototype.hasOwnProperty.call(update, "worktree") ||
|
|
44
|
+
update.commitIds?.length ||
|
|
45
|
+
update.verification ||
|
|
46
|
+
update.publicationDecision);
|
|
47
|
+
}
|
|
48
|
+
export function applyWorktreeExecutionUpdate(existing, update, updatedAt) {
|
|
49
|
+
if (!hasWorktreeExecutionUpdate(update)) {
|
|
50
|
+
throw new WorktreeExecutionMetadataError("At least one execution field is required");
|
|
51
|
+
}
|
|
52
|
+
const execution = normalizeWorktreeExecutionMetadata(existing);
|
|
53
|
+
const worktree = Object.prototype.hasOwnProperty.call(update, "worktree")
|
|
54
|
+
? normalizeWorktreeOwnership(update.worktree)
|
|
55
|
+
: execution.worktree;
|
|
56
|
+
const commitIds = [...execution.commitIds];
|
|
57
|
+
for (const commitId of update.commitIds ?? []) {
|
|
58
|
+
const normalized = requiredNonEmptyString(commitId, "commitId");
|
|
59
|
+
if (!commitIds.includes(normalized)) {
|
|
60
|
+
commitIds.push(normalized);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
const verification = [...execution.verification];
|
|
64
|
+
if (update.verification) {
|
|
65
|
+
verification.push({
|
|
66
|
+
command: requiredNonEmptyString(update.verification.command, "verification.command"),
|
|
67
|
+
status: update.verification.status ?? "passed",
|
|
68
|
+
summary: optionalNullableString(update.verification.summary) ?? null,
|
|
69
|
+
recordedAt: requiredNonEmptyString(updatedAt, "updatedAt"),
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
const publicationDecision = update.publicationDecision
|
|
73
|
+
? {
|
|
74
|
+
type: normalizePublicationDecisionType(update.publicationDecision.type, "publicationDecision.type"),
|
|
75
|
+
targetBranch: optionalNullableString(update.publicationDecision.targetBranch) ?? null,
|
|
76
|
+
remote: optionalNullableString(update.publicationDecision.remote) ?? null,
|
|
77
|
+
prUrl: optionalNullableString(update.publicationDecision.prUrl) ?? null,
|
|
78
|
+
reason: optionalNullableString(update.publicationDecision.reason) ?? null,
|
|
79
|
+
decidedAt: requiredNonEmptyString(updatedAt, "updatedAt"),
|
|
80
|
+
}
|
|
81
|
+
: execution.publicationDecision;
|
|
82
|
+
return {
|
|
83
|
+
worktree,
|
|
84
|
+
commitIds,
|
|
85
|
+
verification,
|
|
86
|
+
publicationDecision,
|
|
87
|
+
updatedAt: requiredNonEmptyString(updatedAt, "updatedAt"),
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
export function normalizeWorktreeExecutionMetadata(value) {
|
|
91
|
+
if (value === undefined || value === null) {
|
|
92
|
+
return emptyWorktreeExecutionMetadata();
|
|
93
|
+
}
|
|
94
|
+
if (typeof value !== "object" || Array.isArray(value)) {
|
|
95
|
+
throw new WorktreeExecutionMetadataError("worktree execution metadata must be an object");
|
|
96
|
+
}
|
|
97
|
+
const record = value;
|
|
98
|
+
return {
|
|
99
|
+
worktree: normalizeWorktreeOwnership(record.worktree),
|
|
100
|
+
commitIds: normalizeStringArray(record.commitIds, "execution.commitIds"),
|
|
101
|
+
verification: normalizeVerificationRecords(record.verification),
|
|
102
|
+
publicationDecision: normalizePublicationDecision(record.publicationDecision),
|
|
103
|
+
updatedAt: typeof record.updatedAt === "string" && record.updatedAt.trim()
|
|
104
|
+
? record.updatedAt
|
|
105
|
+
: null,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
export function worktreeOwnershipMetadataFromPreparedWorktree(value) {
|
|
109
|
+
const normalized = normalizeWorktreeOwnership(value);
|
|
110
|
+
if (!normalized) {
|
|
111
|
+
throw new WorktreeExecutionMetadataError("prepared worktree ownership metadata is required");
|
|
112
|
+
}
|
|
113
|
+
return normalized;
|
|
114
|
+
}
|
|
115
|
+
function normalizeWorktreeOwnership(value) {
|
|
116
|
+
if (value === undefined || value === null) {
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
if (typeof value !== "object" || Array.isArray(value)) {
|
|
120
|
+
throw new WorktreeExecutionMetadataError("execution.worktree must be an object or null");
|
|
121
|
+
}
|
|
122
|
+
const record = value;
|
|
123
|
+
const sourceRoot = path.resolve(requiredNonEmptyString(record.sourceRoot, "execution.worktree.sourceRoot"));
|
|
124
|
+
const worktreesRoot = path.resolve(requiredNonEmptyString(record.worktreesRoot, "execution.worktree.worktreesRoot"));
|
|
125
|
+
const worktreePath = path.resolve(requiredNonEmptyString(record.worktreePath, "execution.worktree.worktreePath"));
|
|
126
|
+
assertWorktreePathInsideRoot(worktreesRoot, worktreePath);
|
|
127
|
+
return {
|
|
128
|
+
componentId: requiredNonEmptyString(record.componentId, "execution.worktree.componentId"),
|
|
129
|
+
sourceRoot,
|
|
130
|
+
worktreesRoot,
|
|
131
|
+
worktreePath,
|
|
132
|
+
branchName: requiredNonEmptyString(record.branchName, "execution.worktree.branchName"),
|
|
133
|
+
baseRef: optionalNullableString(record.baseRef) ?? null,
|
|
134
|
+
workItem: normalizeWorktreeOwnerWorkItem(record.workItem),
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
function normalizeWorktreeOwnerWorkItem(value) {
|
|
138
|
+
if (value === undefined || value === null) {
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
if (typeof value !== "object" || Array.isArray(value)) {
|
|
142
|
+
throw new WorktreeExecutionMetadataError("execution.worktree.workItem must be an object or null");
|
|
143
|
+
}
|
|
144
|
+
const record = value;
|
|
145
|
+
return {
|
|
146
|
+
id: requiredNonEmptyString(record.id, "execution.worktree.workItem.id"),
|
|
147
|
+
title: optionalNullableString(record.title) ?? null,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
function assertWorktreePathInsideRoot(worktreesRoot, worktreePath) {
|
|
151
|
+
const relative = path.relative(worktreesRoot, worktreePath);
|
|
152
|
+
if (!relative || relative.startsWith("..") || path.isAbsolute(relative)) {
|
|
153
|
+
throw new WorktreeExecutionMetadataError(`execution.worktree.worktreePath must resolve inside worktreesRoot: ${worktreePath}`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
function normalizeVerificationRecords(value) {
|
|
157
|
+
if (value === undefined || value === null) {
|
|
158
|
+
return [];
|
|
159
|
+
}
|
|
160
|
+
if (!Array.isArray(value)) {
|
|
161
|
+
throw new WorktreeExecutionMetadataError("execution.verification must be an array");
|
|
162
|
+
}
|
|
163
|
+
return value.map((item, index) => {
|
|
164
|
+
if (!item || typeof item !== "object" || Array.isArray(item)) {
|
|
165
|
+
throw new WorktreeExecutionMetadataError(`execution.verification[${index}] must be an object`);
|
|
166
|
+
}
|
|
167
|
+
const record = item;
|
|
168
|
+
return {
|
|
169
|
+
command: requiredNonEmptyString(record.command, `execution.verification[${index}].command`),
|
|
170
|
+
status: normalizeVerificationStatus(record.status, `execution.verification[${index}].status`),
|
|
171
|
+
summary: optionalNullableString(record.summary) ?? null,
|
|
172
|
+
recordedAt: requiredNonEmptyString(record.recordedAt, `execution.verification[${index}].recordedAt`),
|
|
173
|
+
};
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
function normalizePublicationDecision(value) {
|
|
177
|
+
if (value === undefined || value === null) {
|
|
178
|
+
return null;
|
|
179
|
+
}
|
|
180
|
+
if (typeof value !== "object" || Array.isArray(value)) {
|
|
181
|
+
throw new WorktreeExecutionMetadataError("execution.publicationDecision must be an object or null");
|
|
182
|
+
}
|
|
183
|
+
const record = value;
|
|
184
|
+
return {
|
|
185
|
+
type: normalizePublicationDecisionType(record.type, "execution.publicationDecision.type"),
|
|
186
|
+
targetBranch: optionalNullableString(record.targetBranch) ?? null,
|
|
187
|
+
remote: optionalNullableString(record.remote) ?? null,
|
|
188
|
+
prUrl: optionalNullableString(record.prUrl) ?? null,
|
|
189
|
+
reason: optionalNullableString(record.reason) ?? null,
|
|
190
|
+
decidedAt: requiredNonEmptyString(record.decidedAt, "execution.publicationDecision.decidedAt"),
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
function normalizeStringArray(value, name) {
|
|
194
|
+
if (value === undefined || value === null) {
|
|
195
|
+
return [];
|
|
196
|
+
}
|
|
197
|
+
if (!Array.isArray(value)) {
|
|
198
|
+
throw new WorktreeExecutionMetadataError(`${name} must be an array`);
|
|
199
|
+
}
|
|
200
|
+
return value.map((item, index) => requiredNonEmptyString(item, `${name}[${index}]`));
|
|
201
|
+
}
|
|
202
|
+
function normalizeVerificationStatus(value, name) {
|
|
203
|
+
if (value === "passed" || value === "failed" || value === "not_run") {
|
|
204
|
+
return value;
|
|
205
|
+
}
|
|
206
|
+
throw new WorktreeExecutionMetadataError(`${name} must be passed, failed, or not_run`);
|
|
207
|
+
}
|
|
208
|
+
function normalizePublicationDecisionType(value, name) {
|
|
209
|
+
if (value === "not_decided" ||
|
|
210
|
+
value === "local_only" ||
|
|
211
|
+
value === "direct_integration" ||
|
|
212
|
+
value === "review_handoff" ||
|
|
213
|
+
value === "blocked") {
|
|
214
|
+
return value;
|
|
215
|
+
}
|
|
216
|
+
throw new WorktreeExecutionMetadataError(`${name} must be not_decided, local_only, direct_integration, review_handoff, or blocked`);
|
|
217
|
+
}
|
|
218
|
+
function optionalNullableString(value) {
|
|
219
|
+
if (value === undefined) {
|
|
220
|
+
return undefined;
|
|
221
|
+
}
|
|
222
|
+
if (value === null) {
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
225
|
+
return requiredNonEmptyString(value, "value");
|
|
226
|
+
}
|
|
227
|
+
function isoString(value) {
|
|
228
|
+
const date = value instanceof Date ? value : new Date(value);
|
|
229
|
+
if (Number.isNaN(date.getTime())) {
|
|
230
|
+
throw new WorktreeExecutionMetadataError("now must be a valid date");
|
|
231
|
+
}
|
|
232
|
+
return date.toISOString();
|
|
233
|
+
}
|
|
234
|
+
function requiredNonEmptyString(value, name) {
|
|
235
|
+
if (typeof value !== "string" || value.trim().length === 0) {
|
|
236
|
+
throw new WorktreeExecutionMetadataError(`${name} must be a non-empty string`);
|
|
237
|
+
}
|
|
238
|
+
return value.trim();
|
|
239
|
+
}
|