syntaur 0.8.0 → 0.12.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 +9 -1
- package/dashboard/dist/assets/{_basePickBy-CIZortGD.js → _basePickBy-XOV2F7dX.js} +1 -1
- package/dashboard/dist/assets/{_baseUniq-BHP5NBQ7.js → _baseUniq-Dccfk3fK.js} +1 -1
- package/dashboard/dist/assets/{arc-BLtQy7Cl.js → arc-TwJ5RF-H.js} +1 -1
- package/dashboard/dist/assets/{architectureDiagram-2XIMDMQ5-0mhIBjWy.js → architectureDiagram-2XIMDMQ5-CpkVJudw.js} +1 -1
- package/dashboard/dist/assets/{blockDiagram-WCTKOSBZ-CM7K5Tf5.js → blockDiagram-WCTKOSBZ-Ck6VQ4Fh.js} +1 -1
- package/dashboard/dist/assets/{c4Diagram-IC4MRINW-gsbeygvS.js → c4Diagram-IC4MRINW-B5V7YG03.js} +1 -1
- package/dashboard/dist/assets/channel-AEMTX70R.js +1 -0
- package/dashboard/dist/assets/{chunk-4BX2VUAB-CneRz9Nd.js → chunk-4BX2VUAB-rBdyOxAe.js} +1 -1
- package/dashboard/dist/assets/{chunk-55IACEB6-uetANWHd.js → chunk-55IACEB6-DKlNXjYt.js} +1 -1
- package/dashboard/dist/assets/{chunk-FMBD7UC4-3-tNszoF.js → chunk-FMBD7UC4-Cqm0PtUI.js} +1 -1
- package/dashboard/dist/assets/{chunk-JSJVCQXG-DOO88rZD.js → chunk-JSJVCQXG-CQyXQcG3.js} +1 -1
- package/dashboard/dist/assets/{chunk-KX2RTZJC-Bnc1CFy2.js → chunk-KX2RTZJC-DmqjHPpJ.js} +1 -1
- package/dashboard/dist/assets/{chunk-NQ4KR5QH-BfViC1Ms.js → chunk-NQ4KR5QH-CHXoBcYa.js} +1 -1
- package/dashboard/dist/assets/{chunk-QZHKN3VN-CgjyAt2l.js → chunk-QZHKN3VN-Dd4sChBS.js} +1 -1
- package/dashboard/dist/assets/{chunk-WL4C6EOR-BYFermSR.js → chunk-WL4C6EOR-D-QLnkY8.js} +1 -1
- package/dashboard/dist/assets/classDiagram-VBA2DB6C-LzuOAGzu.js +1 -0
- package/dashboard/dist/assets/classDiagram-v2-RAHNMMFH-LzuOAGzu.js +1 -0
- package/dashboard/dist/assets/clone-Cw63QGUJ.js +1 -0
- package/dashboard/dist/assets/{cose-bilkent-S5V4N54A-CE-k5SLv.js → cose-bilkent-S5V4N54A-VZi6uV56.js} +1 -1
- package/dashboard/dist/assets/{dagre-KLK3FWXG-CX7Br8LQ.js → dagre-KLK3FWXG-CtT97Qhx.js} +1 -1
- package/dashboard/dist/assets/{diagram-E7M64L7V-t-xhWjCU.js → diagram-E7M64L7V-BjYTNNHb.js} +1 -1
- package/dashboard/dist/assets/{diagram-IFDJBPK2-BVhcTXsJ.js → diagram-IFDJBPK2-qj8_r6fb.js} +1 -1
- package/dashboard/dist/assets/{diagram-P4PSJMXO-fxt8ZSca.js → diagram-P4PSJMXO-DlfWo7Vt.js} +1 -1
- package/dashboard/dist/assets/{erDiagram-INFDFZHY-C20k2bxX.js → erDiagram-INFDFZHY-Ch_nApTv.js} +1 -1
- package/dashboard/dist/assets/{flowDiagram-PKNHOUZH-CdeygexM.js → flowDiagram-PKNHOUZH-EOVsqNyi.js} +1 -1
- package/dashboard/dist/assets/{ganttDiagram-A5KZAMGK-CPsoOAV-.js → ganttDiagram-A5KZAMGK-CS-lx0B-.js} +1 -1
- package/dashboard/dist/assets/{gitGraphDiagram-K3NZZRJ6-t0tCTIZy.js → gitGraphDiagram-K3NZZRJ6-Ba6RDzPy.js} +1 -1
- package/dashboard/dist/assets/{graph-Bcqd31wL.js → graph-BKaAyLk-.js} +1 -1
- package/dashboard/dist/assets/index-BTWPZaIA.css +1 -0
- package/dashboard/dist/assets/index-Dk9PBm5B.js +510 -0
- package/dashboard/dist/assets/{infoDiagram-LFFYTUFH-DgoKvH3N.js → infoDiagram-LFFYTUFH-Cr20xEsd.js} +1 -1
- package/dashboard/dist/assets/{ishikawaDiagram-PHBUUO56-CGr4P8do.js → ishikawaDiagram-PHBUUO56-CuILV9ph.js} +1 -1
- package/dashboard/dist/assets/{journeyDiagram-4ABVD52K-CHYRi6wF.js → journeyDiagram-4ABVD52K-CO-l7Mpm.js} +1 -1
- package/dashboard/dist/assets/{kanban-definition-K7BYSVSG-kwzqrFcW.js → kanban-definition-K7BYSVSG-CcirPw_S.js} +1 -1
- package/dashboard/dist/assets/{layout-wud47qGs.js → layout-BXvr8dMw.js} +1 -1
- package/dashboard/dist/assets/{linear-DG5js90X.js → linear-B85hgYnX.js} +1 -1
- package/dashboard/dist/assets/{mermaid.core-BDw69uC2.js → mermaid.core-DcZN9Xp2.js} +4 -4
- package/dashboard/dist/assets/{mindmap-definition-YRQLILUH-Dw_uyg1-.js → mindmap-definition-YRQLILUH-Bxi6p5_3.js} +1 -1
- package/dashboard/dist/assets/{pieDiagram-SKSYHLDU-C7NBi6tK.js → pieDiagram-SKSYHLDU-DOSvU0UD.js} +1 -1
- package/dashboard/dist/assets/{quadrantDiagram-337W2JSQ-_N_BSBd4.js → quadrantDiagram-337W2JSQ-Cmo-5tW9.js} +1 -1
- package/dashboard/dist/assets/{requirementDiagram-Z7DCOOCP-BqUiqfP1.js → requirementDiagram-Z7DCOOCP-Dw8alwuI.js} +1 -1
- package/dashboard/dist/assets/{sankeyDiagram-WA2Y5GQK-C2Qq5ULW.js → sankeyDiagram-WA2Y5GQK-ZPB-rzOg.js} +1 -1
- package/dashboard/dist/assets/{sequenceDiagram-2WXFIKYE-BOCF2z8f.js → sequenceDiagram-2WXFIKYE-Ct8bkK2h.js} +1 -1
- package/dashboard/dist/assets/{stateDiagram-RAJIS63D-BvDyTxC5.js → stateDiagram-RAJIS63D-DnGOXlmx.js} +1 -1
- package/dashboard/dist/assets/stateDiagram-v2-FVOUBMTO-COGzlZxn.js +1 -0
- package/dashboard/dist/assets/{timeline-definition-YZTLITO2-DNNZxSrG.js → timeline-definition-YZTLITO2-AUFmbJjr.js} +1 -1
- package/dashboard/dist/assets/{treemap-KZPCXAKY-C6hOdiGH.js → treemap-KZPCXAKY-Dw5FDFAV.js} +1 -1
- package/dashboard/dist/assets/{vennDiagram-LZ73GAT5-FmXl6puP.js → vennDiagram-LZ73GAT5-DfxicU4N.js} +1 -1
- package/dashboard/dist/assets/{xychartDiagram-JWTSCODW-Bjav12WG.js → xychartDiagram-JWTSCODW--9N0V1r_.js} +1 -1
- package/dashboard/dist/index.html +2 -2
- package/dashboard/dist/syntaur-logo.svg +5 -13
- package/dist/dashboard/server.js +363 -3
- package/dist/dashboard/server.js.map +1 -1
- package/dist/index.js +2140 -153
- package/dist/index.js.map +1 -1
- package/examples/playbooks/keep-records-updated.md +2 -1
- package/package.json +1 -1
- package/platforms/claude-code/.claude-plugin/plugin.json +9 -1
- package/platforms/claude-code/agents/syntaur-expert.md +1 -1
- package/platforms/claude-code/commands/add-memory/add-memory.md +18 -0
- package/platforms/claude-code/commands/add-resource/add-resource.md +16 -0
- package/platforms/claude-code/commands/list-assignments/list-assignments.md +16 -0
- package/platforms/claude-code/commands/log-progress/log-progress.md +16 -0
- package/platforms/claude-code/commands/replan/replan.md +16 -0
- package/platforms/claude-code/commands/resume-session/resume-session.md +16 -0
- package/platforms/claude-code/commands/set-workspace/set-workspace.md +16 -0
- package/platforms/claude-code/commands/syntaur-worktree/syntaur-worktree.md +16 -0
- package/platforms/claude-code/references/protocol-summary.md +8 -0
- package/platforms/claude-code/skills/add-memory/SKILL.md +96 -0
- package/platforms/claude-code/skills/add-resource/SKILL.md +85 -0
- package/platforms/claude-code/skills/capture-artifacts/SKILL.md +84 -0
- package/platforms/claude-code/skills/complete-assignment/SKILL.md +2 -1
- package/platforms/claude-code/skills/list-assignments/SKILL.md +73 -0
- package/platforms/claude-code/skills/log-progress/SKILL.md +128 -0
- package/platforms/claude-code/skills/plan-assignment/SKILL.md +29 -8
- package/platforms/claude-code/skills/replan/SKILL.md +113 -0
- package/platforms/claude-code/skills/resume-session/SKILL.md +83 -0
- package/platforms/claude-code/skills/set-workspace/SKILL.md +109 -0
- package/platforms/claude-code/skills/syntaur-protocol/SKILL.md +4 -0
- package/platforms/claude-code/skills/syntaur-protocol/references/protocol-summary.md +8 -0
- package/platforms/claude-code/skills/syntaur-worktree/SKILL.md +117 -0
- package/platforms/codex/README.md +2 -2
- package/platforms/codex/agents/syntaur-operator.md +7 -0
- package/platforms/codex/commands/add-memory.md +16 -0
- package/platforms/codex/commands/add-resource.md +14 -0
- package/platforms/codex/commands/list-assignments.md +13 -0
- package/platforms/codex/commands/log-progress.md +14 -0
- package/platforms/codex/commands/replan.md +15 -0
- package/platforms/codex/commands/resume-session.md +15 -0
- package/platforms/codex/commands/set-workspace.md +15 -0
- package/platforms/codex/commands/syntaur-worktree.md +15 -0
- package/platforms/codex/references/protocol-summary.md +8 -0
- package/platforms/codex/skills/add-memory/SKILL.md +96 -0
- package/platforms/codex/skills/add-resource/SKILL.md +85 -0
- package/platforms/codex/skills/capture-artifacts/SKILL.md +84 -0
- package/platforms/codex/skills/complete-assignment/SKILL.md +2 -1
- package/platforms/codex/skills/list-assignments/SKILL.md +73 -0
- package/platforms/codex/skills/log-progress/SKILL.md +128 -0
- package/platforms/codex/skills/plan-assignment/SKILL.md +29 -8
- package/platforms/codex/skills/replan/SKILL.md +113 -0
- package/platforms/codex/skills/resume-session/SKILL.md +83 -0
- package/platforms/codex/skills/set-workspace/SKILL.md +109 -0
- package/platforms/codex/skills/syntaur-protocol/SKILL.md +4 -0
- package/platforms/codex/skills/syntaur-protocol/references/protocol-summary.md +8 -0
- package/platforms/codex/skills/syntaur-worktree/SKILL.md +117 -0
- package/skills/add-memory/SKILL.md +96 -0
- package/skills/add-resource/SKILL.md +85 -0
- package/skills/capture-artifacts/SKILL.md +84 -0
- package/skills/complete-assignment/SKILL.md +2 -1
- package/skills/list-assignments/SKILL.md +73 -0
- package/skills/log-progress/SKILL.md +128 -0
- package/skills/plan-assignment/SKILL.md +29 -8
- package/skills/replan/SKILL.md +113 -0
- package/skills/resume-session/SKILL.md +83 -0
- package/skills/set-workspace/SKILL.md +109 -0
- package/skills/syntaur-protocol/SKILL.md +4 -0
- package/skills/syntaur-protocol/references/protocol-summary.md +8 -0
- package/skills/syntaur-worktree/SKILL.md +117 -0
- package/dashboard/dist/assets/channel-FWLgstBg.js +0 -1
- package/dashboard/dist/assets/classDiagram-VBA2DB6C-BAvQTSn_.js +0 -1
- package/dashboard/dist/assets/classDiagram-v2-RAHNMMFH-BAvQTSn_.js +0 -1
- package/dashboard/dist/assets/clone-rSEllQ1P.js +0 -1
- package/dashboard/dist/assets/index-bLWoSCLL.css +0 -1
- package/dashboard/dist/assets/index-eS0wtDO0.js +0 -500
- package/dashboard/dist/assets/stateDiagram-v2-FVOUBMTO-TaLLhLWD.js +0 -1
package/dist/dashboard/server.js
CHANGED
|
@@ -16,6 +16,7 @@ __export(paths_exports, {
|
|
|
16
16
|
expandHome: () => expandHome,
|
|
17
17
|
playbooksDir: () => playbooksDir,
|
|
18
18
|
projectTodosDir: () => projectTodosDir,
|
|
19
|
+
proofDir: () => proofDir,
|
|
19
20
|
serversDir: () => serversDir,
|
|
20
21
|
syntaurRoot: () => syntaurRoot,
|
|
21
22
|
todoPlanDir: () => todoPlanDir,
|
|
@@ -57,6 +58,9 @@ function projectTodosDir(projectsDir, projectSlug) {
|
|
|
57
58
|
function todoPlanDir(todosDir2, workspaceOrProject, todoId) {
|
|
58
59
|
return resolve(todosDir2, "plans", workspaceOrProject, todoId);
|
|
59
60
|
}
|
|
61
|
+
function proofDir(assignmentDir) {
|
|
62
|
+
return resolve(assignmentDir, "proof");
|
|
63
|
+
}
|
|
60
64
|
var init_paths = __esm({
|
|
61
65
|
"src/utils/paths.ts"() {
|
|
62
66
|
"use strict";
|
|
@@ -2071,6 +2075,7 @@ function parseMemory(fileContent) {
|
|
|
2071
2075
|
scope: getField(fm, "scope") ?? "",
|
|
2072
2076
|
sourceAssignment: getField(fm, "sourceAssignment"),
|
|
2073
2077
|
relatedAssignments: parseListField(fm, "relatedAssignments"),
|
|
2078
|
+
tags: parseListField(fm, "tags"),
|
|
2074
2079
|
created: getField(fm, "created") ?? "",
|
|
2075
2080
|
updated: getField(fm, "updated") ?? "",
|
|
2076
2081
|
body
|
|
@@ -3269,7 +3274,7 @@ var init_scanner = __esm({
|
|
|
3269
3274
|
|
|
3270
3275
|
// src/dashboard/api.ts
|
|
3271
3276
|
import { readdir as readdir6, readFile as readFile8, writeFile as writeFile3 } from "fs/promises";
|
|
3272
|
-
import { resolve as resolve9, dirname as dirname2 } from "path";
|
|
3277
|
+
import { resolve as resolve9, dirname as dirname2, basename } from "path";
|
|
3273
3278
|
async function listStandaloneRecords(assignmentsDir2) {
|
|
3274
3279
|
if (!assignmentsDir2) return [];
|
|
3275
3280
|
if (!await fileExists(assignmentsDir2)) return [];
|
|
@@ -4108,12 +4113,102 @@ async function listMemories(projectPath) {
|
|
|
4108
4113
|
source: parsed.source,
|
|
4109
4114
|
scope: parsed.scope,
|
|
4110
4115
|
sourceAssignment: parsed.sourceAssignment,
|
|
4116
|
+
relatedAssignments: parsed.relatedAssignments,
|
|
4111
4117
|
updated: parsed.updated
|
|
4112
4118
|
});
|
|
4113
4119
|
}
|
|
4114
4120
|
results.sort((left, right) => compareTimestamps(right.updated, left.updated));
|
|
4115
4121
|
return results;
|
|
4116
4122
|
}
|
|
4123
|
+
async function listAllMemories(projectsDir) {
|
|
4124
|
+
const projectRecords = await listProjectRecords(projectsDir);
|
|
4125
|
+
const all = [];
|
|
4126
|
+
for (const record of projectRecords) {
|
|
4127
|
+
const memories = await listMemories(record.projectPath);
|
|
4128
|
+
for (const memory of memories) {
|
|
4129
|
+
all.push({
|
|
4130
|
+
...memory,
|
|
4131
|
+
projectSlug: basename(record.projectPath),
|
|
4132
|
+
projectTitle: record.summary.title
|
|
4133
|
+
});
|
|
4134
|
+
}
|
|
4135
|
+
}
|
|
4136
|
+
all.sort((left, right) => compareTimestamps(right.updated, left.updated));
|
|
4137
|
+
return all;
|
|
4138
|
+
}
|
|
4139
|
+
async function listAllResources(projectsDir) {
|
|
4140
|
+
const projectRecords = await listProjectRecords(projectsDir);
|
|
4141
|
+
const all = [];
|
|
4142
|
+
for (const record of projectRecords) {
|
|
4143
|
+
const resources = await listResources(record.projectPath);
|
|
4144
|
+
for (const resource of resources) {
|
|
4145
|
+
all.push({
|
|
4146
|
+
...resource,
|
|
4147
|
+
projectSlug: basename(record.projectPath),
|
|
4148
|
+
projectTitle: record.summary.title
|
|
4149
|
+
});
|
|
4150
|
+
}
|
|
4151
|
+
}
|
|
4152
|
+
all.sort((left, right) => compareTimestamps(right.updated, left.updated));
|
|
4153
|
+
return all;
|
|
4154
|
+
}
|
|
4155
|
+
async function resolveProjectPath(projectsDir, projectSlug) {
|
|
4156
|
+
const direct = resolve9(projectsDir, projectSlug);
|
|
4157
|
+
if (await fileExists(resolve9(direct, "project.md"))) return direct;
|
|
4158
|
+
const records = await listProjectRecords(projectsDir);
|
|
4159
|
+
const match = records.find((r) => r.summary.slug === projectSlug);
|
|
4160
|
+
return match ? match.projectPath : null;
|
|
4161
|
+
}
|
|
4162
|
+
async function getMemoryDetail(projectsDir, projectSlug, itemSlug) {
|
|
4163
|
+
if (itemSlug.startsWith("_")) return null;
|
|
4164
|
+
const projectRecords = await listProjectRecords(projectsDir);
|
|
4165
|
+
const projectRecord = projectRecords.find(
|
|
4166
|
+
(p) => basename(p.projectPath) === projectSlug || p.summary.slug === projectSlug
|
|
4167
|
+
);
|
|
4168
|
+
if (!projectRecord) return null;
|
|
4169
|
+
const filePath = resolve9(projectRecord.projectPath, "memories", `${itemSlug}.md`);
|
|
4170
|
+
if (!await fileExists(filePath)) return null;
|
|
4171
|
+
const content = await readFile8(filePath, "utf-8");
|
|
4172
|
+
const parsed = parseMemory(content);
|
|
4173
|
+
return {
|
|
4174
|
+
name: parsed.name,
|
|
4175
|
+
slug: itemSlug,
|
|
4176
|
+
source: parsed.source,
|
|
4177
|
+
scope: parsed.scope,
|
|
4178
|
+
sourceAssignment: parsed.sourceAssignment,
|
|
4179
|
+
relatedAssignments: parsed.relatedAssignments,
|
|
4180
|
+
updated: parsed.updated,
|
|
4181
|
+
created: parsed.created,
|
|
4182
|
+
body: parsed.body,
|
|
4183
|
+
tags: parsed.tags,
|
|
4184
|
+
projectSlug: basename(projectRecord.projectPath),
|
|
4185
|
+
projectTitle: projectRecord.summary.title
|
|
4186
|
+
};
|
|
4187
|
+
}
|
|
4188
|
+
async function getResourceDetail(projectsDir, projectSlug, itemSlug) {
|
|
4189
|
+
if (itemSlug.startsWith("_")) return null;
|
|
4190
|
+
const projectRecords = await listProjectRecords(projectsDir);
|
|
4191
|
+
const projectRecord = projectRecords.find(
|
|
4192
|
+
(p) => basename(p.projectPath) === projectSlug || p.summary.slug === projectSlug
|
|
4193
|
+
);
|
|
4194
|
+
if (!projectRecord) return null;
|
|
4195
|
+
const filePath = resolve9(projectRecord.projectPath, "resources", `${itemSlug}.md`);
|
|
4196
|
+
if (!await fileExists(filePath)) return null;
|
|
4197
|
+
const content = await readFile8(filePath, "utf-8");
|
|
4198
|
+
const parsed = parseResource(content);
|
|
4199
|
+
return {
|
|
4200
|
+
name: parsed.name,
|
|
4201
|
+
slug: itemSlug,
|
|
4202
|
+
category: parsed.category,
|
|
4203
|
+
source: parsed.source,
|
|
4204
|
+
relatedAssignments: parsed.relatedAssignments,
|
|
4205
|
+
updated: parsed.updated,
|
|
4206
|
+
created: parsed.created,
|
|
4207
|
+
body: parsed.body,
|
|
4208
|
+
projectSlug: basename(projectRecord.projectPath),
|
|
4209
|
+
projectTitle: projectRecord.summary.title
|
|
4210
|
+
};
|
|
4211
|
+
}
|
|
4117
4212
|
async function loadDependencyGraph(projectPath, assignments) {
|
|
4118
4213
|
const statusPath = resolve9(projectPath, "_status.md");
|
|
4119
4214
|
if (await fileExists(statusPath)) {
|
|
@@ -4449,6 +4544,10 @@ function getDocumentPath(projectsDir, documentType, projectSlug, assignmentSlug)
|
|
|
4449
4544
|
return assignmentSlug ? resolve9(projectsDir, projectSlug, "assignments", assignmentSlug, "handoff.md") : null;
|
|
4450
4545
|
case "decision-record":
|
|
4451
4546
|
return assignmentSlug ? resolve9(projectsDir, projectSlug, "assignments", assignmentSlug, "decision-record.md") : null;
|
|
4547
|
+
case "memory":
|
|
4548
|
+
return assignmentSlug ? resolve9(projectsDir, projectSlug, "memories", `${assignmentSlug}.md`) : null;
|
|
4549
|
+
case "resource":
|
|
4550
|
+
return assignmentSlug ? resolve9(projectsDir, projectSlug, "resources", `${assignmentSlug}.md`) : null;
|
|
4452
4551
|
default:
|
|
4453
4552
|
return null;
|
|
4454
4553
|
}
|
|
@@ -4469,6 +4568,10 @@ function getEditableDocumentTitle(documentType, projectSlug, assignmentSlug) {
|
|
|
4469
4568
|
return `Append Decision: ${assignmentSlug || "assignment"}`;
|
|
4470
4569
|
case "playbook":
|
|
4471
4570
|
return `Edit Playbook: ${projectSlug}`;
|
|
4571
|
+
case "memory":
|
|
4572
|
+
return `Edit Memory: ${assignmentSlug || "memory"}`;
|
|
4573
|
+
case "resource":
|
|
4574
|
+
return `Edit Resource: ${assignmentSlug || "resource"}`;
|
|
4472
4575
|
default:
|
|
4473
4576
|
return projectSlug;
|
|
4474
4577
|
}
|
|
@@ -4910,6 +5013,40 @@ var init_decision_record = __esm({
|
|
|
4910
5013
|
});
|
|
4911
5014
|
|
|
4912
5015
|
// src/templates/index-stubs.ts
|
|
5016
|
+
function renderMemoryStub(params2) {
|
|
5017
|
+
return `---
|
|
5018
|
+
type: memory
|
|
5019
|
+
name: ${escapeYamlString(params2.name)}
|
|
5020
|
+
source: claude
|
|
5021
|
+
sourceAssignment: null
|
|
5022
|
+
relatedAssignments: []
|
|
5023
|
+
scope: project
|
|
5024
|
+
created: "${params2.timestamp}"
|
|
5025
|
+
updated: "${params2.timestamp}"
|
|
5026
|
+
tags: []
|
|
5027
|
+
---
|
|
5028
|
+
|
|
5029
|
+
# ${params2.name}
|
|
5030
|
+
|
|
5031
|
+
`;
|
|
5032
|
+
}
|
|
5033
|
+
function renderResourceStub(params2) {
|
|
5034
|
+
return `---
|
|
5035
|
+
type: resource
|
|
5036
|
+
name: ${escapeYamlString(params2.name)}
|
|
5037
|
+
source: claude
|
|
5038
|
+
category: documentation
|
|
5039
|
+
sourceUrl: null
|
|
5040
|
+
sourceAssignment: null
|
|
5041
|
+
relatedAssignments: []
|
|
5042
|
+
created: "${params2.timestamp}"
|
|
5043
|
+
updated: "${params2.timestamp}"
|
|
5044
|
+
---
|
|
5045
|
+
|
|
5046
|
+
# ${params2.name}
|
|
5047
|
+
|
|
5048
|
+
`;
|
|
5049
|
+
}
|
|
4913
5050
|
function renderIndexAssignments(params2) {
|
|
4914
5051
|
return `---
|
|
4915
5052
|
project: ${params2.slug}
|
|
@@ -5022,6 +5159,7 @@ total: 0
|
|
|
5022
5159
|
var init_index_stubs = __esm({
|
|
5023
5160
|
"src/templates/index-stubs.ts"() {
|
|
5024
5161
|
"use strict";
|
|
5162
|
+
init_yaml();
|
|
5025
5163
|
}
|
|
5026
5164
|
});
|
|
5027
5165
|
|
|
@@ -6255,8 +6393,8 @@ init_timestamp();
|
|
|
6255
6393
|
init_fs();
|
|
6256
6394
|
init_parser();
|
|
6257
6395
|
import { Router } from "express";
|
|
6258
|
-
import { resolve as resolve12 } from "path";
|
|
6259
|
-
import { rm, readFile as readFile10 } from "fs/promises";
|
|
6396
|
+
import { resolve as resolve12, basename as basename2 } from "path";
|
|
6397
|
+
import { rm, readFile as readFile10, open as fsOpen } from "fs/promises";
|
|
6260
6398
|
|
|
6261
6399
|
// src/dashboard/acceptance-criteria.ts
|
|
6262
6400
|
function splitFrontmatter(content) {
|
|
@@ -6528,6 +6666,210 @@ function createWriteRouter(projectsDir, assignmentsDir2) {
|
|
|
6528
6666
|
}
|
|
6529
6667
|
res.json(document);
|
|
6530
6668
|
});
|
|
6669
|
+
router.get("/api/projects/:slug/memories/:itemSlug/edit", async (req, res) => {
|
|
6670
|
+
const slug = getParam(req.params.slug);
|
|
6671
|
+
const itemSlug = getParam(req.params.itemSlug);
|
|
6672
|
+
if (!isValidSlug(itemSlug)) {
|
|
6673
|
+
res.status(400).json({ error: "Invalid memory slug." });
|
|
6674
|
+
return;
|
|
6675
|
+
}
|
|
6676
|
+
const projectDir = await resolveProjectPath(projectsDir, slug);
|
|
6677
|
+
if (!projectDir) {
|
|
6678
|
+
res.status(404).json({ error: `Project "${slug}" not found` });
|
|
6679
|
+
return;
|
|
6680
|
+
}
|
|
6681
|
+
const document = await getEditableDocument(projectsDir, "memory", basename2(projectDir), itemSlug);
|
|
6682
|
+
if (!document) {
|
|
6683
|
+
res.status(404).json({ error: "Memory not found" });
|
|
6684
|
+
return;
|
|
6685
|
+
}
|
|
6686
|
+
res.json(document);
|
|
6687
|
+
});
|
|
6688
|
+
router.get("/api/projects/:slug/resources/:itemSlug/edit", async (req, res) => {
|
|
6689
|
+
const slug = getParam(req.params.slug);
|
|
6690
|
+
const itemSlug = getParam(req.params.itemSlug);
|
|
6691
|
+
if (!isValidSlug(itemSlug)) {
|
|
6692
|
+
res.status(400).json({ error: "Invalid resource slug." });
|
|
6693
|
+
return;
|
|
6694
|
+
}
|
|
6695
|
+
const projectDir = await resolveProjectPath(projectsDir, slug);
|
|
6696
|
+
if (!projectDir) {
|
|
6697
|
+
res.status(404).json({ error: `Project "${slug}" not found` });
|
|
6698
|
+
return;
|
|
6699
|
+
}
|
|
6700
|
+
const document = await getEditableDocument(projectsDir, "resource", basename2(projectDir), itemSlug);
|
|
6701
|
+
if (!document) {
|
|
6702
|
+
res.status(404).json({ error: "Resource not found" });
|
|
6703
|
+
return;
|
|
6704
|
+
}
|
|
6705
|
+
res.json(document);
|
|
6706
|
+
});
|
|
6707
|
+
function itemFolder(kind) {
|
|
6708
|
+
return kind === "memory" ? "memories" : "resources";
|
|
6709
|
+
}
|
|
6710
|
+
function renderItemStub(kind, params2) {
|
|
6711
|
+
return kind === "memory" ? renderMemoryStub(params2) : renderResourceStub(params2);
|
|
6712
|
+
}
|
|
6713
|
+
function replaceStubBody(stub, body) {
|
|
6714
|
+
const match = stub.match(/^(---\r?\n[\s\S]*?\r?\n---\r?\n)/);
|
|
6715
|
+
if (!match) return stub;
|
|
6716
|
+
return `${match[1]}
|
|
6717
|
+
${body.startsWith("\n") ? body.slice(1) : body}${body.endsWith("\n") ? "" : "\n"}`;
|
|
6718
|
+
}
|
|
6719
|
+
function extractFrontmatterBlock(content) {
|
|
6720
|
+
const match = content.match(/^(---\r?\n[\s\S]*?\r?\n---\r?\n)/);
|
|
6721
|
+
return match ? match[1] : null;
|
|
6722
|
+
}
|
|
6723
|
+
function parseItem(kind, content) {
|
|
6724
|
+
return kind === "memory" ? parseMemory(content) : parseResource(content);
|
|
6725
|
+
}
|
|
6726
|
+
async function getItemDetail(kind, projectSlug, itemSlug) {
|
|
6727
|
+
return kind === "memory" ? await getMemoryDetail(projectsDir, projectSlug, itemSlug) : await getResourceDetail(projectsDir, projectSlug, itemSlug);
|
|
6728
|
+
}
|
|
6729
|
+
async function resolveProjectDir(projectSlug) {
|
|
6730
|
+
return resolveProjectPath(projectsDir, projectSlug);
|
|
6731
|
+
}
|
|
6732
|
+
function rejectBadItemSlug(itemSlug, kind, res) {
|
|
6733
|
+
if (isValidSlug(itemSlug)) return false;
|
|
6734
|
+
res.status(400).json({
|
|
6735
|
+
error: `Invalid ${kind} slug "${itemSlug}". Slugs must be lowercase letters, numbers, and hyphens only.`
|
|
6736
|
+
});
|
|
6737
|
+
return true;
|
|
6738
|
+
}
|
|
6739
|
+
for (const kind of ["memory", "resource"]) {
|
|
6740
|
+
const folder = itemFolder(kind);
|
|
6741
|
+
router.get(`/api/projects/:slug/${folder}/:itemSlug`, async (req, res) => {
|
|
6742
|
+
try {
|
|
6743
|
+
const projectSlug = getParam(req.params.slug);
|
|
6744
|
+
const itemSlug = getParam(req.params.itemSlug);
|
|
6745
|
+
if (rejectBadItemSlug(itemSlug, kind, res)) return;
|
|
6746
|
+
const detail = await getItemDetail(kind, projectSlug, itemSlug);
|
|
6747
|
+
if (!detail) {
|
|
6748
|
+
res.status(404).json({ error: `${kind === "memory" ? "Memory" : "Resource"} not found` });
|
|
6749
|
+
return;
|
|
6750
|
+
}
|
|
6751
|
+
res.json(detail);
|
|
6752
|
+
} catch (error) {
|
|
6753
|
+
console.error(`Error fetching ${kind} detail:`, error);
|
|
6754
|
+
res.status(500).json({ error: `Failed to load ${kind}: ${error.message}` });
|
|
6755
|
+
}
|
|
6756
|
+
});
|
|
6757
|
+
router.post(`/api/projects/:slug/${folder}`, async (req, res) => {
|
|
6758
|
+
try {
|
|
6759
|
+
const projectSlug = getParam(req.params.slug);
|
|
6760
|
+
const projectDir = await resolveProjectDir(projectSlug);
|
|
6761
|
+
if (!projectDir) {
|
|
6762
|
+
res.status(404).json({ error: `Project "${projectSlug}" not found` });
|
|
6763
|
+
return;
|
|
6764
|
+
}
|
|
6765
|
+
const body = req.body ?? {};
|
|
6766
|
+
const name = typeof body.name === "string" ? body.name.trim() : "";
|
|
6767
|
+
if (!name) {
|
|
6768
|
+
res.status(400).json({ error: "Name is required." });
|
|
6769
|
+
return;
|
|
6770
|
+
}
|
|
6771
|
+
const requestedSlug = typeof body.slug === "string" && body.slug.trim() ? body.slug.trim() : slugify(name);
|
|
6772
|
+
if (!requestedSlug || !isValidSlug(requestedSlug)) {
|
|
6773
|
+
res.status(400).json({
|
|
6774
|
+
error: `Slug "${requestedSlug}" is invalid. Slugs must be lowercase letters, numbers, and hyphens only.`
|
|
6775
|
+
});
|
|
6776
|
+
return;
|
|
6777
|
+
}
|
|
6778
|
+
const folderPath = resolve12(projectDir, folder);
|
|
6779
|
+
await ensureDir(folderPath);
|
|
6780
|
+
const filePath = resolve12(folderPath, `${requestedSlug}.md`);
|
|
6781
|
+
const timestamp = nowTimestamp();
|
|
6782
|
+
let content = renderItemStub(kind, {
|
|
6783
|
+
slug: requestedSlug,
|
|
6784
|
+
name,
|
|
6785
|
+
projectSlug: basename2(projectDir),
|
|
6786
|
+
timestamp
|
|
6787
|
+
});
|
|
6788
|
+
const customBody = typeof body.body === "string" ? body.body : "";
|
|
6789
|
+
if (customBody.trim()) {
|
|
6790
|
+
content = replaceStubBody(content, customBody);
|
|
6791
|
+
}
|
|
6792
|
+
try {
|
|
6793
|
+
const handle = await fsOpen(filePath, "wx");
|
|
6794
|
+
try {
|
|
6795
|
+
await handle.writeFile(content, "utf-8");
|
|
6796
|
+
} finally {
|
|
6797
|
+
await handle.close();
|
|
6798
|
+
}
|
|
6799
|
+
} catch (err) {
|
|
6800
|
+
if (err.code === "EEXIST") {
|
|
6801
|
+
res.status(409).json({
|
|
6802
|
+
error: `${kind === "memory" ? "Memory" : "Resource"} with slug "${requestedSlug}" already exists in project "${basename2(projectDir)}".`
|
|
6803
|
+
});
|
|
6804
|
+
return;
|
|
6805
|
+
}
|
|
6806
|
+
throw err;
|
|
6807
|
+
}
|
|
6808
|
+
res.status(201).json({ slug: requestedSlug, projectSlug: basename2(projectDir), content });
|
|
6809
|
+
} catch (error) {
|
|
6810
|
+
console.error(`Error creating ${kind}:`, error);
|
|
6811
|
+
res.status(500).json({ error: `Failed to create ${kind}: ${error.message}` });
|
|
6812
|
+
}
|
|
6813
|
+
});
|
|
6814
|
+
router.patch(`/api/projects/:slug/${folder}/:itemSlug`, async (req, res) => {
|
|
6815
|
+
try {
|
|
6816
|
+
const projectSlug = getParam(req.params.slug);
|
|
6817
|
+
const itemSlug = getParam(req.params.itemSlug);
|
|
6818
|
+
if (rejectBadItemSlug(itemSlug, kind, res)) return;
|
|
6819
|
+
const projectDir = await resolveProjectDir(projectSlug);
|
|
6820
|
+
if (!projectDir) {
|
|
6821
|
+
res.status(404).json({ error: `Project "${projectSlug}" not found` });
|
|
6822
|
+
return;
|
|
6823
|
+
}
|
|
6824
|
+
const filePath = resolve12(projectDir, folder, `${itemSlug}.md`);
|
|
6825
|
+
if (!await fileExists(filePath)) {
|
|
6826
|
+
res.status(404).json({ error: `${kind === "memory" ? "Memory" : "Resource"} not found` });
|
|
6827
|
+
return;
|
|
6828
|
+
}
|
|
6829
|
+
const nextContentRaw = requireContent(req, res);
|
|
6830
|
+
if (!nextContentRaw) return;
|
|
6831
|
+
const currentContent = await readFile10(filePath, "utf-8");
|
|
6832
|
+
const frontmatterBlock = extractFrontmatterBlock(currentContent);
|
|
6833
|
+
if (!frontmatterBlock) {
|
|
6834
|
+
res.status(500).json({ error: `${kind} file is malformed (no frontmatter)` });
|
|
6835
|
+
return;
|
|
6836
|
+
}
|
|
6837
|
+
const next = parseItem(kind, nextContentRaw);
|
|
6838
|
+
const nextBody = next.body.trimStart();
|
|
6839
|
+
let merged = `${frontmatterBlock}
|
|
6840
|
+
${nextBody}${nextBody.endsWith("\n") ? "" : "\n"}`;
|
|
6841
|
+
merged = setTopLevelField(merged, "updated", nowTimestamp());
|
|
6842
|
+
await writeFileForce(filePath, merged);
|
|
6843
|
+
const detail = await getItemDetail(kind, basename2(projectDir), itemSlug);
|
|
6844
|
+
res.json({ [kind]: detail, content: merged });
|
|
6845
|
+
} catch (error) {
|
|
6846
|
+
console.error(`Error updating ${kind}:`, error);
|
|
6847
|
+
res.status(500).json({ error: `Failed to update ${kind}: ${error.message}` });
|
|
6848
|
+
}
|
|
6849
|
+
});
|
|
6850
|
+
router.delete(`/api/projects/:slug/${folder}/:itemSlug`, async (req, res) => {
|
|
6851
|
+
try {
|
|
6852
|
+
const projectSlug = getParam(req.params.slug);
|
|
6853
|
+
const itemSlug = getParam(req.params.itemSlug);
|
|
6854
|
+
if (rejectBadItemSlug(itemSlug, kind, res)) return;
|
|
6855
|
+
const projectDir = await resolveProjectDir(projectSlug);
|
|
6856
|
+
if (!projectDir) {
|
|
6857
|
+
res.status(404).json({ error: `Project "${projectSlug}" not found` });
|
|
6858
|
+
return;
|
|
6859
|
+
}
|
|
6860
|
+
const filePath = resolve12(projectDir, folder, `${itemSlug}.md`);
|
|
6861
|
+
if (!await fileExists(filePath)) {
|
|
6862
|
+
res.status(404).json({ error: `${kind === "memory" ? "Memory" : "Resource"} not found` });
|
|
6863
|
+
return;
|
|
6864
|
+
}
|
|
6865
|
+
await rm(filePath);
|
|
6866
|
+
res.status(204).end();
|
|
6867
|
+
} catch (error) {
|
|
6868
|
+
console.error(`Error deleting ${kind}:`, error);
|
|
6869
|
+
res.status(500).json({ error: `Failed to delete ${kind}: ${error.message}` });
|
|
6870
|
+
}
|
|
6871
|
+
});
|
|
6872
|
+
}
|
|
6531
6873
|
router.post("/api/projects", async (req, res) => {
|
|
6532
6874
|
try {
|
|
6533
6875
|
const content = requireContent(req, res);
|
|
@@ -10699,6 +11041,24 @@ function createDashboardServer(options) {
|
|
|
10699
11041
|
app.use("/api/servers", createServersRouter(serversDir2, projectsDir, assignmentsDir2));
|
|
10700
11042
|
app.use("/api/agent-sessions", createAgentSessionsRouter(projectsDir, broadcast, assignmentsDir2));
|
|
10701
11043
|
app.use("/api/playbooks", createPlaybooksRouter(playbooksDir2));
|
|
11044
|
+
app.get("/api/memories", async (_req, res) => {
|
|
11045
|
+
try {
|
|
11046
|
+
const memories = await listAllMemories(projectsDir);
|
|
11047
|
+
res.json({ generatedAt: (/* @__PURE__ */ new Date()).toISOString(), memories });
|
|
11048
|
+
} catch (error) {
|
|
11049
|
+
console.error("Error listing memories:", error);
|
|
11050
|
+
res.status(500).json({ error: `Failed to load memories: ${error.message}` });
|
|
11051
|
+
}
|
|
11052
|
+
});
|
|
11053
|
+
app.get("/api/resources", async (_req, res) => {
|
|
11054
|
+
try {
|
|
11055
|
+
const resources = await listAllResources(projectsDir);
|
|
11056
|
+
res.json({ generatedAt: (/* @__PURE__ */ new Date()).toISOString(), resources });
|
|
11057
|
+
} catch (error) {
|
|
11058
|
+
console.error("Error listing resources:", error);
|
|
11059
|
+
res.status(500).json({ error: `Failed to load resources: ${error.message}` });
|
|
11060
|
+
}
|
|
11061
|
+
});
|
|
10702
11062
|
app.use("/api/todos", createTodosRouter(todosDir2, broadcast, projectsDir));
|
|
10703
11063
|
app.use("/api/projects/:projectId/todos", createProjectTodosRouter(projectsDir, broadcast, todosDir2));
|
|
10704
11064
|
app.use("/api/backup", createBackupRouter());
|