openplanr 1.2.7 → 1.3.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 +41 -4
- package/dist/agents/task-parser.d.ts.map +1 -1
- package/dist/agents/task-parser.js +8 -34
- package/dist/agents/task-parser.js.map +1 -1
- package/dist/ai/prompts/prompt-builder.d.ts +48 -0
- package/dist/ai/prompts/prompt-builder.d.ts.map +1 -1
- package/dist/ai/prompts/prompt-builder.js +57 -1
- package/dist/ai/prompts/prompt-builder.js.map +1 -1
- package/dist/ai/prompts/system-prompts.d.ts +24 -1
- package/dist/ai/prompts/system-prompts.d.ts.map +1 -1
- package/dist/ai/prompts/system-prompts.js +104 -6
- package/dist/ai/prompts/system-prompts.js.map +1 -1
- package/dist/ai/schemas/ai-response-schemas.d.ts +68 -0
- package/dist/ai/schemas/ai-response-schemas.d.ts.map +1 -1
- package/dist/ai/schemas/ai-response-schemas.js +81 -0
- package/dist/ai/schemas/ai-response-schemas.js.map +1 -1
- package/dist/ai/types.d.ts +2 -0
- package/dist/ai/types.d.ts.map +1 -1
- package/dist/ai/types.js +4 -0
- package/dist/ai/types.js.map +1 -1
- package/dist/cli/commands/backlog.d.ts +12 -0
- package/dist/cli/commands/backlog.d.ts.map +1 -1
- package/dist/cli/commands/backlog.js +88 -2
- package/dist/cli/commands/backlog.js.map +1 -1
- package/dist/cli/commands/config.d.ts.map +1 -1
- package/dist/cli/commands/config.js +8 -2
- package/dist/cli/commands/config.js.map +1 -1
- package/dist/cli/commands/linear.d.ts +8 -0
- package/dist/cli/commands/linear.d.ts.map +1 -0
- package/dist/cli/commands/linear.js +550 -0
- package/dist/cli/commands/linear.js.map +1 -0
- package/dist/cli/commands/quick.d.ts +17 -0
- package/dist/cli/commands/quick.d.ts.map +1 -1
- package/dist/cli/commands/quick.js +31 -15
- package/dist/cli/commands/quick.js.map +1 -1
- package/dist/cli/commands/revise.d.ts +24 -0
- package/dist/cli/commands/revise.d.ts.map +1 -0
- package/dist/cli/commands/revise.js +570 -0
- package/dist/cli/commands/revise.js.map +1 -0
- package/dist/cli/index.js +4 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/models/schema.d.ts +43 -0
- package/dist/models/schema.d.ts.map +1 -1
- package/dist/models/schema.js +49 -0
- package/dist/models/schema.js.map +1 -1
- package/dist/models/types.d.ts +296 -0
- package/dist/models/types.d.ts.map +1 -1
- package/dist/services/artifact-gathering.d.ts +4 -0
- package/dist/services/artifact-gathering.d.ts.map +1 -1
- package/dist/services/artifact-gathering.js +1 -1
- package/dist/services/artifact-gathering.js.map +1 -1
- package/dist/services/artifact-service.d.ts +12 -1
- package/dist/services/artifact-service.d.ts.map +1 -1
- package/dist/services/artifact-service.js +49 -6
- package/dist/services/artifact-service.js.map +1 -1
- package/dist/services/atomic-write-service.d.ts +41 -0
- package/dist/services/atomic-write-service.d.ts.map +1 -0
- package/dist/services/atomic-write-service.js +87 -0
- package/dist/services/atomic-write-service.js.map +1 -0
- package/dist/services/audit-log-service.d.ts +47 -0
- package/dist/services/audit-log-service.d.ts.map +1 -0
- package/dist/services/audit-log-service.js +210 -0
- package/dist/services/audit-log-service.js.map +1 -0
- package/dist/services/cascade-service.d.ts +62 -0
- package/dist/services/cascade-service.d.ts.map +1 -0
- package/dist/services/cascade-service.js +189 -0
- package/dist/services/cascade-service.js.map +1 -0
- package/dist/services/credentials-service.js +2 -2
- package/dist/services/credentials-service.js.map +1 -1
- package/dist/services/diff-service.d.ts +18 -0
- package/dist/services/diff-service.d.ts.map +1 -0
- package/dist/services/diff-service.js +35 -0
- package/dist/services/diff-service.js.map +1 -0
- package/dist/services/evidence-verifier.d.ts +71 -0
- package/dist/services/evidence-verifier.d.ts.map +1 -0
- package/dist/services/evidence-verifier.js +174 -0
- package/dist/services/evidence-verifier.js.map +1 -0
- package/dist/services/git-service.d.ts +60 -0
- package/dist/services/git-service.d.ts.map +1 -0
- package/dist/services/git-service.js +137 -0
- package/dist/services/git-service.js.map +1 -0
- package/dist/services/graph-integrity.d.ts +35 -0
- package/dist/services/graph-integrity.d.ts.map +1 -0
- package/dist/services/graph-integrity.js +53 -0
- package/dist/services/graph-integrity.js.map +1 -0
- package/dist/services/linear/body-formatters.d.ts +69 -0
- package/dist/services/linear/body-formatters.d.ts.map +1 -0
- package/dist/services/linear/body-formatters.js +183 -0
- package/dist/services/linear/body-formatters.js.map +1 -0
- package/dist/services/linear/constants.d.ts +61 -0
- package/dist/services/linear/constants.d.ts.map +1 -0
- package/dist/services/linear/constants.js +84 -0
- package/dist/services/linear/constants.js.map +1 -0
- package/dist/services/linear/errors.d.ts +14 -0
- package/dist/services/linear/errors.d.ts.map +1 -0
- package/dist/services/linear/errors.js +106 -0
- package/dist/services/linear/errors.js.map +1 -0
- package/dist/services/linear/estimate-resolver.d.ts +50 -0
- package/dist/services/linear/estimate-resolver.d.ts.map +1 -0
- package/dist/services/linear/estimate-resolver.js +82 -0
- package/dist/services/linear/estimate-resolver.js.map +1 -0
- package/dist/services/linear/plan-builders.d.ts +64 -0
- package/dist/services/linear/plan-builders.d.ts.map +1 -0
- package/dist/services/linear/plan-builders.js +237 -0
- package/dist/services/linear/plan-builders.js.map +1 -0
- package/dist/services/linear/scope-loaders.d.ts +79 -0
- package/dist/services/linear/scope-loaders.d.ts.map +1 -0
- package/dist/services/linear/scope-loaders.js +227 -0
- package/dist/services/linear/scope-loaders.js.map +1 -0
- package/dist/services/linear/strategy-context.d.ts +66 -0
- package/dist/services/linear/strategy-context.d.ts.map +1 -0
- package/dist/services/linear/strategy-context.js +121 -0
- package/dist/services/linear/strategy-context.js.map +1 -0
- package/dist/services/linear-mapping-service.d.ts +11 -0
- package/dist/services/linear-mapping-service.d.ts.map +1 -0
- package/dist/services/linear-mapping-service.js +220 -0
- package/dist/services/linear-mapping-service.js.map +1 -0
- package/dist/services/linear-pull-service.d.ts +137 -0
- package/dist/services/linear-pull-service.d.ts.map +1 -0
- package/dist/services/linear-pull-service.js +720 -0
- package/dist/services/linear-pull-service.js.map +1 -0
- package/dist/services/linear-push-service.d.ts +86 -0
- package/dist/services/linear-push-service.d.ts.map +1 -0
- package/dist/services/linear-push-service.js +956 -0
- package/dist/services/linear-push-service.js.map +1 -0
- package/dist/services/linear-service.d.ts +122 -0
- package/dist/services/linear-service.d.ts.map +1 -0
- package/dist/services/linear-service.js +361 -0
- package/dist/services/linear-service.js.map +1 -0
- package/dist/services/prompt-service.d.ts +37 -0
- package/dist/services/prompt-service.d.ts.map +1 -1
- package/dist/services/prompt-service.js +111 -0
- package/dist/services/prompt-service.js.map +1 -1
- package/dist/services/revise-apply-service.d.ts +55 -0
- package/dist/services/revise-apply-service.d.ts.map +1 -0
- package/dist/services/revise-apply-service.js +255 -0
- package/dist/services/revise-apply-service.js.map +1 -0
- package/dist/services/revise-cache-service.d.ts +46 -0
- package/dist/services/revise-cache-service.d.ts.map +1 -0
- package/dist/services/revise-cache-service.js +88 -0
- package/dist/services/revise-cache-service.js.map +1 -0
- package/dist/services/revise-plan-service.d.ts +38 -0
- package/dist/services/revise-plan-service.d.ts.map +1 -0
- package/dist/services/revise-plan-service.js +151 -0
- package/dist/services/revise-plan-service.js.map +1 -0
- package/dist/services/revise-service.d.ts +115 -0
- package/dist/services/revise-service.d.ts.map +1 -0
- package/dist/services/revise-service.js +294 -0
- package/dist/services/revise-service.js.map +1 -0
- package/dist/services/template-sections.d.ts +28 -0
- package/dist/services/template-sections.d.ts.map +1 -0
- package/dist/services/template-sections.js +55 -0
- package/dist/services/template-sections.js.map +1 -0
- package/dist/templates/backlog/backlog-item.md.hbs +3 -0
- package/dist/templates/quick/quick-task.md.hbs +6 -0
- package/dist/utils/diff.d.ts +47 -0
- package/dist/utils/diff.d.ts.map +1 -0
- package/dist/utils/diff.js +278 -0
- package/dist/utils/diff.js.map +1 -0
- package/dist/utils/markdown.d.ts +23 -0
- package/dist/utils/markdown.d.ts.map +1 -1
- package/dist/utils/markdown.js +79 -0
- package/dist/utils/markdown.js.map +1 -1
- package/package.json +3 -2
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure plan-building for `planr linear push --dry-run`. Takes loaded scopes
|
|
3
|
+
* and returns `LinearPushPlan` objects with per-kind row counts. No Linear
|
|
4
|
+
* API calls; no mutations. Epic-scope plans cascade rows for linked QT/BL.
|
|
5
|
+
*/
|
|
6
|
+
import { findArtifactTypeById, listArtifacts, readArtifact } from '../artifact-service.js';
|
|
7
|
+
import { buildMergedTaskListBody, toOptionalString } from './body-formatters.js';
|
|
8
|
+
import { loadForBacklogItem, loadForFeature, loadForQuickTask, loadForStory, loadForTaskFile, loadLinearPushScope, } from './scope-loaders.js';
|
|
9
|
+
/**
|
|
10
|
+
* Extract the linked epic id from QT / BL frontmatter. Canonical field is
|
|
11
|
+
* `epicId`; `parentEpic` is accepted as a compat alias for hand-authored
|
|
12
|
+
* files. Empty strings are normalised to `undefined`.
|
|
13
|
+
*/
|
|
14
|
+
export function getLinkedEpicId(fm) {
|
|
15
|
+
return toOptionalString(fm.epicId) ?? toOptionalString(fm.parentEpic);
|
|
16
|
+
}
|
|
17
|
+
function sortByArtifactId(a, b) {
|
|
18
|
+
return a.id.localeCompare(b.id, undefined, { numeric: true });
|
|
19
|
+
}
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
// Per-kind row builders
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
export function projectRow(epic) {
|
|
24
|
+
const id = epic.linearProjectId;
|
|
25
|
+
return {
|
|
26
|
+
kind: 'project',
|
|
27
|
+
artifactId: epic.id,
|
|
28
|
+
title: epic.title.trim() || epic.id,
|
|
29
|
+
action: id ? 'update' : 'create',
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
export function featureRow(f) {
|
|
33
|
+
return {
|
|
34
|
+
kind: 'feature',
|
|
35
|
+
artifactId: f.id,
|
|
36
|
+
title: f.title.trim() || f.id,
|
|
37
|
+
action: f.linearIssueId ? 'update' : 'create',
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
export function storyRow(s) {
|
|
41
|
+
return {
|
|
42
|
+
kind: 'story',
|
|
43
|
+
artifactId: s.id,
|
|
44
|
+
title: s.title.trim() || s.id,
|
|
45
|
+
action: s.linearIssueId ? 'update' : 'create',
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
export function taskListPlanRow(featureId, taskFiles, hasBody, hadIssue) {
|
|
49
|
+
if (!hasBody && !hadIssue) {
|
|
50
|
+
return {
|
|
51
|
+
kind: 'taskList',
|
|
52
|
+
artifactId: featureId,
|
|
53
|
+
title: `Tasks (${featureId})`,
|
|
54
|
+
action: 'skip',
|
|
55
|
+
detail: 'No task checkbox lines in task file(s) for this feature.',
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
const label = taskFiles[0]?.id ?? featureId;
|
|
59
|
+
return {
|
|
60
|
+
kind: 'taskList',
|
|
61
|
+
artifactId: label,
|
|
62
|
+
title: `Tasks: ${featureId}`,
|
|
63
|
+
action: hadIssue ? 'update' : 'create',
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
export function applyUpdateOnly(rows, updateOnly) {
|
|
67
|
+
if (!updateOnly)
|
|
68
|
+
return rows;
|
|
69
|
+
return rows.map((r) => r.action === 'create'
|
|
70
|
+
? {
|
|
71
|
+
...r,
|
|
72
|
+
action: 'skip',
|
|
73
|
+
detail: r.detail
|
|
74
|
+
? `${r.detail} (not created: --update-only)`
|
|
75
|
+
: 'not created: --update-only',
|
|
76
|
+
}
|
|
77
|
+
: r);
|
|
78
|
+
}
|
|
79
|
+
export function summarizePlan(rootArtifactId, epicId, scope, rows) {
|
|
80
|
+
const countKind = (k) => rows.filter((r) => r.kind === k && r.action !== 'skip').length;
|
|
81
|
+
const project = countKind('project');
|
|
82
|
+
const features = countKind('feature');
|
|
83
|
+
const stories = countKind('story');
|
|
84
|
+
const taskLists = countKind('taskList');
|
|
85
|
+
const quickTasks = countKind('quickTask');
|
|
86
|
+
const backlogItems = countKind('backlogItem');
|
|
87
|
+
return {
|
|
88
|
+
rootArtifactId,
|
|
89
|
+
epicId,
|
|
90
|
+
scope,
|
|
91
|
+
rows,
|
|
92
|
+
counts: {
|
|
93
|
+
project,
|
|
94
|
+
features,
|
|
95
|
+
stories,
|
|
96
|
+
taskLists,
|
|
97
|
+
quickTasks,
|
|
98
|
+
backlogItems,
|
|
99
|
+
total: project + features + stories + taskLists + quickTasks + backlogItems,
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
// ---------------------------------------------------------------------------
|
|
104
|
+
// Scope-level row assembly
|
|
105
|
+
// ---------------------------------------------------------------------------
|
|
106
|
+
export async function buildFeaturePlanRows(projectDir, config, sf) {
|
|
107
|
+
const rows = [];
|
|
108
|
+
rows.push(featureRow(sf.data));
|
|
109
|
+
for (const st of sf.stories) {
|
|
110
|
+
rows.push(storyRow(st.data));
|
|
111
|
+
}
|
|
112
|
+
const withLinear = await Promise.all(sf.taskFiles.map(async (tf) => {
|
|
113
|
+
const a = await readArtifact(projectDir, config, 'task', tf.id);
|
|
114
|
+
return { tf, issueId: toOptionalString(a?.data.linearIssueId) };
|
|
115
|
+
}));
|
|
116
|
+
const hadIssue = Boolean(withLinear.find((x) => x.issueId)?.issueId);
|
|
117
|
+
const body = await buildMergedTaskListBody(projectDir, config, sf.data.id, sf.taskFiles);
|
|
118
|
+
const hasBody = body.trim().length > 0;
|
|
119
|
+
rows.push(taskListPlanRow(sf.data.id, sf.taskFiles, hasBody, hadIssue));
|
|
120
|
+
return rows;
|
|
121
|
+
}
|
|
122
|
+
export async function buildEpicPlanRows(projectDir, config, epicScope) {
|
|
123
|
+
const rows = [];
|
|
124
|
+
rows.push(projectRow(epicScope.epic));
|
|
125
|
+
for (const sf of epicScope.features) {
|
|
126
|
+
rows.push(...(await buildFeaturePlanRows(projectDir, config, sf)));
|
|
127
|
+
}
|
|
128
|
+
// Linked QT / BL artifacts get their own rows so `--dry-run` matches what
|
|
129
|
+
// `runLinearPush` would actually touch.
|
|
130
|
+
const quicks = await listArtifacts(projectDir, config, 'quick');
|
|
131
|
+
for (const q of quicks.sort(sortByArtifactId)) {
|
|
132
|
+
const art = await readArtifact(projectDir, config, 'quick', q.id);
|
|
133
|
+
if (!art || getLinkedEpicId(art.data) !== epicScope.epic.id)
|
|
134
|
+
continue;
|
|
135
|
+
const hasId = Boolean(toOptionalString(art.data.linearIssueId));
|
|
136
|
+
rows.push({
|
|
137
|
+
kind: 'quickTask',
|
|
138
|
+
artifactId: q.id,
|
|
139
|
+
title: art.data.title?.trim() || q.title || q.id,
|
|
140
|
+
action: hasId ? 'update' : 'create',
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
const backlogs = await listArtifacts(projectDir, config, 'backlog');
|
|
144
|
+
for (const b of backlogs.sort(sortByArtifactId)) {
|
|
145
|
+
const art = await readArtifact(projectDir, config, 'backlog', b.id);
|
|
146
|
+
if (!art || getLinkedEpicId(art.data) !== epicScope.epic.id)
|
|
147
|
+
continue;
|
|
148
|
+
const hasId = Boolean(toOptionalString(art.data.linearIssueId));
|
|
149
|
+
rows.push({
|
|
150
|
+
kind: 'backlogItem',
|
|
151
|
+
artifactId: b.id,
|
|
152
|
+
title: art.data.title?.trim() || b.title || b.id,
|
|
153
|
+
action: hasId ? 'update' : 'create',
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
return rows;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Build a push preview (and counts) for `planr linear push --dry-run` at any
|
|
160
|
+
* granularity. Accepts any supported artifact id prefix (EPIC/FEAT/US/TASK/
|
|
161
|
+
* QT/BL); returns `null` when the artifact can't be resolved or is not
|
|
162
|
+
* pushable (ADR/SPRINT/checklist).
|
|
163
|
+
*/
|
|
164
|
+
export async function buildLinearPushPlan(projectDir, config, artifactId, options) {
|
|
165
|
+
const updateOnly = options?.updateOnly === true;
|
|
166
|
+
const type = findArtifactTypeById(artifactId);
|
|
167
|
+
if (!type)
|
|
168
|
+
return null;
|
|
169
|
+
if (type === 'epic') {
|
|
170
|
+
const scope = await loadLinearPushScope(projectDir, config, artifactId);
|
|
171
|
+
if (!scope)
|
|
172
|
+
return null;
|
|
173
|
+
const rows = applyUpdateOnly(await buildEpicPlanRows(projectDir, config, scope), updateOnly);
|
|
174
|
+
return summarizePlan(artifactId, scope.epic.id, 'epic', rows);
|
|
175
|
+
}
|
|
176
|
+
if (type === 'feature') {
|
|
177
|
+
const ctx = await loadForFeature(projectDir, config, artifactId);
|
|
178
|
+
if (!ctx)
|
|
179
|
+
return null;
|
|
180
|
+
const rows = applyUpdateOnly(await buildFeaturePlanRows(projectDir, config, ctx.sf), updateOnly);
|
|
181
|
+
return summarizePlan(artifactId, ctx.epic.id, 'feature', rows);
|
|
182
|
+
}
|
|
183
|
+
if (type === 'story') {
|
|
184
|
+
const ctx = await loadForStory(projectDir, config, artifactId);
|
|
185
|
+
if (!ctx)
|
|
186
|
+
return null;
|
|
187
|
+
const rows = applyUpdateOnly([storyRow(ctx.story.data)], updateOnly);
|
|
188
|
+
return summarizePlan(artifactId, ctx.epic.id, 'story', rows);
|
|
189
|
+
}
|
|
190
|
+
if (type === 'task') {
|
|
191
|
+
const ctx = await loadForTaskFile(projectDir, config, artifactId);
|
|
192
|
+
if (!ctx)
|
|
193
|
+
return null;
|
|
194
|
+
const withLinear = await Promise.all(ctx.sf.taskFiles.map(async (tf) => {
|
|
195
|
+
const a = await readArtifact(projectDir, config, 'task', tf.id);
|
|
196
|
+
return { tf, issueId: toOptionalString(a?.data.linearIssueId) };
|
|
197
|
+
}));
|
|
198
|
+
const hadIssue = Boolean(withLinear.find((x) => x.issueId)?.issueId);
|
|
199
|
+
const body = await buildMergedTaskListBody(projectDir, config, ctx.sf.data.id, ctx.sf.taskFiles);
|
|
200
|
+
const hasBody = body.trim().length > 0;
|
|
201
|
+
const rows = applyUpdateOnly([taskListPlanRow(ctx.sf.data.id, ctx.sf.taskFiles, hasBody, hadIssue)], updateOnly);
|
|
202
|
+
return summarizePlan(artifactId, ctx.epic.id, 'taskFile', rows);
|
|
203
|
+
}
|
|
204
|
+
if (type === 'quick') {
|
|
205
|
+
const qt = await loadForQuickTask(projectDir, config, artifactId);
|
|
206
|
+
if (!qt)
|
|
207
|
+
return null;
|
|
208
|
+
const hasId = Boolean(toOptionalString(qt.frontmatter.linearIssueId));
|
|
209
|
+
const rows = applyUpdateOnly([
|
|
210
|
+
{
|
|
211
|
+
kind: 'quickTask',
|
|
212
|
+
artifactId,
|
|
213
|
+
title: qt.title.trim() || qt.id,
|
|
214
|
+
action: hasId ? 'update' : 'create',
|
|
215
|
+
},
|
|
216
|
+
], updateOnly);
|
|
217
|
+
return summarizePlan(artifactId, undefined, 'quick', rows);
|
|
218
|
+
}
|
|
219
|
+
if (type === 'backlog') {
|
|
220
|
+
const bl = await loadForBacklogItem(projectDir, config, artifactId);
|
|
221
|
+
if (!bl)
|
|
222
|
+
return null;
|
|
223
|
+
const hasId = Boolean(toOptionalString(bl.frontmatter.linearIssueId));
|
|
224
|
+
const rows = applyUpdateOnly([
|
|
225
|
+
{
|
|
226
|
+
kind: 'backlogItem',
|
|
227
|
+
artifactId,
|
|
228
|
+
title: bl.title.trim() || bl.id,
|
|
229
|
+
action: hasId ? 'update' : 'create',
|
|
230
|
+
},
|
|
231
|
+
], updateOnly);
|
|
232
|
+
return summarizePlan(artifactId, undefined, 'backlog', rows);
|
|
233
|
+
}
|
|
234
|
+
// sprint / adr / checklist — not supported.
|
|
235
|
+
return null;
|
|
236
|
+
}
|
|
237
|
+
//# sourceMappingURL=plan-builders.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan-builders.js","sourceRoot":"","sources":["../../../src/services/linear/plan-builders.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure data loaders that hydrate OpenPlanr artifacts into the shapes the
|
|
3
|
+
* Linear push expects. No Linear API calls, no mutations — just filesystem
|
|
4
|
+
* reads + frontmatter parsing. Every scope-level push function routes
|
|
5
|
+
* through one of these loaders first.
|
|
6
|
+
*/
|
|
7
|
+
import type { Epic, Feature, OpenPlanrConfig, UserStory } from '../../models/types.js';
|
|
8
|
+
export interface ScopedTaskFile {
|
|
9
|
+
id: string;
|
|
10
|
+
title: string;
|
|
11
|
+
}
|
|
12
|
+
export interface ScopedStory {
|
|
13
|
+
id: string;
|
|
14
|
+
title: string;
|
|
15
|
+
data: UserStory;
|
|
16
|
+
/** Raw YAML frontmatter — carries fields not mapped onto the typed `data`
|
|
17
|
+
* (e.g. `estimatedPoints`, `storyPoints` for Linear estimate sync). */
|
|
18
|
+
frontmatter: Record<string, unknown>;
|
|
19
|
+
}
|
|
20
|
+
export interface ScopedFeature {
|
|
21
|
+
id: string;
|
|
22
|
+
title: string;
|
|
23
|
+
data: Feature;
|
|
24
|
+
/** Raw YAML frontmatter — same purpose as ScopedStory.frontmatter. */
|
|
25
|
+
frontmatter: Record<string, unknown>;
|
|
26
|
+
stories: ScopedStory[];
|
|
27
|
+
taskFiles: ScopedTaskFile[];
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Shape needed to push a standalone artifact (QT or BL) — the raw markdown
|
|
31
|
+
* (so QT can parse + re-render its checkbox list) plus the frontmatter
|
|
32
|
+
* record (linear* fields, epicId link, etc.).
|
|
33
|
+
*/
|
|
34
|
+
export interface ScopedStandaloneArtifact {
|
|
35
|
+
id: string;
|
|
36
|
+
title: string;
|
|
37
|
+
raw: string;
|
|
38
|
+
frontmatter: Record<string, unknown>;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Load the full epic subtree (epic frontmatter + features + stories per
|
|
42
|
+
* feature + task-file ids per feature). Filters by `epicId` on each child
|
|
43
|
+
* artifact.
|
|
44
|
+
*/
|
|
45
|
+
export declare function loadLinearPushScope(projectDir: string, config: OpenPlanrConfig, epicId: string): Promise<{
|
|
46
|
+
epic: Epic;
|
|
47
|
+
features: ScopedFeature[];
|
|
48
|
+
} | null>;
|
|
49
|
+
/**
|
|
50
|
+
* Parent-chain context needed to push a feature: the feature itself (with
|
|
51
|
+
* its stories and task files) plus its parent epic. Returns `null` if the
|
|
52
|
+
* feature can't be resolved or has no valid `epicId` pointer.
|
|
53
|
+
*/
|
|
54
|
+
export declare function loadForFeature(projectDir: string, config: OpenPlanrConfig, featureId: string): Promise<{
|
|
55
|
+
epic: Epic;
|
|
56
|
+
sf: ScopedFeature;
|
|
57
|
+
} | null>;
|
|
58
|
+
/**
|
|
59
|
+
* Parent-chain context needed to push a story: the story itself, its
|
|
60
|
+
* feature (with sibling stories + tasklists) and the containing epic.
|
|
61
|
+
* Returns `null` if any link in the chain is missing.
|
|
62
|
+
*/
|
|
63
|
+
export declare function loadForStory(projectDir: string, config: OpenPlanrConfig, storyId: string): Promise<{
|
|
64
|
+
epic: Epic;
|
|
65
|
+
sf: ScopedFeature;
|
|
66
|
+
story: ScopedStory;
|
|
67
|
+
} | null>;
|
|
68
|
+
/**
|
|
69
|
+
* Parent-chain context needed to push a task file: the containing feature
|
|
70
|
+
* (with all its task files merged into one Linear sub-issue body) and the
|
|
71
|
+
* epic.
|
|
72
|
+
*/
|
|
73
|
+
export declare function loadForTaskFile(projectDir: string, config: OpenPlanrConfig, taskId: string): Promise<{
|
|
74
|
+
epic: Epic;
|
|
75
|
+
sf: ScopedFeature;
|
|
76
|
+
} | null>;
|
|
77
|
+
export declare function loadForQuickTask(projectDir: string, config: OpenPlanrConfig, qtId: string): Promise<ScopedStandaloneArtifact | null>;
|
|
78
|
+
export declare function loadForBacklogItem(projectDir: string, config: OpenPlanrConfig, blId: string): Promise<ScopedStandaloneArtifact | null>;
|
|
79
|
+
//# sourceMappingURL=scope-loaders.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scope-loaders.d.ts","sourceRoot":"","sources":["../../../src/services/linear/scope-loaders.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,eAAe,EAAc,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAkBnG,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,SAAS,CAAC;IAChB;2EACuE;IACvE,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,OAAO,CAAC;IACd,sEAAsE;IACtE,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,SAAS,EAAE,cAAc,EAAE,CAAC;CAC7B;AAED;;;;GAIG;AACH,MAAM,WAAW,wBAAwB;IACvC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED;;;;GAIG;AACH,wBAAsB,mBAAmB,CACvC,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,eAAe,EACvB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,aAAa,EAAE,CAAA;CAAE,GAAG,IAAI,CAAC,CA8G3D;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAClC,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,eAAe,EACvB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,EAAE,EAAE,aAAa,CAAA;CAAE,GAAG,IAAI,CAAC,CAUnD;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAChC,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,eAAe,EACvB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC;IACT,IAAI,EAAE,IAAI,CAAC;IACX,EAAE,EAAE,aAAa,CAAC;IAClB,KAAK,EAAE,WAAW,CAAC;CACpB,GAAG,IAAI,CAAC,CAUR;AAED;;;;GAIG;AACH,wBAAsB,eAAe,CACnC,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,eAAe,EACvB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,EAAE,EAAE,aAAa,CAAA;CAAE,GAAG,IAAI,CAAC,CAMnD;AAwBD,wBAAsB,gBAAgB,CACpC,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,eAAe,EACvB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,wBAAwB,GAAG,IAAI,CAAC,CAW1C;AAED,wBAAsB,kBAAkB,CACtC,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,eAAe,EACvB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,wBAAwB,GAAG,IAAI,CAAC,CAW1C"}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure data loaders that hydrate OpenPlanr artifacts into the shapes the
|
|
3
|
+
* Linear push expects. No Linear API calls, no mutations — just filesystem
|
|
4
|
+
* reads + frontmatter parsing. Every scope-level push function routes
|
|
5
|
+
* through one of these loaders first.
|
|
6
|
+
*/
|
|
7
|
+
import { listArtifacts, readArtifact, readArtifactRaw } from '../artifact-service.js';
|
|
8
|
+
import { toOptionalString, toOptionalStringArray } from './body-formatters.js';
|
|
9
|
+
import { toOptionalStrategy } from './strategy-context.js';
|
|
10
|
+
function sortByArtifactId(a, b) {
|
|
11
|
+
return a.id.localeCompare(b.id, undefined, { numeric: true });
|
|
12
|
+
}
|
|
13
|
+
function asTaskStatus(s) {
|
|
14
|
+
if (s === 'pending' || s === 'in-progress' || s === 'done')
|
|
15
|
+
return s;
|
|
16
|
+
return 'pending';
|
|
17
|
+
}
|
|
18
|
+
function nowIso() {
|
|
19
|
+
return new Date().toISOString().split('T')[0];
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Load the full epic subtree (epic frontmatter + features + stories per
|
|
23
|
+
* feature + task-file ids per feature). Filters by `epicId` on each child
|
|
24
|
+
* artifact.
|
|
25
|
+
*/
|
|
26
|
+
export async function loadLinearPushScope(projectDir, config, epicId) {
|
|
27
|
+
const epicArt = await readArtifact(projectDir, config, 'epic', epicId);
|
|
28
|
+
if (!epicArt)
|
|
29
|
+
return null;
|
|
30
|
+
const d = epicArt.data;
|
|
31
|
+
const epic = {
|
|
32
|
+
id: d.id || epicId,
|
|
33
|
+
title: d.title || '',
|
|
34
|
+
createdAt: d.createdAt || d.created || nowIso(),
|
|
35
|
+
updatedAt: d.updatedAt || d.updated || nowIso(),
|
|
36
|
+
filePath: epicArt.filePath,
|
|
37
|
+
owner: d.owner || '',
|
|
38
|
+
businessValue: d.businessValue || '',
|
|
39
|
+
targetUsers: d.targetUsers || '',
|
|
40
|
+
problemStatement: d.problemStatement || '',
|
|
41
|
+
solutionOverview: d.solutionOverview || '',
|
|
42
|
+
successCriteria: d.successCriteria || '',
|
|
43
|
+
keyFeatures: d.keyFeatures || [],
|
|
44
|
+
dependencies: d.dependencies || '',
|
|
45
|
+
risks: d.risks || '',
|
|
46
|
+
featureIds: d.featureIds || [],
|
|
47
|
+
linearProjectId: toOptionalString(d.linearProjectId),
|
|
48
|
+
linearProjectIdentifier: toOptionalString(d.linearProjectIdentifier),
|
|
49
|
+
linearProjectUrl: toOptionalString(d.linearProjectUrl),
|
|
50
|
+
linearMappingStrategy: toOptionalStrategy(d.linearMappingStrategy),
|
|
51
|
+
linearMilestoneId: toOptionalString(d.linearMilestoneId),
|
|
52
|
+
linearLabelId: toOptionalString(d.linearLabelId),
|
|
53
|
+
};
|
|
54
|
+
const allFeatures = (await listArtifacts(projectDir, config, 'feature')).sort(sortByArtifactId);
|
|
55
|
+
const allStories = (await listArtifacts(projectDir, config, 'story')).sort(sortByArtifactId);
|
|
56
|
+
const allTasks = (await listArtifacts(projectDir, config, 'task')).sort(sortByArtifactId);
|
|
57
|
+
const featuresUnderEpic = [];
|
|
58
|
+
for (const f of allFeatures) {
|
|
59
|
+
const a = await readArtifact(projectDir, config, 'feature', f.id);
|
|
60
|
+
if (!a || a.data.epicId !== epicId)
|
|
61
|
+
continue;
|
|
62
|
+
const fd = a.data;
|
|
63
|
+
const feature = {
|
|
64
|
+
id: fd.id || f.id,
|
|
65
|
+
title: fd.title || f.title,
|
|
66
|
+
createdAt: fd.createdAt || fd.created || nowIso(),
|
|
67
|
+
updatedAt: fd.updatedAt || fd.updated || nowIso(),
|
|
68
|
+
filePath: a.filePath,
|
|
69
|
+
epicId: fd.epicId,
|
|
70
|
+
owner: fd.owner || '',
|
|
71
|
+
status: asTaskStatus(fd.status),
|
|
72
|
+
overview: fd.overview || '',
|
|
73
|
+
functionalRequirements: fd.functionalRequirements || [],
|
|
74
|
+
storyIds: fd.storyIds || [],
|
|
75
|
+
linearIssueId: toOptionalString(fd.linearIssueId),
|
|
76
|
+
linearIssueIdentifier: toOptionalString(fd.linearIssueIdentifier),
|
|
77
|
+
linearIssueUrl: toOptionalString(fd.linearIssueUrl),
|
|
78
|
+
linearProjectMilestoneId: toOptionalString(fd.linearProjectMilestoneId),
|
|
79
|
+
linearLabelIds: toOptionalStringArray(fd.linearLabelIds),
|
|
80
|
+
};
|
|
81
|
+
const stories = [];
|
|
82
|
+
for (const s of allStories) {
|
|
83
|
+
const st = await readArtifact(projectDir, config, 'story', s.id);
|
|
84
|
+
if (!st || st.data.featureId !== feature.id)
|
|
85
|
+
continue;
|
|
86
|
+
const sd = st.data;
|
|
87
|
+
const story = {
|
|
88
|
+
id: sd.id || s.id,
|
|
89
|
+
title: sd.title || s.title,
|
|
90
|
+
createdAt: sd.createdAt || sd.created || nowIso(),
|
|
91
|
+
updatedAt: sd.updatedAt || sd.updated || nowIso(),
|
|
92
|
+
filePath: st.filePath,
|
|
93
|
+
featureId: sd.featureId,
|
|
94
|
+
status: asTaskStatus(sd.status),
|
|
95
|
+
role: sd.role || '',
|
|
96
|
+
goal: sd.goal || '',
|
|
97
|
+
benefit: sd.benefit || '',
|
|
98
|
+
acceptanceCriteria: sd.acceptanceCriteria || '',
|
|
99
|
+
additionalNotes: toOptionalString(sd.additionalNotes),
|
|
100
|
+
linearIssueId: toOptionalString(sd.linearIssueId),
|
|
101
|
+
linearIssueIdentifier: toOptionalString(sd.linearIssueIdentifier),
|
|
102
|
+
linearIssueUrl: toOptionalString(sd.linearIssueUrl),
|
|
103
|
+
linearParentIssueId: toOptionalString(sd.linearParentIssueId),
|
|
104
|
+
linearProjectMilestoneId: toOptionalString(sd.linearProjectMilestoneId),
|
|
105
|
+
linearLabelIds: toOptionalStringArray(sd.linearLabelIds),
|
|
106
|
+
};
|
|
107
|
+
stories.push({
|
|
108
|
+
id: story.id,
|
|
109
|
+
title: story.title,
|
|
110
|
+
data: story,
|
|
111
|
+
frontmatter: sd,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
const taskFiles = [];
|
|
115
|
+
for (const t of allTasks) {
|
|
116
|
+
const ta = await readArtifact(projectDir, config, 'task', t.id);
|
|
117
|
+
const pfeat = toOptionalString(ta?.data.featureId);
|
|
118
|
+
if (pfeat === feature.id) {
|
|
119
|
+
taskFiles.push({ id: t.id, title: t.title });
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
featuresUnderEpic.push({
|
|
123
|
+
id: feature.id,
|
|
124
|
+
title: feature.title,
|
|
125
|
+
data: feature,
|
|
126
|
+
frontmatter: fd,
|
|
127
|
+
stories,
|
|
128
|
+
taskFiles,
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
return { epic, features: featuresUnderEpic };
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Parent-chain context needed to push a feature: the feature itself (with
|
|
135
|
+
* its stories and task files) plus its parent epic. Returns `null` if the
|
|
136
|
+
* feature can't be resolved or has no valid `epicId` pointer.
|
|
137
|
+
*/
|
|
138
|
+
export async function loadForFeature(projectDir, config, featureId) {
|
|
139
|
+
const featureArt = await readArtifact(projectDir, config, 'feature', featureId);
|
|
140
|
+
if (!featureArt)
|
|
141
|
+
return null;
|
|
142
|
+
const parentEpicId = toOptionalString(featureArt.data.epicId);
|
|
143
|
+
if (!parentEpicId)
|
|
144
|
+
return null;
|
|
145
|
+
const epicScope = await loadLinearPushScope(projectDir, config, parentEpicId);
|
|
146
|
+
if (!epicScope)
|
|
147
|
+
return null;
|
|
148
|
+
const sf = epicScope.features.find((f) => f.id === featureId);
|
|
149
|
+
if (!sf)
|
|
150
|
+
return null;
|
|
151
|
+
return { epic: epicScope.epic, sf };
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Parent-chain context needed to push a story: the story itself, its
|
|
155
|
+
* feature (with sibling stories + tasklists) and the containing epic.
|
|
156
|
+
* Returns `null` if any link in the chain is missing.
|
|
157
|
+
*/
|
|
158
|
+
export async function loadForStory(projectDir, config, storyId) {
|
|
159
|
+
const storyArt = await readArtifact(projectDir, config, 'story', storyId);
|
|
160
|
+
if (!storyArt)
|
|
161
|
+
return null;
|
|
162
|
+
const parentFeatureId = toOptionalString(storyArt.data.featureId);
|
|
163
|
+
if (!parentFeatureId)
|
|
164
|
+
return null;
|
|
165
|
+
const ctx = await loadForFeature(projectDir, config, parentFeatureId);
|
|
166
|
+
if (!ctx)
|
|
167
|
+
return null;
|
|
168
|
+
const story = ctx.sf.stories.find((s) => s.id === storyId);
|
|
169
|
+
if (!story)
|
|
170
|
+
return null;
|
|
171
|
+
return { epic: ctx.epic, sf: ctx.sf, story };
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Parent-chain context needed to push a task file: the containing feature
|
|
175
|
+
* (with all its task files merged into one Linear sub-issue body) and the
|
|
176
|
+
* epic.
|
|
177
|
+
*/
|
|
178
|
+
export async function loadForTaskFile(projectDir, config, taskId) {
|
|
179
|
+
const taskArt = await readArtifact(projectDir, config, 'task', taskId);
|
|
180
|
+
if (!taskArt)
|
|
181
|
+
return null;
|
|
182
|
+
const parentFeatureId = toOptionalString(taskArt.data.featureId);
|
|
183
|
+
if (!parentFeatureId)
|
|
184
|
+
return null;
|
|
185
|
+
return loadForFeature(projectDir, config, parentFeatureId);
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Frontmatter sanity check for standalone artifacts. Every pushable file
|
|
189
|
+
* MUST have at least a real `title` — otherwise we end up creating a
|
|
190
|
+
* Linear issue whose title is just the artifact id (e.g. "QT-015"), and
|
|
191
|
+
* then the subsequent `updateArtifactFields` write-back fails because the
|
|
192
|
+
* file's frontmatter block is malformed. Bail here, before any API call,
|
|
193
|
+
* so the Linear side stays clean.
|
|
194
|
+
*/
|
|
195
|
+
function requireFrontmatter(kind, id, filePath, data) {
|
|
196
|
+
const title = toOptionalString(data.title);
|
|
197
|
+
if (!title) {
|
|
198
|
+
throw new Error(`${kind} ${id} has no \`title\` field in its frontmatter.\n ${filePath}\n Fix the file's frontmatter (must be a \`---\`-delimited YAML block with at least \`id\` and \`title\`) and re-run. No changes were pushed to Linear.`);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
export async function loadForQuickTask(projectDir, config, qtId) {
|
|
202
|
+
const art = await readArtifact(projectDir, config, 'quick', qtId);
|
|
203
|
+
if (!art)
|
|
204
|
+
return null;
|
|
205
|
+
requireFrontmatter('Quick task', qtId, art.filePath, art.data);
|
|
206
|
+
const raw = (await readArtifactRaw(projectDir, config, 'quick', qtId)) ?? '';
|
|
207
|
+
return {
|
|
208
|
+
id: art.data.id || qtId,
|
|
209
|
+
title: art.data.title,
|
|
210
|
+
raw,
|
|
211
|
+
frontmatter: art.data,
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
export async function loadForBacklogItem(projectDir, config, blId) {
|
|
215
|
+
const art = await readArtifact(projectDir, config, 'backlog', blId);
|
|
216
|
+
if (!art)
|
|
217
|
+
return null;
|
|
218
|
+
requireFrontmatter('Backlog item', blId, art.filePath, art.data);
|
|
219
|
+
const raw = (await readArtifactRaw(projectDir, config, 'backlog', blId)) ?? '';
|
|
220
|
+
return {
|
|
221
|
+
id: art.data.id || blId,
|
|
222
|
+
title: art.data.title,
|
|
223
|
+
raw,
|
|
224
|
+
frontmatter: art.data,
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
//# sourceMappingURL=scope-loaders.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scope-loaders.js","sourceRoot":"","sources":["../../../src/services/linear/scope-loaders.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Epic-mapping strategy resolution + descendant-propagation context.
|
|
3
|
+
*
|
|
4
|
+
* `StrategyContext` is the read-only bundle that a single-scope push
|
|
5
|
+
* (feature / story / tasklist / QT / BL) needs to attach descendant issues
|
|
6
|
+
* into Linear correctly: `projectId` is always set, `milestoneId` / `labelId`
|
|
7
|
+
* are populated per the epic's strategy. The epic-scope push also builds a
|
|
8
|
+
* context on first push (interactive mapping prompt or `--as` flag) — that
|
|
9
|
+
* builder lives inside `pushEpicScope` because it performs Linear mutations.
|
|
10
|
+
*/
|
|
11
|
+
import type { LinearClient } from '@linear/sdk';
|
|
12
|
+
import type { Epic, LinearMappingStrategy, OpenPlanrConfig } from '../../models/types.js';
|
|
13
|
+
/**
|
|
14
|
+
* Type → Linear label name for auto-applied GitHub-style filters. Users
|
|
15
|
+
* can override names via `linear.typeLabels` in `.planr/config.json`.
|
|
16
|
+
*/
|
|
17
|
+
export type LinearLabeledArtifactType = 'feature' | 'story' | 'task' | 'quick' | 'backlog';
|
|
18
|
+
export declare function resolveTypeLabelName(config: OpenPlanrConfig, type: LinearLabeledArtifactType): string;
|
|
19
|
+
export interface StrategyContext {
|
|
20
|
+
strategy: LinearMappingStrategy;
|
|
21
|
+
/** Always set — the Linear project that contains the epic's descendants. */
|
|
22
|
+
projectId: string;
|
|
23
|
+
/** Set when strategy === 'milestone-of' — written to every descendant issue. */
|
|
24
|
+
milestoneId?: string;
|
|
25
|
+
/** Set when strategy === 'label-on' — merged into every descendant issue's labelIds. */
|
|
26
|
+
labelId?: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Validate a stored `linearMappingStrategy` frontmatter value at the type
|
|
30
|
+
* boundary. Returns `undefined` for anything that isn't one of the three
|
|
31
|
+
* known strategies — the caller falls back to `'project'` in that case.
|
|
32
|
+
*/
|
|
33
|
+
export declare function toOptionalStrategy(v: unknown): LinearMappingStrategy | undefined;
|
|
34
|
+
/** Resolve the epic-mapping strategy for an already-pushed epic (read-only). */
|
|
35
|
+
export declare function strategyFromEpic(epic: Epic, config: OpenPlanrConfig): LinearMappingStrategy;
|
|
36
|
+
/**
|
|
37
|
+
* Build the descendant-propagation context for a feature/story/tasklist push
|
|
38
|
+
* **without** invoking any Linear mutation. Used by granular push scopes
|
|
39
|
+
* (FEAT/US/TASK/QT/BL) where the epic is already mapped — the strategy is
|
|
40
|
+
* whatever the epic's frontmatter says it is, and the containing projectId
|
|
41
|
+
* + milestoneId + labelId are read-only from that frontmatter.
|
|
42
|
+
*/
|
|
43
|
+
export declare function contextFromMappedEpic(epic: Epic, config: OpenPlanrConfig): StrategyContext;
|
|
44
|
+
/**
|
|
45
|
+
* Read an issue's existing labelIds from Linear so we can merge (not stomp)
|
|
46
|
+
* when the push re-applies the epic's label. Only called in the `label-on`
|
|
47
|
+
* branch, so the extra round-trip is isolated to that strategy.
|
|
48
|
+
*/
|
|
49
|
+
export declare function readExistingLabelIds(client: LinearClient, issueId: string): Promise<string[]>;
|
|
50
|
+
/** Dedupe helper — merges `extra` into `base`, preserving order. */
|
|
51
|
+
export declare function mergeLabelIds(base: string[], extra: string | undefined): string[];
|
|
52
|
+
/**
|
|
53
|
+
* Idempotent team label for a given OpenPlanr artifact type. Ensures the
|
|
54
|
+
* label exists in Linear (creates or reuses by name), caches the result
|
|
55
|
+
* per-push so cascades don't call the API once per item. Used by every
|
|
56
|
+
* push worker to tag issues with a GitHub-style `feature` / `story` /
|
|
57
|
+
* `task` / `quick-task` / `backlog` label.
|
|
58
|
+
*/
|
|
59
|
+
export declare function ensureTypeLabel(client: LinearClient, teamId: string, config: OpenPlanrConfig, type: LinearLabeledArtifactType): Promise<string>;
|
|
60
|
+
/**
|
|
61
|
+
* In-process cache keyed by artifact type. Avoids round-tripping
|
|
62
|
+
* `ensureIssueLabel` once per item in a cascade (`pushEpicScope` with many
|
|
63
|
+
* features / stories / tasks / QTs / BLs hits Linear once per type).
|
|
64
|
+
*/
|
|
65
|
+
export declare function createTypeLabelCache(client: LinearClient, teamId: string, config: OpenPlanrConfig): (type: LinearLabeledArtifactType) => Promise<string>;
|
|
66
|
+
//# sourceMappingURL=strategy-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"strategy-context.d.ts","sourceRoot":"","sources":["../../../src/services/linear/strategy-context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EAAE,IAAI,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAI1F;;;GAGG;AACH,MAAM,MAAM,yBAAyB,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;AA0B3F,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,eAAe,EACvB,IAAI,EAAE,yBAAyB,GAC9B,MAAM,CAER;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,qBAAqB,CAAC;IAChC,4EAA4E;IAC5E,SAAS,EAAE,MAAM,CAAC;IAClB,gFAAgF;IAChF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wFAAwF;IACxF,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,OAAO,GAAG,qBAAqB,GAAG,SAAS,CAGhF;AAED,gFAAgF;AAChF,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,eAAe,GAAG,qBAAqB,CAE3F;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,eAAe,GAAG,eAAe,CAS1F;AAED;;;;GAIG;AACH,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,EAAE,CAAC,CAMnB;AAED,oEAAoE;AACpE,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,EAAE,CAIjF;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,eAAe,EACvB,IAAI,EAAE,yBAAyB,GAC9B,OAAO,CAAC,MAAM,CAAC,CASjB;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,eAAe,GACtB,CAAC,IAAI,EAAE,yBAAyB,KAAK,OAAO,CAAC,MAAM,CAAC,CAStD"}
|