@limina-labs/momentum 0.41.0 → 0.41.1
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/core/ecosystem/lib/orient.js +72 -10
- package/package.json +1 -1
|
@@ -116,23 +116,83 @@ function openBlockers(backlogBody) {
|
|
|
116
116
|
return out;
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
-
/**
|
|
119
|
+
/**
|
|
120
|
+
* Statuses that mean a lane is still in flight. `landed` and `closed` lanes are
|
|
121
|
+
* spent — surfacing them is how BUG-029 reported 30 "open" lanes on a repo whose
|
|
122
|
+
* true state was 29 closed + 1 landed.
|
|
123
|
+
*/
|
|
124
|
+
const IN_FLIGHT = new Set(['open', 'done']);
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Resolve `<git-common-dir>/momentum/lanes` without running git.
|
|
128
|
+
*
|
|
129
|
+
* `.git` is a directory in a normal checkout, but a FILE in a linked worktree
|
|
130
|
+
* (`gitdir: /abs/path/.git/worktrees/<name>`), whose sibling `commondir` points
|
|
131
|
+
* back at the shared dir. Lane state lives under the COMMON dir, so a worktree
|
|
132
|
+
* that did not follow the pointer would see no lanes at all — and Rule 15 lane
|
|
133
|
+
* work happens in worktrees, which is exactly where this has to be right.
|
|
134
|
+
*/
|
|
135
|
+
function laneAnchor(repoDir) {
|
|
136
|
+
const dotGit = path.join(repoDir, '.git');
|
|
137
|
+
let stat;
|
|
138
|
+
try { stat = fs.statSync(dotGit); } catch (_e) { return null; }
|
|
139
|
+
|
|
140
|
+
if (stat.isDirectory()) return path.join(dotGit, 'momentum', 'lanes');
|
|
141
|
+
|
|
142
|
+
const pointer = readIf(dotGit);
|
|
143
|
+
if (!pointer) return null;
|
|
144
|
+
const m = pointer.match(/^gitdir:\s*(.+)$/m);
|
|
145
|
+
if (!m) return null;
|
|
146
|
+
const gitdir = path.resolve(repoDir, m[1].trim());
|
|
147
|
+
const commondir = readIf(path.join(gitdir, 'commondir'));
|
|
148
|
+
const common = commondir
|
|
149
|
+
? path.resolve(gitdir, commondir.trim())
|
|
150
|
+
: gitdir;
|
|
151
|
+
return path.join(common, 'momentum', 'lanes');
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* In-flight lanes for a member.
|
|
156
|
+
*
|
|
157
|
+
* The registry stores an array of lane **id strings**; per-lane detail lives in
|
|
158
|
+
* `<anchor>/<id>/manifest.json`. Reading the ids as objects was BUG-029 —
|
|
159
|
+
* every entry became `{status: undefined}`, and `undefined !== 'closed'` let the
|
|
160
|
+
* whole history through.
|
|
161
|
+
*/
|
|
120
162
|
function openLanes(repoDir) {
|
|
121
|
-
const
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
const body = readIf(file);
|
|
163
|
+
const anchors = [laneAnchor(repoDir), path.join(repoDir, '.momentum', 'lanes')]
|
|
164
|
+
.filter(Boolean);
|
|
165
|
+
|
|
166
|
+
for (const anchor of anchors) {
|
|
167
|
+
const body = readIf(path.join(anchor, 'registry.json'));
|
|
127
168
|
if (!body) continue;
|
|
169
|
+
|
|
170
|
+
let ids;
|
|
128
171
|
try {
|
|
129
172
|
const reg = JSON.parse(body);
|
|
130
|
-
|
|
131
|
-
.filter((l) => l && l.status !== 'closed' && l.status !== 'landed')
|
|
132
|
-
.map((l) => ({ id: l.id, branch: l.branch, status: l.status }));
|
|
173
|
+
ids = Array.isArray(reg.lanes) ? reg.lanes : [];
|
|
133
174
|
} catch (_e) {
|
|
134
175
|
return [];
|
|
135
176
|
}
|
|
177
|
+
|
|
178
|
+
const out = [];
|
|
179
|
+
for (const entry of ids) {
|
|
180
|
+
// Tolerate both shapes: the id-string form momentum writes today, and an
|
|
181
|
+
// inlined object, so a future registry format change degrades instead of
|
|
182
|
+
// silently reporting garbage again.
|
|
183
|
+
const id = typeof entry === 'string' ? entry : (entry && entry.id);
|
|
184
|
+
if (!id) continue;
|
|
185
|
+
|
|
186
|
+
let lane = (entry && typeof entry === 'object') ? entry : null;
|
|
187
|
+
if (!lane || !lane.status) {
|
|
188
|
+
const mf = readIf(path.join(anchor, id, 'manifest.json'));
|
|
189
|
+
if (!mf) continue;
|
|
190
|
+
try { lane = JSON.parse(mf); } catch (_e) { continue; }
|
|
191
|
+
}
|
|
192
|
+
if (!IN_FLIGHT.has(lane.status)) continue;
|
|
193
|
+
out.push({ id, branch: lane.branch || null, status: lane.status });
|
|
194
|
+
}
|
|
195
|
+
return out;
|
|
136
196
|
}
|
|
137
197
|
return [];
|
|
138
198
|
}
|
|
@@ -228,6 +288,8 @@ function memberBrief(summary) {
|
|
|
228
288
|
|
|
229
289
|
module.exports = {
|
|
230
290
|
MAX_ITEMS,
|
|
291
|
+
IN_FLIGHT,
|
|
292
|
+
laneAnchor,
|
|
231
293
|
MAX_TITLE,
|
|
232
294
|
condense,
|
|
233
295
|
activePhases,
|
package/package.json
CHANGED