openplanr 1.2.8 → 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 +7 -3
- 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/system-prompts.d.ts +2 -2
- package/dist/ai/prompts/system-prompts.d.ts.map +1 -1
- package/dist/ai/prompts/system-prompts.js +7 -7
- package/dist/ai/schemas/ai-response-schemas.js +1 -1
- package/dist/ai/schemas/ai-response-schemas.js.map +1 -1
- package/dist/ai/types.d.ts.map +1 -1
- package/dist/ai/types.js +2 -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 +9 -8
- package/dist/cli/commands/revise.d.ts.map +1 -1
- package/dist/cli/commands/revise.js +93 -25
- package/dist/cli/commands/revise.js.map +1 -1
- package/dist/cli/index.js +2 -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 +179 -3
- 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 +2 -2
- package/dist/services/atomic-write-service.js +2 -2
- package/dist/services/audit-log-service.d.ts +3 -6
- package/dist/services/audit-log-service.d.ts.map +1 -1
- package/dist/services/audit-log-service.js +4 -7
- package/dist/services/audit-log-service.js.map +1 -1
- package/dist/services/cascade-service.d.ts +2 -2
- package/dist/services/cascade-service.js +3 -3
- package/dist/services/cascade-service.js.map +1 -1
- package/dist/services/credentials-service.js +2 -2
- package/dist/services/credentials-service.js.map +1 -1
- package/dist/services/diff-service.d.ts +1 -1
- package/dist/services/diff-service.js +1 -1
- package/dist/services/evidence-verifier.d.ts +1 -1
- package/dist/services/evidence-verifier.d.ts.map +1 -1
- package/dist/services/evidence-verifier.js +5 -2
- package/dist/services/evidence-verifier.js.map +1 -1
- package/dist/services/git-service.d.ts +4 -4
- package/dist/services/git-service.js +4 -4
- package/dist/services/graph-integrity.d.ts +2 -3
- package/dist/services/graph-integrity.d.ts.map +1 -1
- package/dist/services/graph-integrity.js +2 -3
- package/dist/services/graph-integrity.js.map +1 -1
- 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 +19 -0
- package/dist/services/prompt-service.d.ts.map +1 -1
- package/dist/services/prompt-service.js +64 -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 +1 -1
- package/dist/services/revise-cache-service.js +1 -1
- 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 +18 -11
- package/dist/services/revise-service.d.ts.map +1 -1
- package/dist/services/revise-service.js +57 -12
- package/dist/services/revise-service.js.map +1 -1
- package/dist/services/template-sections.d.ts +1 -1
- package/dist/services/template-sections.js +1 -1
- 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 +22 -1
- package/dist/utils/diff.d.ts.map +1 -1
- package/dist/utils/diff.js +136 -1
- package/dist/utils/diff.js.map +1 -1
- 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,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"}
|
|
@@ -0,0 +1,121 @@
|
|
|
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 { ensureIssueLabel } from '../linear-service.js';
|
|
12
|
+
import { withLinearRetry } from './errors.js';
|
|
13
|
+
const DEFAULT_TYPE_LABEL_NAMES = {
|
|
14
|
+
feature: 'feature',
|
|
15
|
+
story: 'story',
|
|
16
|
+
task: 'task',
|
|
17
|
+
quick: 'quick-task',
|
|
18
|
+
backlog: 'backlog',
|
|
19
|
+
};
|
|
20
|
+
const TYPE_LABEL_COLORS = {
|
|
21
|
+
feature: '#5E6AD2', // Linear's indigo
|
|
22
|
+
story: '#4CB782', // green
|
|
23
|
+
task: '#F2994A', // orange
|
|
24
|
+
quick: '#BB87FC', // purple
|
|
25
|
+
backlog: '#888888', // grey (unchanged — matches pre-refactor default)
|
|
26
|
+
};
|
|
27
|
+
const TYPE_LABEL_DESCRIPTIONS = {
|
|
28
|
+
feature: 'OpenPlanr features (auto-applied by `planr linear push FEAT-*`).',
|
|
29
|
+
story: 'OpenPlanr user stories (auto-applied by `planr linear push US-*`).',
|
|
30
|
+
task: 'OpenPlanr task lists (auto-applied by `planr linear push TASK-*`).',
|
|
31
|
+
quick: 'OpenPlanr quick tasks (auto-applied by `planr linear push QT-*`).',
|
|
32
|
+
backlog: 'OpenPlanr backlog items (auto-applied by `planr linear push BL-*`).',
|
|
33
|
+
};
|
|
34
|
+
export function resolveTypeLabelName(config, type) {
|
|
35
|
+
return config.linear?.typeLabels?.[type] ?? DEFAULT_TYPE_LABEL_NAMES[type];
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Validate a stored `linearMappingStrategy` frontmatter value at the type
|
|
39
|
+
* boundary. Returns `undefined` for anything that isn't one of the three
|
|
40
|
+
* known strategies — the caller falls back to `'project'` in that case.
|
|
41
|
+
*/
|
|
42
|
+
export function toOptionalStrategy(v) {
|
|
43
|
+
if (v === 'project' || v === 'milestone-of' || v === 'label-on')
|
|
44
|
+
return v;
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
/** Resolve the epic-mapping strategy for an already-pushed epic (read-only). */
|
|
48
|
+
export function strategyFromEpic(epic, config) {
|
|
49
|
+
return epic.linearMappingStrategy ?? config.linear?.defaultEpicStrategy ?? 'project';
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Build the descendant-propagation context for a feature/story/tasklist push
|
|
53
|
+
* **without** invoking any Linear mutation. Used by granular push scopes
|
|
54
|
+
* (FEAT/US/TASK/QT/BL) where the epic is already mapped — the strategy is
|
|
55
|
+
* whatever the epic's frontmatter says it is, and the containing projectId
|
|
56
|
+
* + milestoneId + labelId are read-only from that frontmatter.
|
|
57
|
+
*/
|
|
58
|
+
export function contextFromMappedEpic(epic, config) {
|
|
59
|
+
const strategy = strategyFromEpic(epic, config);
|
|
60
|
+
const projectId = epic.linearProjectId ?? '';
|
|
61
|
+
return {
|
|
62
|
+
strategy,
|
|
63
|
+
projectId,
|
|
64
|
+
milestoneId: strategy === 'milestone-of' ? epic.linearMilestoneId : undefined,
|
|
65
|
+
labelId: strategy === 'label-on' ? epic.linearLabelId : undefined,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Read an issue's existing labelIds from Linear so we can merge (not stomp)
|
|
70
|
+
* when the push re-applies the epic's label. Only called in the `label-on`
|
|
71
|
+
* branch, so the extra round-trip is isolated to that strategy.
|
|
72
|
+
*/
|
|
73
|
+
export async function readExistingLabelIds(client, issueId) {
|
|
74
|
+
return withLinearRetry('read label ids', async () => {
|
|
75
|
+
const issue = await client.issue(issueId);
|
|
76
|
+
const ids = issue?.labelIds;
|
|
77
|
+
return Array.isArray(ids) ? ids : [];
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
/** Dedupe helper — merges `extra` into `base`, preserving order. */
|
|
81
|
+
export function mergeLabelIds(base, extra) {
|
|
82
|
+
if (!extra)
|
|
83
|
+
return [...base];
|
|
84
|
+
if (base.includes(extra))
|
|
85
|
+
return [...base];
|
|
86
|
+
return [...base, extra];
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Idempotent team label for a given OpenPlanr artifact type. Ensures the
|
|
90
|
+
* label exists in Linear (creates or reuses by name), caches the result
|
|
91
|
+
* per-push so cascades don't call the API once per item. Used by every
|
|
92
|
+
* push worker to tag issues with a GitHub-style `feature` / `story` /
|
|
93
|
+
* `task` / `quick-task` / `backlog` label.
|
|
94
|
+
*/
|
|
95
|
+
export async function ensureTypeLabel(client, teamId, config, type) {
|
|
96
|
+
const name = resolveTypeLabelName(config, type);
|
|
97
|
+
const label = await ensureIssueLabel(client, {
|
|
98
|
+
teamId,
|
|
99
|
+
name,
|
|
100
|
+
color: TYPE_LABEL_COLORS[type],
|
|
101
|
+
description: TYPE_LABEL_DESCRIPTIONS[type],
|
|
102
|
+
});
|
|
103
|
+
return label.id;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* In-process cache keyed by artifact type. Avoids round-tripping
|
|
107
|
+
* `ensureIssueLabel` once per item in a cascade (`pushEpicScope` with many
|
|
108
|
+
* features / stories / tasks / QTs / BLs hits Linear once per type).
|
|
109
|
+
*/
|
|
110
|
+
export function createTypeLabelCache(client, teamId, config) {
|
|
111
|
+
const cache = new Map();
|
|
112
|
+
return (type) => {
|
|
113
|
+
const hit = cache.get(type);
|
|
114
|
+
if (hit)
|
|
115
|
+
return hit;
|
|
116
|
+
const promise = ensureTypeLabel(client, teamId, config, type);
|
|
117
|
+
cache.set(type, promise);
|
|
118
|
+
return promise;
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=strategy-context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"strategy-context.js","sourceRoot":"","sources":["../../../src/services/linear/strategy-context.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local-only Linear ↔ OpenPlanr mapping table for `planr linear status`.
|
|
3
|
+
*/
|
|
4
|
+
import type { LinearMappingTableRow, OpenPlanrConfig } from '../models/types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Collect mapping rows from local frontmatter only (no Linear API).
|
|
7
|
+
* With `scopeEpicId`, only that epic and descendants (features, stories, tasks in cascade + tasks with `featureId` in scope).
|
|
8
|
+
*/
|
|
9
|
+
export declare function collectLinearMappingTable(projectDir: string, config: OpenPlanrConfig, scopeEpicId?: string): Promise<LinearMappingTableRow[]>;
|
|
10
|
+
export declare function formatLinearMappingTable(rows: LinearMappingTableRow[]): string;
|
|
11
|
+
//# sourceMappingURL=linear-mapping-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"linear-mapping-service.d.ts","sourceRoot":"","sources":["../../src/services/linear-mapping-service.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AA4GjF;;;GAGG;AACH,wBAAsB,yBAAyB,CAC7C,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,eAAe,EACvB,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAqHlC;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,qBAAqB,EAAE,GAAG,MAAM,CAwB9E"}
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local-only Linear ↔ OpenPlanr mapping table for `planr linear status`.
|
|
3
|
+
*/
|
|
4
|
+
import { listArtifacts, readArtifact } from './artifact-service.js';
|
|
5
|
+
import { buildCascadeOrder } from './cascade-service.js';
|
|
6
|
+
import { isLikelyLinearIssueId } from './linear-service.js';
|
|
7
|
+
/**
|
|
8
|
+
* Flag frontmatter values that don't parse as a plausible Linear issue id —
|
|
9
|
+
* typos like `ENG42` (no hyphen), truncations, or values copied from other
|
|
10
|
+
* tools. Linear issue ids accept two legitimate shapes: UUID v4 (canonical
|
|
11
|
+
* API form) and `ENG-42` identifier form; both return `undefined` here.
|
|
12
|
+
* Anything else gets flagged so the status table highlights it clearly.
|
|
13
|
+
*
|
|
14
|
+
* Note: earlier versions also flagged UUID-shaped values as "looks like a
|
|
15
|
+
* workflow state id" — removed in Gap D because every pushed Linear issue id
|
|
16
|
+
* is a UUID, so that check fired on healthy data.
|
|
17
|
+
*/
|
|
18
|
+
function staleNoteForIssueId(raw) {
|
|
19
|
+
if (!raw?.trim()) {
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
if (!isLikelyLinearIssueId(raw)) {
|
|
23
|
+
return 'stale-id (value does not look like a Linear issue id; re-run `planr linear push`)';
|
|
24
|
+
}
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
27
|
+
function cell(s, max = 48) {
|
|
28
|
+
const t = s.trim() || '—';
|
|
29
|
+
return t.length <= max ? t : `${t.slice(0, max - 1)}…`;
|
|
30
|
+
}
|
|
31
|
+
function toStr(v) {
|
|
32
|
+
if (typeof v !== 'string')
|
|
33
|
+
return undefined;
|
|
34
|
+
const t = v.trim();
|
|
35
|
+
return t.length > 0 ? t : undefined;
|
|
36
|
+
}
|
|
37
|
+
function rowForEpic(openPlanrId, d) {
|
|
38
|
+
const pid = toStr(d.linearProjectId);
|
|
39
|
+
if (!pid) {
|
|
40
|
+
return {
|
|
41
|
+
kind: 'epic',
|
|
42
|
+
openPlanrId,
|
|
43
|
+
linearIdentifier: '(not pushed)',
|
|
44
|
+
linearUrl: '—',
|
|
45
|
+
lastKnownState: '—',
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
const strategy = toStr(d.linearMappingStrategy) ?? 'project';
|
|
49
|
+
const url = toStr(d.linearProjectUrl) ?? '—';
|
|
50
|
+
let identifier;
|
|
51
|
+
if (strategy === 'milestone-of') {
|
|
52
|
+
const mid = toStr(d.linearMilestoneId);
|
|
53
|
+
identifier = mid ? `milestone:${mid.slice(0, 8)}` : 'milestone:(pending)';
|
|
54
|
+
}
|
|
55
|
+
else if (strategy === 'label-on') {
|
|
56
|
+
const lid = toStr(d.linearLabelId);
|
|
57
|
+
identifier = lid ? `label:${lid.slice(0, 8)}` : 'label:(pending)';
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
identifier = toStr(d.linearProjectIdentifier) ?? `project:${pid.slice(0, 8)}`;
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
kind: 'epic',
|
|
64
|
+
openPlanrId,
|
|
65
|
+
linearIdentifier: identifier,
|
|
66
|
+
linearUrl: url,
|
|
67
|
+
lastKnownState: '—',
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Generic row builder for issue-shaped artifacts (feature / story / task /
|
|
72
|
+
* quick / backlog). All five have the same frontmatter fields
|
|
73
|
+
* (`linearIssueId`, `linearIssueIdentifier`, `linearIssueUrl`) so a single
|
|
74
|
+
* implementation handles them — only the `kind` label differs.
|
|
75
|
+
*/
|
|
76
|
+
function rowForIssueArtifact(kind, openPlanrId, d) {
|
|
77
|
+
const issueId = toStr(d.linearIssueId);
|
|
78
|
+
const stale = staleNoteForIssueId(issueId);
|
|
79
|
+
const usable = Boolean(issueId && !stale);
|
|
80
|
+
return {
|
|
81
|
+
kind,
|
|
82
|
+
openPlanrId,
|
|
83
|
+
linearIdentifier: usable
|
|
84
|
+
? (toStr(d.linearIssueIdentifier) ?? issueId.slice(0, 8))
|
|
85
|
+
: issueId
|
|
86
|
+
? issueId.slice(0, 8)
|
|
87
|
+
: '(not pushed)',
|
|
88
|
+
linearUrl: usable ? (toStr(d.linearIssueUrl) ?? '—') : '—',
|
|
89
|
+
lastKnownState: String(d.status ?? '—'),
|
|
90
|
+
note: stale,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
async function pushTaskRow(projectDir, config, rows, taskId) {
|
|
94
|
+
const a = await readArtifact(projectDir, config, 'task', taskId);
|
|
95
|
+
if (!a)
|
|
96
|
+
return;
|
|
97
|
+
rows.push(rowForIssueArtifact('task', taskId, a.data));
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Collect mapping rows from local frontmatter only (no Linear API).
|
|
101
|
+
* With `scopeEpicId`, only that epic and descendants (features, stories, tasks in cascade + tasks with `featureId` in scope).
|
|
102
|
+
*/
|
|
103
|
+
export async function collectLinearMappingTable(projectDir, config, scopeEpicId) {
|
|
104
|
+
const rows = [];
|
|
105
|
+
if (scopeEpicId) {
|
|
106
|
+
const plan = await buildCascadeOrder(projectDir, config, 'epic', scopeEpicId);
|
|
107
|
+
const featureIdsInScope = new Set(plan.levels[1]?.artifactIds ?? []);
|
|
108
|
+
const storyIdsInScope = new Set(plan.levels[2]?.artifactIds ?? []);
|
|
109
|
+
const taskIdsCascade = new Set(plan.levels[3]?.artifactIds ?? []);
|
|
110
|
+
const ep = await readArtifact(projectDir, config, 'epic', scopeEpicId);
|
|
111
|
+
if (ep) {
|
|
112
|
+
rows.push(rowForEpic(scopeEpicId, ep.data));
|
|
113
|
+
}
|
|
114
|
+
for (const fid of [...featureIdsInScope].sort((a, b) => a.localeCompare(b, undefined, { numeric: true }))) {
|
|
115
|
+
const a = await readArtifact(projectDir, config, 'feature', fid);
|
|
116
|
+
if (a) {
|
|
117
|
+
rows.push(rowForIssueArtifact('feature', fid, a.data));
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
for (const sid of [...storyIdsInScope].sort((a, b) => a.localeCompare(b, undefined, { numeric: true }))) {
|
|
121
|
+
const a = await readArtifact(projectDir, config, 'story', sid);
|
|
122
|
+
if (a) {
|
|
123
|
+
rows.push(rowForIssueArtifact('story', sid, a.data));
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
for (const tid of [...taskIdsCascade].sort((a, b) => a.localeCompare(b, undefined, { numeric: true }))) {
|
|
127
|
+
await pushTaskRow(projectDir, config, rows, tid);
|
|
128
|
+
}
|
|
129
|
+
const allTasks = await listArtifacts(projectDir, config, 'task');
|
|
130
|
+
for (const t of allTasks.sort((a, b) => a.id.localeCompare(b.id, undefined, { numeric: true }))) {
|
|
131
|
+
if (taskIdsCascade.has(t.id))
|
|
132
|
+
continue;
|
|
133
|
+
const ta = await readArtifact(projectDir, config, 'task', t.id);
|
|
134
|
+
const feat = ta?.data.featureId;
|
|
135
|
+
if (feat && featureIdsInScope.has(feat)) {
|
|
136
|
+
await pushTaskRow(projectDir, config, rows, t.id);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
// Linked QT / BL artifacts (`epicId` or `parentEpic` pointing at this epic).
|
|
140
|
+
const quicks = await listArtifacts(projectDir, config, 'quick');
|
|
141
|
+
for (const q of quicks.sort((a, b) => a.id.localeCompare(b.id, undefined, { numeric: true }))) {
|
|
142
|
+
const a = await readArtifact(projectDir, config, 'quick', q.id);
|
|
143
|
+
if (!a)
|
|
144
|
+
continue;
|
|
145
|
+
const linked = toStr(a.data.epicId) ?? toStr(a.data.parentEpic);
|
|
146
|
+
if (linked === scopeEpicId) {
|
|
147
|
+
rows.push(rowForIssueArtifact('quick', q.id, a.data));
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
const backlogs = await listArtifacts(projectDir, config, 'backlog');
|
|
151
|
+
for (const b of backlogs.sort((a, b) => a.id.localeCompare(b.id, undefined, { numeric: true }))) {
|
|
152
|
+
const a = await readArtifact(projectDir, config, 'backlog', b.id);
|
|
153
|
+
if (!a)
|
|
154
|
+
continue;
|
|
155
|
+
const linked = toStr(a.data.epicId) ?? toStr(a.data.parentEpic);
|
|
156
|
+
if (linked === scopeEpicId) {
|
|
157
|
+
rows.push(rowForIssueArtifact('backlog', b.id, a.data));
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return rows;
|
|
161
|
+
}
|
|
162
|
+
const epics = await listArtifacts(projectDir, config, 'epic');
|
|
163
|
+
for (const e of epics.sort((a, b) => a.id.localeCompare(b.id, undefined, { numeric: true }))) {
|
|
164
|
+
const a = await readArtifact(projectDir, config, 'epic', e.id);
|
|
165
|
+
if (a) {
|
|
166
|
+
rows.push(rowForEpic(e.id, a.data));
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
const features = await listArtifacts(projectDir, config, 'feature');
|
|
170
|
+
for (const f of features.sort((a, b) => a.id.localeCompare(b.id, undefined, { numeric: true }))) {
|
|
171
|
+
const a = await readArtifact(projectDir, config, 'feature', f.id);
|
|
172
|
+
if (a) {
|
|
173
|
+
rows.push(rowForIssueArtifact('feature', f.id, a.data));
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
const stories = await listArtifacts(projectDir, config, 'story');
|
|
177
|
+
for (const s of stories.sort((a, b) => a.id.localeCompare(b.id, undefined, { numeric: true }))) {
|
|
178
|
+
const a = await readArtifact(projectDir, config, 'story', s.id);
|
|
179
|
+
if (a) {
|
|
180
|
+
rows.push(rowForIssueArtifact('story', s.id, a.data));
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
const tasks = await listArtifacts(projectDir, config, 'task');
|
|
184
|
+
for (const t of tasks.sort((a, b) => a.id.localeCompare(b.id, undefined, { numeric: true }))) {
|
|
185
|
+
await pushTaskRow(projectDir, config, rows, t.id);
|
|
186
|
+
}
|
|
187
|
+
const quicks = await listArtifacts(projectDir, config, 'quick');
|
|
188
|
+
for (const q of quicks.sort((a, b) => a.id.localeCompare(b.id, undefined, { numeric: true }))) {
|
|
189
|
+
const a = await readArtifact(projectDir, config, 'quick', q.id);
|
|
190
|
+
if (a)
|
|
191
|
+
rows.push(rowForIssueArtifact('quick', q.id, a.data));
|
|
192
|
+
}
|
|
193
|
+
const backlogs = await listArtifacts(projectDir, config, 'backlog');
|
|
194
|
+
for (const b of backlogs.sort((a, b) => a.id.localeCompare(b.id, undefined, { numeric: true }))) {
|
|
195
|
+
const a = await readArtifact(projectDir, config, 'backlog', b.id);
|
|
196
|
+
if (a)
|
|
197
|
+
rows.push(rowForIssueArtifact('backlog', b.id, a.data));
|
|
198
|
+
}
|
|
199
|
+
return rows;
|
|
200
|
+
}
|
|
201
|
+
export function formatLinearMappingTable(rows) {
|
|
202
|
+
const lines = [];
|
|
203
|
+
const kindW = 7;
|
|
204
|
+
const idW = 14;
|
|
205
|
+
const idenW = 22;
|
|
206
|
+
const stW = 14;
|
|
207
|
+
const noteW = 40;
|
|
208
|
+
// URL goes LAST and is printed in full (no truncation). Clickable URLs are
|
|
209
|
+
// the primary value of this table; truncating them to a fixed width made
|
|
210
|
+
// them useless for copy-paste. Rows with long URLs now trail off freely
|
|
211
|
+
// without disturbing earlier columns.
|
|
212
|
+
lines.push(`${'Kind'.padEnd(kindW)} ${'OpenPlanr id'.padEnd(idW)} ${'Linear id'.padEnd(idenW)} ${'State'.padEnd(stW)} ${'Note'.padEnd(noteW)} URL`);
|
|
213
|
+
lines.push(`${'─'.repeat(kindW)} ${'─'.repeat(idW)} ${'─'.repeat(idenW)} ${'─'.repeat(stW)} ${'─'.repeat(noteW)} ───`);
|
|
214
|
+
for (const r of rows) {
|
|
215
|
+
const note = r.note ? cell(r.note, noteW) : '';
|
|
216
|
+
lines.push(`${r.kind.padEnd(kindW)} ${r.openPlanrId.padEnd(idW)} ${cell(r.linearIdentifier, idenW).padEnd(idenW)} ${cell(r.lastKnownState, stW).padEnd(stW)} ${note.padEnd(noteW)} ${r.linearUrl}`);
|
|
217
|
+
}
|
|
218
|
+
return lines.join('\n');
|
|
219
|
+
}
|
|
220
|
+
//# sourceMappingURL=linear-mapping-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"linear-mapping-service.js","sourceRoot":"","sources":["../../src/services/linear-mapping-service.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACpE,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAE5D;;;;;;;;;;GAUG;AACH,SAAS,mBAAmB,CAAC,GAAuB;IAClD,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC;QACjB,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,EAAE,CAAC;QAChC,OAAO,mFAAmF,CAAC;IAC7F,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,IAAI,CAAC,CAAS,EAAE,GAAG,GAAG,EAAE;IAC/B,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,IAAI,GAAG,CAAC;IAC1B,OAAO,CAAC,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC;AACzD,CAAC;AAED,SAAS,KAAK,CAAC,CAAU;IACvB,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IAC5C,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IACnB,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AACtC,CAAC;AAED,SAAS,UAAU,CAAC,WAAmB,EAAE,CAA0B;IACjE,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC;IACrC,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,OAAO;YACL,IAAI,EAAE,MAAM;YACZ,WAAW;YACX,gBAAgB,EAAE,cAAc;YAChC,SAAS,EAAE,GAAG;YACd,cAAc,EAAE,GAAG;SACpB,CAAC;IACJ,CAAC;IACD,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,qBAAqB,CAAC,IAAI,SAAS,CAAC;IAC7D,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,gBAAgB,CAAC,IAAI,GAAG,CAAC;IAC7C,IAAI,UAAkB,CAAC;IACvB,IAAI,QAAQ,KAAK,cAAc,EAAE,CAAC;QAChC,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC;QACvC,UAAU,GAAG,GAAG,CAAC,CAAC,CAAC,aAAa,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,qBAAqB,CAAC;IAC5E,CAAC;SAAM,IAAI,QAAQ,KAAK,UAAU,EAAE,CAAC;QACnC,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC;QACnC,UAAU,GAAG,GAAG,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,iBAAiB,CAAC;IACpE,CAAC;SAAM,CAAC;QACN,UAAU,GAAG,KAAK,CAAC,CAAC,CAAC,uBAAuB,CAAC,IAAI,WAAW,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;IAChF,CAAC;IACD,OAAO;QACL,IAAI,EAAE,MAAM;QACZ,WAAW;QACX,gBAAgB,EAAE,UAAU;QAC5B,SAAS,EAAE,GAAG;QACd,cAAc,EAAE,GAAG;KACpB,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,SAAS,mBAAmB,CAC1B,IAAwD,EACxD,WAAmB,EACnB,CAA0B;IAE1B,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC;IACvC,MAAM,KAAK,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAC;IAC3C,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC;IAC1C,OAAO;QACL,IAAI;QACJ,WAAW;QACX,gBAAgB,EAAE,MAAM;YACtB,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,qBAAqB,CAAC,IAAK,OAAkB,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YACrE,CAAC,CAAC,OAAO;gBACP,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;gBACrB,CAAC,CAAC,cAAc;QACpB,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,cAAc,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG;QAC1D,cAAc,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,IAAI,GAAG,CAAC;QACvC,IAAI,EAAE,KAAK;KACZ,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,WAAW,CACxB,UAAkB,EAClB,MAAuB,EACvB,IAA6B,EAC7B,MAAc;IAEd,MAAM,CAAC,GAAG,MAAM,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACjE,IAAI,CAAC,CAAC;QAAE,OAAO;IACf,IAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,IAA+B,CAAC,CAAC,CAAC;AACpF,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC7C,UAAkB,EAClB,MAAuB,EACvB,WAAoB;IAEpB,MAAM,IAAI,GAA4B,EAAE,CAAC;IAEzC,IAAI,WAAW,EAAE,CAAC;QAChB,MAAM,IAAI,GAAG,MAAM,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC;QAC9E,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,WAAW,IAAI,EAAE,CAAC,CAAC;QACrE,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,WAAW,IAAI,EAAE,CAAC,CAAC;QACnE,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,WAAW,IAAI,EAAE,CAAC,CAAC;QAElE,MAAM,EAAE,GAAG,MAAM,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC;QACvE,IAAI,EAAE,EAAE,CAAC;YACP,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,EAAE,CAAC,IAA+B,CAAC,CAAC,CAAC;QACzE,CAAC;QAED,KAAK,MAAM,GAAG,IAAI,CAAC,GAAG,iBAAiB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACrD,CAAC,CAAC,aAAa,CAAC,CAAC,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CACjD,EAAE,CAAC;YACF,MAAM,CAAC,GAAG,MAAM,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC;YACjE,IAAI,CAAC,EAAE,CAAC;gBACN,IAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC,IAA+B,CAAC,CAAC,CAAC;YACpF,CAAC;QACH,CAAC;QAED,KAAK,MAAM,GAAG,IAAI,CAAC,GAAG,eAAe,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACnD,CAAC,CAAC,aAAa,CAAC,CAAC,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CACjD,EAAE,CAAC;YACF,MAAM,CAAC,GAAG,MAAM,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;YAC/D,IAAI,CAAC,EAAE,CAAC;gBACN,IAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,IAA+B,CAAC,CAAC,CAAC;YAClF,CAAC;QACH,CAAC;QAED,KAAK,MAAM,GAAG,IAAI,CAAC,GAAG,cAAc,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAClD,CAAC,CAAC,aAAa,CAAC,CAAC,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CACjD,EAAE,CAAC;YACF,MAAM,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;QACnD,CAAC;QAED,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;QACjE,KAAK,MAAM,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACrC,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CACvD,EAAE,CAAC;YACF,IAAI,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;gBAAE,SAAS;YACvC,MAAM,EAAE,GAAG,MAAM,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;YAChE,MAAM,IAAI,GAAG,EAAE,EAAE,IAAI,CAAC,SAA+B,CAAC;YACtD,IAAI,IAAI,IAAI,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBACxC,MAAM,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;YACpD,CAAC;QACH,CAAC;QAED,6EAA6E;QAC7E,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;QAChE,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;YAC9F,MAAM,CAAC,GAAG,MAAM,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;YAChE,IAAI,CAAC,CAAC;gBAAE,SAAS;YACjB,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAChE,IAAI,MAAM,KAAK,WAAW,EAAE,CAAC;gBAC3B,IAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAA+B,CAAC,CAAC,CAAC;YACnF,CAAC;QACH,CAAC;QACD,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC;QACpE,KAAK,MAAM,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACrC,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CACvD,EAAE,CAAC;YACF,MAAM,CAAC,GAAG,MAAM,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;YAClE,IAAI,CAAC,CAAC;gBAAE,SAAS;YACjB,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAChE,IAAI,MAAM,KAAK,WAAW,EAAE,CAAC;gBAC3B,IAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAA+B,CAAC,CAAC,CAAC;YACrF,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9D,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;QAC7F,MAAM,CAAC,GAAG,MAAM,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;QAC/D,IAAI,CAAC,EAAE,CAAC;YACN,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAA+B,CAAC,CAAC,CAAC;QACjE,CAAC;IACH,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC;IACpE,KAAK,MAAM,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;QAChG,MAAM,CAAC,GAAG,MAAM,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;QAClE,IAAI,CAAC,EAAE,CAAC;YACN,IAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAA+B,CAAC,CAAC,CAAC;QACrF,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IACjE,KAAK,MAAM,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;QAC/F,MAAM,CAAC,GAAG,MAAM,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;QAChE,IAAI,CAAC,EAAE,CAAC;YACN,IAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAA+B,CAAC,CAAC,CAAC;QACnF,CAAC;IACH,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9D,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;QAC7F,MAAM,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;IACpD,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IAChE,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;QAC9F,MAAM,CAAC,GAAG,MAAM,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;QAChE,IAAI,CAAC;YAAE,IAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAA+B,CAAC,CAAC,CAAC;IAC1F,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC;IACpE,KAAK,MAAM,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;QAChG,MAAM,CAAC,GAAG,MAAM,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;QAClE,IAAI,CAAC;YAAE,IAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAA+B,CAAC,CAAC,CAAC;IAC5F,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,IAA6B;IACpE,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,KAAK,GAAG,CAAC,CAAC;IAChB,MAAM,GAAG,GAAG,EAAE,CAAC;IACf,MAAM,KAAK,GAAG,EAAE,CAAC;IACjB,MAAM,GAAG,GAAG,EAAE,CAAC;IACf,MAAM,KAAK,GAAG,EAAE,CAAC;IACjB,2EAA2E;IAC3E,yEAAyE;IACzE,wEAAwE;IACxE,sCAAsC;IACtC,KAAK,CAAC,IAAI,CACR,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,cAAc,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAC7I,CAAC;IACF,KAAK,CAAC,IAAI,CACR,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAChH,CAAC;IACF,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;QACrB,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/C,KAAK,CAAC,IAAI,CACR,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,cAAc,EAAE,GAAG,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,SAAS,EAAE,CAC7L,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Linear → OpenPlanr pull-direction sync.
|
|
3
|
+
*
|
|
4
|
+
* Two concerns consolidated here because both are strictly pull and share
|
|
5
|
+
* the same client lifecycle and auth surface:
|
|
6
|
+
*
|
|
7
|
+
* 1. **Workflow-status sync**: for Features and Stories with a stored
|
|
8
|
+
* `linearIssueId`, fetch the current Linear workflow state name and
|
|
9
|
+
* write OpenPlanr `status` frontmatter when mapped.
|
|
10
|
+
*
|
|
11
|
+
* 2. **Task checkbox sync**: bidirectional 3-way merge between local
|
|
12
|
+
* TASK markdown and Linear TaskList issue description bodies.
|
|
13
|
+
* Pull-side lives here; push-side lives in `linear-push-service.ts`.
|
|
14
|
+
*
|
|
15
|
+
* Keeping them in one module reduces call-site noise for
|
|
16
|
+
* `planr linear sync` and gives the next reader one file to understand
|
|
17
|
+
* everything that pulls state from Linear.
|
|
18
|
+
*/
|
|
19
|
+
import type { LinearClient } from '@linear/sdk';
|
|
20
|
+
import type { ParsedSubtask } from '../agents/task-parser.js';
|
|
21
|
+
import type { BacklogStatus, OpenPlanrConfig, TaskStatus } from '../models/types.js';
|
|
22
|
+
export declare function buildNameToStatusMap(user: Record<string, string> | undefined): Map<string, TaskStatus>;
|
|
23
|
+
export declare function mapLinearNameToTaskStatus(stateName: string, byName: Map<string, TaskStatus>): TaskStatus | undefined;
|
|
24
|
+
export declare function buildNameToBacklogStatusMap(user: Record<string, string> | undefined): Map<string, BacklogStatus>;
|
|
25
|
+
export declare function mapLinearNameToBacklogStatus(stateName: string, byName: Map<string, BacklogStatus>): BacklogStatus | undefined;
|
|
26
|
+
export interface LinearStatusSyncSummary {
|
|
27
|
+
/** Local artifacts overwritten with Linear's state (the pull direction). */
|
|
28
|
+
updated: number;
|
|
29
|
+
/** Linear issues updated from local state (the push-on-sync direction). */
|
|
30
|
+
pushedToLinear: number;
|
|
31
|
+
/** Local and Linear already agree — no write either direction. */
|
|
32
|
+
unchanged: number;
|
|
33
|
+
/** Per-artifact conflicts resolved via `--on-conflict` (includes non-interactive defaults). */
|
|
34
|
+
conflictDecisions: number;
|
|
35
|
+
/** Linear returned a state name we don't know how to map. */
|
|
36
|
+
unmapped: number;
|
|
37
|
+
/** Artifact had no `linearIssueId` or an unparseable one. */
|
|
38
|
+
skippedNoId: number;
|
|
39
|
+
/** Linear didn't return the issue (deleted / no access). */
|
|
40
|
+
missingFromApi: number;
|
|
41
|
+
/** Push-back to Linear failed (API error); local frontmatter left unchanged. */
|
|
42
|
+
pushFailures: number;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Shared three-way merge strategy — governs how both checkbox sync and
|
|
46
|
+
* status sync resolve conflicts. Reused from the existing checkbox merge
|
|
47
|
+
* so users get one flag (`--on-conflict`) for both.
|
|
48
|
+
*/
|
|
49
|
+
export type ConflictStrategy = 'prompt' | 'local' | 'linear';
|
|
50
|
+
/**
|
|
51
|
+
* One side of a three-way status decision. Analogous to the `CheckboxConflict`
|
|
52
|
+
* record used by the task-checkbox merge, but scalar (single `status` value
|
|
53
|
+
* per artifact, not per-checkbox).
|
|
54
|
+
*/
|
|
55
|
+
export interface StatusConflict {
|
|
56
|
+
base: string | undefined;
|
|
57
|
+
local: string;
|
|
58
|
+
remote: string;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Pure three-way merge decision for a single artifact's workflow status.
|
|
62
|
+
*
|
|
63
|
+
* Mirrors `resolveTaskCheckboxFinalStates` but on a scalar. Returns
|
|
64
|
+
* `side='unchanged'` when local and remote already agree (counter path),
|
|
65
|
+
* `side='linear'` when the remote changed and should be pulled, `side='local'`
|
|
66
|
+
* when the local changed and should be pushed back to Linear. True
|
|
67
|
+
* conflicts (both diverged from base, or no base and they disagree) are
|
|
68
|
+
* resolved per `strategy`.
|
|
69
|
+
*/
|
|
70
|
+
export declare function resolveStatusFinalState(c: StatusConflict, strategy: ConflictStrategy): {
|
|
71
|
+
final: string;
|
|
72
|
+
side: 'unchanged' | 'local' | 'linear';
|
|
73
|
+
conflictDecisions: number;
|
|
74
|
+
isTrueConflict: boolean;
|
|
75
|
+
};
|
|
76
|
+
export declare function syncLinearStatusIntoArtifacts(projectDir: string, config: OpenPlanrConfig, client: LinearClient, options?: {
|
|
77
|
+
dryRun?: boolean;
|
|
78
|
+
onConflict?: ConflictStrategy;
|
|
79
|
+
}): Promise<LinearStatusSyncSummary>;
|
|
80
|
+
export declare function formatLinearStatusSyncLine(s: LinearStatusSyncSummary): string;
|
|
81
|
+
export type TaskCheckboxConflictStrategy = 'prompt' | 'local' | 'linear';
|
|
82
|
+
export interface LinearTaskCheckboxSyncSummary {
|
|
83
|
+
filesProcessed: number;
|
|
84
|
+
filesUpdatedLocal: number;
|
|
85
|
+
linearIssuesUpdated: number;
|
|
86
|
+
/** Number of per-id decisions for divergent local vs Linear (includes non-interactive defaults). */
|
|
87
|
+
conflictDecisions: number;
|
|
88
|
+
skippedNoIssue: number;
|
|
89
|
+
/** Artifacts whose `linearIssueId` frontmatter was present but malformed (H1). */
|
|
90
|
+
skippedStaleId: number;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Rebuild a `ParsedSubtask` list in document order: local file order, then any ids only in remote, then apply `final` done flags.
|
|
94
|
+
*/
|
|
95
|
+
export declare function mergeByIdForFormat(local: ParsedSubtask[], remote: ParsedSubtask[], final: ReadonlyMap<string, boolean>): ParsedSubtask[];
|
|
96
|
+
/** Merged issue body: return text for an artifact’s section, or the whole body when a single file owns the issue. */
|
|
97
|
+
export declare function extractTaskSectionFromMergedDescription(merged: string, taskFileId: string, siblingFileCount: number): string;
|
|
98
|
+
export declare function replaceTaskSectionInMergedDescription(merged: string, taskFileId: string, newSectionBody: string): string;
|
|
99
|
+
export interface CheckboxConflict {
|
|
100
|
+
id: string;
|
|
101
|
+
base: boolean | undefined;
|
|
102
|
+
local: boolean | undefined;
|
|
103
|
+
remote: boolean | undefined;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* One auto-resolved conflict entry (M4). Captured when a non-interactive
|
|
107
|
+
* default picks the Linear or local side so the user can review decisions
|
|
108
|
+
* after the fact in `.planr/reports/linear-sync-conflicts-<date>.md`.
|
|
109
|
+
*/
|
|
110
|
+
export interface AutoResolvedConflict {
|
|
111
|
+
label: string;
|
|
112
|
+
id: string;
|
|
113
|
+
base: boolean | undefined;
|
|
114
|
+
local: boolean | undefined;
|
|
115
|
+
remote: boolean | undefined;
|
|
116
|
+
chosen: 'local' | 'linear';
|
|
117
|
+
timestamp: string;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Three-way merge for checkbox `id -> done` and presence. A key is **absent** in a version when the task line is not in that side’s parse.
|
|
121
|
+
* Exported for unit tests.
|
|
122
|
+
*/
|
|
123
|
+
export declare function resolveTaskCheckboxFinalStates(local: Map<string, boolean>, remote: Map<string, boolean>, base: Map<string, boolean>, strategy: TaskCheckboxConflictStrategy, label: string, onAutoResolve?: (entry: AutoResolvedConflict) => void): Promise<{
|
|
124
|
+
final: Map<string, boolean>;
|
|
125
|
+
conflictDecisions: number;
|
|
126
|
+
}>;
|
|
127
|
+
/** Drop checkbox lines for ids that should be absent, apply done states, append new lines for ids in `rebuilt` that are still missing. */
|
|
128
|
+
export declare function applyCheckboxMergeToLocalBody(body: string, final: ReadonlyMap<string, boolean>, rebuilt: ParsedSubtask[]): string;
|
|
129
|
+
/**
|
|
130
|
+
* For each `task` artifact with `linearIssueId`, load the shared Linear description (once per issue id),
|
|
131
|
+
* reconcile checkboxes with the local file using three-way merge, then write back local and/or Linear.
|
|
132
|
+
*/
|
|
133
|
+
export declare function runLinearTaskCheckboxSync(projectDir: string, config: OpenPlanrConfig, client: LinearClient, opts?: {
|
|
134
|
+
onConflict?: TaskCheckboxConflictStrategy;
|
|
135
|
+
dryRun?: boolean;
|
|
136
|
+
}): Promise<LinearTaskCheckboxSyncSummary>;
|
|
137
|
+
//# sourceMappingURL=linear-pull-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"linear-pull-service.d.ts","sourceRoot":"","sources":["../../src/services/linear-pull-service.ts"],"names":[],"mappings":"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"}
|