syntaur 0.23.0 → 0.25.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/dashboard/server.js +164 -129
- package/dist/dashboard/server.js.map +1 -1
- package/dist/index.js +2721 -2050
- package/dist/index.js.map +1 -1
- package/dist/launch/index.d.ts +3 -0
- package/dist/launch/index.js +53 -40
- package/dist/launch/index.js.map +1 -1
- package/package.json +1 -1
- package/platforms/README.md +29 -1
package/dist/dashboard/server.js
CHANGED
|
@@ -388,9 +388,10 @@ __export(fs_exports, {
|
|
|
388
388
|
ensureDir: () => ensureDir,
|
|
389
389
|
fileExists: () => fileExists,
|
|
390
390
|
writeFileForce: () => writeFileForce,
|
|
391
|
+
writeFileReport: () => writeFileReport,
|
|
391
392
|
writeFileSafe: () => writeFileSafe
|
|
392
393
|
});
|
|
393
|
-
import { mkdir, writeFile, access, rename } from "fs/promises";
|
|
394
|
+
import { mkdir, writeFile, readFile, access, rename } from "fs/promises";
|
|
394
395
|
import { dirname, join } from "path";
|
|
395
396
|
async function ensureDir(dir) {
|
|
396
397
|
await mkdir(dir, { recursive: true });
|
|
@@ -421,6 +422,22 @@ async function writeFileForce(filePath, content) {
|
|
|
421
422
|
await writeFile(tempPath, content, "utf-8");
|
|
422
423
|
await rename(tempPath, filePath);
|
|
423
424
|
}
|
|
425
|
+
async function writeFileReport(filePath, content, options = {}) {
|
|
426
|
+
if (!await fileExists(filePath)) {
|
|
427
|
+
await ensureDir(dirname(filePath));
|
|
428
|
+
await writeFile(filePath, content, "utf-8");
|
|
429
|
+
return "written";
|
|
430
|
+
}
|
|
431
|
+
const current = await readFile(filePath, "utf-8").catch(() => null);
|
|
432
|
+
if (current === content) {
|
|
433
|
+
return "already-current";
|
|
434
|
+
}
|
|
435
|
+
if (!options.force) {
|
|
436
|
+
return "differs-preserved";
|
|
437
|
+
}
|
|
438
|
+
await writeFileForce(filePath, content);
|
|
439
|
+
return "overwritten";
|
|
440
|
+
}
|
|
424
441
|
var init_fs = __esm({
|
|
425
442
|
"src/utils/fs.ts"() {
|
|
426
443
|
"use strict";
|
|
@@ -762,7 +779,7 @@ __export(parser_exports, {
|
|
|
762
779
|
writeChecklist: () => writeChecklist
|
|
763
780
|
});
|
|
764
781
|
import { randomBytes } from "crypto";
|
|
765
|
-
import { readFile } from "fs/promises";
|
|
782
|
+
import { readFile as readFile2 } from "fs/promises";
|
|
766
783
|
import { resolve as resolve2 } from "path";
|
|
767
784
|
function generateShortId() {
|
|
768
785
|
return randomBytes(2).toString("hex");
|
|
@@ -1059,7 +1076,7 @@ async function readChecklist(todosDir2, workspace) {
|
|
|
1059
1076
|
if (!await fileExists(path)) {
|
|
1060
1077
|
return { workspace, archiveInterval: "weekly", items: [] };
|
|
1061
1078
|
}
|
|
1062
|
-
const content = await
|
|
1079
|
+
const content = await readFile2(path, "utf-8");
|
|
1063
1080
|
return parseChecklist(content);
|
|
1064
1081
|
}
|
|
1065
1082
|
async function writeChecklist(todosDir2, checklist) {
|
|
@@ -1072,7 +1089,7 @@ async function readLog(todosDir2, workspace) {
|
|
|
1072
1089
|
if (!await fileExists(path)) {
|
|
1073
1090
|
return { workspace, entries: [] };
|
|
1074
1091
|
}
|
|
1075
|
-
const content = await
|
|
1092
|
+
const content = await readFile2(path, "utf-8");
|
|
1076
1093
|
return parseLog(content);
|
|
1077
1094
|
}
|
|
1078
1095
|
async function appendLogEntry(todosDir2, workspace, entry) {
|
|
@@ -1080,7 +1097,7 @@ async function appendLogEntry(todosDir2, workspace, entry) {
|
|
|
1080
1097
|
const path = logPath(todosDir2, workspace);
|
|
1081
1098
|
let content;
|
|
1082
1099
|
if (await fileExists(path)) {
|
|
1083
|
-
content = await
|
|
1100
|
+
content = await readFile2(path, "utf-8");
|
|
1084
1101
|
content = content.trimEnd() + "\n\n" + serializeLogEntry(entry) + "\n";
|
|
1085
1102
|
} else {
|
|
1086
1103
|
const fm = `---
|
|
@@ -1248,7 +1265,7 @@ var init_linked_todos = __esm({
|
|
|
1248
1265
|
|
|
1249
1266
|
// src/lifecycle/transitions.ts
|
|
1250
1267
|
import { resolve as resolve4 } from "path";
|
|
1251
|
-
import { readFile as
|
|
1268
|
+
import { readFile as readFile3 } from "fs/promises";
|
|
1252
1269
|
function linkedAssignmentRef(frontmatter) {
|
|
1253
1270
|
return frontmatter.project ? `${frontmatter.project}/${frontmatter.slug}` : frontmatter.id;
|
|
1254
1271
|
}
|
|
@@ -1268,7 +1285,7 @@ async function readAssignment(filePath) {
|
|
|
1268
1285
|
if (!await fileExists(filePath)) {
|
|
1269
1286
|
throw new Error(`Assignment file not found: ${filePath}`);
|
|
1270
1287
|
}
|
|
1271
|
-
const content = await
|
|
1288
|
+
const content = await readFile3(filePath, "utf-8");
|
|
1272
1289
|
const frontmatter = parseAssignmentFrontmatter(content);
|
|
1273
1290
|
return { content, frontmatter };
|
|
1274
1291
|
}
|
|
@@ -1281,7 +1298,7 @@ async function checkDependencies(projectDir, dependsOn, terminalStatuses) {
|
|
|
1281
1298
|
unmet.push(`${depSlug} (file not found)`);
|
|
1282
1299
|
continue;
|
|
1283
1300
|
}
|
|
1284
|
-
const depContent = await
|
|
1301
|
+
const depContent = await readFile3(depPath, "utf-8");
|
|
1285
1302
|
const depFrontmatter = parseAssignmentFrontmatter(depContent);
|
|
1286
1303
|
if (!terminals.has(depFrontmatter.status)) {
|
|
1287
1304
|
unmet.push(`${depSlug} (status: ${depFrontmatter.status})`);
|
|
@@ -1431,7 +1448,7 @@ var init_config = __esm({
|
|
|
1431
1448
|
});
|
|
1432
1449
|
|
|
1433
1450
|
// src/utils/fs-migration.ts
|
|
1434
|
-
import { readdir as readdir2, readFile as
|
|
1451
|
+
import { readdir as readdir2, readFile as readFile4, rename as rename2, writeFile as writeFile2 } from "fs/promises";
|
|
1435
1452
|
import { resolve as resolve5 } from "path";
|
|
1436
1453
|
async function migrateLegacyProjectFiles(projectsDir) {
|
|
1437
1454
|
const result = {
|
|
@@ -1500,7 +1517,7 @@ async function migrateLegacyArchivedProjects(projectsDir) {
|
|
|
1500
1517
|
const projectMd = resolve5(projectsDir, entry.name, "project.md");
|
|
1501
1518
|
try {
|
|
1502
1519
|
if (!await fileExists(projectMd)) continue;
|
|
1503
|
-
const content = await
|
|
1520
|
+
const content = await readFile4(projectMd, "utf-8");
|
|
1504
1521
|
if (readFrontmatterField(content, "statusOverride") !== "archived") continue;
|
|
1505
1522
|
let next = setFrontmatterField(content, "archived", true);
|
|
1506
1523
|
if (readFrontmatterField(content, "archivedAt") === null) {
|
|
@@ -1525,7 +1542,7 @@ async function migrateLegacyConfig(configPath) {
|
|
|
1525
1542
|
if (!await fileExists(configPath)) return result;
|
|
1526
1543
|
let content;
|
|
1527
1544
|
try {
|
|
1528
|
-
content = await
|
|
1545
|
+
content = await readFile4(configPath, "utf-8");
|
|
1529
1546
|
} catch {
|
|
1530
1547
|
return result;
|
|
1531
1548
|
}
|
|
@@ -1782,7 +1799,7 @@ __export(config_exports, {
|
|
|
1782
1799
|
writeTerminalConfig: () => writeTerminalConfig,
|
|
1783
1800
|
writeThemeConfig: () => writeThemeConfig
|
|
1784
1801
|
});
|
|
1785
|
-
import { readFile as
|
|
1802
|
+
import { readFile as readFile5 } from "fs/promises";
|
|
1786
1803
|
import { spawnSync } from "child_process";
|
|
1787
1804
|
import { resolve as resolve6, isAbsolute } from "path";
|
|
1788
1805
|
function parseAgentCommand(value, agentId) {
|
|
@@ -1910,6 +1927,18 @@ function parseFrontmatter(content) {
|
|
|
1910
1927
|
}
|
|
1911
1928
|
return result;
|
|
1912
1929
|
}
|
|
1930
|
+
function parseInstalledAgents(fm) {
|
|
1931
|
+
const prefix = "integrations.installedAgents.";
|
|
1932
|
+
const installedAgents = {};
|
|
1933
|
+
for (const [key, value] of Object.entries(fm)) {
|
|
1934
|
+
if (!key.startsWith(prefix)) continue;
|
|
1935
|
+
const id = key.slice(prefix.length);
|
|
1936
|
+
if (!id) continue;
|
|
1937
|
+
const scope = value === "project" ? "project" : "global";
|
|
1938
|
+
installedAgents[id] = { scope };
|
|
1939
|
+
}
|
|
1940
|
+
return Object.keys(installedAgents).length > 0 ? { installedAgents } : {};
|
|
1941
|
+
}
|
|
1913
1942
|
function parseStatusConfig(content) {
|
|
1914
1943
|
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
1915
1944
|
if (!match) return null;
|
|
@@ -2039,6 +2068,11 @@ function serializeIntegrationConfig(integrations) {
|
|
|
2039
2068
|
if (integrations.codexMarketplacePath) {
|
|
2040
2069
|
lines.push(` codexMarketplacePath: ${integrations.codexMarketplacePath}`);
|
|
2041
2070
|
}
|
|
2071
|
+
if (integrations.installedAgents) {
|
|
2072
|
+
for (const [id, rec] of Object.entries(integrations.installedAgents)) {
|
|
2073
|
+
lines.push(` installedAgents.${id}: ${rec.scope}`);
|
|
2074
|
+
}
|
|
2075
|
+
}
|
|
2042
2076
|
if (lines.length === 0) {
|
|
2043
2077
|
return null;
|
|
2044
2078
|
}
|
|
@@ -2107,7 +2141,7 @@ async function updatePlaybooksConfig(playbooks) {
|
|
|
2107
2141
|
disabled: Array.from(new Set(playbooks.disabled ?? current.disabled))
|
|
2108
2142
|
};
|
|
2109
2143
|
const playbooksBlock = serializePlaybooksConfig(nextPlaybooks);
|
|
2110
|
-
const existing = await fileExists(configPath) ? await
|
|
2144
|
+
const existing = await fileExists(configPath) ? await readFile5(configPath, "utf-8") : renderConfig({ defaultProjectDir: defaultProjectDir() });
|
|
2111
2145
|
const fmMatch = existing.match(/^(---\n)([\s\S]*?)\n(---)/);
|
|
2112
2146
|
if (!fmMatch) {
|
|
2113
2147
|
const bodyBlock = playbooksBlock ? `${playbooksBlock}
|
|
@@ -2159,7 +2193,7 @@ function serializeThemeConfig(theme) {
|
|
|
2159
2193
|
async function writeThemeConfig(theme) {
|
|
2160
2194
|
const configPath = resolve6(syntaurRoot(), "config.md");
|
|
2161
2195
|
const themeBlock = serializeThemeConfig(theme);
|
|
2162
|
-
const existing = await fileExists(configPath) ? await
|
|
2196
|
+
const existing = await fileExists(configPath) ? await readFile5(configPath, "utf-8") : renderConfig({ defaultProjectDir: defaultProjectDir() });
|
|
2163
2197
|
const fmMatch = existing.match(/^(---\n)([\s\S]*?)\n(---)/);
|
|
2164
2198
|
if (!fmMatch) {
|
|
2165
2199
|
const content = `---
|
|
@@ -2185,7 +2219,7 @@ ${normalizedFm}
|
|
|
2185
2219
|
async function deleteThemeConfig() {
|
|
2186
2220
|
const configPath = resolve6(syntaurRoot(), "config.md");
|
|
2187
2221
|
if (!await fileExists(configPath)) return;
|
|
2188
|
-
const existing = await
|
|
2222
|
+
const existing = await readFile5(configPath, "utf-8");
|
|
2189
2223
|
const fmMatch = existing.match(/^(---\n)([\s\S]*?)\n(---)/);
|
|
2190
2224
|
if (!fmMatch) return;
|
|
2191
2225
|
const fmBlock = fmMatch[2];
|
|
@@ -2205,7 +2239,7 @@ function stripTopLevelScalar(fmBlock, key) {
|
|
|
2205
2239
|
async function writeTerminalConfig(terminal) {
|
|
2206
2240
|
const configPath = resolve6(syntaurRoot(), "config.md");
|
|
2207
2241
|
const terminalLine = `terminal: ${terminal}`;
|
|
2208
|
-
const existing = await fileExists(configPath) ? await
|
|
2242
|
+
const existing = await fileExists(configPath) ? await readFile5(configPath, "utf-8") : renderConfig({ defaultProjectDir: defaultProjectDir() });
|
|
2209
2243
|
const fmMatch = existing.match(/^(---\n)([\s\S]*?)\n(---)/);
|
|
2210
2244
|
if (!fmMatch) {
|
|
2211
2245
|
const content = `---
|
|
@@ -2231,7 +2265,7 @@ ${normalizedFm}
|
|
|
2231
2265
|
async function deleteTerminalConfig() {
|
|
2232
2266
|
const configPath = resolve6(syntaurRoot(), "config.md");
|
|
2233
2267
|
if (!await fileExists(configPath)) return;
|
|
2234
|
-
const existing = await
|
|
2268
|
+
const existing = await readFile5(configPath, "utf-8");
|
|
2235
2269
|
const fmMatch = existing.match(/^(---\n)([\s\S]*?)\n(---)/);
|
|
2236
2270
|
if (!fmMatch) return;
|
|
2237
2271
|
const fmBlock = fmMatch[2];
|
|
@@ -2300,7 +2334,7 @@ async function writeHotkeyBindingsConfig(cfg) {
|
|
|
2300
2334
|
}
|
|
2301
2335
|
const configPath = resolve6(syntaurRoot(), "config.md");
|
|
2302
2336
|
const block = serializeHotkeyBindingsConfig({ bindings: cleaned });
|
|
2303
|
-
const existing = await fileExists(configPath) ? await
|
|
2337
|
+
const existing = await fileExists(configPath) ? await readFile5(configPath, "utf-8") : renderConfig({ defaultProjectDir: defaultProjectDir() });
|
|
2304
2338
|
const fmMatch = existing.match(/^(---\n)([\s\S]*?)\n(---)/);
|
|
2305
2339
|
if (!fmMatch) {
|
|
2306
2340
|
const content = `---
|
|
@@ -2326,7 +2360,7 @@ ${normalizedFm}
|
|
|
2326
2360
|
async function deleteHotkeyBindingsConfig() {
|
|
2327
2361
|
const configPath = resolve6(syntaurRoot(), "config.md");
|
|
2328
2362
|
if (!await fileExists(configPath)) return;
|
|
2329
|
-
const existing = await
|
|
2363
|
+
const existing = await readFile5(configPath, "utf-8");
|
|
2330
2364
|
const fmMatch = existing.match(/^(---\n)([\s\S]*?)\n(---)/);
|
|
2331
2365
|
if (!fmMatch) return;
|
|
2332
2366
|
const fmBlock = fmMatch[2];
|
|
@@ -2643,7 +2677,7 @@ async function writeAgentsConfig(agents) {
|
|
|
2643
2677
|
validateAgentList(agents);
|
|
2644
2678
|
const configPath = resolve6(syntaurRoot(), "config.md");
|
|
2645
2679
|
const agentsBlock = serializeAgentsConfig(agents);
|
|
2646
|
-
const existing = await fileExists(configPath) ? await
|
|
2680
|
+
const existing = await fileExists(configPath) ? await readFile5(configPath, "utf-8") : renderConfig({ defaultProjectDir: defaultProjectDir() });
|
|
2647
2681
|
const fmMatch = existing.match(/^(---\n)([\s\S]*?)\n(---)/);
|
|
2648
2682
|
if (!fmMatch) {
|
|
2649
2683
|
const content = `---
|
|
@@ -2668,7 +2702,7 @@ ${newFm}
|
|
|
2668
2702
|
async function deleteAgentsConfig() {
|
|
2669
2703
|
const configPath = resolve6(syntaurRoot(), "config.md");
|
|
2670
2704
|
if (!await fileExists(configPath)) return;
|
|
2671
|
-
const existing = await
|
|
2705
|
+
const existing = await readFile5(configPath, "utf-8");
|
|
2672
2706
|
const fmMatch = existing.match(/^(---\n)([\s\S]*?)\n(---)/);
|
|
2673
2707
|
if (!fmMatch) return;
|
|
2674
2708
|
const fmBlock = fmMatch[2];
|
|
@@ -2692,7 +2726,7 @@ ${statusBlock}
|
|
|
2692
2726
|
await writeFileForce(configPath, content);
|
|
2693
2727
|
return;
|
|
2694
2728
|
}
|
|
2695
|
-
const existing = await
|
|
2729
|
+
const existing = await readFile5(configPath, "utf-8");
|
|
2696
2730
|
const fmMatch = existing.match(/^(---\n)([\s\S]*?)\n(---)/);
|
|
2697
2731
|
if (!fmMatch) {
|
|
2698
2732
|
const content = `---
|
|
@@ -2736,7 +2770,7 @@ ${statusBlock}
|
|
|
2736
2770
|
async function deleteStatusConfig() {
|
|
2737
2771
|
const configPath = resolve6(syntaurRoot(), "config.md");
|
|
2738
2772
|
if (!await fileExists(configPath)) return;
|
|
2739
|
-
const existing = await
|
|
2773
|
+
const existing = await readFile5(configPath, "utf-8");
|
|
2740
2774
|
const fmMatch = existing.match(/^(---\n)([\s\S]*?)\n(---)/);
|
|
2741
2775
|
if (!fmMatch) return;
|
|
2742
2776
|
const fmBlock = fmMatch[2];
|
|
@@ -2754,7 +2788,7 @@ async function updateIntegrationConfig(integrations) {
|
|
|
2754
2788
|
...integrations
|
|
2755
2789
|
};
|
|
2756
2790
|
const integrationBlock = serializeIntegrationConfig(nextIntegrations);
|
|
2757
|
-
const existing = await fileExists(configPath) ? await
|
|
2791
|
+
const existing = await fileExists(configPath) ? await readFile5(configPath, "utf-8") : renderConfig({ defaultProjectDir: defaultProjectDir() });
|
|
2758
2792
|
const fmMatch = existing.match(/^(---\n)([\s\S]*?)\n(---)/);
|
|
2759
2793
|
if (!fmMatch) {
|
|
2760
2794
|
const content = `---
|
|
@@ -2784,7 +2818,7 @@ async function updateOnboardingConfig(onboarding) {
|
|
|
2784
2818
|
...onboarding
|
|
2785
2819
|
};
|
|
2786
2820
|
const onboardingBlock = serializeOnboardingConfig(nextOnboarding);
|
|
2787
|
-
const existing = await fileExists(configPath) ? await
|
|
2821
|
+
const existing = await fileExists(configPath) ? await readFile5(configPath, "utf-8") : renderConfig({ defaultProjectDir: defaultProjectDir() });
|
|
2788
2822
|
const fmMatch = existing.match(/^(---\n)([\s\S]*?)\n(---)/);
|
|
2789
2823
|
if (!fmMatch) {
|
|
2790
2824
|
const content = `---
|
|
@@ -2818,7 +2852,7 @@ async function updateBackupConfig(backup) {
|
|
|
2818
2852
|
...backup
|
|
2819
2853
|
};
|
|
2820
2854
|
const backupBlock = serializeBackupConfig(nextBackup);
|
|
2821
|
-
const existing = await fileExists(configPath) ? await
|
|
2855
|
+
const existing = await fileExists(configPath) ? await readFile5(configPath, "utf-8") : renderConfig({ defaultProjectDir: defaultProjectDir() });
|
|
2822
2856
|
const fmMatch = existing.match(/^(---\n)([\s\S]*?)\n(---)/);
|
|
2823
2857
|
if (!fmMatch) {
|
|
2824
2858
|
const content = `---
|
|
@@ -2850,7 +2884,7 @@ async function readConfig() {
|
|
|
2850
2884
|
migratedConfigPaths.add(configPath);
|
|
2851
2885
|
await migrateLegacyConfig(configPath);
|
|
2852
2886
|
}
|
|
2853
|
-
const content = await
|
|
2887
|
+
const content = await readFile5(configPath, "utf-8");
|
|
2854
2888
|
const fm = parseFrontmatter(content);
|
|
2855
2889
|
if (Object.keys(fm).length === 0) {
|
|
2856
2890
|
console.warn("Warning: ~/.syntaur/config.md has malformed frontmatter, using defaults");
|
|
@@ -2889,7 +2923,8 @@ async function readConfig() {
|
|
|
2889
2923
|
codexMarketplacePath: parseOptionalAbsolutePath(
|
|
2890
2924
|
fm["integrations.codexMarketplacePath"],
|
|
2891
2925
|
"integrations.codexMarketplacePath"
|
|
2892
|
-
)
|
|
2926
|
+
),
|
|
2927
|
+
...parseInstalledAgents(fm)
|
|
2893
2928
|
},
|
|
2894
2929
|
backup: fm["backup.repo"] || fm["backup.categories"] ? {
|
|
2895
2930
|
repo: fm["backup.repo"] && fm["backup.repo"] !== "null" ? fm["backup.repo"] : null,
|
|
@@ -3054,7 +3089,7 @@ var init_slug = __esm({
|
|
|
3054
3089
|
|
|
3055
3090
|
// src/utils/playbooks.ts
|
|
3056
3091
|
import { resolve as resolve7 } from "path";
|
|
3057
|
-
import { readdir as readdir3, readFile as
|
|
3092
|
+
import { readdir as readdir3, readFile as readFile6, unlink } from "fs/promises";
|
|
3058
3093
|
function escapeRegExp(value) {
|
|
3059
3094
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
3060
3095
|
}
|
|
@@ -3080,7 +3115,7 @@ async function resolvePlaybookSlug(playbooksDir2, slug) {
|
|
|
3080
3115
|
for (const entry of entries) {
|
|
3081
3116
|
if (!isVisiblePlaybookFile(entry.name, entry.isFile())) continue;
|
|
3082
3117
|
const filePath = resolve7(playbooksDir2, entry.name);
|
|
3083
|
-
const raw = await
|
|
3118
|
+
const raw = await readFile6(filePath, "utf-8");
|
|
3084
3119
|
const parsed = parsePlaybook(raw);
|
|
3085
3120
|
const canonical = parsed.slug || entry.name.replace(/\.md$/, "");
|
|
3086
3121
|
if (canonical === slug) {
|
|
@@ -3128,7 +3163,7 @@ async function rebuildPlaybookManifest(playbooksDir2) {
|
|
|
3128
3163
|
const rows = [];
|
|
3129
3164
|
for (const entry of entries) {
|
|
3130
3165
|
if (!isVisiblePlaybookFile(entry.name, entry.isFile())) continue;
|
|
3131
|
-
const raw = await
|
|
3166
|
+
const raw = await readFile6(resolve7(playbooksDir2, entry.name), "utf-8");
|
|
3132
3167
|
const parsed = parsePlaybook(raw);
|
|
3133
3168
|
const slug = parsed.slug || entry.name.replace(/\.md$/, "");
|
|
3134
3169
|
if (disabledSet.has(slug)) continue;
|
|
@@ -3206,7 +3241,7 @@ async function renamePlaybook(playbooksDir2, oldSlug, newSlug) {
|
|
|
3206
3241
|
);
|
|
3207
3242
|
}
|
|
3208
3243
|
}
|
|
3209
|
-
const raw = await
|
|
3244
|
+
const raw = await readFile6(oldPath, "utf-8");
|
|
3210
3245
|
let next = setFrontmatterField2(raw, "slug", newSlug);
|
|
3211
3246
|
next = setFrontmatterField2(next, "updated", `"${nowTimestamp()}"`);
|
|
3212
3247
|
await writeFileForce(newPath, next);
|
|
@@ -3243,7 +3278,7 @@ var init_playbooks = __esm({
|
|
|
3243
3278
|
|
|
3244
3279
|
// src/utils/assignment-resolver.ts
|
|
3245
3280
|
import { resolve as resolve8 } from "path";
|
|
3246
|
-
import { readdir as readdir4, readFile as
|
|
3281
|
+
import { readdir as readdir4, readFile as readFile7 } from "fs/promises";
|
|
3247
3282
|
async function resolveAssignmentById(projectsDir, assignmentsDir2, id) {
|
|
3248
3283
|
let standaloneMatch = null;
|
|
3249
3284
|
let projectMatch = null;
|
|
@@ -3252,7 +3287,7 @@ async function resolveAssignmentById(projectsDir, assignmentsDir2, id) {
|
|
|
3252
3287
|
if (await fileExists(standalonePath)) {
|
|
3253
3288
|
let workspaceGroup = null;
|
|
3254
3289
|
try {
|
|
3255
|
-
const content = await
|
|
3290
|
+
const content = await readFile7(standalonePath, "utf-8");
|
|
3256
3291
|
const [fm] = extractFrontmatter2(content);
|
|
3257
3292
|
workspaceGroup = getField(fm, "workspaceGroup");
|
|
3258
3293
|
} catch {
|
|
@@ -3280,7 +3315,7 @@ async function resolveAssignmentById(projectsDir, assignmentsDir2, id) {
|
|
|
3280
3315
|
const aPath = resolve8(assignmentsPath, a.name, "assignment.md");
|
|
3281
3316
|
if (!await fileExists(aPath)) continue;
|
|
3282
3317
|
try {
|
|
3283
|
-
const content = await
|
|
3318
|
+
const content = await readFile7(aPath, "utf-8");
|
|
3284
3319
|
const [fm] = extractFrontmatter2(content);
|
|
3285
3320
|
const fileId = getField(fm, "id");
|
|
3286
3321
|
if (fileId === id) {
|
|
@@ -3932,8 +3967,8 @@ async function migrateFromMarkdown(projectsDir) {
|
|
|
3932
3967
|
return allSessions.length;
|
|
3933
3968
|
}
|
|
3934
3969
|
async function parseMarkdownSessionsIndex(filePath, projectSlug) {
|
|
3935
|
-
const { readFile:
|
|
3936
|
-
const raw = await
|
|
3970
|
+
const { readFile: readFile21 } = await import("fs/promises");
|
|
3971
|
+
const raw = await readFile21(filePath, "utf-8");
|
|
3937
3972
|
const sessions = [];
|
|
3938
3973
|
const lines = raw.split("\n");
|
|
3939
3974
|
let inTable = false;
|
|
@@ -4003,7 +4038,7 @@ CREATE INDEX IF NOT EXISTS idx_sessions_assignment ON sessions(project_slug, ass
|
|
|
4003
4038
|
});
|
|
4004
4039
|
|
|
4005
4040
|
// src/dashboard/agent-sessions.ts
|
|
4006
|
-
import { readFile as
|
|
4041
|
+
import { readFile as readFile8 } from "fs/promises";
|
|
4007
4042
|
import { resolve as resolve10 } from "path";
|
|
4008
4043
|
function rowToSession(row) {
|
|
4009
4044
|
return {
|
|
@@ -4091,7 +4126,7 @@ async function deleteSessions(sessionIds) {
|
|
|
4091
4126
|
}
|
|
4092
4127
|
async function readAssignmentStatusFromPath(assignmentMdPath) {
|
|
4093
4128
|
if (!await fileExists(assignmentMdPath)) return null;
|
|
4094
|
-
const raw = await
|
|
4129
|
+
const raw = await readFile8(assignmentMdPath, "utf-8");
|
|
4095
4130
|
const match = raw.match(/^status:\s*(.+)$/m);
|
|
4096
4131
|
return match ? match[1].trim() : null;
|
|
4097
4132
|
}
|
|
@@ -4176,7 +4211,7 @@ var init_overviewCopy = __esm({
|
|
|
4176
4211
|
});
|
|
4177
4212
|
|
|
4178
4213
|
// src/dashboard/servers.ts
|
|
4179
|
-
import { readdir as readdir6, readFile as
|
|
4214
|
+
import { readdir as readdir6, readFile as readFile9, unlink as unlink2 } from "fs/promises";
|
|
4180
4215
|
import { resolve as resolve11 } from "path";
|
|
4181
4216
|
function sanitizeSessionName(name) {
|
|
4182
4217
|
return name.replace(/[^a-zA-Z0-9_-]/g, "-");
|
|
@@ -4236,7 +4271,7 @@ async function listSessionFiles(dir) {
|
|
|
4236
4271
|
async function readSessionFile(dir, name) {
|
|
4237
4272
|
const filePath = resolve11(dir, `${sanitizeSessionName(name)}.md`);
|
|
4238
4273
|
if (!await fileExists(filePath)) return null;
|
|
4239
|
-
const raw = await
|
|
4274
|
+
const raw = await readFile9(filePath, "utf-8");
|
|
4240
4275
|
const [frontmatter] = extractFrontmatter2(raw);
|
|
4241
4276
|
if (!frontmatter) return null;
|
|
4242
4277
|
const session = getField(frontmatter, "session") ?? name;
|
|
@@ -4809,7 +4844,7 @@ var init_scanner = __esm({
|
|
|
4809
4844
|
});
|
|
4810
4845
|
|
|
4811
4846
|
// src/dashboard/api.ts
|
|
4812
|
-
import { readdir as readdir7, readFile as
|
|
4847
|
+
import { readdir as readdir7, readFile as readFile10, writeFile as writeFile3 } from "fs/promises";
|
|
4813
4848
|
import { resolve as resolve13, dirname as dirname2, basename } from "path";
|
|
4814
4849
|
function clearFrontmatterField(content, key) {
|
|
4815
4850
|
const fieldRegex = new RegExp(`^(${escapeRegExp2(key)}:)\\s*.*$`, "m");
|
|
@@ -4897,7 +4932,7 @@ async function computeStandaloneRecords(assignmentsDir2) {
|
|
|
4897
4932
|
const assignmentMdPath = resolve13(assignmentDir, "assignment.md");
|
|
4898
4933
|
if (!await fileExists(assignmentMdPath)) continue;
|
|
4899
4934
|
try {
|
|
4900
|
-
const content = await
|
|
4935
|
+
const content = await readFile10(assignmentMdPath, "utf-8");
|
|
4901
4936
|
const record = parseAssignmentFull(content);
|
|
4902
4937
|
records.push({ assignmentDir, id: entry.name, record });
|
|
4903
4938
|
} catch {
|
|
@@ -4973,7 +5008,7 @@ async function listProjects(projectsDir) {
|
|
|
4973
5008
|
async function readWorkspaceRegistry(projectsDir) {
|
|
4974
5009
|
const registryPath = resolve13(dirname2(projectsDir), "workspaces.json");
|
|
4975
5010
|
try {
|
|
4976
|
-
const raw = await
|
|
5011
|
+
const raw = await readFile10(registryPath, "utf-8");
|
|
4977
5012
|
const parsed = JSON.parse(raw);
|
|
4978
5013
|
return Array.isArray(parsed) ? parsed.filter((w) => typeof w === "string") : [];
|
|
4979
5014
|
} catch {
|
|
@@ -5062,7 +5097,7 @@ async function deleteWorkspace(projectsDir, name, opts = {}) {
|
|
|
5062
5097
|
const timestamp = nowTimestamp();
|
|
5063
5098
|
for (const slug of projectsReferencing) {
|
|
5064
5099
|
const path = resolve13(projectsDir, slug, "project.md");
|
|
5065
|
-
const raw = await
|
|
5100
|
+
const raw = await readFile10(path, "utf-8");
|
|
5066
5101
|
let next = clearFrontmatterField(raw, "workspace");
|
|
5067
5102
|
next = setUpdatedField(next, timestamp);
|
|
5068
5103
|
await writeFileForce(path, next);
|
|
@@ -5071,7 +5106,7 @@ async function deleteWorkspace(projectsDir, name, opts = {}) {
|
|
|
5071
5106
|
for (const id of standalonesReferencing) {
|
|
5072
5107
|
if (!opts.assignmentsDir) break;
|
|
5073
5108
|
const path = resolve13(opts.assignmentsDir, id, "assignment.md");
|
|
5074
|
-
const raw = await
|
|
5109
|
+
const raw = await readFile10(path, "utf-8");
|
|
5075
5110
|
let next = clearFrontmatterField(raw, "workspaceGroup");
|
|
5076
5111
|
next = setUpdatedField(next, timestamp);
|
|
5077
5112
|
await writeFileForce(path, next);
|
|
@@ -5308,7 +5343,7 @@ async function getEditableDocument(projectsDir, documentType, projectSlug, assig
|
|
|
5308
5343
|
if (!filePath || !await fileExists(filePath)) {
|
|
5309
5344
|
return null;
|
|
5310
5345
|
}
|
|
5311
|
-
const content = await
|
|
5346
|
+
const content = await readFile10(filePath, "utf-8");
|
|
5312
5347
|
const title = getEditableDocumentTitle(documentType, projectSlug, assignmentSlug);
|
|
5313
5348
|
return {
|
|
5314
5349
|
documentType,
|
|
@@ -5334,7 +5369,7 @@ async function getEditableDocumentById(projectsDir, assignmentsDir2, documentTyp
|
|
|
5334
5369
|
if (!fileName) return null;
|
|
5335
5370
|
const filePath = resolve13(resolved.assignmentDir, fileName);
|
|
5336
5371
|
if (!await fileExists(filePath)) return null;
|
|
5337
|
-
const content = await
|
|
5372
|
+
const content = await readFile10(filePath, "utf-8");
|
|
5338
5373
|
const label = resolved.id;
|
|
5339
5374
|
const title = documentType === "assignment" ? `Edit Assignment: ${label}` : documentType === "plan" ? `Edit Plan: ${label}` : documentType === "scratchpad" ? `Edit Scratchpad: ${label}` : documentType === "handoff" ? `Append Handoff: ${label}` : `Append Decision: ${label}`;
|
|
5340
5375
|
return {
|
|
@@ -5353,7 +5388,7 @@ async function getProjectDetail(projectsDir, slug) {
|
|
|
5353
5388
|
if (!await fileExists(projectMdPath)) {
|
|
5354
5389
|
return null;
|
|
5355
5390
|
}
|
|
5356
|
-
const projectContent = await
|
|
5391
|
+
const projectContent = await readFile10(projectMdPath, "utf-8");
|
|
5357
5392
|
const project = parseProject(projectContent);
|
|
5358
5393
|
const assignments = await listAssignmentRecords(projectPath);
|
|
5359
5394
|
const rollup = await buildProjectRollup(projectPath, project, assignments);
|
|
@@ -5390,18 +5425,18 @@ async function getAssignmentDetail(projectsDir, projectSlug, assignmentSlug) {
|
|
|
5390
5425
|
if (!await fileExists(assignmentMdPath)) {
|
|
5391
5426
|
return null;
|
|
5392
5427
|
}
|
|
5393
|
-
const assignmentContent = await
|
|
5428
|
+
const assignmentContent = await readFile10(assignmentMdPath, "utf-8");
|
|
5394
5429
|
const assignment = parseAssignmentFull(assignmentContent);
|
|
5395
5430
|
let projectWorkspace = null;
|
|
5396
5431
|
const projectMdPath = resolve13(projectsDir, projectSlug, "project.md");
|
|
5397
5432
|
if (await fileExists(projectMdPath)) {
|
|
5398
|
-
const projectContent = await
|
|
5433
|
+
const projectContent = await readFile10(projectMdPath, "utf-8");
|
|
5399
5434
|
projectWorkspace = parseProject(projectContent).workspace;
|
|
5400
5435
|
}
|
|
5401
5436
|
let plan = null;
|
|
5402
5437
|
const planPath = resolve13(assignmentDir, "plan.md");
|
|
5403
5438
|
if (await fileExists(planPath)) {
|
|
5404
|
-
const planContent = await
|
|
5439
|
+
const planContent = await readFile10(planPath, "utf-8");
|
|
5405
5440
|
const parsed = parsePlan(planContent);
|
|
5406
5441
|
plan = {
|
|
5407
5442
|
status: parsed.status,
|
|
@@ -5412,7 +5447,7 @@ async function getAssignmentDetail(projectsDir, projectSlug, assignmentSlug) {
|
|
|
5412
5447
|
let scratchpad = null;
|
|
5413
5448
|
const scratchpadPath = resolve13(assignmentDir, "scratchpad.md");
|
|
5414
5449
|
if (await fileExists(scratchpadPath)) {
|
|
5415
|
-
const scratchpadContent = await
|
|
5450
|
+
const scratchpadContent = await readFile10(scratchpadPath, "utf-8");
|
|
5416
5451
|
const parsed = parseScratchpad(scratchpadContent);
|
|
5417
5452
|
scratchpad = {
|
|
5418
5453
|
updated: parsed.updated,
|
|
@@ -5422,7 +5457,7 @@ async function getAssignmentDetail(projectsDir, projectSlug, assignmentSlug) {
|
|
|
5422
5457
|
let handoff = null;
|
|
5423
5458
|
const handoffPath = resolve13(assignmentDir, "handoff.md");
|
|
5424
5459
|
if (await fileExists(handoffPath)) {
|
|
5425
|
-
const handoffContent = await
|
|
5460
|
+
const handoffContent = await readFile10(handoffPath, "utf-8");
|
|
5426
5461
|
const parsed = parseHandoff(handoffContent);
|
|
5427
5462
|
handoff = {
|
|
5428
5463
|
updated: parsed.updated,
|
|
@@ -5433,7 +5468,7 @@ async function getAssignmentDetail(projectsDir, projectSlug, assignmentSlug) {
|
|
|
5433
5468
|
let decisionRecord = null;
|
|
5434
5469
|
const decisionRecordPath = resolve13(assignmentDir, "decision-record.md");
|
|
5435
5470
|
if (await fileExists(decisionRecordPath)) {
|
|
5436
|
-
const decisionRecordContent = await
|
|
5471
|
+
const decisionRecordContent = await readFile10(decisionRecordPath, "utf-8");
|
|
5437
5472
|
const parsed = parseDecisionRecord(decisionRecordContent);
|
|
5438
5473
|
decisionRecord = {
|
|
5439
5474
|
updated: parsed.updated,
|
|
@@ -5444,7 +5479,7 @@ async function getAssignmentDetail(projectsDir, projectSlug, assignmentSlug) {
|
|
|
5444
5479
|
let progress = null;
|
|
5445
5480
|
const progressPath = resolve13(assignmentDir, "progress.md");
|
|
5446
5481
|
if (await fileExists(progressPath)) {
|
|
5447
|
-
const progressContent = await
|
|
5482
|
+
const progressContent = await readFile10(progressPath, "utf-8");
|
|
5448
5483
|
const parsed = parseProgress(progressContent);
|
|
5449
5484
|
progress = {
|
|
5450
5485
|
updated: parsed.updated,
|
|
@@ -5455,7 +5490,7 @@ async function getAssignmentDetail(projectsDir, projectSlug, assignmentSlug) {
|
|
|
5455
5490
|
let comments = null;
|
|
5456
5491
|
const commentsPath = resolve13(assignmentDir, "comments.md");
|
|
5457
5492
|
if (await fileExists(commentsPath)) {
|
|
5458
|
-
const commentsContent = await
|
|
5493
|
+
const commentsContent = await readFile10(commentsPath, "utf-8");
|
|
5459
5494
|
const parsed = parseComments(commentsContent);
|
|
5460
5495
|
comments = {
|
|
5461
5496
|
updated: parsed.updated,
|
|
@@ -5609,7 +5644,7 @@ async function countMentionsInAssignment(sourceDir, target) {
|
|
|
5609
5644
|
const bodies = [];
|
|
5610
5645
|
const assignmentMd = resolve13(sourceDir, "assignment.md");
|
|
5611
5646
|
if (await fileExists(assignmentMd)) {
|
|
5612
|
-
const content = await
|
|
5647
|
+
const content = await readFile10(assignmentMd, "utf-8");
|
|
5613
5648
|
const todosMatch = content.match(/^## Todos\s*$([\s\S]*?)(?=^## |$(?![\r\n]))/m);
|
|
5614
5649
|
if (todosMatch) bodies.push(todosMatch[1]);
|
|
5615
5650
|
}
|
|
@@ -5617,7 +5652,7 @@ async function countMentionsInAssignment(sourceDir, target) {
|
|
|
5617
5652
|
const path = resolve13(sourceDir, filename);
|
|
5618
5653
|
if (await fileExists(path)) {
|
|
5619
5654
|
try {
|
|
5620
|
-
bodies.push(await
|
|
5655
|
+
bodies.push(await readFile10(path, "utf-8"));
|
|
5621
5656
|
} catch {
|
|
5622
5657
|
}
|
|
5623
5658
|
}
|
|
@@ -5677,42 +5712,42 @@ async function buildStandaloneAssignmentDetail(resolved) {
|
|
|
5677
5712
|
const assignmentDir = resolved.assignmentDir;
|
|
5678
5713
|
const assignmentMdPath = resolve13(assignmentDir, "assignment.md");
|
|
5679
5714
|
if (!await fileExists(assignmentMdPath)) return null;
|
|
5680
|
-
const assignmentContent = await
|
|
5715
|
+
const assignmentContent = await readFile10(assignmentMdPath, "utf-8");
|
|
5681
5716
|
const assignment = parseAssignmentFull(assignmentContent);
|
|
5682
5717
|
let plan = null;
|
|
5683
5718
|
const planPath = resolve13(assignmentDir, "plan.md");
|
|
5684
5719
|
if (await fileExists(planPath)) {
|
|
5685
|
-
const parsed = parsePlan(await
|
|
5720
|
+
const parsed = parsePlan(await readFile10(planPath, "utf-8"));
|
|
5686
5721
|
plan = { status: parsed.status, updated: parsed.updated, body: parsed.body };
|
|
5687
5722
|
}
|
|
5688
5723
|
let scratchpad = null;
|
|
5689
5724
|
const scratchpadPath = resolve13(assignmentDir, "scratchpad.md");
|
|
5690
5725
|
if (await fileExists(scratchpadPath)) {
|
|
5691
|
-
const parsed = parseScratchpad(await
|
|
5726
|
+
const parsed = parseScratchpad(await readFile10(scratchpadPath, "utf-8"));
|
|
5692
5727
|
scratchpad = { updated: parsed.updated, body: parsed.body };
|
|
5693
5728
|
}
|
|
5694
5729
|
let handoff = null;
|
|
5695
5730
|
const handoffPath = resolve13(assignmentDir, "handoff.md");
|
|
5696
5731
|
if (await fileExists(handoffPath)) {
|
|
5697
|
-
const parsed = parseHandoff(await
|
|
5732
|
+
const parsed = parseHandoff(await readFile10(handoffPath, "utf-8"));
|
|
5698
5733
|
handoff = { updated: parsed.updated, handoffCount: parsed.handoffCount, body: parsed.body };
|
|
5699
5734
|
}
|
|
5700
5735
|
let decisionRecord = null;
|
|
5701
5736
|
const decisionRecordPath = resolve13(assignmentDir, "decision-record.md");
|
|
5702
5737
|
if (await fileExists(decisionRecordPath)) {
|
|
5703
|
-
const parsed = parseDecisionRecord(await
|
|
5738
|
+
const parsed = parseDecisionRecord(await readFile10(decisionRecordPath, "utf-8"));
|
|
5704
5739
|
decisionRecord = { updated: parsed.updated, decisionCount: parsed.decisionCount, body: parsed.body };
|
|
5705
5740
|
}
|
|
5706
5741
|
let progress = null;
|
|
5707
5742
|
const progressPath = resolve13(assignmentDir, "progress.md");
|
|
5708
5743
|
if (await fileExists(progressPath)) {
|
|
5709
|
-
const parsed = parseProgress(await
|
|
5744
|
+
const parsed = parseProgress(await readFile10(progressPath, "utf-8"));
|
|
5710
5745
|
progress = { updated: parsed.updated, entryCount: parsed.entryCount, entries: parsed.entries };
|
|
5711
5746
|
}
|
|
5712
5747
|
let comments = null;
|
|
5713
5748
|
const commentsPath = resolve13(assignmentDir, "comments.md");
|
|
5714
5749
|
if (await fileExists(commentsPath)) {
|
|
5715
|
-
const parsed = parseComments(await
|
|
5750
|
+
const parsed = parseComments(await readFile10(commentsPath, "utf-8"));
|
|
5716
5751
|
comments = { updated: parsed.updated, entryCount: parsed.entryCount, entries: parsed.entries };
|
|
5717
5752
|
}
|
|
5718
5753
|
const detail = {
|
|
@@ -5778,7 +5813,7 @@ async function computeProjectRecords(projectsDir, traces) {
|
|
|
5778
5813
|
return null;
|
|
5779
5814
|
}
|
|
5780
5815
|
const t0 = traces ? performance.now() : 0;
|
|
5781
|
-
const projectContent = await
|
|
5816
|
+
const projectContent = await readFile10(projectMdPath, "utf-8");
|
|
5782
5817
|
const project = parseProject(projectContent);
|
|
5783
5818
|
if (traces) accumulatePhase(traces, "parse-project-md", performance.now() - t0);
|
|
5784
5819
|
const t1 = traces ? performance.now() : 0;
|
|
@@ -5832,7 +5867,7 @@ async function listAssignmentRecords(projectPath, traces) {
|
|
|
5832
5867
|
return null;
|
|
5833
5868
|
}
|
|
5834
5869
|
const t0 = traces ? performance.now() : 0;
|
|
5835
|
-
const content = await
|
|
5870
|
+
const content = await readFile10(assignmentMd, "utf-8");
|
|
5836
5871
|
const parsed = parseAssignmentFull(content);
|
|
5837
5872
|
if (traces) accumulatePhase(traces, "read-assignment-md", performance.now() - t0);
|
|
5838
5873
|
return parsed;
|
|
@@ -5854,7 +5889,7 @@ async function listResources(projectPath) {
|
|
|
5854
5889
|
continue;
|
|
5855
5890
|
}
|
|
5856
5891
|
const filePath = resolve13(resourcesDir, entry.name);
|
|
5857
|
-
const content = await
|
|
5892
|
+
const content = await readFile10(filePath, "utf-8");
|
|
5858
5893
|
const parsed = parseResource(content);
|
|
5859
5894
|
results.push({
|
|
5860
5895
|
name: parsed.name,
|
|
@@ -5880,7 +5915,7 @@ async function listMemories(projectPath) {
|
|
|
5880
5915
|
continue;
|
|
5881
5916
|
}
|
|
5882
5917
|
const filePath = resolve13(memoriesDir, entry.name);
|
|
5883
|
-
const content = await
|
|
5918
|
+
const content = await readFile10(filePath, "utf-8");
|
|
5884
5919
|
const parsed = parseMemory(content);
|
|
5885
5920
|
results.push({
|
|
5886
5921
|
name: parsed.name,
|
|
@@ -5943,7 +5978,7 @@ async function getMemoryDetail(projectsDir, projectSlug, itemSlug) {
|
|
|
5943
5978
|
if (!projectRecord) return null;
|
|
5944
5979
|
const filePath = resolve13(projectRecord.projectPath, "memories", `${itemSlug}.md`);
|
|
5945
5980
|
if (!await fileExists(filePath)) return null;
|
|
5946
|
-
const content = await
|
|
5981
|
+
const content = await readFile10(filePath, "utf-8");
|
|
5947
5982
|
const parsed = parseMemory(content);
|
|
5948
5983
|
return {
|
|
5949
5984
|
name: parsed.name,
|
|
@@ -5969,7 +6004,7 @@ async function getResourceDetail(projectsDir, projectSlug, itemSlug) {
|
|
|
5969
6004
|
if (!projectRecord) return null;
|
|
5970
6005
|
const filePath = resolve13(projectRecord.projectPath, "resources", `${itemSlug}.md`);
|
|
5971
6006
|
if (!await fileExists(filePath)) return null;
|
|
5972
|
-
const content = await
|
|
6007
|
+
const content = await readFile10(filePath, "utf-8");
|
|
5973
6008
|
const parsed = parseResource(content);
|
|
5974
6009
|
return {
|
|
5975
6010
|
name: parsed.name,
|
|
@@ -5987,7 +6022,7 @@ async function getResourceDetail(projectsDir, projectSlug, itemSlug) {
|
|
|
5987
6022
|
async function loadDependencyGraph(projectPath, assignments) {
|
|
5988
6023
|
const statusPath = resolve13(projectPath, "_status.md");
|
|
5989
6024
|
if (await fileExists(statusPath)) {
|
|
5990
|
-
const statusContent = await
|
|
6025
|
+
const statusContent = await readFile10(statusPath, "utf-8");
|
|
5991
6026
|
const parsed = parseStatus(statusContent);
|
|
5992
6027
|
const derivedGraph = extractMermaidGraph(parsed.body);
|
|
5993
6028
|
if (derivedGraph) {
|
|
@@ -6154,7 +6189,7 @@ async function getUnmetDependencies(projectPath, dependsOn, terminalStatuses, de
|
|
|
6154
6189
|
unmet.push(`${dependency} (missing)`);
|
|
6155
6190
|
continue;
|
|
6156
6191
|
}
|
|
6157
|
-
const content = await
|
|
6192
|
+
const content = await readFile10(dependencyPath, "utf-8");
|
|
6158
6193
|
const parsed = parseAssignmentFull(content);
|
|
6159
6194
|
if (!terminals.has(parsed.status)) {
|
|
6160
6195
|
unmet.push(`${dependency} (${parsed.status})`);
|
|
@@ -6449,7 +6484,7 @@ async function countOpenQuestions(projectPath, assignmentSlug) {
|
|
|
6449
6484
|
return 0;
|
|
6450
6485
|
}
|
|
6451
6486
|
try {
|
|
6452
|
-
const content = await
|
|
6487
|
+
const content = await readFile10(commentsPath, "utf-8");
|
|
6453
6488
|
const parsed = parseComments(content);
|
|
6454
6489
|
return parsed.entries.filter(
|
|
6455
6490
|
(e) => e.type === "question" && e.resolved !== true
|
|
@@ -6522,7 +6557,7 @@ async function listPlaybooks(playbooksDir2) {
|
|
|
6522
6557
|
for (const entry of entries) {
|
|
6523
6558
|
if (!entry.isFile() || !entry.name.endsWith(".md") || entry.name.startsWith("_") || entry.name === "manifest.md") continue;
|
|
6524
6559
|
const filePath = resolve13(playbooksDir2, entry.name);
|
|
6525
|
-
const raw = await
|
|
6560
|
+
const raw = await readFile10(filePath, "utf-8");
|
|
6526
6561
|
const parsed = parsePlaybook(raw);
|
|
6527
6562
|
const slug = parsed.slug || entry.name.replace(/\.md$/, "");
|
|
6528
6563
|
playbooks.push({
|
|
@@ -7201,7 +7236,7 @@ function mergePatch(current, patch) {
|
|
|
7201
7236
|
// src/utils/view-prefs.ts
|
|
7202
7237
|
init_paths();
|
|
7203
7238
|
init_fs();
|
|
7204
|
-
import { readFile as
|
|
7239
|
+
import { readFile as readFile11, rename as rename3, unlink as unlink3 } from "fs/promises";
|
|
7205
7240
|
import { resolve as resolve14 } from "path";
|
|
7206
7241
|
function corruptFilePath() {
|
|
7207
7242
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
@@ -7224,7 +7259,7 @@ async function readViewPrefsFile() {
|
|
|
7224
7259
|
}
|
|
7225
7260
|
let raw;
|
|
7226
7261
|
try {
|
|
7227
|
-
raw = await
|
|
7262
|
+
raw = await readFile11(path, "utf-8");
|
|
7228
7263
|
} catch {
|
|
7229
7264
|
return { ...DEFAULT_VIEW_PREFS_FILE };
|
|
7230
7265
|
}
|
|
@@ -7407,7 +7442,7 @@ function isDashboardSlot(value) {
|
|
|
7407
7442
|
// src/utils/saved-views.ts
|
|
7408
7443
|
init_paths();
|
|
7409
7444
|
init_fs();
|
|
7410
|
-
import { readFile as
|
|
7445
|
+
import { readFile as readFile12, rename as rename4, unlink as unlink4 } from "fs/promises";
|
|
7411
7446
|
import { randomUUID } from "crypto";
|
|
7412
7447
|
import { resolve as resolve15 } from "path";
|
|
7413
7448
|
function corruptFilePath2() {
|
|
@@ -7437,7 +7472,7 @@ async function readSavedViewsFile() {
|
|
|
7437
7472
|
}
|
|
7438
7473
|
let raw;
|
|
7439
7474
|
try {
|
|
7440
|
-
raw = await
|
|
7475
|
+
raw = await readFile12(path, "utf-8");
|
|
7441
7476
|
} catch {
|
|
7442
7477
|
return cloneDefault();
|
|
7443
7478
|
}
|
|
@@ -7753,7 +7788,7 @@ init_lifecycle();
|
|
|
7753
7788
|
init_slug();
|
|
7754
7789
|
import { Router as Router2 } from "express";
|
|
7755
7790
|
import { resolve as resolve18, basename as basename3, isAbsolute as isAbsolute2 } from "path";
|
|
7756
|
-
import { rm, readFile as
|
|
7791
|
+
import { rm, readFile as readFile15, open as fsOpen, stat as fsStat, realpath as fsRealpath } from "fs/promises";
|
|
7757
7792
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
7758
7793
|
|
|
7759
7794
|
// src/utils/uuid.ts
|
|
@@ -7770,7 +7805,7 @@ init_fs();
|
|
|
7770
7805
|
init_frontmatter();
|
|
7771
7806
|
init_fs();
|
|
7772
7807
|
import { spawn } from "child_process";
|
|
7773
|
-
import { readFile as
|
|
7808
|
+
import { readFile as readFile13 } from "fs/promises";
|
|
7774
7809
|
function run(command, args, cwd) {
|
|
7775
7810
|
return new Promise((resolvePromise) => {
|
|
7776
7811
|
const child = spawn(command, args, { cwd, stdio: ["ignore", "pipe", "pipe"] });
|
|
@@ -7854,7 +7889,7 @@ async function createWorktreeAndRecord(opts) {
|
|
|
7854
7889
|
const { assignmentPath, repository, branch, worktreePath, parentBranch } = opts;
|
|
7855
7890
|
await createWorktree({ repository, branch, worktreePath, parentBranch });
|
|
7856
7891
|
try {
|
|
7857
|
-
const content = await
|
|
7892
|
+
const content = await readFile13(assignmentPath, "utf-8");
|
|
7858
7893
|
const updated = updateAssignmentWorkspace(content, {
|
|
7859
7894
|
repository,
|
|
7860
7895
|
worktreePath,
|
|
@@ -7967,7 +8002,7 @@ function validateBranchName(name) {
|
|
|
7967
8002
|
// src/dashboard/repository-candidates.ts
|
|
7968
8003
|
init_fs();
|
|
7969
8004
|
init_parser();
|
|
7970
|
-
import { readdir as readdir8, readFile as
|
|
8005
|
+
import { readdir as readdir8, readFile as readFile14 } from "fs/promises";
|
|
7971
8006
|
import { resolve as resolve17 } from "path";
|
|
7972
8007
|
function toSourceAssignment(parsed, fallbackId) {
|
|
7973
8008
|
const repository = parsed.workspace.repository?.trim();
|
|
@@ -7987,7 +8022,7 @@ async function getProjectRepositoryCandidates(projectsDir, projectSlug) {
|
|
|
7987
8022
|
const out = [];
|
|
7988
8023
|
const projectPath = resolve17(projectsDir, projectSlug, "project.md");
|
|
7989
8024
|
if (await fileExists(projectPath)) {
|
|
7990
|
-
const project = parseProject(await
|
|
8025
|
+
const project = parseProject(await readFile14(projectPath, "utf-8"));
|
|
7991
8026
|
for (const raw of project.repositories) {
|
|
7992
8027
|
const path = raw.trim();
|
|
7993
8028
|
if (!path) continue;
|
|
@@ -8004,7 +8039,7 @@ async function getProjectRepositoryCandidates(projectsDir, projectSlug) {
|
|
|
8004
8039
|
if (!entry.isDirectory()) continue;
|
|
8005
8040
|
const assignmentMd = resolve17(assignmentsDir2, entry.name, "assignment.md");
|
|
8006
8041
|
if (!await fileExists(assignmentMd)) continue;
|
|
8007
|
-
const parsed = parseAssignmentFull(await
|
|
8042
|
+
const parsed = parseAssignmentFull(await readFile14(assignmentMd, "utf-8"));
|
|
8008
8043
|
const repo = parsed.workspace.repository?.trim();
|
|
8009
8044
|
if (!repo) continue;
|
|
8010
8045
|
const abs = resolve17(repo);
|
|
@@ -8027,7 +8062,7 @@ async function getStandaloneRepositoryCandidates(assignmentsDir2, excludeAssignm
|
|
|
8027
8062
|
if (entry.name === excludeAssignmentId) continue;
|
|
8028
8063
|
const assignmentMd = resolve17(assignmentsDir2, entry.name, "assignment.md");
|
|
8029
8064
|
if (!await fileExists(assignmentMd)) continue;
|
|
8030
|
-
const parsed = parseAssignmentFull(await
|
|
8065
|
+
const parsed = parseAssignmentFull(await readFile14(assignmentMd, "utf-8"));
|
|
8031
8066
|
const repo = parsed.workspace.repository?.trim();
|
|
8032
8067
|
if (!repo) continue;
|
|
8033
8068
|
const abs = resolve17(repo);
|
|
@@ -8048,7 +8083,7 @@ async function getProjectSourceAssignments(projectsDir, projectSlug, excludeSlug
|
|
|
8048
8083
|
if (entry.name === excludeSlug) continue;
|
|
8049
8084
|
const assignmentMd = resolve17(assignmentsDir2, entry.name, "assignment.md");
|
|
8050
8085
|
if (!await fileExists(assignmentMd)) continue;
|
|
8051
|
-
const parsed = parseAssignmentFull(await
|
|
8086
|
+
const parsed = parseAssignmentFull(await readFile14(assignmentMd, "utf-8"));
|
|
8052
8087
|
const source = toSourceAssignment(parsed, entry.name);
|
|
8053
8088
|
if (!source) continue;
|
|
8054
8089
|
if (seen.has(entry.name)) continue;
|
|
@@ -8067,7 +8102,7 @@ async function getStandaloneSourceAssignments(assignmentsDir2, excludeAssignment
|
|
|
8067
8102
|
if (entry.name === excludeAssignmentId) continue;
|
|
8068
8103
|
const assignmentMd = resolve17(assignmentsDir2, entry.name, "assignment.md");
|
|
8069
8104
|
if (!await fileExists(assignmentMd)) continue;
|
|
8070
|
-
const parsed = parseAssignmentFull(await
|
|
8105
|
+
const parsed = parseAssignmentFull(await readFile14(assignmentMd, "utf-8"));
|
|
8071
8106
|
const source = toSourceAssignment(parsed, entry.name);
|
|
8072
8107
|
if (!source) continue;
|
|
8073
8108
|
if (seen.has(entry.name)) continue;
|
|
@@ -8642,7 +8677,7 @@ async function readCurrentDocument(filePath) {
|
|
|
8642
8677
|
if (!await fileExists(filePath)) {
|
|
8643
8678
|
return null;
|
|
8644
8679
|
}
|
|
8645
|
-
return
|
|
8680
|
+
return readFile15(filePath, "utf-8");
|
|
8646
8681
|
}
|
|
8647
8682
|
var worktreeInFlight = /* @__PURE__ */ new Set();
|
|
8648
8683
|
async function assertRepoRoot(repoInput) {
|
|
@@ -8696,7 +8731,7 @@ async function handleWorktreeCreate(req, res, ctx) {
|
|
|
8696
8731
|
}
|
|
8697
8732
|
worktreeInFlight.add(ctx.assignmentPath);
|
|
8698
8733
|
try {
|
|
8699
|
-
const parsed = parseAssignmentFull(await
|
|
8734
|
+
const parsed = parseAssignmentFull(await readFile15(ctx.assignmentPath, "utf-8"));
|
|
8700
8735
|
if (parsed.workspace.worktreePath) {
|
|
8701
8736
|
res.status(409).json({ error: "Worktree already configured for this assignment" });
|
|
8702
8737
|
return;
|
|
@@ -9066,7 +9101,7 @@ ${body.startsWith("\n") ? body.slice(1) : body}${body.endsWith("\n") ? "" : "\n"
|
|
|
9066
9101
|
}
|
|
9067
9102
|
const nextContentRaw = requireContent(req, res);
|
|
9068
9103
|
if (!nextContentRaw) return;
|
|
9069
|
-
const currentContent = await
|
|
9104
|
+
const currentContent = await readFile15(filePath, "utf-8");
|
|
9070
9105
|
const frontmatterBlock = extractFrontmatterBlock(currentContent);
|
|
9071
9106
|
if (!frontmatterBlock) {
|
|
9072
9107
|
res.status(500).json({ error: `${kind} file is malformed (no frontmatter)` });
|
|
@@ -9517,7 +9552,7 @@ ${nextBody}${nextBody.endsWith("\n") ? "" : "\n"}`;
|
|
|
9517
9552
|
let currentContent;
|
|
9518
9553
|
let currentCount = 0;
|
|
9519
9554
|
if (await fileExists(commentsPath)) {
|
|
9520
|
-
currentContent = await
|
|
9555
|
+
currentContent = await readFile15(commentsPath, "utf-8");
|
|
9521
9556
|
const countMatch = currentContent.match(/^entryCount:\s*(\d+)/m);
|
|
9522
9557
|
if (countMatch) currentCount = parseInt(countMatch[1], 10);
|
|
9523
9558
|
} else {
|
|
@@ -9574,7 +9609,7 @@ ${entry}`;
|
|
|
9574
9609
|
res.status(400).json({ error: "resolved (boolean) is required" });
|
|
9575
9610
|
return;
|
|
9576
9611
|
}
|
|
9577
|
-
const content = await
|
|
9612
|
+
const content = await readFile15(commentsPath, "utf-8");
|
|
9578
9613
|
const parsed = parseComments(content);
|
|
9579
9614
|
const target = parsed.entries.find((e) => e.id === commentId);
|
|
9580
9615
|
if (!target) {
|
|
@@ -9621,7 +9656,7 @@ ${entry}`;
|
|
|
9621
9656
|
});
|
|
9622
9657
|
return;
|
|
9623
9658
|
}
|
|
9624
|
-
let content = await
|
|
9659
|
+
let content = await readFile15(projectPath, "utf-8");
|
|
9625
9660
|
content = setTopLevelField(content, "workspace", workspace ?? null);
|
|
9626
9661
|
content = setTopLevelField(content, "updated", nowTimestamp());
|
|
9627
9662
|
await writeFileForce(projectPath, content);
|
|
@@ -9658,7 +9693,7 @@ ${entry}`;
|
|
|
9658
9693
|
return;
|
|
9659
9694
|
}
|
|
9660
9695
|
const assignmentPath = resolve18(resolved.assignmentDir, "assignment.md");
|
|
9661
|
-
let content = await
|
|
9696
|
+
let content = await readFile15(assignmentPath, "utf-8");
|
|
9662
9697
|
content = setTopLevelField(content, "workspaceGroup", workspaceGroup ?? null);
|
|
9663
9698
|
content = setTopLevelField(content, "updated", nowTimestamp());
|
|
9664
9699
|
await writeFileForce(assignmentPath, content);
|
|
@@ -9875,7 +9910,7 @@ ${entry}`;
|
|
|
9875
9910
|
return;
|
|
9876
9911
|
}
|
|
9877
9912
|
const assignmentPath = resolve18(resolved.assignmentDir, "assignment.md");
|
|
9878
|
-
const parsedForSlug = parseAssignmentFull(await
|
|
9913
|
+
const parsedForSlug = parseAssignmentFull(await readFile15(assignmentPath, "utf-8"));
|
|
9879
9914
|
const assignmentSlugForBranch = parsedForSlug.slug || resolved.id;
|
|
9880
9915
|
await handleWorktreeCreate(req, res, {
|
|
9881
9916
|
assignmentPath,
|
|
@@ -9904,7 +9939,7 @@ ${entry}`;
|
|
|
9904
9939
|
res.status(400).json({ error: `Invalid status. Must be one of: ${validStatuses.join(", ")}, or null to clear.` });
|
|
9905
9940
|
return;
|
|
9906
9941
|
}
|
|
9907
|
-
let content = await
|
|
9942
|
+
let content = await readFile15(projectPath, "utf-8");
|
|
9908
9943
|
content = setTopLevelField(content, "statusOverride", status ?? null);
|
|
9909
9944
|
content = setTopLevelField(content, "updated", nowTimestamp());
|
|
9910
9945
|
await writeFileForce(projectPath, content);
|
|
@@ -9937,7 +9972,7 @@ ${entry}`;
|
|
|
9937
9972
|
res.status(400).json({ error: `Invalid status. Must be one of: ${validStatuses.join(", ")}.` });
|
|
9938
9973
|
return;
|
|
9939
9974
|
}
|
|
9940
|
-
let content = await
|
|
9975
|
+
let content = await readFile15(assignmentPath, "utf-8");
|
|
9941
9976
|
content = setTopLevelField(content, "status", status);
|
|
9942
9977
|
content = setTopLevelField(content, "updated", nowTimestamp());
|
|
9943
9978
|
if (status !== "blocked") {
|
|
@@ -9963,7 +9998,7 @@ ${entry}`;
|
|
|
9963
9998
|
res.status(404).json({ error: `Project "${projectSlug}" not found` });
|
|
9964
9999
|
return;
|
|
9965
10000
|
}
|
|
9966
|
-
const content = await
|
|
10001
|
+
const content = await readFile15(projectPath, "utf-8");
|
|
9967
10002
|
await writeFileForce(projectPath, applyArchiveFields(content, true, archiveReason(req.body)));
|
|
9968
10003
|
const project = await getProjectDetail(projectsDir, projectSlug);
|
|
9969
10004
|
res.json({ project });
|
|
@@ -9980,7 +10015,7 @@ ${entry}`;
|
|
|
9980
10015
|
res.status(404).json({ error: `Project "${projectSlug}" not found` });
|
|
9981
10016
|
return;
|
|
9982
10017
|
}
|
|
9983
|
-
const content = await
|
|
10018
|
+
const content = await readFile15(projectPath, "utf-8");
|
|
9984
10019
|
await writeFileForce(projectPath, applyArchiveFields(content, false, null));
|
|
9985
10020
|
const project = await getProjectDetail(projectsDir, projectSlug);
|
|
9986
10021
|
res.json({ project });
|
|
@@ -9997,7 +10032,7 @@ ${entry}`;
|
|
|
9997
10032
|
res.status(404).json({ error: "Assignment not found" });
|
|
9998
10033
|
return;
|
|
9999
10034
|
}
|
|
10000
|
-
const content = await
|
|
10035
|
+
const content = await readFile15(assignmentPath, "utf-8");
|
|
10001
10036
|
await writeFileForce(assignmentPath, applyArchiveFields(content, archived, archived ? archiveReason(req.body) : null));
|
|
10002
10037
|
const assignment = await getAssignmentDetail(projectsDir, projectSlug, assignmentSlug);
|
|
10003
10038
|
res.json({ assignment });
|
|
@@ -10030,7 +10065,7 @@ ${entry}`;
|
|
|
10030
10065
|
return;
|
|
10031
10066
|
}
|
|
10032
10067
|
const assignmentPath = resolve18(resolved.assignmentDir, "assignment.md");
|
|
10033
|
-
const content = await
|
|
10068
|
+
const content = await readFile15(assignmentPath, "utf-8");
|
|
10034
10069
|
await writeFileForce(assignmentPath, applyArchiveFields(content, archived, archived ? archiveReason(req.body) : null));
|
|
10035
10070
|
const assignment = await getAssignmentDetailById(projectsDir, assignmentsDir2, id);
|
|
10036
10071
|
res.json({ assignment });
|
|
@@ -10071,7 +10106,7 @@ ${entry}`;
|
|
|
10071
10106
|
res.status(400).json({ error: validation.error });
|
|
10072
10107
|
return;
|
|
10073
10108
|
}
|
|
10074
|
-
let content = await
|
|
10109
|
+
let content = await readFile15(assignmentPath, "utf-8");
|
|
10075
10110
|
content = setTopLevelField(content, "assignee", validation.value);
|
|
10076
10111
|
content = setTopLevelField(content, "updated", nowTimestamp());
|
|
10077
10112
|
await writeFileForce(assignmentPath, content);
|
|
@@ -10102,7 +10137,7 @@ ${entry}`;
|
|
|
10102
10137
|
res.status(400).json({ error: validation.error });
|
|
10103
10138
|
return;
|
|
10104
10139
|
}
|
|
10105
|
-
let content = await
|
|
10140
|
+
let content = await readFile15(assignmentPath, "utf-8");
|
|
10106
10141
|
content = setTopLevelField(content, "title", validation.value);
|
|
10107
10142
|
content = setTopLevelField(content, "updated", nowTimestamp());
|
|
10108
10143
|
await writeFileForce(assignmentPath, content);
|
|
@@ -10620,7 +10655,7 @@ ${entry}`;
|
|
|
10620
10655
|
res.status(400).json({ error: `Invalid status. Must be one of: ${validStatuses.join(", ")}.` });
|
|
10621
10656
|
return;
|
|
10622
10657
|
}
|
|
10623
|
-
let content = await
|
|
10658
|
+
let content = await readFile15(assignmentPath, "utf-8");
|
|
10624
10659
|
content = setTopLevelField(content, "status", status);
|
|
10625
10660
|
content = setTopLevelField(content, "updated", nowTimestamp());
|
|
10626
10661
|
if (status !== "blocked") {
|
|
@@ -10656,7 +10691,7 @@ ${entry}`;
|
|
|
10656
10691
|
res.status(400).json({ error: validation.error });
|
|
10657
10692
|
return;
|
|
10658
10693
|
}
|
|
10659
|
-
let content = await
|
|
10694
|
+
let content = await readFile15(assignmentPath, "utf-8");
|
|
10660
10695
|
content = setTopLevelField(content, "assignee", validation.value);
|
|
10661
10696
|
content = setTopLevelField(content, "updated", nowTimestamp());
|
|
10662
10697
|
await writeFileForce(assignmentPath, content);
|
|
@@ -10689,7 +10724,7 @@ ${entry}`;
|
|
|
10689
10724
|
res.status(400).json({ error: validation.error });
|
|
10690
10725
|
return;
|
|
10691
10726
|
}
|
|
10692
|
-
let content = await
|
|
10727
|
+
let content = await readFile15(assignmentPath, "utf-8");
|
|
10693
10728
|
content = setTopLevelField(content, "title", validation.value);
|
|
10694
10729
|
content = setTopLevelField(content, "updated", nowTimestamp());
|
|
10695
10730
|
await writeFileForce(assignmentPath, content);
|
|
@@ -10826,7 +10861,7 @@ async function appendCommentTo(assignmentDir, assignmentRef, req, res, reloadDet
|
|
|
10826
10861
|
let currentContent;
|
|
10827
10862
|
let currentCount = 0;
|
|
10828
10863
|
if (await fileExists(commentsPath)) {
|
|
10829
|
-
currentContent = await
|
|
10864
|
+
currentContent = await readFile15(commentsPath, "utf-8");
|
|
10830
10865
|
const countMatch = currentContent.match(/^entryCount:\s*(\d+)/m);
|
|
10831
10866
|
if (countMatch) currentCount = parseInt(countMatch[1], 10);
|
|
10832
10867
|
} else {
|
|
@@ -10866,7 +10901,7 @@ async function toggleCommentResolvedAt(assignmentDir, commentId, req, res, reloa
|
|
|
10866
10901
|
res.status(400).json({ error: "resolved (boolean) is required" });
|
|
10867
10902
|
return;
|
|
10868
10903
|
}
|
|
10869
|
-
const content = await
|
|
10904
|
+
const content = await readFile15(commentsPath, "utf-8");
|
|
10870
10905
|
const parsed = parseComments(content);
|
|
10871
10906
|
const target = parsed.entries.find((e) => e.id === commentId);
|
|
10872
10907
|
if (!target) {
|
|
@@ -11694,7 +11729,7 @@ import { Router as Router8 } from "express";
|
|
|
11694
11729
|
|
|
11695
11730
|
// src/utils/status-config-resolution.ts
|
|
11696
11731
|
init_frontmatter();
|
|
11697
|
-
import { readFile as
|
|
11732
|
+
import { readFile as readFile16, writeFile as writeFile4, rm as rm2 } from "fs/promises";
|
|
11698
11733
|
import { dirname as dirname4 } from "path";
|
|
11699
11734
|
|
|
11700
11735
|
// src/utils/assignment-walk.ts
|
|
@@ -11777,7 +11812,7 @@ async function scanAssignmentsByStatus(projectsDir, standaloneDir, ids) {
|
|
|
11777
11812
|
const assignmentPath = `${entry.assignmentDir}/assignment.md`;
|
|
11778
11813
|
let content;
|
|
11779
11814
|
try {
|
|
11780
|
-
content = await
|
|
11815
|
+
content = await readFile16(assignmentPath, "utf-8");
|
|
11781
11816
|
} catch (err) {
|
|
11782
11817
|
const code = err?.code;
|
|
11783
11818
|
if (code === "ENOENT") {
|
|
@@ -11840,7 +11875,7 @@ async function applyStatusResolutions(resolutions, affected, validTargets) {
|
|
|
11840
11875
|
const list = affected.get(r.id) ?? [];
|
|
11841
11876
|
for (const a of list) {
|
|
11842
11877
|
try {
|
|
11843
|
-
const content = await
|
|
11878
|
+
const content = await readFile16(a.path, "utf-8");
|
|
11844
11879
|
buffer.set(a.path, content);
|
|
11845
11880
|
} catch (err) {
|
|
11846
11881
|
const code = err?.code;
|
|
@@ -11868,7 +11903,7 @@ async function applyStatusResolutions(resolutions, affected, validTargets) {
|
|
|
11868
11903
|
for (const a of list) {
|
|
11869
11904
|
let current;
|
|
11870
11905
|
try {
|
|
11871
|
-
current = await
|
|
11906
|
+
current = await readFile16(a.path, "utf-8");
|
|
11872
11907
|
} catch (err) {
|
|
11873
11908
|
const code = err?.code;
|
|
11874
11909
|
if (code === "ENOENT") {
|
|
@@ -11917,7 +11952,7 @@ async function applyStatusResolutions(resolutions, affected, validTargets) {
|
|
|
11917
11952
|
const list = affected.get(r.id) ?? [];
|
|
11918
11953
|
for (const a of list) {
|
|
11919
11954
|
try {
|
|
11920
|
-
const current = await
|
|
11955
|
+
const current = await readFile16(a.path, "utf-8");
|
|
11921
11956
|
const fm = parseAssignmentFrontmatter(current);
|
|
11922
11957
|
if (fm.status !== r.id) {
|
|
11923
11958
|
console.warn(
|
|
@@ -12792,7 +12827,7 @@ init_timestamp();
|
|
|
12792
12827
|
init_fs();
|
|
12793
12828
|
import { Router as Router11 } from "express";
|
|
12794
12829
|
import { resolve as resolve23 } from "path";
|
|
12795
|
-
import { readFile as
|
|
12830
|
+
import { readFile as readFile17 } from "fs/promises";
|
|
12796
12831
|
init_playbooks();
|
|
12797
12832
|
function statusForPlaybookError(code) {
|
|
12798
12833
|
switch (code) {
|
|
@@ -12875,7 +12910,7 @@ function createPlaybooksRouter(playbooksDir2) {
|
|
|
12875
12910
|
return;
|
|
12876
12911
|
}
|
|
12877
12912
|
const filePath = resolve23(playbooksDir2, resolved.filename);
|
|
12878
|
-
const content = await
|
|
12913
|
+
const content = await readFile17(filePath, "utf-8");
|
|
12879
12914
|
res.json({
|
|
12880
12915
|
documentType: "playbook",
|
|
12881
12916
|
title: `Edit Playbook: ${resolved.slug}`,
|
|
@@ -13562,7 +13597,7 @@ function createTodosRouter(todosDir2, broadcast, projectsDir) {
|
|
|
13562
13597
|
try {
|
|
13563
13598
|
const { archivePath: archivePath2 } = await Promise.resolve().then(() => (init_parser2(), parser_exports));
|
|
13564
13599
|
const { resolve: resolve29 } = await import("path");
|
|
13565
|
-
const { readFile:
|
|
13600
|
+
const { readFile: readFile21 } = await import("fs/promises");
|
|
13566
13601
|
const { writeFileForce: writeFileForce2 } = await Promise.resolve().then(() => (init_fs(), fs_exports));
|
|
13567
13602
|
const workspace = getWorkspaceParam(req.params.workspace);
|
|
13568
13603
|
const checklist = await readChecklist(todosDir2, workspace);
|
|
@@ -13581,7 +13616,7 @@ function createTodosRouter(todosDir2, broadcast, projectsDir) {
|
|
|
13581
13616
|
await ensureDir(resolve29(todosDir2, "archive"));
|
|
13582
13617
|
let archContent = "";
|
|
13583
13618
|
if (await fileExists(archFile)) {
|
|
13584
|
-
archContent = await
|
|
13619
|
+
archContent = await readFile21(archFile, "utf-8");
|
|
13585
13620
|
archContent = archContent.trimEnd() + "\n\n";
|
|
13586
13621
|
} else {
|
|
13587
13622
|
archContent = `---
|
|
@@ -13863,7 +13898,7 @@ workspace: ${workspace}
|
|
|
13863
13898
|
const { readConfig: readConfig2 } = await Promise.resolve().then(() => (init_config2(), config_exports));
|
|
13864
13899
|
const { assignmentsDir: assignmentsDirFn } = await Promise.resolve().then(() => (init_paths(), paths_exports));
|
|
13865
13900
|
const { fileExists: fileExists2, writeFileForce: writeFileForce2 } = await Promise.resolve().then(() => (init_fs(), fs_exports));
|
|
13866
|
-
const { readFile:
|
|
13901
|
+
const { readFile: readFile21 } = await import("fs/promises");
|
|
13867
13902
|
const { appendTodosToAssignmentBody: appendTodosToAssignmentBody2, touchAssignmentUpdated: touchAssignmentUpdated2 } = await Promise.resolve().then(() => (init_assignment_todos(), assignment_todos_exports));
|
|
13868
13903
|
const { nowTimestamp: nowTimestamp3 } = await Promise.resolve().then(() => (init_timestamp(), timestamp_exports));
|
|
13869
13904
|
let assignmentRef;
|
|
@@ -13884,7 +13919,7 @@ workspace: ${workspace}
|
|
|
13884
13919
|
}
|
|
13885
13920
|
const assignmentMdPath = resolvePath2(assignmentDir, "assignment.md");
|
|
13886
13921
|
if (!await fileExists2(assignmentMdPath)) return { error: `Target assignment not found: ${assignmentMdPath}` };
|
|
13887
|
-
let content = await
|
|
13922
|
+
let content = await readFile21(assignmentMdPath, "utf-8");
|
|
13888
13923
|
content = appendTodosToAssignmentBody2(
|
|
13889
13924
|
content,
|
|
13890
13925
|
items.map((it) => ({
|
|
@@ -14072,7 +14107,7 @@ init_fs();
|
|
|
14072
14107
|
init_paths();
|
|
14073
14108
|
init_slug();
|
|
14074
14109
|
import { Router as Router13 } from "express";
|
|
14075
|
-
import { mkdir as mkdir3, readFile as
|
|
14110
|
+
import { mkdir as mkdir3, readFile as readFile18, rename as rename6 } from "fs/promises";
|
|
14076
14111
|
import { resolve as resolve25, dirname as dirname6 } from "path";
|
|
14077
14112
|
init_api();
|
|
14078
14113
|
var WORKSPACE_REGEX2 = /^[a-z0-9_][a-z0-9-]*$/;
|
|
@@ -14296,7 +14331,7 @@ function createProjectTodosRouter(projectsDir, broadcast, workspaceTodosDir) {
|
|
|
14296
14331
|
const archFile = archivePath(todosDir2, slug, checklist.archiveInterval);
|
|
14297
14332
|
let archContent = "";
|
|
14298
14333
|
if (await fileExists(archFile)) {
|
|
14299
|
-
archContent = await
|
|
14334
|
+
archContent = await readFile18(archFile, "utf-8");
|
|
14300
14335
|
archContent = archContent.trimEnd() + "\n\n";
|
|
14301
14336
|
} else {
|
|
14302
14337
|
archContent = `---
|
|
@@ -14753,7 +14788,7 @@ workspace: ${slug}
|
|
|
14753
14788
|
}
|
|
14754
14789
|
const assignmentMdPath = resolve25(assignmentDir, "assignment.md");
|
|
14755
14790
|
if (!await fileExists(assignmentMdPath)) return { error: `Target assignment not found: ${assignmentMdPath}` };
|
|
14756
|
-
let content = await
|
|
14791
|
+
let content = await readFile18(assignmentMdPath, "utf-8");
|
|
14757
14792
|
content = appendTodosToAssignmentBody2(
|
|
14758
14793
|
content,
|
|
14759
14794
|
items.map((it) => ({
|
|
@@ -14957,7 +14992,7 @@ init_fs();
|
|
|
14957
14992
|
init_paths();
|
|
14958
14993
|
init_parser2();
|
|
14959
14994
|
import { randomBytes as randomBytes2 } from "crypto";
|
|
14960
|
-
import { readFile as
|
|
14995
|
+
import { readFile as readFile19 } from "fs/promises";
|
|
14961
14996
|
var BUNDLE_ID_REGEX = /^[a-f0-9]{4}$/;
|
|
14962
14997
|
var SCOPE_VALUES = /* @__PURE__ */ new Set(["workspace", "project", "global"]);
|
|
14963
14998
|
var SCOPE_ID_REGEX = /^[a-z0-9_][a-z0-9_-]*$/;
|
|
@@ -15024,7 +15059,7 @@ function parseBundles(content) {
|
|
|
15024
15059
|
async function readBundles(todosDir2) {
|
|
15025
15060
|
const path = bundlesPath(todosDir2);
|
|
15026
15061
|
if (!await fileExists(path)) return [];
|
|
15027
|
-
const content = await
|
|
15062
|
+
const content = await readFile19(path, "utf-8");
|
|
15028
15063
|
return parseBundles(content).bundles;
|
|
15029
15064
|
}
|
|
15030
15065
|
|
|
@@ -15197,7 +15232,7 @@ init_fs();
|
|
|
15197
15232
|
init_config2();
|
|
15198
15233
|
import { execFile as execFile2 } from "child_process";
|
|
15199
15234
|
import { promisify as promisify2 } from "util";
|
|
15200
|
-
import { cp, mkdtemp, rm as rm3, readFile as
|
|
15235
|
+
import { cp, mkdtemp, rm as rm3, readFile as readFile20, writeFile as writeFile5, unlink as unlink5, stat, open as open2, rename as rename7 } from "fs/promises";
|
|
15201
15236
|
import { resolve as resolve27, join as join3 } from "path";
|
|
15202
15237
|
import { tmpdir } from "os";
|
|
15203
15238
|
var exec2 = promisify2(execFile2);
|
|
@@ -15258,7 +15293,7 @@ async function acquireLock() {
|
|
|
15258
15293
|
return lockPath;
|
|
15259
15294
|
} catch (err) {
|
|
15260
15295
|
if (err.code === "EEXIST") {
|
|
15261
|
-
const pid = await
|
|
15296
|
+
const pid = await readFile20(lockPath, "utf-8").catch(() => "");
|
|
15262
15297
|
throw new Error(
|
|
15263
15298
|
`Backup operation already in progress (lock file at ${lockPath}, pid ${pid.trim() || "unknown"}). If stale, delete the file and retry.`
|
|
15264
15299
|
);
|
|
@@ -15305,7 +15340,7 @@ function resolveCategoriesStrict(csv) {
|
|
|
15305
15340
|
return parseCategoriesStrict(parts);
|
|
15306
15341
|
}
|
|
15307
15342
|
async function readSanitizedConfig(configPath) {
|
|
15308
|
-
const content = await
|
|
15343
|
+
const content = await readFile20(configPath, "utf-8");
|
|
15309
15344
|
return content.replace(/^(\s*lastBackup:\s*).*$/m, "$1null").replace(/^(\s*lastRestore:\s*).*$/m, "$1null");
|
|
15310
15345
|
}
|
|
15311
15346
|
async function backupToGithub(overrides) {
|