syntaur 0.17.1 → 0.17.2
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/.claude-plugin/plugin.json +2 -1
- package/dashboard/dist/assets/{_basePickBy-Dek5-ACb.js → _basePickBy-DiPrdxAJ.js} +1 -1
- package/dashboard/dist/assets/{_baseUniq-BeLddDKU.js → _baseUniq-CChFfAnf.js} +1 -1
- package/dashboard/dist/assets/{arc-kotdj4Uh.js → arc-CfkGktFw.js} +1 -1
- package/dashboard/dist/assets/{architectureDiagram-2XIMDMQ5-BaqFXQ-q.js → architectureDiagram-2XIMDMQ5-hFcMu5eO.js} +1 -1
- package/dashboard/dist/assets/{blockDiagram-WCTKOSBZ-BSyGne6h.js → blockDiagram-WCTKOSBZ-GZDth9sZ.js} +1 -1
- package/dashboard/dist/assets/{c4Diagram-IC4MRINW-iYjZFKOW.js → c4Diagram-IC4MRINW-BVajqiYz.js} +1 -1
- package/dashboard/dist/assets/channel-C3CI1Xiu.js +1 -0
- package/dashboard/dist/assets/{chunk-4BX2VUAB-DvY9Y7jB.js → chunk-4BX2VUAB-L7ajwHyw.js} +1 -1
- package/dashboard/dist/assets/{chunk-55IACEB6-2vCDm2cJ.js → chunk-55IACEB6-BACmeqT4.js} +1 -1
- package/dashboard/dist/assets/{chunk-FMBD7UC4-BVPaoRtV.js → chunk-FMBD7UC4-BYQ2kuuH.js} +1 -1
- package/dashboard/dist/assets/{chunk-JSJVCQXG-B9uJpMzd.js → chunk-JSJVCQXG-akulVsXk.js} +1 -1
- package/dashboard/dist/assets/{chunk-KX2RTZJC-CHcjjGaq.js → chunk-KX2RTZJC-4ibFxLB_.js} +1 -1
- package/dashboard/dist/assets/{chunk-NQ4KR5QH-B8n19pSs.js → chunk-NQ4KR5QH-DU4iJf0Y.js} +1 -1
- package/dashboard/dist/assets/{chunk-QZHKN3VN-CF9ZYFGK.js → chunk-QZHKN3VN-ouyGBhQB.js} +1 -1
- package/dashboard/dist/assets/{chunk-WL4C6EOR-mY_1Vmdf.js → chunk-WL4C6EOR-Pq-ySwIY.js} +1 -1
- package/dashboard/dist/assets/classDiagram-VBA2DB6C-Ck2tXWRf.js +1 -0
- package/dashboard/dist/assets/classDiagram-v2-RAHNMMFH-Ck2tXWRf.js +1 -0
- package/dashboard/dist/assets/clone-BEaO4u3F.js +1 -0
- package/dashboard/dist/assets/{cose-bilkent-S5V4N54A-DOYoG3gB.js → cose-bilkent-S5V4N54A-BfkMWgQb.js} +1 -1
- package/dashboard/dist/assets/{dagre-KLK3FWXG-CZFrp-Yq.js → dagre-KLK3FWXG-0yhY8ZsO.js} +1 -1
- package/dashboard/dist/assets/{diagram-E7M64L7V-F3rF5YwM.js → diagram-E7M64L7V-DBkanpFi.js} +1 -1
- package/dashboard/dist/assets/{diagram-IFDJBPK2-BynWv-Vo.js → diagram-IFDJBPK2-CrucCpxV.js} +1 -1
- package/dashboard/dist/assets/{diagram-P4PSJMXO-NIyzhm_M.js → diagram-P4PSJMXO-BJrQ6lK3.js} +1 -1
- package/dashboard/dist/assets/{erDiagram-INFDFZHY-Ca9NbihE.js → erDiagram-INFDFZHY--joDpxAm.js} +1 -1
- package/dashboard/dist/assets/{flowDiagram-PKNHOUZH-YhS0MOu4.js → flowDiagram-PKNHOUZH-BUXiVwju.js} +1 -1
- package/dashboard/dist/assets/{ganttDiagram-A5KZAMGK-G7P3qq_2.js → ganttDiagram-A5KZAMGK-u2XuIMRA.js} +1 -1
- package/dashboard/dist/assets/{gitGraphDiagram-K3NZZRJ6-BJAK7M7E.js → gitGraphDiagram-K3NZZRJ6-Ayf0-gwT.js} +1 -1
- package/dashboard/dist/assets/{graph-11geMy3f.js → graph-BUGVXq3c.js} +1 -1
- package/dashboard/dist/assets/index-Bv6vn4_x.js +535 -0
- package/dashboard/dist/assets/{infoDiagram-LFFYTUFH-COcQYcLf.js → infoDiagram-LFFYTUFH-DYehx6g7.js} +1 -1
- package/dashboard/dist/assets/{ishikawaDiagram-PHBUUO56-B7Jjyw8J.js → ishikawaDiagram-PHBUUO56-Bo8-BClf.js} +1 -1
- package/dashboard/dist/assets/{journeyDiagram-4ABVD52K--snU-QAX.js → journeyDiagram-4ABVD52K-DLm-bRYd.js} +1 -1
- package/dashboard/dist/assets/{kanban-definition-K7BYSVSG-BucLoc89.js → kanban-definition-K7BYSVSG-stPdEvds.js} +1 -1
- package/dashboard/dist/assets/{layout-Bcgxdz8A.js → layout-B7aPbDvN.js} +1 -1
- package/dashboard/dist/assets/{linear-CRF8xwvk.js → linear-CtQ_RMAp.js} +1 -1
- package/dashboard/dist/assets/{mermaid.core-D5JD5uYg.js → mermaid.core-CcJoQ5At.js} +4 -4
- package/dashboard/dist/assets/{mindmap-definition-YRQLILUH-BqGcTcbk.js → mindmap-definition-YRQLILUH-DahXO6Ui.js} +1 -1
- package/dashboard/dist/assets/{pieDiagram-SKSYHLDU-CnQ2EkyX.js → pieDiagram-SKSYHLDU-DXv973_0.js} +1 -1
- package/dashboard/dist/assets/{quadrantDiagram-337W2JSQ-CKCfmTRc.js → quadrantDiagram-337W2JSQ-5U0ryvjr.js} +1 -1
- package/dashboard/dist/assets/{requirementDiagram-Z7DCOOCP-B9J4bvUK.js → requirementDiagram-Z7DCOOCP-CvGflSyl.js} +1 -1
- package/dashboard/dist/assets/{sankeyDiagram-WA2Y5GQK-CMSzI5rg.js → sankeyDiagram-WA2Y5GQK-AeetdpCi.js} +1 -1
- package/dashboard/dist/assets/{sequenceDiagram-2WXFIKYE-BFQDtxd0.js → sequenceDiagram-2WXFIKYE-BhRR4qzn.js} +1 -1
- package/dashboard/dist/assets/{stateDiagram-RAJIS63D-DgWYKT02.js → stateDiagram-RAJIS63D-CxxF58nH.js} +1 -1
- package/dashboard/dist/assets/stateDiagram-v2-FVOUBMTO-DHCNHbs7.js +1 -0
- package/dashboard/dist/assets/{timeline-definition-YZTLITO2-jANu0e7M.js → timeline-definition-YZTLITO2-BEQIeygp.js} +1 -1
- package/dashboard/dist/assets/{treemap-KZPCXAKY-BFjWMkyM.js → treemap-KZPCXAKY-BCWNTFfj.js} +1 -1
- package/dashboard/dist/assets/{vennDiagram-LZ73GAT5-DGwrAJYj.js → vennDiagram-LZ73GAT5-BcuC_UIz.js} +1 -1
- package/dashboard/dist/assets/{xychartDiagram-JWTSCODW-BLCPfoFM.js → xychartDiagram-JWTSCODW-CWGez3_f.js} +1 -1
- package/dashboard/dist/index.html +1 -1
- package/dist/dashboard/server.js +198 -160
- package/dist/dashboard/server.js.map +1 -1
- package/dist/index.js +329 -290
- package/dist/index.js.map +1 -1
- package/dist/launch/index.js +20 -1
- package/dist/launch/index.js.map +1 -1
- package/package.json +1 -1
- package/platforms/claude-code/.claude-plugin/plugin.json +2 -1
- package/platforms/claude-code/commands/run-playbook/run-playbook.md +16 -0
- package/platforms/claude-code/skills/run-playbook/SKILL.md +87 -0
- package/platforms/codex/skills/run-playbook/SKILL.md +87 -0
- package/skills/run-playbook/SKILL.md +87 -0
- package/dashboard/dist/assets/channel-eXdj7ayV.js +0 -1
- package/dashboard/dist/assets/classDiagram-VBA2DB6C-B-bBQACr.js +0 -1
- package/dashboard/dist/assets/classDiagram-v2-RAHNMMFH-B-bBQACr.js +0 -1
- package/dashboard/dist/assets/clone-CL04pv9J.js +0 -1
- package/dashboard/dist/assets/index--qwybK3W.js +0 -535
- package/dashboard/dist/assets/stateDiagram-v2-FVOUBMTO-Nmwft4cR.js +0 -1
package/dist/index.js
CHANGED
|
@@ -5042,8 +5042,8 @@ async function migrateFromMarkdown(projectsDir2) {
|
|
|
5042
5042
|
return allSessions.length;
|
|
5043
5043
|
}
|
|
5044
5044
|
async function parseMarkdownSessionsIndex(filePath, projectSlug) {
|
|
5045
|
-
const { readFile:
|
|
5046
|
-
const raw = await
|
|
5045
|
+
const { readFile: readFile53 } = await import("fs/promises");
|
|
5046
|
+
const raw = await readFile53(filePath, "utf-8");
|
|
5047
5047
|
const sessions = [];
|
|
5048
5048
|
const lines = raw.split("\n");
|
|
5049
5049
|
let inTable = false;
|
|
@@ -5460,12 +5460,13 @@ __export(scanner_exports, {
|
|
|
5460
5460
|
import { execFile } from "child_process";
|
|
5461
5461
|
import { promisify } from "util";
|
|
5462
5462
|
import { resolve as resolve15 } from "path";
|
|
5463
|
-
import { realpath
|
|
5463
|
+
import { realpath } from "fs/promises";
|
|
5464
5464
|
function clearScanCache() {
|
|
5465
5465
|
cache = null;
|
|
5466
5466
|
forceFreshNext = true;
|
|
5467
5467
|
scanEpoch++;
|
|
5468
5468
|
inFlight = null;
|
|
5469
|
+
tmuxAvailableCache = null;
|
|
5469
5470
|
}
|
|
5470
5471
|
function emptyScan() {
|
|
5471
5472
|
return { sessions: [], tmuxAvailable: false };
|
|
@@ -5523,8 +5524,10 @@ async function execQuiet(cmd, args) {
|
|
|
5523
5524
|
}
|
|
5524
5525
|
}
|
|
5525
5526
|
async function checkTmuxAvailable() {
|
|
5526
|
-
|
|
5527
|
-
|
|
5527
|
+
if (!tmuxAvailableCache) {
|
|
5528
|
+
tmuxAvailableCache = execQuiet("which", ["tmux"]).then((result) => result.length > 0);
|
|
5529
|
+
}
|
|
5530
|
+
return tmuxAvailableCache;
|
|
5528
5531
|
}
|
|
5529
5532
|
async function sessionAlive(name) {
|
|
5530
5533
|
try {
|
|
@@ -5619,62 +5622,11 @@ async function getGitInfo(cwd) {
|
|
|
5619
5622
|
return { branch: branch || null, worktree: isWorktree };
|
|
5620
5623
|
}
|
|
5621
5624
|
async function loadWorkspaceRecords(projectsDir2, assignmentsDir2) {
|
|
5622
|
-
const records = [];
|
|
5623
5625
|
try {
|
|
5624
|
-
|
|
5625
|
-
for (const project of projects) {
|
|
5626
|
-
const projectAssignmentsDir = resolve15(projectsDir2, project.slug, "assignments");
|
|
5627
|
-
let slugs;
|
|
5628
|
-
try {
|
|
5629
|
-
slugs = await readdir8(projectAssignmentsDir);
|
|
5630
|
-
} catch {
|
|
5631
|
-
continue;
|
|
5632
|
-
}
|
|
5633
|
-
for (const aslug of slugs) {
|
|
5634
|
-
const aFile = resolve15(projectAssignmentsDir, aslug, "assignment.md");
|
|
5635
|
-
try {
|
|
5636
|
-
const raw = await readFile10(aFile, "utf-8");
|
|
5637
|
-
const [fm] = extractFrontmatter(raw);
|
|
5638
|
-
if (!fm) continue;
|
|
5639
|
-
records.push({
|
|
5640
|
-
projectSlug: project.slug,
|
|
5641
|
-
assignmentSlug: aslug,
|
|
5642
|
-
assignmentTitle: getField(fm, "title") ?? aslug,
|
|
5643
|
-
worktreePath: getNestedField(fm, "workspace", "worktreePath") ?? null,
|
|
5644
|
-
branch: getNestedField(fm, "workspace", "branch") ?? null
|
|
5645
|
-
});
|
|
5646
|
-
} catch {
|
|
5647
|
-
continue;
|
|
5648
|
-
}
|
|
5649
|
-
}
|
|
5650
|
-
}
|
|
5626
|
+
return await listWorkspaceRecords(projectsDir2, assignmentsDir2);
|
|
5651
5627
|
} catch {
|
|
5628
|
+
return [];
|
|
5652
5629
|
}
|
|
5653
|
-
if (assignmentsDir2) {
|
|
5654
|
-
try {
|
|
5655
|
-
const entries = await readdir8(assignmentsDir2);
|
|
5656
|
-
for (const id of entries) {
|
|
5657
|
-
if (id.startsWith(".") || id.startsWith("_")) continue;
|
|
5658
|
-
const aFile = resolve15(assignmentsDir2, id, "assignment.md");
|
|
5659
|
-
try {
|
|
5660
|
-
const raw = await readFile10(aFile, "utf-8");
|
|
5661
|
-
const [fm] = extractFrontmatter(raw);
|
|
5662
|
-
if (!fm) continue;
|
|
5663
|
-
records.push({
|
|
5664
|
-
projectSlug: null,
|
|
5665
|
-
assignmentSlug: id,
|
|
5666
|
-
assignmentTitle: getField(fm, "title") ?? id,
|
|
5667
|
-
worktreePath: getNestedField(fm, "workspace", "worktreePath") ?? null,
|
|
5668
|
-
branch: getNestedField(fm, "workspace", "branch") ?? null
|
|
5669
|
-
});
|
|
5670
|
-
} catch {
|
|
5671
|
-
continue;
|
|
5672
|
-
}
|
|
5673
|
-
}
|
|
5674
|
-
} catch {
|
|
5675
|
-
}
|
|
5676
|
-
}
|
|
5677
|
-
return records;
|
|
5678
5630
|
}
|
|
5679
5631
|
async function resolveAndNormalize(p) {
|
|
5680
5632
|
try {
|
|
@@ -5945,13 +5897,12 @@ async function scanSingleSession(serversDir2, projectsDir2, name, options) {
|
|
|
5945
5897
|
}
|
|
5946
5898
|
return scanSession(data, lsofOutput, workspaceRecords, procSnapshot);
|
|
5947
5899
|
}
|
|
5948
|
-
var exec, cache, lastKnown, inFlight, forceFreshNext, scanEpoch, cacheKey, CACHE_TTL_MS, COLD_WAIT_BUDGET_MS, PROBE_TIMEOUT_MS, PROBE_MAX_BUFFER;
|
|
5900
|
+
var exec, cache, lastKnown, inFlight, forceFreshNext, scanEpoch, cacheKey, CACHE_TTL_MS, COLD_WAIT_BUDGET_MS, PROBE_TIMEOUT_MS, PROBE_MAX_BUFFER, tmuxAvailableCache;
|
|
5949
5901
|
var init_scanner = __esm({
|
|
5950
5902
|
"src/dashboard/scanner.ts"() {
|
|
5951
5903
|
"use strict";
|
|
5952
5904
|
init_api();
|
|
5953
5905
|
init_servers();
|
|
5954
|
-
init_parser();
|
|
5955
5906
|
exec = promisify(execFile);
|
|
5956
5907
|
cache = null;
|
|
5957
5908
|
lastKnown = null;
|
|
@@ -5963,11 +5914,12 @@ var init_scanner = __esm({
|
|
|
5963
5914
|
COLD_WAIT_BUDGET_MS = 2500;
|
|
5964
5915
|
PROBE_TIMEOUT_MS = 15e3;
|
|
5965
5916
|
PROBE_MAX_BUFFER = 32 * 1024 * 1024;
|
|
5917
|
+
tmuxAvailableCache = null;
|
|
5966
5918
|
}
|
|
5967
5919
|
});
|
|
5968
5920
|
|
|
5969
5921
|
// src/dashboard/api.ts
|
|
5970
|
-
import { readdir as
|
|
5922
|
+
import { readdir as readdir8, readFile as readFile10, writeFile as writeFile3 } from "fs/promises";
|
|
5971
5923
|
import { resolve as resolve16, dirname as dirname3, basename } from "path";
|
|
5972
5924
|
function clearFrontmatterField(content, key) {
|
|
5973
5925
|
const fieldRegex = new RegExp(`^(${escapeRegExp2(key)}:)\\s*.*$`, "m");
|
|
@@ -6007,10 +5959,41 @@ function emitTrace(traces, meta) {
|
|
|
6007
5959
|
JSON.stringify({ kind: "overview-trace", totalMs, phases: traces.entries, subPhases, ...meta })
|
|
6008
5960
|
);
|
|
6009
5961
|
}
|
|
5962
|
+
function invalidateRecordsCache() {
|
|
5963
|
+
projectRecordsCache.clear();
|
|
5964
|
+
standaloneRecordsCache.clear();
|
|
5965
|
+
}
|
|
5966
|
+
function installRecordsInvalidation(router) {
|
|
5967
|
+
for (const method of ["post", "put", "patch", "delete"]) {
|
|
5968
|
+
const original = router[method].bind(router);
|
|
5969
|
+
router[method] = (path, ...handlers) => {
|
|
5970
|
+
if (handlers.length > 0) {
|
|
5971
|
+
const last = handlers[handlers.length - 1];
|
|
5972
|
+
handlers[handlers.length - 1] = async (req, res, next) => {
|
|
5973
|
+
try {
|
|
5974
|
+
return await last(req, res, next);
|
|
5975
|
+
} finally {
|
|
5976
|
+
invalidateRecordsCache();
|
|
5977
|
+
}
|
|
5978
|
+
};
|
|
5979
|
+
}
|
|
5980
|
+
return original(path, ...handlers);
|
|
5981
|
+
};
|
|
5982
|
+
}
|
|
5983
|
+
}
|
|
6010
5984
|
async function listStandaloneRecords(assignmentsDir2) {
|
|
5985
|
+
const key = assignmentsDir2 ?? "";
|
|
5986
|
+
const cached = standaloneRecordsCache.get(key);
|
|
5987
|
+
if (cached) return cached;
|
|
5988
|
+
const promise = computeStandaloneRecords(assignmentsDir2);
|
|
5989
|
+
standaloneRecordsCache.set(key, promise);
|
|
5990
|
+
promise.catch(() => standaloneRecordsCache.delete(key));
|
|
5991
|
+
return promise;
|
|
5992
|
+
}
|
|
5993
|
+
async function computeStandaloneRecords(assignmentsDir2) {
|
|
6011
5994
|
if (!assignmentsDir2) return [];
|
|
6012
5995
|
if (!await fileExists(assignmentsDir2)) return [];
|
|
6013
|
-
const entries = await
|
|
5996
|
+
const entries = await readdir8(assignmentsDir2, { withFileTypes: true });
|
|
6014
5997
|
const records = [];
|
|
6015
5998
|
for (const entry of entries) {
|
|
6016
5999
|
if (!entry.isDirectory() || entry.name.startsWith(".") || entry.name.startsWith("_")) continue;
|
|
@@ -6018,7 +6001,7 @@ async function listStandaloneRecords(assignmentsDir2) {
|
|
|
6018
6001
|
const assignmentMdPath2 = resolve16(assignmentDir, "assignment.md");
|
|
6019
6002
|
if (!await fileExists(assignmentMdPath2)) continue;
|
|
6020
6003
|
try {
|
|
6021
|
-
const content = await
|
|
6004
|
+
const content = await readFile10(assignmentMdPath2, "utf-8");
|
|
6022
6005
|
const record = parseAssignmentFull(content);
|
|
6023
6006
|
records.push({ assignmentDir, id: entry.name, record });
|
|
6024
6007
|
} catch {
|
|
@@ -6094,7 +6077,7 @@ async function listProjects(projectsDir2) {
|
|
|
6094
6077
|
async function readWorkspaceRegistry(projectsDir2) {
|
|
6095
6078
|
const registryPath = resolve16(dirname3(projectsDir2), "workspaces.json");
|
|
6096
6079
|
try {
|
|
6097
|
-
const raw = await
|
|
6080
|
+
const raw = await readFile10(registryPath, "utf-8");
|
|
6098
6081
|
const parsed = JSON.parse(raw);
|
|
6099
6082
|
return Array.isArray(parsed) ? parsed.filter((w) => typeof w === "string") : [];
|
|
6100
6083
|
} catch {
|
|
@@ -6130,6 +6113,34 @@ async function listWorkspaces(projectsDir2, assignmentsDir2) {
|
|
|
6130
6113
|
const workspaces = Array.from(workspaceSet).sort();
|
|
6131
6114
|
return { workspaces, hasUngrouped };
|
|
6132
6115
|
}
|
|
6116
|
+
async function listWorkspaceRecords(projectsDir2, assignmentsDir2) {
|
|
6117
|
+
const [projectRecords, standaloneRecords] = await Promise.all([
|
|
6118
|
+
listProjectRecords(projectsDir2),
|
|
6119
|
+
listStandaloneRecords(assignmentsDir2)
|
|
6120
|
+
]);
|
|
6121
|
+
const records = [];
|
|
6122
|
+
for (const project of projectRecords) {
|
|
6123
|
+
for (const assignment of project.assignments) {
|
|
6124
|
+
records.push({
|
|
6125
|
+
projectSlug: project.summary.slug,
|
|
6126
|
+
assignmentSlug: assignment.slug,
|
|
6127
|
+
assignmentTitle: assignment.title || assignment.slug,
|
|
6128
|
+
worktreePath: assignment.workspace.worktreePath ?? null,
|
|
6129
|
+
branch: assignment.workspace.branch ?? null
|
|
6130
|
+
});
|
|
6131
|
+
}
|
|
6132
|
+
}
|
|
6133
|
+
for (const standalone of standaloneRecords) {
|
|
6134
|
+
records.push({
|
|
6135
|
+
projectSlug: null,
|
|
6136
|
+
assignmentSlug: standalone.id,
|
|
6137
|
+
assignmentTitle: standalone.record.title || standalone.id,
|
|
6138
|
+
worktreePath: standalone.record.workspace.worktreePath ?? null,
|
|
6139
|
+
branch: standalone.record.workspace.branch ?? null
|
|
6140
|
+
});
|
|
6141
|
+
}
|
|
6142
|
+
return records;
|
|
6143
|
+
}
|
|
6133
6144
|
async function createWorkspace(projectsDir2, name) {
|
|
6134
6145
|
const registered = await readWorkspaceRegistry(projectsDir2);
|
|
6135
6146
|
if (!registered.includes(name)) {
|
|
@@ -6155,7 +6166,7 @@ async function deleteWorkspace(projectsDir2, name, opts = {}) {
|
|
|
6155
6166
|
const timestamp = nowTimestamp();
|
|
6156
6167
|
for (const slug of projectsReferencing) {
|
|
6157
6168
|
const path = resolve16(projectsDir2, slug, "project.md");
|
|
6158
|
-
const raw = await
|
|
6169
|
+
const raw = await readFile10(path, "utf-8");
|
|
6159
6170
|
let next = clearFrontmatterField(raw, "workspace");
|
|
6160
6171
|
next = setUpdatedField(next, timestamp);
|
|
6161
6172
|
await writeFileForce(path, next);
|
|
@@ -6164,7 +6175,7 @@ async function deleteWorkspace(projectsDir2, name, opts = {}) {
|
|
|
6164
6175
|
for (const id of standalonesReferencing) {
|
|
6165
6176
|
if (!opts.assignmentsDir) break;
|
|
6166
6177
|
const path = resolve16(opts.assignmentsDir, id, "assignment.md");
|
|
6167
|
-
const raw = await
|
|
6178
|
+
const raw = await readFile10(path, "utf-8");
|
|
6168
6179
|
let next = clearFrontmatterField(raw, "workspaceGroup");
|
|
6169
6180
|
next = setUpdatedField(next, timestamp);
|
|
6170
6181
|
await writeFileForce(path, next);
|
|
@@ -6174,6 +6185,9 @@ async function deleteWorkspace(projectsDir2, name, opts = {}) {
|
|
|
6174
6185
|
const registered = await readWorkspaceRegistry(projectsDir2);
|
|
6175
6186
|
const filtered = registered.filter((w) => w !== name);
|
|
6176
6187
|
await writeWorkspaceRegistry(projectsDir2, filtered);
|
|
6188
|
+
if (rewroteFiles) {
|
|
6189
|
+
invalidateRecordsCache();
|
|
6190
|
+
}
|
|
6177
6191
|
return { rewroteFiles };
|
|
6178
6192
|
}
|
|
6179
6193
|
async function getOverview(projectsDir2, serversDir2, assignmentsDir2, options = {}) {
|
|
@@ -6341,7 +6355,7 @@ async function getEditableDocument(projectsDir2, documentType, projectSlug, assi
|
|
|
6341
6355
|
if (!filePath || !await fileExists(filePath)) {
|
|
6342
6356
|
return null;
|
|
6343
6357
|
}
|
|
6344
|
-
const content = await
|
|
6358
|
+
const content = await readFile10(filePath, "utf-8");
|
|
6345
6359
|
const title = getEditableDocumentTitle(documentType, projectSlug, assignmentSlug);
|
|
6346
6360
|
return {
|
|
6347
6361
|
documentType,
|
|
@@ -6367,7 +6381,7 @@ async function getEditableDocumentById(projectsDir2, assignmentsDir2, documentTy
|
|
|
6367
6381
|
if (!fileName) return null;
|
|
6368
6382
|
const filePath = resolve16(resolved.assignmentDir, fileName);
|
|
6369
6383
|
if (!await fileExists(filePath)) return null;
|
|
6370
|
-
const content = await
|
|
6384
|
+
const content = await readFile10(filePath, "utf-8");
|
|
6371
6385
|
const label = resolved.id;
|
|
6372
6386
|
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}`;
|
|
6373
6387
|
return {
|
|
@@ -6386,7 +6400,7 @@ async function getProjectDetail(projectsDir2, slug) {
|
|
|
6386
6400
|
if (!await fileExists(projectMdPath)) {
|
|
6387
6401
|
return null;
|
|
6388
6402
|
}
|
|
6389
|
-
const projectContent = await
|
|
6403
|
+
const projectContent = await readFile10(projectMdPath, "utf-8");
|
|
6390
6404
|
const project = parseProject(projectContent);
|
|
6391
6405
|
const assignments = await listAssignmentRecords(projectPath);
|
|
6392
6406
|
const rollup = await buildProjectRollup(projectPath, project, assignments);
|
|
@@ -6423,18 +6437,18 @@ async function getAssignmentDetail(projectsDir2, projectSlug, assignmentSlug) {
|
|
|
6423
6437
|
if (!await fileExists(assignmentMdPath2)) {
|
|
6424
6438
|
return null;
|
|
6425
6439
|
}
|
|
6426
|
-
const assignmentContent = await
|
|
6440
|
+
const assignmentContent = await readFile10(assignmentMdPath2, "utf-8");
|
|
6427
6441
|
const assignment = parseAssignmentFull(assignmentContent);
|
|
6428
6442
|
let projectWorkspace = null;
|
|
6429
6443
|
const projectMdPath = resolve16(projectsDir2, projectSlug, "project.md");
|
|
6430
6444
|
if (await fileExists(projectMdPath)) {
|
|
6431
|
-
const projectContent = await
|
|
6445
|
+
const projectContent = await readFile10(projectMdPath, "utf-8");
|
|
6432
6446
|
projectWorkspace = parseProject(projectContent).workspace;
|
|
6433
6447
|
}
|
|
6434
6448
|
let plan = null;
|
|
6435
6449
|
const planPath = resolve16(assignmentDir, "plan.md");
|
|
6436
6450
|
if (await fileExists(planPath)) {
|
|
6437
|
-
const planContent = await
|
|
6451
|
+
const planContent = await readFile10(planPath, "utf-8");
|
|
6438
6452
|
const parsed = parsePlan(planContent);
|
|
6439
6453
|
plan = {
|
|
6440
6454
|
status: parsed.status,
|
|
@@ -6445,7 +6459,7 @@ async function getAssignmentDetail(projectsDir2, projectSlug, assignmentSlug) {
|
|
|
6445
6459
|
let scratchpad = null;
|
|
6446
6460
|
const scratchpadPath = resolve16(assignmentDir, "scratchpad.md");
|
|
6447
6461
|
if (await fileExists(scratchpadPath)) {
|
|
6448
|
-
const scratchpadContent = await
|
|
6462
|
+
const scratchpadContent = await readFile10(scratchpadPath, "utf-8");
|
|
6449
6463
|
const parsed = parseScratchpad(scratchpadContent);
|
|
6450
6464
|
scratchpad = {
|
|
6451
6465
|
updated: parsed.updated,
|
|
@@ -6455,7 +6469,7 @@ async function getAssignmentDetail(projectsDir2, projectSlug, assignmentSlug) {
|
|
|
6455
6469
|
let handoff = null;
|
|
6456
6470
|
const handoffPath = resolve16(assignmentDir, "handoff.md");
|
|
6457
6471
|
if (await fileExists(handoffPath)) {
|
|
6458
|
-
const handoffContent = await
|
|
6472
|
+
const handoffContent = await readFile10(handoffPath, "utf-8");
|
|
6459
6473
|
const parsed = parseHandoff(handoffContent);
|
|
6460
6474
|
handoff = {
|
|
6461
6475
|
updated: parsed.updated,
|
|
@@ -6466,7 +6480,7 @@ async function getAssignmentDetail(projectsDir2, projectSlug, assignmentSlug) {
|
|
|
6466
6480
|
let decisionRecord = null;
|
|
6467
6481
|
const decisionRecordPath = resolve16(assignmentDir, "decision-record.md");
|
|
6468
6482
|
if (await fileExists(decisionRecordPath)) {
|
|
6469
|
-
const decisionRecordContent = await
|
|
6483
|
+
const decisionRecordContent = await readFile10(decisionRecordPath, "utf-8");
|
|
6470
6484
|
const parsed = parseDecisionRecord(decisionRecordContent);
|
|
6471
6485
|
decisionRecord = {
|
|
6472
6486
|
updated: parsed.updated,
|
|
@@ -6477,7 +6491,7 @@ async function getAssignmentDetail(projectsDir2, projectSlug, assignmentSlug) {
|
|
|
6477
6491
|
let progress = null;
|
|
6478
6492
|
const progressPath = resolve16(assignmentDir, "progress.md");
|
|
6479
6493
|
if (await fileExists(progressPath)) {
|
|
6480
|
-
const progressContent = await
|
|
6494
|
+
const progressContent = await readFile10(progressPath, "utf-8");
|
|
6481
6495
|
const parsed = parseProgress(progressContent);
|
|
6482
6496
|
progress = {
|
|
6483
6497
|
updated: parsed.updated,
|
|
@@ -6488,7 +6502,7 @@ async function getAssignmentDetail(projectsDir2, projectSlug, assignmentSlug) {
|
|
|
6488
6502
|
let comments = null;
|
|
6489
6503
|
const commentsPath = resolve16(assignmentDir, "comments.md");
|
|
6490
6504
|
if (await fileExists(commentsPath)) {
|
|
6491
|
-
const commentsContent = await
|
|
6505
|
+
const commentsContent = await readFile10(commentsPath, "utf-8");
|
|
6492
6506
|
const parsed = parseComments(commentsContent);
|
|
6493
6507
|
comments = {
|
|
6494
6508
|
updated: parsed.updated,
|
|
@@ -6639,7 +6653,7 @@ async function countMentionsInAssignment(sourceDir, target) {
|
|
|
6639
6653
|
const bodies = [];
|
|
6640
6654
|
const assignmentMd = resolve16(sourceDir, "assignment.md");
|
|
6641
6655
|
if (await fileExists(assignmentMd)) {
|
|
6642
|
-
const content = await
|
|
6656
|
+
const content = await readFile10(assignmentMd, "utf-8");
|
|
6643
6657
|
const todosMatch = content.match(/^## Todos\s*$([\s\S]*?)(?=^## |$(?![\r\n]))/m);
|
|
6644
6658
|
if (todosMatch) bodies.push(todosMatch[1]);
|
|
6645
6659
|
}
|
|
@@ -6647,7 +6661,7 @@ async function countMentionsInAssignment(sourceDir, target) {
|
|
|
6647
6661
|
const path = resolve16(sourceDir, filename);
|
|
6648
6662
|
if (await fileExists(path)) {
|
|
6649
6663
|
try {
|
|
6650
|
-
bodies.push(await
|
|
6664
|
+
bodies.push(await readFile10(path, "utf-8"));
|
|
6651
6665
|
} catch {
|
|
6652
6666
|
}
|
|
6653
6667
|
}
|
|
@@ -6707,42 +6721,42 @@ async function buildStandaloneAssignmentDetail(resolved) {
|
|
|
6707
6721
|
const assignmentDir = resolved.assignmentDir;
|
|
6708
6722
|
const assignmentMdPath2 = resolve16(assignmentDir, "assignment.md");
|
|
6709
6723
|
if (!await fileExists(assignmentMdPath2)) return null;
|
|
6710
|
-
const assignmentContent = await
|
|
6724
|
+
const assignmentContent = await readFile10(assignmentMdPath2, "utf-8");
|
|
6711
6725
|
const assignment = parseAssignmentFull(assignmentContent);
|
|
6712
6726
|
let plan = null;
|
|
6713
6727
|
const planPath = resolve16(assignmentDir, "plan.md");
|
|
6714
6728
|
if (await fileExists(planPath)) {
|
|
6715
|
-
const parsed = parsePlan(await
|
|
6729
|
+
const parsed = parsePlan(await readFile10(planPath, "utf-8"));
|
|
6716
6730
|
plan = { status: parsed.status, updated: parsed.updated, body: parsed.body };
|
|
6717
6731
|
}
|
|
6718
6732
|
let scratchpad = null;
|
|
6719
6733
|
const scratchpadPath = resolve16(assignmentDir, "scratchpad.md");
|
|
6720
6734
|
if (await fileExists(scratchpadPath)) {
|
|
6721
|
-
const parsed = parseScratchpad(await
|
|
6735
|
+
const parsed = parseScratchpad(await readFile10(scratchpadPath, "utf-8"));
|
|
6722
6736
|
scratchpad = { updated: parsed.updated, body: parsed.body };
|
|
6723
6737
|
}
|
|
6724
6738
|
let handoff = null;
|
|
6725
6739
|
const handoffPath = resolve16(assignmentDir, "handoff.md");
|
|
6726
6740
|
if (await fileExists(handoffPath)) {
|
|
6727
|
-
const parsed = parseHandoff(await
|
|
6741
|
+
const parsed = parseHandoff(await readFile10(handoffPath, "utf-8"));
|
|
6728
6742
|
handoff = { updated: parsed.updated, handoffCount: parsed.handoffCount, body: parsed.body };
|
|
6729
6743
|
}
|
|
6730
6744
|
let decisionRecord = null;
|
|
6731
6745
|
const decisionRecordPath = resolve16(assignmentDir, "decision-record.md");
|
|
6732
6746
|
if (await fileExists(decisionRecordPath)) {
|
|
6733
|
-
const parsed = parseDecisionRecord(await
|
|
6747
|
+
const parsed = parseDecisionRecord(await readFile10(decisionRecordPath, "utf-8"));
|
|
6734
6748
|
decisionRecord = { updated: parsed.updated, decisionCount: parsed.decisionCount, body: parsed.body };
|
|
6735
6749
|
}
|
|
6736
6750
|
let progress = null;
|
|
6737
6751
|
const progressPath = resolve16(assignmentDir, "progress.md");
|
|
6738
6752
|
if (await fileExists(progressPath)) {
|
|
6739
|
-
const parsed = parseProgress(await
|
|
6753
|
+
const parsed = parseProgress(await readFile10(progressPath, "utf-8"));
|
|
6740
6754
|
progress = { updated: parsed.updated, entryCount: parsed.entryCount, entries: parsed.entries };
|
|
6741
6755
|
}
|
|
6742
6756
|
let comments = null;
|
|
6743
6757
|
const commentsPath = resolve16(assignmentDir, "comments.md");
|
|
6744
6758
|
if (await fileExists(commentsPath)) {
|
|
6745
|
-
const parsed = parseComments(await
|
|
6759
|
+
const parsed = parseComments(await readFile10(commentsPath, "utf-8"));
|
|
6746
6760
|
comments = { updated: parsed.updated, entryCount: parsed.entryCount, entries: parsed.entries };
|
|
6747
6761
|
}
|
|
6748
6762
|
const detail = {
|
|
@@ -6779,6 +6793,14 @@ async function buildStandaloneAssignmentDetail(resolved) {
|
|
|
6779
6793
|
return detail;
|
|
6780
6794
|
}
|
|
6781
6795
|
async function listProjectRecords(projectsDir2, traces) {
|
|
6796
|
+
const cached = projectRecordsCache.get(projectsDir2);
|
|
6797
|
+
if (cached) return cached;
|
|
6798
|
+
const promise = computeProjectRecords(projectsDir2, traces);
|
|
6799
|
+
projectRecordsCache.set(projectsDir2, promise);
|
|
6800
|
+
promise.catch(() => projectRecordsCache.delete(projectsDir2));
|
|
6801
|
+
return promise;
|
|
6802
|
+
}
|
|
6803
|
+
async function computeProjectRecords(projectsDir2, traces) {
|
|
6782
6804
|
if (!await fileExists(projectsDir2)) {
|
|
6783
6805
|
return [];
|
|
6784
6806
|
}
|
|
@@ -6786,7 +6808,7 @@ async function listProjectRecords(projectsDir2, traces) {
|
|
|
6786
6808
|
migratedProjectsDirs.add(projectsDir2);
|
|
6787
6809
|
await migrateLegacyProjectFiles(projectsDir2);
|
|
6788
6810
|
}
|
|
6789
|
-
const entries = await
|
|
6811
|
+
const entries = await readdir8(projectsDir2, { withFileTypes: true });
|
|
6790
6812
|
const projectDirs = entries.filter((entry) => entry.isDirectory() && !entry.name.startsWith("."));
|
|
6791
6813
|
const maybeRecords = await Promise.all(
|
|
6792
6814
|
projectDirs.map(async (entry) => {
|
|
@@ -6796,7 +6818,7 @@ async function listProjectRecords(projectsDir2, traces) {
|
|
|
6796
6818
|
return null;
|
|
6797
6819
|
}
|
|
6798
6820
|
const t0 = traces ? performance.now() : 0;
|
|
6799
|
-
const projectContent = await
|
|
6821
|
+
const projectContent = await readFile10(projectMdPath, "utf-8");
|
|
6800
6822
|
const project = parseProject(projectContent);
|
|
6801
6823
|
if (traces) accumulatePhase(traces, "parse-project-md", performance.now() - t0);
|
|
6802
6824
|
const t1 = traces ? performance.now() : 0;
|
|
@@ -6841,7 +6863,7 @@ async function listAssignmentRecords(projectPath, traces) {
|
|
|
6841
6863
|
if (!await fileExists(assignmentsDir2)) {
|
|
6842
6864
|
return [];
|
|
6843
6865
|
}
|
|
6844
|
-
const entries = await
|
|
6866
|
+
const entries = await readdir8(assignmentsDir2, { withFileTypes: true });
|
|
6845
6867
|
const dirEntries = entries.filter((entry) => entry.isDirectory());
|
|
6846
6868
|
const maybeRecords = await Promise.all(
|
|
6847
6869
|
dirEntries.map(async (entry) => {
|
|
@@ -6850,7 +6872,7 @@ async function listAssignmentRecords(projectPath, traces) {
|
|
|
6850
6872
|
return null;
|
|
6851
6873
|
}
|
|
6852
6874
|
const t0 = traces ? performance.now() : 0;
|
|
6853
|
-
const content = await
|
|
6875
|
+
const content = await readFile10(assignmentMd, "utf-8");
|
|
6854
6876
|
const parsed = parseAssignmentFull(content);
|
|
6855
6877
|
if (traces) accumulatePhase(traces, "read-assignment-md", performance.now() - t0);
|
|
6856
6878
|
return parsed;
|
|
@@ -6865,14 +6887,14 @@ async function listResources(projectPath) {
|
|
|
6865
6887
|
if (!await fileExists(resourcesDir)) {
|
|
6866
6888
|
return [];
|
|
6867
6889
|
}
|
|
6868
|
-
const entries = await
|
|
6890
|
+
const entries = await readdir8(resourcesDir, { withFileTypes: true });
|
|
6869
6891
|
const results = [];
|
|
6870
6892
|
for (const entry of entries) {
|
|
6871
6893
|
if (!entry.isFile() || !entry.name.endsWith(".md") || entry.name.startsWith("_")) {
|
|
6872
6894
|
continue;
|
|
6873
6895
|
}
|
|
6874
6896
|
const filePath = resolve16(resourcesDir, entry.name);
|
|
6875
|
-
const content = await
|
|
6897
|
+
const content = await readFile10(filePath, "utf-8");
|
|
6876
6898
|
const parsed = parseResource(content);
|
|
6877
6899
|
results.push({
|
|
6878
6900
|
name: parsed.name,
|
|
@@ -6891,14 +6913,14 @@ async function listMemories(projectPath) {
|
|
|
6891
6913
|
if (!await fileExists(memoriesDir)) {
|
|
6892
6914
|
return [];
|
|
6893
6915
|
}
|
|
6894
|
-
const entries = await
|
|
6916
|
+
const entries = await readdir8(memoriesDir, { withFileTypes: true });
|
|
6895
6917
|
const results = [];
|
|
6896
6918
|
for (const entry of entries) {
|
|
6897
6919
|
if (!entry.isFile() || !entry.name.endsWith(".md") || entry.name.startsWith("_")) {
|
|
6898
6920
|
continue;
|
|
6899
6921
|
}
|
|
6900
6922
|
const filePath = resolve16(memoriesDir, entry.name);
|
|
6901
|
-
const content = await
|
|
6923
|
+
const content = await readFile10(filePath, "utf-8");
|
|
6902
6924
|
const parsed = parseMemory(content);
|
|
6903
6925
|
results.push({
|
|
6904
6926
|
name: parsed.name,
|
|
@@ -6961,7 +6983,7 @@ async function getMemoryDetail(projectsDir2, projectSlug, itemSlug) {
|
|
|
6961
6983
|
if (!projectRecord) return null;
|
|
6962
6984
|
const filePath = resolve16(projectRecord.projectPath, "memories", `${itemSlug}.md`);
|
|
6963
6985
|
if (!await fileExists(filePath)) return null;
|
|
6964
|
-
const content = await
|
|
6986
|
+
const content = await readFile10(filePath, "utf-8");
|
|
6965
6987
|
const parsed = parseMemory(content);
|
|
6966
6988
|
return {
|
|
6967
6989
|
name: parsed.name,
|
|
@@ -6987,7 +7009,7 @@ async function getResourceDetail(projectsDir2, projectSlug, itemSlug) {
|
|
|
6987
7009
|
if (!projectRecord) return null;
|
|
6988
7010
|
const filePath = resolve16(projectRecord.projectPath, "resources", `${itemSlug}.md`);
|
|
6989
7011
|
if (!await fileExists(filePath)) return null;
|
|
6990
|
-
const content = await
|
|
7012
|
+
const content = await readFile10(filePath, "utf-8");
|
|
6991
7013
|
const parsed = parseResource(content);
|
|
6992
7014
|
return {
|
|
6993
7015
|
name: parsed.name,
|
|
@@ -7005,7 +7027,7 @@ async function getResourceDetail(projectsDir2, projectSlug, itemSlug) {
|
|
|
7005
7027
|
async function loadDependencyGraph(projectPath, assignments) {
|
|
7006
7028
|
const statusPath = resolve16(projectPath, "_status.md");
|
|
7007
7029
|
if (await fileExists(statusPath)) {
|
|
7008
|
-
const statusContent = await
|
|
7030
|
+
const statusContent = await readFile10(statusPath, "utf-8");
|
|
7009
7031
|
const parsed = parseStatus(statusContent);
|
|
7010
7032
|
const derivedGraph = extractMermaidGraph(parsed.body);
|
|
7011
7033
|
if (derivedGraph) {
|
|
@@ -7166,7 +7188,7 @@ async function getUnmetDependencies(projectPath, dependsOn, terminalStatuses3, d
|
|
|
7166
7188
|
unmet.push(`${dependency} (missing)`);
|
|
7167
7189
|
continue;
|
|
7168
7190
|
}
|
|
7169
|
-
const content = await
|
|
7191
|
+
const content = await readFile10(dependencyPath, "utf-8");
|
|
7170
7192
|
const parsed = parseAssignmentFull(content);
|
|
7171
7193
|
if (!terminals.has(parsed.status)) {
|
|
7172
7194
|
unmet.push(`${dependency} (${parsed.status})`);
|
|
@@ -7459,7 +7481,7 @@ async function countOpenQuestions(projectPath, assignmentSlug) {
|
|
|
7459
7481
|
return 0;
|
|
7460
7482
|
}
|
|
7461
7483
|
try {
|
|
7462
|
-
const content = await
|
|
7484
|
+
const content = await readFile10(commentsPath, "utf-8");
|
|
7463
7485
|
const parsed = parseComments(content);
|
|
7464
7486
|
return parsed.entries.filter(
|
|
7465
7487
|
(e) => e.type === "question" && e.resolved !== true
|
|
@@ -7527,12 +7549,12 @@ async function listPlaybooks(playbooksDir3) {
|
|
|
7527
7549
|
if (!await fileExists(playbooksDir3)) return [];
|
|
7528
7550
|
const config = await readConfig();
|
|
7529
7551
|
const disabledSet = new Set(config.playbooks.disabled);
|
|
7530
|
-
const entries = await
|
|
7552
|
+
const entries = await readdir8(playbooksDir3, { withFileTypes: true });
|
|
7531
7553
|
const playbooks = [];
|
|
7532
7554
|
for (const entry of entries) {
|
|
7533
7555
|
if (!entry.isFile() || !entry.name.endsWith(".md") || entry.name.startsWith("_") || entry.name === "manifest.md") continue;
|
|
7534
7556
|
const filePath = resolve16(playbooksDir3, entry.name);
|
|
7535
|
-
const raw = await
|
|
7557
|
+
const raw = await readFile10(filePath, "utf-8");
|
|
7536
7558
|
const parsed = parsePlaybook(raw);
|
|
7537
7559
|
const slug = parsed.slug || entry.name.replace(/\.md$/, "");
|
|
7538
7560
|
playbooks.push({
|
|
@@ -7566,7 +7588,7 @@ async function getPlaybookDetail(playbooksDir3, slug) {
|
|
|
7566
7588
|
enabled
|
|
7567
7589
|
};
|
|
7568
7590
|
}
|
|
7569
|
-
var WorkspaceBlockedError, STALE_ASSIGNMENT_MS, RECENT_PROJECTS_LIMIT, RECENT_ACTIVITY_LIMIT, RECENT_SESSIONS_LIMIT, NEWEST_CREATED_LIMIT, SEGMENT_DISPLAY_CAP, STALE_LIMIT_DEFAULT, STALE_LIMIT_MAX, TERMINAL_STATUSES2, STATUS_TO_SEGMENT, HERO_PRIORITY, DEFAULT_TRANSITION_DEFINITIONS, DEFAULT_STATUS_COLORS, _cachedConfig, REFERENCED_BY_LIMIT, migratedProjectsDirs, DEFAULT_GRAPH_COLORS;
|
|
7591
|
+
var WorkspaceBlockedError, STALE_ASSIGNMENT_MS, RECENT_PROJECTS_LIMIT, RECENT_ACTIVITY_LIMIT, RECENT_SESSIONS_LIMIT, NEWEST_CREATED_LIMIT, SEGMENT_DISPLAY_CAP, STALE_LIMIT_DEFAULT, STALE_LIMIT_MAX, TERMINAL_STATUSES2, STATUS_TO_SEGMENT, HERO_PRIORITY, projectRecordsCache, standaloneRecordsCache, DEFAULT_TRANSITION_DEFINITIONS, DEFAULT_STATUS_COLORS, _cachedConfig, REFERENCED_BY_LIMIT, migratedProjectsDirs, DEFAULT_GRAPH_COLORS;
|
|
7570
7592
|
var init_api = __esm({
|
|
7571
7593
|
"src/dashboard/api.ts"() {
|
|
7572
7594
|
"use strict";
|
|
@@ -7617,6 +7639,8 @@ var init_api = __esm({
|
|
|
7617
7639
|
["blocked", "blocked"],
|
|
7618
7640
|
["stale", "stale"]
|
|
7619
7641
|
];
|
|
7642
|
+
projectRecordsCache = /* @__PURE__ */ new Map();
|
|
7643
|
+
standaloneRecordsCache = /* @__PURE__ */ new Map();
|
|
7620
7644
|
DEFAULT_TRANSITION_DEFINITIONS = [
|
|
7621
7645
|
{
|
|
7622
7646
|
command: "start",
|
|
@@ -7713,7 +7737,7 @@ __export(git_worktree_exports, {
|
|
|
7713
7737
|
removeWorktree: () => removeWorktree
|
|
7714
7738
|
});
|
|
7715
7739
|
import { spawn } from "child_process";
|
|
7716
|
-
import { readFile as
|
|
7740
|
+
import { readFile as readFile13 } from "fs/promises";
|
|
7717
7741
|
function run(command, args, cwd) {
|
|
7718
7742
|
return new Promise((resolvePromise) => {
|
|
7719
7743
|
const child = spawn(command, args, { cwd, stdio: ["ignore", "pipe", "pipe"] });
|
|
@@ -7757,7 +7781,7 @@ async function createWorktreeAndRecord(opts) {
|
|
|
7757
7781
|
const { assignmentPath, repository, branch, worktreePath, parentBranch } = opts;
|
|
7758
7782
|
await createWorktree({ repository, branch, worktreePath, parentBranch });
|
|
7759
7783
|
try {
|
|
7760
|
-
const content = await
|
|
7784
|
+
const content = await readFile13(assignmentPath, "utf-8");
|
|
7761
7785
|
const updated = updateAssignmentWorkspace(content, {
|
|
7762
7786
|
repository,
|
|
7763
7787
|
worktreePath,
|
|
@@ -9604,7 +9628,7 @@ function mergePatch(current, patch) {
|
|
|
9604
9628
|
// src/utils/view-prefs.ts
|
|
9605
9629
|
init_paths();
|
|
9606
9630
|
init_fs();
|
|
9607
|
-
import { readFile as
|
|
9631
|
+
import { readFile as readFile11, rename as rename3, unlink as unlink3 } from "fs/promises";
|
|
9608
9632
|
import { resolve as resolve17 } from "path";
|
|
9609
9633
|
function corruptFilePath() {
|
|
9610
9634
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
@@ -9627,7 +9651,7 @@ async function readViewPrefsFile() {
|
|
|
9627
9651
|
}
|
|
9628
9652
|
let raw;
|
|
9629
9653
|
try {
|
|
9630
|
-
raw = await
|
|
9654
|
+
raw = await readFile11(path, "utf-8");
|
|
9631
9655
|
} catch {
|
|
9632
9656
|
return { ...DEFAULT_VIEW_PREFS_FILE };
|
|
9633
9657
|
}
|
|
@@ -9810,7 +9834,7 @@ function isDashboardSlot(value) {
|
|
|
9810
9834
|
// src/utils/saved-views.ts
|
|
9811
9835
|
init_paths();
|
|
9812
9836
|
init_fs();
|
|
9813
|
-
import { readFile as
|
|
9837
|
+
import { readFile as readFile12, rename as rename4, unlink as unlink4 } from "fs/promises";
|
|
9814
9838
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
9815
9839
|
import { resolve as resolve18 } from "path";
|
|
9816
9840
|
function corruptFilePath2() {
|
|
@@ -9840,7 +9864,7 @@ async function readSavedViewsFile() {
|
|
|
9840
9864
|
}
|
|
9841
9865
|
let raw;
|
|
9842
9866
|
try {
|
|
9843
|
-
raw = await
|
|
9867
|
+
raw = await readFile12(path, "utf-8");
|
|
9844
9868
|
} catch {
|
|
9845
9869
|
return cloneDefault();
|
|
9846
9870
|
}
|
|
@@ -10160,7 +10184,7 @@ init_fs();
|
|
|
10160
10184
|
init_git_worktree();
|
|
10161
10185
|
import { Router as Router2 } from "express";
|
|
10162
10186
|
import { resolve as resolve21, basename as basename3, isAbsolute as isAbsolute2 } from "path";
|
|
10163
|
-
import { rm, readFile as
|
|
10187
|
+
import { rm, readFile as readFile15, open as fsOpen, stat as fsStat, realpath as fsRealpath } from "fs/promises";
|
|
10164
10188
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
10165
10189
|
|
|
10166
10190
|
// src/utils/worktree-defaults.ts
|
|
@@ -10207,14 +10231,14 @@ function detectCurrentBranch(cwd) {
|
|
|
10207
10231
|
// src/dashboard/repository-candidates.ts
|
|
10208
10232
|
init_fs();
|
|
10209
10233
|
init_parser();
|
|
10210
|
-
import { readdir as
|
|
10234
|
+
import { readdir as readdir9, readFile as readFile14 } from "fs/promises";
|
|
10211
10235
|
import { resolve as resolve20 } from "path";
|
|
10212
10236
|
async function getProjectRepositoryCandidates(projectsDir2, projectSlug) {
|
|
10213
10237
|
const seen = /* @__PURE__ */ new Set();
|
|
10214
10238
|
const out = [];
|
|
10215
10239
|
const projectPath = resolve20(projectsDir2, projectSlug, "project.md");
|
|
10216
10240
|
if (await fileExists(projectPath)) {
|
|
10217
|
-
const project = parseProject(await
|
|
10241
|
+
const project = parseProject(await readFile14(projectPath, "utf-8"));
|
|
10218
10242
|
for (const raw of project.repositories) {
|
|
10219
10243
|
const path = raw.trim();
|
|
10220
10244
|
if (!path) continue;
|
|
@@ -10226,12 +10250,12 @@ async function getProjectRepositoryCandidates(projectsDir2, projectSlug) {
|
|
|
10226
10250
|
}
|
|
10227
10251
|
const assignmentsDir2 = resolve20(projectsDir2, projectSlug, "assignments");
|
|
10228
10252
|
if (await fileExists(assignmentsDir2)) {
|
|
10229
|
-
const entries = await
|
|
10253
|
+
const entries = await readdir9(assignmentsDir2, { withFileTypes: true });
|
|
10230
10254
|
for (const entry of entries) {
|
|
10231
10255
|
if (!entry.isDirectory()) continue;
|
|
10232
10256
|
const assignmentMd = resolve20(assignmentsDir2, entry.name, "assignment.md");
|
|
10233
10257
|
if (!await fileExists(assignmentMd)) continue;
|
|
10234
|
-
const parsed = parseAssignmentFull(await
|
|
10258
|
+
const parsed = parseAssignmentFull(await readFile14(assignmentMd, "utf-8"));
|
|
10235
10259
|
const repo = parsed.workspace.repository?.trim();
|
|
10236
10260
|
if (!repo) continue;
|
|
10237
10261
|
const abs = resolve20(repo);
|
|
@@ -10248,13 +10272,13 @@ async function getStandaloneRepositoryCandidates(assignmentsDir2, excludeAssignm
|
|
|
10248
10272
|
}
|
|
10249
10273
|
const seen = /* @__PURE__ */ new Set();
|
|
10250
10274
|
const out = [];
|
|
10251
|
-
const entries = await
|
|
10275
|
+
const entries = await readdir9(assignmentsDir2, { withFileTypes: true });
|
|
10252
10276
|
for (const entry of entries) {
|
|
10253
10277
|
if (!entry.isDirectory()) continue;
|
|
10254
10278
|
if (entry.name === excludeAssignmentId) continue;
|
|
10255
10279
|
const assignmentMd = resolve20(assignmentsDir2, entry.name, "assignment.md");
|
|
10256
10280
|
if (!await fileExists(assignmentMd)) continue;
|
|
10257
|
-
const parsed = parseAssignmentFull(await
|
|
10281
|
+
const parsed = parseAssignmentFull(await readFile14(assignmentMd, "utf-8"));
|
|
10258
10282
|
const repo = parsed.workspace.repository?.trim();
|
|
10259
10283
|
if (!repo) continue;
|
|
10260
10284
|
const abs = resolve20(repo);
|
|
@@ -10419,14 +10443,14 @@ async function readCurrentDocument(filePath) {
|
|
|
10419
10443
|
if (!await fileExists(filePath)) {
|
|
10420
10444
|
return null;
|
|
10421
10445
|
}
|
|
10422
|
-
return
|
|
10446
|
+
return readFile15(filePath, "utf-8");
|
|
10423
10447
|
}
|
|
10424
10448
|
async function handleWorktreeCreate(req, res, ctx) {
|
|
10425
10449
|
if (!await fileExists(ctx.assignmentPath)) {
|
|
10426
10450
|
res.status(404).json({ error: "Assignment not found" });
|
|
10427
10451
|
return;
|
|
10428
10452
|
}
|
|
10429
|
-
const parsed = parseAssignmentFull(await
|
|
10453
|
+
const parsed = parseAssignmentFull(await readFile15(ctx.assignmentPath, "utf-8"));
|
|
10430
10454
|
if (parsed.workspace.worktreePath) {
|
|
10431
10455
|
res.status(409).json({ error: "Worktree already configured for this assignment" });
|
|
10432
10456
|
return;
|
|
@@ -10518,6 +10542,7 @@ async function handleWorktreeCreate(req, res, ctx) {
|
|
|
10518
10542
|
function createWriteRouter(projectsDir2, assignmentsDir2, todosDir2) {
|
|
10519
10543
|
const linkedTodosLookup = todosDir2 ? { todosDir: todosDir2, projectsDir: projectsDir2 } : void 0;
|
|
10520
10544
|
const router = Router2();
|
|
10545
|
+
installRecordsInvalidation(router);
|
|
10521
10546
|
router.get("/api/templates/project", (_req, res) => {
|
|
10522
10547
|
const content = renderProject({
|
|
10523
10548
|
id: generateId(),
|
|
@@ -10795,7 +10820,7 @@ ${body.startsWith("\n") ? body.slice(1) : body}${body.endsWith("\n") ? "" : "\n"
|
|
|
10795
10820
|
}
|
|
10796
10821
|
const nextContentRaw = requireContent(req, res);
|
|
10797
10822
|
if (!nextContentRaw) return;
|
|
10798
|
-
const currentContent = await
|
|
10823
|
+
const currentContent = await readFile15(filePath, "utf-8");
|
|
10799
10824
|
const frontmatterBlock = extractFrontmatterBlock(currentContent);
|
|
10800
10825
|
if (!frontmatterBlock) {
|
|
10801
10826
|
res.status(500).json({ error: `${kind} file is malformed (no frontmatter)` });
|
|
@@ -11246,7 +11271,7 @@ ${nextBody}${nextBody.endsWith("\n") ? "" : "\n"}`;
|
|
|
11246
11271
|
let currentContent;
|
|
11247
11272
|
let currentCount = 0;
|
|
11248
11273
|
if (await fileExists(commentsPath)) {
|
|
11249
|
-
currentContent = await
|
|
11274
|
+
currentContent = await readFile15(commentsPath, "utf-8");
|
|
11250
11275
|
const countMatch = currentContent.match(/^entryCount:\s*(\d+)/m);
|
|
11251
11276
|
if (countMatch) currentCount = parseInt(countMatch[1], 10);
|
|
11252
11277
|
} else {
|
|
@@ -11303,7 +11328,7 @@ ${entry}`;
|
|
|
11303
11328
|
res.status(400).json({ error: "resolved (boolean) is required" });
|
|
11304
11329
|
return;
|
|
11305
11330
|
}
|
|
11306
|
-
const content = await
|
|
11331
|
+
const content = await readFile15(commentsPath, "utf-8");
|
|
11307
11332
|
const parsed = parseComments(content);
|
|
11308
11333
|
const target = parsed.entries.find((e) => e.id === commentId);
|
|
11309
11334
|
if (!target) {
|
|
@@ -11350,7 +11375,7 @@ ${entry}`;
|
|
|
11350
11375
|
});
|
|
11351
11376
|
return;
|
|
11352
11377
|
}
|
|
11353
|
-
let content = await
|
|
11378
|
+
let content = await readFile15(projectPath, "utf-8");
|
|
11354
11379
|
content = setTopLevelField(content, "workspace", workspace ?? null);
|
|
11355
11380
|
content = setTopLevelField(content, "updated", nowTimestamp());
|
|
11356
11381
|
await writeFileForce(projectPath, content);
|
|
@@ -11387,7 +11412,7 @@ ${entry}`;
|
|
|
11387
11412
|
return;
|
|
11388
11413
|
}
|
|
11389
11414
|
const assignmentPath = resolve21(resolved.assignmentDir, "assignment.md");
|
|
11390
|
-
let content = await
|
|
11415
|
+
let content = await readFile15(assignmentPath, "utf-8");
|
|
11391
11416
|
content = setTopLevelField(content, "workspaceGroup", workspaceGroup ?? null);
|
|
11392
11417
|
content = setTopLevelField(content, "updated", nowTimestamp());
|
|
11393
11418
|
await writeFileForce(assignmentPath, content);
|
|
@@ -11482,7 +11507,7 @@ ${entry}`;
|
|
|
11482
11507
|
return;
|
|
11483
11508
|
}
|
|
11484
11509
|
const assignmentPath = resolve21(resolved.assignmentDir, "assignment.md");
|
|
11485
|
-
const parsedForSlug = parseAssignmentFull(await
|
|
11510
|
+
const parsedForSlug = parseAssignmentFull(await readFile15(assignmentPath, "utf-8"));
|
|
11486
11511
|
const assignmentSlugForBranch = parsedForSlug.slug || resolved.id;
|
|
11487
11512
|
await handleWorktreeCreate(req, res, {
|
|
11488
11513
|
assignmentPath,
|
|
@@ -11511,7 +11536,7 @@ ${entry}`;
|
|
|
11511
11536
|
res.status(400).json({ error: `Invalid status. Must be one of: ${validStatuses.join(", ")}, or null to clear.` });
|
|
11512
11537
|
return;
|
|
11513
11538
|
}
|
|
11514
|
-
let content = await
|
|
11539
|
+
let content = await readFile15(projectPath, "utf-8");
|
|
11515
11540
|
content = setTopLevelField(content, "statusOverride", status ?? null);
|
|
11516
11541
|
content = setTopLevelField(content, "updated", nowTimestamp());
|
|
11517
11542
|
await writeFileForce(projectPath, content);
|
|
@@ -11544,7 +11569,7 @@ ${entry}`;
|
|
|
11544
11569
|
res.status(400).json({ error: `Invalid status. Must be one of: ${validStatuses.join(", ")}.` });
|
|
11545
11570
|
return;
|
|
11546
11571
|
}
|
|
11547
|
-
let content = await
|
|
11572
|
+
let content = await readFile15(assignmentPath, "utf-8");
|
|
11548
11573
|
content = setTopLevelField(content, "status", status);
|
|
11549
11574
|
content = setTopLevelField(content, "updated", nowTimestamp());
|
|
11550
11575
|
if (status !== "blocked") {
|
|
@@ -11578,7 +11603,7 @@ ${entry}`;
|
|
|
11578
11603
|
res.status(400).json({ error: validation.error });
|
|
11579
11604
|
return;
|
|
11580
11605
|
}
|
|
11581
|
-
let content = await
|
|
11606
|
+
let content = await readFile15(assignmentPath, "utf-8");
|
|
11582
11607
|
content = setTopLevelField(content, "assignee", validation.value);
|
|
11583
11608
|
content = setTopLevelField(content, "updated", nowTimestamp());
|
|
11584
11609
|
await writeFileForce(assignmentPath, content);
|
|
@@ -11609,7 +11634,7 @@ ${entry}`;
|
|
|
11609
11634
|
res.status(400).json({ error: validation.error });
|
|
11610
11635
|
return;
|
|
11611
11636
|
}
|
|
11612
|
-
let content = await
|
|
11637
|
+
let content = await readFile15(assignmentPath, "utf-8");
|
|
11613
11638
|
content = setTopLevelField(content, "title", validation.value);
|
|
11614
11639
|
content = setTopLevelField(content, "updated", nowTimestamp());
|
|
11615
11640
|
await writeFileForce(assignmentPath, content);
|
|
@@ -12127,7 +12152,7 @@ ${entry}`;
|
|
|
12127
12152
|
res.status(400).json({ error: `Invalid status. Must be one of: ${validStatuses.join(", ")}.` });
|
|
12128
12153
|
return;
|
|
12129
12154
|
}
|
|
12130
|
-
let content = await
|
|
12155
|
+
let content = await readFile15(assignmentPath, "utf-8");
|
|
12131
12156
|
content = setTopLevelField(content, "status", status);
|
|
12132
12157
|
content = setTopLevelField(content, "updated", nowTimestamp());
|
|
12133
12158
|
if (status !== "blocked") {
|
|
@@ -12163,7 +12188,7 @@ ${entry}`;
|
|
|
12163
12188
|
res.status(400).json({ error: validation.error });
|
|
12164
12189
|
return;
|
|
12165
12190
|
}
|
|
12166
|
-
let content = await
|
|
12191
|
+
let content = await readFile15(assignmentPath, "utf-8");
|
|
12167
12192
|
content = setTopLevelField(content, "assignee", validation.value);
|
|
12168
12193
|
content = setTopLevelField(content, "updated", nowTimestamp());
|
|
12169
12194
|
await writeFileForce(assignmentPath, content);
|
|
@@ -12196,7 +12221,7 @@ ${entry}`;
|
|
|
12196
12221
|
res.status(400).json({ error: validation.error });
|
|
12197
12222
|
return;
|
|
12198
12223
|
}
|
|
12199
|
-
let content = await
|
|
12224
|
+
let content = await readFile15(assignmentPath, "utf-8");
|
|
12200
12225
|
content = setTopLevelField(content, "title", validation.value);
|
|
12201
12226
|
content = setTopLevelField(content, "updated", nowTimestamp());
|
|
12202
12227
|
await writeFileForce(assignmentPath, content);
|
|
@@ -12265,7 +12290,7 @@ ${entry}`;
|
|
|
12265
12290
|
if (!await fileExists(assignmentPath)) {
|
|
12266
12291
|
throw new Error("assignment file not found");
|
|
12267
12292
|
}
|
|
12268
|
-
let content = await
|
|
12293
|
+
let content = await readFile15(assignmentPath, "utf-8");
|
|
12269
12294
|
content = setTopLevelField(content, "status", status);
|
|
12270
12295
|
content = setTopLevelField(content, "updated", timestamp);
|
|
12271
12296
|
if (status !== "blocked") {
|
|
@@ -12421,7 +12446,7 @@ async function appendCommentTo(assignmentDir, assignmentRef, req, res, reloadDet
|
|
|
12421
12446
|
let currentContent;
|
|
12422
12447
|
let currentCount = 0;
|
|
12423
12448
|
if (await fileExists(commentsPath)) {
|
|
12424
|
-
currentContent = await
|
|
12449
|
+
currentContent = await readFile15(commentsPath, "utf-8");
|
|
12425
12450
|
const countMatch = currentContent.match(/^entryCount:\s*(\d+)/m);
|
|
12426
12451
|
if (countMatch) currentCount = parseInt(countMatch[1], 10);
|
|
12427
12452
|
} else {
|
|
@@ -12461,7 +12486,7 @@ async function toggleCommentResolvedAt(assignmentDir, commentId, req, res, reloa
|
|
|
12461
12486
|
res.status(400).json({ error: "resolved (boolean) is required" });
|
|
12462
12487
|
return;
|
|
12463
12488
|
}
|
|
12464
|
-
const content = await
|
|
12489
|
+
const content = await readFile15(commentsPath, "utf-8");
|
|
12465
12490
|
const parsed = parseComments(content);
|
|
12466
12491
|
const target = parsed.entries.find((e) => e.id === commentId);
|
|
12467
12492
|
if (!target) {
|
|
@@ -13189,26 +13214,26 @@ import { Router as Router8 } from "express";
|
|
|
13189
13214
|
|
|
13190
13215
|
// src/utils/status-config-resolution.ts
|
|
13191
13216
|
init_frontmatter();
|
|
13192
|
-
import { readFile as
|
|
13217
|
+
import { readFile as readFile16, writeFile as writeFile4, rm as rm2 } from "fs/promises";
|
|
13193
13218
|
import { dirname as dirname5 } from "path";
|
|
13194
13219
|
|
|
13195
13220
|
// src/utils/assignment-walk.ts
|
|
13196
13221
|
init_fs();
|
|
13197
13222
|
import { resolve as resolve23 } from "path";
|
|
13198
|
-
import { readdir as
|
|
13223
|
+
import { readdir as readdir10 } from "fs/promises";
|
|
13199
13224
|
async function listAssignmentsByProject(projectsDir2, standaloneDir) {
|
|
13200
13225
|
const result = {
|
|
13201
13226
|
withAssignmentMd: [],
|
|
13202
13227
|
orphanFolders: []
|
|
13203
13228
|
};
|
|
13204
13229
|
if (await fileExists(projectsDir2)) {
|
|
13205
|
-
const projects = await
|
|
13230
|
+
const projects = await readdir10(projectsDir2, { withFileTypes: true });
|
|
13206
13231
|
for (const m of projects) {
|
|
13207
13232
|
if (!m.isDirectory()) continue;
|
|
13208
13233
|
if (m.name.startsWith(".") || m.name.startsWith("_")) continue;
|
|
13209
13234
|
const assignmentsDir2 = resolve23(projectsDir2, m.name, "assignments");
|
|
13210
13235
|
if (!await fileExists(assignmentsDir2)) continue;
|
|
13211
|
-
const entries = await
|
|
13236
|
+
const entries = await readdir10(assignmentsDir2, { withFileTypes: true });
|
|
13212
13237
|
for (const a of entries) {
|
|
13213
13238
|
if (!a.isDirectory()) continue;
|
|
13214
13239
|
if (a.name.startsWith(".") || a.name.startsWith("_")) continue;
|
|
@@ -13230,7 +13255,7 @@ async function listAssignmentsByProject(projectsDir2, standaloneDir) {
|
|
|
13230
13255
|
}
|
|
13231
13256
|
}
|
|
13232
13257
|
if (standaloneDir !== null && await fileExists(standaloneDir)) {
|
|
13233
|
-
const entries = await
|
|
13258
|
+
const entries = await readdir10(standaloneDir, { withFileTypes: true });
|
|
13234
13259
|
for (const a of entries) {
|
|
13235
13260
|
if (!a.isDirectory()) continue;
|
|
13236
13261
|
if (a.name.startsWith(".") || a.name.startsWith("_")) continue;
|
|
@@ -13272,7 +13297,7 @@ async function scanAssignmentsByStatus(projectsDir2, standaloneDir, ids) {
|
|
|
13272
13297
|
const assignmentPath = `${entry.assignmentDir}/assignment.md`;
|
|
13273
13298
|
let content;
|
|
13274
13299
|
try {
|
|
13275
|
-
content = await
|
|
13300
|
+
content = await readFile16(assignmentPath, "utf-8");
|
|
13276
13301
|
} catch (err2) {
|
|
13277
13302
|
const code = err2?.code;
|
|
13278
13303
|
if (code === "ENOENT") {
|
|
@@ -13335,7 +13360,7 @@ async function applyStatusResolutions(resolutions, affected, validTargets) {
|
|
|
13335
13360
|
const list = affected.get(r.id) ?? [];
|
|
13336
13361
|
for (const a of list) {
|
|
13337
13362
|
try {
|
|
13338
|
-
const content = await
|
|
13363
|
+
const content = await readFile16(a.path, "utf-8");
|
|
13339
13364
|
buffer.set(a.path, content);
|
|
13340
13365
|
} catch (err2) {
|
|
13341
13366
|
const code = err2?.code;
|
|
@@ -13363,7 +13388,7 @@ async function applyStatusResolutions(resolutions, affected, validTargets) {
|
|
|
13363
13388
|
for (const a of list) {
|
|
13364
13389
|
let current;
|
|
13365
13390
|
try {
|
|
13366
|
-
current = await
|
|
13391
|
+
current = await readFile16(a.path, "utf-8");
|
|
13367
13392
|
} catch (err2) {
|
|
13368
13393
|
const code = err2?.code;
|
|
13369
13394
|
if (code === "ENOENT") {
|
|
@@ -13412,7 +13437,7 @@ async function applyStatusResolutions(resolutions, affected, validTargets) {
|
|
|
13412
13437
|
const list = affected.get(r.id) ?? [];
|
|
13413
13438
|
for (const a of list) {
|
|
13414
13439
|
try {
|
|
13415
|
-
const current = await
|
|
13440
|
+
const current = await readFile16(a.path, "utf-8");
|
|
13416
13441
|
const fm = parseAssignmentFrontmatter(current);
|
|
13417
13442
|
if (fm.status !== r.id) {
|
|
13418
13443
|
console.warn(
|
|
@@ -13548,6 +13573,7 @@ function mapResolutionErrorToHttp(err2, applied) {
|
|
|
13548
13573
|
}
|
|
13549
13574
|
function createStatusConfigRouter(projectsDir2, assignmentsDir2) {
|
|
13550
13575
|
const router = Router8();
|
|
13576
|
+
installRecordsInvalidation(router);
|
|
13551
13577
|
router.get("/", async (_req, res) => {
|
|
13552
13578
|
try {
|
|
13553
13579
|
const config = await getStatusConfig();
|
|
@@ -14772,7 +14798,7 @@ init_playbook();
|
|
|
14772
14798
|
init_playbooks();
|
|
14773
14799
|
import { Router as Router11 } from "express";
|
|
14774
14800
|
import { resolve as resolve26 } from "path";
|
|
14775
|
-
import { readFile as
|
|
14801
|
+
import { readFile as readFile17 } from "fs/promises";
|
|
14776
14802
|
function statusForPlaybookError(code) {
|
|
14777
14803
|
switch (code) {
|
|
14778
14804
|
case "manifest":
|
|
@@ -14854,7 +14880,7 @@ function createPlaybooksRouter(playbooksDir3) {
|
|
|
14854
14880
|
return;
|
|
14855
14881
|
}
|
|
14856
14882
|
const filePath = resolve26(playbooksDir3, resolved.filename);
|
|
14857
|
-
const content = await
|
|
14883
|
+
const content = await readFile17(filePath, "utf-8");
|
|
14858
14884
|
res.json({
|
|
14859
14885
|
documentType: "playbook",
|
|
14860
14886
|
title: `Edit Playbook: ${resolved.slug}`,
|
|
@@ -14951,11 +14977,12 @@ init_parser2();
|
|
|
14951
14977
|
init_fs();
|
|
14952
14978
|
init_paths();
|
|
14953
14979
|
import { Router as Router12 } from "express";
|
|
14954
|
-
import { readdir as
|
|
14980
|
+
import { readdir as readdir11 } from "fs/promises";
|
|
14955
14981
|
import { resolve as resolvePath, dirname as dirname6 } from "path";
|
|
14956
14982
|
import { rename as rename5, mkdir as mkdir2 } from "fs/promises";
|
|
14957
14983
|
init_slug();
|
|
14958
14984
|
init_promote_todos();
|
|
14985
|
+
init_api();
|
|
14959
14986
|
var WORKSPACE_REGEX = /^[a-z0-9_][a-z0-9-]*$/;
|
|
14960
14987
|
function getWorkspaceParam(value) {
|
|
14961
14988
|
if (Array.isArray(value)) {
|
|
@@ -14970,6 +14997,7 @@ function touchItem3(item) {
|
|
|
14970
14997
|
}
|
|
14971
14998
|
function createTodosRouter(todosDir2, broadcast, projectsDir2) {
|
|
14972
14999
|
const router = Router12();
|
|
15000
|
+
installRecordsInvalidation(router);
|
|
14973
15001
|
function broadcastUpdate() {
|
|
14974
15002
|
broadcast({ type: "todos-updated", timestamp: (/* @__PURE__ */ new Date()).toISOString() });
|
|
14975
15003
|
}
|
|
@@ -15089,7 +15117,7 @@ function createTodosRouter(todosDir2, broadcast, projectsDir2) {
|
|
|
15089
15117
|
router.get("/", async (_req, res) => {
|
|
15090
15118
|
try {
|
|
15091
15119
|
await ensureDir(todosDir2);
|
|
15092
|
-
const files = await
|
|
15120
|
+
const files = await readdir11(todosDir2).catch(() => []);
|
|
15093
15121
|
const workspaces = [];
|
|
15094
15122
|
for (const file of files) {
|
|
15095
15123
|
if (typeof file !== "string") continue;
|
|
@@ -15204,7 +15232,7 @@ function createTodosRouter(todosDir2, broadcast, projectsDir2) {
|
|
|
15204
15232
|
try {
|
|
15205
15233
|
const { archivePath: archivePath2 } = await Promise.resolve().then(() => (init_parser2(), parser_exports));
|
|
15206
15234
|
const { resolve: resolve78 } = await import("path");
|
|
15207
|
-
const { readFile:
|
|
15235
|
+
const { readFile: readFile53 } = await import("fs/promises");
|
|
15208
15236
|
const { writeFileForce: writeFileForce2 } = await Promise.resolve().then(() => (init_fs(), fs_exports));
|
|
15209
15237
|
const workspace = getWorkspaceParam(req.params.workspace);
|
|
15210
15238
|
const checklist = await readChecklist(todosDir2, workspace);
|
|
@@ -15223,7 +15251,7 @@ function createTodosRouter(todosDir2, broadcast, projectsDir2) {
|
|
|
15223
15251
|
await ensureDir(resolve78(todosDir2, "archive"));
|
|
15224
15252
|
let archContent = "";
|
|
15225
15253
|
if (await fileExists(archFile)) {
|
|
15226
|
-
archContent = await
|
|
15254
|
+
archContent = await readFile53(archFile, "utf-8");
|
|
15227
15255
|
archContent = archContent.trimEnd() + "\n\n";
|
|
15228
15256
|
} else {
|
|
15229
15257
|
archContent = `---
|
|
@@ -15505,7 +15533,7 @@ workspace: ${workspace}
|
|
|
15505
15533
|
const { readConfig: readConfig3 } = await Promise.resolve().then(() => (init_config2(), config_exports));
|
|
15506
15534
|
const { assignmentsDir: assignmentsDirFn } = await Promise.resolve().then(() => (init_paths(), paths_exports));
|
|
15507
15535
|
const { fileExists: fileExists2, writeFileForce: writeFileForce2 } = await Promise.resolve().then(() => (init_fs(), fs_exports));
|
|
15508
|
-
const { readFile:
|
|
15536
|
+
const { readFile: readFile53 } = await import("fs/promises");
|
|
15509
15537
|
const { appendTodosToAssignmentBody: appendTodosToAssignmentBody2, touchAssignmentUpdated: touchAssignmentUpdated2 } = await Promise.resolve().then(() => (init_assignment_todos(), assignment_todos_exports));
|
|
15510
15538
|
const { nowTimestamp: nowTimestamp3 } = await Promise.resolve().then(() => (init_timestamp(), timestamp_exports));
|
|
15511
15539
|
let assignmentRef;
|
|
@@ -15526,7 +15554,7 @@ workspace: ${workspace}
|
|
|
15526
15554
|
}
|
|
15527
15555
|
const assignmentMdPath2 = resolvePath2(assignmentDir, "assignment.md");
|
|
15528
15556
|
if (!await fileExists2(assignmentMdPath2)) return { error: `Target assignment not found: ${assignmentMdPath2}` };
|
|
15529
|
-
let content = await
|
|
15557
|
+
let content = await readFile53(assignmentMdPath2, "utf-8");
|
|
15530
15558
|
content = appendTodosToAssignmentBody2(
|
|
15531
15559
|
content,
|
|
15532
15560
|
items.map((it) => ({
|
|
@@ -15714,9 +15742,10 @@ init_fs();
|
|
|
15714
15742
|
init_paths();
|
|
15715
15743
|
init_slug();
|
|
15716
15744
|
import { Router as Router13 } from "express";
|
|
15717
|
-
import { mkdir as mkdir3, readFile as
|
|
15745
|
+
import { mkdir as mkdir3, readFile as readFile18, rename as rename6 } from "fs/promises";
|
|
15718
15746
|
import { resolve as resolve27, dirname as dirname7 } from "path";
|
|
15719
15747
|
init_promote_todos();
|
|
15748
|
+
init_api();
|
|
15720
15749
|
var WORKSPACE_REGEX2 = /^[a-z0-9_][a-z0-9-]*$/;
|
|
15721
15750
|
function touchItem4(item) {
|
|
15722
15751
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -15765,6 +15794,7 @@ function notFound(res, slug) {
|
|
|
15765
15794
|
}
|
|
15766
15795
|
function createProjectTodosRouter(projectsDir2, broadcast, workspaceTodosDir) {
|
|
15767
15796
|
const router = Router13({ mergeParams: true });
|
|
15797
|
+
installRecordsInvalidation(router);
|
|
15768
15798
|
function broadcastUpdate(projectSlug) {
|
|
15769
15799
|
broadcast({ type: "todos-updated", projectSlug, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
|
|
15770
15800
|
}
|
|
@@ -15937,7 +15967,7 @@ function createProjectTodosRouter(projectsDir2, broadcast, workspaceTodosDir) {
|
|
|
15937
15967
|
const archFile = archivePath(todosDir2, slug, checklist.archiveInterval);
|
|
15938
15968
|
let archContent = "";
|
|
15939
15969
|
if (await fileExists(archFile)) {
|
|
15940
|
-
archContent = await
|
|
15970
|
+
archContent = await readFile18(archFile, "utf-8");
|
|
15941
15971
|
archContent = archContent.trimEnd() + "\n\n";
|
|
15942
15972
|
} else {
|
|
15943
15973
|
archContent = `---
|
|
@@ -16394,7 +16424,7 @@ workspace: ${slug}
|
|
|
16394
16424
|
}
|
|
16395
16425
|
const assignmentMdPath2 = resolve27(assignmentDir, "assignment.md");
|
|
16396
16426
|
if (!await fileExists(assignmentMdPath2)) return { error: `Target assignment not found: ${assignmentMdPath2}` };
|
|
16397
|
-
let content = await
|
|
16427
|
+
let content = await readFile18(assignmentMdPath2, "utf-8");
|
|
16398
16428
|
content = appendTodosToAssignmentBody2(
|
|
16399
16429
|
content,
|
|
16400
16430
|
items.map((it) => ({
|
|
@@ -16590,7 +16620,7 @@ workspace: ${slug}
|
|
|
16590
16620
|
|
|
16591
16621
|
// src/dashboard/api-bundles.ts
|
|
16592
16622
|
import { Router as Router14 } from "express";
|
|
16593
|
-
import { readdir as
|
|
16623
|
+
import { readdir as readdir12 } from "fs/promises";
|
|
16594
16624
|
|
|
16595
16625
|
// src/todos/bundle-parser.ts
|
|
16596
16626
|
init_parser();
|
|
@@ -16598,7 +16628,7 @@ init_fs();
|
|
|
16598
16628
|
init_paths();
|
|
16599
16629
|
init_parser2();
|
|
16600
16630
|
import { randomBytes as randomBytes2 } from "crypto";
|
|
16601
|
-
import { readFile as
|
|
16631
|
+
import { readFile as readFile19 } from "fs/promises";
|
|
16602
16632
|
var BUNDLE_ID_REGEX = /^[a-f0-9]{4}$/;
|
|
16603
16633
|
var SCOPE_VALUES = /* @__PURE__ */ new Set(["workspace", "project", "global"]);
|
|
16604
16634
|
var SCOPE_ID_REGEX = /^[a-z0-9_][a-z0-9_-]*$/;
|
|
@@ -16701,7 +16731,7 @@ ${lines}
|
|
|
16701
16731
|
async function readBundles(todosDir2) {
|
|
16702
16732
|
const path = bundlesPath(todosDir2);
|
|
16703
16733
|
if (!await fileExists(path)) return [];
|
|
16704
|
-
const content = await
|
|
16734
|
+
const content = await readFile19(path, "utf-8");
|
|
16705
16735
|
return parseBundles(content).bundles;
|
|
16706
16736
|
}
|
|
16707
16737
|
async function writeBundles(todosDir2, bundles) {
|
|
@@ -16754,7 +16784,7 @@ function createBundlesRouter(todosDir2, broadcast) {
|
|
|
16754
16784
|
try {
|
|
16755
16785
|
await ensureDir(todosDir2);
|
|
16756
16786
|
const bundles = await readBundles(todosDir2);
|
|
16757
|
-
const workspaceFiles = await
|
|
16787
|
+
const workspaceFiles = await readdir12(todosDir2).catch(() => []);
|
|
16758
16788
|
const itemsByKey = /* @__PURE__ */ new Map();
|
|
16759
16789
|
for (const f of workspaceFiles) {
|
|
16760
16790
|
if (typeof f !== "string") continue;
|
|
@@ -16868,6 +16898,8 @@ function createProjectBundlesRouter(projectsDir2, broadcast) {
|
|
|
16868
16898
|
|
|
16869
16899
|
// src/dashboard/api-backup.ts
|
|
16870
16900
|
init_config2();
|
|
16901
|
+
init_api();
|
|
16902
|
+
init_scanner();
|
|
16871
16903
|
import { Router as Router16 } from "express";
|
|
16872
16904
|
|
|
16873
16905
|
// src/utils/github-backup.ts
|
|
@@ -16876,7 +16908,7 @@ init_fs();
|
|
|
16876
16908
|
init_config2();
|
|
16877
16909
|
import { execFile as execFile2 } from "child_process";
|
|
16878
16910
|
import { promisify as promisify2 } from "util";
|
|
16879
|
-
import { cp, mkdtemp, rm as rm3, readFile as
|
|
16911
|
+
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";
|
|
16880
16912
|
import { resolve as resolve29, join as join2 } from "path";
|
|
16881
16913
|
import { tmpdir } from "os";
|
|
16882
16914
|
var exec2 = promisify2(execFile2);
|
|
@@ -16937,7 +16969,7 @@ async function acquireLock() {
|
|
|
16937
16969
|
return lockPath;
|
|
16938
16970
|
} catch (err2) {
|
|
16939
16971
|
if (err2.code === "EEXIST") {
|
|
16940
|
-
const pid = await
|
|
16972
|
+
const pid = await readFile20(lockPath, "utf-8").catch(() => "");
|
|
16941
16973
|
throw new Error(
|
|
16942
16974
|
`Backup operation already in progress (lock file at ${lockPath}, pid ${pid.trim() || "unknown"}). If stale, delete the file and retry.`
|
|
16943
16975
|
);
|
|
@@ -16984,7 +17016,7 @@ function resolveCategoriesStrict(csv) {
|
|
|
16984
17016
|
return parseCategoriesStrict(parts);
|
|
16985
17017
|
}
|
|
16986
17018
|
async function readSanitizedConfig(configPath) {
|
|
16987
|
-
const content = await
|
|
17019
|
+
const content = await readFile20(configPath, "utf-8");
|
|
16988
17020
|
return content.replace(/^(\s*lastBackup:\s*).*$/m, "$1null").replace(/^(\s*lastRestore:\s*).*$/m, "$1null");
|
|
16989
17021
|
}
|
|
16990
17022
|
async function backupToGithub(overrides) {
|
|
@@ -17266,6 +17298,9 @@ function createBackupRouter() {
|
|
|
17266
17298
|
success: false,
|
|
17267
17299
|
error: error instanceof Error ? error.message : String(error)
|
|
17268
17300
|
});
|
|
17301
|
+
} finally {
|
|
17302
|
+
invalidateRecordsCache();
|
|
17303
|
+
clearScanCache();
|
|
17269
17304
|
}
|
|
17270
17305
|
});
|
|
17271
17306
|
return router;
|
|
@@ -17504,6 +17539,9 @@ function createDashboardServer(options) {
|
|
|
17504
17539
|
});
|
|
17505
17540
|
});
|
|
17506
17541
|
function broadcast(message) {
|
|
17542
|
+
if (message.type === "project-updated" || message.type === "assignment-updated") {
|
|
17543
|
+
invalidateRecordsCache();
|
|
17544
|
+
}
|
|
17507
17545
|
const data = JSON.stringify(message);
|
|
17508
17546
|
for (const client of clients) {
|
|
17509
17547
|
if (client.readyState === WebSocket.OPEN) {
|
|
@@ -18372,7 +18410,7 @@ init_config2();
|
|
|
18372
18410
|
init_frontmatter();
|
|
18373
18411
|
init_timestamp();
|
|
18374
18412
|
import { resolve as resolve33 } from "path";
|
|
18375
|
-
import { readdir as
|
|
18413
|
+
import { readdir as readdir13, readFile as readFile21 } from "fs/promises";
|
|
18376
18414
|
var PROMOTABLE_STATUSES = /* @__PURE__ */ new Set(["pending"]);
|
|
18377
18415
|
function objectiveIsFleshedOut(content) {
|
|
18378
18416
|
const match = content.match(/##\s+Objective\s*\n([\s\S]*?)(?=\n##\s+|$)/);
|
|
@@ -18390,7 +18428,7 @@ async function collectCandidates(baseDirs) {
|
|
|
18390
18428
|
const candidates = [];
|
|
18391
18429
|
for (const baseDir of baseDirs) {
|
|
18392
18430
|
if (!await fileExists(baseDir)) continue;
|
|
18393
|
-
const projects = await
|
|
18431
|
+
const projects = await readdir13(baseDir, { withFileTypes: true });
|
|
18394
18432
|
for (const m of projects) {
|
|
18395
18433
|
if (!m.isDirectory()) continue;
|
|
18396
18434
|
if (m.name.startsWith(".") || m.name.startsWith("_")) continue;
|
|
@@ -18398,7 +18436,7 @@ async function collectCandidates(baseDirs) {
|
|
|
18398
18436
|
if (await fileExists(directAssignmentMd)) {
|
|
18399
18437
|
const fm = await parseSafe(directAssignmentMd);
|
|
18400
18438
|
if (fm && PROMOTABLE_STATUSES.has(fm.status)) {
|
|
18401
|
-
const content = await
|
|
18439
|
+
const content = await readFile21(directAssignmentMd, "utf-8");
|
|
18402
18440
|
if (objectiveIsFleshedOut(content) && hasAcceptanceCriteria(content)) {
|
|
18403
18441
|
candidates.push({
|
|
18404
18442
|
projectSlug: null,
|
|
@@ -18413,7 +18451,7 @@ async function collectCandidates(baseDirs) {
|
|
|
18413
18451
|
}
|
|
18414
18452
|
const assignmentsDir2 = resolve33(baseDir, m.name, "assignments");
|
|
18415
18453
|
if (!await fileExists(assignmentsDir2)) continue;
|
|
18416
|
-
const entries = await
|
|
18454
|
+
const entries = await readdir13(assignmentsDir2, { withFileTypes: true });
|
|
18417
18455
|
for (const a of entries) {
|
|
18418
18456
|
if (!a.isDirectory()) continue;
|
|
18419
18457
|
if (a.name.startsWith(".") || a.name.startsWith("_")) continue;
|
|
@@ -18421,7 +18459,7 @@ async function collectCandidates(baseDirs) {
|
|
|
18421
18459
|
if (!await fileExists(assignmentMd)) continue;
|
|
18422
18460
|
const fm = await parseSafe(assignmentMd);
|
|
18423
18461
|
if (!fm || !PROMOTABLE_STATUSES.has(fm.status)) continue;
|
|
18424
|
-
const content = await
|
|
18462
|
+
const content = await readFile21(assignmentMd, "utf-8");
|
|
18425
18463
|
if (!objectiveIsFleshedOut(content)) continue;
|
|
18426
18464
|
if (!hasAcceptanceCriteria(content)) continue;
|
|
18427
18465
|
candidates.push({
|
|
@@ -18438,7 +18476,7 @@ async function collectCandidates(baseDirs) {
|
|
|
18438
18476
|
}
|
|
18439
18477
|
async function parseSafe(path) {
|
|
18440
18478
|
try {
|
|
18441
|
-
const content = await
|
|
18479
|
+
const content = await readFile21(path, "utf-8");
|
|
18442
18480
|
return parseAssignmentFrontmatter(content);
|
|
18443
18481
|
} catch {
|
|
18444
18482
|
return null;
|
|
@@ -18467,7 +18505,7 @@ async function migrateStatusesCommand(options) {
|
|
|
18467
18505
|
const now = nowTimestamp();
|
|
18468
18506
|
let migrated = 0;
|
|
18469
18507
|
for (const c2 of candidates) {
|
|
18470
|
-
const content = await
|
|
18508
|
+
const content = await readFile21(c2.assignmentMd, "utf-8");
|
|
18471
18509
|
const updated = updateAssignmentFile(content, {
|
|
18472
18510
|
status: c2.toStatus,
|
|
18473
18511
|
updated: now
|
|
@@ -18522,10 +18560,10 @@ init_config2();
|
|
|
18522
18560
|
init_fs();
|
|
18523
18561
|
import {
|
|
18524
18562
|
cp as cp2,
|
|
18525
|
-
readdir as
|
|
18563
|
+
readdir as readdir14,
|
|
18526
18564
|
symlink,
|
|
18527
18565
|
lstat,
|
|
18528
|
-
readFile as
|
|
18566
|
+
readFile as readFile22,
|
|
18529
18567
|
readlink,
|
|
18530
18568
|
rename as rename8,
|
|
18531
18569
|
rm as rm4,
|
|
@@ -18586,7 +18624,7 @@ function getInstallMarkerPath(targetDir) {
|
|
|
18586
18624
|
return resolve35(targetDir, INSTALL_MARKER_FILENAME);
|
|
18587
18625
|
}
|
|
18588
18626
|
async function readPackageManifest(packageRoot) {
|
|
18589
|
-
const raw = await
|
|
18627
|
+
const raw = await readFile22(resolve35(packageRoot, "package.json"), "utf-8");
|
|
18590
18628
|
return JSON.parse(raw);
|
|
18591
18629
|
}
|
|
18592
18630
|
async function readJsonFileIfExists(pathValue) {
|
|
@@ -18594,7 +18632,7 @@ async function readJsonFileIfExists(pathValue) {
|
|
|
18594
18632
|
return null;
|
|
18595
18633
|
}
|
|
18596
18634
|
try {
|
|
18597
|
-
const raw = await
|
|
18635
|
+
const raw = await readFile22(pathValue, "utf-8");
|
|
18598
18636
|
return JSON.parse(raw);
|
|
18599
18637
|
} catch {
|
|
18600
18638
|
return null;
|
|
@@ -18610,7 +18648,7 @@ async function readPluginManifestName(targetDir, pluginKind) {
|
|
|
18610
18648
|
if (!await fileExists(manifestPath)) {
|
|
18611
18649
|
return void 0;
|
|
18612
18650
|
}
|
|
18613
|
-
const raw = await
|
|
18651
|
+
const raw = await readFile22(manifestPath, "utf-8");
|
|
18614
18652
|
const parsed = JSON.parse(raw);
|
|
18615
18653
|
return parsed.name;
|
|
18616
18654
|
}
|
|
@@ -18620,7 +18658,7 @@ async function readInstallMetadata(targetDir) {
|
|
|
18620
18658
|
return null;
|
|
18621
18659
|
}
|
|
18622
18660
|
try {
|
|
18623
|
-
const raw = await
|
|
18661
|
+
const raw = await readFile22(markerPath, "utf-8");
|
|
18624
18662
|
return JSON.parse(raw);
|
|
18625
18663
|
} catch {
|
|
18626
18664
|
return null;
|
|
@@ -18743,7 +18781,7 @@ async function writeClaudeMarketplaceFile(manifestPath, marketplace) {
|
|
|
18743
18781
|
}
|
|
18744
18782
|
if (await fileExists(manifestPath)) {
|
|
18745
18783
|
try {
|
|
18746
|
-
const prev = await
|
|
18784
|
+
const prev = await readFile22(manifestPath, "utf-8");
|
|
18747
18785
|
JSON.parse(prev);
|
|
18748
18786
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
18749
18787
|
await writeFile7(`${manifestPath}.bak-${stamp}`, prev, "utf-8");
|
|
@@ -18816,7 +18854,7 @@ async function listClaudeMarketplaceCandidates() {
|
|
|
18816
18854
|
const [knownMarketplaces, activeMarketplaceNames, entries] = await Promise.all([
|
|
18817
18855
|
readKnownClaudeMarketplaceRecords(),
|
|
18818
18856
|
readInstalledClaudeMarketplaceNames(),
|
|
18819
|
-
|
|
18857
|
+
readdir14(rootDir, { withFileTypes: true })
|
|
18820
18858
|
]);
|
|
18821
18859
|
const candidates = [];
|
|
18822
18860
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -18891,7 +18929,7 @@ async function registerKnownClaudeMarketplace(name, rootDir) {
|
|
|
18891
18929
|
const manifestPath = getClaudeKnownMarketplacesPath();
|
|
18892
18930
|
let existing = {};
|
|
18893
18931
|
if (await fileExists(manifestPath)) {
|
|
18894
|
-
const raw = await
|
|
18932
|
+
const raw = await readFile22(manifestPath, "utf-8");
|
|
18895
18933
|
try {
|
|
18896
18934
|
const parsed = JSON.parse(raw);
|
|
18897
18935
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
@@ -18918,7 +18956,7 @@ async function registerKnownClaudeMarketplace(name, rootDir) {
|
|
|
18918
18956
|
existing[name].autoUpdate = true;
|
|
18919
18957
|
await ensureDir(dirname10(manifestPath));
|
|
18920
18958
|
if (await fileExists(manifestPath)) {
|
|
18921
|
-
const prev = await
|
|
18959
|
+
const prev = await readFile22(manifestPath, "utf-8");
|
|
18922
18960
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
18923
18961
|
await writeFile7(`${manifestPath}.bak-${stamp}`, prev, "utf-8");
|
|
18924
18962
|
}
|
|
@@ -18936,7 +18974,7 @@ async function setSyntaurPluginEnabled(options) {
|
|
|
18936
18974
|
const key = `syntaur@${options.marketplaceName}`;
|
|
18937
18975
|
let parsed = {};
|
|
18938
18976
|
if (await fileExists(settingsPath)) {
|
|
18939
|
-
const raw = await
|
|
18977
|
+
const raw = await readFile22(settingsPath, "utf-8");
|
|
18940
18978
|
try {
|
|
18941
18979
|
parsed = JSON.parse(raw);
|
|
18942
18980
|
} catch {
|
|
@@ -18955,7 +18993,7 @@ async function setSyntaurPluginEnabled(options) {
|
|
|
18955
18993
|
await ensureDir(dirname10(settingsPath));
|
|
18956
18994
|
if (await fileExists(settingsPath)) {
|
|
18957
18995
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
18958
|
-
const prev = await
|
|
18996
|
+
const prev = await readFile22(settingsPath, "utf-8");
|
|
18959
18997
|
await writeFile7(`${settingsPath}.bak-${stamp}`, prev, "utf-8");
|
|
18960
18998
|
}
|
|
18961
18999
|
const tmpPath = `${settingsPath}.tmp`;
|
|
@@ -19193,7 +19231,7 @@ async function readMarketplaceFile(marketplacePath) {
|
|
|
19193
19231
|
plugins: []
|
|
19194
19232
|
};
|
|
19195
19233
|
}
|
|
19196
|
-
const raw = await
|
|
19234
|
+
const raw = await readFile22(marketplacePath, "utf-8");
|
|
19197
19235
|
const parsed = JSON.parse(raw);
|
|
19198
19236
|
return {
|
|
19199
19237
|
name: parsed.name ?? "local",
|
|
@@ -19429,13 +19467,13 @@ async function textPrompt(question, defaultValue) {
|
|
|
19429
19467
|
|
|
19430
19468
|
// src/utils/install-skills.ts
|
|
19431
19469
|
init_fs();
|
|
19432
|
-
import { readFile as
|
|
19470
|
+
import { readFile as readFile24, readdir as readdir15, mkdir as mkdir4, copyFile, rm as rm5, lstat as lstat2 } from "fs/promises";
|
|
19433
19471
|
import { resolve as resolve37, relative as relative3, join as join3 } from "path";
|
|
19434
19472
|
import { homedir as homedir4 } from "os";
|
|
19435
19473
|
|
|
19436
19474
|
// src/utils/plugin-state.ts
|
|
19437
19475
|
init_fs();
|
|
19438
|
-
import { readFile as
|
|
19476
|
+
import { readFile as readFile23 } from "fs/promises";
|
|
19439
19477
|
import { resolve as resolve36 } from "path";
|
|
19440
19478
|
import { homedir as homedir3 } from "os";
|
|
19441
19479
|
function settingsPathFor(agent) {
|
|
@@ -19446,7 +19484,7 @@ async function readJsonOrNull(path) {
|
|
|
19446
19484
|
if (!path) return null;
|
|
19447
19485
|
if (!await fileExists(path)) return null;
|
|
19448
19486
|
try {
|
|
19449
|
-
const raw = await
|
|
19487
|
+
const raw = await readFile23(path, "utf-8");
|
|
19450
19488
|
return JSON.parse(raw);
|
|
19451
19489
|
} catch {
|
|
19452
19490
|
return null;
|
|
@@ -19489,7 +19527,8 @@ var KNOWN_SKILL_NAMES = [
|
|
|
19489
19527
|
"claim-resource",
|
|
19490
19528
|
"release-resource",
|
|
19491
19529
|
"extend-resource",
|
|
19492
|
-
"list-resources"
|
|
19530
|
+
"list-resources",
|
|
19531
|
+
"run-playbook"
|
|
19493
19532
|
];
|
|
19494
19533
|
var KNOWN_SKILLS = KNOWN_SKILL_NAMES;
|
|
19495
19534
|
async function getSkillsDir() {
|
|
@@ -19503,7 +19542,7 @@ function defaultSkillTargetDir(target) {
|
|
|
19503
19542
|
async function walkFiles(root) {
|
|
19504
19543
|
const out = [];
|
|
19505
19544
|
async function walk(dir) {
|
|
19506
|
-
const entries = await
|
|
19545
|
+
const entries = await readdir15(dir, { withFileTypes: true });
|
|
19507
19546
|
for (const entry of entries) {
|
|
19508
19547
|
const full = join3(dir, entry.name);
|
|
19509
19548
|
if (entry.isDirectory()) {
|
|
@@ -19518,7 +19557,7 @@ async function walkFiles(root) {
|
|
|
19518
19557
|
}
|
|
19519
19558
|
async function filesEqual(a, b) {
|
|
19520
19559
|
try {
|
|
19521
|
-
const [ba, bb] = await Promise.all([
|
|
19560
|
+
const [ba, bb] = await Promise.all([readFile24(a), readFile24(b)]);
|
|
19522
19561
|
if (ba.length !== bb.length) return false;
|
|
19523
19562
|
return ba.equals(bb);
|
|
19524
19563
|
} catch {
|
|
@@ -19527,7 +19566,7 @@ async function filesEqual(a, b) {
|
|
|
19527
19566
|
}
|
|
19528
19567
|
async function copyDir(srcDir, destDir) {
|
|
19529
19568
|
await mkdir4(destDir, { recursive: true });
|
|
19530
|
-
const entries = await
|
|
19569
|
+
const entries = await readdir15(srcDir, { withFileTypes: true });
|
|
19531
19570
|
for (const entry of entries) {
|
|
19532
19571
|
const src = join3(srcDir, entry.name);
|
|
19533
19572
|
const dest = join3(destDir, entry.name);
|
|
@@ -19581,7 +19620,7 @@ async function installSkillDir(srcDir, destDir, skillName, force) {
|
|
|
19581
19620
|
return { skill: skillName, status: "differs-preserved", targetPath: destDir };
|
|
19582
19621
|
}
|
|
19583
19622
|
async function discoverSkillNames(sourceDir) {
|
|
19584
|
-
const entries = await
|
|
19623
|
+
const entries = await readdir15(sourceDir, { withFileTypes: true });
|
|
19585
19624
|
const names = [];
|
|
19586
19625
|
for (const entry of entries) {
|
|
19587
19626
|
if (!entry.isDirectory()) continue;
|
|
@@ -19640,7 +19679,7 @@ async function uninstallSkills(options) {
|
|
|
19640
19679
|
if (await isSymlink(destDir)) continue;
|
|
19641
19680
|
const skillMd = join3(destDir, "SKILL.md");
|
|
19642
19681
|
if (!await fileExists(skillMd)) continue;
|
|
19643
|
-
const content = await
|
|
19682
|
+
const content = await readFile24(skillMd, "utf-8").catch(() => "");
|
|
19644
19683
|
const match = content.match(/^name:\s*(\S+)\s*$/m);
|
|
19645
19684
|
if (!match || match[1] !== skill) continue;
|
|
19646
19685
|
await rm5(destDir, { recursive: true, force: true });
|
|
@@ -19829,7 +19868,7 @@ async function installPluginCommand(options) {
|
|
|
19829
19868
|
// src/commands/install-statusline.ts
|
|
19830
19869
|
init_paths();
|
|
19831
19870
|
init_fs();
|
|
19832
|
-
import { readFile as
|
|
19871
|
+
import { readFile as readFile26, writeFile as writeFile9, copyFile as copyFile2, rm as rm6, stat as stat2, symlink as symlink2, unlink as unlink8, lstat as lstat3 } from "fs/promises";
|
|
19833
19872
|
import { resolve as resolve39, dirname as dirname12 } from "path";
|
|
19834
19873
|
import { homedir as homedir5 } from "os";
|
|
19835
19874
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
@@ -19837,7 +19876,7 @@ import { fileURLToPath as fileURLToPath4 } from "url";
|
|
|
19837
19876
|
// src/commands/configure-statusline.ts
|
|
19838
19877
|
init_paths();
|
|
19839
19878
|
init_fs();
|
|
19840
|
-
import { readFile as
|
|
19879
|
+
import { readFile as readFile25, writeFile as writeFile8 } from "fs/promises";
|
|
19841
19880
|
import { resolve as resolve38, dirname as dirname11 } from "path";
|
|
19842
19881
|
import { spawnSync as spawnSync5 } from "child_process";
|
|
19843
19882
|
import { checkbox, input as input2, confirm } from "@inquirer/prompts";
|
|
@@ -19864,7 +19903,7 @@ function getConfigPath(installRoot) {
|
|
|
19864
19903
|
async function readConfig2(path) {
|
|
19865
19904
|
if (!await fileExists(path)) return null;
|
|
19866
19905
|
try {
|
|
19867
|
-
const raw = await
|
|
19906
|
+
const raw = await readFile25(path, "utf-8");
|
|
19868
19907
|
const parsed = JSON.parse(raw);
|
|
19869
19908
|
if (!parsed || typeof parsed !== "object") return null;
|
|
19870
19909
|
const segments = Array.isArray(parsed.segments) ? parsed.segments.filter(isSegmentName) : [];
|
|
@@ -20052,7 +20091,7 @@ function getPackageStatuslineSource() {
|
|
|
20052
20091
|
}
|
|
20053
20092
|
async function readSettingsJson(settingsPath) {
|
|
20054
20093
|
if (!await fileExists(settingsPath)) return {};
|
|
20055
|
-
const raw = await
|
|
20094
|
+
const raw = await readFile26(settingsPath, "utf-8");
|
|
20056
20095
|
if (raw.trim() === "") return {};
|
|
20057
20096
|
try {
|
|
20058
20097
|
const parsed = JSON.parse(raw);
|
|
@@ -20240,7 +20279,7 @@ async function uninstallStatuslineCommand(options = {}) {
|
|
|
20240
20279
|
let restored = null;
|
|
20241
20280
|
if (await fileExists(backupPath)) {
|
|
20242
20281
|
try {
|
|
20243
|
-
const raw = await
|
|
20282
|
+
const raw = await readFile26(backupPath, "utf-8");
|
|
20244
20283
|
const parsed = JSON.parse(raw);
|
|
20245
20284
|
const prev = parsed?.previousStatusLine;
|
|
20246
20285
|
if (prev && typeof prev === "object" && typeof prev.command === "string") {
|
|
@@ -21273,7 +21312,7 @@ function normalizeSlashes(p) {
|
|
|
21273
21312
|
}
|
|
21274
21313
|
function detectInstallKind(scriptUrl, opts = {}) {
|
|
21275
21314
|
const realpath3 = opts.realpath ?? realpathSync.native;
|
|
21276
|
-
const
|
|
21315
|
+
const readFile53 = opts.readFile ?? ((p) => readFileSync(p, "utf-8"));
|
|
21277
21316
|
const ua = opts.envUserAgent !== void 0 ? opts.envUserAgent : process.env.npm_config_user_agent ?? "";
|
|
21278
21317
|
const resolved = resolveScriptPath(scriptUrl, realpath3);
|
|
21279
21318
|
if (resolved === null) {
|
|
@@ -21294,7 +21333,7 @@ function detectInstallKind(scriptUrl, opts = {}) {
|
|
|
21294
21333
|
const pkgJsonPath = join4(dir, "package.json");
|
|
21295
21334
|
let raw;
|
|
21296
21335
|
try {
|
|
21297
|
-
raw =
|
|
21336
|
+
raw = readFile53(pkgJsonPath);
|
|
21298
21337
|
} catch {
|
|
21299
21338
|
const parent2 = dirname13(dir);
|
|
21300
21339
|
if (parent2 === dir) break;
|
|
@@ -21468,7 +21507,7 @@ init_config2();
|
|
|
21468
21507
|
init_paths();
|
|
21469
21508
|
init_fs();
|
|
21470
21509
|
import { resolve as resolve46, isAbsolute as isAbsolute7 } from "path";
|
|
21471
|
-
import { readFile as
|
|
21510
|
+
import { readFile as readFile27 } from "fs/promises";
|
|
21472
21511
|
import { select, confirm as confirm2, input as input3 } from "@inquirer/prompts";
|
|
21473
21512
|
async function browseCommand(options) {
|
|
21474
21513
|
const config = await readConfig();
|
|
@@ -21547,7 +21586,7 @@ async function ensureWorktree(opts) {
|
|
|
21547
21586
|
if (!await fileExists(assignmentPath)) {
|
|
21548
21587
|
return void 0;
|
|
21549
21588
|
}
|
|
21550
|
-
const content = await
|
|
21589
|
+
const content = await readFile27(assignmentPath, "utf-8");
|
|
21551
21590
|
const { parseAssignmentFrontmatter: parseAssignmentFrontmatter2 } = await Promise.resolve().then(() => (init_frontmatter(), frontmatter_exports));
|
|
21552
21591
|
const fm = parseAssignmentFrontmatter2(content);
|
|
21553
21592
|
const { workspace } = fm;
|
|
@@ -21681,7 +21720,7 @@ init_paths();
|
|
|
21681
21720
|
init_fs();
|
|
21682
21721
|
init_parser();
|
|
21683
21722
|
init_config2();
|
|
21684
|
-
import { readdir as
|
|
21723
|
+
import { readdir as readdir16, readFile as readFile28 } from "fs/promises";
|
|
21685
21724
|
import { resolve as resolve48 } from "path";
|
|
21686
21725
|
async function listPlaybooksCommand(options = {}) {
|
|
21687
21726
|
const dir = playbooksDir();
|
|
@@ -21691,14 +21730,14 @@ async function listPlaybooksCommand(options = {}) {
|
|
|
21691
21730
|
}
|
|
21692
21731
|
const config = await readConfig();
|
|
21693
21732
|
const disabledSet = new Set(config.playbooks.disabled);
|
|
21694
|
-
const entries = await
|
|
21733
|
+
const entries = await readdir16(dir, { withFileTypes: true });
|
|
21695
21734
|
const mdFiles = entries.filter(
|
|
21696
21735
|
(e) => e.isFile() && e.name.endsWith(".md") && !e.name.startsWith("_") && e.name !== "manifest.md"
|
|
21697
21736
|
);
|
|
21698
21737
|
const rows = [];
|
|
21699
21738
|
for (const entry of mdFiles) {
|
|
21700
21739
|
const filePath = resolve48(dir, entry.name);
|
|
21701
|
-
const raw = await
|
|
21740
|
+
const raw = await readFile28(filePath, "utf-8");
|
|
21702
21741
|
const parsed = parsePlaybook(raw);
|
|
21703
21742
|
const slug = parsed.slug || entry.name.replace(/\.md$/, "");
|
|
21704
21743
|
const disabled = disabledSet.has(slug);
|
|
@@ -21821,13 +21860,13 @@ init_fs();
|
|
|
21821
21860
|
init_config2();
|
|
21822
21861
|
init_slug();
|
|
21823
21862
|
import { Command as Command2 } from "commander";
|
|
21824
|
-
import { readFile as
|
|
21863
|
+
import { readFile as readFile30 } from "fs/promises";
|
|
21825
21864
|
import { resolve as resolve50 } from "path";
|
|
21826
21865
|
|
|
21827
21866
|
// src/commands/bundle.ts
|
|
21828
21867
|
init_paths();
|
|
21829
21868
|
import { Command } from "commander";
|
|
21830
|
-
import { mkdir as mkdir7, readFile as
|
|
21869
|
+
import { mkdir as mkdir7, readFile as readFile29, readdir as readdir17, rm as rm7, writeFile as writeFile11 } from "fs/promises";
|
|
21831
21870
|
import { resolve as resolve49 } from "path";
|
|
21832
21871
|
init_parser2();
|
|
21833
21872
|
init_fs();
|
|
@@ -22120,7 +22159,7 @@ bundleCommand.command("plan").description("Create or open the bundle's shared pl
|
|
|
22120
22159
|
}
|
|
22121
22160
|
const planDir = bundlePlanDir(sc.todosPath, sc.scopeId, id);
|
|
22122
22161
|
await ensureDir(planDir);
|
|
22123
|
-
const existing = (await
|
|
22162
|
+
const existing = (await readdir17(planDir).catch(() => [])).filter((f) => /^plan(?:-v\d+)?\.md$/.test(f));
|
|
22124
22163
|
const { target } = pickNextPlanFile(planDir, existing);
|
|
22125
22164
|
const checklist = await readChecklist(sc.todosPath, sc.checklistKey);
|
|
22126
22165
|
if (!await fileExists(target)) {
|
|
@@ -22189,8 +22228,8 @@ bundleCommand.command("worktree").description("Create a git worktree for the bun
|
|
|
22189
22228
|
}
|
|
22190
22229
|
const bundlesFilePath = bundlesPath(sc.todosPath);
|
|
22191
22230
|
const checklistFilePath = checklistPath(sc.todosPath, sc.checklistKey);
|
|
22192
|
-
const bundlesSnapshot = await fileExists(bundlesFilePath) ? await
|
|
22193
|
-
const checklistSnapshot = await fileExists(checklistFilePath) ? await
|
|
22231
|
+
const bundlesSnapshot = await fileExists(bundlesFilePath) ? await readFile29(bundlesFilePath, "utf-8") : null;
|
|
22232
|
+
const checklistSnapshot = await fileExists(checklistFilePath) ? await readFile29(checklistFilePath, "utf-8") : null;
|
|
22194
22233
|
const record = async () => {
|
|
22195
22234
|
bundle.branch = options.branch;
|
|
22196
22235
|
bundle.worktreePath = worktreePath;
|
|
@@ -22736,7 +22775,7 @@ todoCommand.command("archive").description("Archive completed todos and their lo
|
|
|
22736
22775
|
await ensureDir(resolve50(todosPath, "archive"));
|
|
22737
22776
|
let archContent = "";
|
|
22738
22777
|
if (await fileExists(archFile)) {
|
|
22739
|
-
archContent = await
|
|
22778
|
+
archContent = await readFile30(archFile, "utf-8");
|
|
22740
22779
|
archContent = archContent.trimEnd() + "\n\n";
|
|
22741
22780
|
} else {
|
|
22742
22781
|
archContent = `---
|
|
@@ -22913,12 +22952,12 @@ function describeScope(scope) {
|
|
|
22913
22952
|
}
|
|
22914
22953
|
async function injectPromotedTodos(assignmentDir, todos, scopeLabel) {
|
|
22915
22954
|
const { resolve: resolvePath2 } = await import("path");
|
|
22916
|
-
const { readFile:
|
|
22955
|
+
const { readFile: readFile53 } = await import("fs/promises");
|
|
22917
22956
|
const { writeFileForce: writeFileForce2 } = await Promise.resolve().then(() => (init_fs(), fs_exports));
|
|
22918
22957
|
const { appendTodosToAssignmentBody: appendTodosToAssignmentBody2, touchAssignmentUpdated: touchAssignmentUpdated2 } = await Promise.resolve().then(() => (init_assignment_todos(), assignment_todos_exports));
|
|
22919
22958
|
const { nowTimestamp: nowTimestamp3 } = await Promise.resolve().then(() => (init_timestamp(), timestamp_exports));
|
|
22920
22959
|
const assignmentMdPath2 = resolvePath2(assignmentDir, "assignment.md");
|
|
22921
|
-
let content = await
|
|
22960
|
+
let content = await readFile53(assignmentMdPath2, "utf-8");
|
|
22922
22961
|
content = appendTodosToAssignmentBody2(
|
|
22923
22962
|
content,
|
|
22924
22963
|
todos.map((t) => ({
|
|
@@ -22963,8 +23002,8 @@ todoCommand.command("plan").description("Create or open a plan directory for a t
|
|
|
22963
23002
|
}
|
|
22964
23003
|
const planDir = todoPlanDir(todosPath, workspace, id);
|
|
22965
23004
|
await ensureDir(planDir);
|
|
22966
|
-
const { readdir:
|
|
22967
|
-
const existingFiles = (await
|
|
23005
|
+
const { readdir: readdir29 } = await import("fs/promises");
|
|
23006
|
+
const existingFiles = (await readdir29(planDir).catch(() => [])).filter(
|
|
22968
23007
|
(f) => /^plan(?:-v\d+)?\.md$/.test(f)
|
|
22969
23008
|
);
|
|
22970
23009
|
let target;
|
|
@@ -23168,12 +23207,12 @@ backupCommand.command("config").description("Show or update backup configuration
|
|
|
23168
23207
|
|
|
23169
23208
|
// src/commands/doctor.ts
|
|
23170
23209
|
import { Command as Command4 } from "commander";
|
|
23171
|
-
import { readFile as
|
|
23210
|
+
import { readFile as readFile38 } from "fs/promises";
|
|
23172
23211
|
import { isAbsolute as isAbsolute10, resolve as resolve62 } from "path";
|
|
23173
23212
|
|
|
23174
23213
|
// src/utils/doctor/index.ts
|
|
23175
23214
|
import { fileURLToPath as fileURLToPath8 } from "url";
|
|
23176
|
-
import { readFile as
|
|
23215
|
+
import { readFile as readFile37 } from "fs/promises";
|
|
23177
23216
|
import { dirname as dirname17, join as join8 } from "path";
|
|
23178
23217
|
|
|
23179
23218
|
// src/utils/doctor/context.ts
|
|
@@ -23220,7 +23259,7 @@ function closeCheckContext(ctx) {
|
|
|
23220
23259
|
init_fs();
|
|
23221
23260
|
init_paths();
|
|
23222
23261
|
import { resolve as resolve52, isAbsolute as isAbsolute8 } from "path";
|
|
23223
|
-
import { readFile as
|
|
23262
|
+
import { readFile as readFile31, stat as stat3 } from "fs/promises";
|
|
23224
23263
|
import { fileURLToPath as fileURLToPath7 } from "url";
|
|
23225
23264
|
import { dirname as dirname15, join as join6 } from "path";
|
|
23226
23265
|
var CATEGORY = "env";
|
|
@@ -23277,7 +23316,7 @@ var configValid = {
|
|
|
23277
23316
|
autoFixable: false
|
|
23278
23317
|
};
|
|
23279
23318
|
}
|
|
23280
|
-
const content = await
|
|
23319
|
+
const content = await readFile31(configPath, "utf-8");
|
|
23281
23320
|
const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
23282
23321
|
if (!fmMatch || fmMatch[1].trim() === "") {
|
|
23283
23322
|
return {
|
|
@@ -23557,7 +23596,7 @@ async function readLocalPkg() {
|
|
|
23557
23596
|
for (let i = 0; i < 6; i++) {
|
|
23558
23597
|
const candidate = join6(dir, "package.json");
|
|
23559
23598
|
try {
|
|
23560
|
-
const text = await
|
|
23599
|
+
const text = await readFile31(candidate, "utf-8");
|
|
23561
23600
|
return JSON.parse(text);
|
|
23562
23601
|
} catch {
|
|
23563
23602
|
dir = dirname15(dir);
|
|
@@ -23610,7 +23649,7 @@ function versionGte(a, b) {
|
|
|
23610
23649
|
// src/utils/doctor/checks/structure.ts
|
|
23611
23650
|
init_fs();
|
|
23612
23651
|
import { resolve as resolve53 } from "path";
|
|
23613
|
-
import { readdir as
|
|
23652
|
+
import { readdir as readdir18, stat as stat4 } from "fs/promises";
|
|
23614
23653
|
var CATEGORY2 = "structure";
|
|
23615
23654
|
var KNOWN_TOP_LEVEL = /* @__PURE__ */ new Set([
|
|
23616
23655
|
"projects",
|
|
@@ -23741,7 +23780,7 @@ var knownFilesRecognized = {
|
|
|
23741
23780
|
category: CATEGORY2,
|
|
23742
23781
|
title: "No unexpected top-level entries under ~/.syntaur/",
|
|
23743
23782
|
async run(ctx) {
|
|
23744
|
-
const entries = await
|
|
23783
|
+
const entries = await readdir18(ctx.syntaurRoot, { withFileTypes: true });
|
|
23745
23784
|
const unexpected = [];
|
|
23746
23785
|
for (const e of entries) {
|
|
23747
23786
|
if (e.name.startsWith(".")) continue;
|
|
@@ -23785,7 +23824,7 @@ function pass2(check) {
|
|
|
23785
23824
|
// src/utils/doctor/checks/project.ts
|
|
23786
23825
|
init_fs();
|
|
23787
23826
|
import { resolve as resolve54 } from "path";
|
|
23788
|
-
import { readdir as
|
|
23827
|
+
import { readdir as readdir19, stat as stat5 } from "fs/promises";
|
|
23789
23828
|
var CATEGORY3 = "project";
|
|
23790
23829
|
var REQUIRED_PROJECT_FILES = [
|
|
23791
23830
|
"project.md",
|
|
@@ -23809,7 +23848,7 @@ var PROJECT_MARKERS = ["project.md", "manifest.md", "assignments"];
|
|
|
23809
23848
|
async function listProjects2(ctx) {
|
|
23810
23849
|
const dir = ctx.config.defaultProjectDir;
|
|
23811
23850
|
if (!await fileExists(dir)) return [];
|
|
23812
|
-
const entries = await
|
|
23851
|
+
const entries = await readdir19(dir, { withFileTypes: true });
|
|
23813
23852
|
const result = [];
|
|
23814
23853
|
for (const e of entries) {
|
|
23815
23854
|
if (!e.isDirectory()) continue;
|
|
@@ -23903,7 +23942,7 @@ var orphanFiles = {
|
|
|
23903
23942
|
const projects = await listProjects2(ctx);
|
|
23904
23943
|
const results = [];
|
|
23905
23944
|
for (const projectDir of projects) {
|
|
23906
|
-
const entries = await
|
|
23945
|
+
const entries = await readdir19(projectDir, { withFileTypes: true });
|
|
23907
23946
|
const orphans = [];
|
|
23908
23947
|
for (const e of entries) {
|
|
23909
23948
|
if (e.name.startsWith(".")) continue;
|
|
@@ -23933,7 +23972,7 @@ async function newestAssignmentMtime(projectDir) {
|
|
|
23933
23972
|
let newest = 0;
|
|
23934
23973
|
let entries;
|
|
23935
23974
|
try {
|
|
23936
|
-
entries = await
|
|
23975
|
+
entries = await readdir19(assignmentsRoot, { withFileTypes: true });
|
|
23937
23976
|
} catch {
|
|
23938
23977
|
return 0;
|
|
23939
23978
|
}
|
|
@@ -23964,7 +24003,7 @@ init_parser();
|
|
|
23964
24003
|
init_types();
|
|
23965
24004
|
init_paths();
|
|
23966
24005
|
import { resolve as resolve55 } from "path";
|
|
23967
|
-
import { readFile as
|
|
24006
|
+
import { readFile as readFile32, readdir as readdir20 } from "fs/promises";
|
|
23968
24007
|
var CATEGORY4 = "assignment";
|
|
23969
24008
|
var STATUSES_REQUIRING_HANDOFF = /* @__PURE__ */ new Set(["review", "completed"]);
|
|
23970
24009
|
var PRE_WORKSPACE_STATUSES = /* @__PURE__ */ new Set([
|
|
@@ -24312,7 +24351,7 @@ var draftMissingObjective = {
|
|
|
24312
24351
|
if (parsed.status !== "draft") continue;
|
|
24313
24352
|
let raw;
|
|
24314
24353
|
try {
|
|
24315
|
-
raw = await
|
|
24354
|
+
raw = await readFile32(path, "utf-8");
|
|
24316
24355
|
} catch {
|
|
24317
24356
|
continue;
|
|
24318
24357
|
}
|
|
@@ -24349,12 +24388,12 @@ var readyToImplementMissingPlan = {
|
|
|
24349
24388
|
const parsed = await parseSafe2(path);
|
|
24350
24389
|
if (!parsed) continue;
|
|
24351
24390
|
if (parsed.status !== "ready_to_implement") continue;
|
|
24352
|
-
const entries = await
|
|
24391
|
+
const entries = await readdir20(a.assignmentDir).catch(() => []);
|
|
24353
24392
|
const planFiles = entries.filter((f) => /^plan(?:-v\d+)?\.md$/i.test(f));
|
|
24354
24393
|
let hasPlanContent = false;
|
|
24355
24394
|
for (const f of planFiles) {
|
|
24356
24395
|
try {
|
|
24357
|
-
const c2 = await
|
|
24396
|
+
const c2 = await readFile32(resolve55(a.assignmentDir, f), "utf-8");
|
|
24358
24397
|
if (c2.trim().length > 0) {
|
|
24359
24398
|
hasPlanContent = true;
|
|
24360
24399
|
break;
|
|
@@ -24397,7 +24436,7 @@ var assignmentChecks = [
|
|
|
24397
24436
|
];
|
|
24398
24437
|
async function parseSafe2(path) {
|
|
24399
24438
|
try {
|
|
24400
|
-
const content = await
|
|
24439
|
+
const content = await readFile32(path, "utf-8");
|
|
24401
24440
|
return parseAssignmentFull(content);
|
|
24402
24441
|
} catch {
|
|
24403
24442
|
return null;
|
|
@@ -24558,7 +24597,7 @@ function skipped(check, reason) {
|
|
|
24558
24597
|
// src/utils/doctor/checks/integrations.ts
|
|
24559
24598
|
init_fs();
|
|
24560
24599
|
import { resolve as resolve57, dirname as dirname16, basename as basename5 } from "path";
|
|
24561
|
-
import { readdir as
|
|
24600
|
+
import { readdir as readdir21, readFile as readFile33 } from "fs/promises";
|
|
24562
24601
|
import { homedir as homedir7 } from "os";
|
|
24563
24602
|
var CATEGORY6 = "integrations";
|
|
24564
24603
|
var claudePluginLinked = {
|
|
@@ -24621,7 +24660,7 @@ var backupConfigured = {
|
|
|
24621
24660
|
if (ctx.config.backup?.repo) return pass6(this);
|
|
24622
24661
|
const projectsDir2 = ctx.config.defaultProjectDir;
|
|
24623
24662
|
if (!await fileExists(projectsDir2)) return skipped2(this, "no projects dir");
|
|
24624
|
-
const entries = await
|
|
24663
|
+
const entries = await readdir21(projectsDir2, { withFileTypes: true });
|
|
24625
24664
|
const hasProjects = entries.some((e) => e.isDirectory() && !e.name.startsWith(".") && !e.name.startsWith("_"));
|
|
24626
24665
|
if (!hasProjects) return skipped2(this, "no projects yet");
|
|
24627
24666
|
return {
|
|
@@ -24643,7 +24682,7 @@ async function readKnownMarketplaces() {
|
|
|
24643
24682
|
const path = resolve57(homedir7(), ".claude", "plugins", "known_marketplaces.json");
|
|
24644
24683
|
if (!await fileExists(path)) return {};
|
|
24645
24684
|
try {
|
|
24646
|
-
const raw = await
|
|
24685
|
+
const raw = await readFile33(path, "utf-8");
|
|
24647
24686
|
return JSON.parse(raw);
|
|
24648
24687
|
} catch {
|
|
24649
24688
|
return {};
|
|
@@ -24696,7 +24735,7 @@ var claudeMarketplaceRegistered = {
|
|
|
24696
24735
|
}
|
|
24697
24736
|
let parsed = {};
|
|
24698
24737
|
try {
|
|
24699
|
-
parsed = JSON.parse(await
|
|
24738
|
+
parsed = JSON.parse(await readFile33(marketplaceManifest, "utf-8"));
|
|
24700
24739
|
} catch {
|
|
24701
24740
|
return {
|
|
24702
24741
|
id: this.id,
|
|
@@ -24769,7 +24808,7 @@ init_fs();
|
|
|
24769
24808
|
init_parser();
|
|
24770
24809
|
init_types();
|
|
24771
24810
|
import { resolve as resolve58 } from "path";
|
|
24772
|
-
import { readFile as
|
|
24811
|
+
import { readFile as readFile34 } from "fs/promises";
|
|
24773
24812
|
var CATEGORY7 = "workspace";
|
|
24774
24813
|
var ASSIGNMENT_FIELDS = ["projectSlug", "assignmentSlug", "projectDir", "assignmentDir"];
|
|
24775
24814
|
var BUNDLE_FIELDS = ["bundleId", "bundleScope", "bundleScopeId"];
|
|
@@ -24795,7 +24834,7 @@ async function loadContext(ctx) {
|
|
|
24795
24834
|
return { data: null, path, exists: false, parseError: null };
|
|
24796
24835
|
}
|
|
24797
24836
|
try {
|
|
24798
|
-
const raw = await
|
|
24837
|
+
const raw = await readFile34(path, "utf-8");
|
|
24799
24838
|
return { data: JSON.parse(raw), path, exists: true, parseError: null };
|
|
24800
24839
|
} catch (err2) {
|
|
24801
24840
|
return {
|
|
@@ -24922,7 +24961,7 @@ var contextTerminal = {
|
|
|
24922
24961
|
const assignmentMd = resolve58(data.assignmentDir, "assignment.md");
|
|
24923
24962
|
if (!await fileExists(assignmentMd)) return skipped3(this, "assignment file missing");
|
|
24924
24963
|
try {
|
|
24925
|
-
const content = await
|
|
24964
|
+
const content = await readFile34(assignmentMd, "utf-8");
|
|
24926
24965
|
const parsed = parseAssignmentFull(content);
|
|
24927
24966
|
const terminal = terminalStatuses2(ctx);
|
|
24928
24967
|
if (terminal.has(parsed.status)) {
|
|
@@ -25068,7 +25107,7 @@ var agentChecks = [agentsResolvable];
|
|
|
25068
25107
|
// src/utils/doctor/checks/terminal.ts
|
|
25069
25108
|
init_config2();
|
|
25070
25109
|
import { spawnSync as spawnSync8 } from "child_process";
|
|
25071
|
-
import { readFile as
|
|
25110
|
+
import { readFile as readFile35 } from "fs/promises";
|
|
25072
25111
|
import { resolve as resolve59 } from "path";
|
|
25073
25112
|
init_paths();
|
|
25074
25113
|
init_fs();
|
|
@@ -25076,7 +25115,7 @@ var CATEGORY9 = "terminal";
|
|
|
25076
25115
|
async function readRawTerminalKey() {
|
|
25077
25116
|
const configPath = resolve59(syntaurRoot(), "config.md");
|
|
25078
25117
|
if (!await fileExists(configPath)) return null;
|
|
25079
|
-
const content = await
|
|
25118
|
+
const content = await readFile35(configPath, "utf-8");
|
|
25080
25119
|
const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
25081
25120
|
if (!fmMatch) return null;
|
|
25082
25121
|
const line = fmMatch[1].split("\n").find((l) => /^terminal:\s*/.test(l));
|
|
@@ -25227,7 +25266,7 @@ var terminalChecks = [
|
|
|
25227
25266
|
// src/utils/doctor/checks/skills.ts
|
|
25228
25267
|
init_fs();
|
|
25229
25268
|
import { resolve as resolve60, join as join7 } from "path";
|
|
25230
|
-
import { readdir as
|
|
25269
|
+
import { readdir as readdir22, readFile as readFile36, lstat as lstat4 } from "fs/promises";
|
|
25231
25270
|
import { homedir as homedir8 } from "os";
|
|
25232
25271
|
var CATEGORY10 = "skills";
|
|
25233
25272
|
var skillTargets = [
|
|
@@ -25247,7 +25286,7 @@ var skillsDedupCheck = {
|
|
|
25247
25286
|
const present = [];
|
|
25248
25287
|
let entries;
|
|
25249
25288
|
try {
|
|
25250
|
-
entries = await
|
|
25289
|
+
entries = await readdir22(dir, { withFileTypes: true });
|
|
25251
25290
|
} catch {
|
|
25252
25291
|
continue;
|
|
25253
25292
|
}
|
|
@@ -25256,7 +25295,7 @@ var skillsDedupCheck = {
|
|
|
25256
25295
|
if (!KNOWN_SKILLS.includes(entry.name)) continue;
|
|
25257
25296
|
const skillMd = join7(dir, entry.name, "SKILL.md");
|
|
25258
25297
|
if (!await fileExists(skillMd)) continue;
|
|
25259
|
-
const content = await
|
|
25298
|
+
const content = await readFile36(skillMd, "utf-8").catch(() => "");
|
|
25260
25299
|
const match = content.match(/^name:\s*(\S+)\s*$/m);
|
|
25261
25300
|
if (!match || match[1] !== entry.name) continue;
|
|
25262
25301
|
let isSymlink2 = false;
|
|
@@ -25308,7 +25347,7 @@ var skillsChecks = [skillsDedupCheck];
|
|
|
25308
25347
|
init_fs();
|
|
25309
25348
|
init_paths();
|
|
25310
25349
|
import { resolve as resolve61 } from "path";
|
|
25311
|
-
import { readdir as
|
|
25350
|
+
import { readdir as readdir23 } from "fs/promises";
|
|
25312
25351
|
import { spawnSync as spawnSync9 } from "child_process";
|
|
25313
25352
|
init_parser2();
|
|
25314
25353
|
var CATEGORY11 = "bundles";
|
|
@@ -25316,7 +25355,7 @@ async function listScopes(ctx) {
|
|
|
25316
25355
|
const out = [];
|
|
25317
25356
|
const td = todosDir();
|
|
25318
25357
|
if (await fileExists(td)) {
|
|
25319
|
-
const entries = await
|
|
25358
|
+
const entries = await readdir23(td).catch(() => []);
|
|
25320
25359
|
for (const f of entries) {
|
|
25321
25360
|
if (typeof f !== "string") continue;
|
|
25322
25361
|
if (!f.endsWith(".md") || f.endsWith("-log.md")) continue;
|
|
@@ -25332,7 +25371,7 @@ async function listScopes(ctx) {
|
|
|
25332
25371
|
}
|
|
25333
25372
|
}
|
|
25334
25373
|
if (await fileExists(ctx.config.defaultProjectDir)) {
|
|
25335
|
-
const projectEntries = await
|
|
25374
|
+
const projectEntries = await readdir23(ctx.config.defaultProjectDir, { withFileTypes: true }).catch(() => []);
|
|
25336
25375
|
for (const e of projectEntries) {
|
|
25337
25376
|
if (!e.isDirectory()) continue;
|
|
25338
25377
|
const slug = e.name;
|
|
@@ -25628,7 +25667,7 @@ async function readVersion() {
|
|
|
25628
25667
|
let dir = dirname17(here);
|
|
25629
25668
|
for (let i = 0; i < 6; i++) {
|
|
25630
25669
|
try {
|
|
25631
|
-
const raw = await
|
|
25670
|
+
const raw = await readFile37(join8(dir, "package.json"), "utf-8");
|
|
25632
25671
|
const parsed = JSON.parse(raw);
|
|
25633
25672
|
return typeof parsed.version === "string" ? parsed.version : null;
|
|
25634
25673
|
} catch {
|
|
@@ -25738,7 +25777,7 @@ async function validateAssignmentFile(inputPath, cwd = process.cwd()) {
|
|
|
25738
25777
|
}
|
|
25739
25778
|
let content;
|
|
25740
25779
|
try {
|
|
25741
|
-
content = await
|
|
25780
|
+
content = await readFile38(absolute, "utf-8");
|
|
25742
25781
|
} catch (err2) {
|
|
25743
25782
|
return {
|
|
25744
25783
|
ok: false,
|
|
@@ -26063,7 +26102,7 @@ init_timestamp();
|
|
|
26063
26102
|
init_assignment_resolver();
|
|
26064
26103
|
init_templates();
|
|
26065
26104
|
import { resolve as resolve63 } from "path";
|
|
26066
|
-
import { readFile as
|
|
26105
|
+
import { readFile as readFile39 } from "fs/promises";
|
|
26067
26106
|
function shortId() {
|
|
26068
26107
|
return generateId().split("-")[0];
|
|
26069
26108
|
}
|
|
@@ -26109,7 +26148,7 @@ async function commentCommand(target, text, options = {}) {
|
|
|
26109
26148
|
let currentContent;
|
|
26110
26149
|
let currentCount = 0;
|
|
26111
26150
|
if (await fileExists(commentsPath)) {
|
|
26112
|
-
currentContent = await
|
|
26151
|
+
currentContent = await readFile39(commentsPath, "utf-8");
|
|
26113
26152
|
const countMatch = currentContent.match(/^entryCount:\s*(\d+)/m);
|
|
26114
26153
|
if (countMatch) currentCount = parseInt(countMatch[1], 10);
|
|
26115
26154
|
} else {
|
|
@@ -26155,7 +26194,7 @@ init_slug();
|
|
|
26155
26194
|
init_assignment_resolver();
|
|
26156
26195
|
init_parser();
|
|
26157
26196
|
import { resolve as resolve64 } from "path";
|
|
26158
|
-
import { readFile as
|
|
26197
|
+
import { readFile as readFile40 } from "fs/promises";
|
|
26159
26198
|
var AssignmentTargetError = class extends Error {
|
|
26160
26199
|
};
|
|
26161
26200
|
function classifyContext(ctx) {
|
|
@@ -26170,7 +26209,7 @@ async function readAssignmentFrontmatterId(assignmentDir) {
|
|
|
26170
26209
|
const path = resolve64(assignmentDir, "assignment.md");
|
|
26171
26210
|
if (!await fileExists(path)) return null;
|
|
26172
26211
|
try {
|
|
26173
|
-
const content = await
|
|
26212
|
+
const content = await readFile40(path, "utf-8");
|
|
26174
26213
|
const [fm] = extractFrontmatter(content);
|
|
26175
26214
|
return getField(fm, "id");
|
|
26176
26215
|
} catch {
|
|
@@ -26181,7 +26220,7 @@ async function readContextJson(cwd) {
|
|
|
26181
26220
|
const path = resolve64(cwd, ".syntaur", "context.json");
|
|
26182
26221
|
if (!await fileExists(path)) return null;
|
|
26183
26222
|
try {
|
|
26184
|
-
const raw = await
|
|
26223
|
+
const raw = await readFile40(path, "utf-8");
|
|
26185
26224
|
return JSON.parse(raw);
|
|
26186
26225
|
} catch {
|
|
26187
26226
|
return null;
|
|
@@ -26414,7 +26453,7 @@ async function captureScreenshot(mode) {
|
|
|
26414
26453
|
|
|
26415
26454
|
// src/utils/asciinema.ts
|
|
26416
26455
|
import { spawn as spawn6 } from "child_process";
|
|
26417
|
-
import { mkdtemp as mkdtemp3, readFile as
|
|
26456
|
+
import { mkdtemp as mkdtemp3, readFile as readFile41, rm as rm9 } from "fs/promises";
|
|
26418
26457
|
import { tmpdir as tmpdir4 } from "os";
|
|
26419
26458
|
import { join as join10 } from "path";
|
|
26420
26459
|
var SAFE_RE = /^[A-Za-z0-9_@%+=:,./-]+$/;
|
|
@@ -26477,7 +26516,7 @@ async function captureAsciinema(opts) {
|
|
|
26477
26516
|
}
|
|
26478
26517
|
throw err2;
|
|
26479
26518
|
}
|
|
26480
|
-
const text = await
|
|
26519
|
+
const text = await readFile41(castPath, "utf8").catch(() => null);
|
|
26481
26520
|
if (text === null) {
|
|
26482
26521
|
throw new Error(
|
|
26483
26522
|
`asciinema produced no cast file at ${castPath} (exit ${exitCode}). Try running 'asciinema rec ${castPath}' directly to diagnose.`
|
|
@@ -26505,7 +26544,7 @@ async function captureAsciinema(opts) {
|
|
|
26505
26544
|
// src/utils/recording.ts
|
|
26506
26545
|
init_paths();
|
|
26507
26546
|
import { spawn as spawn7 } from "child_process";
|
|
26508
|
-
import { mkdir as mkdir8, mkdtemp as mkdtemp4, open as open3, readFile as
|
|
26547
|
+
import { mkdir as mkdir8, mkdtemp as mkdtemp4, open as open3, readFile as readFile42, rm as rm10, stat as stat7, unlink as unlink9, writeFile as writeFile12 } from "fs/promises";
|
|
26509
26548
|
import { tmpdir as tmpdir5 } from "os";
|
|
26510
26549
|
import { join as join11, resolve as resolve65 } from "path";
|
|
26511
26550
|
import { setTimeout as sleep } from "timers/promises";
|
|
@@ -26579,7 +26618,7 @@ async function acquirePidfile(pidfile) {
|
|
|
26579
26618
|
} catch (err2) {
|
|
26580
26619
|
if (err2.code !== "EEXIST") throw err2;
|
|
26581
26620
|
if (attempt === 1) throw err2;
|
|
26582
|
-
const existing = (await
|
|
26621
|
+
const existing = (await readFile42(pidfile, "utf-8").catch(() => "")).trim();
|
|
26583
26622
|
if (existing.startsWith(STARTING_SENTINEL_PREFIX)) {
|
|
26584
26623
|
const parentPidRaw = existing.slice(STARTING_SENTINEL_PREFIX.length);
|
|
26585
26624
|
const parentPid = Number.parseInt(parentPidRaw, 10);
|
|
@@ -26681,7 +26720,7 @@ async function startRecording(input4) {
|
|
|
26681
26720
|
logHandle = null;
|
|
26682
26721
|
if (warmupMs > 0) await sleep(warmupMs);
|
|
26683
26722
|
if (!await isProcessAlive(pid)) {
|
|
26684
|
-
const tail = await
|
|
26723
|
+
const tail = await readFile42(log, "utf-8").then((s) => s.split("\n").slice(-20).join("\n")).catch(() => "");
|
|
26685
26724
|
acquiredPid = null;
|
|
26686
26725
|
throw new Error(
|
|
26687
26726
|
`ffmpeg exited during startup \u2014 likely macOS Screen Recording permission missing. Grant access to your terminal in System Settings \u2192 Privacy & Security \u2192 Screen Recording, then retry. Log: ${log}
|
|
@@ -26738,7 +26777,7 @@ ${tail}`
|
|
|
26738
26777
|
async function stopRecording() {
|
|
26739
26778
|
const pidfile = pidfilePath();
|
|
26740
26779
|
const sidecar = sidecarPath();
|
|
26741
|
-
const pidRaw = await
|
|
26780
|
+
const pidRaw = await readFile42(pidfile, "utf-8").catch(() => null);
|
|
26742
26781
|
if (pidRaw === null) {
|
|
26743
26782
|
throw new Error(
|
|
26744
26783
|
`No active recording found (no pidfile at ${pidfile}). Did you run --start?`
|
|
@@ -26748,7 +26787,7 @@ async function stopRecording() {
|
|
|
26748
26787
|
if (!Number.isInteger(pid) || pid <= 0) {
|
|
26749
26788
|
throw new Error(`Pidfile at ${pidfile} is corrupt (got "${pidRaw}").`);
|
|
26750
26789
|
}
|
|
26751
|
-
const sidecarRaw = await
|
|
26790
|
+
const sidecarRaw = await readFile42(sidecar, "utf-8").catch(() => null);
|
|
26752
26791
|
if (sidecarRaw === null) {
|
|
26753
26792
|
throw new Error(
|
|
26754
26793
|
`No recording sidecar at ${sidecar}. The recording state is inconsistent \u2014 delete ${pidfile} and re-run --start.`
|
|
@@ -26881,7 +26920,7 @@ function listArtifactsByAssignment(assignmentId) {
|
|
|
26881
26920
|
|
|
26882
26921
|
// src/utils/transcribers/elevenlabs.ts
|
|
26883
26922
|
import { spawn as spawn8 } from "child_process";
|
|
26884
|
-
import { mkdtemp as mkdtemp5, readFile as
|
|
26923
|
+
import { mkdtemp as mkdtemp5, readFile as readFile43, rm as rm11 } from "fs/promises";
|
|
26885
26924
|
import { tmpdir as tmpdir6 } from "os";
|
|
26886
26925
|
import { join as join12 } from "path";
|
|
26887
26926
|
var SCRIBE_URL = "https://api.elevenlabs.io/v1/speech-to-text";
|
|
@@ -26945,7 +26984,7 @@ async function extractAudio(videoAbsPath, wavOut) {
|
|
|
26945
26984
|
throw new TranscribeFfmpegError(`ffmpeg failed (exit ${result.code}): ${tail}`);
|
|
26946
26985
|
}
|
|
26947
26986
|
async function callScribe(wavPath, apiKey, opts) {
|
|
26948
|
-
const audio = await
|
|
26987
|
+
const audio = await readFile43(wavPath);
|
|
26949
26988
|
const form = new FormData();
|
|
26950
26989
|
form.set("file", new Blob([new Uint8Array(audio)], { type: "audio/wav" }), "audio.wav");
|
|
26951
26990
|
form.set("model_id", "scribe_v1");
|
|
@@ -27410,7 +27449,7 @@ async function captureCommand(target, options = {}) {
|
|
|
27410
27449
|
|
|
27411
27450
|
// src/commands/proof.ts
|
|
27412
27451
|
import { Command as Command6 } from "commander";
|
|
27413
|
-
import { readFile as
|
|
27452
|
+
import { readFile as readFile44, writeFile as writeFile14, rename as rename9, stat as stat9 } from "fs/promises";
|
|
27414
27453
|
import { resolve as resolve68, relative as relative5, isAbsolute as isAbsolute11, dirname as dirname19 } from "path";
|
|
27415
27454
|
import { randomBytes as randomBytes4 } from "crypto";
|
|
27416
27455
|
|
|
@@ -27655,7 +27694,7 @@ async function readAssignmentMeta(assignmentDir) {
|
|
|
27655
27694
|
if (!await fileExists(path)) {
|
|
27656
27695
|
return { title: "", body: "" };
|
|
27657
27696
|
}
|
|
27658
|
-
const content = await
|
|
27697
|
+
const content = await readFile44(path, "utf-8");
|
|
27659
27698
|
const fmMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n?/);
|
|
27660
27699
|
let title = "";
|
|
27661
27700
|
if (fmMatch) {
|
|
@@ -27717,7 +27756,7 @@ async function loadInlineFiles(rows, assignmentDir) {
|
|
|
27717
27756
|
continue;
|
|
27718
27757
|
}
|
|
27719
27758
|
try {
|
|
27720
|
-
out.set(r.file_path, await
|
|
27759
|
+
out.set(r.file_path, await readFile44(abs, "utf-8"));
|
|
27721
27760
|
} catch {
|
|
27722
27761
|
out.set(r.file_path, null);
|
|
27723
27762
|
}
|
|
@@ -27736,7 +27775,7 @@ async function loadTranscriptSidecars(rows, assignmentDir) {
|
|
|
27736
27775
|
const st = await stat9(sidecar);
|
|
27737
27776
|
if (st.size > INLINE_TEXT_LIMIT_BYTES) continue;
|
|
27738
27777
|
try {
|
|
27739
|
-
out.set(r.id, await
|
|
27778
|
+
out.set(r.id, await readFile44(sidecar, "utf-8"));
|
|
27740
27779
|
} catch {
|
|
27741
27780
|
}
|
|
27742
27781
|
}
|
|
@@ -28494,7 +28533,7 @@ function isoToCcusageDate(iso) {
|
|
|
28494
28533
|
|
|
28495
28534
|
// src/usage/cwd-extractor.ts
|
|
28496
28535
|
init_paths();
|
|
28497
|
-
import { open as open4, readdir as
|
|
28536
|
+
import { open as open4, readdir as readdir24, stat as stat10 } from "fs/promises";
|
|
28498
28537
|
import { join as join13 } from "path";
|
|
28499
28538
|
import { homedir as homedir9 } from "os";
|
|
28500
28539
|
var SCAN_LINE_CAP = 50;
|
|
@@ -28617,7 +28656,7 @@ function resolveCodexSessionsRoot(override) {
|
|
|
28617
28656
|
}
|
|
28618
28657
|
async function listDirSafe(path) {
|
|
28619
28658
|
try {
|
|
28620
|
-
const entries = await
|
|
28659
|
+
const entries = await readdir24(path, { withFileTypes: true });
|
|
28621
28660
|
return entries.map((e) => ({
|
|
28622
28661
|
name: e.name,
|
|
28623
28662
|
isFile: e.isFile(),
|
|
@@ -28973,7 +29012,7 @@ init_timestamp();
|
|
|
28973
29012
|
init_assignment_resolver();
|
|
28974
29013
|
init_assignment_todos();
|
|
28975
29014
|
import { resolve as resolve69 } from "path";
|
|
28976
|
-
import { readFile as
|
|
29015
|
+
import { readFile as readFile45 } from "fs/promises";
|
|
28977
29016
|
async function requestCommand(target, text, options = {}) {
|
|
28978
29017
|
if (!text || !text.trim()) {
|
|
28979
29018
|
throw new Error("Request text cannot be empty.");
|
|
@@ -29004,7 +29043,7 @@ async function requestCommand(target, text, options = {}) {
|
|
|
29004
29043
|
throw new Error(`assignment.md not found at ${assignmentMdPath2}`);
|
|
29005
29044
|
}
|
|
29006
29045
|
const source = options.from ?? process.env.SYNTAUR_ASSIGNMENT ?? "unknown";
|
|
29007
|
-
let content = await
|
|
29046
|
+
let content = await readFile45(assignmentMdPath2, "utf-8");
|
|
29008
29047
|
content = appendTodosToAssignmentBody(content, [
|
|
29009
29048
|
{ description: `${text.trim()} (from: ${source})` }
|
|
29010
29049
|
]);
|
|
@@ -29017,13 +29056,13 @@ async function requestCommand(target, text, options = {}) {
|
|
|
29017
29056
|
init_fs();
|
|
29018
29057
|
init_paths();
|
|
29019
29058
|
import { Command as Command9 } from "commander";
|
|
29020
|
-
import { readFile as
|
|
29059
|
+
import { readFile as readFile46, readdir as readdir25 } from "fs/promises";
|
|
29021
29060
|
import { resolve as resolve70 } from "path";
|
|
29022
29061
|
async function readContextAssignmentDir(cwd) {
|
|
29023
29062
|
const path = resolve70(cwd, ".syntaur", "context.json");
|
|
29024
29063
|
if (!await fileExists(path)) return null;
|
|
29025
29064
|
try {
|
|
29026
|
-
const raw = await
|
|
29065
|
+
const raw = await readFile46(path, "utf-8");
|
|
29027
29066
|
const ctx = JSON.parse(raw);
|
|
29028
29067
|
if (typeof ctx.assignmentDir === "string" && ctx.assignmentDir.length > 0) {
|
|
29029
29068
|
return ctx.assignmentDir;
|
|
@@ -29050,7 +29089,7 @@ async function resolveAssignmentDir(opts) {
|
|
|
29050
29089
|
var PLAN_PATTERN = /^plan(?:-v(\d+))?\.md$/;
|
|
29051
29090
|
async function listPlanFiles(assignmentDir) {
|
|
29052
29091
|
if (!await fileExists(assignmentDir)) return [];
|
|
29053
|
-
const entries = await
|
|
29092
|
+
const entries = await readdir25(assignmentDir, { withFileTypes: true });
|
|
29054
29093
|
const out = [];
|
|
29055
29094
|
for (const e of entries) {
|
|
29056
29095
|
if (!e.isFile()) continue;
|
|
@@ -29198,11 +29237,11 @@ async function runPlanVersion(options) {
|
|
|
29198
29237
|
if (await fileExists(newPath) && !options.force) {
|
|
29199
29238
|
throw new Error(`${next.fileName} already exists. Use --force to overwrite.`);
|
|
29200
29239
|
}
|
|
29201
|
-
const assignmentMd = await
|
|
29240
|
+
const assignmentMd = await readFile46(assignmentMdPath2, "utf-8");
|
|
29202
29241
|
const slugMatch = assignmentMd.match(/^slug:\s*(.+?)\s*$/m);
|
|
29203
29242
|
const slug = slugMatch ? slugMatch[1].trim() : assignmentDir.split("/").pop() ?? "";
|
|
29204
29243
|
const oldPlanPath = resolve70(assignmentDir, current.fileName);
|
|
29205
|
-
const oldPlanContent = await
|
|
29244
|
+
const oldPlanContent = await readFile46(oldPlanPath, "utf-8");
|
|
29206
29245
|
const oldBody = oldPlanContent.replace(/^---[\s\S]*?\n---\n?/, "");
|
|
29207
29246
|
const carriedTodos = extractUncheckedTodos(oldBody);
|
|
29208
29247
|
const stub = buildNewPlanStub({
|
|
@@ -29239,13 +29278,13 @@ planCommand.command("version").description(
|
|
|
29239
29278
|
// src/commands/session.ts
|
|
29240
29279
|
init_fs();
|
|
29241
29280
|
import { Command as Command10 } from "commander";
|
|
29242
|
-
import { readFile as
|
|
29281
|
+
import { readFile as readFile47, readdir as readdir26, stat as stat11 } from "fs/promises";
|
|
29243
29282
|
import { resolve as resolve71 } from "path";
|
|
29244
29283
|
async function readContext(cwd) {
|
|
29245
29284
|
const path = resolve71(cwd, ".syntaur", "context.json");
|
|
29246
29285
|
if (!await fileExists(path)) return null;
|
|
29247
29286
|
try {
|
|
29248
|
-
const raw = await
|
|
29287
|
+
const raw = await readFile47(path, "utf-8");
|
|
29249
29288
|
return JSON.parse(raw);
|
|
29250
29289
|
} catch {
|
|
29251
29290
|
return null;
|
|
@@ -29254,7 +29293,7 @@ async function readContext(cwd) {
|
|
|
29254
29293
|
async function findLatestSessionSummary(assignmentDir) {
|
|
29255
29294
|
const sessionsRoot = resolve71(assignmentDir, "sessions");
|
|
29256
29295
|
if (!await fileExists(sessionsRoot)) return null;
|
|
29257
|
-
const entries = await
|
|
29296
|
+
const entries = await readdir26(sessionsRoot, { withFileTypes: true });
|
|
29258
29297
|
let best = null;
|
|
29259
29298
|
for (const entry of entries) {
|
|
29260
29299
|
if (!entry.isDirectory()) continue;
|
|
@@ -29270,7 +29309,7 @@ async function findLatestSessionSummary(assignmentDir) {
|
|
|
29270
29309
|
async function findOpenHandoff(assignmentDir) {
|
|
29271
29310
|
const handoffPath = resolve71(assignmentDir, "handoff.md");
|
|
29272
29311
|
if (!await fileExists(handoffPath)) return null;
|
|
29273
|
-
const content = await
|
|
29312
|
+
const content = await readFile47(handoffPath, "utf-8");
|
|
29274
29313
|
const body = content.replace(/^---[\s\S]*?\n---\n?/, "").trim();
|
|
29275
29314
|
if (body.length === 0) return null;
|
|
29276
29315
|
if (/^<!--[\s\S]*-->$/.test(body)) return null;
|
|
@@ -29378,13 +29417,13 @@ init_git_worktree();
|
|
|
29378
29417
|
init_fs();
|
|
29379
29418
|
init_paths();
|
|
29380
29419
|
import { Command as Command11 } from "commander";
|
|
29381
|
-
import { readFile as
|
|
29420
|
+
import { readFile as readFile48 } from "fs/promises";
|
|
29382
29421
|
import { resolve as resolve72 } from "path";
|
|
29383
29422
|
async function readContext2(cwd) {
|
|
29384
29423
|
const path = resolve72(cwd, ".syntaur", "context.json");
|
|
29385
29424
|
if (!await fileExists(path)) return null;
|
|
29386
29425
|
try {
|
|
29387
|
-
return JSON.parse(await
|
|
29426
|
+
return JSON.parse(await readFile48(path, "utf-8"));
|
|
29388
29427
|
} catch {
|
|
29389
29428
|
return null;
|
|
29390
29429
|
}
|
|
@@ -29456,7 +29495,7 @@ import { resolve as resolve74 } from "path";
|
|
|
29456
29495
|
// src/utils/project-indexes.ts
|
|
29457
29496
|
init_parser();
|
|
29458
29497
|
init_fs();
|
|
29459
|
-
import { readdir as
|
|
29498
|
+
import { readdir as readdir27, readFile as readFile49 } from "fs/promises";
|
|
29460
29499
|
import { resolve as resolve73 } from "path";
|
|
29461
29500
|
function nowIso3() {
|
|
29462
29501
|
return (/* @__PURE__ */ new Date()).toISOString().replace(/\.\d{3}Z$/, "Z");
|
|
@@ -29466,7 +29505,7 @@ function readProjectSlug(projectDir) {
|
|
|
29466
29505
|
}
|
|
29467
29506
|
async function listSlugFiles(dir) {
|
|
29468
29507
|
if (!await fileExists(dir)) return [];
|
|
29469
|
-
const entries = await
|
|
29508
|
+
const entries = await readdir27(dir, { withFileTypes: true });
|
|
29470
29509
|
return entries.filter((e) => e.isFile() && e.name.endsWith(".md") && !e.name.startsWith("_")).map((e) => e.name).sort();
|
|
29471
29510
|
}
|
|
29472
29511
|
function escapeCell(value) {
|
|
@@ -29492,7 +29531,7 @@ async function rebuildResourcesIndex(projectDir) {
|
|
|
29492
29531
|
lines.push("| Name | Category | Source | Related Assignments | Updated |");
|
|
29493
29532
|
lines.push("|------|----------|--------|---------------------|---------|");
|
|
29494
29533
|
for (const fileName of files) {
|
|
29495
|
-
const content = await
|
|
29534
|
+
const content = await readFile49(resolve73(dir, fileName), "utf-8");
|
|
29496
29535
|
const parsed = parseResource(content);
|
|
29497
29536
|
const slugBase = fileName.replace(/\.md$/, "");
|
|
29498
29537
|
const name = parsed.name || slugBase;
|
|
@@ -29523,7 +29562,7 @@ async function rebuildMemoriesIndex(projectDir) {
|
|
|
29523
29562
|
lines.push("| Name | Source | Scope | Source Assignment | Updated |");
|
|
29524
29563
|
lines.push("|------|--------|-------|-------------------|---------|");
|
|
29525
29564
|
for (const fileName of files) {
|
|
29526
|
-
const content = await
|
|
29565
|
+
const content = await readFile49(resolve73(dir, fileName), "utf-8");
|
|
29527
29566
|
const parsed = parseMemory(content);
|
|
29528
29567
|
const slugBase = fileName.replace(/\.md$/, "");
|
|
29529
29568
|
const name = parsed.name || slugBase;
|
|
@@ -29698,7 +29737,7 @@ init_paths();
|
|
|
29698
29737
|
init_fs();
|
|
29699
29738
|
init_frontmatter();
|
|
29700
29739
|
import { Command as Command14 } from "commander";
|
|
29701
|
-
import { readFile as
|
|
29740
|
+
import { readFile as readFile50 } from "fs/promises";
|
|
29702
29741
|
import { resolve as resolve76 } from "path";
|
|
29703
29742
|
var AGE_PATTERN = /^(\d+)([dhwm])$/i;
|
|
29704
29743
|
function parseAgeToCutoff(age) {
|
|
@@ -29732,7 +29771,7 @@ async function loadTags(item) {
|
|
|
29732
29771
|
const path = assignmentMdPath(item);
|
|
29733
29772
|
if (!await fileExists(path)) return [];
|
|
29734
29773
|
try {
|
|
29735
|
-
const content = await
|
|
29774
|
+
const content = await readFile50(path, "utf-8");
|
|
29736
29775
|
return parseAssignmentFrontmatter(content).tags;
|
|
29737
29776
|
} catch {
|
|
29738
29777
|
return [];
|
|
@@ -29810,10 +29849,10 @@ var lsCommand = new Command14("ls").description(
|
|
|
29810
29849
|
|
|
29811
29850
|
// src/cli-default-command.ts
|
|
29812
29851
|
init_config2();
|
|
29813
|
-
import { readdir as
|
|
29852
|
+
import { readdir as readdir28 } from "fs/promises";
|
|
29814
29853
|
async function hasAnyProjectContent(projectsDir2) {
|
|
29815
29854
|
try {
|
|
29816
|
-
const entries = await
|
|
29855
|
+
const entries = await readdir28(projectsDir2, { withFileTypes: true });
|
|
29817
29856
|
return entries.some((entry) => entry.isDirectory());
|
|
29818
29857
|
} catch {
|
|
29819
29858
|
return false;
|
|
@@ -29850,20 +29889,20 @@ async function getDefaultCommandName() {
|
|
|
29850
29889
|
init_paths();
|
|
29851
29890
|
init_fs();
|
|
29852
29891
|
import { fileURLToPath as fileURLToPath10 } from "url";
|
|
29853
|
-
import { readFile as
|
|
29892
|
+
import { readFile as readFile52 } from "fs/promises";
|
|
29854
29893
|
import { dirname as dirname21, join as join15, resolve as resolve77 } from "path";
|
|
29855
29894
|
import { spawn as spawn10 } from "child_process";
|
|
29856
29895
|
import { createInterface as createInterface2 } from "readline/promises";
|
|
29857
29896
|
|
|
29858
29897
|
// src/utils/version.ts
|
|
29859
29898
|
import { fileURLToPath as fileURLToPath9 } from "url";
|
|
29860
|
-
import { readFile as
|
|
29899
|
+
import { readFile as readFile51 } from "fs/promises";
|
|
29861
29900
|
import { dirname as dirname20, join as join14 } from "path";
|
|
29862
29901
|
async function readPackageVersion(scriptUrl) {
|
|
29863
29902
|
try {
|
|
29864
29903
|
const scriptPath = fileURLToPath9(scriptUrl);
|
|
29865
29904
|
const pkgRoot = dirname20(dirname20(scriptPath));
|
|
29866
|
-
const raw = await
|
|
29905
|
+
const raw = await readFile51(join14(pkgRoot, "package.json"), "utf-8");
|
|
29867
29906
|
const parsed = JSON.parse(raw);
|
|
29868
29907
|
return typeof parsed.version === "string" ? parsed.version : null;
|
|
29869
29908
|
} catch {
|
|
@@ -29893,7 +29932,7 @@ function isRunningViaNpx(scriptUrl) {
|
|
|
29893
29932
|
async function readState() {
|
|
29894
29933
|
if (!await fileExists(STATE_FILE)) return null;
|
|
29895
29934
|
try {
|
|
29896
|
-
const raw = await
|
|
29935
|
+
const raw = await readFile52(STATE_FILE, "utf-8");
|
|
29897
29936
|
return JSON.parse(raw);
|
|
29898
29937
|
} catch {
|
|
29899
29938
|
return null;
|
|
@@ -29952,7 +29991,7 @@ async function readGlobalVersion() {
|
|
|
29952
29991
|
try {
|
|
29953
29992
|
const manifestPath = join15(rootPath, "syntaur", "package.json");
|
|
29954
29993
|
if (!await fileExists(manifestPath)) return null;
|
|
29955
|
-
const raw = await
|
|
29994
|
+
const raw = await readFile52(manifestPath, "utf-8");
|
|
29956
29995
|
const parsed = JSON.parse(raw);
|
|
29957
29996
|
return typeof parsed.version === "string" ? parsed.version : null;
|
|
29958
29997
|
} catch {
|