@proletariat/cli 0.3.86 → 0.3.88
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/dist/commands/config/index.js +42 -0
- package/dist/commands/config/index.js.map +1 -1
- package/dist/commands/init.d.ts +6 -1
- package/dist/commands/init.js +44 -89
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/new.d.ts +30 -2
- package/dist/commands/new.js +141 -9
- package/dist/commands/new.js.map +1 -1
- package/dist/commands/session/poke.d.ts +3 -7
- package/dist/commands/session/poke.js +5 -7
- package/dist/commands/session/poke.js.map +1 -1
- package/dist/commands/ticket/cancel.js +2 -0
- package/dist/commands/ticket/cancel.js.map +1 -1
- package/dist/commands/ticket/complete.js +2 -0
- package/dist/commands/ticket/complete.js.map +1 -1
- package/dist/commands/ticket/delete.js +2 -0
- package/dist/commands/ticket/delete.js.map +1 -1
- package/dist/commands/ticket/edit.js +5 -0
- package/dist/commands/ticket/edit.js.map +1 -1
- package/dist/commands/ticket/move.js +2 -0
- package/dist/commands/ticket/move.js.map +1 -1
- package/dist/commands/ticket/project.js +2 -0
- package/dist/commands/ticket/project.js.map +1 -1
- package/dist/commands/ticket/reassign.js +2 -0
- package/dist/commands/ticket/reassign.js.map +1 -1
- package/dist/commands/ticket/resolve.js +2 -0
- package/dist/commands/ticket/resolve.js.map +1 -1
- package/dist/commands/ticket/update.js +5 -0
- package/dist/commands/ticket/update.js.map +1 -1
- package/dist/commands/work/complete.js +2 -0
- package/dist/commands/work/complete.js.map +1 -1
- package/dist/commands/work/peek.js +4 -0
- package/dist/commands/work/peek.js.map +1 -1
- package/dist/commands/work/poke.d.ts +3 -4
- package/dist/commands/work/poke.js +9 -4
- package/dist/commands/work/poke.js.map +1 -1
- package/dist/commands/work/ready.js +2 -0
- package/dist/commands/work/ready.js.map +1 -1
- package/dist/commands/work/start.d.ts +1 -0
- package/dist/commands/work/start.js +46 -2
- package/dist/commands/work/start.js.map +1 -1
- package/dist/commands/work/stop.js +5 -0
- package/dist/commands/work/stop.js.map +1 -1
- package/dist/hooks/init.js +6 -6
- package/dist/hooks/init.js.map +1 -1
- package/dist/hooks/postrun.js +3 -0
- package/dist/hooks/postrun.js.map +1 -1
- package/dist/lib/asana/config.d.ts +1 -1
- package/dist/lib/asana/config.js +18 -30
- package/dist/lib/asana/config.js.map +1 -1
- package/dist/lib/asana/mapper.d.ts +4 -3
- package/dist/lib/asana/mapper.js +17 -10
- package/dist/lib/asana/mapper.js.map +1 -1
- package/dist/lib/database/agents.d.ts +73 -0
- package/dist/lib/database/agents.js +341 -0
- package/dist/lib/database/agents.js.map +1 -0
- package/dist/lib/database/driver.d.ts +115 -0
- package/dist/lib/database/driver.js +109 -0
- package/dist/lib/database/driver.js.map +1 -0
- package/dist/lib/database/drizzle-schema.d.ts +1 -1
- package/dist/lib/database/index.d.ts +25 -287
- package/dist/lib/database/index.js +35 -1067
- package/dist/lib/database/index.js.map +1 -1
- package/dist/lib/database/media.d.ts +53 -0
- package/dist/lib/database/media.js +118 -0
- package/dist/lib/database/media.js.map +1 -0
- package/dist/lib/database/migrations/0011_add_review_gate.d.ts +8 -0
- package/dist/lib/database/migrations/0011_add_review_gate.js +21 -0
- package/dist/lib/database/migrations/0011_add_review_gate.js.map +1 -0
- package/dist/lib/database/migrations/index.js +2 -0
- package/dist/lib/database/migrations/index.js.map +1 -1
- package/dist/lib/database/pmo-bootstrap.d.ts +30 -0
- package/dist/lib/database/pmo-bootstrap.js +105 -0
- package/dist/lib/database/pmo-bootstrap.js.map +1 -0
- package/dist/lib/database/repositories.d.ts +26 -0
- package/dist/lib/database/repositories.js +56 -0
- package/dist/lib/database/repositories.js.map +1 -0
- package/dist/lib/database/settings-store.d.ts +60 -0
- package/dist/lib/database/settings-store.js +87 -0
- package/dist/lib/database/settings-store.js.map +1 -0
- package/dist/lib/database/themes.d.ts +59 -0
- package/dist/lib/database/themes.js +212 -0
- package/dist/lib/database/themes.js.map +1 -0
- package/dist/lib/database/workspace.d.ts +46 -0
- package/dist/lib/database/workspace.js +158 -0
- package/dist/lib/database/workspace.js.map +1 -0
- package/dist/lib/database/worktrees.d.ts +33 -0
- package/dist/lib/database/worktrees.js +60 -0
- package/dist/lib/database/worktrees.js.map +1 -0
- package/dist/lib/execution/config.d.ts +1 -1
- package/dist/lib/execution/config.js +7 -17
- package/dist/lib/execution/config.js.map +1 -1
- package/dist/lib/execution/runners/prompt-builder.js +49 -15
- package/dist/lib/execution/runners/prompt-builder.js.map +1 -1
- package/dist/lib/execution/spawner.d.ts +1 -1
- package/dist/lib/execution/storage.d.ts +6 -4
- package/dist/lib/execution/storage.js +17 -9
- package/dist/lib/execution/storage.js.map +1 -1
- package/dist/lib/execution/types.d.ts +1 -0
- package/dist/lib/execution/types.js.map +1 -1
- package/dist/lib/external-issues/mapping-store.d.ts +4 -3
- package/dist/lib/external-issues/mapping-store.js +21 -13
- package/dist/lib/external-issues/mapping-store.js.map +1 -1
- package/dist/lib/external-issues/outbound-sync.d.ts +1 -1
- package/dist/lib/jira/config.d.ts +1 -6
- package/dist/lib/jira/config.js +16 -33
- package/dist/lib/jira/config.js.map +1 -1
- package/dist/lib/linear/config.d.ts +1 -1
- package/dist/lib/linear/config.js +16 -38
- package/dist/lib/linear/config.js.map +1 -1
- package/dist/lib/linear/mapper.d.ts +4 -3
- package/dist/lib/linear/mapper.js +20 -13
- package/dist/lib/linear/mapper.js.map +1 -1
- package/dist/lib/mcp/tools/action.js +34 -0
- package/dist/lib/mcp/tools/action.js.map +1 -1
- package/dist/lib/monday/config.d.ts +1 -1
- package/dist/lib/monday/config.js +16 -32
- package/dist/lib/monday/config.js.map +1 -1
- package/dist/lib/monday/mapper.d.ts +4 -3
- package/dist/lib/monday/mapper.js +19 -12
- package/dist/lib/monday/mapper.js.map +1 -1
- package/dist/lib/onboarding/wizard.d.ts +2 -2
- package/dist/lib/onboarding/wizard.js +32 -24
- package/dist/lib/onboarding/wizard.js.map +1 -1
- package/dist/lib/pmo/diet.d.ts +1 -1
- package/dist/lib/pmo/schema.d.ts +1 -1
- package/dist/lib/pmo/schema.js +1 -0
- package/dist/lib/pmo/schema.js.map +1 -1
- package/dist/lib/pmo/storage/actions.js +9 -3
- package/dist/lib/pmo/storage/actions.js.map +1 -1
- package/dist/lib/pmo/storage/index.d.ts +9 -0
- package/dist/lib/pmo/storage/index.js +16 -1
- package/dist/lib/pmo/storage/index.js.map +1 -1
- package/dist/lib/pmo/storage/tickets.d.ts +7 -0
- package/dist/lib/pmo/storage/tickets.js +33 -2
- package/dist/lib/pmo/storage/tickets.js.map +1 -1
- package/dist/lib/pmo/storage/types.d.ts +5 -1
- package/dist/lib/pmo/types.d.ts +10 -0
- package/dist/lib/pmo/types.js.map +1 -1
- package/dist/lib/pmo/utils.d.ts +38 -0
- package/dist/lib/pmo/utils.js +61 -0
- package/dist/lib/pmo/utils.js.map +1 -1
- package/dist/lib/providers/event-emitting-provider.js +13 -2
- package/dist/lib/providers/event-emitting-provider.js.map +1 -1
- package/dist/lib/shortcut/config.d.ts +1 -7
- package/dist/lib/shortcut/config.js +13 -32
- package/dist/lib/shortcut/config.js.map +1 -1
- package/dist/lib/telemetry/analytics.d.ts +47 -0
- package/dist/lib/telemetry/analytics.js +52 -0
- package/dist/lib/telemetry/analytics.js.map +1 -1
- package/dist/lib/telemetry/telemetry-bridge.d.ts +35 -0
- package/dist/lib/telemetry/telemetry-bridge.js +139 -0
- package/dist/lib/telemetry/telemetry-bridge.js.map +1 -0
- package/dist/lib/trello/config.d.ts +1 -26
- package/dist/lib/trello/config.js +23 -64
- package/dist/lib/trello/config.js.map +1 -1
- package/dist/lib/trello/mapper.d.ts +4 -3
- package/dist/lib/trello/mapper.js +17 -10
- package/dist/lib/trello/mapper.js.map +1 -1
- package/dist/lib/work-lifecycle/post-execution.d.ts +6 -2
- package/dist/lib/work-lifecycle/post-execution.js +30 -18
- package/dist/lib/work-lifecycle/post-execution.js.map +1 -1
- package/dist/lib/work-source/config.d.ts +1 -1
- package/dist/lib/work-source/config.js +14 -24
- package/dist/lib/work-source/config.js.map +1 -1
- package/dist/lib/work-source/provider-sources.d.ts +1 -1
- package/dist/lib/work-source/provider-sources.js +8 -20
- package/dist/lib/work-source/provider-sources.js.map +1 -1
- package/oclif.manifest.json +1035 -987
- package/package.json +9 -9
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Telemetry Bridge — Subscribes to EventBus events and fires PostHog tracking calls.
|
|
3
|
+
*
|
|
4
|
+
* Centralizes instrumentation so individual commands/providers don't need to
|
|
5
|
+
* import and call tracking functions directly. The bridge listens to typed
|
|
6
|
+
* runtime events and translates them into PostHog telemetry events.
|
|
7
|
+
*
|
|
8
|
+
* Privacy rules:
|
|
9
|
+
* - DO track: command names, action types, provider names, durations, success/failure, environment type
|
|
10
|
+
* - DO NOT track: ticket descriptions, code content, file paths, API keys, branch names, usernames, ticket IDs
|
|
11
|
+
*/
|
|
12
|
+
import { getEventBus } from '../events/event-bus.js';
|
|
13
|
+
import { trackAgentCompleted, trackAgentErrored, trackPrimitiveExecuted, } from './analytics.js';
|
|
14
|
+
// Track agent spawn times by sessionId for duration calculation
|
|
15
|
+
const agentSpawnTimes = new Map();
|
|
16
|
+
// Track primitive start times by command ID
|
|
17
|
+
const primitiveStartTimes = new Map();
|
|
18
|
+
let unsubscribers = [];
|
|
19
|
+
/**
|
|
20
|
+
* Start the telemetry bridge — subscribe to EventBus events and track them.
|
|
21
|
+
* Safe to call multiple times; subsequent calls are no-ops.
|
|
22
|
+
*/
|
|
23
|
+
export function startTelemetryBridge() {
|
|
24
|
+
if (unsubscribers.length > 0)
|
|
25
|
+
return;
|
|
26
|
+
const bus = getEventBus();
|
|
27
|
+
// ── Agent Lifecycle ─────────────────────────────────────────────────────
|
|
28
|
+
// Track agent spawn time for duration calculation on completion
|
|
29
|
+
unsubscribers.push(bus.on('agent:spawned', (event) => {
|
|
30
|
+
agentSpawnTimes.set(event.sessionId, {
|
|
31
|
+
timestamp: event.timestamp,
|
|
32
|
+
action: 'unknown', // Will be enriched by work:started if available
|
|
33
|
+
});
|
|
34
|
+
}));
|
|
35
|
+
// Track agent completion
|
|
36
|
+
unsubscribers.push(bus.on('agent:stopped', (event) => {
|
|
37
|
+
const spawnInfo = agentSpawnTimes.get(event.sessionId);
|
|
38
|
+
const durationMs = spawnInfo
|
|
39
|
+
? event.timestamp.getTime() - spawnInfo.timestamp.getTime()
|
|
40
|
+
: 0;
|
|
41
|
+
// Map event reason ('manual' | 'completed' | 'error') to telemetry exit reasons
|
|
42
|
+
if (event.reason === 'error') {
|
|
43
|
+
trackAgentErrored({
|
|
44
|
+
action: spawnInfo?.action ?? 'unknown',
|
|
45
|
+
durationMs,
|
|
46
|
+
exitReason: 'errored',
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
trackAgentCompleted({
|
|
51
|
+
action: spawnInfo?.action ?? 'unknown',
|
|
52
|
+
durationMs,
|
|
53
|
+
exitReason: event.reason === 'manual' ? 'stopped' : event.reason,
|
|
54
|
+
prCreated: false,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
agentSpawnTimes.delete(event.sessionId);
|
|
58
|
+
}));
|
|
59
|
+
// Track agent errors
|
|
60
|
+
unsubscribers.push(bus.on('agent:error', (event) => {
|
|
61
|
+
const spawnInfo = agentSpawnTimes.get(event.sessionId);
|
|
62
|
+
const durationMs = spawnInfo
|
|
63
|
+
? event.timestamp.getTime() - spawnInfo.timestamp.getTime()
|
|
64
|
+
: 0;
|
|
65
|
+
trackAgentErrored({
|
|
66
|
+
action: spawnInfo?.action ?? 'unknown',
|
|
67
|
+
durationMs,
|
|
68
|
+
exitReason: 'errored',
|
|
69
|
+
errorType: classifyError(event.error),
|
|
70
|
+
});
|
|
71
|
+
agentSpawnTimes.delete(event.sessionId);
|
|
72
|
+
}));
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Stop the telemetry bridge and clean up subscriptions.
|
|
76
|
+
*/
|
|
77
|
+
export function stopTelemetryBridge() {
|
|
78
|
+
for (const unsub of unsubscribers) {
|
|
79
|
+
unsub();
|
|
80
|
+
}
|
|
81
|
+
unsubscribers = [];
|
|
82
|
+
agentSpawnTimes.clear();
|
|
83
|
+
primitiveStartTimes.clear();
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Record the start of a work primitive for duration tracking.
|
|
87
|
+
* Call this at the beginning of a primitive command, then call
|
|
88
|
+
* `endPrimitiveTracking()` when it completes.
|
|
89
|
+
*/
|
|
90
|
+
export function beginPrimitiveTracking(id, primitive) {
|
|
91
|
+
primitiveStartTimes.set(id, { timestamp: new Date(), primitive });
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Record the completion of a work primitive and fire the tracking event.
|
|
95
|
+
*/
|
|
96
|
+
export function endPrimitiveTracking(id, success, errorType) {
|
|
97
|
+
const startInfo = primitiveStartTimes.get(id);
|
|
98
|
+
if (!startInfo)
|
|
99
|
+
return;
|
|
100
|
+
const durationMs = Date.now() - startInfo.timestamp.getTime();
|
|
101
|
+
trackPrimitiveExecuted({
|
|
102
|
+
primitive: startInfo.primitive,
|
|
103
|
+
durationMs,
|
|
104
|
+
success,
|
|
105
|
+
errorType,
|
|
106
|
+
});
|
|
107
|
+
primitiveStartTimes.delete(id);
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Enrich an agent session with its action name (called from work:start).
|
|
111
|
+
* This lets agent_completed/agent_errored events report the correct action.
|
|
112
|
+
*/
|
|
113
|
+
export function enrichAgentSession(sessionId, action) {
|
|
114
|
+
const existing = agentSpawnTimes.get(sessionId);
|
|
115
|
+
if (existing) {
|
|
116
|
+
existing.action = action;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Classify an error message into a safe, non-PII error type.
|
|
121
|
+
* Only returns generic categories — never includes the original message.
|
|
122
|
+
*/
|
|
123
|
+
function classifyError(errorMessage) {
|
|
124
|
+
const lower = errorMessage.toLowerCase();
|
|
125
|
+
if (lower.includes('timeout'))
|
|
126
|
+
return 'timeout';
|
|
127
|
+
if (lower.includes('docker') || lower.includes('container'))
|
|
128
|
+
return 'container';
|
|
129
|
+
if (lower.includes('permission') || lower.includes('denied'))
|
|
130
|
+
return 'permission';
|
|
131
|
+
if (lower.includes('network') || lower.includes('econnrefused') || lower.includes('fetch'))
|
|
132
|
+
return 'network';
|
|
133
|
+
if (lower.includes('spawn') || lower.includes('enoent'))
|
|
134
|
+
return 'spawn_failure';
|
|
135
|
+
if (lower.includes('oom') || lower.includes('memory'))
|
|
136
|
+
return 'memory';
|
|
137
|
+
return 'unknown';
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=telemetry-bridge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry-bridge.js","sourceRoot":"","sources":["../../../src/lib/telemetry/telemetry-bridge.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,9 +2,8 @@
|
|
|
2
2
|
* Trello Configuration Storage
|
|
3
3
|
*
|
|
4
4
|
* Stores Trello credentials and preferences in the workspace_settings table.
|
|
5
|
-
* Mirrors the Shortcut/Asana config module pattern.
|
|
6
5
|
*/
|
|
7
|
-
import Database from 'better-sqlite3';
|
|
6
|
+
import type Database from 'better-sqlite3';
|
|
8
7
|
export interface TrelloConfig {
|
|
9
8
|
apiKey: string;
|
|
10
9
|
apiToken: string;
|
|
@@ -13,43 +12,19 @@ export interface TrelloConfig {
|
|
|
13
12
|
}
|
|
14
13
|
/**
|
|
15
14
|
* Check if Trello is configured.
|
|
16
|
-
* Returns true if either:
|
|
17
|
-
* - Database has trello.api_key and trello.api_token stored, OR
|
|
18
|
-
* - Environment variables PRLT_TRELLO_API_KEY/TRELLO_API_KEY and PRLT_TRELLO_API_TOKEN/TRELLO_API_TOKEN are set
|
|
19
15
|
*/
|
|
20
16
|
export declare function isTrelloConfigured(db: Database.Database): boolean;
|
|
21
17
|
/**
|
|
22
18
|
* Load Trello configuration from the database + environment.
|
|
23
|
-
* Returns null if not configured.
|
|
24
19
|
*/
|
|
25
20
|
export declare function loadTrelloConfig(db: Database.Database): TrelloConfig | null;
|
|
26
21
|
/**
|
|
27
22
|
* Save Trello configuration to the database.
|
|
28
23
|
*/
|
|
29
24
|
export declare function saveTrelloConfig(db: Database.Database, config: TrelloConfig): void;
|
|
30
|
-
/**
|
|
31
|
-
* Save the Trello API key.
|
|
32
|
-
*/
|
|
33
25
|
export declare function saveTrelloApiKey(db: Database.Database, apiKey: string): void;
|
|
34
|
-
/**
|
|
35
|
-
* Save the Trello API token.
|
|
36
|
-
*/
|
|
37
26
|
export declare function saveTrelloApiToken(db: Database.Database, apiToken: string): void;
|
|
38
|
-
/**
|
|
39
|
-
* Save the Trello board.
|
|
40
|
-
*/
|
|
41
27
|
export declare function saveTrelloBoard(db: Database.Database, boardId: string, boardName: string): void;
|
|
42
|
-
/**
|
|
43
|
-
* Clear all Trello configuration from the database.
|
|
44
|
-
*/
|
|
45
28
|
export declare function clearTrelloConfig(db: Database.Database): void;
|
|
46
|
-
/**
|
|
47
|
-
* Get the stored Trello API key.
|
|
48
|
-
* Also checks PRLT_TRELLO_API_KEY and TRELLO_API_KEY environment variables.
|
|
49
|
-
*/
|
|
50
29
|
export declare function getTrelloApiKey(db: Database.Database): string | null;
|
|
51
|
-
/**
|
|
52
|
-
* Get the stored Trello API token.
|
|
53
|
-
* Also checks PRLT_TRELLO_API_TOKEN and TRELLO_API_TOKEN environment variables.
|
|
54
|
-
*/
|
|
55
30
|
export declare function getTrelloApiToken(db: Database.Database): string | null;
|
|
@@ -2,41 +2,22 @@
|
|
|
2
2
|
* Trello Configuration Storage
|
|
3
3
|
*
|
|
4
4
|
* Stores Trello credentials and preferences in the workspace_settings table.
|
|
5
|
-
* Mirrors the Shortcut/Asana config module pattern.
|
|
6
5
|
*/
|
|
7
6
|
import { loadProviderSources, resolveApiKey } from '../work-source/provider-sources.js';
|
|
8
|
-
|
|
7
|
+
import { SettingsStore } from '../database/settings-store.js';
|
|
9
8
|
const TRELLO_CONFIG_KEYS = {
|
|
10
9
|
apiKey: 'trello.api_key',
|
|
11
10
|
apiToken: 'trello.api_token',
|
|
12
11
|
boardId: 'trello.board_id',
|
|
13
12
|
boardName: 'trello.board_name',
|
|
14
13
|
};
|
|
15
|
-
function getSetting(db, key) {
|
|
16
|
-
const row = db
|
|
17
|
-
.prepare(`SELECT value FROM ${SETTINGS_TABLE} WHERE key = ?`)
|
|
18
|
-
.get(key);
|
|
19
|
-
return row?.value ?? null;
|
|
20
|
-
}
|
|
21
|
-
function setSetting(db, key, value) {
|
|
22
|
-
db.prepare(`
|
|
23
|
-
INSERT INTO ${SETTINGS_TABLE} (key, value)
|
|
24
|
-
VALUES (?, ?)
|
|
25
|
-
ON CONFLICT(key) DO UPDATE SET value = excluded.value
|
|
26
|
-
`).run(key, value);
|
|
27
|
-
}
|
|
28
|
-
function deleteSetting(db, key) {
|
|
29
|
-
db.prepare(`DELETE FROM ${SETTINGS_TABLE} WHERE key = ?`).run(key);
|
|
30
|
-
}
|
|
31
14
|
/**
|
|
32
15
|
* Check if Trello is configured.
|
|
33
|
-
* Returns true if either:
|
|
34
|
-
* - Database has trello.api_key and trello.api_token stored, OR
|
|
35
|
-
* - Environment variables PRLT_TRELLO_API_KEY/TRELLO_API_KEY and PRLT_TRELLO_API_TOKEN/TRELLO_API_TOKEN are set
|
|
36
16
|
*/
|
|
37
17
|
export function isTrelloConfigured(db) {
|
|
38
|
-
const
|
|
39
|
-
|
|
18
|
+
const settings = new SettingsStore(db);
|
|
19
|
+
const hasDbConfig = settings.has(TRELLO_CONFIG_KEYS.apiKey)
|
|
20
|
+
&& settings.has(TRELLO_CONFIG_KEYS.apiToken);
|
|
40
21
|
if (hasDbConfig)
|
|
41
22
|
return true;
|
|
42
23
|
const hasEnvKey = !!(process.env.PRLT_TRELLO_API_KEY || process.env.TRELLO_API_KEY);
|
|
@@ -45,13 +26,13 @@ export function isTrelloConfigured(db) {
|
|
|
45
26
|
}
|
|
46
27
|
/**
|
|
47
28
|
* Load Trello configuration from the database + environment.
|
|
48
|
-
* Returns null if not configured.
|
|
49
29
|
*/
|
|
50
30
|
export function loadTrelloConfig(db) {
|
|
51
|
-
const
|
|
31
|
+
const settings = new SettingsStore(db);
|
|
32
|
+
const apiKey = settings.get(TRELLO_CONFIG_KEYS.apiKey)
|
|
52
33
|
|| process.env.PRLT_TRELLO_API_KEY
|
|
53
34
|
|| process.env.TRELLO_API_KEY;
|
|
54
|
-
const apiToken =
|
|
35
|
+
const apiToken = settings.get(TRELLO_CONFIG_KEYS.apiToken)
|
|
55
36
|
|| process.env.PRLT_TRELLO_API_TOKEN
|
|
56
37
|
|| process.env.TRELLO_API_TOKEN;
|
|
57
38
|
if (!apiKey || !apiToken)
|
|
@@ -59,58 +40,44 @@ export function loadTrelloConfig(db) {
|
|
|
59
40
|
return {
|
|
60
41
|
apiKey,
|
|
61
42
|
apiToken,
|
|
62
|
-
boardId:
|
|
43
|
+
boardId: settings.get(TRELLO_CONFIG_KEYS.boardId)
|
|
63
44
|
|| process.env.PRLT_TRELLO_BOARD_ID
|
|
64
45
|
|| undefined,
|
|
65
|
-
boardName:
|
|
46
|
+
boardName: settings.get(TRELLO_CONFIG_KEYS.boardName) || undefined,
|
|
66
47
|
};
|
|
67
48
|
}
|
|
68
49
|
/**
|
|
69
50
|
* Save Trello configuration to the database.
|
|
70
51
|
*/
|
|
71
52
|
export function saveTrelloConfig(db, config) {
|
|
72
|
-
|
|
73
|
-
|
|
53
|
+
const settings = new SettingsStore(db);
|
|
54
|
+
settings.set(TRELLO_CONFIG_KEYS.apiKey, config.apiKey);
|
|
55
|
+
settings.set(TRELLO_CONFIG_KEYS.apiToken, config.apiToken);
|
|
74
56
|
if (config.boardId) {
|
|
75
|
-
|
|
57
|
+
settings.set(TRELLO_CONFIG_KEYS.boardId, config.boardId);
|
|
76
58
|
}
|
|
77
59
|
if (config.boardName) {
|
|
78
|
-
|
|
60
|
+
settings.set(TRELLO_CONFIG_KEYS.boardName, config.boardName);
|
|
79
61
|
}
|
|
80
62
|
}
|
|
81
|
-
/**
|
|
82
|
-
* Save the Trello API key.
|
|
83
|
-
*/
|
|
84
63
|
export function saveTrelloApiKey(db, apiKey) {
|
|
85
|
-
|
|
64
|
+
new SettingsStore(db).set(TRELLO_CONFIG_KEYS.apiKey, apiKey);
|
|
86
65
|
}
|
|
87
|
-
/**
|
|
88
|
-
* Save the Trello API token.
|
|
89
|
-
*/
|
|
90
66
|
export function saveTrelloApiToken(db, apiToken) {
|
|
91
|
-
|
|
67
|
+
new SettingsStore(db).set(TRELLO_CONFIG_KEYS.apiToken, apiToken);
|
|
92
68
|
}
|
|
93
|
-
/**
|
|
94
|
-
* Save the Trello board.
|
|
95
|
-
*/
|
|
96
69
|
export function saveTrelloBoard(db, boardId, boardName) {
|
|
97
|
-
|
|
98
|
-
|
|
70
|
+
const settings = new SettingsStore(db);
|
|
71
|
+
settings.set(TRELLO_CONFIG_KEYS.boardId, boardId);
|
|
72
|
+
settings.set(TRELLO_CONFIG_KEYS.boardName, boardName);
|
|
99
73
|
}
|
|
100
|
-
/**
|
|
101
|
-
* Clear all Trello configuration from the database.
|
|
102
|
-
*/
|
|
103
74
|
export function clearTrelloConfig(db) {
|
|
75
|
+
const settings = new SettingsStore(db);
|
|
104
76
|
for (const key of Object.values(TRELLO_CONFIG_KEYS)) {
|
|
105
|
-
|
|
77
|
+
settings.delete(key);
|
|
106
78
|
}
|
|
107
79
|
}
|
|
108
|
-
/**
|
|
109
|
-
* Get the stored Trello API key.
|
|
110
|
-
* Also checks PRLT_TRELLO_API_KEY and TRELLO_API_KEY environment variables.
|
|
111
|
-
*/
|
|
112
80
|
export function getTrelloApiKey(db) {
|
|
113
|
-
// 1. Try provider sources (resolves apiKeyRef → trello.api_key)
|
|
114
81
|
try {
|
|
115
82
|
const sources = loadProviderSources(db);
|
|
116
83
|
for (const source of sources) {
|
|
@@ -124,23 +91,15 @@ export function getTrelloApiKey(db) {
|
|
|
124
91
|
catch {
|
|
125
92
|
// Provider sources may not exist in older databases
|
|
126
93
|
}
|
|
127
|
-
// 2. Legacy: environment variables
|
|
128
94
|
const envKey = process.env.PRLT_TRELLO_API_KEY || process.env.TRELLO_API_KEY;
|
|
129
95
|
if (envKey)
|
|
130
96
|
return envKey;
|
|
131
|
-
|
|
132
|
-
return getSetting(db, TRELLO_CONFIG_KEYS.apiKey);
|
|
97
|
+
return new SettingsStore(db).get(TRELLO_CONFIG_KEYS.apiKey);
|
|
133
98
|
}
|
|
134
|
-
/**
|
|
135
|
-
* Get the stored Trello API token.
|
|
136
|
-
* Also checks PRLT_TRELLO_API_TOKEN and TRELLO_API_TOKEN environment variables.
|
|
137
|
-
*/
|
|
138
99
|
export function getTrelloApiToken(db) {
|
|
139
|
-
// 1. Legacy: environment variables
|
|
140
100
|
const envToken = process.env.PRLT_TRELLO_API_TOKEN || process.env.TRELLO_API_TOKEN;
|
|
141
101
|
if (envToken)
|
|
142
102
|
return envToken;
|
|
143
|
-
|
|
144
|
-
return getSetting(db, TRELLO_CONFIG_KEYS.apiToken);
|
|
103
|
+
return new SettingsStore(db).get(TRELLO_CONFIG_KEYS.apiToken);
|
|
145
104
|
}
|
|
146
105
|
//# sourceMappingURL=config.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/lib/trello/config.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/lib/trello/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import Database from 'better-sqlite3';
|
|
1
|
+
import type Database from 'better-sqlite3';
|
|
2
2
|
import type { TrelloCardMap } from './types.js';
|
|
3
|
+
import { type DatabaseDriver } from '../database/driver.js';
|
|
3
4
|
export declare class TrelloMapper {
|
|
4
|
-
private
|
|
5
|
-
constructor(
|
|
5
|
+
private driver;
|
|
6
|
+
constructor(dbOrDriver: DatabaseDriver | Database.Database);
|
|
6
7
|
private ensureTable;
|
|
7
8
|
createOrUpdateMapping(pmoTicketId: string, trelloCardId: string, trelloBoardId?: string): void;
|
|
8
9
|
getByTicketId(ticketId: string): TrelloCardMap | null;
|
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
import { PMO_TABLES } from '../pmo/schema.js';
|
|
2
|
+
import { wrapDatabase } from '../database/driver.js';
|
|
3
|
+
function toDriver(dbOrDriver) {
|
|
4
|
+
if ('prepare' in dbOrDriver && 'pragma' in dbOrDriver && !('raw' in dbOrDriver)) {
|
|
5
|
+
return wrapDatabase(dbOrDriver);
|
|
6
|
+
}
|
|
7
|
+
return dbOrDriver;
|
|
8
|
+
}
|
|
2
9
|
export class TrelloMapper {
|
|
3
|
-
|
|
4
|
-
constructor(
|
|
5
|
-
this.
|
|
10
|
+
driver;
|
|
11
|
+
constructor(dbOrDriver) {
|
|
12
|
+
this.driver = toDriver(dbOrDriver);
|
|
6
13
|
this.ensureTable();
|
|
7
14
|
}
|
|
8
15
|
ensureTable() {
|
|
9
|
-
this.
|
|
16
|
+
this.driver.exec(`
|
|
10
17
|
CREATE TABLE IF NOT EXISTS ${PMO_TABLES.trello_card_map} (
|
|
11
18
|
pmo_ticket_id TEXT NOT NULL REFERENCES ${PMO_TABLES.tickets}(id) ON DELETE CASCADE,
|
|
12
19
|
trello_card_id TEXT NOT NULL,
|
|
@@ -17,13 +24,13 @@ export class TrelloMapper {
|
|
|
17
24
|
UNIQUE (trello_card_id)
|
|
18
25
|
)
|
|
19
26
|
`);
|
|
20
|
-
this.
|
|
27
|
+
this.driver.exec(`
|
|
21
28
|
CREATE INDEX IF NOT EXISTS idx_pmo_trello_card_map_card_id
|
|
22
29
|
ON ${PMO_TABLES.trello_card_map}(trello_card_id)
|
|
23
30
|
`);
|
|
24
31
|
}
|
|
25
32
|
createOrUpdateMapping(pmoTicketId, trelloCardId, trelloBoardId) {
|
|
26
|
-
this.
|
|
33
|
+
this.driver.prepare(`
|
|
27
34
|
INSERT INTO ${PMO_TABLES.trello_card_map}
|
|
28
35
|
(pmo_ticket_id, trello_card_id, trello_board_id, last_synced_at, created_at)
|
|
29
36
|
VALUES (?, ?, ?, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
|
|
@@ -34,25 +41,25 @@ export class TrelloMapper {
|
|
|
34
41
|
`).run(pmoTicketId, trelloCardId, trelloBoardId ?? null);
|
|
35
42
|
}
|
|
36
43
|
getByTicketId(ticketId) {
|
|
37
|
-
const row = this.
|
|
44
|
+
const row = this.driver.prepare(`
|
|
38
45
|
SELECT * FROM ${PMO_TABLES.trello_card_map} WHERE pmo_ticket_id = ?
|
|
39
46
|
`).get(ticketId);
|
|
40
47
|
return row ? this.rowToMap(row) : null;
|
|
41
48
|
}
|
|
42
49
|
getByCardId(trelloCardId) {
|
|
43
|
-
const row = this.
|
|
50
|
+
const row = this.driver.prepare(`
|
|
44
51
|
SELECT * FROM ${PMO_TABLES.trello_card_map} WHERE trello_card_id = ?
|
|
45
52
|
`).get(trelloCardId);
|
|
46
53
|
return row ? this.rowToMap(row) : null;
|
|
47
54
|
}
|
|
48
55
|
listMappings() {
|
|
49
|
-
const rows = this.
|
|
56
|
+
const rows = this.driver.prepare(`
|
|
50
57
|
SELECT * FROM ${PMO_TABLES.trello_card_map} ORDER BY created_at DESC
|
|
51
58
|
`).all();
|
|
52
59
|
return rows.map((row) => this.rowToMap(row));
|
|
53
60
|
}
|
|
54
61
|
updateSyncTimestamp(ticketId) {
|
|
55
|
-
this.
|
|
62
|
+
this.driver.prepare(`
|
|
56
63
|
UPDATE ${PMO_TABLES.trello_card_map}
|
|
57
64
|
SET last_synced_at = CURRENT_TIMESTAMP
|
|
58
65
|
WHERE pmo_ticket_id = ?
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mapper.js","sourceRoot":"","sources":["../../../src/lib/trello/mapper.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"mapper.js","sourceRoot":"","sources":["../../../src/lib/trello/mapper.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAE7C,OAAO,EAAuB,YAAY,EAAE,MAAM,uBAAuB,CAAA;AAEzE,SAAS,QAAQ,CAAC,UAA8C;IAC9D,IAAI,SAAS,IAAI,UAAU,IAAI,QAAQ,IAAI,UAAU,IAAI,CAAC,CAAC,KAAK,IAAI,UAAU,CAAC,EAAE,CAAC;QAChF,OAAO,YAAY,CAAC,UAA+B,CAAC,CAAA;IACtD,CAAC;IACD,OAAO,UAA4B,CAAA;AACrC,CAAC;AAED,MAAM,OAAO,YAAY;IACf,MAAM,CAAgB;IAE9B,YAAY,UAA8C;QACxD,IAAI,CAAC,MAAM,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAA;QAClC,IAAI,CAAC,WAAW,EAAE,CAAA;IACpB,CAAC;IAEO,WAAW;QACjB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;mCACc,UAAU,CAAC,eAAe;iDACZ,UAAU,CAAC,OAAO;;;;;;;;KAQ9D,CAAC,CAAA;QAEF,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;;aAER,UAAU,CAAC,eAAe;KAClC,CAAC,CAAA;IACJ,CAAC;IAED,qBAAqB,CAAC,WAAmB,EAAE,YAAoB,EAAE,aAAsB;QACrF,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC;oBACJ,UAAU,CAAC,eAAe;;;;;;;KAOzC,CAAC,CAAC,GAAG,CAAC,WAAW,EAAE,YAAY,EAAE,aAAa,IAAI,IAAI,CAAC,CAAA;IAC1D,CAAC;IAED,aAAa,CAAC,QAAgB;QAC5B,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAA0B;sBACvC,UAAU,CAAC,eAAe;KAC3C,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QAEhB,OAAO,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;IACxC,CAAC;IAED,WAAW,CAAC,YAAoB;QAC9B,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAA0B;sBACvC,UAAU,CAAC,eAAe;KAC3C,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,CAAA;QAEpB,OAAO,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;IACxC,CAAC;IAED,YAAY;QACV,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAA0B;sBACxC,UAAU,CAAC,eAAe;KAC3C,CAAC,CAAC,GAAG,EAAE,CAAA;QAER,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAA;IAC9C,CAAC;IAED,mBAAmB,CAAC,QAAgB;QAClC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC;eACT,UAAU,CAAC,eAAe;;;KAGpC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;IAClB,CAAC;IAEO,QAAQ,CAAC,GAA4B;QAC3C,OAAO;YACL,WAAW,EAAE,GAAG,CAAC,aAAuB;YACxC,YAAY,EAAE,GAAG,CAAC,cAAwB;YAC1C,aAAa,EAAG,GAAG,CAAC,eAAiC,IAAI,SAAS;YAClE,YAAY,EAAE,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,cAAwB,CAAC,CAAC,CAAC,CAAC,SAAS;YACrF,SAAS,EAAE,IAAI,IAAI,CAAC,GAAG,CAAC,UAAoB,CAAC;SAC9C,CAAA;IACH,CAAC;CACF"}
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
* (Linear, Jira, etc.) — not through the local PMO as a cache layer.
|
|
14
14
|
* The local PMO is just the default provider for users without integrations.
|
|
15
15
|
*/
|
|
16
|
-
import Database from 'better-sqlite3';
|
|
17
|
-
import type { StateCategory } from '../pmo/types.js';
|
|
16
|
+
import type Database from 'better-sqlite3';
|
|
17
|
+
import type { StateCategory, ReviewGateMode } from '../pmo/types.js';
|
|
18
18
|
import type { ProviderStorage } from '../providers/types.js';
|
|
19
19
|
import { type CommitValidationResult } from '../execution/commit-validation.js';
|
|
20
20
|
export interface PostExecutionContext {
|
|
@@ -28,6 +28,8 @@ export interface PostExecutionContext {
|
|
|
28
28
|
agentDir?: string;
|
|
29
29
|
/** Repo worktree names within agentDir */
|
|
30
30
|
repoWorktrees?: string[];
|
|
31
|
+
/** Review gate mode — determines post-execution behavior */
|
|
32
|
+
reviewGate?: ReviewGateMode;
|
|
31
33
|
}
|
|
32
34
|
export interface PostExecutionResult {
|
|
33
35
|
transitioned: boolean;
|
|
@@ -41,6 +43,8 @@ export interface PostExecutionResult {
|
|
|
41
43
|
validation?: CommitValidationResult;
|
|
42
44
|
/** True if the transition was blocked by commit validation */
|
|
43
45
|
blockedByValidation?: boolean;
|
|
46
|
+
/** The review gate mode that was applied */
|
|
47
|
+
reviewGate?: ReviewGateMode;
|
|
44
48
|
}
|
|
45
49
|
/**
|
|
46
50
|
* Minimal storage interface for post-execution transitions.
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* (Linear, Jira, etc.) — not through the local PMO as a cache layer.
|
|
14
14
|
* The local PMO is just the default provider for users without integrations.
|
|
15
15
|
*/
|
|
16
|
-
import { getWorkColumnSetting, findColumnByName } from '../pmo/utils.js';
|
|
16
|
+
import { getWorkColumnSetting, findColumnByName, getReviewGateSetting } from '../pmo/utils.js';
|
|
17
17
|
import { resolveTicketProvider } from '../providers/resolver.js';
|
|
18
18
|
import { tryValidateCommits } from '../execution/commit-validation.js';
|
|
19
19
|
/**
|
|
@@ -47,10 +47,15 @@ export async function handlePostExecutionTransition(context, storage, db) {
|
|
|
47
47
|
if (ticket.statusCategory !== 'started') {
|
|
48
48
|
return { transitioned: false };
|
|
49
49
|
}
|
|
50
|
-
//
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
50
|
+
// Resolve the effective review gate mode
|
|
51
|
+
const reviewGate = context.reviewGate || getReviewGateSetting(db);
|
|
52
|
+
// For auto mode, skip PR check — agent ships directly to main
|
|
53
|
+
// For required/post modes, check if a PR was created
|
|
54
|
+
if (reviewGate !== 'auto') {
|
|
55
|
+
const prUrl = ticket.metadata?.pr_url;
|
|
56
|
+
if (!prUrl) {
|
|
57
|
+
return { transitioned: false, reviewGate };
|
|
58
|
+
}
|
|
54
59
|
}
|
|
55
60
|
// PRLT-984: Validate that meaningful code was committed before transitioning.
|
|
56
61
|
// If agent info is available (branch + agentDir), run commit validation.
|
|
@@ -67,6 +72,7 @@ export async function handlePostExecutionTransition(context, storage, db) {
|
|
|
67
72
|
fromState: ticket.statusName,
|
|
68
73
|
validation,
|
|
69
74
|
blockedByValidation: true,
|
|
75
|
+
reviewGate,
|
|
70
76
|
};
|
|
71
77
|
}
|
|
72
78
|
}
|
|
@@ -76,21 +82,25 @@ export async function handlePostExecutionTransition(context, storage, db) {
|
|
|
76
82
|
// If we can't validate, allow the transition to proceed.
|
|
77
83
|
}
|
|
78
84
|
}
|
|
79
|
-
//
|
|
80
|
-
|
|
81
|
-
//
|
|
85
|
+
// Determine target column based on review gate mode:
|
|
86
|
+
// - auto: move to Done (no human review needed)
|
|
87
|
+
// - post: move to Review (human reviews post-merge)
|
|
88
|
+
// - required: move to Review (human must approve)
|
|
89
|
+
const targetColumnType = reviewGate === 'auto' ? 'done' : 'review';
|
|
90
|
+
const targetColumnName = getWorkColumnSetting(db, targetColumnType);
|
|
91
|
+
// Get board columns to find the target column
|
|
82
92
|
const board = await storage.getProjectBoard(ticket.projectId);
|
|
83
93
|
if (!board) {
|
|
84
|
-
return { transitioned: false };
|
|
94
|
+
return { transitioned: false, reviewGate };
|
|
85
95
|
}
|
|
86
96
|
const columnNames = board.columns.map(col => col.name);
|
|
87
|
-
const
|
|
88
|
-
if (!
|
|
89
|
-
return { transitioned: false };
|
|
97
|
+
const targetColumn = findColumnByName(columnNames, targetColumnName);
|
|
98
|
+
if (!targetColumn) {
|
|
99
|
+
return { transitioned: false, reviewGate };
|
|
90
100
|
}
|
|
91
|
-
// Already in
|
|
92
|
-
if (ticket.statusName ===
|
|
93
|
-
return { transitioned: false };
|
|
101
|
+
// Already in target state — skip
|
|
102
|
+
if (ticket.statusName === targetColumn) {
|
|
103
|
+
return { transitioned: false, reviewGate };
|
|
94
104
|
}
|
|
95
105
|
// Resolve the appropriate provider for this ticket
|
|
96
106
|
// Cast to ProviderStorage — at runtime the actual object is SQLiteStorage
|
|
@@ -98,23 +108,25 @@ export async function handlePostExecutionTransition(context, storage, db) {
|
|
|
98
108
|
const provider = resolveTicketProvider(context.ticketId, ticket.projectId, db, storage, ticket.metadata);
|
|
99
109
|
// Move ticket via the provider
|
|
100
110
|
const previousState = ticket.statusName;
|
|
101
|
-
const moveResult = await provider.moveTicket(context.ticketId,
|
|
111
|
+
const moveResult = await provider.moveTicket(context.ticketId, targetColumn);
|
|
102
112
|
if (!moveResult.success) {
|
|
103
113
|
return {
|
|
104
114
|
transitioned: false,
|
|
105
115
|
fromState: previousState,
|
|
106
|
-
toState:
|
|
116
|
+
toState: targetColumn,
|
|
107
117
|
provider: moveResult.provider,
|
|
108
118
|
providerError: moveResult.error,
|
|
109
119
|
validation,
|
|
120
|
+
reviewGate,
|
|
110
121
|
};
|
|
111
122
|
}
|
|
112
123
|
return {
|
|
113
124
|
transitioned: true,
|
|
114
125
|
fromState: previousState,
|
|
115
|
-
toState:
|
|
126
|
+
toState: targetColumn,
|
|
116
127
|
provider: moveResult.provider,
|
|
117
128
|
validation,
|
|
129
|
+
reviewGate,
|
|
118
130
|
};
|
|
119
131
|
}
|
|
120
132
|
//# sourceMappingURL=post-execution.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"post-execution.js","sourceRoot":"","sources":["../../../src/lib/work-lifecycle/post-execution.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"post-execution.js","sourceRoot":"","sources":["../../../src/lib/work-lifecycle/post-execution.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import Database from 'better-sqlite3';
|
|
1
|
+
import type Database from 'better-sqlite3';
|
|
2
2
|
export declare const WORK_SOURCE_PROVIDERS: readonly ["pmo", "linear", "jira", "shortcut", "asana", "trello", "monday"];
|
|
3
3
|
export type WorkSourceProvider = typeof WORK_SOURCE_PROVIDERS[number];
|
|
4
4
|
export interface WorkSourceRef {
|