@rness/cli 0.21.0 → 0.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/README.md +151 -95
- package/dist/bin/rness.js +2 -2
- package/dist/{chunk-4BM4FUWO.js → chunk-AEL2W76O.js} +6 -6
- package/dist/chunk-AEL2W76O.js.map +1 -0
- package/dist/{chunk-T5PINUCP.js → chunk-S4NARIQP.js} +88 -71
- package/dist/chunk-S4NARIQP.js.map +1 -0
- package/dist/{chunk-D3D2WCGW.js → chunk-XCO5ZT2H.js} +453 -390
- package/dist/chunk-XCO5ZT2H.js.map +1 -0
- package/dist/index.js +2 -2
- package/dist/{note-RBG7OXVI.js → note-XSJ7ASXM.js} +5 -5
- package/dist/{summary-UCMFESSA.js → summary-47SFWNSQ.js} +4 -4
- package/dist/summary-47SFWNSQ.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-4BM4FUWO.js.map +0 -1
- package/dist/chunk-D3D2WCGW.js.map +0 -1
- package/dist/chunk-T5PINUCP.js.map +0 -1
- package/dist/summary-UCMFESSA.js.map +0 -1
- /package/dist/{note-RBG7OXVI.js.map → note-XSJ7ASXM.js.map} +0 -0
|
@@ -856,16 +856,33 @@ function readHooks(value, at, fields2, holdsPlans) {
|
|
|
856
856
|
).withColon();
|
|
857
857
|
return hooks;
|
|
858
858
|
}
|
|
859
|
+
var PULSE = "pulse";
|
|
860
|
+
var presetFor = (name) => name === PULSE ? "agent-pulse" : "collection";
|
|
861
|
+
var PRESET_NAME = /^[a-z][a-z0-9-]*(?:\/[1-9][0-9]*)?$/;
|
|
862
|
+
function readPresetEntry(name, value, knows = isPresetRevision) {
|
|
863
|
+
const at = `boards.${name}`;
|
|
864
|
+
const preset = presetFor(name);
|
|
865
|
+
if (!PRESET_NAME.test(value))
|
|
866
|
+
throw new BoardRefused(at, `must name a preset, as "${preset}"`);
|
|
867
|
+
if (presetNameOf(value) !== preset)
|
|
868
|
+
throw new BoardRefused(
|
|
869
|
+
at,
|
|
870
|
+
name === PULSE ? `names ${value}: ${PULSE} is made from ${preset}` : `names ${value}: a collection's board is made from ${preset}`
|
|
871
|
+
);
|
|
872
|
+
if (value.includes("/") && !knows(value))
|
|
873
|
+
throw new BoardRefused(at, `names ${value}, which this rness does not have`);
|
|
874
|
+
return value;
|
|
875
|
+
}
|
|
859
876
|
function parseBoard(name, value, knows = isPresetRevision) {
|
|
860
|
-
const at = `
|
|
877
|
+
const at = `boards.${name}`;
|
|
861
878
|
if (!isRecord(value))
|
|
862
879
|
throw new BoardRefused(
|
|
863
880
|
at,
|
|
864
|
-
'must be an object, as { "
|
|
881
|
+
'must be an object, as { "collections": \u2026, "views": \u2026 }'
|
|
865
882
|
);
|
|
866
883
|
unknownKeys(value, BOARD_KEYS, at, "a board");
|
|
867
|
-
const number = value["number"];
|
|
868
|
-
if (typeof number !== "number" || !Number.isInteger(number) || number < 1)
|
|
884
|
+
const number = value["number"] ?? null;
|
|
885
|
+
if (number !== null && (typeof number !== "number" || !Number.isInteger(number) || number < 1))
|
|
869
886
|
throw new BoardRefused(`${at}.number`, "must be a project number");
|
|
870
887
|
const preset = value["preset"];
|
|
871
888
|
if (preset !== void 0 && (typeof preset !== "string" || !PRESET.test(preset)))
|
|
@@ -1230,8 +1247,10 @@ var KEYS = [
|
|
|
1230
1247
|
"provider",
|
|
1231
1248
|
"org",
|
|
1232
1249
|
"agents",
|
|
1233
|
-
"
|
|
1250
|
+
"boards",
|
|
1251
|
+
// Former names of `boards`, still read: `sync` renames them (spec 0033 §3).
|
|
1234
1252
|
"projects",
|
|
1253
|
+
"pulse",
|
|
1235
1254
|
"repos",
|
|
1236
1255
|
"scopes"
|
|
1237
1256
|
];
|
|
@@ -1287,52 +1306,57 @@ function readProvider(value) {
|
|
|
1287
1306
|
return name;
|
|
1288
1307
|
}
|
|
1289
1308
|
function readPulse(value) {
|
|
1290
|
-
if (value === void 0) return null;
|
|
1291
1309
|
if (!isRecord2(value) || Object.keys(value).length !== 1 || typeof value.project !== "number" || !Number.isInteger(value.project) || value.project < 1)
|
|
1292
1310
|
fail2(
|
|
1293
1311
|
`"pulse" must be { "project": <number> } (got ${JSON.stringify(value)})`
|
|
1294
1312
|
);
|
|
1295
1313
|
return { [PULSE]: value.project };
|
|
1296
1314
|
}
|
|
1297
|
-
var
|
|
1298
|
-
var PULSE = "pulse";
|
|
1299
|
-
var PROJECT_NAME = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
|
|
1315
|
+
var BOARD_NAME = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
|
|
1300
1316
|
var isProjectNumber = (n) => typeof n === "number" && Number.isInteger(n) && n >= 1;
|
|
1301
|
-
function
|
|
1302
|
-
if (value === void 0) return { projects: null, refused: [] };
|
|
1317
|
+
function readBoardEntries(value) {
|
|
1303
1318
|
const entries = isRecord2(value) ? Object.entries(value) : [];
|
|
1304
|
-
const numbers = entries.
|
|
1305
|
-
([, n]) => isRecord2(n)
|
|
1319
|
+
const numbers = entries.flatMap(
|
|
1320
|
+
([, n]) => isRecord2(n) ? isProjectNumber(n["number"]) ? [n["number"]] : [] : [n]
|
|
1306
1321
|
);
|
|
1307
1322
|
if (entries.length === 0 || !entries.every(
|
|
1308
|
-
([name, n]) =>
|
|
1323
|
+
([name, n]) => BOARD_NAME.test(name) && (isProjectNumber(n) || typeof n === "string" || isRecord2(n))
|
|
1309
1324
|
) || new Set(numbers).size !== numbers.length)
|
|
1310
1325
|
fail2(
|
|
1311
|
-
`"
|
|
1326
|
+
`"boards" must map names to boards on distinct projects, as { "pulse": "agent-pulse", "marketing": 5 } (got ${JSON.stringify(value)})`
|
|
1312
1327
|
);
|
|
1313
|
-
const
|
|
1328
|
+
const boards = {};
|
|
1314
1329
|
const refused = [];
|
|
1315
1330
|
for (const [name, entry] of entries) {
|
|
1316
1331
|
if (isProjectNumber(entry)) {
|
|
1317
|
-
|
|
1332
|
+
boards[name] = entry;
|
|
1318
1333
|
continue;
|
|
1319
1334
|
}
|
|
1320
1335
|
try {
|
|
1321
|
-
|
|
1336
|
+
boards[name] = typeof entry === "string" ? readPresetEntry(name, entry) : parseBoard(name, entry);
|
|
1322
1337
|
} catch (e) {
|
|
1323
1338
|
if (!(e instanceof BoardRefused)) throw e;
|
|
1324
1339
|
refused.push({ name, reason: e.message, source: entry });
|
|
1325
1340
|
}
|
|
1326
1341
|
}
|
|
1327
1342
|
return {
|
|
1328
|
-
|
|
1343
|
+
boards: Object.keys(boards).length === 0 ? null : boards,
|
|
1329
1344
|
refused
|
|
1330
1345
|
};
|
|
1331
1346
|
}
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1347
|
+
var HOLDERS = ["boards", "projects", "pulse"];
|
|
1348
|
+
function readBoardsOrFormer(data) {
|
|
1349
|
+
const present = HOLDERS.filter((k) => data[k] !== void 0);
|
|
1350
|
+
if (present.length > 1)
|
|
1351
|
+
fail2(
|
|
1352
|
+
`${present.map((k) => JSON.stringify(k)).join(" and ")} at once: keep "boards" only`
|
|
1353
|
+
);
|
|
1354
|
+
const key = present[0];
|
|
1355
|
+
if (key === void 0) return { boards: null, refused: [] };
|
|
1356
|
+
if (key === "pulse")
|
|
1357
|
+
return { boards: readPulse(data.pulse), refused: [], formerKey: key };
|
|
1358
|
+
const read = readBoardEntries(data[key]);
|
|
1359
|
+
return key === "boards" ? read : { ...read, formerKey: key };
|
|
1336
1360
|
}
|
|
1337
1361
|
function providerOf(manifest) {
|
|
1338
1362
|
if (manifest.provider !== null) return manifest.provider;
|
|
@@ -1399,34 +1423,36 @@ function parseManifest(raw) {
|
|
|
1399
1423
|
for (const key of Object.keys(data)) {
|
|
1400
1424
|
if (!KEYS.includes(key)) fail2(`unknown key ${JSON.stringify(key)}`);
|
|
1401
1425
|
}
|
|
1402
|
-
const {
|
|
1426
|
+
const { boards, refused, formerKey } = readBoardsOrFormer(data);
|
|
1403
1427
|
return {
|
|
1404
1428
|
contract: 1,
|
|
1405
1429
|
provider: readProvider(data.provider),
|
|
1406
1430
|
org: readOrg(data.org),
|
|
1407
1431
|
agents: readAgents(data.agents),
|
|
1408
|
-
|
|
1432
|
+
boards,
|
|
1409
1433
|
...refused.length === 0 ? {} : { refused },
|
|
1434
|
+
...formerKey === void 0 ? {} : { formerKey },
|
|
1410
1435
|
repos: readRepos(data.repos),
|
|
1411
1436
|
scopes: readScopes(data.scopes)
|
|
1412
1437
|
};
|
|
1413
1438
|
}
|
|
1414
|
-
var
|
|
1415
|
-
|
|
1439
|
+
var boardEntry = (name, value) => ` ${JSON.stringify(name)}: ${JSON.stringify(value, null, 2).replaceAll("\n", "\n ")}`;
|
|
1440
|
+
var isScalar = (v) => typeof v === "number" || typeof v === "string";
|
|
1441
|
+
function boardsLines(manifest) {
|
|
1416
1442
|
const entries = [
|
|
1417
|
-
...Object.entries(manifest.
|
|
1418
|
-
([name,
|
|
1443
|
+
...Object.entries(manifest.boards ?? {}).map(
|
|
1444
|
+
([name, b]) => [name, isScalar(b) ? b : b.source]
|
|
1419
1445
|
),
|
|
1420
1446
|
...(manifest.refused ?? []).map((r) => [r.name, r.source])
|
|
1421
1447
|
];
|
|
1422
1448
|
if (entries.length === 0) return [];
|
|
1423
|
-
if (entries.every(([, v]) =>
|
|
1449
|
+
if (entries.every(([, v]) => isScalar(v)))
|
|
1424
1450
|
return [
|
|
1425
|
-
` "
|
|
1451
|
+
` "boards": { ${entries.map(([name, v]) => `${JSON.stringify(name)}: ${JSON.stringify(v)}`).join(", ")} },`
|
|
1426
1452
|
];
|
|
1427
1453
|
return [
|
|
1428
|
-
' "
|
|
1429
|
-
entries.map(([name, v]) =>
|
|
1454
|
+
' "boards": {',
|
|
1455
|
+
entries.map(([name, v]) => boardEntry(name, v)).join(",\n"),
|
|
1430
1456
|
" },"
|
|
1431
1457
|
];
|
|
1432
1458
|
}
|
|
@@ -1447,7 +1473,7 @@ async function writeManifest(rnessDir, manifest) {
|
|
|
1447
1473
|
lines.push(
|
|
1448
1474
|
` "agents": [${manifest.agents.map((a) => JSON.stringify(a)).join(", ")}],`
|
|
1449
1475
|
);
|
|
1450
|
-
lines.push(...
|
|
1476
|
+
lines.push(...boardsLines(manifest));
|
|
1451
1477
|
lines.push(
|
|
1452
1478
|
' "repos": {',
|
|
1453
1479
|
repos.join(",\n"),
|
|
@@ -1489,7 +1515,7 @@ function parseRepoSpec(spec, org, host) {
|
|
|
1489
1515
|
}
|
|
1490
1516
|
|
|
1491
1517
|
// src/version.ts
|
|
1492
|
-
var VERSION = "0.
|
|
1518
|
+
var VERSION = "0.22.0";
|
|
1493
1519
|
|
|
1494
1520
|
// src/core/pm.ts
|
|
1495
1521
|
import { execFile as execFile2 } from "child_process";
|
|
@@ -1715,7 +1741,7 @@ async function documentsIn(ws, manifest, scope, collections, statuses) {
|
|
|
1715
1741
|
return paths;
|
|
1716
1742
|
}
|
|
1717
1743
|
|
|
1718
|
-
// src/
|
|
1744
|
+
// src/board/urls.ts
|
|
1719
1745
|
var boardUrl = (org, project) => `https://github.com/orgs/${org}/projects/${project}`;
|
|
1720
1746
|
var itemUrl = (org, project, path) => `${boardUrl(org, project)}?filterQuery=${encodeURIComponent(`path:"${path}"`)}`;
|
|
1721
1747
|
var blobUrl = (org, path) => `https://github.com/${org}/.rness/blob/main/${encodeURI(path)}`;
|
|
@@ -3053,7 +3079,7 @@ import { join as join8 } from "path";
|
|
|
3053
3079
|
var GITHUB_CLIENT_ID = "Ov23liv1ia2UWeWttsOK";
|
|
3054
3080
|
var GITHUB_WEB = "https://github.com";
|
|
3055
3081
|
var SCOPES = "repo read:org";
|
|
3056
|
-
var
|
|
3082
|
+
var BOARD_SCOPE = "project";
|
|
3057
3083
|
function clientId() {
|
|
3058
3084
|
return process.env["RNESS_GITHUB_CLIENT_ID"] ?? GITHUB_CLIENT_ID;
|
|
3059
3085
|
}
|
|
@@ -3312,7 +3338,7 @@ async function resolveToken(deps = {}) {
|
|
|
3312
3338
|
return refreshed === null ? null : answer(refreshed);
|
|
3313
3339
|
}
|
|
3314
3340
|
|
|
3315
|
-
// src/
|
|
3341
|
+
// src/board/body.ts
|
|
3316
3342
|
import { createHash } from "crypto";
|
|
3317
3343
|
import { posix as posix4 } from "path";
|
|
3318
3344
|
var BODY_LIMIT = 65536;
|
|
@@ -3462,7 +3488,7 @@ ${content}`;
|
|
|
3462
3488
|
${comment2(digest(text))}`;
|
|
3463
3489
|
}
|
|
3464
3490
|
|
|
3465
|
-
// src/
|
|
3491
|
+
// src/board/collection.ts
|
|
3466
3492
|
import { readFile as readFile5, readdir as readdir2 } from "fs/promises";
|
|
3467
3493
|
import { join as join9 } from "path";
|
|
3468
3494
|
var FIELD_TYPES2 = ["text", "date", "select", "number"];
|
|
@@ -3654,7 +3680,7 @@ async function readUpdates(rnessDir, dir) {
|
|
|
3654
3680
|
return updates;
|
|
3655
3681
|
}
|
|
3656
3682
|
|
|
3657
|
-
// src/
|
|
3683
|
+
// src/board/layout.ts
|
|
3658
3684
|
var statusOf2 = (status2) => status2 === null || status2 === "?" ? null : status2;
|
|
3659
3685
|
var LIFECYCLE = [
|
|
3660
3686
|
"Draft",
|
|
@@ -3873,7 +3899,7 @@ function desiredOf(board, collections, org, fronts = /* @__PURE__ */ new Map(),
|
|
|
3873
3899
|
}));
|
|
3874
3900
|
}
|
|
3875
3901
|
|
|
3876
|
-
// src/
|
|
3902
|
+
// src/board/plan.ts
|
|
3877
3903
|
var lower = (labels) => new Set(labels.map((l) => l.toLowerCase()));
|
|
3878
3904
|
function labelsDiffer(item, w) {
|
|
3879
3905
|
if (w.labels.length === 0 && w.unlabels.length === 0) return false;
|
|
@@ -4093,7 +4119,7 @@ var GitHubBoards = class {
|
|
|
4093
4119
|
const found = await repository(org, MEMORY, LABEL, this.#o);
|
|
4094
4120
|
if (found === null)
|
|
4095
4121
|
throw new Error(
|
|
4096
|
-
`
|
|
4122
|
+
`boards need ${org}/${MEMORY} on GitHub: it is not there, or this login cannot see it`
|
|
4097
4123
|
);
|
|
4098
4124
|
this.#memories.set(org, found);
|
|
4099
4125
|
return found;
|
|
@@ -4101,7 +4127,7 @@ var GitHubBoards = class {
|
|
|
4101
4127
|
async checkIssues(org) {
|
|
4102
4128
|
if (!(await this.#memory(org)).issues)
|
|
4103
4129
|
throw new Error(
|
|
4104
|
-
`
|
|
4130
|
+
`boards need Issues on ${org}/${MEMORY}: turn them on in its Settings`
|
|
4105
4131
|
);
|
|
4106
4132
|
}
|
|
4107
4133
|
/** The project only: the caller declares it before `ensureLayout` builds it. */
|
|
@@ -4602,7 +4628,7 @@ var GitHubBoards = class {
|
|
|
4602
4628
|
const id = (await this.#memory(board.org)).labelId;
|
|
4603
4629
|
if (id === null)
|
|
4604
4630
|
throw new Error(
|
|
4605
|
-
`${board.org}/${MEMORY} has no label ${LABEL}: run rness
|
|
4631
|
+
`${board.org}/${MEMORY} has no label ${LABEL}: run rness board push`
|
|
4606
4632
|
);
|
|
4607
4633
|
return id;
|
|
4608
4634
|
}
|
|
@@ -4739,7 +4765,7 @@ var GitHubOAuthProvider = class {
|
|
|
4739
4765
|
}
|
|
4740
4766
|
#boards() {
|
|
4741
4767
|
if (this.#token === null)
|
|
4742
|
-
throw new Error("
|
|
4768
|
+
throw new Error("boards need a GitHub login: run rness login");
|
|
4743
4769
|
this.#boardClient ??= new GitHubBoards(this.#api(this.#token.token));
|
|
4744
4770
|
return this.#boardClient;
|
|
4745
4771
|
}
|
|
@@ -5406,14 +5432,14 @@ async function loginCommand(opts, deps = {}) {
|
|
|
5406
5432
|
ui.error(unsupportedProviderMessage(manifest.provider));
|
|
5407
5433
|
return 1;
|
|
5408
5434
|
}
|
|
5409
|
-
const needsProject = opts.project === true || manifest?.
|
|
5435
|
+
const needsProject = opts.project === true || manifest?.boards != null;
|
|
5410
5436
|
const bin = deps.bin ?? await realpath2(process.argv[1] ?? "").catch(() => "");
|
|
5411
5437
|
const env = envToken();
|
|
5412
5438
|
if (env !== null)
|
|
5413
5439
|
ui.hint(`${env.source} is set and wins over a stored login`);
|
|
5414
5440
|
const stored = await readAuth();
|
|
5415
5441
|
const resolved = stored === null ? null : await resolveToken();
|
|
5416
|
-
const lacksProject = needsProject && resolved?.source === "login" && !splitScopes(stored?.tokens.scopes ?? "").includes(
|
|
5442
|
+
const lacksProject = needsProject && resolved?.source === "login" && !splitScopes(stored?.tokens.scopes ?? "").includes(BOARD_SCOPE);
|
|
5417
5443
|
if (stored !== null && resolved !== null && !lacksProject) {
|
|
5418
5444
|
ui.line(
|
|
5419
5445
|
"logged in",
|
|
@@ -5425,7 +5451,7 @@ async function loginCommand(opts, deps = {}) {
|
|
|
5425
5451
|
}
|
|
5426
5452
|
if (lacksProject) ui.line("login", "logging in again for the project scope");
|
|
5427
5453
|
const code = await requestDeviceCode(
|
|
5428
|
-
needsProject ? `${SCOPES} ${
|
|
5454
|
+
needsProject ? `${SCOPES} ${BOARD_SCOPE}` : SCOPES
|
|
5429
5455
|
);
|
|
5430
5456
|
if (ui.session)
|
|
5431
5457
|
ui.line(
|
|
@@ -5471,7 +5497,7 @@ async function loginCommand(opts, deps = {}) {
|
|
|
5471
5497
|
}
|
|
5472
5498
|
}
|
|
5473
5499
|
|
|
5474
|
-
// src/
|
|
5500
|
+
// src/board/journal-state.ts
|
|
5475
5501
|
import { mkdir as mkdir2, readFile as readFile7, rename as rename2, rm as rm4, writeFile as writeFile2 } from "fs/promises";
|
|
5476
5502
|
import { dirname as dirname4, join as join12 } from "path";
|
|
5477
5503
|
var notedOf = (value) => {
|
|
@@ -5583,13 +5609,182 @@ async function takeNotices() {
|
|
|
5583
5609
|
return Array.isArray(now) ? now.filter((l) => typeof l === "string") : [];
|
|
5584
5610
|
}
|
|
5585
5611
|
|
|
5586
|
-
// src/commands/
|
|
5612
|
+
// src/commands/board.ts
|
|
5587
5613
|
import { readFile as readFile12, readdir as readdir4 } from "fs/promises";
|
|
5588
5614
|
import { join as join15 } from "path";
|
|
5589
5615
|
import { setTimeout as delay3 } from "timers/promises";
|
|
5590
5616
|
|
|
5617
|
+
// src/board/detached.ts
|
|
5618
|
+
import { spawn as nodeSpawn } from "child_process";
|
|
5619
|
+
import { mkdir as mkdir3, open as open2, readFile as readFile8, rm as rm5, stat as stat2, writeFile as writeFile3 } from "fs/promises";
|
|
5620
|
+
import { join as join13 } from "path";
|
|
5621
|
+
import { setTimeout as delay2 } from "timers/promises";
|
|
5622
|
+
var detached = (args, cwd) => {
|
|
5623
|
+
const bin = process.argv[1];
|
|
5624
|
+
if (bin === void 0) return;
|
|
5625
|
+
const child = nodeSpawn(process.execPath, [bin, ...args], {
|
|
5626
|
+
detached: true,
|
|
5627
|
+
stdio: "ignore",
|
|
5628
|
+
cwd,
|
|
5629
|
+
env: { ...process.env, RNESS_NO_DELEGATE: "1" }
|
|
5630
|
+
});
|
|
5631
|
+
child.on("error", () => void 0);
|
|
5632
|
+
child.unref();
|
|
5633
|
+
};
|
|
5634
|
+
var failureFile = () => join13(configDir(), "board.json");
|
|
5635
|
+
var formerFailureFile = () => join13(configDir(), "pulse.json");
|
|
5636
|
+
async function recordFailure(reason3) {
|
|
5637
|
+
try {
|
|
5638
|
+
await mkdir3(configDir(), { recursive: true, mode: 448 });
|
|
5639
|
+
await writeFile3(
|
|
5640
|
+
failureFile(),
|
|
5641
|
+
`${JSON.stringify({ at: (/* @__PURE__ */ new Date()).toISOString(), reason: reason3 })}
|
|
5642
|
+
`
|
|
5643
|
+
);
|
|
5644
|
+
} catch {
|
|
5645
|
+
}
|
|
5646
|
+
}
|
|
5647
|
+
async function takeFailure() {
|
|
5648
|
+
return await takeFrom(failureFile()) ?? await takeFrom(formerFailureFile());
|
|
5649
|
+
}
|
|
5650
|
+
async function takeFrom(file) {
|
|
5651
|
+
try {
|
|
5652
|
+
const data = JSON.parse(await readFile8(file, "utf8"));
|
|
5653
|
+
await rm5(file, { force: true });
|
|
5654
|
+
const reason3 = data !== null && typeof data === "object" ? data["reason"] : void 0;
|
|
5655
|
+
return typeof reason3 === "string" && reason3 !== "" ? reason3 : null;
|
|
5656
|
+
} catch {
|
|
5657
|
+
return null;
|
|
5658
|
+
}
|
|
5659
|
+
}
|
|
5660
|
+
var LOCK_STALE_MS2 = 15 * 6e4;
|
|
5661
|
+
async function oneSyncAtATime(key, work, options = {}) {
|
|
5662
|
+
await mkdir3(configDir(), { recursive: true, mode: 448 });
|
|
5663
|
+
const file = join13(configDir(), `board-${key}.lock`);
|
|
5664
|
+
for (; ; ) {
|
|
5665
|
+
try {
|
|
5666
|
+
const handle = await open2(file, "wx");
|
|
5667
|
+
await handle.close();
|
|
5668
|
+
break;
|
|
5669
|
+
} catch (e) {
|
|
5670
|
+
if (e.code !== "EEXIST") throw e;
|
|
5671
|
+
const age = await stat2(file).then(
|
|
5672
|
+
(s) => Date.now() - s.mtimeMs,
|
|
5673
|
+
() => 0
|
|
5674
|
+
);
|
|
5675
|
+
if (age > LOCK_STALE_MS2) await rm5(file, { force: true });
|
|
5676
|
+
else if (options.wait !== true) return false;
|
|
5677
|
+
else await (options.sleep ?? ((ms) => delay2(ms)))(1e3);
|
|
5678
|
+
}
|
|
5679
|
+
}
|
|
5680
|
+
try {
|
|
5681
|
+
await work();
|
|
5682
|
+
return true;
|
|
5683
|
+
} finally {
|
|
5684
|
+
await rm5(file, { force: true });
|
|
5685
|
+
}
|
|
5686
|
+
}
|
|
5687
|
+
|
|
5688
|
+
// src/board/noted.ts
|
|
5689
|
+
import { mkdir as mkdir4, readFile as readFile9, rename as rename3, rm as rm6, writeFile as writeFile4 } from "fs/promises";
|
|
5690
|
+
import { dirname as dirname5 } from "path";
|
|
5691
|
+
var NAME2 = "rness/noted";
|
|
5692
|
+
function notedFile(rnessDir) {
|
|
5693
|
+
return gitPath(rnessDir, NAME2);
|
|
5694
|
+
}
|
|
5695
|
+
async function readNoted(file) {
|
|
5696
|
+
if (file === null) return /* @__PURE__ */ new Set();
|
|
5697
|
+
try {
|
|
5698
|
+
const data = JSON.parse(await readFile9(file, "utf8"));
|
|
5699
|
+
return new Set(
|
|
5700
|
+
Array.isArray(data) ? data.filter((l) => typeof l === "string") : []
|
|
5701
|
+
);
|
|
5702
|
+
} catch {
|
|
5703
|
+
return /* @__PURE__ */ new Set();
|
|
5704
|
+
}
|
|
5705
|
+
}
|
|
5706
|
+
async function writeNoted(file, noted) {
|
|
5707
|
+
if (file === null) return;
|
|
5708
|
+
try {
|
|
5709
|
+
if (noted.size === 0) {
|
|
5710
|
+
await rm6(file, { force: true });
|
|
5711
|
+
return;
|
|
5712
|
+
}
|
|
5713
|
+
await mkdir4(dirname5(file), { recursive: true });
|
|
5714
|
+
const temporary = `${file}.${process.pid}`;
|
|
5715
|
+
await writeFile4(
|
|
5716
|
+
temporary,
|
|
5717
|
+
`${JSON.stringify([...noted].sort(), null, 2)}
|
|
5718
|
+
`
|
|
5719
|
+
);
|
|
5720
|
+
await rename3(temporary, file);
|
|
5721
|
+
} catch {
|
|
5722
|
+
}
|
|
5723
|
+
}
|
|
5724
|
+
async function onceSaid(rnessDir, board, lines) {
|
|
5725
|
+
const file = await notedFile(rnessDir);
|
|
5726
|
+
const noted = await readNoted(file);
|
|
5727
|
+
const prefix = `${board}: `;
|
|
5728
|
+
const notes = lines.filter((l) => l.startsWith("note "));
|
|
5729
|
+
const now = new Set(notes.map((l) => `${prefix}${l}`));
|
|
5730
|
+
const said = lines.filter(
|
|
5731
|
+
(l) => !l.startsWith("note ") || !noted.has(`${prefix}${l}`)
|
|
5732
|
+
);
|
|
5733
|
+
const next = /* @__PURE__ */ new Set([
|
|
5734
|
+
...[...noted].filter((l) => !l.startsWith(prefix)),
|
|
5735
|
+
...now
|
|
5736
|
+
]);
|
|
5737
|
+
if (next.size !== noted.size || [...next].some((l) => !noted.has(l)))
|
|
5738
|
+
await writeNoted(file, next);
|
|
5739
|
+
return said;
|
|
5740
|
+
}
|
|
5741
|
+
|
|
5742
|
+
// src/board/opened.ts
|
|
5743
|
+
import { mkdir as mkdir5, readFile as readFile10, rename as rename4, rm as rm7, writeFile as writeFile5 } from "fs/promises";
|
|
5744
|
+
import { dirname as dirname6 } from "path";
|
|
5745
|
+
var NAME3 = "rness/opened";
|
|
5746
|
+
function openedFile(rnessDir) {
|
|
5747
|
+
return gitPath(rnessDir, NAME3);
|
|
5748
|
+
}
|
|
5749
|
+
var NUMBER = /^[1-9][0-9]*$/;
|
|
5750
|
+
async function readOpened(file) {
|
|
5751
|
+
const opened = /* @__PURE__ */ new Map();
|
|
5752
|
+
if (file === null) return opened;
|
|
5753
|
+
let data;
|
|
5754
|
+
try {
|
|
5755
|
+
data = JSON.parse(await readFile10(file, "utf8"));
|
|
5756
|
+
} catch {
|
|
5757
|
+
return opened;
|
|
5758
|
+
}
|
|
5759
|
+
if (data === null || typeof data !== "object" || Array.isArray(data))
|
|
5760
|
+
return opened;
|
|
5761
|
+
for (const [key, path] of Object.entries(data))
|
|
5762
|
+
if (NUMBER.test(key) && typeof path === "string" && path !== "")
|
|
5763
|
+
opened.set(Number(key), path);
|
|
5764
|
+
return opened;
|
|
5765
|
+
}
|
|
5766
|
+
async function writeOpened(file, opened) {
|
|
5767
|
+
if (file === null) return;
|
|
5768
|
+
try {
|
|
5769
|
+
if (opened.size === 0) {
|
|
5770
|
+
await rm7(file, { force: true });
|
|
5771
|
+
return;
|
|
5772
|
+
}
|
|
5773
|
+
const entries = [...opened].sort(([a], [b]) => a - b);
|
|
5774
|
+
await mkdir5(dirname6(file), { recursive: true });
|
|
5775
|
+
const temporary = `${file}.${process.pid}`;
|
|
5776
|
+
await writeFile5(
|
|
5777
|
+
temporary,
|
|
5778
|
+
`${JSON.stringify(Object.fromEntries(entries), null, 2)}
|
|
5779
|
+
`
|
|
5780
|
+
);
|
|
5781
|
+
await rename4(temporary, file);
|
|
5782
|
+
} catch {
|
|
5783
|
+
}
|
|
5784
|
+
}
|
|
5785
|
+
|
|
5591
5786
|
// src/core/board-migration.ts
|
|
5592
|
-
import { readFile as
|
|
5787
|
+
import { readFile as readFile11 } from "fs/promises";
|
|
5593
5788
|
import { parseDocument } from "yaml";
|
|
5594
5789
|
|
|
5595
5790
|
// src/core/board-merge.ts
|
|
@@ -5667,7 +5862,7 @@ function mergeViews(at, base, ours, theirs, ref, kept) {
|
|
|
5667
5862
|
return merged;
|
|
5668
5863
|
}
|
|
5669
5864
|
function mergeBoard(name, base, ours, theirs, ref) {
|
|
5670
|
-
const at = `
|
|
5865
|
+
const at = `boards.${name}`;
|
|
5671
5866
|
const kept = [];
|
|
5672
5867
|
const { number, preset: _, ...team } = ours;
|
|
5673
5868
|
const keys = [
|
|
@@ -5699,8 +5894,8 @@ function mergeBoard(name, base, ours, theirs, ref) {
|
|
|
5699
5894
|
}
|
|
5700
5895
|
|
|
5701
5896
|
// src/core/preset-board.ts
|
|
5702
|
-
import { stat as
|
|
5703
|
-
import { join as
|
|
5897
|
+
import { stat as stat3 } from "fs/promises";
|
|
5898
|
+
import { join as join14 } from "path";
|
|
5704
5899
|
var ORDER = [
|
|
5705
5900
|
"number",
|
|
5706
5901
|
"preset",
|
|
@@ -5722,30 +5917,30 @@ var ordered = (board) => Object.fromEntries(
|
|
|
5722
5917
|
);
|
|
5723
5918
|
async function exists2(path) {
|
|
5724
5919
|
try {
|
|
5725
|
-
await
|
|
5920
|
+
await stat3(path);
|
|
5726
5921
|
return true;
|
|
5727
5922
|
} catch {
|
|
5728
5923
|
return false;
|
|
5729
5924
|
}
|
|
5730
5925
|
}
|
|
5731
|
-
async function presetSource(name, rnessDir, number) {
|
|
5732
|
-
|
|
5733
|
-
|
|
5926
|
+
async function presetSource(name, rnessDir, number, ref) {
|
|
5927
|
+
const kind = presetFor(name);
|
|
5928
|
+
const preset = ref?.includes("/") === true ? ref : currentPreset(kind);
|
|
5929
|
+
const numbered = number === null ? {} : { number };
|
|
5930
|
+
if (name === PULSE)
|
|
5734
5931
|
return ordered({
|
|
5735
|
-
|
|
5736
|
-
preset
|
|
5737
|
-
...presetTemplate(
|
|
5932
|
+
...numbered,
|
|
5933
|
+
preset,
|
|
5934
|
+
...presetTemplate(preset, { collection: name })
|
|
5738
5935
|
});
|
|
5739
|
-
}
|
|
5740
|
-
const preset = currentPreset("collection");
|
|
5741
5936
|
const board = {
|
|
5742
|
-
|
|
5937
|
+
...numbered,
|
|
5743
5938
|
preset,
|
|
5744
5939
|
...presetTemplate(preset, { collection: name })
|
|
5745
5940
|
};
|
|
5746
|
-
if (await exists2(
|
|
5941
|
+
if (await exists2(join14(rnessDir, name, "README.md")))
|
|
5747
5942
|
board["readme"] = `${name}/README.md`;
|
|
5748
|
-
if (await exists2(
|
|
5943
|
+
if (await exists2(join14(rnessDir, name, "updates")))
|
|
5749
5944
|
board["updates"] = `${name}/updates`;
|
|
5750
5945
|
const shape = await readShape(rnessDir, name);
|
|
5751
5946
|
if (shape.description !== null) board["description"] = shape.description;
|
|
@@ -5777,23 +5972,24 @@ async function presetSource(name, rnessDir, number) {
|
|
|
5777
5972
|
return ordered(board);
|
|
5778
5973
|
}
|
|
5779
5974
|
async function declaredBoard(name, entry, rnessDir) {
|
|
5780
|
-
if (typeof entry
|
|
5781
|
-
|
|
5975
|
+
if (typeof entry === "number")
|
|
5976
|
+
return parseBoard(name, await presetSource(name, rnessDir, entry));
|
|
5977
|
+
if (typeof entry === "string")
|
|
5978
|
+
return parseBoard(name, await presetSource(name, rnessDir, null, entry));
|
|
5979
|
+
return entry;
|
|
5782
5980
|
}
|
|
5783
5981
|
async function readBoards(rnessDir) {
|
|
5784
|
-
let
|
|
5982
|
+
let declared;
|
|
5785
5983
|
try {
|
|
5786
|
-
|
|
5984
|
+
declared = (await loadManifest(rnessDir)).boards ?? {};
|
|
5787
5985
|
} catch {
|
|
5788
5986
|
return [];
|
|
5789
5987
|
}
|
|
5790
5988
|
const boards = [];
|
|
5791
|
-
for (const [name, entry] of Object.entries(
|
|
5989
|
+
for (const [name, entry] of Object.entries(declared))
|
|
5792
5990
|
try {
|
|
5793
|
-
|
|
5794
|
-
|
|
5795
|
-
declaration: await declaredBoard(name, entry, rnessDir)
|
|
5796
|
-
});
|
|
5991
|
+
const declaration = await declaredBoard(name, entry, rnessDir);
|
|
5992
|
+
if (declaration.number !== null) boards.push({ name, declaration });
|
|
5797
5993
|
} catch {
|
|
5798
5994
|
}
|
|
5799
5995
|
return boards;
|
|
@@ -5814,7 +6010,7 @@ var BUNDLED = {
|
|
|
5814
6010
|
var README = (collection) => `${collection}/README.md`;
|
|
5815
6011
|
async function readmeOf(rnessDir, collection) {
|
|
5816
6012
|
try {
|
|
5817
|
-
return await
|
|
6013
|
+
return await readFile11(
|
|
5818
6014
|
await containedPath(rnessDir, README(collection)),
|
|
5819
6015
|
"utf8"
|
|
5820
6016
|
);
|
|
@@ -5887,20 +6083,31 @@ function moveInto(name, collection, source, declared) {
|
|
|
5887
6083
|
conflicts.push(`fields.${field}`);
|
|
5888
6084
|
}
|
|
5889
6085
|
if (conflicts.length > 0)
|
|
5890
|
-
return `${README(collection)} declares ${conflicts.join(", ")} otherwise than
|
|
6086
|
+
return `${README(collection)} declares ${conflicts.join(", ")} otherwise than boards.${name}: keep one, in rness.json`;
|
|
5891
6087
|
source["fields"] = fields2;
|
|
5892
6088
|
return null;
|
|
5893
6089
|
}
|
|
5894
6090
|
async function migrateBoards(rnessDir, manifest, presets = BUNDLED) {
|
|
5895
6091
|
const migration = {
|
|
5896
6092
|
changed: false,
|
|
5897
|
-
|
|
6093
|
+
boards: manifest.boards,
|
|
5898
6094
|
readmes: /* @__PURE__ */ new Map(),
|
|
5899
6095
|
lines: []
|
|
5900
6096
|
};
|
|
5901
|
-
if (manifest.
|
|
5902
|
-
|
|
5903
|
-
|
|
6097
|
+
if (manifest.formerKey !== void 0) {
|
|
6098
|
+
migration.lines.push([
|
|
6099
|
+
"renamed",
|
|
6100
|
+
`${manifest.formerKey} to boards in .rness/rness.json`
|
|
6101
|
+
]);
|
|
6102
|
+
migration.changed = true;
|
|
6103
|
+
}
|
|
6104
|
+
if (manifest.boards === null) return migration;
|
|
6105
|
+
const boards = {};
|
|
6106
|
+
for (const [name, entry] of Object.entries(manifest.boards)) {
|
|
6107
|
+
if (typeof entry === "string") {
|
|
6108
|
+
boards[name] = entry;
|
|
6109
|
+
continue;
|
|
6110
|
+
}
|
|
5904
6111
|
let source;
|
|
5905
6112
|
if (typeof entry === "number") {
|
|
5906
6113
|
source = await presetSource(name, rnessDir, entry);
|
|
@@ -5950,186 +6157,21 @@ async function migrateBoards(rnessDir, manifest, presets = BUNDLED) {
|
|
|
5950
6157
|
}
|
|
5951
6158
|
}
|
|
5952
6159
|
try {
|
|
5953
|
-
|
|
6160
|
+
boards[name] = typeof entry === "number" || migration.changed ? parseBoard(name, source, presets.knows) : entry;
|
|
5954
6161
|
} catch (e) {
|
|
5955
6162
|
if (!(e instanceof BoardRefused)) throw e;
|
|
5956
6163
|
migration.lines.push(["refused", e.message]);
|
|
5957
|
-
|
|
6164
|
+
boards[name] = entry;
|
|
5958
6165
|
}
|
|
5959
6166
|
}
|
|
5960
|
-
migration.
|
|
6167
|
+
migration.boards = boards;
|
|
5961
6168
|
return migration;
|
|
5962
6169
|
}
|
|
5963
6170
|
|
|
5964
|
-
// src/
|
|
5965
|
-
import { spawn as nodeSpawn } from "child_process";
|
|
5966
|
-
import { mkdir as mkdir3, open as open2, readFile as readFile9, rm as rm5, stat as stat3, writeFile as writeFile3 } from "fs/promises";
|
|
5967
|
-
import { join as join14 } from "path";
|
|
5968
|
-
import { setTimeout as delay2 } from "timers/promises";
|
|
5969
|
-
var detached = (args, cwd) => {
|
|
5970
|
-
const bin = process.argv[1];
|
|
5971
|
-
if (bin === void 0) return;
|
|
5972
|
-
const child = nodeSpawn(process.execPath, [bin, ...args], {
|
|
5973
|
-
detached: true,
|
|
5974
|
-
stdio: "ignore",
|
|
5975
|
-
cwd,
|
|
5976
|
-
env: { ...process.env, RNESS_NO_DELEGATE: "1" }
|
|
5977
|
-
});
|
|
5978
|
-
child.on("error", () => void 0);
|
|
5979
|
-
child.unref();
|
|
5980
|
-
};
|
|
5981
|
-
var failureFile = () => join14(configDir(), "pulse.json");
|
|
5982
|
-
async function recordFailure(reason3) {
|
|
5983
|
-
try {
|
|
5984
|
-
await mkdir3(configDir(), { recursive: true, mode: 448 });
|
|
5985
|
-
await writeFile3(
|
|
5986
|
-
failureFile(),
|
|
5987
|
-
`${JSON.stringify({ at: (/* @__PURE__ */ new Date()).toISOString(), reason: reason3 })}
|
|
5988
|
-
`
|
|
5989
|
-
);
|
|
5990
|
-
} catch {
|
|
5991
|
-
}
|
|
5992
|
-
}
|
|
5993
|
-
async function takeFailure() {
|
|
5994
|
-
try {
|
|
5995
|
-
const data = JSON.parse(await readFile9(failureFile(), "utf8"));
|
|
5996
|
-
await rm5(failureFile(), { force: true });
|
|
5997
|
-
const reason3 = data !== null && typeof data === "object" ? data["reason"] : void 0;
|
|
5998
|
-
return typeof reason3 === "string" && reason3 !== "" ? reason3 : null;
|
|
5999
|
-
} catch {
|
|
6000
|
-
return null;
|
|
6001
|
-
}
|
|
6002
|
-
}
|
|
6003
|
-
var PULSE_LOCK_STALE_MS = 15 * 6e4;
|
|
6004
|
-
async function oneSyncAtATime(key, work, options = {}) {
|
|
6005
|
-
await mkdir3(configDir(), { recursive: true, mode: 448 });
|
|
6006
|
-
const file = join14(configDir(), `pulse-${key}.lock`);
|
|
6007
|
-
for (; ; ) {
|
|
6008
|
-
try {
|
|
6009
|
-
const handle = await open2(file, "wx");
|
|
6010
|
-
await handle.close();
|
|
6011
|
-
break;
|
|
6012
|
-
} catch (e) {
|
|
6013
|
-
if (e.code !== "EEXIST") throw e;
|
|
6014
|
-
const age = await stat3(file).then(
|
|
6015
|
-
(s) => Date.now() - s.mtimeMs,
|
|
6016
|
-
() => 0
|
|
6017
|
-
);
|
|
6018
|
-
if (age > PULSE_LOCK_STALE_MS) await rm5(file, { force: true });
|
|
6019
|
-
else if (options.wait !== true) return false;
|
|
6020
|
-
else await (options.sleep ?? ((ms) => delay2(ms)))(1e3);
|
|
6021
|
-
}
|
|
6022
|
-
}
|
|
6023
|
-
try {
|
|
6024
|
-
await work();
|
|
6025
|
-
return true;
|
|
6026
|
-
} finally {
|
|
6027
|
-
await rm5(file, { force: true });
|
|
6028
|
-
}
|
|
6029
|
-
}
|
|
6030
|
-
|
|
6031
|
-
// src/pulse/noted.ts
|
|
6032
|
-
import { mkdir as mkdir4, readFile as readFile10, rename as rename3, rm as rm6, writeFile as writeFile4 } from "fs/promises";
|
|
6033
|
-
import { dirname as dirname5 } from "path";
|
|
6034
|
-
var NAME2 = "rness/noted";
|
|
6035
|
-
function notedFile(rnessDir) {
|
|
6036
|
-
return gitPath(rnessDir, NAME2);
|
|
6037
|
-
}
|
|
6038
|
-
async function readNoted(file) {
|
|
6039
|
-
if (file === null) return /* @__PURE__ */ new Set();
|
|
6040
|
-
try {
|
|
6041
|
-
const data = JSON.parse(await readFile10(file, "utf8"));
|
|
6042
|
-
return new Set(
|
|
6043
|
-
Array.isArray(data) ? data.filter((l) => typeof l === "string") : []
|
|
6044
|
-
);
|
|
6045
|
-
} catch {
|
|
6046
|
-
return /* @__PURE__ */ new Set();
|
|
6047
|
-
}
|
|
6048
|
-
}
|
|
6049
|
-
async function writeNoted(file, noted) {
|
|
6050
|
-
if (file === null) return;
|
|
6051
|
-
try {
|
|
6052
|
-
if (noted.size === 0) {
|
|
6053
|
-
await rm6(file, { force: true });
|
|
6054
|
-
return;
|
|
6055
|
-
}
|
|
6056
|
-
await mkdir4(dirname5(file), { recursive: true });
|
|
6057
|
-
const temporary = `${file}.${process.pid}`;
|
|
6058
|
-
await writeFile4(
|
|
6059
|
-
temporary,
|
|
6060
|
-
`${JSON.stringify([...noted].sort(), null, 2)}
|
|
6061
|
-
`
|
|
6062
|
-
);
|
|
6063
|
-
await rename3(temporary, file);
|
|
6064
|
-
} catch {
|
|
6065
|
-
}
|
|
6066
|
-
}
|
|
6067
|
-
async function onceSaid(rnessDir, board, lines) {
|
|
6068
|
-
const file = await notedFile(rnessDir);
|
|
6069
|
-
const noted = await readNoted(file);
|
|
6070
|
-
const prefix = `${board}: `;
|
|
6071
|
-
const notes = lines.filter((l) => l.startsWith("note "));
|
|
6072
|
-
const now = new Set(notes.map((l) => `${prefix}${l}`));
|
|
6073
|
-
const said = lines.filter(
|
|
6074
|
-
(l) => !l.startsWith("note ") || !noted.has(`${prefix}${l}`)
|
|
6075
|
-
);
|
|
6076
|
-
const next = /* @__PURE__ */ new Set([
|
|
6077
|
-
...[...noted].filter((l) => !l.startsWith(prefix)),
|
|
6078
|
-
...now
|
|
6079
|
-
]);
|
|
6080
|
-
if (next.size !== noted.size || [...next].some((l) => !noted.has(l)))
|
|
6081
|
-
await writeNoted(file, next);
|
|
6082
|
-
return said;
|
|
6083
|
-
}
|
|
6084
|
-
|
|
6085
|
-
// src/pulse/opened.ts
|
|
6086
|
-
import { mkdir as mkdir5, readFile as readFile11, rename as rename4, rm as rm7, writeFile as writeFile5 } from "fs/promises";
|
|
6087
|
-
import { dirname as dirname6 } from "path";
|
|
6088
|
-
var NAME3 = "rness/opened";
|
|
6089
|
-
function openedFile(rnessDir) {
|
|
6090
|
-
return gitPath(rnessDir, NAME3);
|
|
6091
|
-
}
|
|
6092
|
-
var NUMBER = /^[1-9][0-9]*$/;
|
|
6093
|
-
async function readOpened(file) {
|
|
6094
|
-
const opened = /* @__PURE__ */ new Map();
|
|
6095
|
-
if (file === null) return opened;
|
|
6096
|
-
let data;
|
|
6097
|
-
try {
|
|
6098
|
-
data = JSON.parse(await readFile11(file, "utf8"));
|
|
6099
|
-
} catch {
|
|
6100
|
-
return opened;
|
|
6101
|
-
}
|
|
6102
|
-
if (data === null || typeof data !== "object" || Array.isArray(data))
|
|
6103
|
-
return opened;
|
|
6104
|
-
for (const [key, path] of Object.entries(data))
|
|
6105
|
-
if (NUMBER.test(key) && typeof path === "string" && path !== "")
|
|
6106
|
-
opened.set(Number(key), path);
|
|
6107
|
-
return opened;
|
|
6108
|
-
}
|
|
6109
|
-
async function writeOpened(file, opened) {
|
|
6110
|
-
if (file === null) return;
|
|
6111
|
-
try {
|
|
6112
|
-
if (opened.size === 0) {
|
|
6113
|
-
await rm7(file, { force: true });
|
|
6114
|
-
return;
|
|
6115
|
-
}
|
|
6116
|
-
const entries = [...opened].sort(([a], [b]) => a - b);
|
|
6117
|
-
await mkdir5(dirname6(file), { recursive: true });
|
|
6118
|
-
const temporary = `${file}.${process.pid}`;
|
|
6119
|
-
await writeFile5(
|
|
6120
|
-
temporary,
|
|
6121
|
-
`${JSON.stringify(Object.fromEntries(entries), null, 2)}
|
|
6122
|
-
`
|
|
6123
|
-
);
|
|
6124
|
-
await rename4(temporary, file);
|
|
6125
|
-
} catch {
|
|
6126
|
-
}
|
|
6127
|
-
}
|
|
6128
|
-
|
|
6129
|
-
// src/commands/pulse.ts
|
|
6171
|
+
// src/commands/board.ts
|
|
6130
6172
|
var PROJECT_SCOPE = "project";
|
|
6131
|
-
var NEEDS_LOGIN = "
|
|
6132
|
-
var NEEDS_SCOPE = "
|
|
6173
|
+
var NEEDS_LOGIN = "boards need a GitHub login: run rness login";
|
|
6174
|
+
var NEEDS_SCOPE = "boards need the project scope: run rness login";
|
|
6133
6175
|
async function fromGithub(work) {
|
|
6134
6176
|
try {
|
|
6135
6177
|
return await work;
|
|
@@ -6149,7 +6191,7 @@ async function context(opts, wait) {
|
|
|
6149
6191
|
const manifest = await loadManifest(ws.rnessDir);
|
|
6150
6192
|
const provider = await openProvider(manifest, providerOptions(opts, wait));
|
|
6151
6193
|
if (manifest.org === null)
|
|
6152
|
-
throw new Error('
|
|
6194
|
+
throw new Error('boards need an organization: rness.json has no "org"');
|
|
6153
6195
|
return {
|
|
6154
6196
|
root: ws.root,
|
|
6155
6197
|
rnessDir: ws.rnessDir,
|
|
@@ -6167,17 +6209,19 @@ async function missingAccess(provider) {
|
|
|
6167
6209
|
const scopes = await fromGithub(provider.scopes());
|
|
6168
6210
|
return scopes?.includes(PROJECT_SCOPE) === true ? null : NEEDS_SCOPE;
|
|
6169
6211
|
}
|
|
6212
|
+
var isCreated = (d) => d.number !== null;
|
|
6170
6213
|
var takesAll = (d) => d.declaration.collections === "all";
|
|
6171
6214
|
var namedCollections = (d) => d.collections === "all" ? [] : Object.keys(d.collections);
|
|
6172
6215
|
async function declarations(c, ui) {
|
|
6173
|
-
const
|
|
6216
|
+
const boards = c.manifest.boards ?? {};
|
|
6174
6217
|
for (const r of c.manifest.refused ?? [])
|
|
6175
6218
|
ui?.line("skipped", `${r.name}: ${r.reason}`);
|
|
6176
6219
|
const all = [];
|
|
6177
|
-
|
|
6220
|
+
const notCreated = [];
|
|
6221
|
+
for (const [name, entry] of Object.entries(boards)) {
|
|
6178
6222
|
const declaration = await declaredBoard(name, entry, c.rnessDir);
|
|
6179
6223
|
const still = [];
|
|
6180
|
-
if (typeof entry
|
|
6224
|
+
if (typeof entry === "object")
|
|
6181
6225
|
for (const collection of namedCollections(declaration)) {
|
|
6182
6226
|
const keys = Object.keys(
|
|
6183
6227
|
await readmeDeclarations(c.rnessDir, collection)
|
|
@@ -6192,19 +6236,28 @@ async function declarations(c, ui) {
|
|
|
6192
6236
|
);
|
|
6193
6237
|
continue;
|
|
6194
6238
|
}
|
|
6195
|
-
all.push({ name, declaration });
|
|
6239
|
+
if (isCreated(declaration)) all.push({ name, declaration });
|
|
6240
|
+
else if (typeof entry !== "number")
|
|
6241
|
+
notCreated.push({ name, entry, declaration });
|
|
6196
6242
|
}
|
|
6197
|
-
return
|
|
6243
|
+
return {
|
|
6244
|
+
created: all.sort((a, b) => Number(takesAll(a)) - Number(takesAll(b))),
|
|
6245
|
+
notCreated
|
|
6246
|
+
};
|
|
6247
|
+
}
|
|
6248
|
+
function noBoard(c) {
|
|
6249
|
+
return new Error(
|
|
6250
|
+
c.manifest.refused === void 0 ? 'no board declared \u2014 declare one in .rness/rness.json, as "boards": { "pulse": "agent-pulse" }, then rness board push' : `no board rness.json declares is valid: ${c.manifest.refused.map((r) => r.reason).join("; ")}`
|
|
6251
|
+
);
|
|
6198
6252
|
}
|
|
6199
6253
|
async function declaredBoards(c, ui) {
|
|
6200
|
-
if (c.manifest.
|
|
6201
|
-
|
|
6202
|
-
|
|
6203
|
-
);
|
|
6254
|
+
if (c.manifest.boards === null) throw noBoard(c);
|
|
6255
|
+
const { created } = await declarations(c, ui);
|
|
6256
|
+
if (created.length === 0) return [];
|
|
6204
6257
|
const missing = await missingAccess(c.provider);
|
|
6205
6258
|
if (missing !== null) throw new Error(missing);
|
|
6206
6259
|
const declared = [];
|
|
6207
|
-
for (const { name, declaration } of
|
|
6260
|
+
for (const { name, declaration } of created) {
|
|
6208
6261
|
const board = await fromGithub(c.provider.board(c.org, declaration.number));
|
|
6209
6262
|
if (board === null)
|
|
6210
6263
|
throw new Error(`GitHub has no project ${declaration.number} in ${c.org}`);
|
|
@@ -6442,7 +6495,7 @@ async function syncBoard(c, board, ui, sayLayout, scope) {
|
|
|
6442
6495
|
if (!(e instanceof RateLimitError)) throw e;
|
|
6443
6496
|
const total = changes + writes.length;
|
|
6444
6497
|
throw new Error(
|
|
6445
|
-
`${e.message}: ${total - made} of ${total} changes not made \u2014 the next rness
|
|
6498
|
+
`${e.message}: ${total - made} of ${total} changes not made \u2014 the next rness board push makes them`,
|
|
6446
6499
|
{ cause: e }
|
|
6447
6500
|
);
|
|
6448
6501
|
}
|
|
@@ -6470,125 +6523,131 @@ async function syncAll(c, declared, ui, sayLayout) {
|
|
|
6470
6523
|
);
|
|
6471
6524
|
}
|
|
6472
6525
|
}
|
|
6473
|
-
async function
|
|
6474
|
-
|
|
6475
|
-
|
|
6476
|
-
|
|
6477
|
-
|
|
6478
|
-
|
|
6479
|
-
|
|
6480
|
-
|
|
6481
|
-
|
|
6482
|
-
|
|
6483
|
-
|
|
6484
|
-
|
|
6485
|
-
|
|
6486
|
-
|
|
6487
|
-
|
|
6488
|
-
if (refused !== void 0)
|
|
6489
|
-
throw new Error(`already declared, and refused: ${refused.reason}`);
|
|
6490
|
-
const tab = opts.collection === void 0 ? null : (await statusTabs(c.rnessDir)).find(
|
|
6491
|
-
(t) => t.name === opts.collection
|
|
6492
|
-
) ?? null;
|
|
6493
|
-
if (opts.collection !== void 0 && tab === null)
|
|
6494
|
-
throw new Error(
|
|
6495
|
-
`${opts.collection} is no collection of .rness: none of its documents carries a status`
|
|
6496
|
-
);
|
|
6497
|
-
const detected = providerOf(c.manifest);
|
|
6498
|
-
if (!PROVIDERS[detected].available)
|
|
6499
|
-
throw new Error(
|
|
6500
|
-
`the pulse needs a GitHub organization, and this workspace's repositories look like ${detected} (detected): write "provider": "github" in rness.json if the organization is on GitHub`
|
|
6501
|
-
);
|
|
6502
|
-
const missing = await missingAccess(c.provider);
|
|
6503
|
-
if (missing !== null) {
|
|
6504
|
-
if (opts.yes === true || !terminal.isTty()) throw new Error(missing);
|
|
6505
|
-
const p = await terminal.prompts();
|
|
6506
|
-
const ok = await p.confirm({
|
|
6507
|
-
message: missing === NEEDS_LOGIN ? "The pulse needs a GitHub login with the project scope. Log in now?" : "The pulse needs the project scope of your GitHub login. Log in again to grant it?"
|
|
6508
|
-
});
|
|
6509
|
-
if (p.isCancel(ok) || ok !== true) throw new Error(missing);
|
|
6510
|
-
const code = await loginCommand(
|
|
6511
|
-
{
|
|
6512
|
-
project: true,
|
|
6513
|
-
// The git question is `rness login`'s own, not the pulse's to ask.
|
|
6514
|
-
setupGit: false,
|
|
6515
|
-
...opts.githubApi === void 0 ? {} : { githubApi: opts.githubApi }
|
|
6516
|
-
},
|
|
6517
|
-
{ terminal, ui, ...opts.cwd === void 0 ? {} : { cwd: opts.cwd } }
|
|
6518
|
-
);
|
|
6519
|
-
if (code !== 0) return code;
|
|
6520
|
-
c = {
|
|
6521
|
-
...c,
|
|
6522
|
-
provider: await openProvider(c.manifest, providerOptions(opts, wait))
|
|
6523
|
-
};
|
|
6524
|
-
const still = await missingAccess(c.provider);
|
|
6525
|
-
if (still !== null) throw new Error(still);
|
|
6526
|
-
}
|
|
6527
|
-
await fromGithub(c.provider.checkIssues(c.org));
|
|
6528
|
-
const login = (await c.provider.identity())?.login ?? "unknown";
|
|
6529
|
-
ui.line(
|
|
6530
|
-
"checked",
|
|
6531
|
-
`${detected}, logged in as ${login}, scope ${PROJECT_SCOPE}`
|
|
6526
|
+
async function checkBoardName(rnessDir, name) {
|
|
6527
|
+
if (name === PULSE) return;
|
|
6528
|
+
const tabs = await statusTabs(rnessDir);
|
|
6529
|
+
if (!tabs.some((t) => t.name === name))
|
|
6530
|
+
throw new Error(
|
|
6531
|
+
`"boards.${name}": ${name} is no collection of .rness: none of its documents carries a status`
|
|
6532
|
+
);
|
|
6533
|
+
}
|
|
6534
|
+
var titleOf = (b) => b.declaration.title ?? labelOf(b.name);
|
|
6535
|
+
async function createBoards(c, boards, opts, terminal, ui, wait) {
|
|
6536
|
+
for (const b of boards) await checkBoardName(c.rnessDir, b.name);
|
|
6537
|
+
const detected = providerOf(c.manifest);
|
|
6538
|
+
if (!PROVIDERS[detected].available)
|
|
6539
|
+
throw new Error(
|
|
6540
|
+
`boards need a GitHub organization, and this workspace's repositories look like ${detected} (detected): write "provider": "github" in rness.json if the organization is on GitHub`
|
|
6532
6541
|
);
|
|
6533
|
-
|
|
6534
|
-
|
|
6535
|
-
|
|
6542
|
+
const names = boards.map((b) => b.name);
|
|
6543
|
+
if (opts.confirmed !== true && opts.yes !== true) {
|
|
6544
|
+
if (!terminal.isTty()) return { c, made: [], left: names };
|
|
6545
|
+
const p = await terminal.prompts();
|
|
6546
|
+
const ok = await p.confirm({
|
|
6547
|
+
message: `Create ${boards.map((b) => `${titleOf(b)} (${b.name})`).join(", ")} on GitHub, in ${c.org}?`
|
|
6548
|
+
});
|
|
6549
|
+
if (p.isCancel(ok) || ok !== true) return { c, made: [], left: names };
|
|
6550
|
+
}
|
|
6551
|
+
const missing = await missingAccess(c.provider);
|
|
6552
|
+
if (missing !== null) {
|
|
6553
|
+
if (opts.yes === true || !terminal.isTty()) throw new Error(missing);
|
|
6554
|
+
const p = await terminal.prompts();
|
|
6555
|
+
const ok = await p.confirm({
|
|
6556
|
+
message: missing === NEEDS_LOGIN ? "Boards need a GitHub login with the project scope. Log in now?" : "Boards need the project scope of your GitHub login. Log in again to grant it?"
|
|
6557
|
+
});
|
|
6558
|
+
if (p.isCancel(ok) || ok !== true) throw new Error(missing);
|
|
6559
|
+
const code = await loginCommand(
|
|
6560
|
+
{
|
|
6561
|
+
project: true,
|
|
6562
|
+
// The git question is `rness login`'s own, not the board's to ask.
|
|
6563
|
+
setupGit: false,
|
|
6564
|
+
...opts.githubApi === void 0 ? {} : { githubApi: opts.githubApi }
|
|
6565
|
+
},
|
|
6566
|
+
{ terminal, ui, ...opts.cwd === void 0 ? {} : { cwd: opts.cwd } }
|
|
6567
|
+
);
|
|
6568
|
+
if (code !== 0) throw new Error(missing);
|
|
6569
|
+
c = {
|
|
6570
|
+
...c,
|
|
6571
|
+
provider: await openProvider(c.manifest, providerOptions(opts, wait))
|
|
6572
|
+
};
|
|
6573
|
+
const still = await missingAccess(c.provider);
|
|
6574
|
+
if (still !== null) throw new Error(still);
|
|
6575
|
+
}
|
|
6576
|
+
await fromGithub(c.provider.checkIssues(c.org));
|
|
6577
|
+
const login = (await c.provider.identity())?.login ?? "unknown";
|
|
6578
|
+
ui.line(
|
|
6579
|
+
"checked",
|
|
6580
|
+
`${detected}, logged in as ${login}, scope ${PROJECT_SCOPE}`
|
|
6581
|
+
);
|
|
6582
|
+
const made = [];
|
|
6583
|
+
for (const b of boards) {
|
|
6584
|
+
const source = typeof b.entry === "string" ? await presetSource(b.name, c.rnessDir, null, b.entry) : b.declaration.source;
|
|
6585
|
+
const readme = typeof b.entry === "string" && b.name !== PULSE ? await readmeText(c.rnessDir, b.name) : null;
|
|
6586
|
+
const title = titleOf(b);
|
|
6536
6587
|
const board = await fromGithub(c.provider.createBoard(c.org, title));
|
|
6537
6588
|
const manifest = {
|
|
6538
6589
|
...c.manifest,
|
|
6539
6590
|
provider: detected,
|
|
6540
|
-
|
|
6541
|
-
...c.manifest.
|
|
6542
|
-
[name]: parseBoard(name, {
|
|
6591
|
+
boards: {
|
|
6592
|
+
...c.manifest.boards,
|
|
6593
|
+
[b.name]: parseBoard(b.name, { number: board.number, ...source })
|
|
6543
6594
|
}
|
|
6544
6595
|
};
|
|
6545
6596
|
await writeManifest(c.rnessDir, manifest);
|
|
6546
|
-
if (readme !== null
|
|
6597
|
+
if (readme !== null) {
|
|
6547
6598
|
const cleaned = withoutDeclarations(readme);
|
|
6548
6599
|
if (cleaned !== readme)
|
|
6549
|
-
await writeFileAtomic(
|
|
6550
|
-
join15(c.rnessDir, opts.collection, "README.md"),
|
|
6551
|
-
cleaned
|
|
6552
|
-
);
|
|
6600
|
+
await writeFileAtomic(join15(c.rnessDir, b.name, "README.md"), cleaned);
|
|
6553
6601
|
}
|
|
6554
6602
|
c = { ...c, manifest };
|
|
6603
|
+
made.push(b.name);
|
|
6555
6604
|
ui.line("created", `${title} \u2014 ${board.url}`);
|
|
6605
|
+
}
|
|
6606
|
+
return { c, made, left: [] };
|
|
6607
|
+
}
|
|
6608
|
+
async function boardPushCommand(opts, deps = {}) {
|
|
6609
|
+
try {
|
|
6610
|
+
const terminal = deps.terminal ?? defaultTerminal;
|
|
6611
|
+
const ui = deps.ui ?? await makeUi(terminal);
|
|
6612
|
+
const wait = waitSaid(opts, ui);
|
|
6613
|
+
let c = await context(opts, wait);
|
|
6614
|
+
if (c.manifest.boards === null) throw noBoard(c);
|
|
6615
|
+
const { notCreated } = await declarations(c, ui);
|
|
6616
|
+
let made = [];
|
|
6617
|
+
let left = [];
|
|
6618
|
+
if (notCreated.length > 0)
|
|
6619
|
+
({ c, made, left } = await createBoards(
|
|
6620
|
+
c,
|
|
6621
|
+
notCreated,
|
|
6622
|
+
opts,
|
|
6623
|
+
terminal,
|
|
6624
|
+
ui,
|
|
6625
|
+
wait
|
|
6626
|
+
));
|
|
6556
6627
|
try {
|
|
6628
|
+
const declared = await declaredBoards(c);
|
|
6557
6629
|
await syncAll(
|
|
6558
6630
|
c,
|
|
6559
|
-
|
|
6631
|
+
declared,
|
|
6560
6632
|
ui,
|
|
6561
|
-
(n) => n
|
|
6633
|
+
(n) => made.includes(n) ? createdByKind : eachAdded
|
|
6562
6634
|
);
|
|
6563
6635
|
} finally {
|
|
6564
|
-
|
|
6565
|
-
|
|
6566
|
-
|
|
6567
|
-
|
|
6636
|
+
if (made.length > 0)
|
|
6637
|
+
ui.line(
|
|
6638
|
+
"declared",
|
|
6639
|
+
`${made.join(", ")} in .rness/rness.json \u2014 commit it: git -C .rness commit -am "chore: board ${made.join(", ")}"`
|
|
6640
|
+
);
|
|
6568
6641
|
}
|
|
6642
|
+
if (left.length > 0)
|
|
6643
|
+
throw new Error(
|
|
6644
|
+
`not created: ${left.join(", ")} \u2014 rness board push in a terminal, or with --yes, creates ${left.length === 1 ? "it" : "them"}`
|
|
6645
|
+
);
|
|
6569
6646
|
return 0;
|
|
6570
6647
|
} catch (e) {
|
|
6571
6648
|
return reportError(e);
|
|
6572
6649
|
}
|
|
6573
6650
|
}
|
|
6574
|
-
async function pulseSyncCommand(opts, deps = {}) {
|
|
6575
|
-
try {
|
|
6576
|
-
const ui = deps.ui ?? await makeUi(deps.terminal ?? defaultTerminal);
|
|
6577
|
-
const c = await context(opts, waitSaid(opts, ui));
|
|
6578
|
-
await syncAll(c, await declaredBoards(c, ui), ui, () => eachAdded);
|
|
6579
|
-
return 0;
|
|
6580
|
-
} catch (e) {
|
|
6581
|
-
return reportError(e);
|
|
6582
|
-
}
|
|
6583
|
-
}
|
|
6584
|
-
async function pulseMarkCommand(opts) {
|
|
6585
|
-
try {
|
|
6586
|
-
return await mark(opts);
|
|
6587
|
-
} catch (e) {
|
|
6588
|
-
await recordFailure(e instanceof Error ? e.message : String(e));
|
|
6589
|
-
return 0;
|
|
6590
|
-
}
|
|
6591
|
-
}
|
|
6592
6651
|
function markFields(d) {
|
|
6593
6652
|
const fields2 = Object.entries(d.fields);
|
|
6594
6653
|
const agent = fields2.find(
|
|
@@ -6658,29 +6717,7 @@ async function clearOn(c, d, session) {
|
|
|
6658
6717
|
}).map((i) => i.id);
|
|
6659
6718
|
await fromGithub(c.provider.mark(d.board, ids, null, fields2));
|
|
6660
6719
|
}
|
|
6661
|
-
async function
|
|
6662
|
-
const c = await context(opts);
|
|
6663
|
-
const declared = await declaredBoards(c);
|
|
6664
|
-
const lock = opts.sleep === void 0 ? {} : { sleep: opts.sleep };
|
|
6665
|
-
if (opts.end === true) {
|
|
6666
|
-
for (const d of declared) await clearOn(c, d, opts.session);
|
|
6667
|
-
await oneSyncAtATime(
|
|
6668
|
-
lockKey(c, declared),
|
|
6669
|
-
() => syncAll(c, declared, plainUi, () => eachAdded),
|
|
6670
|
-
{ ...lock, wait: true }
|
|
6671
|
-
);
|
|
6672
|
-
return 0;
|
|
6673
|
-
}
|
|
6674
|
-
const wanted = /* @__PURE__ */ new Map();
|
|
6675
|
-
for (const d of declared) {
|
|
6676
|
-
const paths = opts.paths.filter((p) => holds(d, p));
|
|
6677
|
-
if (paths.length > 0) wanted.set(d, new Set(paths));
|
|
6678
|
-
}
|
|
6679
|
-
if (wanted.size === 0) return 0;
|
|
6680
|
-
await markOn(c, declared, wanted, opts.session, lock);
|
|
6681
|
-
return 0;
|
|
6682
|
-
}
|
|
6683
|
-
async function pulseRunCommand(opts) {
|
|
6720
|
+
async function boardRunCommand(opts) {
|
|
6684
6721
|
const failures = [];
|
|
6685
6722
|
try {
|
|
6686
6723
|
await run(opts, failures);
|
|
@@ -6703,7 +6740,7 @@ async function run(opts, failures) {
|
|
|
6703
6740
|
if (event === "session-end") {
|
|
6704
6741
|
for (const d of acting("journal-summary"))
|
|
6705
6742
|
try {
|
|
6706
|
-
const { postSummary } = await import("./summary-
|
|
6743
|
+
const { postSummary } = await import("./summary-47SFWNSQ.js");
|
|
6707
6744
|
await postSummary({
|
|
6708
6745
|
c,
|
|
6709
6746
|
board: d,
|
|
@@ -6764,6 +6801,33 @@ async function run(opts, failures) {
|
|
|
6764
6801
|
)
|
|
6765
6802
|
);
|
|
6766
6803
|
}
|
|
6804
|
+
async function pulseCreateCommand(collection, opts, deps = {}) {
|
|
6805
|
+
try {
|
|
6806
|
+
const name = collection ?? PULSE;
|
|
6807
|
+
const ws = await findWorkspace(opts.cwd ?? process.cwd());
|
|
6808
|
+
const manifest = await loadManifest(ws.rnessDir);
|
|
6809
|
+
if (manifest.org === null)
|
|
6810
|
+
throw new Error('boards need an organization: rness.json has no "org"');
|
|
6811
|
+
const refused = manifest.refused?.find((r) => r.name === name);
|
|
6812
|
+
if (refused !== void 0)
|
|
6813
|
+
throw new Error(`already declared, and refused: ${refused.reason}`);
|
|
6814
|
+
let said = "rness pulse create is now rness board push";
|
|
6815
|
+
if (manifest.boards?.[name] === void 0) {
|
|
6816
|
+
await checkBoardName(ws.rnessDir, name);
|
|
6817
|
+
const preset = presetFor(name);
|
|
6818
|
+
await writeManifest(ws.rnessDir, {
|
|
6819
|
+
...manifest,
|
|
6820
|
+
boards: { ...manifest.boards, [name]: preset }
|
|
6821
|
+
});
|
|
6822
|
+
said = `boards are declared in rness.json now: added "${name}": "${preset}", then rness board push`;
|
|
6823
|
+
}
|
|
6824
|
+
process.stderr.write(`${said}
|
|
6825
|
+
`);
|
|
6826
|
+
return await boardPushCommand({ ...opts, confirmed: true }, deps);
|
|
6827
|
+
} catch (e) {
|
|
6828
|
+
return reportError(e);
|
|
6829
|
+
}
|
|
6830
|
+
}
|
|
6767
6831
|
|
|
6768
6832
|
export {
|
|
6769
6833
|
exists,
|
|
@@ -6787,6 +6851,7 @@ export {
|
|
|
6787
6851
|
presetTemplate,
|
|
6788
6852
|
BoardRefused,
|
|
6789
6853
|
contractOf,
|
|
6854
|
+
PULSE,
|
|
6790
6855
|
parseBoard,
|
|
6791
6856
|
clone,
|
|
6792
6857
|
isClean,
|
|
@@ -6809,7 +6874,6 @@ export {
|
|
|
6809
6874
|
NAME_RULE,
|
|
6810
6875
|
ORG_NAME,
|
|
6811
6876
|
workspaceName,
|
|
6812
|
-
PULSE,
|
|
6813
6877
|
loadManifest,
|
|
6814
6878
|
parseManifest,
|
|
6815
6879
|
writeManifest,
|
|
@@ -6871,12 +6935,12 @@ export {
|
|
|
6871
6935
|
readBoards,
|
|
6872
6936
|
readmeDeclarations,
|
|
6873
6937
|
migrateBoards,
|
|
6938
|
+
detached,
|
|
6939
|
+
takeFailure,
|
|
6874
6940
|
openInBrowser,
|
|
6875
6941
|
canOpenBrowser,
|
|
6876
6942
|
removeGitSetup,
|
|
6877
6943
|
loginCommand,
|
|
6878
|
-
detached,
|
|
6879
|
-
takeFailure,
|
|
6880
6944
|
notesPosted,
|
|
6881
6945
|
notePosted,
|
|
6882
6946
|
issuesNoted,
|
|
@@ -6889,9 +6953,8 @@ export {
|
|
|
6889
6953
|
fromGithub,
|
|
6890
6954
|
context,
|
|
6891
6955
|
declaredBoards,
|
|
6892
|
-
|
|
6893
|
-
|
|
6894
|
-
|
|
6895
|
-
pulseRunCommand
|
|
6956
|
+
boardPushCommand,
|
|
6957
|
+
boardRunCommand,
|
|
6958
|
+
pulseCreateCommand
|
|
6896
6959
|
};
|
|
6897
|
-
//# sourceMappingURL=chunk-
|
|
6960
|
+
//# sourceMappingURL=chunk-XCO5ZT2H.js.map
|