syntaur 0.69.0 → 0.70.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +1 -1
- package/dist/dashboard/server.js +74 -41
- package/dist/dashboard/server.js.map +1 -1
- package/dist/index.js +344 -321
- package/dist/index.js.map +1 -1
- package/dist/launch/index.js +319 -32
- package/dist/launch/index.js.map +1 -1
- package/package.json +1 -1
- package/platforms/claude-code/.claude-plugin/plugin.json +1 -1
- package/platforms/codex/.codex-plugin/plugin.json +1 -1
- package/platforms/hermes/plugins/syntaur/__pycache__/__init__.cpython-312.pyc +0 -0
- package/platforms/hermes/plugins/syntaur/__pycache__/boundary.cpython-312.pyc +0 -0
package/dist/index.js
CHANGED
|
@@ -849,7 +849,7 @@ function getTargetStatus(_from, command, table) {
|
|
|
849
849
|
if (!table) {
|
|
850
850
|
return DEFAULT_COMMAND_TARGETS.get(command) ?? null;
|
|
851
851
|
}
|
|
852
|
-
return table.get(command) ?? table.get(
|
|
852
|
+
return table.get(`${_from}:${command}`) ?? table.get(command) ?? null;
|
|
853
853
|
}
|
|
854
854
|
function isTerminalStatus(status, terminalSet) {
|
|
855
855
|
return (terminalSet ?? TERMINAL_STATUSES).has(status);
|
|
@@ -7685,8 +7685,7 @@ async function areDependenciesSatisfied(projectDir, dependsOn, terminalStatuses3
|
|
|
7685
7685
|
if (!await fileExists(depPath)) return false;
|
|
7686
7686
|
try {
|
|
7687
7687
|
const content = await readFile10(depPath, "utf-8");
|
|
7688
|
-
const
|
|
7689
|
-
const status = m ? m[1].trim() : "";
|
|
7688
|
+
const { status } = parseAssignmentFrontmatter(content);
|
|
7690
7689
|
if (!terminalStatuses3.has(status)) return false;
|
|
7691
7690
|
} catch {
|
|
7692
7691
|
return false;
|
|
@@ -7801,6 +7800,7 @@ var init_facts = __esm({
|
|
|
7801
7800
|
init_fs();
|
|
7802
7801
|
init_git_worktree();
|
|
7803
7802
|
init_derive();
|
|
7803
|
+
init_frontmatter();
|
|
7804
7804
|
HTML_COMMENT_RE = /<!--[\s\S]*?-->/g;
|
|
7805
7805
|
PLAN_FILE_RE = /^plan(?:-v(\d+))?\.md$/;
|
|
7806
7806
|
}
|
|
@@ -13391,6 +13391,22 @@ var init_assignment_todos = __esm({
|
|
|
13391
13391
|
}
|
|
13392
13392
|
});
|
|
13393
13393
|
|
|
13394
|
+
// src/utils/path-canon.ts
|
|
13395
|
+
import { realpathSync as realpathSync2 } from "fs";
|
|
13396
|
+
import { resolve as resolve45 } from "path";
|
|
13397
|
+
function canonicalPath(p) {
|
|
13398
|
+
try {
|
|
13399
|
+
return realpathSync2(resolve45(p));
|
|
13400
|
+
} catch {
|
|
13401
|
+
return resolve45(p).replace(/\/+$/, "");
|
|
13402
|
+
}
|
|
13403
|
+
}
|
|
13404
|
+
var init_path_canon = __esm({
|
|
13405
|
+
"src/utils/path-canon.ts"() {
|
|
13406
|
+
"use strict";
|
|
13407
|
+
}
|
|
13408
|
+
});
|
|
13409
|
+
|
|
13394
13410
|
// src/targets/renderers.ts
|
|
13395
13411
|
var RENDERERS;
|
|
13396
13412
|
var init_renderers = __esm({
|
|
@@ -13411,10 +13427,10 @@ var init_renderers = __esm({
|
|
|
13411
13427
|
});
|
|
13412
13428
|
|
|
13413
13429
|
// src/targets/user-descriptors.ts
|
|
13414
|
-
import { resolve as
|
|
13430
|
+
import { resolve as resolve46 } from "path";
|
|
13415
13431
|
import { readFile as readFile31, readdir as readdir19 } from "fs/promises";
|
|
13416
13432
|
function userTargetsDir() {
|
|
13417
|
-
return
|
|
13433
|
+
return resolve46(syntaurRoot(), "targets");
|
|
13418
13434
|
}
|
|
13419
13435
|
function msg(err2) {
|
|
13420
13436
|
return err2 instanceof Error ? err2.message : String(err2);
|
|
@@ -13428,7 +13444,7 @@ function expandHomeAndEnv(p) {
|
|
|
13428
13444
|
return v ?? "";
|
|
13429
13445
|
}
|
|
13430
13446
|
);
|
|
13431
|
-
return
|
|
13447
|
+
return resolve46(expandHome(envExpanded));
|
|
13432
13448
|
}
|
|
13433
13449
|
function compileDetect(spec) {
|
|
13434
13450
|
switch (spec.kind) {
|
|
@@ -13580,7 +13596,7 @@ async function loadUserDescriptors(opts = {}) {
|
|
|
13580
13596
|
const targets = [];
|
|
13581
13597
|
const seen = /* @__PURE__ */ new Set();
|
|
13582
13598
|
for (const file of files) {
|
|
13583
|
-
const full =
|
|
13599
|
+
const full = resolve46(dir, file);
|
|
13584
13600
|
let raw2;
|
|
13585
13601
|
try {
|
|
13586
13602
|
raw2 = await readFile31(full, "utf-8");
|
|
@@ -13633,23 +13649,23 @@ var init_user_descriptors = __esm({
|
|
|
13633
13649
|
|
|
13634
13650
|
// src/targets/registry.ts
|
|
13635
13651
|
import { homedir as homedir7 } from "os";
|
|
13636
|
-
import { join as join10, resolve as
|
|
13652
|
+
import { join as join10, resolve as resolve47 } from "path";
|
|
13637
13653
|
function home(...segments) {
|
|
13638
|
-
return
|
|
13654
|
+
return resolve47(homedir7(), ...segments);
|
|
13639
13655
|
}
|
|
13640
13656
|
function hermesHome() {
|
|
13641
13657
|
const env = process.env.HERMES_HOME;
|
|
13642
|
-
return env && env.length > 0 ?
|
|
13658
|
+
return env && env.length > 0 ? resolve47(env) : home(".hermes");
|
|
13643
13659
|
}
|
|
13644
13660
|
function hermesSkillsDir() {
|
|
13645
|
-
return
|
|
13661
|
+
return resolve47(hermesHome(), "skills");
|
|
13646
13662
|
}
|
|
13647
13663
|
function isHermesHomeCustom() {
|
|
13648
13664
|
return hermesHome() !== home(".hermes");
|
|
13649
13665
|
}
|
|
13650
13666
|
function codexHome() {
|
|
13651
13667
|
const env = process.env.CODEX_HOME;
|
|
13652
|
-
return env && env.length > 0 ?
|
|
13668
|
+
return env && env.length > 0 ? resolve47(env) : home(".codex");
|
|
13653
13669
|
}
|
|
13654
13670
|
function toDiscovered(meta) {
|
|
13655
13671
|
if (!meta) return null;
|
|
@@ -13726,7 +13742,7 @@ var init_registry = __esm({
|
|
|
13726
13742
|
skillsShAgentId: "codex",
|
|
13727
13743
|
nativePlugin: "codex",
|
|
13728
13744
|
detect: detectDir(codexHome()),
|
|
13729
|
-
skillsDir: { global:
|
|
13745
|
+
skillsDir: { global: resolve47(codexHome(), "skills") },
|
|
13730
13746
|
instructions: { files: [{ path: "AGENTS.md", renderer: "codexAgents" }] },
|
|
13731
13747
|
sessions: codexSessions
|
|
13732
13748
|
},
|
|
@@ -13795,7 +13811,7 @@ var init_registry = __esm({
|
|
|
13795
13811
|
tier3: {
|
|
13796
13812
|
kind: "hermes-plugin",
|
|
13797
13813
|
source: "platforms/hermes/plugins/syntaur",
|
|
13798
|
-
installDir: () =>
|
|
13814
|
+
installDir: () => resolve47(hermesHome(), "plugins", "syntaur"),
|
|
13799
13815
|
entry: "plugin.yaml"
|
|
13800
13816
|
}
|
|
13801
13817
|
}
|
|
@@ -13815,7 +13831,7 @@ import { execFile as execFile3, execFileSync as execFileSync4 } from "child_proc
|
|
|
13815
13831
|
import { promisify as promisify3 } from "util";
|
|
13816
13832
|
import { statSync as statSync4 } from "fs";
|
|
13817
13833
|
import { readFile as readFile32 } from "fs/promises";
|
|
13818
|
-
import { resolve as
|
|
13834
|
+
import { resolve as resolve48 } from "path";
|
|
13819
13835
|
function emptySummary() {
|
|
13820
13836
|
return { discovered: 0, inserted: 0, revived: 0, swept: 0, skipped: 0, changed: false };
|
|
13821
13837
|
}
|
|
@@ -13868,10 +13884,15 @@ async function defaultOpenFiles(files) {
|
|
|
13868
13884
|
}
|
|
13869
13885
|
return open7;
|
|
13870
13886
|
}
|
|
13887
|
+
function canonicalizeOpenSet(open7) {
|
|
13888
|
+
const out = /* @__PURE__ */ new Set();
|
|
13889
|
+
for (const p of open7) out.add(canonicalPath(p));
|
|
13890
|
+
return out;
|
|
13891
|
+
}
|
|
13871
13892
|
async function readContextLink(cwd, cache3) {
|
|
13872
13893
|
if (cache3.has(cwd)) return cache3.get(cwd);
|
|
13873
13894
|
let link = null;
|
|
13874
|
-
const path =
|
|
13895
|
+
const path = resolve48(cwd, ".syntaur", "context.json");
|
|
13875
13896
|
if (await fileExists(path)) {
|
|
13876
13897
|
try {
|
|
13877
13898
|
const parsed = JSON.parse(await readFile32(path, "utf-8"));
|
|
@@ -13923,7 +13944,9 @@ async function scanSessions(opts = {}, deps = {}) {
|
|
|
13923
13944
|
}
|
|
13924
13945
|
}
|
|
13925
13946
|
summary.discovered = discovered.length;
|
|
13926
|
-
const openSet =
|
|
13947
|
+
const openSet = canonicalizeOpenSet(
|
|
13948
|
+
await openFiles(discovered.map((d) => d.transcriptPath))
|
|
13949
|
+
);
|
|
13927
13950
|
const contextCache = /* @__PURE__ */ new Map();
|
|
13928
13951
|
for (const d of discovered) {
|
|
13929
13952
|
const link = await readContextLink(d.cwd, contextCache);
|
|
@@ -13932,7 +13955,7 @@ async function scanSessions(opts = {}, deps = {}) {
|
|
|
13932
13955
|
continue;
|
|
13933
13956
|
}
|
|
13934
13957
|
const mtime = statMtimeMs(d.transcriptPath);
|
|
13935
|
-
const heldOpen = openSet.has(d.transcriptPath);
|
|
13958
|
+
const heldOpen = openSet.has(canonicalPath(d.transcriptPath));
|
|
13936
13959
|
const isLive = heldOpen || mtime !== null && now() - mtime < FRESH_MTIME_MS;
|
|
13937
13960
|
const prev = getSessionById(d.sessionId);
|
|
13938
13961
|
const status = isLive ? "active" : prev?.status ?? "stopped";
|
|
@@ -13994,12 +14017,14 @@ async function scanSessions(opts = {}, deps = {}) {
|
|
|
13994
14017
|
sweepCandidates.push({ sessionId: row.session_id, transcriptPath: null });
|
|
13995
14018
|
}
|
|
13996
14019
|
}
|
|
13997
|
-
const sweepOpenSet =
|
|
13998
|
-
|
|
14020
|
+
const sweepOpenSet = canonicalizeOpenSet(
|
|
14021
|
+
await openFiles(
|
|
14022
|
+
sweepCandidates.map((c2) => c2.transcriptPath).filter((p) => p !== null)
|
|
14023
|
+
)
|
|
13999
14024
|
);
|
|
14000
14025
|
for (const candidate of sweepCandidates) {
|
|
14001
14026
|
if (candidate.transcriptPath) {
|
|
14002
|
-
if (sweepOpenSet.has(candidate.transcriptPath)) continue;
|
|
14027
|
+
if (sweepOpenSet.has(canonicalPath(candidate.transcriptPath))) continue;
|
|
14003
14028
|
const mtime = statMtimeMs(candidate.transcriptPath);
|
|
14004
14029
|
if (mtime !== null && now() - mtime < FRESH_MTIME_MS) continue;
|
|
14005
14030
|
const endedAt = mtime !== null ? new Date(mtime).toISOString() : void 0;
|
|
@@ -14020,6 +14045,7 @@ var init_scanner2 = __esm({
|
|
|
14020
14045
|
"src/sessions/scanner.ts"() {
|
|
14021
14046
|
"use strict";
|
|
14022
14047
|
init_fs();
|
|
14048
|
+
init_path_canon();
|
|
14023
14049
|
init_config2();
|
|
14024
14050
|
init_session_id();
|
|
14025
14051
|
init_registry();
|
|
@@ -14076,13 +14102,13 @@ import {
|
|
|
14076
14102
|
mkdirSync as mkdirSync3,
|
|
14077
14103
|
rmSync,
|
|
14078
14104
|
writeFileSync as writeFileSync2,
|
|
14079
|
-
realpathSync as
|
|
14105
|
+
realpathSync as realpathSync4,
|
|
14080
14106
|
openSync,
|
|
14081
14107
|
closeSync,
|
|
14082
14108
|
unlinkSync
|
|
14083
14109
|
} from "fs";
|
|
14084
14110
|
import { fileURLToPath as fileURLToPath9, pathToFileURL } from "url";
|
|
14085
|
-
import { dirname as dirname21, resolve as
|
|
14111
|
+
import { dirname as dirname21, resolve as resolve73, join as join16 } from "path";
|
|
14086
14112
|
import { homedir as homedir13, tmpdir as tmpdir2 } from "os";
|
|
14087
14113
|
import { spawnSync as spawnSync7 } from "child_process";
|
|
14088
14114
|
function syntaurRootMjs() {
|
|
@@ -14104,7 +14130,7 @@ async function registerMacosUrlHandler(options = { throwOnFailure: false }) {
|
|
|
14104
14130
|
}
|
|
14105
14131
|
const stateRoot = syntaurRootMjs();
|
|
14106
14132
|
mkdirSync3(stateRoot, { recursive: true });
|
|
14107
|
-
const lockPath =
|
|
14133
|
+
const lockPath = resolve73(stateRoot, "install-url-handler.lock");
|
|
14108
14134
|
let lockFd;
|
|
14109
14135
|
try {
|
|
14110
14136
|
lockFd = openSync(lockPath, "wx");
|
|
@@ -14120,8 +14146,8 @@ async function registerMacosUrlHandler(options = { throwOnFailure: false }) {
|
|
|
14120
14146
|
throw err2;
|
|
14121
14147
|
}
|
|
14122
14148
|
try {
|
|
14123
|
-
const pkgRoot =
|
|
14124
|
-
const cliBin =
|
|
14149
|
+
const pkgRoot = resolve73(dirname21(fileURLToPath9(import.meta.url)), "..");
|
|
14150
|
+
const cliBin = realpathSync4(resolve73(pkgRoot, "bin/syntaur.js"));
|
|
14125
14151
|
const nodeBin = process.execPath;
|
|
14126
14152
|
const bundleParent = join16(
|
|
14127
14153
|
homedir13(),
|
|
@@ -15129,7 +15155,7 @@ init_create_assignment();
|
|
|
15129
15155
|
init_config2();
|
|
15130
15156
|
import { spawn as spawn5 } from "child_process";
|
|
15131
15157
|
import { createServer as createNetServer } from "net";
|
|
15132
|
-
import { resolve as
|
|
15158
|
+
import { resolve as resolve50, dirname as dirname13 } from "path";
|
|
15133
15159
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
15134
15160
|
|
|
15135
15161
|
// src/dashboard/server.ts
|
|
@@ -15139,7 +15165,7 @@ init_assignment_resolver();
|
|
|
15139
15165
|
init_agent_sessions();
|
|
15140
15166
|
import express from "express";
|
|
15141
15167
|
import { createServer } from "http";
|
|
15142
|
-
import { resolve as
|
|
15168
|
+
import { resolve as resolve49 } from "path";
|
|
15143
15169
|
import { writeFile as writeFile8, unlink as unlink9 } from "fs/promises";
|
|
15144
15170
|
import { WebSocketServer, WebSocket } from "ws";
|
|
15145
15171
|
|
|
@@ -20508,6 +20534,12 @@ async function resolveSessionPlan(input4, terminal) {
|
|
|
20508
20534
|
}
|
|
20509
20535
|
}
|
|
20510
20536
|
}
|
|
20537
|
+
if (!cwd.trim()) {
|
|
20538
|
+
throw new LaunchError(
|
|
20539
|
+
"workspace-path-invalid",
|
|
20540
|
+
`Session ${input4.id} has no recorded working directory and no linked assignment workspace resolved \u2014 refusing to launch in an unknown directory.`
|
|
20541
|
+
);
|
|
20542
|
+
}
|
|
20511
20543
|
const agent = getAgents(input4.config).find((a) => a.id === session.agent);
|
|
20512
20544
|
if (!agent) {
|
|
20513
20545
|
throw new LaunchError(
|
|
@@ -22968,8 +23000,7 @@ function predictReset(_provider, anchor) {
|
|
|
22968
23000
|
}
|
|
22969
23001
|
function verifyReset(provider, anchor, now) {
|
|
22970
23002
|
const reset = predictReset(provider, anchor);
|
|
22971
|
-
|
|
22972
|
-
return { eligible: false, rescheduleToIso: reset };
|
|
23003
|
+
return { eligible: now.getTime() >= Date.parse(reset) };
|
|
22973
23004
|
}
|
|
22974
23005
|
|
|
22975
23006
|
// src/schedules/triggers.ts
|
|
@@ -22993,13 +23024,15 @@ function evaluateKind(trigger, job, ctx) {
|
|
|
22993
23024
|
switch (trigger.kind) {
|
|
22994
23025
|
case "at": {
|
|
22995
23026
|
const at = Date.parse(trigger.at);
|
|
22996
|
-
const
|
|
23027
|
+
const beforeCreation = !Number.isNaN(createdAtMs) && at < createdAtMs;
|
|
23028
|
+
const due = !Number.isNaN(at) && ctx.now.getTime() >= at && !beforeCreation;
|
|
22997
23029
|
return { due, dedupeKey: `at:${trigger.at}`, nextFireIso: trigger.at };
|
|
22998
23030
|
}
|
|
22999
23031
|
case "in": {
|
|
23000
23032
|
const anchor = Date.parse(trigger.anchorIso);
|
|
23001
23033
|
const fireAt = anchor + trigger.durationMs;
|
|
23002
|
-
const
|
|
23034
|
+
const beforeCreation = !Number.isNaN(createdAtMs) && fireAt < createdAtMs;
|
|
23035
|
+
const due = !Number.isNaN(anchor) && ctx.now.getTime() >= fireAt && !beforeCreation;
|
|
23003
23036
|
const fireIso = Number.isNaN(anchor) ? null : iso(new Date(fireAt));
|
|
23004
23037
|
return { due, dedupeKey: `in:${fireAt}`, nextFireIso: fireIso };
|
|
23005
23038
|
}
|
|
@@ -23033,7 +23066,7 @@ function evaluateAfterReset(trigger, now) {
|
|
|
23033
23066
|
if (v.eligible) {
|
|
23034
23067
|
return { due: true, dedupeKey: `after-reset:${trigger.anchor.windowStartIso}`, nextFireIso: predicted };
|
|
23035
23068
|
}
|
|
23036
|
-
return { due: false, nextFireIso: predicted
|
|
23069
|
+
return { due: false, nextFireIso: predicted };
|
|
23037
23070
|
}
|
|
23038
23071
|
function evaluateWhenStatus(trigger, job, ctx, createdAtMs) {
|
|
23039
23072
|
const fm = ctx.assignment;
|
|
@@ -28377,7 +28410,7 @@ function createDashboardServer(options) {
|
|
|
28377
28410
|
(async () => {
|
|
28378
28411
|
try {
|
|
28379
28412
|
const configResult = await migrateLegacyConfig(
|
|
28380
|
-
|
|
28413
|
+
resolve49(syntaurRoot(), "config.md")
|
|
28381
28414
|
);
|
|
28382
28415
|
const projectResult = await migrateLegacyProjectFiles(projectsDir2);
|
|
28383
28416
|
const summary = summarizeMigration(projectResult, configResult);
|
|
@@ -28900,14 +28933,14 @@ function createDashboardServer(options) {
|
|
|
28900
28933
|
app.use("/api/backup", createBackupRouter());
|
|
28901
28934
|
if (serveStaticUi && dashboardDistPath) {
|
|
28902
28935
|
const sendOpts = { dotfiles: "allow" };
|
|
28903
|
-
app.use("/assets", express.static(
|
|
28936
|
+
app.use("/assets", express.static(resolve49(dashboardDistPath, "assets"), sendOpts));
|
|
28904
28937
|
app.use(express.static(dashboardDistPath, { ...sendOpts, index: false, fallthrough: true }));
|
|
28905
28938
|
app.get("{*path}", async (req2, res) => {
|
|
28906
28939
|
if (req2.path.startsWith("/api") || req2.path === "/ws" || req2.path.startsWith("/assets")) {
|
|
28907
28940
|
res.status(404).json({ error: "Not Found" });
|
|
28908
28941
|
return;
|
|
28909
28942
|
}
|
|
28910
|
-
const indexPath =
|
|
28943
|
+
const indexPath = resolve49(dashboardDistPath, "index.html");
|
|
28911
28944
|
if (!await fileExists(indexPath)) {
|
|
28912
28945
|
res.status(503).send(
|
|
28913
28946
|
'Dashboard not built. Run "npm run build:dashboard" first.'
|
|
@@ -28943,8 +28976,8 @@ function createDashboardServer(options) {
|
|
|
28943
28976
|
if (!await migrationGate()) return;
|
|
28944
28977
|
try {
|
|
28945
28978
|
const context = await resolveDeriveContext2();
|
|
28946
|
-
const projectDir = projectSlug ?
|
|
28947
|
-
const path = projectDir ?
|
|
28979
|
+
const projectDir = projectSlug ? resolve49(projectsDir2, projectSlug) : null;
|
|
28980
|
+
const path = projectDir ? resolve49(projectDir, "assignments", assignmentSlug, "assignment.md") : resolve49(assignmentsDir2, assignmentSlug, "assignment.md");
|
|
28948
28981
|
if (!await fileExists(path)) return;
|
|
28949
28982
|
const result = await recomputeAndWrite2(path, {
|
|
28950
28983
|
cause: "derive",
|
|
@@ -28997,8 +29030,8 @@ function createDashboardServer(options) {
|
|
|
28997
29030
|
serversDir: serversDir2,
|
|
28998
29031
|
playbooksDir: playbooksDir3,
|
|
28999
29032
|
todosDir: todosDir2,
|
|
29000
|
-
dbPath:
|
|
29001
|
-
configPath:
|
|
29033
|
+
dbPath: resolve49(syntaurRoot(), "syntaur.db"),
|
|
29034
|
+
configPath: resolve49(syntaurRoot(), "config.md"),
|
|
29002
29035
|
onMessage: broadcast,
|
|
29003
29036
|
onAssignmentChanged: (projectSlug, assignmentSlug) => {
|
|
29004
29037
|
void recomputeOne(projectSlug, assignmentSlug);
|
|
@@ -29066,7 +29099,7 @@ function createDashboardServer(options) {
|
|
|
29066
29099
|
}
|
|
29067
29100
|
});
|
|
29068
29101
|
server.listen(port, () => {
|
|
29069
|
-
const portFile =
|
|
29102
|
+
const portFile = resolve49(syntaurRoot(), "dashboard-port");
|
|
29070
29103
|
writeFile8(portFile, String(port), "utf-8").catch(() => {
|
|
29071
29104
|
});
|
|
29072
29105
|
resolvePromise();
|
|
@@ -29090,7 +29123,7 @@ function createDashboardServer(options) {
|
|
|
29090
29123
|
client.terminate();
|
|
29091
29124
|
}
|
|
29092
29125
|
clients.clear();
|
|
29093
|
-
const portFile =
|
|
29126
|
+
const portFile = resolve49(syntaurRoot(), "dashboard-port");
|
|
29094
29127
|
await unlink9(portFile).catch(() => {
|
|
29095
29128
|
});
|
|
29096
29129
|
server.closeAllConnections?.();
|
|
@@ -29218,8 +29251,8 @@ async function dashboardCommand(options) {
|
|
|
29218
29251
|
port = availablePort;
|
|
29219
29252
|
}
|
|
29220
29253
|
const thisFile = fileURLToPath3(import.meta.url);
|
|
29221
|
-
const packageRoot =
|
|
29222
|
-
const dashboardDist =
|
|
29254
|
+
const packageRoot = resolve50(dirname13(thisFile), "..");
|
|
29255
|
+
const dashboardDist = resolve50(packageRoot, "dashboard", "dist");
|
|
29223
29256
|
const server = createDashboardServer({
|
|
29224
29257
|
port,
|
|
29225
29258
|
projectsDir: projectsDir2,
|
|
@@ -29243,8 +29276,8 @@ async function dashboardCommand(options) {
|
|
|
29243
29276
|
}
|
|
29244
29277
|
let viteProcess = null;
|
|
29245
29278
|
if (mode === "dev") {
|
|
29246
|
-
const dashboardDir =
|
|
29247
|
-
const viteBin =
|
|
29279
|
+
const dashboardDir = resolve50(packageRoot, "dashboard");
|
|
29280
|
+
const viteBin = resolve50(dashboardDir, "node_modules", ".bin", "vite");
|
|
29248
29281
|
if (!await fileExists(viteBin)) {
|
|
29249
29282
|
console.error(
|
|
29250
29283
|
'Vite not found. Run "npm ci --prefix dashboard" first, or use the default bundled dashboard mode.'
|
|
@@ -29319,7 +29352,7 @@ init_config2();
|
|
|
29319
29352
|
init_slug();
|
|
29320
29353
|
init_lifecycle();
|
|
29321
29354
|
init_assignment_resolver();
|
|
29322
|
-
import { resolve as
|
|
29355
|
+
import { resolve as resolve51 } from "path";
|
|
29323
29356
|
function resolveLinkedTodosLookup(projectsDir2) {
|
|
29324
29357
|
return { todosDir: todosDir(), projectsDir: projectsDir2 };
|
|
29325
29358
|
}
|
|
@@ -29333,8 +29366,8 @@ async function runTransition(assignment, command, options = {}) {
|
|
|
29333
29366
|
if (!isValidSlug(assignment)) {
|
|
29334
29367
|
throw new Error(`Invalid assignment slug "${assignment}".`);
|
|
29335
29368
|
}
|
|
29336
|
-
const projectDir =
|
|
29337
|
-
const projectMdPath =
|
|
29369
|
+
const projectDir = resolve51(baseDir, options.project);
|
|
29370
|
+
const projectMdPath = resolve51(projectDir, "project.md");
|
|
29338
29371
|
if (!await fileExists(projectDir) || !await fileExists(projectMdPath)) {
|
|
29339
29372
|
throw new Error(`Project "${options.project}" not found at ${projectDir}.`);
|
|
29340
29373
|
}
|
|
@@ -29367,8 +29400,8 @@ async function runAssign(assignment, agent, options = {}) {
|
|
|
29367
29400
|
if (!isValidSlug(assignment)) {
|
|
29368
29401
|
throw new Error(`Invalid assignment slug "${assignment}".`);
|
|
29369
29402
|
}
|
|
29370
|
-
const projectDir =
|
|
29371
|
-
const projectMdPath =
|
|
29403
|
+
const projectDir = resolve51(baseDir, options.project);
|
|
29404
|
+
const projectMdPath = resolve51(projectDir, "project.md");
|
|
29372
29405
|
if (!await fileExists(projectDir) || !await fileExists(projectMdPath)) {
|
|
29373
29406
|
throw new Error(`Project "${options.project}" not found at ${projectDir}.`);
|
|
29374
29407
|
}
|
|
@@ -29392,8 +29425,8 @@ async function runUnassign(assignment, options = {}) {
|
|
|
29392
29425
|
if (!isValidSlug(assignment)) {
|
|
29393
29426
|
throw new Error(`Invalid assignment slug "${assignment}".`);
|
|
29394
29427
|
}
|
|
29395
|
-
const projectDir =
|
|
29396
|
-
const projectMdPath =
|
|
29428
|
+
const projectDir = resolve51(baseDir, options.project);
|
|
29429
|
+
const projectMdPath = resolve51(projectDir, "project.md");
|
|
29397
29430
|
if (!await fileExists(projectDir) || !await fileExists(projectMdPath)) {
|
|
29398
29431
|
throw new Error(`Project "${options.project}" not found at ${projectDir}.`);
|
|
29399
29432
|
}
|
|
@@ -29446,7 +29479,7 @@ init_recompute();
|
|
|
29446
29479
|
init_event_emit();
|
|
29447
29480
|
init_transitions();
|
|
29448
29481
|
import { readFile as readFile34 } from "fs/promises";
|
|
29449
|
-
import { resolve as
|
|
29482
|
+
import { resolve as resolve53, basename as basename7 } from "path";
|
|
29450
29483
|
|
|
29451
29484
|
// src/utils/assignment-target.ts
|
|
29452
29485
|
init_paths();
|
|
@@ -29455,7 +29488,7 @@ init_config2();
|
|
|
29455
29488
|
init_slug();
|
|
29456
29489
|
init_assignment_resolver();
|
|
29457
29490
|
init_parser();
|
|
29458
|
-
import { resolve as
|
|
29491
|
+
import { resolve as resolve52 } from "path";
|
|
29459
29492
|
import { readFile as readFile33 } from "fs/promises";
|
|
29460
29493
|
var AssignmentTargetError = class extends Error {
|
|
29461
29494
|
};
|
|
@@ -29468,7 +29501,7 @@ function classifyContext(ctx) {
|
|
|
29468
29501
|
return "empty";
|
|
29469
29502
|
}
|
|
29470
29503
|
async function readAssignmentFrontmatterId(assignmentDir) {
|
|
29471
|
-
const path =
|
|
29504
|
+
const path = resolve52(assignmentDir, "assignment.md");
|
|
29472
29505
|
if (!await fileExists(path)) return null;
|
|
29473
29506
|
try {
|
|
29474
29507
|
const content = await readFile33(path, "utf-8");
|
|
@@ -29479,7 +29512,7 @@ async function readAssignmentFrontmatterId(assignmentDir) {
|
|
|
29479
29512
|
}
|
|
29480
29513
|
}
|
|
29481
29514
|
async function readContextJson(cwd) {
|
|
29482
|
-
const path =
|
|
29515
|
+
const path = resolve52(cwd, ".syntaur", "context.json");
|
|
29483
29516
|
if (!await fileExists(path)) return null;
|
|
29484
29517
|
try {
|
|
29485
29518
|
const raw2 = await readFile33(path, "utf-8");
|
|
@@ -29503,15 +29536,15 @@ async function resolveAssignmentTarget(input4, opts = {}) {
|
|
|
29503
29536
|
if (!isValidSlug(input4)) {
|
|
29504
29537
|
throw new AssignmentTargetError(`Invalid assignment slug "${input4}".`);
|
|
29505
29538
|
}
|
|
29506
|
-
const projectDir =
|
|
29507
|
-
const projectMdPath =
|
|
29539
|
+
const projectDir = resolve52(baseDir, opts.project);
|
|
29540
|
+
const projectMdPath = resolve52(projectDir, "project.md");
|
|
29508
29541
|
if (!await fileExists(projectDir) || !await fileExists(projectMdPath)) {
|
|
29509
29542
|
throw new AssignmentTargetError(
|
|
29510
29543
|
`Project "${opts.project}" not found at ${projectDir}.`
|
|
29511
29544
|
);
|
|
29512
29545
|
}
|
|
29513
|
-
const assignmentDir =
|
|
29514
|
-
const assignmentMdPath2 =
|
|
29546
|
+
const assignmentDir = resolve52(projectDir, "assignments", input4);
|
|
29547
|
+
const assignmentMdPath2 = resolve52(assignmentDir, "assignment.md");
|
|
29515
29548
|
if (!await fileExists(assignmentMdPath2)) {
|
|
29516
29549
|
throw new AssignmentTargetError(
|
|
29517
29550
|
`Assignment "${input4}" not found in project "${opts.project}".`
|
|
@@ -29550,7 +29583,7 @@ async function resolveAssignmentTarget(input4, opts = {}) {
|
|
|
29550
29583
|
}
|
|
29551
29584
|
if (ctx.assignmentDir) {
|
|
29552
29585
|
const dir = expandHome(ctx.assignmentDir);
|
|
29553
|
-
const assignmentMdPath2 =
|
|
29586
|
+
const assignmentMdPath2 = resolve52(dir, "assignment.md");
|
|
29554
29587
|
if (!await fileExists(assignmentMdPath2)) {
|
|
29555
29588
|
throw new AssignmentTargetError(
|
|
29556
29589
|
`.syntaur/context.json points to a missing assignment dir: ${dir}.`
|
|
@@ -29579,8 +29612,8 @@ async function resolveAssignmentTarget(input4, opts = {}) {
|
|
|
29579
29612
|
`.syntaur/context.json contains invalid slugs: project="${ctx.projectSlug}" assignment="${ctx.assignmentSlug}".`
|
|
29580
29613
|
);
|
|
29581
29614
|
}
|
|
29582
|
-
const assignmentDir =
|
|
29583
|
-
const assignmentMdPath2 =
|
|
29615
|
+
const assignmentDir = resolve52(baseDir, ctx.projectSlug, "assignments", ctx.assignmentSlug);
|
|
29616
|
+
const assignmentMdPath2 = resolve52(assignmentDir, "assignment.md");
|
|
29584
29617
|
if (!await fileExists(assignmentMdPath2)) {
|
|
29585
29618
|
throw new AssignmentTargetError(
|
|
29586
29619
|
`.syntaur/context.json points to a missing assignment: ${assignmentDir}.`
|
|
@@ -29608,9 +29641,9 @@ async function resolveTarget(assignment, options) {
|
|
|
29608
29641
|
if (options.project) {
|
|
29609
29642
|
if (!isValidSlug(options.project)) throw new Error(`Invalid project slug "${options.project}".`);
|
|
29610
29643
|
if (!isValidSlug(assignment)) throw new Error(`Invalid assignment slug "${assignment}".`);
|
|
29611
|
-
const projectDir =
|
|
29612
|
-
const assignmentDir =
|
|
29613
|
-
const assignmentPath =
|
|
29644
|
+
const projectDir = resolve53(baseDir, options.project);
|
|
29645
|
+
const assignmentDir = resolve53(projectDir, "assignments", assignment);
|
|
29646
|
+
const assignmentPath = resolve53(assignmentDir, "assignment.md");
|
|
29614
29647
|
if (!await fileExists(assignmentPath)) {
|
|
29615
29648
|
throw new Error(`Assignment "${assignment}" not found at ${assignmentPath}.`);
|
|
29616
29649
|
}
|
|
@@ -29622,14 +29655,14 @@ async function resolveTarget(assignment, options) {
|
|
|
29622
29655
|
}
|
|
29623
29656
|
return {
|
|
29624
29657
|
assignmentDir: resolved.assignmentDir,
|
|
29625
|
-
assignmentPath:
|
|
29626
|
-
projectDir: resolved.standalone ? null :
|
|
29658
|
+
assignmentPath: resolve53(resolved.assignmentDir, "assignment.md"),
|
|
29659
|
+
projectDir: resolved.standalone ? null : resolve53(resolved.assignmentDir, "..", "..")
|
|
29627
29660
|
};
|
|
29628
29661
|
}
|
|
29629
29662
|
async function inferActor(options) {
|
|
29630
29663
|
if (options.agent) return `agent:${options.agent}`;
|
|
29631
29664
|
try {
|
|
29632
|
-
const raw2 = await readFile34(
|
|
29665
|
+
const raw2 = await readFile34(resolve53(process.cwd(), ".syntaur", "context.json"), "utf-8");
|
|
29633
29666
|
const ctx = JSON.parse(raw2);
|
|
29634
29667
|
if (ctx.sessionId) return `agent:${ctx.sessionId.slice(0, 8)}`;
|
|
29635
29668
|
} catch {
|
|
@@ -29699,7 +29732,7 @@ async function planApproveCommand(assignment, options) {
|
|
|
29699
29732
|
throw new Error("No plan file found (plan.md / plan-v*.md). Write a plan before approving.");
|
|
29700
29733
|
}
|
|
29701
29734
|
approvedFile = planFile;
|
|
29702
|
-
const planContent = await readFile34(
|
|
29735
|
+
const planContent = await readFile34(resolve53(target2.assignmentDir, planFile), "utf-8");
|
|
29703
29736
|
return updatePlanApproval(content, {
|
|
29704
29737
|
file: planFile,
|
|
29705
29738
|
digest: planDigest(planContent),
|
|
@@ -29772,7 +29805,7 @@ async function attestCommand(assignment, fact, options) {
|
|
|
29772
29805
|
"No plan file found (plan.md / plan-v*.md). Write a plan before attesting a binds:plan fact."
|
|
29773
29806
|
);
|
|
29774
29807
|
}
|
|
29775
|
-
const planContent = await readFile34(
|
|
29808
|
+
const planContent = await readFile34(resolve53(target2.assignmentDir, planFile), "utf-8");
|
|
29776
29809
|
record.file = planFile;
|
|
29777
29810
|
record.digest = planDigest(planContent);
|
|
29778
29811
|
} else if (binds === "commit") {
|
|
@@ -29914,8 +29947,8 @@ async function recomputeCommand(assignment, options) {
|
|
|
29914
29947
|
project: options.project,
|
|
29915
29948
|
dir: options.dir
|
|
29916
29949
|
});
|
|
29917
|
-
const projectDir = resolved.standalone ? null :
|
|
29918
|
-
const result = await recomputeAndWrite(
|
|
29950
|
+
const projectDir = resolved.standalone ? null : resolve53(resolved.assignmentDir, "..", "..");
|
|
29951
|
+
const result = await recomputeAndWrite(resolve53(resolved.assignmentDir, "assignment.md"), {
|
|
29919
29952
|
cause: "recompute",
|
|
29920
29953
|
by: await inferActor(options),
|
|
29921
29954
|
projectDir,
|
|
@@ -29938,7 +29971,7 @@ init_frontmatter();
|
|
|
29938
29971
|
init_timestamp();
|
|
29939
29972
|
init_assignment_resolver();
|
|
29940
29973
|
init_event_emit();
|
|
29941
|
-
import { resolve as
|
|
29974
|
+
import { resolve as resolve54 } from "path";
|
|
29942
29975
|
import { readFile as readFile35, writeFile as writeFile9 } from "fs/promises";
|
|
29943
29976
|
async function resolveTarget2(target, options) {
|
|
29944
29977
|
const config = await readConfig();
|
|
@@ -29950,7 +29983,7 @@ async function resolveTarget2(target, options) {
|
|
|
29950
29983
|
if (!isValidSlug(target)) {
|
|
29951
29984
|
throw new Error(`Invalid assignment slug "${target}".`);
|
|
29952
29985
|
}
|
|
29953
|
-
const assignmentMd =
|
|
29986
|
+
const assignmentMd = resolve54(baseDir, options.project, "assignments", target, "assignment.md");
|
|
29954
29987
|
if (!await fileExists(assignmentMd)) {
|
|
29955
29988
|
throw new Error(`Assignment "${target}" not found in project "${options.project}".`);
|
|
29956
29989
|
}
|
|
@@ -29960,11 +29993,11 @@ async function resolveTarget2(target, options) {
|
|
|
29960
29993
|
if (resolved) {
|
|
29961
29994
|
return {
|
|
29962
29995
|
kind: "assignment",
|
|
29963
|
-
filePath:
|
|
29996
|
+
filePath: resolve54(resolved.assignmentDir, "assignment.md"),
|
|
29964
29997
|
label: resolved.projectSlug ? `assignment "${resolved.projectSlug}/${resolved.assignmentSlug}"` : `assignment "${target}"`
|
|
29965
29998
|
};
|
|
29966
29999
|
}
|
|
29967
|
-
const projectMd =
|
|
30000
|
+
const projectMd = resolve54(baseDir, target, "project.md");
|
|
29968
30001
|
if (await fileExists(projectMd)) {
|
|
29969
30002
|
return { kind: "project", filePath: projectMd, label: `project "${target}"` };
|
|
29970
30003
|
}
|
|
@@ -30053,7 +30086,7 @@ init_config2();
|
|
|
30053
30086
|
init_frontmatter();
|
|
30054
30087
|
init_timestamp();
|
|
30055
30088
|
init_event_emit();
|
|
30056
|
-
import { resolve as
|
|
30089
|
+
import { resolve as resolve55 } from "path";
|
|
30057
30090
|
import { readdir as readdir20, readFile as readFile36 } from "fs/promises";
|
|
30058
30091
|
var PROMOTABLE_STATUSES = /* @__PURE__ */ new Set(["pending"]);
|
|
30059
30092
|
function objectiveIsFleshedOut(content) {
|
|
@@ -30076,7 +30109,7 @@ async function collectCandidates(baseDirs) {
|
|
|
30076
30109
|
for (const m of projects) {
|
|
30077
30110
|
if (!m.isDirectory()) continue;
|
|
30078
30111
|
if (m.name.startsWith(".") || m.name.startsWith("_")) continue;
|
|
30079
|
-
const directAssignmentMd =
|
|
30112
|
+
const directAssignmentMd = resolve55(baseDir, m.name, "assignment.md");
|
|
30080
30113
|
if (await fileExists(directAssignmentMd)) {
|
|
30081
30114
|
const fm = await parseSafe(directAssignmentMd);
|
|
30082
30115
|
if (fm && PROMOTABLE_STATUSES.has(fm.status)) {
|
|
@@ -30093,13 +30126,13 @@ async function collectCandidates(baseDirs) {
|
|
|
30093
30126
|
}
|
|
30094
30127
|
continue;
|
|
30095
30128
|
}
|
|
30096
|
-
const assignmentsDir2 =
|
|
30129
|
+
const assignmentsDir2 = resolve55(baseDir, m.name, "assignments");
|
|
30097
30130
|
if (!await fileExists(assignmentsDir2)) continue;
|
|
30098
30131
|
const entries = await readdir20(assignmentsDir2, { withFileTypes: true });
|
|
30099
30132
|
for (const a of entries) {
|
|
30100
30133
|
if (!a.isDirectory()) continue;
|
|
30101
30134
|
if (a.name.startsWith(".") || a.name.startsWith("_")) continue;
|
|
30102
|
-
const assignmentMd =
|
|
30135
|
+
const assignmentMd = resolve55(assignmentsDir2, a.name, "assignment.md");
|
|
30103
30136
|
if (!await fileExists(assignmentMd)) continue;
|
|
30104
30137
|
const fm = await parseSafe(assignmentMd);
|
|
30105
30138
|
if (!fm || !PROMOTABLE_STATUSES.has(fm.status)) continue;
|
|
@@ -30172,7 +30205,7 @@ init_config2();
|
|
|
30172
30205
|
init_frontmatter();
|
|
30173
30206
|
init_event_emit();
|
|
30174
30207
|
init_types();
|
|
30175
|
-
import { resolve as
|
|
30208
|
+
import { resolve as resolve56 } from "path";
|
|
30176
30209
|
import { readdir as readdir21, readFile as readFile37 } from "fs/promises";
|
|
30177
30210
|
async function parseSafe2(path) {
|
|
30178
30211
|
try {
|
|
@@ -30203,7 +30236,7 @@ async function collectTargets(baseDirs, terminalStatuses3) {
|
|
|
30203
30236
|
for (const m of entries) {
|
|
30204
30237
|
if (!m.isDirectory()) continue;
|
|
30205
30238
|
if (m.name.startsWith(".") || m.name.startsWith("_")) continue;
|
|
30206
|
-
const directAssignmentMd =
|
|
30239
|
+
const directAssignmentMd = resolve56(baseDir, m.name, "assignment.md");
|
|
30207
30240
|
if (await fileExists(directAssignmentMd)) {
|
|
30208
30241
|
if (seen.has(directAssignmentMd)) continue;
|
|
30209
30242
|
const fm = await parseSafe2(directAssignmentMd);
|
|
@@ -30218,13 +30251,13 @@ async function collectTargets(baseDirs, terminalStatuses3) {
|
|
|
30218
30251
|
}
|
|
30219
30252
|
continue;
|
|
30220
30253
|
}
|
|
30221
|
-
const assignmentsBase =
|
|
30254
|
+
const assignmentsBase = resolve56(baseDir, m.name, "assignments");
|
|
30222
30255
|
if (!await fileExists(assignmentsBase)) continue;
|
|
30223
30256
|
const slugs = await readdir21(assignmentsBase, { withFileTypes: true });
|
|
30224
30257
|
for (const a of slugs) {
|
|
30225
30258
|
if (!a.isDirectory()) continue;
|
|
30226
30259
|
if (a.name.startsWith(".") || a.name.startsWith("_")) continue;
|
|
30227
|
-
const assignmentMd =
|
|
30260
|
+
const assignmentMd = resolve56(assignmentsBase, a.name, "assignment.md");
|
|
30228
30261
|
if (!await fileExists(assignmentMd)) continue;
|
|
30229
30262
|
if (seen.has(assignmentMd)) continue;
|
|
30230
30263
|
const fm = await parseSafe2(assignmentMd);
|
|
@@ -30296,7 +30329,7 @@ init_fs();
|
|
|
30296
30329
|
init_config2();
|
|
30297
30330
|
init_parser();
|
|
30298
30331
|
init_events_db();
|
|
30299
|
-
import { resolve as
|
|
30332
|
+
import { resolve as resolve57 } from "path";
|
|
30300
30333
|
import { readdir as readdir22, readFile as readFile38 } from "fs/promises";
|
|
30301
30334
|
async function parseSafe3(path) {
|
|
30302
30335
|
try {
|
|
@@ -30337,7 +30370,7 @@ async function collectTargets2(baseDirs) {
|
|
|
30337
30370
|
for (const m of entries) {
|
|
30338
30371
|
if (!m.isDirectory()) continue;
|
|
30339
30372
|
if (m.name.startsWith(".") || m.name.startsWith("_")) continue;
|
|
30340
|
-
const directAssignmentMd =
|
|
30373
|
+
const directAssignmentMd = resolve57(baseDir, m.name, "assignment.md");
|
|
30341
30374
|
if (await fileExists(directAssignmentMd)) {
|
|
30342
30375
|
if (seen.has(directAssignmentMd)) continue;
|
|
30343
30376
|
seen.add(directAssignmentMd);
|
|
@@ -30355,13 +30388,13 @@ async function collectTargets2(baseDirs) {
|
|
|
30355
30388
|
}
|
|
30356
30389
|
continue;
|
|
30357
30390
|
}
|
|
30358
|
-
const assignmentsBase =
|
|
30391
|
+
const assignmentsBase = resolve57(baseDir, m.name, "assignments");
|
|
30359
30392
|
if (!await fileExists(assignmentsBase)) continue;
|
|
30360
30393
|
const slugs = await readdir22(assignmentsBase, { withFileTypes: true });
|
|
30361
30394
|
for (const a of slugs) {
|
|
30362
30395
|
if (!a.isDirectory()) continue;
|
|
30363
30396
|
if (a.name.startsWith(".") || a.name.startsWith("_")) continue;
|
|
30364
|
-
const assignmentMd =
|
|
30397
|
+
const assignmentMd = resolve57(assignmentsBase, a.name, "assignment.md");
|
|
30365
30398
|
if (!await fileExists(assignmentMd)) continue;
|
|
30366
30399
|
if (seen.has(assignmentMd)) continue;
|
|
30367
30400
|
seen.add(assignmentMd);
|
|
@@ -30443,7 +30476,7 @@ init_facts();
|
|
|
30443
30476
|
init_derive();
|
|
30444
30477
|
init_recompute();
|
|
30445
30478
|
import { readdir as readdir23, readFile as readFile39 } from "fs/promises";
|
|
30446
|
-
import { resolve as
|
|
30479
|
+
import { resolve as resolve58 } from "path";
|
|
30447
30480
|
var IMPLEMENTATION_STATUSES = /* @__PURE__ */ new Set(["in_progress", "review", "code_review"]);
|
|
30448
30481
|
var REVIEW_STATUSES = /* @__PURE__ */ new Set(["review", "code_review"]);
|
|
30449
30482
|
async function listTargets(projectsDir2, standaloneDir) {
|
|
@@ -30454,15 +30487,15 @@ async function listTargets(projectsDir2, standaloneDir) {
|
|
|
30454
30487
|
} catch {
|
|
30455
30488
|
}
|
|
30456
30489
|
for (const project of projects) {
|
|
30457
|
-
const projectDir =
|
|
30490
|
+
const projectDir = resolve58(projectsDir2, project);
|
|
30458
30491
|
let slugs = [];
|
|
30459
30492
|
try {
|
|
30460
|
-
slugs = await readdir23(
|
|
30493
|
+
slugs = await readdir23(resolve58(projectDir, "assignments"));
|
|
30461
30494
|
} catch {
|
|
30462
30495
|
continue;
|
|
30463
30496
|
}
|
|
30464
30497
|
for (const slug of slugs) {
|
|
30465
|
-
const path =
|
|
30498
|
+
const path = resolve58(projectDir, "assignments", slug, "assignment.md");
|
|
30466
30499
|
if (await fileExists(path)) targets.push({ path, projectDir, ref: `${project}/${slug}` });
|
|
30467
30500
|
}
|
|
30468
30501
|
}
|
|
@@ -30472,7 +30505,7 @@ async function listTargets(projectsDir2, standaloneDir) {
|
|
|
30472
30505
|
} catch {
|
|
30473
30506
|
}
|
|
30474
30507
|
for (const id of ids) {
|
|
30475
|
-
const path =
|
|
30508
|
+
const path = resolve58(standaloneDir, id, "assignment.md");
|
|
30476
30509
|
if (await fileExists(path)) targets.push({ path, projectDir: null, ref: id });
|
|
30477
30510
|
}
|
|
30478
30511
|
return targets;
|
|
@@ -30542,7 +30575,7 @@ async function migrateDeriveCommand(options) {
|
|
|
30542
30575
|
const seededFm = parseAssignmentFrontmatter(seededContent);
|
|
30543
30576
|
const body = seededContent.replace(/^---\n[\s\S]*?\n---/, "");
|
|
30544
30577
|
const facts = await computeFacts({
|
|
30545
|
-
assignmentDir:
|
|
30578
|
+
assignmentDir: resolve58(target.path, ".."),
|
|
30546
30579
|
frontmatter: seededFm,
|
|
30547
30580
|
body,
|
|
30548
30581
|
projectDir: target.projectDir,
|
|
@@ -30602,7 +30635,7 @@ async function migrateDeriveCommand(options) {
|
|
|
30602
30635
|
}
|
|
30603
30636
|
|
|
30604
30637
|
// src/commands/complete.ts
|
|
30605
|
-
import { resolve as
|
|
30638
|
+
import { resolve as resolve59 } from "path";
|
|
30606
30639
|
init_config2();
|
|
30607
30640
|
init_paths();
|
|
30608
30641
|
init_assignment_resolver();
|
|
@@ -30616,12 +30649,12 @@ async function completeCommand(assignment, options) {
|
|
|
30616
30649
|
let projectDir;
|
|
30617
30650
|
let changedSlug;
|
|
30618
30651
|
if (options.project) {
|
|
30619
|
-
projectDir =
|
|
30652
|
+
projectDir = resolve59(baseDir, options.project);
|
|
30620
30653
|
changedSlug = assignment;
|
|
30621
30654
|
} else {
|
|
30622
30655
|
const resolved = await resolveAssignmentById(baseDir, assignmentsDir(), assignment);
|
|
30623
30656
|
if (!resolved) return;
|
|
30624
|
-
projectDir = resolved.standalone ? null :
|
|
30657
|
+
projectDir = resolved.standalone ? null : resolve59(resolved.assignmentDir, "..", "..");
|
|
30625
30658
|
changedSlug = resolved.assignmentSlug;
|
|
30626
30659
|
}
|
|
30627
30660
|
if (projectDir) {
|
|
@@ -30652,7 +30685,7 @@ async function reviewCommand(assignment, options) {
|
|
|
30652
30685
|
}
|
|
30653
30686
|
|
|
30654
30687
|
// src/commands/fail.ts
|
|
30655
|
-
import { resolve as
|
|
30688
|
+
import { resolve as resolve60 } from "path";
|
|
30656
30689
|
init_config2();
|
|
30657
30690
|
init_paths();
|
|
30658
30691
|
init_assignment_resolver();
|
|
@@ -30666,12 +30699,12 @@ async function failCommand(assignment, options) {
|
|
|
30666
30699
|
let projectDir;
|
|
30667
30700
|
let changedSlug;
|
|
30668
30701
|
if (options.project) {
|
|
30669
|
-
projectDir =
|
|
30702
|
+
projectDir = resolve60(baseDir, options.project);
|
|
30670
30703
|
changedSlug = assignment;
|
|
30671
30704
|
} else {
|
|
30672
30705
|
const resolved = await resolveAssignmentById(baseDir, assignmentsDir(), assignment);
|
|
30673
30706
|
if (!resolved) return;
|
|
30674
|
-
projectDir = resolved.standalone ? null :
|
|
30707
|
+
projectDir = resolved.standalone ? null : resolve60(resolved.assignmentDir, "..", "..");
|
|
30675
30708
|
changedSlug = resolved.assignmentSlug;
|
|
30676
30709
|
}
|
|
30677
30710
|
if (projectDir) {
|
|
@@ -30687,7 +30720,7 @@ async function failCommand(assignment, options) {
|
|
|
30687
30720
|
}
|
|
30688
30721
|
|
|
30689
30722
|
// src/commands/reopen.ts
|
|
30690
|
-
import { resolve as
|
|
30723
|
+
import { resolve as resolve61 } from "path";
|
|
30691
30724
|
init_config2();
|
|
30692
30725
|
init_paths();
|
|
30693
30726
|
init_assignment_resolver();
|
|
@@ -30703,14 +30736,14 @@ async function reopenCommand(assignment, options) {
|
|
|
30703
30736
|
let projectDir;
|
|
30704
30737
|
let changedSlug;
|
|
30705
30738
|
if (options.project) {
|
|
30706
|
-
projectDir =
|
|
30707
|
-
assignmentPath =
|
|
30739
|
+
projectDir = resolve61(baseDir, options.project);
|
|
30740
|
+
assignmentPath = resolve61(projectDir, "assignments", assignment, "assignment.md");
|
|
30708
30741
|
changedSlug = assignment;
|
|
30709
30742
|
} else {
|
|
30710
30743
|
const resolved = await resolveAssignmentById(baseDir, assignmentsDir(), assignment);
|
|
30711
30744
|
if (!resolved) return;
|
|
30712
|
-
assignmentPath =
|
|
30713
|
-
projectDir = resolved.standalone ? null :
|
|
30745
|
+
assignmentPath = resolve61(resolved.assignmentDir, "assignment.md");
|
|
30746
|
+
projectDir = resolved.standalone ? null : resolve61(resolved.assignmentDir, "..", "..");
|
|
30714
30747
|
changedSlug = resolved.assignmentSlug;
|
|
30715
30748
|
}
|
|
30716
30749
|
const derived = await recomputeAndWrite(assignmentPath, {
|
|
@@ -30753,20 +30786,20 @@ import {
|
|
|
30753
30786
|
} from "fs/promises";
|
|
30754
30787
|
import { existsSync as existsSync4 } from "fs";
|
|
30755
30788
|
import { homedir as homedir8 } from "os";
|
|
30756
|
-
import { basename as basename8, dirname as dirname15, isAbsolute as isAbsolute7, relative as relative2, resolve as
|
|
30789
|
+
import { basename as basename8, dirname as dirname15, isAbsolute as isAbsolute7, relative as relative2, resolve as resolve63 } from "path";
|
|
30757
30790
|
|
|
30758
30791
|
// src/utils/package-root.ts
|
|
30759
30792
|
init_fs();
|
|
30760
|
-
import { dirname as dirname14, resolve as
|
|
30793
|
+
import { dirname as dirname14, resolve as resolve62 } from "path";
|
|
30761
30794
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
30762
30795
|
async function findPackageRoot(expectedRelativePath) {
|
|
30763
30796
|
let currentDir = dirname14(fileURLToPath4(import.meta.url));
|
|
30764
30797
|
while (true) {
|
|
30765
|
-
const candidate =
|
|
30798
|
+
const candidate = resolve62(currentDir, expectedRelativePath);
|
|
30766
30799
|
if (await fileExists(candidate)) {
|
|
30767
30800
|
return currentDir;
|
|
30768
30801
|
}
|
|
30769
|
-
const parentDir =
|
|
30802
|
+
const parentDir = resolve62(currentDir, "..");
|
|
30770
30803
|
if (parentDir === currentDir) {
|
|
30771
30804
|
throw new Error(
|
|
30772
30805
|
`Could not locate package root containing ${expectedRelativePath}.`
|
|
@@ -30787,25 +30820,25 @@ function getPluginManifestRelativePath(pluginKind) {
|
|
|
30787
30820
|
}
|
|
30788
30821
|
function getDefaultPluginTargetDir(pluginKind) {
|
|
30789
30822
|
const home2 = homedir8();
|
|
30790
|
-
return pluginKind === "claude" ?
|
|
30823
|
+
return pluginKind === "claude" ? resolve63(home2, ".claude", "plugins", "syntaur") : resolve63(home2, "plugins", "syntaur");
|
|
30791
30824
|
}
|
|
30792
30825
|
function getDefaultMarketplacePath() {
|
|
30793
|
-
return
|
|
30826
|
+
return resolve63(homedir8(), ".agents", "plugins", "marketplace.json");
|
|
30794
30827
|
}
|
|
30795
30828
|
function getClaudeMarketplacesRoot() {
|
|
30796
|
-
return
|
|
30829
|
+
return resolve63(homedir8(), ".claude", "plugins", "marketplaces");
|
|
30797
30830
|
}
|
|
30798
30831
|
function getClaudeKnownMarketplacesPath() {
|
|
30799
|
-
return
|
|
30832
|
+
return resolve63(homedir8(), ".claude", "plugins", "known_marketplaces.json");
|
|
30800
30833
|
}
|
|
30801
30834
|
function getClaudeInstalledPluginsPath() {
|
|
30802
|
-
return
|
|
30835
|
+
return resolve63(homedir8(), ".claude", "plugins", "installed_plugins.json");
|
|
30803
30836
|
}
|
|
30804
30837
|
function getInstallMarkerPath(targetDir) {
|
|
30805
|
-
return
|
|
30838
|
+
return resolve63(targetDir, INSTALL_MARKER_FILENAME);
|
|
30806
30839
|
}
|
|
30807
30840
|
async function readPackageManifest(packageRoot) {
|
|
30808
|
-
const raw2 = await readFile40(
|
|
30841
|
+
const raw2 = await readFile40(resolve63(packageRoot, "package.json"), "utf-8");
|
|
30809
30842
|
return JSON.parse(raw2);
|
|
30810
30843
|
}
|
|
30811
30844
|
async function readJsonFileIfExists(pathValue) {
|
|
@@ -30821,11 +30854,11 @@ async function readJsonFileIfExists(pathValue) {
|
|
|
30821
30854
|
}
|
|
30822
30855
|
async function readClaudePluginManifest(pluginDir) {
|
|
30823
30856
|
return await readJsonFileIfExists(
|
|
30824
|
-
|
|
30857
|
+
resolve63(pluginDir, ".claude-plugin", "plugin.json")
|
|
30825
30858
|
) ?? {};
|
|
30826
30859
|
}
|
|
30827
30860
|
async function readPluginManifestName(targetDir, pluginKind) {
|
|
30828
|
-
const manifestPath =
|
|
30861
|
+
const manifestPath = resolve63(targetDir, getPluginManifestRelativePath(pluginKind));
|
|
30829
30862
|
if (!await fileExists(manifestPath)) {
|
|
30830
30863
|
return void 0;
|
|
30831
30864
|
}
|
|
@@ -30852,7 +30885,7 @@ async function getInstallStatus(targetDir, pluginKind) {
|
|
|
30852
30885
|
const info = await lstat(targetDir);
|
|
30853
30886
|
if (info.isSymbolicLink()) {
|
|
30854
30887
|
const symlinkTarget = await readlink(targetDir);
|
|
30855
|
-
const resolvedTarget =
|
|
30888
|
+
const resolvedTarget = resolve63(dirname15(targetDir), symlinkTarget);
|
|
30856
30889
|
const manifestName2 = await readPluginManifestName(resolvedTarget, pluginKind);
|
|
30857
30890
|
return {
|
|
30858
30891
|
exists: true,
|
|
@@ -30898,7 +30931,7 @@ async function installLink(paths) {
|
|
|
30898
30931
|
await ensureDir(dirname15(paths.targetDir));
|
|
30899
30932
|
await rm6(paths.targetDir, { recursive: true, force: true });
|
|
30900
30933
|
await ensureDir(dirname15(paths.targetDir));
|
|
30901
|
-
await symlink(
|
|
30934
|
+
await symlink(resolve63(paths.sourceDir), paths.targetDir, "dir");
|
|
30902
30935
|
}
|
|
30903
30936
|
async function removeInstallMarker(targetDir) {
|
|
30904
30937
|
const markerPath = getInstallMarkerPath(targetDir);
|
|
@@ -30912,13 +30945,13 @@ function normalizeAbsoluteInstallPath(pathValue, label) {
|
|
|
30912
30945
|
if (!isAbsolute7(expanded)) {
|
|
30913
30946
|
throw new Error(`${label} must be an absolute path.`);
|
|
30914
30947
|
}
|
|
30915
|
-
return
|
|
30948
|
+
return resolve63(expanded);
|
|
30916
30949
|
}
|
|
30917
30950
|
async function resolvePluginPaths(pluginKind, targetDir) {
|
|
30918
30951
|
const packageRoot = await findPackageRoot(getPluginRelativePath(pluginKind));
|
|
30919
30952
|
return {
|
|
30920
30953
|
packageRoot,
|
|
30921
|
-
sourceDir:
|
|
30954
|
+
sourceDir: resolve63(packageRoot, getPluginRelativePath(pluginKind)),
|
|
30922
30955
|
targetDir: targetDir ?? getDefaultPluginTargetDir(pluginKind)
|
|
30923
30956
|
};
|
|
30924
30957
|
}
|
|
@@ -31043,8 +31076,8 @@ async function listClaudeMarketplaceCandidates() {
|
|
|
31043
31076
|
if (!entry.isDirectory()) {
|
|
31044
31077
|
continue;
|
|
31045
31078
|
}
|
|
31046
|
-
const candidateRoot =
|
|
31047
|
-
const manifestPath =
|
|
31079
|
+
const candidateRoot = resolve63(rootDir, entry.name);
|
|
31080
|
+
const manifestPath = resolve63(candidateRoot, ".claude-plugin", "marketplace.json");
|
|
31048
31081
|
if (!await fileExists(manifestPath)) {
|
|
31049
31082
|
continue;
|
|
31050
31083
|
}
|
|
@@ -31071,11 +31104,11 @@ async function listClaudeMarketplaceCandidates() {
|
|
|
31071
31104
|
if (!installLocation) {
|
|
31072
31105
|
continue;
|
|
31073
31106
|
}
|
|
31074
|
-
const candidateRoot =
|
|
31107
|
+
const candidateRoot = resolve63(expandHome(installLocation));
|
|
31075
31108
|
if (seen.has(candidateRoot)) {
|
|
31076
31109
|
continue;
|
|
31077
31110
|
}
|
|
31078
|
-
const manifestPath =
|
|
31111
|
+
const manifestPath = resolve63(candidateRoot, ".claude-plugin", "marketplace.json");
|
|
31079
31112
|
if (!await fileExists(manifestPath)) {
|
|
31080
31113
|
continue;
|
|
31081
31114
|
}
|
|
@@ -31103,7 +31136,7 @@ async function getPreferredClaudeMarketplace() {
|
|
|
31103
31136
|
name: candidate.name,
|
|
31104
31137
|
rootDir: candidate.rootDir,
|
|
31105
31138
|
manifestPath: candidate.manifestPath,
|
|
31106
|
-
targetDir:
|
|
31139
|
+
targetDir: resolve63(candidate.rootDir, "plugins", "syntaur")
|
|
31107
31140
|
};
|
|
31108
31141
|
}
|
|
31109
31142
|
async function registerKnownClaudeMarketplace(name, rootDir) {
|
|
@@ -31151,7 +31184,7 @@ async function ensureKnownClaudeMarketplaceForRoot(options) {
|
|
|
31151
31184
|
return registerKnownClaudeMarketplace(options.name, options.rootDir);
|
|
31152
31185
|
}
|
|
31153
31186
|
async function setSyntaurPluginEnabled(options) {
|
|
31154
|
-
const settingsPath =
|
|
31187
|
+
const settingsPath = resolve63(homedir8(), ".claude", "settings.json");
|
|
31155
31188
|
const key = `syntaur@${options.marketplaceName}`;
|
|
31156
31189
|
let parsed = {};
|
|
31157
31190
|
if (await fileExists(settingsPath)) {
|
|
@@ -31188,9 +31221,9 @@ async function ensureClaudeUserMarketplace() {
|
|
|
31188
31221
|
if (existing) {
|
|
31189
31222
|
return existing;
|
|
31190
31223
|
}
|
|
31191
|
-
const rootDir =
|
|
31192
|
-
const manifestPath =
|
|
31193
|
-
await ensureDir(
|
|
31224
|
+
const rootDir = resolve63(getClaudeMarketplacesRoot(), "user-plugins");
|
|
31225
|
+
const manifestPath = resolve63(rootDir, ".claude-plugin", "marketplace.json");
|
|
31226
|
+
await ensureDir(resolve63(rootDir, "plugins"));
|
|
31194
31227
|
if (!await fileExists(manifestPath)) {
|
|
31195
31228
|
const scaffold = {
|
|
31196
31229
|
plugins: []
|
|
@@ -31209,7 +31242,7 @@ async function ensureClaudeUserMarketplace() {
|
|
|
31209
31242
|
name: "user-plugins",
|
|
31210
31243
|
rootDir,
|
|
31211
31244
|
manifestPath,
|
|
31212
|
-
targetDir:
|
|
31245
|
+
targetDir: resolve63(rootDir, "plugins", "syntaur")
|
|
31213
31246
|
};
|
|
31214
31247
|
}
|
|
31215
31248
|
async function detectClaudeMarketplaceForTarget(targetDir) {
|
|
@@ -31219,7 +31252,7 @@ async function detectClaudeMarketplaceForTarget(targetDir) {
|
|
|
31219
31252
|
return null;
|
|
31220
31253
|
}
|
|
31221
31254
|
const rootDir = dirname15(pluginsDir);
|
|
31222
|
-
const manifestPath =
|
|
31255
|
+
const manifestPath = resolve63(rootDir, ".claude-plugin", "marketplace.json");
|
|
31223
31256
|
if (!await fileExists(manifestPath)) {
|
|
31224
31257
|
return null;
|
|
31225
31258
|
}
|
|
@@ -31235,7 +31268,7 @@ async function detectClaudeMarketplaceForTarget(targetDir) {
|
|
|
31235
31268
|
async function findManagedClaudeMarketplacePluginDir() {
|
|
31236
31269
|
const marketplaces = await listClaudeMarketplaceCandidates();
|
|
31237
31270
|
for (const marketplace of marketplaces) {
|
|
31238
|
-
const targetDir =
|
|
31271
|
+
const targetDir = resolve63(marketplace.rootDir, "plugins", "syntaur");
|
|
31239
31272
|
const status = await getInstallStatus(targetDir, "claude");
|
|
31240
31273
|
if (status.exists && status.managed) {
|
|
31241
31274
|
return targetDir;
|
|
@@ -31360,7 +31393,7 @@ async function installManagedPlugin(options) {
|
|
|
31360
31393
|
`${paths.targetDir} already exists and is not a Syntaur-managed install. Remove it manually before installing Syntaur there.`
|
|
31361
31394
|
);
|
|
31362
31395
|
}
|
|
31363
|
-
if (desiredMode === "link" && existing.exists && existing.installMode === "link" && existing.symlinkTarget ===
|
|
31396
|
+
if (desiredMode === "link" && existing.exists && existing.installMode === "link" && existing.symlinkTarget === resolve63(paths.sourceDir) && !force) {
|
|
31364
31397
|
return {
|
|
31365
31398
|
targetDir: paths.targetDir,
|
|
31366
31399
|
sourceDir: paths.sourceDir,
|
|
@@ -31579,13 +31612,13 @@ async function recommendMarketplacePath() {
|
|
|
31579
31612
|
return configuredOrManaged ?? getDefaultMarketplacePath();
|
|
31580
31613
|
}
|
|
31581
31614
|
async function isSyntaurDataInstalled() {
|
|
31582
|
-
return fileExists(
|
|
31615
|
+
return fileExists(resolve63(syntaurRoot(), "config.md"));
|
|
31583
31616
|
}
|
|
31584
31617
|
async function removeSyntaurData() {
|
|
31585
31618
|
await rm6(syntaurRoot(), { recursive: true, force: true });
|
|
31586
31619
|
}
|
|
31587
31620
|
async function getConfiguredProjectDir() {
|
|
31588
|
-
if (!await fileExists(
|
|
31621
|
+
if (!await fileExists(resolve63(syntaurRoot(), "config.md"))) {
|
|
31589
31622
|
return null;
|
|
31590
31623
|
}
|
|
31591
31624
|
return (await readConfig()).defaultProjectDir;
|
|
@@ -31655,16 +31688,16 @@ async function textPrompt(question, defaultValue) {
|
|
|
31655
31688
|
// src/utils/install-skills.ts
|
|
31656
31689
|
init_fs();
|
|
31657
31690
|
import { readFile as readFile42, readdir as readdir25, mkdir as mkdir7, copyFile, rm as rm7, lstat as lstat2 } from "fs/promises";
|
|
31658
|
-
import { resolve as
|
|
31691
|
+
import { resolve as resolve65, relative as relative3, join as join11 } from "path";
|
|
31659
31692
|
import { homedir as homedir10 } from "os";
|
|
31660
31693
|
|
|
31661
31694
|
// src/utils/plugin-state.ts
|
|
31662
31695
|
init_fs();
|
|
31663
31696
|
import { readFile as readFile41 } from "fs/promises";
|
|
31664
|
-
import { resolve as
|
|
31697
|
+
import { resolve as resolve64 } from "path";
|
|
31665
31698
|
import { homedir as homedir9 } from "os";
|
|
31666
31699
|
function settingsPathFor(agent) {
|
|
31667
|
-
if (agent === "claude") return
|
|
31700
|
+
if (agent === "claude") return resolve64(homedir9(), ".claude", "settings.json");
|
|
31668
31701
|
return null;
|
|
31669
31702
|
}
|
|
31670
31703
|
async function readJsonOrNull(path) {
|
|
@@ -31721,11 +31754,11 @@ var KNOWN_SKILL_NAMES = [
|
|
|
31721
31754
|
var KNOWN_SKILLS = KNOWN_SKILL_NAMES;
|
|
31722
31755
|
async function getSkillsDir() {
|
|
31723
31756
|
const packageRoot = await findPackageRoot("skills");
|
|
31724
|
-
return
|
|
31757
|
+
return resolve65(packageRoot, "skills");
|
|
31725
31758
|
}
|
|
31726
31759
|
function defaultSkillTargetDir(target) {
|
|
31727
|
-
if (target === "claude") return
|
|
31728
|
-
return
|
|
31760
|
+
if (target === "claude") return resolve65(homedir10(), ".claude", "skills");
|
|
31761
|
+
return resolve65(homedir10(), ".codex", "skills");
|
|
31729
31762
|
}
|
|
31730
31763
|
async function walkFiles(root) {
|
|
31731
31764
|
const out = [];
|
|
@@ -32074,14 +32107,14 @@ async function installPluginCommand(options) {
|
|
|
32074
32107
|
// src/commands/update.ts
|
|
32075
32108
|
import { spawn as spawn7 } from "child_process";
|
|
32076
32109
|
import { fileURLToPath as fileURLToPath7 } from "url";
|
|
32077
|
-
import { realpathSync as
|
|
32110
|
+
import { realpathSync as realpathSync3 } from "fs";
|
|
32078
32111
|
|
|
32079
32112
|
// src/utils/npx-prompt.ts
|
|
32080
32113
|
init_paths();
|
|
32081
32114
|
init_fs();
|
|
32082
32115
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
32083
32116
|
import { readFile as readFile44 } from "fs/promises";
|
|
32084
|
-
import { dirname as dirname17, join as join13, resolve as
|
|
32117
|
+
import { dirname as dirname17, join as join13, resolve as resolve66 } from "path";
|
|
32085
32118
|
import { spawn as spawn6 } from "child_process";
|
|
32086
32119
|
import { createInterface as createInterface2 } from "readline/promises";
|
|
32087
32120
|
|
|
@@ -32102,7 +32135,7 @@ async function readPackageVersion(scriptUrl) {
|
|
|
32102
32135
|
}
|
|
32103
32136
|
|
|
32104
32137
|
// src/utils/npx-prompt.ts
|
|
32105
|
-
var STATE_FILE =
|
|
32138
|
+
var STATE_FILE = resolve66(syntaurRoot(), "npx-install.json");
|
|
32106
32139
|
var META_ARGS2 = /* @__PURE__ */ new Set(["-h", "--help", "-V", "--version", "help"]);
|
|
32107
32140
|
var GLOBAL_VERSION_TIMEOUT_MS = 2e3;
|
|
32108
32141
|
function isRunningViaNpx(scriptUrl) {
|
|
@@ -32427,7 +32460,7 @@ async function updateCommand(options, deps = {}) {
|
|
|
32427
32460
|
const log = deps.log ?? ((m) => console.log(m));
|
|
32428
32461
|
const env = deps.env ?? process.env;
|
|
32429
32462
|
const runner = deps.runner ?? defaultRunner;
|
|
32430
|
-
const realpath3 = deps.detectKindDeps?.realpath ??
|
|
32463
|
+
const realpath3 = deps.detectKindDeps?.realpath ?? realpathSync3.native;
|
|
32431
32464
|
const detectKind = deps.detectKind ?? ((u) => detectInstallKind(u, deps.detectKindDeps));
|
|
32432
32465
|
const fetchLatest = deps.fetchLatest ?? fetchLatestNpmVersion;
|
|
32433
32466
|
const getManagedDir = deps.getManagedDir ?? getConfiguredOrLegacyManagedPluginDir;
|
|
@@ -32541,7 +32574,7 @@ async function refreshPluginSkills(options, pm, runner, getManagedDir, resolveFr
|
|
|
32541
32574
|
init_paths();
|
|
32542
32575
|
init_fs();
|
|
32543
32576
|
import { readFile as readFile46, writeFile as writeFile12, copyFile as copyFile2, rm as rm8, stat as stat8, symlink as symlink2, unlink as unlink11, lstat as lstat3 } from "fs/promises";
|
|
32544
|
-
import { resolve as
|
|
32577
|
+
import { resolve as resolve68, dirname as dirname19 } from "path";
|
|
32545
32578
|
import { homedir as homedir12 } from "os";
|
|
32546
32579
|
import { fileURLToPath as fileURLToPath8 } from "url";
|
|
32547
32580
|
|
|
@@ -32549,7 +32582,7 @@ import { fileURLToPath as fileURLToPath8 } from "url";
|
|
|
32549
32582
|
init_paths();
|
|
32550
32583
|
init_fs();
|
|
32551
32584
|
import { readFile as readFile45, writeFile as writeFile11 } from "fs/promises";
|
|
32552
|
-
import { resolve as
|
|
32585
|
+
import { resolve as resolve67, dirname as dirname18 } from "path";
|
|
32553
32586
|
import { spawnSync as spawnSync5 } from "child_process";
|
|
32554
32587
|
import { checkbox, input as input2, confirm } from "@inquirer/prompts";
|
|
32555
32588
|
var AVAILABLE_SEGMENTS = [
|
|
@@ -32570,7 +32603,7 @@ var PRESETS = {
|
|
|
32570
32603
|
tracker: { segments: ["git", "assignment", "external", "session"], separator: " \xB7 " }
|
|
32571
32604
|
};
|
|
32572
32605
|
function getConfigPath(installRoot) {
|
|
32573
|
-
return
|
|
32606
|
+
return resolve67(installRoot, "statusline.config.json");
|
|
32574
32607
|
}
|
|
32575
32608
|
async function readConfig2(path) {
|
|
32576
32609
|
if (!await fileExists(path)) return null;
|
|
@@ -32728,7 +32761,7 @@ async function configureStatuslineCommand(options = {}) {
|
|
|
32728
32761
|
console.log(` segments: ${config.segments.join(", ")}`);
|
|
32729
32762
|
console.log(` separator: ${JSON.stringify(config.separator)}`);
|
|
32730
32763
|
if (config.wrap) console.log(` wrap: ${config.wrap}`);
|
|
32731
|
-
const script = options.statuslineScript ??
|
|
32764
|
+
const script = options.statuslineScript ?? resolve67(installRoot, "statusline.sh");
|
|
32732
32765
|
if (await fileExists(script)) {
|
|
32733
32766
|
console.log("");
|
|
32734
32767
|
console.log("Live preview:");
|
|
@@ -32759,7 +32792,7 @@ async function writeDefaultConfigIfMissing(installRoot) {
|
|
|
32759
32792
|
// src/commands/install-statusline.ts
|
|
32760
32793
|
function getPackageStatuslineSource() {
|
|
32761
32794
|
const here = dirname19(fileURLToPath8(import.meta.url));
|
|
32762
|
-
return
|
|
32795
|
+
return resolve68(here, "..", "statusline", "statusline.sh");
|
|
32763
32796
|
}
|
|
32764
32797
|
async function readSettingsJson(settingsPath) {
|
|
32765
32798
|
if (!await fileExists(settingsPath)) return {};
|
|
@@ -32843,12 +32876,12 @@ async function installScript(sourceScript, destScript, link) {
|
|
|
32843
32876
|
}
|
|
32844
32877
|
async function installStatuslineCommand(options = {}) {
|
|
32845
32878
|
const mode = options.mode ?? "ask";
|
|
32846
|
-
const settingsPath = options.settingsPath ??
|
|
32879
|
+
const settingsPath = options.settingsPath ?? resolve68(homedir12(), ".claude", "settings.json");
|
|
32847
32880
|
const installRoot = options.installRoot ?? syntaurRoot();
|
|
32848
32881
|
const sourceScript = options.sourceScript ?? getPackageStatuslineSource();
|
|
32849
|
-
const destScript =
|
|
32850
|
-
const confPath =
|
|
32851
|
-
const backupPath =
|
|
32882
|
+
const destScript = resolve68(installRoot, "statusline.sh");
|
|
32883
|
+
const confPath = resolve68(installRoot, "statusline.conf");
|
|
32884
|
+
const backupPath = resolve68(installRoot, "statusline.backup.json");
|
|
32852
32885
|
if (!await fileExists(sourceScript)) {
|
|
32853
32886
|
throw new Error(
|
|
32854
32887
|
`Statusline source script not found at ${sourceScript}. Try re-installing syntaur (npm install -g syntaur) or pass --source-script explicitly.`
|
|
@@ -32884,7 +32917,7 @@ async function installStatuslineCommand(options = {}) {
|
|
|
32884
32917
|
if (parsed) {
|
|
32885
32918
|
wrapTarget = parsed;
|
|
32886
32919
|
} else {
|
|
32887
|
-
const wrapperPath =
|
|
32920
|
+
const wrapperPath = resolve68(installRoot, "statusline-wrapped.sh");
|
|
32888
32921
|
const wrapperBody = `#!/usr/bin/env bash
|
|
32889
32922
|
# Auto-generated by syntaur install-statusline.
|
|
32890
32923
|
# Executes the previously configured statusLine command.
|
|
@@ -32939,12 +32972,12 @@ async function chmodExec(path) {
|
|
|
32939
32972
|
}
|
|
32940
32973
|
}
|
|
32941
32974
|
async function uninstallStatuslineCommand(options = {}) {
|
|
32942
|
-
const settingsPath = options.settingsPath ??
|
|
32975
|
+
const settingsPath = options.settingsPath ?? resolve68(homedir12(), ".claude", "settings.json");
|
|
32943
32976
|
const installRoot = options.installRoot ?? syntaurRoot();
|
|
32944
|
-
const destScript =
|
|
32945
|
-
const confPath =
|
|
32946
|
-
const backupPath =
|
|
32947
|
-
const wrapperPath =
|
|
32977
|
+
const destScript = resolve68(installRoot, "statusline.sh");
|
|
32978
|
+
const confPath = resolve68(installRoot, "statusline.conf");
|
|
32979
|
+
const backupPath = resolve68(installRoot, "statusline.backup.json");
|
|
32980
|
+
const wrapperPath = resolve68(installRoot, "statusline-wrapped.sh");
|
|
32948
32981
|
const settings = await readSettingsJson(settingsPath);
|
|
32949
32982
|
const existing = extractExistingCommand(settings);
|
|
32950
32983
|
const ourCommand = `bash ${destScript}`;
|
|
@@ -32972,7 +33005,7 @@ async function uninstallStatuslineCommand(options = {}) {
|
|
|
32972
33005
|
await writeSettingsJson(settingsPath, settings);
|
|
32973
33006
|
}
|
|
32974
33007
|
if (!options.keepScript) {
|
|
32975
|
-
const configPath2 =
|
|
33008
|
+
const configPath2 = resolve68(installRoot, "statusline.config.json");
|
|
32976
33009
|
for (const path of [destScript, confPath, backupPath, wrapperPath, configPath2]) {
|
|
32977
33010
|
try {
|
|
32978
33011
|
await rm8(path, { force: true });
|
|
@@ -33132,7 +33165,7 @@ init_config2();
|
|
|
33132
33165
|
// src/commands/cross-agent-install.ts
|
|
33133
33166
|
init_fs();
|
|
33134
33167
|
import { spawnSync as spawnSync6 } from "child_process";
|
|
33135
|
-
import { dirname as dirname20, join as join15, resolve as
|
|
33168
|
+
import { dirname as dirname20, join as join15, resolve as resolve70 } from "path";
|
|
33136
33169
|
import { cp as cp4, mkdir as mkdir9, readFile as readFile47 } from "fs/promises";
|
|
33137
33170
|
|
|
33138
33171
|
// src/commands/setup-adapter.ts
|
|
@@ -33142,7 +33175,7 @@ init_config2();
|
|
|
33142
33175
|
init_slug();
|
|
33143
33176
|
init_registry();
|
|
33144
33177
|
init_renderers();
|
|
33145
|
-
import { resolve as
|
|
33178
|
+
import { resolve as resolve69 } from "path";
|
|
33146
33179
|
async function setupAdapterCommand(framework, options) {
|
|
33147
33180
|
const { targets: known, warnings } = await resolveAgentTargets();
|
|
33148
33181
|
const target = known.find((t) => t.id === framework);
|
|
@@ -33171,13 +33204,13 @@ async function setupAdapterCommand(framework, options) {
|
|
|
33171
33204
|
}
|
|
33172
33205
|
const config = await readConfig();
|
|
33173
33206
|
const baseDir = options.dir ? expandHome(options.dir) : config.defaultProjectDir;
|
|
33174
|
-
const projectDir =
|
|
33175
|
-
const assignmentDir =
|
|
33176
|
-
const projectMdPath =
|
|
33207
|
+
const projectDir = resolve69(baseDir, options.project);
|
|
33208
|
+
const assignmentDir = resolve69(projectDir, "assignments", options.assignment);
|
|
33209
|
+
const projectMdPath = resolve69(projectDir, "project.md");
|
|
33177
33210
|
if (!await fileExists(projectDir) || !await fileExists(projectMdPath)) {
|
|
33178
33211
|
throw new Error(`Project "${options.project}" not found at ${projectDir}.`);
|
|
33179
33212
|
}
|
|
33180
|
-
const assignmentMdPath2 =
|
|
33213
|
+
const assignmentMdPath2 = resolve69(assignmentDir, "assignment.md");
|
|
33181
33214
|
if (!await fileExists(assignmentDir) || !await fileExists(assignmentMdPath2)) {
|
|
33182
33215
|
throw new Error(
|
|
33183
33216
|
`Assignment "${options.assignment}" not found at ${assignmentDir}.`
|
|
@@ -33194,7 +33227,7 @@ async function setupAdapterCommand(framework, options) {
|
|
|
33194
33227
|
const upToDateFiles = [];
|
|
33195
33228
|
const skippedFiles = [];
|
|
33196
33229
|
for (const file of target.instructions.files) {
|
|
33197
|
-
const filePath =
|
|
33230
|
+
const filePath = resolve69(cwd, file.path);
|
|
33198
33231
|
const content = RENDERERS[file.renderer](rendererParams);
|
|
33199
33232
|
const status = await writeFileReport(filePath, content, {
|
|
33200
33233
|
force: options.force
|
|
@@ -33250,7 +33283,7 @@ async function installTier3Plugin(t, opts = {}) {
|
|
|
33250
33283
|
return "already-present";
|
|
33251
33284
|
}
|
|
33252
33285
|
try {
|
|
33253
|
-
const sourceDir =
|
|
33286
|
+
const sourceDir = resolve70(await findPackageRoot(plugin.source), plugin.source);
|
|
33254
33287
|
await mkdir9(dirname20(installDir), { recursive: true });
|
|
33255
33288
|
await cp4(sourceDir, installDir, { recursive: true, force: true });
|
|
33256
33289
|
console.log(`Tier 3 (${t.id}): installed ${plugin.kind} -> ${installDir}`);
|
|
@@ -33275,7 +33308,7 @@ function isNpxAvailable() {
|
|
|
33275
33308
|
}
|
|
33276
33309
|
}
|
|
33277
33310
|
async function readAssignmentContext() {
|
|
33278
|
-
const p =
|
|
33311
|
+
const p = resolve70(process.cwd(), ".syntaur", "context.json");
|
|
33279
33312
|
if (!await fileExists(p)) return null;
|
|
33280
33313
|
try {
|
|
33281
33314
|
return JSON.parse(await readFile47(p, "utf-8"));
|
|
@@ -33358,7 +33391,7 @@ async function crossAgentInstallCommand(options) {
|
|
|
33358
33391
|
if (dryRun) {
|
|
33359
33392
|
for (const f of t.instructions.files) {
|
|
33360
33393
|
console.log(
|
|
33361
|
-
`${prefix}Tier 2 (${t.id}): ${
|
|
33394
|
+
`${prefix}Tier 2 (${t.id}): ${resolve70(process.cwd(), f.path)}`
|
|
33362
33395
|
);
|
|
33363
33396
|
}
|
|
33364
33397
|
continue;
|
|
@@ -33515,7 +33548,7 @@ async function setupCommand(options) {
|
|
|
33515
33548
|
}
|
|
33516
33549
|
|
|
33517
33550
|
// src/commands/uninstall.ts
|
|
33518
|
-
import { resolve as
|
|
33551
|
+
import { resolve as resolve71 } from "path";
|
|
33519
33552
|
init_paths();
|
|
33520
33553
|
function expandTargets(options) {
|
|
33521
33554
|
if (options.all) {
|
|
@@ -33595,7 +33628,7 @@ async function uninstallCommand(options) {
|
|
|
33595
33628
|
const configuredProjectDir = await getConfiguredProjectDir();
|
|
33596
33629
|
await removeSyntaurData();
|
|
33597
33630
|
console.log(`Removed ${syntaurRoot()}`);
|
|
33598
|
-
if (configuredProjectDir &&
|
|
33631
|
+
if (configuredProjectDir && resolve71(configuredProjectDir) !== resolve71(syntaurRoot(), "projects")) {
|
|
33599
33632
|
console.warn(
|
|
33600
33633
|
`Warning: config.md pointed to an external project directory (${configuredProjectDir}). That directory was not removed automatically.`
|
|
33601
33634
|
);
|
|
@@ -33617,7 +33650,7 @@ init_session_id();
|
|
|
33617
33650
|
init_cwd();
|
|
33618
33651
|
init_session_db();
|
|
33619
33652
|
init_agent_sessions();
|
|
33620
|
-
import { resolve as
|
|
33653
|
+
import { resolve as resolve72 } from "path";
|
|
33621
33654
|
import { readFile as readFile48 } from "fs/promises";
|
|
33622
33655
|
async function trackSessionCommand(options, deps = {}) {
|
|
33623
33656
|
if (!options.agent) {
|
|
@@ -33628,7 +33661,7 @@ async function trackSessionCommand(options, deps = {}) {
|
|
|
33628
33661
|
const cwd = process.cwd();
|
|
33629
33662
|
let legacyHint;
|
|
33630
33663
|
try {
|
|
33631
|
-
const raw2 = await readFile48(
|
|
33664
|
+
const raw2 = await readFile48(resolve72(cwd, ".syntaur", "context.json"), "utf-8");
|
|
33632
33665
|
const parsed = JSON.parse(raw2);
|
|
33633
33666
|
if (typeof parsed.sessionId === "string") legacyHint = parsed.sessionId;
|
|
33634
33667
|
} catch {
|
|
@@ -33643,7 +33676,7 @@ async function trackSessionCommand(options, deps = {}) {
|
|
|
33643
33676
|
if (options.project) {
|
|
33644
33677
|
const config = await readConfig();
|
|
33645
33678
|
const baseDir = options.dir ? expandHome(options.dir) : config.defaultProjectDir;
|
|
33646
|
-
const projectDir =
|
|
33679
|
+
const projectDir = resolve72(baseDir, options.project);
|
|
33647
33680
|
if (!await fileExists(projectDir)) {
|
|
33648
33681
|
throw new Error(
|
|
33649
33682
|
`Project "${options.project}" not found at ${projectDir}.`
|
|
@@ -33776,7 +33809,7 @@ function formatInstallUrlHandlerError(err2) {
|
|
|
33776
33809
|
init_config2();
|
|
33777
33810
|
init_paths();
|
|
33778
33811
|
init_fs();
|
|
33779
|
-
import { resolve as
|
|
33812
|
+
import { resolve as resolve74, isAbsolute as isAbsolute8 } from "path";
|
|
33780
33813
|
import { readFile as readFile49 } from "fs/promises";
|
|
33781
33814
|
import { select, confirm as confirm2, input as input3 } from "@inquirer/prompts";
|
|
33782
33815
|
async function browseCommand(options) {
|
|
@@ -33846,7 +33879,7 @@ async function pickAgent2(agents) {
|
|
|
33846
33879
|
return picked;
|
|
33847
33880
|
}
|
|
33848
33881
|
async function ensureWorktree(opts) {
|
|
33849
|
-
const assignmentPath =
|
|
33882
|
+
const assignmentPath = resolve74(
|
|
33850
33883
|
opts.projectsDir,
|
|
33851
33884
|
opts.projectSlug,
|
|
33852
33885
|
"assignments",
|
|
@@ -33926,7 +33959,7 @@ async function ensureWorktree(opts) {
|
|
|
33926
33959
|
async function runCreate(opts) {
|
|
33927
33960
|
const { createWorktreeAndRecord: createWorktreeAndRecord2, GitWorktreeError: GitWorktreeError2 } = await Promise.resolve().then(() => (init_git_worktree(), git_worktree_exports));
|
|
33928
33961
|
const expandedWorktree = expandHome(opts.worktreePath);
|
|
33929
|
-
const absWorktree = isAbsolute8(expandedWorktree) ? expandedWorktree :
|
|
33962
|
+
const absWorktree = isAbsolute8(expandedWorktree) ? expandedWorktree : resolve74(expandedWorktree);
|
|
33930
33963
|
try {
|
|
33931
33964
|
await createWorktreeAndRecord2({
|
|
33932
33965
|
assignmentPath: opts.assignmentPath,
|
|
@@ -33955,7 +33988,7 @@ init_paths();
|
|
|
33955
33988
|
init_fs();
|
|
33956
33989
|
init_playbook();
|
|
33957
33990
|
init_playbooks();
|
|
33958
|
-
import { resolve as
|
|
33991
|
+
import { resolve as resolve75 } from "path";
|
|
33959
33992
|
async function createPlaybookCommand(name, options) {
|
|
33960
33993
|
if (!name.trim()) {
|
|
33961
33994
|
throw new Error("Playbook name cannot be empty.");
|
|
@@ -33968,7 +34001,7 @@ async function createPlaybookCommand(name, options) {
|
|
|
33968
34001
|
}
|
|
33969
34002
|
const dir = playbooksDir();
|
|
33970
34003
|
await ensureDir(dir);
|
|
33971
|
-
const filePath =
|
|
34004
|
+
const filePath = resolve75(dir, `${slug}.md`);
|
|
33972
34005
|
if (await fileExists(filePath)) {
|
|
33973
34006
|
throw new Error(
|
|
33974
34007
|
`Playbook "${slug}" already exists at ${filePath}
|
|
@@ -33991,7 +34024,7 @@ init_fs();
|
|
|
33991
34024
|
init_parser();
|
|
33992
34025
|
init_config2();
|
|
33993
34026
|
import { readdir as readdir26, readFile as readFile50 } from "fs/promises";
|
|
33994
|
-
import { resolve as
|
|
34027
|
+
import { resolve as resolve76 } from "path";
|
|
33995
34028
|
async function listPlaybooksCommand(options = {}) {
|
|
33996
34029
|
const dir = playbooksDir();
|
|
33997
34030
|
if (!await fileExists(dir)) {
|
|
@@ -34006,7 +34039,7 @@ async function listPlaybooksCommand(options = {}) {
|
|
|
34006
34039
|
);
|
|
34007
34040
|
const rows = [];
|
|
34008
34041
|
for (const entry of mdFiles) {
|
|
34009
|
-
const filePath =
|
|
34042
|
+
const filePath = resolve76(dir, entry.name);
|
|
34010
34043
|
const raw2 = await readFile50(filePath, "utf-8");
|
|
34011
34044
|
const parsed = parsePlaybook(raw2);
|
|
34012
34045
|
const slug = parsed.slug || entry.name.replace(/\.md$/, "");
|
|
@@ -34131,13 +34164,13 @@ init_config2();
|
|
|
34131
34164
|
init_slug();
|
|
34132
34165
|
import { Command as Command2 } from "commander";
|
|
34133
34166
|
import { readFile as readFile52 } from "fs/promises";
|
|
34134
|
-
import { resolve as
|
|
34167
|
+
import { resolve as resolve78 } from "path";
|
|
34135
34168
|
|
|
34136
34169
|
// src/commands/bundle.ts
|
|
34137
34170
|
init_paths();
|
|
34138
34171
|
import { Command } from "commander";
|
|
34139
34172
|
import { mkdir as mkdir10, readFile as readFile51, readdir as readdir27, rm as rm9, writeFile as writeFile13 } from "fs/promises";
|
|
34140
|
-
import { resolve as
|
|
34173
|
+
import { resolve as resolve77 } from "path";
|
|
34141
34174
|
init_parser2();
|
|
34142
34175
|
init_fs();
|
|
34143
34176
|
init_config2();
|
|
@@ -34155,7 +34188,7 @@ async function resolveBundleScope(options) {
|
|
|
34155
34188
|
throw new Error(`Invalid project slug: "${options.project}".`);
|
|
34156
34189
|
}
|
|
34157
34190
|
const config = await readConfig();
|
|
34158
|
-
const projectMd =
|
|
34191
|
+
const projectMd = resolve77(config.defaultProjectDir, options.project, "project.md");
|
|
34159
34192
|
if (!await fileExists(projectMd)) {
|
|
34160
34193
|
throw new Error(`Project "${options.project}" not found.`);
|
|
34161
34194
|
}
|
|
@@ -34225,10 +34258,10 @@ function pickNextPlanFile(planDir, existingFiles) {
|
|
|
34225
34258
|
const m = f.match(/^plan-v(\d+)\.md$/);
|
|
34226
34259
|
if (m) versions.add(parseInt(m[1], 10));
|
|
34227
34260
|
}
|
|
34228
|
-
if (versions.size === 0) return { target:
|
|
34261
|
+
if (versions.size === 0) return { target: resolve77(planDir, "plan.md"), version: 1 };
|
|
34229
34262
|
let n = 2;
|
|
34230
34263
|
while (versions.has(n)) n++;
|
|
34231
|
-
return { target:
|
|
34264
|
+
return { target: resolve77(planDir, `plan-v${n}.md`), version: n };
|
|
34232
34265
|
}
|
|
34233
34266
|
function dedupePreserveOrder(ids) {
|
|
34234
34267
|
const out = [];
|
|
@@ -34312,7 +34345,7 @@ bundleCommand.command("new").description("Create a new bundle from 2+ existing t
|
|
|
34312
34345
|
if (options.plan) {
|
|
34313
34346
|
const planDir = bundlePlanDir(sc.todosPath, sc.scopeId, id);
|
|
34314
34347
|
await ensureDir(planDir);
|
|
34315
|
-
const target =
|
|
34348
|
+
const target = resolve77(planDir, "plan.md");
|
|
34316
34349
|
const memberLines = items.map((it) => `- ${it.description} [t:${it.id}]`).join("\n");
|
|
34317
34350
|
const stub = [
|
|
34318
34351
|
"---",
|
|
@@ -34488,7 +34521,7 @@ bundleCommand.command("worktree").description("Create a git worktree for the bun
|
|
|
34488
34521
|
}
|
|
34489
34522
|
const repository = options.repository ?? process.cwd();
|
|
34490
34523
|
const parentBranch = options.parentBranch ?? "main";
|
|
34491
|
-
const worktreePath = options.worktreePath ??
|
|
34524
|
+
const worktreePath = options.worktreePath ?? resolve77(repository, ".worktrees", options.branch);
|
|
34492
34525
|
const checklist = await readChecklist(sc.todosPath, sc.checklistKey);
|
|
34493
34526
|
for (const memberId of bundle.todoIds) {
|
|
34494
34527
|
const item = checklist.items.find((i) => i.id === memberId);
|
|
@@ -34515,7 +34548,7 @@ bundleCommand.command("worktree").description("Create a git worktree for the bun
|
|
|
34515
34548
|
try {
|
|
34516
34549
|
await writeBundles(sc.todosPath, bundles);
|
|
34517
34550
|
await writeChecklist(sc.todosPath, checklist);
|
|
34518
|
-
const ctxDir =
|
|
34551
|
+
const ctxDir = resolve77(worktreePath, ".syntaur");
|
|
34519
34552
|
await mkdir10(ctxDir, { recursive: true });
|
|
34520
34553
|
const payload = {
|
|
34521
34554
|
bundleId: bundle.id,
|
|
@@ -34529,7 +34562,7 @@ bundleCommand.command("worktree").description("Create a git worktree for the bun
|
|
|
34529
34562
|
repository,
|
|
34530
34563
|
boundAt: nowISO()
|
|
34531
34564
|
};
|
|
34532
|
-
await writeFile13(
|
|
34565
|
+
await writeFile13(resolve77(ctxDir, "context.json"), JSON.stringify(payload, null, 2) + "\n");
|
|
34533
34566
|
} catch (err2) {
|
|
34534
34567
|
try {
|
|
34535
34568
|
if (bundlesSnapshot === null) {
|
|
@@ -34719,7 +34752,7 @@ async function resolveScope(options) {
|
|
|
34719
34752
|
throw new Error(`Invalid project slug: "${options.project}".`);
|
|
34720
34753
|
}
|
|
34721
34754
|
const config = await readConfig();
|
|
34722
|
-
const projectMd =
|
|
34755
|
+
const projectMd = resolve78(config.defaultProjectDir, options.project, "project.md");
|
|
34723
34756
|
if (!await fileExists(projectMd)) {
|
|
34724
34757
|
throw new Error(`Project "${options.project}" not found.`);
|
|
34725
34758
|
}
|
|
@@ -35052,7 +35085,7 @@ todoCommand.command("archive").description("Archive completed todos and their lo
|
|
|
35052
35085
|
(e) => e.itemIds.every((id) => completedIds.has(id))
|
|
35053
35086
|
);
|
|
35054
35087
|
const archFile = archivePath(todosPath, workspace, checklist.archiveInterval);
|
|
35055
|
-
await ensureDir(
|
|
35088
|
+
await ensureDir(resolve78(todosPath, "archive"));
|
|
35056
35089
|
let archContent = "";
|
|
35057
35090
|
if (await fileExists(archFile)) {
|
|
35058
35091
|
archContent = await readFile52(archFile, "utf-8");
|
|
@@ -35289,7 +35322,7 @@ todoCommand.command("plan").description("Create or open a plan directory for a t
|
|
|
35289
35322
|
);
|
|
35290
35323
|
let target;
|
|
35291
35324
|
if (existingFiles.length === 0) {
|
|
35292
|
-
target =
|
|
35325
|
+
target = resolve78(planDir, "plan.md");
|
|
35293
35326
|
} else {
|
|
35294
35327
|
const versions = /* @__PURE__ */ new Set();
|
|
35295
35328
|
for (const f of existingFiles) {
|
|
@@ -35299,7 +35332,7 @@ todoCommand.command("plan").description("Create or open a plan directory for a t
|
|
|
35299
35332
|
}
|
|
35300
35333
|
let n = 2;
|
|
35301
35334
|
while (versions.has(n)) n++;
|
|
35302
|
-
target =
|
|
35335
|
+
target = resolve78(planDir, `plan-v${n}.md`);
|
|
35303
35336
|
}
|
|
35304
35337
|
if (!await fileExists(target)) {
|
|
35305
35338
|
const stub = `---
|
|
@@ -35494,7 +35527,7 @@ backupCommand.command("config").description("Show or update backup configuration
|
|
|
35494
35527
|
// src/commands/doctor.ts
|
|
35495
35528
|
import { Command as Command4 } from "commander";
|
|
35496
35529
|
import { readFile as readFile64 } from "fs/promises";
|
|
35497
|
-
import { isAbsolute as isAbsolute11, resolve as
|
|
35530
|
+
import { isAbsolute as isAbsolute11, resolve as resolve92 } from "path";
|
|
35498
35531
|
|
|
35499
35532
|
// src/utils/doctor/index.ts
|
|
35500
35533
|
import { fileURLToPath as fileURLToPath12 } from "url";
|
|
@@ -35506,11 +35539,11 @@ init_config2();
|
|
|
35506
35539
|
init_paths();
|
|
35507
35540
|
init_fs();
|
|
35508
35541
|
import Database5 from "better-sqlite3";
|
|
35509
|
-
import { resolve as
|
|
35542
|
+
import { resolve as resolve79 } from "path";
|
|
35510
35543
|
async function buildCheckContext(cwd = process.cwd()) {
|
|
35511
35544
|
const config = await readConfig();
|
|
35512
35545
|
const root = syntaurRoot();
|
|
35513
|
-
const dbPath =
|
|
35546
|
+
const dbPath = resolve79(root, "syntaur.db");
|
|
35514
35547
|
let db6 = null;
|
|
35515
35548
|
let dbError = null;
|
|
35516
35549
|
if (await fileExists(dbPath)) {
|
|
@@ -35544,7 +35577,7 @@ function closeCheckContext(ctx) {
|
|
|
35544
35577
|
// src/utils/doctor/checks/env.ts
|
|
35545
35578
|
init_fs();
|
|
35546
35579
|
init_paths();
|
|
35547
|
-
import { resolve as
|
|
35580
|
+
import { resolve as resolve80, isAbsolute as isAbsolute9 } from "path";
|
|
35548
35581
|
import { readFile as readFile53, stat as stat9 } from "fs/promises";
|
|
35549
35582
|
import { fileURLToPath as fileURLToPath10 } from "url";
|
|
35550
35583
|
import { dirname as dirname22, join as join17 } from "path";
|
|
@@ -35585,7 +35618,7 @@ var configValid = {
|
|
|
35585
35618
|
category: CATEGORY,
|
|
35586
35619
|
title: "~/.syntaur/config.md is valid",
|
|
35587
35620
|
async run(ctx) {
|
|
35588
|
-
const configPath2 =
|
|
35621
|
+
const configPath2 = resolve80(ctx.syntaurRoot, "config.md");
|
|
35589
35622
|
if (!await fileExists(configPath2)) {
|
|
35590
35623
|
return {
|
|
35591
35624
|
id: this.id,
|
|
@@ -35934,7 +35967,7 @@ function versionGte(a, b) {
|
|
|
35934
35967
|
|
|
35935
35968
|
// src/utils/doctor/checks/structure.ts
|
|
35936
35969
|
init_fs();
|
|
35937
|
-
import { resolve as
|
|
35970
|
+
import { resolve as resolve81 } from "path";
|
|
35938
35971
|
import { readdir as readdir28, stat as stat10 } from "fs/promises";
|
|
35939
35972
|
var CATEGORY2 = "structure";
|
|
35940
35973
|
var KNOWN_TOP_LEVEL = /* @__PURE__ */ new Set([
|
|
@@ -35954,7 +35987,7 @@ var projectsDir = {
|
|
|
35954
35987
|
category: CATEGORY2,
|
|
35955
35988
|
title: "projects/ directory exists",
|
|
35956
35989
|
async run(ctx) {
|
|
35957
|
-
const p =
|
|
35990
|
+
const p = resolve81(ctx.syntaurRoot, "projects");
|
|
35958
35991
|
if (!await fileExists(p)) {
|
|
35959
35992
|
return {
|
|
35960
35993
|
id: this.id,
|
|
@@ -35979,7 +36012,7 @@ var playbooksDir2 = {
|
|
|
35979
36012
|
category: CATEGORY2,
|
|
35980
36013
|
title: "playbooks/ directory exists",
|
|
35981
36014
|
async run(ctx) {
|
|
35982
|
-
const p =
|
|
36015
|
+
const p = resolve81(ctx.syntaurRoot, "playbooks");
|
|
35983
36016
|
if (!await fileExists(p)) {
|
|
35984
36017
|
return {
|
|
35985
36018
|
id: this.id,
|
|
@@ -36004,7 +36037,7 @@ var todosDirValid = {
|
|
|
36004
36037
|
category: CATEGORY2,
|
|
36005
36038
|
title: "todos/ directory is readable (if present)",
|
|
36006
36039
|
async run(ctx) {
|
|
36007
|
-
const p =
|
|
36040
|
+
const p = resolve81(ctx.syntaurRoot, "todos");
|
|
36008
36041
|
if (!await fileExists(p)) {
|
|
36009
36042
|
return {
|
|
36010
36043
|
id: this.id,
|
|
@@ -36035,7 +36068,7 @@ var serversDirValid = {
|
|
|
36035
36068
|
category: CATEGORY2,
|
|
36036
36069
|
title: "servers/ directory is readable (if present)",
|
|
36037
36070
|
async run(ctx) {
|
|
36038
|
-
const p =
|
|
36071
|
+
const p = resolve81(ctx.syntaurRoot, "servers");
|
|
36039
36072
|
if (!await fileExists(p)) {
|
|
36040
36073
|
return {
|
|
36041
36074
|
id: this.id,
|
|
@@ -36080,7 +36113,7 @@ var knownFilesRecognized = {
|
|
|
36080
36113
|
title: this.title,
|
|
36081
36114
|
status: "warn",
|
|
36082
36115
|
detail: `unexpected top-level entries: ${unexpected.join(", ")}`,
|
|
36083
|
-
affected: unexpected.map((n) =>
|
|
36116
|
+
affected: unexpected.map((n) => resolve81(ctx.syntaurRoot, n)),
|
|
36084
36117
|
remediation: {
|
|
36085
36118
|
kind: "manual",
|
|
36086
36119
|
suggestion: "Review these entries \u2014 they may be leftover state from older versions",
|
|
@@ -36109,7 +36142,7 @@ function pass2(check) {
|
|
|
36109
36142
|
|
|
36110
36143
|
// src/utils/doctor/checks/project.ts
|
|
36111
36144
|
init_fs();
|
|
36112
|
-
import { resolve as
|
|
36145
|
+
import { resolve as resolve82 } from "path";
|
|
36113
36146
|
import { readdir as readdir29, stat as stat11 } from "fs/promises";
|
|
36114
36147
|
var CATEGORY3 = "project";
|
|
36115
36148
|
var REQUIRED_PROJECT_FILES = [
|
|
@@ -36139,10 +36172,10 @@ async function listProjects2(ctx) {
|
|
|
36139
36172
|
for (const e of entries) {
|
|
36140
36173
|
if (!e.isDirectory()) continue;
|
|
36141
36174
|
if (e.name.startsWith(".") || e.name.startsWith("_")) continue;
|
|
36142
|
-
const projectDir =
|
|
36175
|
+
const projectDir = resolve82(dir, e.name);
|
|
36143
36176
|
let looksLikeProject = false;
|
|
36144
36177
|
for (const marker of PROJECT_MARKERS) {
|
|
36145
|
-
if (await fileExists(
|
|
36178
|
+
if (await fileExists(resolve82(projectDir, marker))) {
|
|
36146
36179
|
looksLikeProject = true;
|
|
36147
36180
|
break;
|
|
36148
36181
|
}
|
|
@@ -36161,7 +36194,7 @@ var requiredFiles = {
|
|
|
36161
36194
|
for (const projectDir of projects) {
|
|
36162
36195
|
const missing = [];
|
|
36163
36196
|
for (const rel of REQUIRED_PROJECT_FILES) {
|
|
36164
|
-
const p =
|
|
36197
|
+
const p = resolve82(projectDir, rel);
|
|
36165
36198
|
if (!await fileExists(p)) missing.push(rel);
|
|
36166
36199
|
}
|
|
36167
36200
|
if (missing.length === 0) continue;
|
|
@@ -36171,7 +36204,7 @@ var requiredFiles = {
|
|
|
36171
36204
|
title: this.title,
|
|
36172
36205
|
status: "error",
|
|
36173
36206
|
detail: `project at ${projectDir} is missing: ${missing.join(", ")}`,
|
|
36174
|
-
affected: missing.map((m) =>
|
|
36207
|
+
affected: missing.map((m) => resolve82(projectDir, m)),
|
|
36175
36208
|
remediation: {
|
|
36176
36209
|
kind: "manual",
|
|
36177
36210
|
suggestion: "Recreate the missing scaffold files from templates",
|
|
@@ -36194,7 +36227,7 @@ var manifestStale = {
|
|
|
36194
36227
|
const projects = await listProjects2(ctx);
|
|
36195
36228
|
const results = [];
|
|
36196
36229
|
for (const projectDir of projects) {
|
|
36197
|
-
const manifestPath =
|
|
36230
|
+
const manifestPath = resolve82(projectDir, "manifest.md");
|
|
36198
36231
|
if (!await fileExists(manifestPath)) continue;
|
|
36199
36232
|
const manifestMtime = (await stat11(manifestPath)).mtimeMs;
|
|
36200
36233
|
const newestAssignment = await newestAssignmentMtime(projectDir);
|
|
@@ -36243,7 +36276,7 @@ var orphanFiles = {
|
|
|
36243
36276
|
title: this.title,
|
|
36244
36277
|
status: "warn",
|
|
36245
36278
|
detail: `project at ${projectDir} has unexpected entries: ${orphans.join(", ")}`,
|
|
36246
|
-
affected: orphans.map((o) =>
|
|
36279
|
+
affected: orphans.map((o) => resolve82(projectDir, o)),
|
|
36247
36280
|
autoFixable: false
|
|
36248
36281
|
});
|
|
36249
36282
|
}
|
|
@@ -36253,7 +36286,7 @@ var orphanFiles = {
|
|
|
36253
36286
|
};
|
|
36254
36287
|
var projectChecks = [requiredFiles, manifestStale, orphanFiles];
|
|
36255
36288
|
async function newestAssignmentMtime(projectDir) {
|
|
36256
|
-
const assignmentsRoot =
|
|
36289
|
+
const assignmentsRoot = resolve82(projectDir, "assignments");
|
|
36257
36290
|
if (!await fileExists(assignmentsRoot)) return 0;
|
|
36258
36291
|
let newest = 0;
|
|
36259
36292
|
let entries;
|
|
@@ -36264,7 +36297,7 @@ async function newestAssignmentMtime(projectDir) {
|
|
|
36264
36297
|
}
|
|
36265
36298
|
for (const e of entries) {
|
|
36266
36299
|
if (!e.isDirectory()) continue;
|
|
36267
|
-
const assignmentMd =
|
|
36300
|
+
const assignmentMd = resolve82(assignmentsRoot, e.name, "assignment.md");
|
|
36268
36301
|
try {
|
|
36269
36302
|
const s = await stat11(assignmentMd);
|
|
36270
36303
|
if (s.mtimeMs > newest) newest = s.mtimeMs;
|
|
@@ -36289,7 +36322,7 @@ init_parser();
|
|
|
36289
36322
|
init_types();
|
|
36290
36323
|
init_paths();
|
|
36291
36324
|
init_assignment_walk();
|
|
36292
|
-
import { resolve as
|
|
36325
|
+
import { resolve as resolve83 } from "path";
|
|
36293
36326
|
import { readFile as readFile54, readdir as readdir30 } from "fs/promises";
|
|
36294
36327
|
var CATEGORY4 = "assignment";
|
|
36295
36328
|
var STATUSES_REQUIRING_HANDOFF = /* @__PURE__ */ new Set(["review", "completed"]);
|
|
@@ -36384,7 +36417,7 @@ var invalidStatus = {
|
|
|
36384
36417
|
const allowed = configuredStatuses(ctx);
|
|
36385
36418
|
const results = [];
|
|
36386
36419
|
for (const a of withAssignmentMd) {
|
|
36387
|
-
const path =
|
|
36420
|
+
const path = resolve83(a.assignmentDir, "assignment.md");
|
|
36388
36421
|
const parsed = await parseSafe4(path);
|
|
36389
36422
|
if (!parsed) continue;
|
|
36390
36423
|
if (!allowed.has(parsed.status)) {
|
|
@@ -36417,7 +36450,7 @@ var workspaceMissing = {
|
|
|
36417
36450
|
const terminal = terminalStatuses(ctx);
|
|
36418
36451
|
const results = [];
|
|
36419
36452
|
for (const a of withAssignmentMd) {
|
|
36420
|
-
const path =
|
|
36453
|
+
const path = resolve83(a.assignmentDir, "assignment.md");
|
|
36421
36454
|
const parsed = await parseSafe4(path);
|
|
36422
36455
|
if (!parsed) continue;
|
|
36423
36456
|
if (terminal.has(parsed.status)) continue;
|
|
@@ -36464,12 +36497,12 @@ var requiredFilesByStatus = {
|
|
|
36464
36497
|
const { withAssignmentMd } = await listAssignments(ctx);
|
|
36465
36498
|
const results = [];
|
|
36466
36499
|
for (const a of withAssignmentMd) {
|
|
36467
|
-
const assignmentPath =
|
|
36500
|
+
const assignmentPath = resolve83(a.assignmentDir, "assignment.md");
|
|
36468
36501
|
const parsed = await parseSafe4(assignmentPath);
|
|
36469
36502
|
if (!parsed) continue;
|
|
36470
36503
|
const missing = [];
|
|
36471
36504
|
if (STATUSES_REQUIRING_HANDOFF.has(parsed.status)) {
|
|
36472
|
-
const handoffPath =
|
|
36505
|
+
const handoffPath = resolve83(a.assignmentDir, "handoff.md");
|
|
36473
36506
|
if (!await fileExists(handoffPath)) missing.push("handoff.md");
|
|
36474
36507
|
}
|
|
36475
36508
|
if (missing.length === 0) continue;
|
|
@@ -36479,7 +36512,7 @@ var requiredFilesByStatus = {
|
|
|
36479
36512
|
title: this.title,
|
|
36480
36513
|
status: "warn",
|
|
36481
36514
|
detail: `${a.projectSlug}/${a.assignmentSlug} (status: ${parsed.status}) is missing ${missing.join(", ")}`,
|
|
36482
|
-
affected: missing.map((m) =>
|
|
36515
|
+
affected: missing.map((m) => resolve83(a.assignmentDir, m)),
|
|
36483
36516
|
remediation: {
|
|
36484
36517
|
kind: "manual",
|
|
36485
36518
|
suggestion: `Create the missing ${missing.join(" and ")} files for this assignment`,
|
|
@@ -36502,7 +36535,7 @@ var companionFilesScaffolded = {
|
|
|
36502
36535
|
for (const a of withAssignmentMd) {
|
|
36503
36536
|
const missing = [];
|
|
36504
36537
|
for (const filename of ["progress.md", "comments.md"]) {
|
|
36505
|
-
if (!await fileExists(
|
|
36538
|
+
if (!await fileExists(resolve83(a.assignmentDir, filename))) {
|
|
36506
36539
|
missing.push(filename);
|
|
36507
36540
|
}
|
|
36508
36541
|
}
|
|
@@ -36514,7 +36547,7 @@ var companionFilesScaffolded = {
|
|
|
36514
36547
|
title: this.title,
|
|
36515
36548
|
status: "warn",
|
|
36516
36549
|
detail: `${label} is missing ${missing.join(" and ")} (pre-v2.0 assignment \u2014 not required, but scaffolding them keeps the dashboard and CLIs consistent)`,
|
|
36517
|
-
affected: missing.map((m) =>
|
|
36550
|
+
affected: missing.map((m) => resolve83(a.assignmentDir, m)),
|
|
36518
36551
|
remediation: {
|
|
36519
36552
|
kind: "manual",
|
|
36520
36553
|
suggestion: `Create ${missing.join(" and ")} with the renderProgress/renderComments templates, or re-scaffold via the CLI`,
|
|
@@ -36547,7 +36580,7 @@ var typeDefinition = {
|
|
|
36547
36580
|
const { withAssignmentMd } = await listAssignments(ctx);
|
|
36548
36581
|
const results = [];
|
|
36549
36582
|
for (const a of withAssignmentMd) {
|
|
36550
|
-
const path =
|
|
36583
|
+
const path = resolve83(a.assignmentDir, "assignment.md");
|
|
36551
36584
|
const parsed = await parseSafe4(path);
|
|
36552
36585
|
if (!parsed) continue;
|
|
36553
36586
|
if (!parsed.type) continue;
|
|
@@ -36581,7 +36614,7 @@ var projectFrontmatterMatchesContainer = {
|
|
|
36581
36614
|
const { withAssignmentMd } = await listAssignments(ctx);
|
|
36582
36615
|
const results = [];
|
|
36583
36616
|
for (const a of withAssignmentMd) {
|
|
36584
|
-
const path =
|
|
36617
|
+
const path = resolve83(a.assignmentDir, "assignment.md");
|
|
36585
36618
|
const parsed = await parseSafe4(path);
|
|
36586
36619
|
if (!parsed) continue;
|
|
36587
36620
|
if (a.standalone) {
|
|
@@ -36632,7 +36665,7 @@ var draftMissingObjective = {
|
|
|
36632
36665
|
const { withAssignmentMd } = await listAssignments(ctx);
|
|
36633
36666
|
const results = [];
|
|
36634
36667
|
for (const a of withAssignmentMd) {
|
|
36635
|
-
const path =
|
|
36668
|
+
const path = resolve83(a.assignmentDir, "assignment.md");
|
|
36636
36669
|
const parsed = await parseSafe4(path);
|
|
36637
36670
|
if (!parsed) continue;
|
|
36638
36671
|
if (parsed.status !== "draft") continue;
|
|
@@ -36671,7 +36704,7 @@ var readyToImplementMissingPlan = {
|
|
|
36671
36704
|
const { withAssignmentMd } = await listAssignments(ctx);
|
|
36672
36705
|
const results = [];
|
|
36673
36706
|
for (const a of withAssignmentMd) {
|
|
36674
|
-
const path =
|
|
36707
|
+
const path = resolve83(a.assignmentDir, "assignment.md");
|
|
36675
36708
|
const parsed = await parseSafe4(path);
|
|
36676
36709
|
if (!parsed) continue;
|
|
36677
36710
|
if (parsed.status !== "ready_to_implement") continue;
|
|
@@ -36680,7 +36713,7 @@ var readyToImplementMissingPlan = {
|
|
|
36680
36713
|
let hasPlanContent = false;
|
|
36681
36714
|
for (const f of planFiles) {
|
|
36682
36715
|
try {
|
|
36683
|
-
const c2 = await readFile54(
|
|
36716
|
+
const c2 = await readFile54(resolve83(a.assignmentDir, f), "utf-8");
|
|
36684
36717
|
if (c2.trim().length > 0) {
|
|
36685
36718
|
hasPlanContent = true;
|
|
36686
36719
|
break;
|
|
@@ -36696,7 +36729,7 @@ var readyToImplementMissingPlan = {
|
|
|
36696
36729
|
title: this.title,
|
|
36697
36730
|
status: "warn",
|
|
36698
36731
|
detail: `${label} (status: ready_to_implement) has no plan.md or plan-v<N>.md`,
|
|
36699
|
-
affected: [
|
|
36732
|
+
affected: [resolve83(a.assignmentDir, "plan.md")],
|
|
36700
36733
|
remediation: {
|
|
36701
36734
|
kind: "manual",
|
|
36702
36735
|
suggestion: `Write a plan with '/plan-assignment' (or 'syntaur plan'), then re-mark ready_to_implement`,
|
|
@@ -36742,7 +36775,7 @@ function pass4(check, detail) {
|
|
|
36742
36775
|
|
|
36743
36776
|
// src/utils/doctor/checks/dashboard.ts
|
|
36744
36777
|
init_fs();
|
|
36745
|
-
import { resolve as
|
|
36778
|
+
import { resolve as resolve84 } from "path";
|
|
36746
36779
|
var CATEGORY5 = "dashboard";
|
|
36747
36780
|
var dbReachable = {
|
|
36748
36781
|
id: "dashboard.db-reachable",
|
|
@@ -36756,7 +36789,7 @@ var dbReachable = {
|
|
|
36756
36789
|
title: this.title,
|
|
36757
36790
|
status: "error",
|
|
36758
36791
|
detail: `could not open syntaur.db: ${ctx.dbError ?? "unknown error"}`,
|
|
36759
|
-
affected: [
|
|
36792
|
+
affected: [resolve84(ctx.syntaurRoot, "syntaur.db")],
|
|
36760
36793
|
remediation: {
|
|
36761
36794
|
kind: "manual",
|
|
36762
36795
|
suggestion: "Start the dashboard once (`syntaur dashboard`) to initialize the DB, or restore it from backup",
|
|
@@ -36774,7 +36807,7 @@ var dbReachable = {
|
|
|
36774
36807
|
title: this.title,
|
|
36775
36808
|
status: "error",
|
|
36776
36809
|
detail: 'syntaur.db is missing the expected "sessions" table',
|
|
36777
|
-
affected: [
|
|
36810
|
+
affected: [resolve84(ctx.syntaurRoot, "syntaur.db")],
|
|
36778
36811
|
autoFixable: false
|
|
36779
36812
|
};
|
|
36780
36813
|
}
|
|
@@ -36786,7 +36819,7 @@ var dbReachable = {
|
|
|
36786
36819
|
title: this.title,
|
|
36787
36820
|
status: "error",
|
|
36788
36821
|
detail: `syntaur.db query failed: ${err2 instanceof Error ? err2.message : String(err2)}`,
|
|
36789
|
-
affected: [
|
|
36822
|
+
affected: [resolve84(ctx.syntaurRoot, "syntaur.db")],
|
|
36790
36823
|
autoFixable: false
|
|
36791
36824
|
};
|
|
36792
36825
|
}
|
|
@@ -36812,7 +36845,7 @@ var ghostSessions = {
|
|
|
36812
36845
|
const results = [];
|
|
36813
36846
|
for (const row of rows) {
|
|
36814
36847
|
if (!row.project_slug) continue;
|
|
36815
|
-
const projectPath =
|
|
36848
|
+
const projectPath = resolve84(projectsDir2, row.project_slug, "project.md");
|
|
36816
36849
|
if (!await fileExists(projectPath)) {
|
|
36817
36850
|
results.push({
|
|
36818
36851
|
id: this.id,
|
|
@@ -36831,7 +36864,7 @@ var ghostSessions = {
|
|
|
36831
36864
|
continue;
|
|
36832
36865
|
}
|
|
36833
36866
|
if (row.assignment_slug) {
|
|
36834
|
-
const assignmentPath =
|
|
36867
|
+
const assignmentPath = resolve84(
|
|
36835
36868
|
projectsDir2,
|
|
36836
36869
|
row.project_slug,
|
|
36837
36870
|
"assignments",
|
|
@@ -36883,7 +36916,7 @@ function skipped(check, reason) {
|
|
|
36883
36916
|
|
|
36884
36917
|
// src/utils/doctor/checks/integrations.ts
|
|
36885
36918
|
init_fs();
|
|
36886
|
-
import { resolve as
|
|
36919
|
+
import { resolve as resolve85, dirname as dirname23, basename as basename9 } from "path";
|
|
36887
36920
|
import { readdir as readdir31, readFile as readFile55 } from "fs/promises";
|
|
36888
36921
|
import { homedir as homedir14 } from "os";
|
|
36889
36922
|
var CATEGORY6 = "integrations";
|
|
@@ -36966,7 +36999,7 @@ var backupConfigured = {
|
|
|
36966
36999
|
}
|
|
36967
37000
|
};
|
|
36968
37001
|
async function readKnownMarketplaces() {
|
|
36969
|
-
const path =
|
|
37002
|
+
const path = resolve85(homedir14(), ".claude", "plugins", "known_marketplaces.json");
|
|
36970
37003
|
if (!await fileExists(path)) return {};
|
|
36971
37004
|
try {
|
|
36972
37005
|
const raw2 = await readFile55(path, "utf-8");
|
|
@@ -37003,7 +37036,7 @@ var claudeMarketplaceRegistered = {
|
|
|
37003
37036
|
};
|
|
37004
37037
|
}
|
|
37005
37038
|
const marketplaceRoot = dirname23(pluginsParent);
|
|
37006
|
-
const marketplaceManifest =
|
|
37039
|
+
const marketplaceManifest = resolve85(marketplaceRoot, ".claude-plugin", "marketplace.json");
|
|
37007
37040
|
if (!await fileExists(marketplaceManifest)) {
|
|
37008
37041
|
return {
|
|
37009
37042
|
id: this.id,
|
|
@@ -37054,7 +37087,7 @@ var claudeMarketplaceRegistered = {
|
|
|
37054
37087
|
title: this.title,
|
|
37055
37088
|
status: "error",
|
|
37056
37089
|
detail: issues.join("; "),
|
|
37057
|
-
affected: [marketplaceManifest,
|
|
37090
|
+
affected: [marketplaceManifest, resolve85(homedir14(), ".claude", "plugins", "known_marketplaces.json")],
|
|
37058
37091
|
remediation: {
|
|
37059
37092
|
kind: "manual",
|
|
37060
37093
|
suggestion: "Re-run install-plugin to ensure both files are in sync.",
|
|
@@ -37094,7 +37127,7 @@ function skipped2(check, reason) {
|
|
|
37094
37127
|
init_fs();
|
|
37095
37128
|
init_parser();
|
|
37096
37129
|
init_types();
|
|
37097
|
-
import { resolve as
|
|
37130
|
+
import { resolve as resolve86 } from "path";
|
|
37098
37131
|
import { readFile as readFile56 } from "fs/promises";
|
|
37099
37132
|
var CATEGORY7 = "workspace";
|
|
37100
37133
|
var ASSIGNMENT_FIELDS2 = ["projectSlug", "assignmentSlug", "projectDir", "assignmentDir"];
|
|
@@ -37117,7 +37150,7 @@ function isStandaloneSession(ctx) {
|
|
|
37117
37150
|
return !hasAnyAssignmentField(ctx) && !hasAnyBundleField(ctx) && hasSessionMeta;
|
|
37118
37151
|
}
|
|
37119
37152
|
async function loadContext(ctx) {
|
|
37120
|
-
const path =
|
|
37153
|
+
const path = resolve86(ctx.cwd, ".syntaur", "context.json");
|
|
37121
37154
|
if (!await fileExists(path)) {
|
|
37122
37155
|
return { data: null, path, exists: false, parseError: null };
|
|
37123
37156
|
}
|
|
@@ -37216,7 +37249,7 @@ var contextAssignmentResolves = {
|
|
|
37216
37249
|
if (isStandaloneSession(data)) return skipped3(this, "standalone session context \u2014 no assignment to resolve");
|
|
37217
37250
|
if (isBundleContext(data)) return skipped3(this, "bundle context \u2014 no assignment to resolve");
|
|
37218
37251
|
if (!data?.assignmentDir) return skipped3(this, "context has no assignmentDir");
|
|
37219
|
-
const assignmentMd =
|
|
37252
|
+
const assignmentMd = resolve86(data.assignmentDir, "assignment.md");
|
|
37220
37253
|
if (!await fileExists(assignmentMd)) {
|
|
37221
37254
|
return {
|
|
37222
37255
|
id: this.id,
|
|
@@ -37246,7 +37279,7 @@ var contextTerminal = {
|
|
|
37246
37279
|
if (isStandaloneSession(data)) return skipped3(this, "standalone session context \u2014 no assignment to check");
|
|
37247
37280
|
if (isBundleContext(data)) return skipped3(this, "bundle context \u2014 no assignment to check");
|
|
37248
37281
|
if (!data?.assignmentDir) return skipped3(this, "context has no assignmentDir");
|
|
37249
|
-
const assignmentMd =
|
|
37282
|
+
const assignmentMd = resolve86(data.assignmentDir, "assignment.md");
|
|
37250
37283
|
if (!await fileExists(assignmentMd)) return skipped3(this, "assignment file missing");
|
|
37251
37284
|
try {
|
|
37252
37285
|
const content = await readFile56(assignmentMd, "utf-8");
|
|
@@ -37396,12 +37429,12 @@ var agentChecks = [agentsResolvable];
|
|
|
37396
37429
|
init_config2();
|
|
37397
37430
|
import { spawnSync as spawnSync9 } from "child_process";
|
|
37398
37431
|
import { readFile as readFile57 } from "fs/promises";
|
|
37399
|
-
import { resolve as
|
|
37432
|
+
import { resolve as resolve87 } from "path";
|
|
37400
37433
|
init_paths();
|
|
37401
37434
|
init_fs();
|
|
37402
37435
|
var CATEGORY9 = "terminal";
|
|
37403
37436
|
async function readRawTerminalKey() {
|
|
37404
|
-
const configPath2 =
|
|
37437
|
+
const configPath2 = resolve87(syntaurRoot(), "config.md");
|
|
37405
37438
|
if (!await fileExists(configPath2)) return null;
|
|
37406
37439
|
const content = await readFile57(configPath2, "utf-8");
|
|
37407
37440
|
const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
@@ -37553,13 +37586,13 @@ var terminalChecks = [
|
|
|
37553
37586
|
|
|
37554
37587
|
// src/utils/doctor/checks/skills.ts
|
|
37555
37588
|
init_fs();
|
|
37556
|
-
import { resolve as
|
|
37589
|
+
import { resolve as resolve88, join as join18 } from "path";
|
|
37557
37590
|
import { readdir as readdir32, readFile as readFile58, lstat as lstat4 } from "fs/promises";
|
|
37558
37591
|
import { homedir as homedir15 } from "os";
|
|
37559
37592
|
var CATEGORY10 = "skills";
|
|
37560
37593
|
var skillTargets = [
|
|
37561
|
-
{ agent: "claude", dir:
|
|
37562
|
-
{ agent: "codex", dir:
|
|
37594
|
+
{ agent: "claude", dir: resolve88(homedir15(), ".claude", "skills"), label: "~/.claude/skills" },
|
|
37595
|
+
{ agent: "codex", dir: resolve88(homedir15(), ".codex", "skills"), label: "~/.codex/skills" }
|
|
37563
37596
|
];
|
|
37564
37597
|
var skillsDedupCheck = {
|
|
37565
37598
|
id: "skills.dedup",
|
|
@@ -37633,7 +37666,7 @@ var skillsChecks = [skillsDedupCheck];
|
|
|
37633
37666
|
|
|
37634
37667
|
// src/utils/doctor/checks/cross-agent.ts
|
|
37635
37668
|
init_fs();
|
|
37636
|
-
import { join as join19, resolve as
|
|
37669
|
+
import { join as join19, resolve as resolve89 } from "path";
|
|
37637
37670
|
import { readFile as readFile60 } from "fs/promises";
|
|
37638
37671
|
|
|
37639
37672
|
// src/utils/skill-frontmatter.ts
|
|
@@ -37776,7 +37809,7 @@ var crossAgentSkillsCheck = {
|
|
|
37776
37809
|
}
|
|
37777
37810
|
if (recorded && t.instructions) {
|
|
37778
37811
|
for (const f of t.instructions.files) {
|
|
37779
|
-
const p =
|
|
37812
|
+
const p = resolve89(ctx.cwd, f.path);
|
|
37780
37813
|
if (!await fileExists(p)) {
|
|
37781
37814
|
problems.push(`${t.displayName}: missing protocol file ${f.path} in cwd`);
|
|
37782
37815
|
affected.push(p);
|
|
@@ -37852,7 +37885,7 @@ var crossAgentChecks = [crossAgentSkillsCheck];
|
|
|
37852
37885
|
// src/utils/doctor/checks/bundles.ts
|
|
37853
37886
|
init_fs();
|
|
37854
37887
|
init_paths();
|
|
37855
|
-
import { resolve as
|
|
37888
|
+
import { resolve as resolve90 } from "path";
|
|
37856
37889
|
import { readdir as readdir33 } from "fs/promises";
|
|
37857
37890
|
import { spawnSync as spawnSync10 } from "child_process";
|
|
37858
37891
|
init_parser2();
|
|
@@ -37882,7 +37915,7 @@ async function listScopes(ctx) {
|
|
|
37882
37915
|
if (!e.isDirectory()) continue;
|
|
37883
37916
|
const slug = e.name;
|
|
37884
37917
|
if (typeof slug !== "string" || slug.startsWith(".")) continue;
|
|
37885
|
-
const projectMd =
|
|
37918
|
+
const projectMd = resolve90(ctx.config.defaultProjectDir, slug, "project.md");
|
|
37886
37919
|
if (!await fileExists(projectMd)) continue;
|
|
37887
37920
|
out.push({
|
|
37888
37921
|
scopeLabel: `project:${slug}`,
|
|
@@ -38195,7 +38228,7 @@ var deriveConfigChecks = [deriveConfigValid];
|
|
|
38195
38228
|
|
|
38196
38229
|
// src/utils/doctor/checks/staleness.ts
|
|
38197
38230
|
init_config2();
|
|
38198
|
-
import { resolve as
|
|
38231
|
+
import { resolve as resolve91 } from "path";
|
|
38199
38232
|
import { readFile as readFile62 } from "fs/promises";
|
|
38200
38233
|
var CATEGORY15 = "staleness";
|
|
38201
38234
|
var stalenessConfigValid = {
|
|
@@ -38205,7 +38238,7 @@ var stalenessConfigValid = {
|
|
|
38205
38238
|
async run(ctx) {
|
|
38206
38239
|
let content;
|
|
38207
38240
|
try {
|
|
38208
|
-
content = await readFile62(
|
|
38241
|
+
content = await readFile62(resolve91(ctx.syntaurRoot, "config.md"), "utf-8");
|
|
38209
38242
|
} catch {
|
|
38210
38243
|
return {
|
|
38211
38244
|
id: this.id,
|
|
@@ -38455,7 +38488,7 @@ var REQUIRED_WORKSPACE_FIELDS = [
|
|
|
38455
38488
|
];
|
|
38456
38489
|
var ISO_DATE = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z$/;
|
|
38457
38490
|
async function validateAssignmentFile(inputPath, cwd = process.cwd()) {
|
|
38458
|
-
const absolute = isAbsolute11(inputPath) ? inputPath :
|
|
38491
|
+
const absolute = isAbsolute11(inputPath) ? inputPath : resolve92(cwd, inputPath);
|
|
38459
38492
|
const errors = [];
|
|
38460
38493
|
const warnings = [];
|
|
38461
38494
|
if (!await fileExists(absolute)) {
|
|
@@ -38835,7 +38868,7 @@ init_assignment_resolver();
|
|
|
38835
38868
|
init_frontmatter();
|
|
38836
38869
|
init_event_emit();
|
|
38837
38870
|
init_templates();
|
|
38838
|
-
import { resolve as
|
|
38871
|
+
import { resolve as resolve93 } from "path";
|
|
38839
38872
|
import { readFile as readFile65 } from "fs/promises";
|
|
38840
38873
|
function shortId() {
|
|
38841
38874
|
return generateId().split("-")[0];
|
|
@@ -38867,7 +38900,7 @@ async function commentCommand(target, text, options = {}) {
|
|
|
38867
38900
|
if (!isValidSlug(target)) {
|
|
38868
38901
|
throw new Error(`Invalid assignment slug "${target}".`);
|
|
38869
38902
|
}
|
|
38870
|
-
assignmentDir =
|
|
38903
|
+
assignmentDir = resolve93(baseDir, options.project, "assignments", target);
|
|
38871
38904
|
assignmentRef = target;
|
|
38872
38905
|
projectSlug = options.project;
|
|
38873
38906
|
} else {
|
|
@@ -38879,7 +38912,7 @@ async function commentCommand(target, text, options = {}) {
|
|
|
38879
38912
|
assignmentRef = resolved.standalone ? resolved.id : resolved.assignmentSlug;
|
|
38880
38913
|
projectSlug = resolved.projectSlug;
|
|
38881
38914
|
}
|
|
38882
|
-
const commentsPath =
|
|
38915
|
+
const commentsPath = resolve93(assignmentDir, "comments.md");
|
|
38883
38916
|
const timestamp = nowTimestamp();
|
|
38884
38917
|
const author = options.author ?? process.env.USER ?? "unknown";
|
|
38885
38918
|
let currentContent;
|
|
@@ -38913,7 +38946,7 @@ ${entry}`;
|
|
|
38913
38946
|
}
|
|
38914
38947
|
await writeFileForce(commentsPath, next);
|
|
38915
38948
|
try {
|
|
38916
|
-
const assignmentMd =
|
|
38949
|
+
const assignmentMd = resolve93(assignmentDir, "assignment.md");
|
|
38917
38950
|
if (await fileExists(assignmentMd)) {
|
|
38918
38951
|
const fm = parseAssignmentFrontmatter(await readFile65(assignmentMd, "utf-8"));
|
|
38919
38952
|
emitEvent({
|
|
@@ -38939,7 +38972,7 @@ ${entry}`;
|
|
|
38939
38972
|
}
|
|
38940
38973
|
|
|
38941
38974
|
// src/commands/capture.ts
|
|
38942
|
-
import { resolve as
|
|
38975
|
+
import { resolve as resolve96, relative as relative4, dirname as dirname26 } from "path";
|
|
38943
38976
|
import { copyFile as copyFile3, mkdir as mkdir12, realpath as realpath2, rm as rm14, stat as stat14, writeFile as writeFile15 } from "fs/promises";
|
|
38944
38977
|
import { existsSync as existsSync7 } from "fs";
|
|
38945
38978
|
init_paths();
|
|
@@ -39114,7 +39147,7 @@ init_paths();
|
|
|
39114
39147
|
import { spawn as spawn10 } from "child_process";
|
|
39115
39148
|
import { mkdir as mkdir11, mkdtemp as mkdtemp4, open as open6, readFile as readFile67, rm as rm12, stat as stat13, unlink as unlink12, writeFile as writeFile14 } from "fs/promises";
|
|
39116
39149
|
import { tmpdir as tmpdir5 } from "os";
|
|
39117
|
-
import { join as join24, resolve as
|
|
39150
|
+
import { join as join24, resolve as resolve94 } from "path";
|
|
39118
39151
|
import { setTimeout as sleep } from "timers/promises";
|
|
39119
39152
|
function sigintPollIntervalMs() {
|
|
39120
39153
|
const raw2 = process.env.SYNTAUR_RECORDING_POLL_INTERVAL_MS;
|
|
@@ -39135,13 +39168,13 @@ function sigtermWaitMs() {
|
|
|
39135
39168
|
return Number.isFinite(parsed) && parsed >= 0 ? parsed : 1e3;
|
|
39136
39169
|
}
|
|
39137
39170
|
function pidfilePath() {
|
|
39138
|
-
return
|
|
39171
|
+
return resolve94(syntaurRoot(), "recording.pid");
|
|
39139
39172
|
}
|
|
39140
39173
|
function logPath2() {
|
|
39141
|
-
return
|
|
39174
|
+
return resolve94(syntaurRoot(), "recording.log");
|
|
39142
39175
|
}
|
|
39143
39176
|
function sidecarPath() {
|
|
39144
|
-
return
|
|
39177
|
+
return resolve94(syntaurRoot(), "recording.json");
|
|
39145
39178
|
}
|
|
39146
39179
|
function ffmpegArgs(device, fps, mp4Path) {
|
|
39147
39180
|
return [
|
|
@@ -39420,7 +39453,7 @@ async function stopRecording() {
|
|
|
39420
39453
|
// src/db/proof-db.ts
|
|
39421
39454
|
init_paths();
|
|
39422
39455
|
import Database6 from "better-sqlite3";
|
|
39423
|
-
import { resolve as
|
|
39456
|
+
import { resolve as resolve95 } from "path";
|
|
39424
39457
|
var db5 = null;
|
|
39425
39458
|
var PROOF_SCHEMA_VERSION = "1";
|
|
39426
39459
|
var SCHEMA_SQL5 = `
|
|
@@ -39440,7 +39473,7 @@ CREATE TABLE IF NOT EXISTS meta (key TEXT PRIMARY KEY, value TEXT);
|
|
|
39440
39473
|
`;
|
|
39441
39474
|
function initProofDb(dbPath) {
|
|
39442
39475
|
if (db5) return db5;
|
|
39443
|
-
const finalPath = dbPath ??
|
|
39476
|
+
const finalPath = dbPath ?? resolve95(syntaurRoot(), "syntaur.db");
|
|
39444
39477
|
db5 = new Database6(finalPath);
|
|
39445
39478
|
db5.pragma("journal_mode = WAL");
|
|
39446
39479
|
db5.exec(SCHEMA_SQL5);
|
|
@@ -39868,7 +39901,7 @@ async function captureCommand(target, options = {}) {
|
|
|
39868
39901
|
});
|
|
39869
39902
|
}
|
|
39870
39903
|
if (options.file) {
|
|
39871
|
-
const expanded = options.file.startsWith("~/") ?
|
|
39904
|
+
const expanded = options.file.startsWith("~/") ? resolve96(process.env.HOME ?? "", options.file.slice(2)) : resolve96(options.file);
|
|
39872
39905
|
if (!await fileExists(expanded)) {
|
|
39873
39906
|
throw new Error(`--file does not exist: ${options.file}`);
|
|
39874
39907
|
}
|
|
@@ -39909,7 +39942,7 @@ async function captureCommand(target, options = {}) {
|
|
|
39909
39942
|
}
|
|
39910
39943
|
initProofDb();
|
|
39911
39944
|
const subdir = criterionIndex === null ? "untagged" : String(criterionIndex);
|
|
39912
|
-
const destDir =
|
|
39945
|
+
const destDir = resolve96(proofDir(resolved.assignmentDir), subdir);
|
|
39913
39946
|
if (resolvedSource) await mkdir12(destDir, { recursive: true });
|
|
39914
39947
|
const ext = resolvedSource ? extensionForKind(kind) : null;
|
|
39915
39948
|
let id = null;
|
|
@@ -39918,7 +39951,7 @@ async function captureCommand(target, options = {}) {
|
|
|
39918
39951
|
let lastErr = null;
|
|
39919
39952
|
for (let attempt = 0; attempt < MAX_ID_RETRIES; attempt += 1) {
|
|
39920
39953
|
const candidate = generateArtifactId();
|
|
39921
|
-
const candidateAbsPath = resolvedSource && ext ?
|
|
39954
|
+
const candidateAbsPath = resolvedSource && ext ? resolve96(destDir, `${candidate}.${ext}`) : null;
|
|
39922
39955
|
const candidateRel = candidateAbsPath ? relative4(resolved.assignmentDir, candidateAbsPath) : null;
|
|
39923
39956
|
try {
|
|
39924
39957
|
insertArtifact({
|
|
@@ -39962,7 +39995,7 @@ async function captureCommand(target, options = {}) {
|
|
|
39962
39995
|
}
|
|
39963
39996
|
}
|
|
39964
39997
|
if (options.transcribe && kind === "video" && absPath && id) {
|
|
39965
|
-
const sidecarPath2 =
|
|
39998
|
+
const sidecarPath2 = resolve96(destDir, `${id}.transcript.md`);
|
|
39966
39999
|
if (existsSync7(sidecarPath2)) {
|
|
39967
40000
|
console.warn(
|
|
39968
40001
|
`transcript: ${sidecarPath2} already exists, skipping (delete to re-transcribe)`
|
|
@@ -39994,7 +40027,7 @@ async function captureCommand(target, options = {}) {
|
|
|
39994
40027
|
const tagSuffix = criterionIndex === null ? "untagged" : `criterion ${criterionIndex}`;
|
|
39995
40028
|
console.log(`Captured artifact ${id} (${kind}) for ${ref} \u2014 ${tagSuffix}.`);
|
|
39996
40029
|
if (relativeFilePath) {
|
|
39997
|
-
console.log(` file: ${
|
|
40030
|
+
console.log(` file: ${resolve96(resolved.assignmentDir, relativeFilePath)}`);
|
|
39998
40031
|
}
|
|
39999
40032
|
} catch (err2) {
|
|
40000
40033
|
if (options.stop && kind === "video" && shelloutCleanup && resolvedSource) {
|
|
@@ -40018,7 +40051,7 @@ async function captureCommand(target, options = {}) {
|
|
|
40018
40051
|
// src/commands/proof.ts
|
|
40019
40052
|
import { Command as Command6 } from "commander";
|
|
40020
40053
|
import { readFile as readFile69, writeFile as writeFile16, rename as rename10, stat as stat15 } from "fs/promises";
|
|
40021
|
-
import { resolve as
|
|
40054
|
+
import { resolve as resolve97, relative as relative5, isAbsolute as isAbsolute12, dirname as dirname27 } from "path";
|
|
40022
40055
|
import { randomBytes as randomBytes4 } from "crypto";
|
|
40023
40056
|
|
|
40024
40057
|
// src/utils/acceptance-criteria-parse.ts
|
|
@@ -40258,7 +40291,7 @@ function renderProofHtml(params2, inlineFiles = /* @__PURE__ */ new Map(), trans
|
|
|
40258
40291
|
|
|
40259
40292
|
// src/commands/proof.ts
|
|
40260
40293
|
async function readAssignmentMeta(assignmentDir) {
|
|
40261
|
-
const path =
|
|
40294
|
+
const path = resolve97(assignmentDir, "assignment.md");
|
|
40262
40295
|
if (!await fileExists(path)) {
|
|
40263
40296
|
return { title: "", body: "" };
|
|
40264
40297
|
}
|
|
@@ -40309,7 +40342,7 @@ async function loadInlineFiles(rows, assignmentDir) {
|
|
|
40309
40342
|
for (const r of rows) {
|
|
40310
40343
|
if (!r.file_path) continue;
|
|
40311
40344
|
if (r.kind !== "http" && r.kind !== "text") continue;
|
|
40312
|
-
const abs =
|
|
40345
|
+
const abs = resolve97(assignmentDir, r.file_path);
|
|
40313
40346
|
if (!isWithin(proofRoot, abs)) {
|
|
40314
40347
|
out.set(r.file_path, null);
|
|
40315
40348
|
continue;
|
|
@@ -40336,8 +40369,8 @@ async function loadTranscriptSidecars(rows, assignmentDir) {
|
|
|
40336
40369
|
const proofRoot = proofDir(assignmentDir);
|
|
40337
40370
|
for (const r of rows) {
|
|
40338
40371
|
if (r.kind !== "video" || !r.file_path) continue;
|
|
40339
|
-
const videoAbs =
|
|
40340
|
-
const sidecar =
|
|
40372
|
+
const videoAbs = resolve97(assignmentDir, r.file_path);
|
|
40373
|
+
const sidecar = resolve97(dirname27(videoAbs), `${r.id}.transcript.md`);
|
|
40341
40374
|
if (!isWithin(proofRoot, sidecar)) continue;
|
|
40342
40375
|
if (!await fileExists(sidecar)) continue;
|
|
40343
40376
|
const st = await stat15(sidecar);
|
|
@@ -40377,8 +40410,8 @@ async function proofBuildCommand(target, options = {}) {
|
|
|
40377
40410
|
};
|
|
40378
40411
|
const md = renderProofMarkdown(renderParams);
|
|
40379
40412
|
const html = renderProofHtml(renderParams, inlineFiles, transcriptSidecars);
|
|
40380
|
-
const mdPath =
|
|
40381
|
-
const htmlPath =
|
|
40413
|
+
const mdPath = resolve97(resolved.assignmentDir, "proof.md");
|
|
40414
|
+
const htmlPath = resolve97(resolved.assignmentDir, "proof.html");
|
|
40382
40415
|
await atomicWrite(mdPath, md);
|
|
40383
40416
|
await atomicWrite(htmlPath, html);
|
|
40384
40417
|
console.log(`Wrote ${htmlPath}`);
|
|
@@ -40919,9 +40952,9 @@ function isScheduledSessionLive(sessionId, launchPid) {
|
|
|
40919
40952
|
|
|
40920
40953
|
// src/schedules/launchd.ts
|
|
40921
40954
|
import { execFileSync as execFileSync5 } from "child_process";
|
|
40922
|
-
import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync3, rmSync as rmSync2, realpathSync as
|
|
40955
|
+
import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync3, rmSync as rmSync2, realpathSync as realpathSync5, openSync as openSync2, closeSync as closeSync2 } from "fs";
|
|
40923
40956
|
import { homedir as homedir16, userInfo } from "os";
|
|
40924
|
-
import { dirname as dirname28, join as join26, resolve as
|
|
40957
|
+
import { dirname as dirname28, join as join26, resolve as resolve98 } from "path";
|
|
40925
40958
|
var LAUNCH_AGENT_LABEL = "com.syntaur.schedule.tick";
|
|
40926
40959
|
var LaunchAgentRefusalError = class extends Error {
|
|
40927
40960
|
constructor(message) {
|
|
@@ -40973,9 +41006,9 @@ function defaultAcquireInstallLock(home2) {
|
|
|
40973
41006
|
}
|
|
40974
41007
|
function absolutize(p) {
|
|
40975
41008
|
try {
|
|
40976
|
-
return
|
|
41009
|
+
return realpathSync5(p);
|
|
40977
41010
|
} catch {
|
|
40978
|
-
return
|
|
41011
|
+
return resolve98(p);
|
|
40979
41012
|
}
|
|
40980
41013
|
}
|
|
40981
41014
|
function defaultRun(command, args) {
|
|
@@ -41351,7 +41384,7 @@ init_slug();
|
|
|
41351
41384
|
init_timestamp();
|
|
41352
41385
|
init_assignment_resolver();
|
|
41353
41386
|
init_assignment_todos();
|
|
41354
|
-
import { resolve as
|
|
41387
|
+
import { resolve as resolve99 } from "path";
|
|
41355
41388
|
import { readFile as readFile70 } from "fs/promises";
|
|
41356
41389
|
async function requestCommand(target, text, options = {}) {
|
|
41357
41390
|
if (!text || !text.trim()) {
|
|
@@ -41368,7 +41401,7 @@ async function requestCommand(target, text, options = {}) {
|
|
|
41368
41401
|
if (!isValidSlug(target)) {
|
|
41369
41402
|
throw new Error(`Invalid assignment slug "${target}".`);
|
|
41370
41403
|
}
|
|
41371
|
-
assignmentDir =
|
|
41404
|
+
assignmentDir = resolve99(baseDir, options.project, "assignments", target);
|
|
41372
41405
|
targetRef = target;
|
|
41373
41406
|
} else {
|
|
41374
41407
|
const resolved = await resolveAssignmentById(baseDir, assignmentsDir(), target);
|
|
@@ -41378,7 +41411,7 @@ async function requestCommand(target, text, options = {}) {
|
|
|
41378
41411
|
assignmentDir = resolved.assignmentDir;
|
|
41379
41412
|
targetRef = resolved.standalone ? resolved.id : resolved.assignmentSlug;
|
|
41380
41413
|
}
|
|
41381
|
-
const assignmentMdPath2 =
|
|
41414
|
+
const assignmentMdPath2 = resolve99(assignmentDir, "assignment.md");
|
|
41382
41415
|
if (!await fileExists(assignmentMdPath2)) {
|
|
41383
41416
|
throw new Error(`assignment.md not found at ${assignmentMdPath2}`);
|
|
41384
41417
|
}
|
|
@@ -41399,9 +41432,9 @@ init_config2();
|
|
|
41399
41432
|
init_recompute();
|
|
41400
41433
|
import { Command as Command10 } from "commander";
|
|
41401
41434
|
import { readFile as readFile71, readdir as readdir34 } from "fs/promises";
|
|
41402
|
-
import { resolve as
|
|
41435
|
+
import { resolve as resolve100 } from "path";
|
|
41403
41436
|
async function readContextAssignmentDir(cwd) {
|
|
41404
|
-
const path =
|
|
41437
|
+
const path = resolve100(cwd, ".syntaur", "context.json");
|
|
41405
41438
|
if (!await fileExists(path)) return null;
|
|
41406
41439
|
try {
|
|
41407
41440
|
const raw2 = await readFile71(path, "utf-8");
|
|
@@ -41418,9 +41451,9 @@ async function resolveAssignmentDir(opts) {
|
|
|
41418
41451
|
const cwd = opts.cwd ?? process.cwd();
|
|
41419
41452
|
if (opts.assignment) {
|
|
41420
41453
|
if (opts.project) {
|
|
41421
|
-
return
|
|
41454
|
+
return resolve100((await readConfig()).defaultProjectDir, opts.project, "assignments", opts.assignment);
|
|
41422
41455
|
}
|
|
41423
|
-
return
|
|
41456
|
+
return resolve100(assignmentsDir(), opts.assignment);
|
|
41424
41457
|
}
|
|
41425
41458
|
const fromCtx = await readContextAssignmentDir(cwd);
|
|
41426
41459
|
if (fromCtx) return fromCtx;
|
|
@@ -41616,11 +41649,11 @@ async function runPlanCreate(options) {
|
|
|
41616
41649
|
if (!await fileExists(assignmentDir)) {
|
|
41617
41650
|
throw new Error(`Assignment directory does not exist: ${assignmentDir}`);
|
|
41618
41651
|
}
|
|
41619
|
-
const assignmentMdPath2 =
|
|
41652
|
+
const assignmentMdPath2 = resolve100(assignmentDir, "assignment.md");
|
|
41620
41653
|
if (!await fileExists(assignmentMdPath2)) {
|
|
41621
41654
|
throw new Error(`Missing assignment.md at: ${assignmentMdPath2}`);
|
|
41622
41655
|
}
|
|
41623
|
-
const planPath =
|
|
41656
|
+
const planPath = resolve100(assignmentDir, "plan.md");
|
|
41624
41657
|
if (await fileExists(planPath) && !options.force) {
|
|
41625
41658
|
throw new Error(
|
|
41626
41659
|
"plan.md already exists. Use --force to overwrite, or `syntaur plan version` to create the next version."
|
|
@@ -41647,7 +41680,7 @@ async function runPlanVersion(options) {
|
|
|
41647
41680
|
if (!await fileExists(assignmentDir)) {
|
|
41648
41681
|
throw new Error(`Assignment directory does not exist: ${assignmentDir}`);
|
|
41649
41682
|
}
|
|
41650
|
-
const assignmentMdPath2 =
|
|
41683
|
+
const assignmentMdPath2 = resolve100(assignmentDir, "assignment.md");
|
|
41651
41684
|
if (!await fileExists(assignmentMdPath2)) {
|
|
41652
41685
|
throw new Error(`Missing assignment.md at: ${assignmentMdPath2}`);
|
|
41653
41686
|
}
|
|
@@ -41659,14 +41692,14 @@ async function runPlanVersion(options) {
|
|
|
41659
41692
|
}
|
|
41660
41693
|
const current = planFiles[planFiles.length - 1];
|
|
41661
41694
|
const next = nextPlanFileName(current.version);
|
|
41662
|
-
const newPath =
|
|
41695
|
+
const newPath = resolve100(assignmentDir, next.fileName);
|
|
41663
41696
|
if (await fileExists(newPath) && !options.force) {
|
|
41664
41697
|
throw new Error(`${next.fileName} already exists. Use --force to overwrite.`);
|
|
41665
41698
|
}
|
|
41666
41699
|
const assignmentMd = await readFile71(assignmentMdPath2, "utf-8");
|
|
41667
41700
|
const slugMatch = assignmentMd.match(/^slug:\s*(.+?)\s*$/m);
|
|
41668
41701
|
const slug = slugMatch ? slugMatch[1].trim() : assignmentDir.split("/").pop() ?? "";
|
|
41669
|
-
const oldPlanPath =
|
|
41702
|
+
const oldPlanPath = resolve100(assignmentDir, current.fileName);
|
|
41670
41703
|
const oldPlanContent = await readFile71(oldPlanPath, "utf-8");
|
|
41671
41704
|
const oldBody = oldPlanContent.replace(/^---[\s\S]*?\n---\n?/, "");
|
|
41672
41705
|
const carriedTodos = extractUncheckedTodos(oldBody);
|
|
@@ -41739,9 +41772,9 @@ init_session_db();
|
|
|
41739
41772
|
init_agent_sessions();
|
|
41740
41773
|
import { Command as Command11 } from "commander";
|
|
41741
41774
|
import { readFile as readFile72, readdir as readdir35, stat as stat16 } from "fs/promises";
|
|
41742
|
-
import { resolve as
|
|
41775
|
+
import { resolve as resolve101 } from "path";
|
|
41743
41776
|
async function readContext(cwd) {
|
|
41744
|
-
const path =
|
|
41777
|
+
const path = resolve101(cwd, ".syntaur", "context.json");
|
|
41745
41778
|
if (!await fileExists(path)) return null;
|
|
41746
41779
|
try {
|
|
41747
41780
|
const raw2 = await readFile72(path, "utf-8");
|
|
@@ -41751,13 +41784,13 @@ async function readContext(cwd) {
|
|
|
41751
41784
|
}
|
|
41752
41785
|
}
|
|
41753
41786
|
async function findLatestSessionSummary(assignmentDir) {
|
|
41754
|
-
const sessionsRoot =
|
|
41787
|
+
const sessionsRoot = resolve101(assignmentDir, "sessions");
|
|
41755
41788
|
if (!await fileExists(sessionsRoot)) return null;
|
|
41756
41789
|
const entries = await readdir35(sessionsRoot, { withFileTypes: true });
|
|
41757
41790
|
let best = null;
|
|
41758
41791
|
for (const entry of entries) {
|
|
41759
41792
|
if (!entry.isDirectory()) continue;
|
|
41760
|
-
const summaryPath =
|
|
41793
|
+
const summaryPath = resolve101(sessionsRoot, entry.name, "summary.md");
|
|
41761
41794
|
if (!await fileExists(summaryPath)) continue;
|
|
41762
41795
|
const st = await stat16(summaryPath);
|
|
41763
41796
|
if (best === null || st.mtime.getTime() > best.mtime.getTime()) {
|
|
@@ -41767,7 +41800,7 @@ async function findLatestSessionSummary(assignmentDir) {
|
|
|
41767
41800
|
return best;
|
|
41768
41801
|
}
|
|
41769
41802
|
async function findOpenHandoff(assignmentDir) {
|
|
41770
|
-
const handoffPath =
|
|
41803
|
+
const handoffPath = resolve101(assignmentDir, "handoff.md");
|
|
41771
41804
|
if (!await fileExists(handoffPath)) return null;
|
|
41772
41805
|
const content = await readFile72(handoffPath, "utf-8");
|
|
41773
41806
|
const body = content.replace(/^---[\s\S]*?\n---\n?/, "").trim();
|
|
@@ -41864,7 +41897,7 @@ async function resolveSaveTarget(options, cwd) {
|
|
|
41864
41897
|
let slug;
|
|
41865
41898
|
const ctx = await readContext(cwd);
|
|
41866
41899
|
if (options.assignment) {
|
|
41867
|
-
assignmentDir = options.project ?
|
|
41900
|
+
assignmentDir = options.project ? resolve101((await readConfig()).defaultProjectDir, options.project, "assignments", options.assignment) : resolve101(assignmentsDir(), options.assignment);
|
|
41868
41901
|
slug = options.assignment;
|
|
41869
41902
|
} else {
|
|
41870
41903
|
if (!ctx?.assignmentDir) {
|
|
@@ -41921,11 +41954,11 @@ function extractCreated(content) {
|
|
|
41921
41954
|
}
|
|
41922
41955
|
async function runSessionSave(options, cwd = process.cwd(), body) {
|
|
41923
41956
|
const { assignmentDir, slug, sessionId } = await resolveSaveTarget(options, cwd);
|
|
41924
|
-
if (!await fileExists(
|
|
41957
|
+
if (!await fileExists(resolve101(assignmentDir, "assignment.md"))) {
|
|
41925
41958
|
throw new Error(`No assignment found at ${assignmentDir} (missing assignment.md).`);
|
|
41926
41959
|
}
|
|
41927
|
-
const sessionDir =
|
|
41928
|
-
const summaryPath =
|
|
41960
|
+
const sessionDir = resolve101(assignmentDir, "sessions", sessionId);
|
|
41961
|
+
const summaryPath = resolve101(sessionDir, "summary.md");
|
|
41929
41962
|
const now = nowTimestamp();
|
|
41930
41963
|
let created = now;
|
|
41931
41964
|
if (await fileExists(summaryPath)) {
|
|
@@ -41935,7 +41968,7 @@ async function runSessionSave(options, cwd = process.cwd(), body) {
|
|
|
41935
41968
|
let sectionBody2 = body;
|
|
41936
41969
|
if (sectionBody2 === void 0) {
|
|
41937
41970
|
if (options.fromFile) {
|
|
41938
|
-
sectionBody2 = await readFile72(
|
|
41971
|
+
sectionBody2 = await readFile72(resolve101(cwd, options.fromFile), "utf-8");
|
|
41939
41972
|
} else {
|
|
41940
41973
|
sectionBody2 = await readStdin();
|
|
41941
41974
|
}
|
|
@@ -41971,7 +42004,7 @@ async function runSessionRegister(rawStdin, options = {}, deps = {}) {
|
|
|
41971
42004
|
if (!isSafeSessionId(sessionId) || !cwd) return result;
|
|
41972
42005
|
result.sessionId = sessionId;
|
|
41973
42006
|
const transcriptPath = payload.transcript_path ?? "";
|
|
41974
|
-
const contextPath =
|
|
42007
|
+
const contextPath = resolve101(cwd, ".syntaur", "context.json");
|
|
41975
42008
|
const hasContextFile = await fileExists(contextPath);
|
|
41976
42009
|
const ctx = hasContextFile ? await readContext(cwd) : null;
|
|
41977
42010
|
if (ctx) {
|
|
@@ -42124,17 +42157,7 @@ init_paths();
|
|
|
42124
42157
|
init_config2();
|
|
42125
42158
|
init_assignment_walk();
|
|
42126
42159
|
init_state_machine();
|
|
42127
|
-
|
|
42128
|
-
// src/utils/path-canon.ts
|
|
42129
|
-
import { realpathSync as realpathSync5 } from "fs";
|
|
42130
|
-
import { resolve as resolve101 } from "path";
|
|
42131
|
-
function canonicalPath(p) {
|
|
42132
|
-
try {
|
|
42133
|
-
return realpathSync5(resolve101(p));
|
|
42134
|
-
} catch {
|
|
42135
|
-
return resolve101(p).replace(/\/+$/, "");
|
|
42136
|
-
}
|
|
42137
|
-
}
|
|
42160
|
+
init_path_canon();
|
|
42138
42161
|
|
|
42139
42162
|
// src/utils/session-count.ts
|
|
42140
42163
|
import Database7 from "better-sqlite3";
|