@rasensio/aidlc 1.21.0 → 1.22.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/dist/commands/roadmap.d.ts.map +1 -1
- package/dist/commands/roadmap.js +19 -1
- package/dist/commands/roadmap.js.map +1 -1
- package/dist/roadmap/paths.d.ts +21 -0
- package/dist/roadmap/paths.d.ts.map +1 -1
- package/dist/roadmap/paths.js +17 -1
- package/dist/roadmap/paths.js.map +1 -1
- package/dist/roadmap/sync/body.d.ts +109 -23
- package/dist/roadmap/sync/body.d.ts.map +1 -1
- package/dist/roadmap/sync/body.js +260 -23
- package/dist/roadmap/sync/body.js.map +1 -1
- package/dist/roadmap/sync/collect.d.ts +9 -0
- package/dist/roadmap/sync/collect.d.ts.map +1 -1
- package/dist/roadmap/sync/collect.js +48 -3
- package/dist/roadmap/sync/collect.js.map +1 -1
- package/dist/roadmap/sync/execute.d.ts.map +1 -1
- package/dist/roadmap/sync/execute.js +12 -2
- package/dist/roadmap/sync/execute.js.map +1 -1
- package/dist/roadmap/sync/gh.d.ts +10 -0
- package/dist/roadmap/sync/gh.d.ts.map +1 -1
- package/dist/roadmap/sync/gh.js +24 -0
- package/dist/roadmap/sync/gh.js.map +1 -1
- package/dist/roadmap/sync/markdown.d.ts +79 -0
- package/dist/roadmap/sync/markdown.d.ts.map +1 -0
- package/dist/roadmap/sync/markdown.js +165 -0
- package/dist/roadmap/sync/markdown.js.map +1 -0
- package/dist/roadmap/sync/marker.d.ts +10 -1
- package/dist/roadmap/sync/marker.d.ts.map +1 -1
- package/dist/roadmap/sync/marker.js +16 -1
- package/dist/roadmap/sync/marker.js.map +1 -1
- package/dist/roadmap/sync/plan.d.ts +7 -0
- package/dist/roadmap/sync/plan.d.ts.map +1 -1
- package/dist/roadmap/sync/plan.js +22 -4
- package/dist/roadmap/sync/plan.js.map +1 -1
- package/dist/roadmap/sync/render.d.ts.map +1 -1
- package/dist/roadmap/sync/render.js +2 -0
- package/dist/roadmap/sync/render.js.map +1 -1
- package/dist/roadmap/sync/sanitize.d.ts +56 -0
- package/dist/roadmap/sync/sanitize.d.ts.map +1 -0
- package/dist/roadmap/sync/sanitize.js +140 -0
- package/dist/roadmap/sync/sanitize.js.map +1 -0
- package/dist/roadmap/sync/types.d.ts +30 -2
- package/dist/roadmap/sync/types.d.ts.map +1 -1
- package/dist/roadmap/sync/types.js +9 -2
- package/dist/roadmap/sync/types.js.map +1 -1
- package/package.json +2 -2
|
@@ -1,39 +1,209 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The body of a
|
|
2
|
+
* The body of a projected issue.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* v1.21.0 emitted a fixed six-line notice carrying no item prose at all, on the grounds
|
|
5
|
+
* that projecting prose risked marker injection, mention notifications, and the 65,536
|
|
6
|
+
* character field limit. The hazards were real; the conclusion was not. What shipped was a
|
|
7
|
+
* redirect — thirty issues on a board with thirty copies of one paragraph, unreadable to
|
|
8
|
+
* exactly the person the feature was for: somebody triaging in the tracker who will not
|
|
9
|
+
* clone the repository. `richer-issue-bodies` answers all three hazards instead of avoiding
|
|
10
|
+
* them: `sanitize.ts` neutralises comments and autolink triggers code-awarely, and the
|
|
11
|
+
* budget below bounds the field.
|
|
7
12
|
*
|
|
8
|
-
*
|
|
9
|
-
* requirements document does — would put a second marker into a different issue, making
|
|
10
|
-
* the id→issue map ambiguous enough to retitle or close the wrong issue.
|
|
11
|
-
* - **Notification side effects.** Item prose containing `@name` or `#123` sends
|
|
12
|
-
* notifications and creates cross-links the moment it is published, which is the class
|
|
13
|
-
* of harm the per-status eligibility rule exists to prevent.
|
|
14
|
-
* - **Field limits.** GitHub caps bodies at 65,536 characters. A generated body is
|
|
15
|
-
* bounded by construction, so no truncation logic exists to get wrong.
|
|
13
|
+
* Two structural decisions carry the rest of the design.
|
|
16
14
|
*
|
|
17
|
-
* The
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
15
|
+
* **The region is delimited, and everything outside it is somebody else's.** A body is
|
|
16
|
+
* regenerated on every sync, so it must be possible to say precisely which bytes the
|
|
17
|
+
* projection owns. Text before `BODY_BEGIN` or after `BODY_END` survives untouched, which
|
|
18
|
+
* is what makes a projected issue still usable as a tracker: a reader can add a note to the
|
|
19
|
+
* description and keep it.
|
|
21
20
|
*
|
|
22
|
-
* The body is
|
|
23
|
-
*
|
|
21
|
+
* **The body is rewritten, not written once.** v1.21.0 froze it at creation, reasoning that
|
|
22
|
+
* an update "would delete the context around [comments]". That does not hold — GitHub issue
|
|
23
|
+
* comments are separate entities from the body, and a body edit keeps its own revision
|
|
24
|
+
* history — and the cost of freezing is that every issue created before this change stays
|
|
25
|
+
* thin forever while every later item edit makes its issue quietly wrong. The rejected
|
|
26
|
+
* alternative was a one-off migration command; this project has a recorded lesson that a
|
|
27
|
+
* capability needing a manual post-deploy command will be un-run.
|
|
24
28
|
*
|
|
25
|
-
*
|
|
29
|
+
* Nothing volatile may enter this module's output. A timestamp, a commit sha or a metric
|
|
30
|
+
* would make the rendered region differ from the stored one on every single run, so every
|
|
31
|
+
* item would plan `update-body` forever and the projection would never converge — the same
|
|
32
|
+
* defect class as `discover.ts`'s labels-are-objects bug. That is why the region is a pure
|
|
33
|
+
* function of the item and the repository coordinates, and why a test pins that this file
|
|
34
|
+
* imports neither `node:fs` nor `node:child_process`.
|
|
35
|
+
*
|
|
36
|
+
* Requirements: richer-issue-bodies/AC-1 … richer-issue-bodies/AC-4,
|
|
37
|
+
* richer-issue-bodies/AC-6, richer-issue-bodies/AC-7, richer-issue-bodies/AC-16,
|
|
38
|
+
* richer-issue-bodies/AC-17, richer-issue-bodies/AC-21 … richer-issue-bodies/AC-24,
|
|
39
|
+
* richer-issue-bodies/AC-28
|
|
26
40
|
*
|
|
27
41
|
* @module
|
|
28
42
|
*/
|
|
43
|
+
import { lastProseBreakBefore } from './markdown.js';
|
|
29
44
|
import { renderMarker } from './marker.js';
|
|
45
|
+
import { sanitizeItemBody } from './sanitize.js';
|
|
46
|
+
/** Start of the projection-owned region. */
|
|
47
|
+
export const BODY_BEGIN = '<!-- aidlc-body:begin -->';
|
|
48
|
+
/** End of the projection-owned region. */
|
|
49
|
+
export const BODY_END = '<!-- aidlc-body:end -->';
|
|
50
|
+
/**
|
|
51
|
+
* The ceiling this module will not cross.
|
|
52
|
+
*
|
|
53
|
+
* GitHub's own limit is 65,536. The margin is not decoration: the largest real item in this
|
|
54
|
+
* project's roadmap is 44,481 characters, so nothing today comes close, and the headroom is
|
|
55
|
+
* what keeps a future item from failing a write *after* consent was given — the one moment
|
|
56
|
+
* in the projection where a failure is expensive.
|
|
57
|
+
*/
|
|
58
|
+
export const MAX_BODY_LENGTH = 60_000;
|
|
59
|
+
/**
|
|
60
|
+
* A permalink to a file on the default branch.
|
|
61
|
+
*
|
|
62
|
+
* `blob/HEAD/` rather than a resolved branch name, and this was measured rather than
|
|
63
|
+
* reasoned: on 2026-09-07, `github.com/cli/cli/blob/HEAD/README.md` returned 200 while
|
|
64
|
+
* `blob/main/README.md` returned 404, because that repository's default branch is `trunk`.
|
|
65
|
+
* Hardcoding `main` would ship broken links to every project that renamed its default
|
|
66
|
+
* branch. `HEAD` also needs no extra `gh` call and puts no remote state in the body.
|
|
67
|
+
*/
|
|
68
|
+
export function fileUrlFor(repo, relPath) {
|
|
69
|
+
return `https://github.com/${repo.owner}/${repo.name}/blob/HEAD/${relPath}`;
|
|
70
|
+
}
|
|
71
|
+
/** The context's URL builder, or null when coordinates are unknown. */
|
|
72
|
+
function urlBuilder(ctx) {
|
|
73
|
+
const { repo } = ctx;
|
|
74
|
+
return repo === null ? null : (relPath) => fileUrlFor(repo, relPath);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* The projection-owned region, delimiters included.
|
|
78
|
+
*
|
|
79
|
+
* Facts first, because a triager reads the top of a body the way they read the top of an
|
|
80
|
+
* item. The marker sits *inside* the region, so replacing the region can never orphan or
|
|
81
|
+
* duplicate it.
|
|
82
|
+
*/
|
|
83
|
+
export function renderGeneratedRegion(item, ctx) {
|
|
84
|
+
const url = urlBuilder(ctx);
|
|
85
|
+
// Assemble around a prose slot, so the fixed cost is measured rather than estimated.
|
|
86
|
+
const assemble = (prose) => [
|
|
87
|
+
BODY_BEGIN,
|
|
88
|
+
'',
|
|
89
|
+
renderFacts(item, ctx, url),
|
|
90
|
+
'',
|
|
91
|
+
'---',
|
|
92
|
+
'',
|
|
93
|
+
prose,
|
|
94
|
+
'',
|
|
95
|
+
'---',
|
|
96
|
+
'',
|
|
97
|
+
renderFooter(),
|
|
98
|
+
'',
|
|
99
|
+
renderMarker(item.id),
|
|
100
|
+
BODY_END,
|
|
101
|
+
// No trailing newline. `extractRegion` ends AT `BODY_END`, so a region that ended one
|
|
102
|
+
// byte later would never compare equal to the one read back off an issue — every item
|
|
103
|
+
// would plan `update-body` on every run and the projection would never converge. The
|
|
104
|
+
// convergence test is what caught it; the two functions have to agree byte for byte.
|
|
105
|
+
].join('\n');
|
|
106
|
+
// Trimmed: an item body starts with the newline that followed its closing `---`, and the
|
|
107
|
+
// assembly already puts blank lines around the prose slot. Without this the region renders
|
|
108
|
+
// with a double blank line above the first heading — visible in the first real sample,
|
|
109
|
+
// invisible in every fixture, which is why generated prose gets read as rendered output.
|
|
110
|
+
const sanitized = sanitizeItemBody(item.body, { itemPaths: ctx.itemPaths, fileUrl: url }).trim();
|
|
111
|
+
return assemble(fitProse(sanitized, item, url, assemble('').length));
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* The facts block.
|
|
115
|
+
*
|
|
116
|
+
* `not recorded` for a key the frontmatter does not carry — an admitted gap a reader can
|
|
117
|
+
* tell apart from a real value, which an empty cell cannot. `promoted_to` is the one
|
|
118
|
+
* exception: absent and explicitly `null` both mean the same thing there, and *not
|
|
119
|
+
* promoted* is what that means.
|
|
120
|
+
*/
|
|
121
|
+
function renderFacts(item, ctx, url) {
|
|
122
|
+
const { facts } = item;
|
|
123
|
+
const value = (v) => (v === null ? '_not recorded_' : v);
|
|
124
|
+
const depends = facts.dependsOn.length === 0
|
|
125
|
+
? '_none_'
|
|
126
|
+
: facts.dependsOn.map((id) => renderItemRef(id, ctx, url)).join(', ');
|
|
127
|
+
const filePath = url === null ? `\`${item.relPath}\`` : `[${item.relPath}](${url(item.relPath)})`;
|
|
128
|
+
// A bullet list, not backslash hard breaks: it survives any renderer, and a screen
|
|
129
|
+
// reader announces four labelled facts rather than one run-on paragraph.
|
|
130
|
+
return [
|
|
131
|
+
`- **Status:** \`${item.status}\``,
|
|
132
|
+
`- **Created:** ${value(facts.createdAt)}`,
|
|
133
|
+
`- **Author:** ${value(facts.author)}`,
|
|
134
|
+
`- **Source:** ${value(facts.source)}`,
|
|
135
|
+
`- **Depends on:** ${depends}`,
|
|
136
|
+
`- **Promoted to:** ${facts.promotedTo === null ? '_not promoted_' : `\`${facts.promotedTo}\``}`,
|
|
137
|
+
`- **Roadmap file:** ${filePath}`,
|
|
138
|
+
].join('\n');
|
|
139
|
+
}
|
|
140
|
+
/** One `depends_on` entry: a link when the item exists, a named gap when it does not. */
|
|
141
|
+
function renderItemRef(id, ctx, url) {
|
|
142
|
+
const relPath = ctx.itemPaths.get(id);
|
|
143
|
+
if (relPath === undefined)
|
|
144
|
+
return `\`${id}\` (no such item)`;
|
|
145
|
+
if (url === null)
|
|
146
|
+
return `\`${id}\``;
|
|
147
|
+
return `[\`${id}\`](${url(relPath)})`;
|
|
148
|
+
}
|
|
149
|
+
/** The standing explanation, identical on every issue. */
|
|
150
|
+
function renderFooter() {
|
|
151
|
+
return [
|
|
152
|
+
'Projected from this repository’s AIDLC roadmap by `aidlc roadmap sync`. The roadmap',
|
|
153
|
+
'file named above is the source of truth — edit it there. This region is regenerated on',
|
|
154
|
+
'every sync; anything written outside it is preserved. Comments are never copied back',
|
|
155
|
+
'into the repository.',
|
|
156
|
+
].join('\n');
|
|
157
|
+
}
|
|
30
158
|
/**
|
|
31
|
-
*
|
|
159
|
+
* Fit sanitized prose inside the remaining budget.
|
|
32
160
|
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
161
|
+
* The cut point is the last newline before the budget that sits in **prose**, which is what
|
|
162
|
+
* stops truncation leaving a fence open — a body ending mid-fence renders everything after
|
|
163
|
+
* it as one code block. When no safe break exists the prose is dropped entirely rather than
|
|
164
|
+
* cut mid-construct, and the notice says so; that case cannot arise from any real item
|
|
165
|
+
* today and a silent hard slice would be the worse failure if it ever did.
|
|
35
166
|
*/
|
|
36
|
-
|
|
167
|
+
function fitProse(prose, item, url, fixedLength) {
|
|
168
|
+
const budget = MAX_BODY_LENGTH - fixedLength;
|
|
169
|
+
if (prose.length <= budget)
|
|
170
|
+
return prose;
|
|
171
|
+
const link = url === null ? `\`${item.relPath}\`` : `[${item.relPath}](${url(item.relPath)})`;
|
|
172
|
+
// Reserve room for the notice itself, which is why the break is sought below a reduced
|
|
173
|
+
// limit rather than at the budget.
|
|
174
|
+
const notice = (omitted) => `\n_… ${omitted.toLocaleString('en-US')} further characters are not shown. Read the whole item at ${link}._`;
|
|
175
|
+
const reserve = notice(prose.length).length;
|
|
176
|
+
const cut = lastProseBreakBefore(prose, Math.max(0, budget - reserve));
|
|
177
|
+
if (cut === -1)
|
|
178
|
+
return notice(prose.length).trimStart();
|
|
179
|
+
return prose.slice(0, cut) + notice(prose.length - cut);
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* The region bytes of an existing body, or null when it carries no region.
|
|
183
|
+
*
|
|
184
|
+
* Delimiters included, so the value can be compared directly against
|
|
185
|
+
* `renderGeneratedRegion`'s output — comparing the insides would let a delimiter change go
|
|
186
|
+
* undetected.
|
|
187
|
+
*/
|
|
188
|
+
export function extractRegion(body) {
|
|
189
|
+
const start = body.indexOf(BODY_BEGIN);
|
|
190
|
+
if (start === -1)
|
|
191
|
+
return null;
|
|
192
|
+
const end = body.indexOf(BODY_END, start);
|
|
193
|
+
if (end === -1)
|
|
194
|
+
return null;
|
|
195
|
+
return body.slice(start, end + BODY_END.length);
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* v1.21.0's body, reproduced exactly.
|
|
199
|
+
*
|
|
200
|
+
* **Frozen history, not a template.** Its only job is to be recognised so it can be
|
|
201
|
+
* replaced, so it must keep emitting the bytes v1.21.0 emitted even as the real renderer
|
|
202
|
+
* changes. A test pins it as a literal for that reason: edit it and issues created before
|
|
203
|
+
* this change stop being recognised, and every one of them gains a new region below a stale
|
|
204
|
+
* notice instead of replacing it.
|
|
205
|
+
*/
|
|
206
|
+
export function renderLegacyIssueBody(item) {
|
|
37
207
|
return [
|
|
38
208
|
'Projected from this repository’s AIDLC roadmap.',
|
|
39
209
|
'',
|
|
@@ -49,4 +219,71 @@ export function renderIssueBody(item) {
|
|
|
49
219
|
'',
|
|
50
220
|
].join('\n');
|
|
51
221
|
}
|
|
222
|
+
/**
|
|
223
|
+
* The body to write: a fresh region merged into whatever the issue already has.
|
|
224
|
+
*
|
|
225
|
+
* Four cases, first match wins:
|
|
226
|
+
*
|
|
227
|
+
* 1. **Both delimiters present** — replace the span between them and keep everything else.
|
|
228
|
+
* This is the steady state, and the reason a human's note survives a sync.
|
|
229
|
+
* 2. **Exactly the legacy notice** — the region alone. An issue created by v1.21.0 stops
|
|
230
|
+
* being thin.
|
|
231
|
+
* 3. **Legacy notice plus other text** — replace only the recognised notice. Whatever
|
|
232
|
+
* somebody added stays.
|
|
233
|
+
* 4. **Anything else** — append the region below the existing body, after stripping any
|
|
234
|
+
* marker naming *this* item, so the body ends up with exactly one.
|
|
235
|
+
*
|
|
236
|
+
* Case 4 deliberately leaves markers naming *other* ids alone. Those are the ambiguity
|
|
237
|
+
* `indexByMarker` exists to refuse, and quietly deleting one would hide a genuine
|
|
238
|
+
* two-issue collision rather than resolve it.
|
|
239
|
+
*/
|
|
240
|
+
export function mergeBody(existing, region, itemId) {
|
|
241
|
+
const start = existing.indexOf(BODY_BEGIN);
|
|
242
|
+
if (start !== -1) {
|
|
243
|
+
const end = existing.indexOf(BODY_END, start);
|
|
244
|
+
if (end !== -1) {
|
|
245
|
+
return existing.slice(0, start) + region + existing.slice(end + BODY_END.length);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
const legacy = legacyNoticeFor(itemId, existing);
|
|
249
|
+
if (legacy !== null) {
|
|
250
|
+
if (existing === legacy)
|
|
251
|
+
return region;
|
|
252
|
+
const at = existing.indexOf(legacy);
|
|
253
|
+
if (at !== -1)
|
|
254
|
+
return existing.slice(0, at) + region + existing.slice(at + legacy.length);
|
|
255
|
+
}
|
|
256
|
+
const kept = stripOwnMarkers(existing, itemId).trimEnd();
|
|
257
|
+
return kept.length === 0 ? region : `${kept}\n\n${region}`;
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* The legacy notice for this item, if the body contains one.
|
|
261
|
+
*
|
|
262
|
+
* `renderLegacyIssueBody` needs a whole `ProjectableItem`, but a merge only knows the id
|
|
263
|
+
* and the body. The file path is recoverable from the notice itself, which is the one place
|
|
264
|
+
* v1.21.0 recorded it — so the notice is rebuilt from what it claims rather than from what
|
|
265
|
+
* the item currently says. That matters: an item that has since moved between statuses has
|
|
266
|
+
* a different `relPath` today, and rebuilding from the item would fail to match its own
|
|
267
|
+
* issue.
|
|
268
|
+
*/
|
|
269
|
+
function legacyNoticeFor(itemId, existing) {
|
|
270
|
+
const match = /- \*\*File:\*\* `([^`\n]+)`/.exec(existing);
|
|
271
|
+
if (match === null)
|
|
272
|
+
return null;
|
|
273
|
+
return renderLegacyIssueBody({
|
|
274
|
+
id: itemId,
|
|
275
|
+
relPath: match[1],
|
|
276
|
+
// Unused by the legacy renderer; present only to satisfy the shape.
|
|
277
|
+
title: '',
|
|
278
|
+
status: 'backlog',
|
|
279
|
+
filename: '',
|
|
280
|
+
body: '',
|
|
281
|
+
facts: { createdAt: null, author: null, source: null, promotedTo: null, dependsOn: [] },
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
/** Remove markers naming this item, leaving markers for other ids in place. */
|
|
285
|
+
function stripOwnMarkers(body, itemId) {
|
|
286
|
+
const escaped = itemId.replace(/[.*+?^${}()|[\]\\-]/g, '\\$&');
|
|
287
|
+
return body.replace(new RegExp(String.raw `<!--\s*aidlc-item:\s*${escaped}\s*-->\n?`, 'g'), '');
|
|
288
|
+
}
|
|
52
289
|
//# sourceMappingURL=body.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"body.js","sourceRoot":"","sources":["../../../src/roadmap/sync/body.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"body.js","sourceRoot":"","sources":["../../../src/roadmap/sync/body.ts"],"names":[],"mappings":"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"}
|
|
@@ -31,6 +31,15 @@ export interface Collected {
|
|
|
31
31
|
root: string;
|
|
32
32
|
items: readonly ProjectableItem[];
|
|
33
33
|
unprojectable: readonly UnprojectableRef[];
|
|
34
|
+
/**
|
|
35
|
+
* Every item id → its repo-relative path, across **all five statuses**.
|
|
36
|
+
*
|
|
37
|
+
* Not restricted to the eligible ones. A `backlog` item routinely names the four `hold`
|
|
38
|
+
* items it supersedes, and those references are the most useful links in the body
|
|
39
|
+
* precisely because a reader cannot guess where a parked item went. Restricting this map
|
|
40
|
+
* to projected statuses would drop them silently.
|
|
41
|
+
*/
|
|
42
|
+
itemPaths: ReadonlyMap<string, string>;
|
|
34
43
|
}
|
|
35
44
|
/**
|
|
36
45
|
* A title for an item whose frontmatter has none.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collect.d.ts","sourceRoot":"","sources":["../../../src/roadmap/sync/collect.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;
|
|
1
|
+
{"version":3,"file":"collect.d.ts","sourceRoot":"","sources":["../../../src/roadmap/sync/collect.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAaH,OAAO,KAAK,EAAa,eAAe,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE/E,MAAM,WAAW,SAAS;IACxB,gFAAgF;IAChF,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,SAAS,eAAe,EAAE,CAAC;IAClC,aAAa,EAAE,SAAS,gBAAgB,EAAE,CAAC;IAC3C;;;;;;;OAOG;IACH,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACxC;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAI1D;AAED,4EAA4E;AAC5E,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAmDnD"}
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
*
|
|
26
26
|
* @module
|
|
27
27
|
*/
|
|
28
|
-
import { ITEM_FILENAME_RE, ROADMAP_DIR, ROADMAP_STATUSES, listStatus, primaryCheckout, unparseableItems, } from '../paths.js';
|
|
28
|
+
import { ITEM_FILENAME_RE, ROADMAP_DIR, ROADMAP_STATUSES, frontmatter, itemBody, listStatus, primaryCheckout, unparseableItems, } from '../paths.js';
|
|
29
29
|
/**
|
|
30
30
|
* A title for an item whose frontmatter has none.
|
|
31
31
|
*
|
|
@@ -43,6 +43,7 @@ export function collectItems(cwd) {
|
|
|
43
43
|
const root = primaryCheckout(cwd);
|
|
44
44
|
const items = [];
|
|
45
45
|
const unprojectable = [];
|
|
46
|
+
const itemPaths = new Map();
|
|
46
47
|
// Unparseable first, so its entries keep their own reasons rather than being
|
|
47
48
|
// overwritten by the weaker "no id" classification below.
|
|
48
49
|
const unparseableLabels = new Set();
|
|
@@ -69,16 +70,60 @@ export function collectItems(cwd) {
|
|
|
69
70
|
});
|
|
70
71
|
continue;
|
|
71
72
|
}
|
|
73
|
+
const relPath = relPathOf(status, item.filename);
|
|
74
|
+
// First writer wins, matching `findByPromotedTo` and `indexByMarker`: a duplicate id
|
|
75
|
+
// is refused by `planProjection` anyway, so silently preferring one here cannot
|
|
76
|
+
// change an outcome — it only keeps this map from depending on directory order.
|
|
77
|
+
if (!itemPaths.has(item.id))
|
|
78
|
+
itemPaths.set(item.id, relPath);
|
|
72
79
|
items.push({
|
|
73
80
|
id: item.id,
|
|
74
81
|
title: item.title ?? titleFromFilename(item.filename),
|
|
75
82
|
status,
|
|
76
83
|
filename: item.filename,
|
|
77
|
-
relPath
|
|
84
|
+
relPath,
|
|
85
|
+
body: itemBody(item.raw),
|
|
86
|
+
facts: factsOf(item.raw),
|
|
78
87
|
});
|
|
79
88
|
}
|
|
80
89
|
}
|
|
81
|
-
return { root, items, unprojectable };
|
|
90
|
+
return { root, items, unprojectable, itemPaths };
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* The frontmatter facts, from the `raw` `readItem` already returned.
|
|
94
|
+
*
|
|
95
|
+
* No second disk read, and no second parse of the whole file: `readItem` keeps `raw`
|
|
96
|
+
* precisely so a caller can work from it. Every value is validated at this boundary and
|
|
97
|
+
* becomes `null` on anything unexpected — a wrong-typed `author` is a cosmetic gap, not a
|
|
98
|
+
* reason to make the whole item unprojectable, which is the same call the existing
|
|
99
|
+
* missing-`title` fallback already makes.
|
|
100
|
+
*/
|
|
101
|
+
function factsOf(raw) {
|
|
102
|
+
const data = frontmatter(raw)?.data ?? {};
|
|
103
|
+
const str = (key) => {
|
|
104
|
+
const value = data[key];
|
|
105
|
+
if (typeof value === 'string' && value.trim().length > 0)
|
|
106
|
+
return value.trim();
|
|
107
|
+
// `created_at: 2026-09-05` parses as a Date under YAML 1.1 timestamp rules, so a
|
|
108
|
+
// string check alone would drop the one fact every item has.
|
|
109
|
+
if (value instanceof Date)
|
|
110
|
+
return value.toISOString().slice(0, 10);
|
|
111
|
+
return null;
|
|
112
|
+
};
|
|
113
|
+
const dependsOn = [];
|
|
114
|
+
if (Array.isArray(data.depends_on)) {
|
|
115
|
+
for (const entry of data.depends_on) {
|
|
116
|
+
if (typeof entry === 'string' && entry.trim().length > 0)
|
|
117
|
+
dependsOn.push(entry.trim());
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return {
|
|
121
|
+
createdAt: str('created_at'),
|
|
122
|
+
author: str('author'),
|
|
123
|
+
source: str('source'),
|
|
124
|
+
promotedTo: str('promoted_to'),
|
|
125
|
+
dependsOn,
|
|
126
|
+
};
|
|
82
127
|
}
|
|
83
128
|
/**
|
|
84
129
|
* Repo-relative path of an item, with forward slashes on every platform.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collect.js","sourceRoot":"","sources":["../../../src/roadmap/sync/collect.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EACL,gBAAgB,EAChB,WAAW,EACX,gBAAgB,EAChB,UAAU,EACV,eAAe,EACf,gBAAgB,GAEjB,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"collect.js","sourceRoot":"","sources":["../../../src/roadmap/sync/collect.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"execute.d.ts","sourceRoot":"","sources":["../../../src/roadmap/sync/execute.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;
|
|
1
|
+
{"version":3,"file":"execute.d.ts","sourceRoot":"","sources":["../../../src/roadmap/sync/execute.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAuB,KAAK,QAAQ,EAAE,MAAM,SAAS,CAAC;AAE7D,OAAO,EAAW,KAAK,IAAI,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE/D,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,SAAS,QAAQ,EAAE,CAAC;IAC7B,uFAAuF;IACvF,OAAO,EAAE;QAAE,IAAI,EAAE,QAAQ,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAClD,YAAY,EAAE,SAAS,QAAQ,EAAE,CAAC;CACnC;AAED,wBAAgB,SAAS,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,GAAG,UAAU,CAyBtF;AAED,2CAA2C;AAC3C,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,GAAG,MAAM,EAAE,CAqD1F;AAyCD,6CAA6C;AAC7C,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAuB3D"}
|
|
@@ -22,7 +22,6 @@
|
|
|
22
22
|
*
|
|
23
23
|
* @module
|
|
24
24
|
*/
|
|
25
|
-
import { renderIssueBody } from './body.js';
|
|
26
25
|
import { firstLine, repoArgs } from './gh.js';
|
|
27
26
|
import { colorFor, descriptionFor } from './labels.js';
|
|
28
27
|
import { isWrite } from './types.js';
|
|
@@ -55,6 +54,8 @@ export function invocationFor(plan, line, discoveryLabel) {
|
|
|
55
54
|
case 'create': {
|
|
56
55
|
if (line.item === null)
|
|
57
56
|
throw new Error('create without an item');
|
|
57
|
+
if (line.newBody === null)
|
|
58
|
+
throw new Error('create without a rendered body');
|
|
58
59
|
return [
|
|
59
60
|
'issue',
|
|
60
61
|
'create',
|
|
@@ -62,7 +63,7 @@ export function invocationFor(plan, line, discoveryLabel) {
|
|
|
62
63
|
'--title',
|
|
63
64
|
line.item.title,
|
|
64
65
|
'--body',
|
|
65
|
-
|
|
66
|
+
line.newBody,
|
|
66
67
|
'--label',
|
|
67
68
|
discoveryLabel,
|
|
68
69
|
...line.addLabels.flatMap((l) => ['--label', l]),
|
|
@@ -88,6 +89,15 @@ export function invocationFor(plan, line, discoveryLabel) {
|
|
|
88
89
|
...line.removeLabels.flatMap((l) => ['--remove-label', l]),
|
|
89
90
|
];
|
|
90
91
|
}
|
|
92
|
+
case 'update-body': {
|
|
93
|
+
if (line.issueNumber === null)
|
|
94
|
+
throw new Error('update-body without an issue');
|
|
95
|
+
if (line.newBody === null)
|
|
96
|
+
throw new Error('update-body without a body');
|
|
97
|
+
// The whole body, not a patch: `gh issue edit --body` replaces it, and the merge that
|
|
98
|
+
// preserved anything a human added already happened in the planner (design DD-6).
|
|
99
|
+
return ['issue', 'edit', String(line.issueNumber), ...repo, '--body', line.newBody];
|
|
100
|
+
}
|
|
91
101
|
case 'close': {
|
|
92
102
|
if (line.issueNumber === null)
|
|
93
103
|
throw new Error('close without an issue');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"execute.js","sourceRoot":"","sources":["../../../src/roadmap/sync/execute.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"execute.js","sourceRoot":"","sources":["../../../src/roadmap/sync/execute.ts"],"names":[],"mappings":"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"}
|
|
@@ -61,4 +61,14 @@ export declare function ghPreflight(gh: GhRunner): {
|
|
|
61
61
|
export declare function firstLine(text: string): string;
|
|
62
62
|
/** `['--repo', repo]` when a coordinate was resolved, else `[]`. */
|
|
63
63
|
export declare function repoArgs(repo: string | null): readonly string[];
|
|
64
|
+
/**
|
|
65
|
+
* Ask `gh` which repository the current directory belongs to.
|
|
66
|
+
*
|
|
67
|
+
* Only needed when `roadmap.sync.repo` is unset, and only so bodies can carry permalinks.
|
|
68
|
+
* A failure is **not** fatal: it yields null, and the projection continues with unlinked
|
|
69
|
+
* paths. Refusing to sync because a hyperlink could not be built would trade the feature's
|
|
70
|
+
* whole purpose for one of its conveniences, and the plan header already names the target,
|
|
71
|
+
* so a wrong repository stays visible either way.
|
|
72
|
+
*/
|
|
73
|
+
export declare function resolveNameWithOwner(gh: GhRunner): string | null;
|
|
64
74
|
//# sourceMappingURL=gh.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gh.d.ts","sourceRoot":"","sources":["../../../src/roadmap/sync/gh.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAIH,MAAM,MAAM,QAAQ,GAChB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC5B;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC;AAE1D,MAAM,WAAW,QAAQ;IACvB,GAAG,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,QAAQ,CAAC;CACxC;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,aAAa,QAAoB,CAAC;AAE/C,kEAAkE;AAClE,wBAAgB,YAAY,IAAI,QAAQ,CAkBvC;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,EAAE,EAAE,QAAQ,GAAG;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CASrF;AAED,4EAA4E;AAC5E,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAM9C;AAED,oEAAoE;AACpE,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,MAAM,EAAE,CAE/D"}
|
|
1
|
+
{"version":3,"file":"gh.d.ts","sourceRoot":"","sources":["../../../src/roadmap/sync/gh.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAIH,MAAM,MAAM,QAAQ,GAChB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC5B;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC;AAE1D,MAAM,WAAW,QAAQ;IACvB,GAAG,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,QAAQ,CAAC;CACxC;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,aAAa,QAAoB,CAAC;AAE/C,kEAAkE;AAClE,wBAAgB,YAAY,IAAI,QAAQ,CAkBvC;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,EAAE,EAAE,QAAQ,GAAG;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CASrF;AAED,4EAA4E;AAC5E,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAM9C;AAED,oEAAoE;AACpE,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,MAAM,EAAE,CAE/D;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,QAAQ,GAAG,MAAM,GAAG,IAAI,CAWhE"}
|
package/dist/roadmap/sync/gh.js
CHANGED
|
@@ -83,4 +83,28 @@ export function firstLine(text) {
|
|
|
83
83
|
export function repoArgs(repo) {
|
|
84
84
|
return repo === null ? [] : ['--repo', repo];
|
|
85
85
|
}
|
|
86
|
+
/**
|
|
87
|
+
* Ask `gh` which repository the current directory belongs to.
|
|
88
|
+
*
|
|
89
|
+
* Only needed when `roadmap.sync.repo` is unset, and only so bodies can carry permalinks.
|
|
90
|
+
* A failure is **not** fatal: it yields null, and the projection continues with unlinked
|
|
91
|
+
* paths. Refusing to sync because a hyperlink could not be built would trade the feature's
|
|
92
|
+
* whole purpose for one of its conveniences, and the plan header already names the target,
|
|
93
|
+
* so a wrong repository stays visible either way.
|
|
94
|
+
*/
|
|
95
|
+
export function resolveNameWithOwner(gh) {
|
|
96
|
+
const result = gh.run(['repo', 'view', '--json', 'nameWithOwner']);
|
|
97
|
+
if (!result.ok)
|
|
98
|
+
return null;
|
|
99
|
+
try {
|
|
100
|
+
const parsed = JSON.parse(result.stdout);
|
|
101
|
+
if (typeof parsed !== 'object' || parsed === null)
|
|
102
|
+
return null;
|
|
103
|
+
const value = parsed.nameWithOwner;
|
|
104
|
+
return typeof value === 'string' && value.length > 0 ? value : null;
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
86
110
|
//# sourceMappingURL=gh.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gh.js","sourceRoot":"","sources":["../../../src/roadmap/sync/gh.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAUlD;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,GAAG,GAAG,IAAI,GAAG,IAAI,CAAC;AAE/C,kEAAkE;AAClE,MAAM,UAAU,YAAY;IAC1B,OAAO;QACL,GAAG,CAAC,IAAuB;YACzB,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC,EAAE;oBAC3C,QAAQ,EAAE,MAAM;oBAChB,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;oBACjC,SAAS,EAAE,aAAa;iBACzB,CAAC,CAAC;gBACH,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;YAC9B,CAAC;YAAC,OAAO,GAAY,EAAE,CAAC;gBACtB,MAAM,CAAC,GAAG,GAA6E,CAAC;gBACxF,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;gBACpF,MAAM,OAAO,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC,OAAO,IAAI,sBAAsB,CAAC,CAAC,IAAI,EAAE,CAAC;gBACvE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC,MAAM,IAAI,IAAI,EAAE,CAAC;YACnE,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,WAAW,CAAC,EAAY;IACtC,MAAM,MAAM,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;IAC1C,IAAI,MAAM,CAAC,EAAE;QAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;IACnC,OAAO;QACL,EAAE,EAAE,KAAK;QACT,KAAK,EACH,4EAA4E;YAC5E,kDAAkD,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;KAC9E,CAAC;AACJ,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACpC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,OAAO,CAAC;IACzC,CAAC;IACD,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC;AACrB,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,QAAQ,CAAC,IAAmB;IAC1C,OAAO,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;AAC/C,CAAC"}
|
|
1
|
+
{"version":3,"file":"gh.js","sourceRoot":"","sources":["../../../src/roadmap/sync/gh.ts"],"names":[],"mappings":"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"}
|