@a-company/paradigm 5.6.2 → 5.8.1

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.
Files changed (28) hide show
  1. package/dist/{chunk-SU3WDCRR.js → chunk-T3YGSZCI.js} +12 -0
  2. package/dist/conductor-CQVGTEQN.js +161 -0
  3. package/dist/{docs-J2BTKRVU.js → docs-AIY6VNF7.js} +1 -1
  4. package/dist/index.js +7 -7
  5. package/dist/mcp.js +2 -2
  6. package/dist/{platform-server-2D6S6YTK.js → platform-server-U5L2G3EU.js} +196 -15
  7. package/dist/{reindex-J5SEDVTT.js → reindex-KFUPB3ES.js} +1 -1
  8. package/dist/{serve-EFVRS4GA.js → serve-QWWJP2EW.js} +1 -1
  9. package/dist/{shift-VFG23DLA.js → shift-2NYRFVEZ.js} +6 -2
  10. package/dist/university-ui/assets/{index-BLWmLEDq.js → index-BjewBB6s.js} +2 -2
  11. package/dist/university-ui/assets/{index-BLWmLEDq.js.map → index-BjewBB6s.js.map} +1 -1
  12. package/dist/university-ui/index.html +1 -1
  13. package/package.json +1 -1
  14. package/platform-ui/dist/assets/AmbientSection-10pbwWjo.css +1 -0
  15. package/platform-ui/dist/assets/AmbientSection-WtHfNedO.js +1 -0
  16. package/platform-ui/dist/assets/CanvasSection-DwPTRdIN.js +9 -0
  17. package/platform-ui/dist/assets/CanvasSection-flMXU19z.css +1 -0
  18. package/platform-ui/dist/assets/{DocsSection-ByAgPzWV.js → DocsSection-BJc_ws4I.js} +1 -1
  19. package/platform-ui/dist/assets/{GitSection-BLovj9yT.js → GitSection-DhqBo1xc.js} +1 -1
  20. package/platform-ui/dist/assets/{GraphSection-C5PCPUFl.js → GraphSection-D9fhVnZ0.js} +1 -1
  21. package/platform-ui/dist/assets/{LoreSection-BftejTla.js → LoreSection-CwDDHrz9.js} +1 -1
  22. package/platform-ui/dist/assets/{SentinelSection-CnYcasN7.js → SentinelSection-Cl7e5oZ6.js} +1 -1
  23. package/platform-ui/dist/assets/{SymphonySection-BpmqCHeK.js → SymphonySection-BRoBaUSS.js} +1 -1
  24. package/platform-ui/dist/assets/TeamSection-CqSIMrKz.js +1 -0
  25. package/platform-ui/dist/assets/TeamSection-udxWQTcX.css +1 -0
  26. package/platform-ui/dist/assets/{index-G9JnWEs_.js → index-F0KL9xrN.js} +11 -11
  27. package/platform-ui/dist/index.html +1 -1
  28. package/dist/conductor-PGPDVIVE.js +0 -88
@@ -2277,6 +2277,18 @@ var SessionTracker = class {
2277
2277
  if (checkpoint && Date.now() - checkpoint.timestamp > CHECKPOINT_MAX_AGE_MS) {
2278
2278
  return null;
2279
2279
  }
2280
+ if (checkpoint) {
2281
+ for (const key of ["modifiedFiles", "symbolsTouched", "decisions"]) {
2282
+ const val = checkpoint[key];
2283
+ if (typeof val === "string") {
2284
+ try {
2285
+ checkpoint[key] = JSON.parse(val);
2286
+ } catch {
2287
+ checkpoint[key] = [];
2288
+ }
2289
+ }
2290
+ }
2291
+ }
2280
2292
  return checkpoint;
2281
2293
  }
2282
2294
  /**
@@ -0,0 +1,161 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ log
4
+ } from "./chunk-4NCFWYGG.js";
5
+ import "./chunk-PDX44BCA.js";
6
+
7
+ // src/commands/conductor.ts
8
+ import { execSync, spawn } from "child_process";
9
+ import * as fs from "fs";
10
+ import * as path from "path";
11
+ import * as os from "os";
12
+ import { fileURLToPath } from "url";
13
+ import chalk from "chalk";
14
+ var __filename = fileURLToPath(import.meta.url);
15
+ var __dirname = path.dirname(__filename);
16
+ var INSTALLED_BINARY = path.join(os.homedir(), ".paradigm", "conductor", "bin", "conductor");
17
+ async function conductorCommand(options) {
18
+ const cmdLog = log.command("conductor");
19
+ if (options.install) {
20
+ await installConductor(options, cmdLog);
21
+ return;
22
+ }
23
+ const binaryPath = resolveBinary(options, cmdLog);
24
+ if (!binaryPath) {
25
+ return;
26
+ }
27
+ if (options.build) {
28
+ const conductorDir = findConductorDir();
29
+ if (conductorDir) {
30
+ buildFromSource(conductorDir, options, cmdLog);
31
+ const devBinary = path.join(conductorDir, ".build", "release", "conductor");
32
+ launchBinary(devBinary, cmdLog);
33
+ return;
34
+ } else {
35
+ cmdLog.error("--build requires the Paradigm monorepo");
36
+ console.log(chalk.gray(" Run from inside the a-paradigm repo, or use --install to update the global binary."));
37
+ process.exit(1);
38
+ }
39
+ }
40
+ launchBinary(binaryPath, cmdLog);
41
+ }
42
+ function resolveBinary(options, cmdLog) {
43
+ if (fs.existsSync(INSTALLED_BINARY)) {
44
+ return INSTALLED_BINARY;
45
+ }
46
+ const conductorDir = findConductorDir();
47
+ if (conductorDir) {
48
+ const devBinary = path.join(conductorDir, ".build", "release", "conductor");
49
+ if (fs.existsSync(devBinary)) {
50
+ return devBinary;
51
+ }
52
+ cmdLog.info("Dev binary not found, building\u2026");
53
+ buildFromSource(conductorDir, options, cmdLog);
54
+ if (fs.existsSync(devBinary)) {
55
+ return devBinary;
56
+ }
57
+ }
58
+ cmdLog.error("Conductor binary not found");
59
+ console.log("");
60
+ console.log(chalk.white(" To install Conductor:"));
61
+ console.log(chalk.cyan(" cd <paradigm-repo> && paradigm conductor --install"));
62
+ console.log("");
63
+ console.log(chalk.gray(" This builds the native binary and installs it to ~/.paradigm/conductor/bin/"));
64
+ console.log(chalk.gray(" After that, `paradigm conductor` works from any directory."));
65
+ console.log("");
66
+ process.exit(1);
67
+ return null;
68
+ }
69
+ async function installConductor(options, cmdLog) {
70
+ const conductorDir = findConductorDir();
71
+ if (!conductorDir) {
72
+ cmdLog.error("Cannot install \u2014 not in the Paradigm monorepo");
73
+ console.log(chalk.gray(" Run this command from inside the a-paradigm repository."));
74
+ process.exit(1);
75
+ }
76
+ const devBinary = path.join(conductorDir, ".build", "release", "conductor");
77
+ if (!fs.existsSync(devBinary) || options.build) {
78
+ buildFromSource(conductorDir, options, cmdLog);
79
+ }
80
+ if (!fs.existsSync(devBinary)) {
81
+ cmdLog.error("Build did not produce a binary");
82
+ process.exit(1);
83
+ }
84
+ const installDir = path.dirname(INSTALLED_BINARY);
85
+ fs.mkdirSync(installDir, { recursive: true });
86
+ fs.copyFileSync(devBinary, INSTALLED_BINARY);
87
+ fs.chmodSync(INSTALLED_BINARY, 493);
88
+ const size = (fs.statSync(INSTALLED_BINARY).size / (1024 * 1024)).toFixed(1);
89
+ cmdLog.success(`Conductor installed (${size} MB)`);
90
+ console.log("");
91
+ console.log(chalk.green(" \u2713 ") + chalk.white("Installed to ") + chalk.cyan("~/.paradigm/conductor/bin/conductor"));
92
+ console.log(chalk.green(" \u2713 ") + chalk.white("Run ") + chalk.cyan("paradigm conductor") + chalk.white(" from any directory"));
93
+ console.log("");
94
+ }
95
+ function buildFromSource(conductorDir, options, cmdLog) {
96
+ cmdLog.info("Building Conductor\u2026");
97
+ try {
98
+ execSync("swift build -c release", {
99
+ cwd: conductorDir,
100
+ stdio: options.verbose ? "inherit" : "pipe"
101
+ });
102
+ cmdLog.success("Build complete");
103
+ } catch (error) {
104
+ cmdLog.error("Build failed");
105
+ const errMsg = error.message || "";
106
+ if (errMsg.includes("xcode-select")) {
107
+ console.log(chalk.gray(" Xcode Command Line Tools are required."));
108
+ console.log(chalk.gray(" Install with: xcode-select --install"));
109
+ } else {
110
+ console.log(chalk.gray(` ${errMsg.slice(0, 200)}`));
111
+ }
112
+ process.exit(1);
113
+ }
114
+ }
115
+ function launchBinary(binaryPath, cmdLog) {
116
+ cmdLog.info("Launching Conductor\u2026");
117
+ const child = spawn(binaryPath, [], {
118
+ detached: true,
119
+ stdio: "ignore"
120
+ });
121
+ child.unref();
122
+ const isInstalled = binaryPath === INSTALLED_BINARY;
123
+ console.log(chalk.cyan("\n Paradigm Conductor is running."));
124
+ if (isInstalled) {
125
+ console.log(chalk.gray(" Binary: ~/.paradigm/conductor/bin/conductor"));
126
+ }
127
+ console.log(chalk.gray(" Look for the waveform icon in your menu bar."));
128
+ console.log(chalk.gray(" Quit via the menu bar icon or Cmd+Q.\n"));
129
+ }
130
+ function findConductorDir() {
131
+ let dir = path.resolve(__dirname, "..");
132
+ for (let i = 0; i < 5; i++) {
133
+ const candidate = path.join(dir, "packages", "conductor");
134
+ if (fs.existsSync(path.join(candidate, "Package.swift"))) {
135
+ return candidate;
136
+ }
137
+ dir = path.dirname(dir);
138
+ }
139
+ const cwdCandidate = path.join(process.cwd(), "packages", "conductor");
140
+ if (fs.existsSync(path.join(cwdCandidate, "Package.swift"))) {
141
+ return cwdCandidate;
142
+ }
143
+ if (fs.existsSync(path.join(process.cwd(), "Package.swift"))) {
144
+ const basename2 = path.basename(process.cwd());
145
+ if (basename2 === "conductor") {
146
+ return process.cwd();
147
+ }
148
+ }
149
+ let cwdDir = process.cwd();
150
+ for (let i = 0; i < 5; i++) {
151
+ cwdDir = path.dirname(cwdDir);
152
+ const candidate = path.join(cwdDir, "packages", "conductor");
153
+ if (fs.existsSync(path.join(candidate, "Package.swift"))) {
154
+ return candidate;
155
+ }
156
+ }
157
+ return null;
158
+ }
159
+ export {
160
+ conductorCommand
161
+ };
@@ -17,7 +17,7 @@ async function docsServeCommand(options) {
17
17
  const shouldOpen = options.open !== false;
18
18
  console.log(chalk.cyan("\n Starting Paradigm Docs...\n"));
19
19
  try {
20
- const { startPlatformServer } = await import("./platform-server-2D6S6YTK.js");
20
+ const { startPlatformServer } = await import("./platform-server-U5L2G3EU.js");
21
21
  await startPlatformServer({
22
22
  projectDir,
23
23
  port,
package/dist/index.js CHANGED
@@ -111,7 +111,7 @@ ${chalk2.magenta("\u2569 ")}${chalk2.cyan("\u2534 \u2534\u2534\u2514\u2500\u253
111
111
  program.name("paradigm").description("Unified developer tools ecosystem").version(VERSION).addHelpText("before", banner);
112
112
  program.command("init").description("Initialize Paradigm in the current project").option("-f, --force", "Overwrite existing files").option("--name <name>", "Project name").option("--ide <ide>", "Target IDE: cursor, copilot, windsurf, claude").option("--stack <stack>", "Stack preset (e.g., nextjs, fastapi, swift-ios). Auto-detected if omitted.").option("--migrate", "Output migration prompt for existing IDE files").option("--quick", "Non-interactive mode with smart defaults").option("--dry-run", "Show what would be created without creating").action(initCommand);
113
113
  program.command("shift").description("Full project setup in one command (init + team init + scan + sync all IDEs + doctor)").option("-f, --force", "Reinitialize even if already setup").option("-q, --quick", "Skip slow operations (scan)").option("--verify", "Run health checks after setup").option("--ide <ide>", "Target specific IDE instead of all").option("--configure-models", "Force model configuration prompts for team agents").option("--stack <stack>", "Stack preset (e.g., nextjs, fastapi, swift-ios). Auto-detected if omitted.").option("--workspace <name>", "Create or join a multi-project workspace with this name (creates ../.paradigm-workspace)").option("--workspace-path <path>", "Custom workspace file location (default: ../.paradigm-workspace)").action(async (options) => {
114
- const { shiftCommand } = await import("./shift-VFG23DLA.js");
114
+ const { shiftCommand } = await import("./shift-2NYRFVEZ.js");
115
115
  await shiftCommand(options);
116
116
  });
117
117
  program.command("presets").description("List available stack presets for paradigm init/shift").option("-d, --discipline <discipline>", "Filter by discipline (e.g., fullstack, api, mobile)").action(async (options) => {
@@ -719,7 +719,7 @@ loreCmd.option("-p, --port <port>", "Port to run on", "3840").option("--no-open"
719
719
  await loreServeCommand(void 0, options);
720
720
  });
721
721
  program.command("serve").description("Launch Paradigm Platform \u2014 unified development management UI").option("-p, --port <port>", "Port to run on", "3850").option("--no-open", "Don't open browser automatically").option("--sections <list>", "Comma-separated sections to enable (e.g., lore,graph,git)").action(async (options) => {
722
- const { serveCommand } = await import("./serve-EFVRS4GA.js");
722
+ const { serveCommand } = await import("./serve-QWWJP2EW.js");
723
723
  await serveCommand(options);
724
724
  });
725
725
  var graphCmd = program.command("graph").description("Interactive symbol relationship graph").argument("[path]", "Project directory", void 0).option("-p, --port <port>", "Port to run on", "3841").option("--no-open", "Don't open browser automatically").action(async (path2, options) => {
@@ -818,8 +818,8 @@ sentinelCmd.command("defend [path]", { isDefault: true }).description("Launch th
818
818
  const { sentinelCommand } = await import("./sentinel-4XIG4STA.js");
819
819
  await sentinelCommand(path2, options);
820
820
  });
821
- program.command("conductor").description("Launch Paradigm Conductor \u2014 multimodal mission control for Claude Code sessions").option("--build", "Force rebuild the native binary").option("-v, --verbose", "Show build output").action(async (options) => {
822
- const { conductorCommand } = await import("./conductor-PGPDVIVE.js");
821
+ program.command("conductor").description("Launch Paradigm Conductor \u2014 multimodal mission control for Claude Code sessions").option("--build", "Force rebuild the native binary").option("--install", "Install Conductor binary to ~/.paradigm/conductor/bin/").option("-v, --verbose", "Show build output").action(async (options) => {
822
+ const { conductorCommand } = await import("./conductor-CQVGTEQN.js");
823
823
  await conductorCommand(options);
824
824
  });
825
825
  var universityCmd = program.command("university").description("Per-project university - knowledge base, quizzes, learning paths & PLSAT certification");
@@ -857,15 +857,15 @@ universityCmd.option("-p, --port <port>", "Port to run on", "3839").option("--no
857
857
  });
858
858
  var docsCmd = program.command("docs").description("Auto-generated documentation from the symbol graph");
859
859
  docsCmd.command("serve").description("Launch interactive docs viewer in browser").option("-p, --port <port>", "Port number (default: 3850)").option("--no-open", "Do not open browser automatically").action(async (options) => {
860
- const { docsServeCommand } = await import("./docs-J2BTKRVU.js");
860
+ const { docsServeCommand } = await import("./docs-AIY6VNF7.js");
861
861
  await docsServeCommand(options);
862
862
  });
863
863
  docsCmd.command("build").description("Build static documentation site").option("-o, --output <dir>", "Output directory (default: from config or .paradigm/docs-site)").action(async (options) => {
864
- const { docsBuildCommand } = await import("./docs-J2BTKRVU.js");
864
+ const { docsBuildCommand } = await import("./docs-AIY6VNF7.js");
865
865
  await docsBuildCommand(options);
866
866
  });
867
867
  docsCmd.action(async () => {
868
- const { docsServeCommand } = await import("./docs-J2BTKRVU.js");
868
+ const { docsServeCommand } = await import("./docs-AIY6VNF7.js");
869
869
  await docsServeCommand({});
870
870
  });
871
871
  var pipelineCmd = program.command("pipeline").description("Spec pipeline \u2014 structured feature workflow with configurable gates");
package/dist/mcp.js CHANGED
@@ -79,7 +79,7 @@ import {
79
79
  validateProtocol,
80
80
  validatePurposeFile,
81
81
  validateUniversityContent
82
- } from "./chunk-SU3WDCRR.js";
82
+ } from "./chunk-T3YGSZCI.js";
83
83
  import "./chunk-L27I3CPZ.js";
84
84
  import {
85
85
  getWorkLogSummary,
@@ -21155,7 +21155,7 @@ Update command:
21155
21155
  trackToolCall(noWsText.length, name);
21156
21156
  return { content: [{ type: "text", text: noWsText }] };
21157
21157
  }
21158
- const { rebuildStaticFiles: rebuildStaticFiles2 } = await import("./reindex-J5SEDVTT.js");
21158
+ const { rebuildStaticFiles: rebuildStaticFiles2 } = await import("./reindex-KFUPB3ES.js");
21159
21159
  const memberResults = [];
21160
21160
  for (const member of ctx.workspace.config.members) {
21161
21161
  const memberAbsPath = path34.resolve(path34.dirname(ctx.workspace.workspacePath), member.path);
@@ -13,8 +13,8 @@ import "./chunk-PDX44BCA.js";
13
13
  // src/platform-server/index.ts
14
14
  import express from "express";
15
15
  import * as http from "http";
16
- import * as path4 from "path";
17
- import * as fs4 from "fs";
16
+ import * as path5 from "path";
17
+ import * as fs5 from "fs";
18
18
  import { fileURLToPath } from "url";
19
19
  import chalk from "chalk";
20
20
 
@@ -1097,9 +1097,189 @@ function createTeamRouter(projectDir) {
1097
1097
  return router;
1098
1098
  }
1099
1099
 
1100
+ // src/platform-server/routes/canvas.ts
1101
+ import { Router as Router5 } from "express";
1102
+ import * as fs4 from "fs";
1103
+ import * as path4 from "path";
1104
+ import * as yaml4 from "js-yaml";
1105
+ var IGNORE_DIRS = /* @__PURE__ */ new Set([
1106
+ "node_modules",
1107
+ ".git",
1108
+ "dist",
1109
+ ".next",
1110
+ "build",
1111
+ ".paradigm",
1112
+ ".turbo",
1113
+ ".cache",
1114
+ "coverage",
1115
+ ".output"
1116
+ ]);
1117
+ function findCanvasFiles(dir, rootDir) {
1118
+ const results = [];
1119
+ let entries;
1120
+ try {
1121
+ entries = fs4.readdirSync(dir, { withFileTypes: true });
1122
+ } catch {
1123
+ return results;
1124
+ }
1125
+ for (const entry of entries) {
1126
+ if (entry.isDirectory()) {
1127
+ if (!IGNORE_DIRS.has(entry.name) && !entry.name.startsWith(".")) {
1128
+ results.push(...findCanvasFiles(path4.join(dir, entry.name), rootDir));
1129
+ }
1130
+ } else if (entry.isFile() && entry.name.endsWith(".canvas")) {
1131
+ results.push(path4.relative(rootDir, path4.join(dir, entry.name)));
1132
+ }
1133
+ }
1134
+ return results;
1135
+ }
1136
+ var cachedFiles = null;
1137
+ var cacheTimestamp = 0;
1138
+ var CACHE_TTL = 5e3;
1139
+ function getCanvasFiles(projectDir) {
1140
+ const now = Date.now();
1141
+ if (cachedFiles && now - cacheTimestamp < CACHE_TTL) {
1142
+ return cachedFiles;
1143
+ }
1144
+ const rootFiles = fs4.readdirSync(projectDir).filter((f) => f.endsWith(".canvas")).map((f) => f);
1145
+ const nestedFiles = findCanvasFiles(projectDir, projectDir).filter((f) => !rootFiles.includes(f));
1146
+ cachedFiles = [...rootFiles, ...nestedFiles];
1147
+ cacheTimestamp = now;
1148
+ return cachedFiles;
1149
+ }
1150
+ function safePath(projectDir, requestedPath) {
1151
+ const resolved = path4.resolve(projectDir, requestedPath);
1152
+ if (!resolved.startsWith(projectDir + path4.sep) && resolved !== projectDir) {
1153
+ return null;
1154
+ }
1155
+ if (!resolved.endsWith(".canvas")) {
1156
+ return null;
1157
+ }
1158
+ return resolved;
1159
+ }
1160
+ function createCanvasRouter(projectDir) {
1161
+ const router = Router5();
1162
+ router.get("/files", (_req, res) => {
1163
+ try {
1164
+ const relativePaths = getCanvasFiles(projectDir);
1165
+ const files = relativePaths.map((relPath) => {
1166
+ const absPath = path4.join(projectDir, relPath);
1167
+ try {
1168
+ const stat = fs4.statSync(absPath);
1169
+ let name = path4.basename(relPath, ".canvas");
1170
+ let description = "";
1171
+ try {
1172
+ const raw = yaml4.load(fs4.readFileSync(absPath, "utf8"));
1173
+ if (raw && typeof raw.name === "string") name = raw.name;
1174
+ if (raw && typeof raw.description === "string") description = raw.description;
1175
+ } catch {
1176
+ }
1177
+ return {
1178
+ path: relPath,
1179
+ name,
1180
+ description,
1181
+ modified: stat.mtime.toISOString(),
1182
+ size: stat.size
1183
+ };
1184
+ } catch {
1185
+ return null;
1186
+ }
1187
+ }).filter(Boolean);
1188
+ files.sort((a, b) => b.modified.localeCompare(a.modified));
1189
+ res.json({ files });
1190
+ } catch (err) {
1191
+ res.status(500).json({ error: "Failed to list canvas files", details: err.message });
1192
+ }
1193
+ });
1194
+ router.get("/files/*", (req, res) => {
1195
+ const requestedPath = req.params[0] || req.params["path"] || "";
1196
+ if (!requestedPath) {
1197
+ res.status(400).json({ error: "File path required" });
1198
+ return;
1199
+ }
1200
+ const absPath = safePath(projectDir, requestedPath);
1201
+ if (!absPath) {
1202
+ res.status(400).json({ error: "Invalid path" });
1203
+ return;
1204
+ }
1205
+ if (!fs4.existsSync(absPath)) {
1206
+ res.status(404).json({ error: `Canvas file not found: ${requestedPath}` });
1207
+ return;
1208
+ }
1209
+ try {
1210
+ const raw = fs4.readFileSync(absPath, "utf8");
1211
+ const parsed = yaml4.load(raw);
1212
+ res.json(parsed);
1213
+ } catch (err) {
1214
+ res.status(500).json({ error: "Failed to read canvas file", details: err.message });
1215
+ }
1216
+ });
1217
+ router.put("/files/*", (req, res) => {
1218
+ const requestedPath = req.params[0] || req.params["path"] || "";
1219
+ if (!requestedPath) {
1220
+ res.status(400).json({ error: "File path required" });
1221
+ return;
1222
+ }
1223
+ const absPath = safePath(projectDir, requestedPath);
1224
+ if (!absPath) {
1225
+ res.status(400).json({ error: "Invalid path" });
1226
+ return;
1227
+ }
1228
+ try {
1229
+ const data = req.body;
1230
+ if (!data || typeof data !== "object") {
1231
+ res.status(400).json({ error: "Request body must be a JSON object" });
1232
+ return;
1233
+ }
1234
+ const now = (/* @__PURE__ */ new Date()).toISOString();
1235
+ if (!data.created) data.created = now;
1236
+ data.updated = now;
1237
+ const dir = path4.dirname(absPath);
1238
+ if (!fs4.existsSync(dir)) {
1239
+ fs4.mkdirSync(dir, { recursive: true });
1240
+ }
1241
+ const yamlStr = yaml4.dump(data, {
1242
+ lineWidth: -1,
1243
+ noRefs: true,
1244
+ quotingType: '"',
1245
+ forceQuotes: false
1246
+ });
1247
+ fs4.writeFileSync(absPath, yamlStr, "utf8");
1248
+ cachedFiles = null;
1249
+ res.json({ saved: true, path: requestedPath });
1250
+ } catch (err) {
1251
+ res.status(500).json({ error: "Failed to save canvas file", details: err.message });
1252
+ }
1253
+ });
1254
+ router.delete("/files/*", (req, res) => {
1255
+ const requestedPath = req.params[0] || req.params["path"] || "";
1256
+ if (!requestedPath) {
1257
+ res.status(400).json({ error: "File path required" });
1258
+ return;
1259
+ }
1260
+ const absPath = safePath(projectDir, requestedPath);
1261
+ if (!absPath) {
1262
+ res.status(400).json({ error: "Invalid path" });
1263
+ return;
1264
+ }
1265
+ if (!fs4.existsSync(absPath)) {
1266
+ res.status(404).json({ error: `Canvas file not found: ${requestedPath}` });
1267
+ return;
1268
+ }
1269
+ try {
1270
+ fs4.unlinkSync(absPath);
1271
+ cachedFiles = null;
1272
+ res.json({ deleted: true, path: requestedPath });
1273
+ } catch (err) {
1274
+ res.status(500).json({ error: "Failed to delete canvas file", details: err.message });
1275
+ }
1276
+ });
1277
+ return router;
1278
+ }
1279
+
1100
1280
  // src/platform-server/index.ts
1101
1281
  var __filename = fileURLToPath(import.meta.url);
1102
- var __dirname = path4.dirname(__filename);
1282
+ var __dirname = path5.dirname(__filename);
1103
1283
  var log = {
1104
1284
  component(name) {
1105
1285
  const symbol = chalk.magenta(`#${name}`);
@@ -1124,7 +1304,7 @@ var log = {
1124
1304
  }
1125
1305
  };
1126
1306
  function resolveSections(options) {
1127
- const always = ["overview", "lore", "graph", "git", "ambient", "team"];
1307
+ const always = ["overview", "lore", "graph", "canvas", "git", "ambient", "team"];
1128
1308
  const requested = options.sections ?? [...always, "sentinel", "university", "symphony", "docs"];
1129
1309
  const enabled = /* @__PURE__ */ new Set();
1130
1310
  for (const section of requested) {
@@ -1133,15 +1313,15 @@ function resolveSections(options) {
1133
1313
  continue;
1134
1314
  }
1135
1315
  if (section === "sentinel") {
1136
- const sentinelRoutesPath = path4.join(options.projectDir, ".paradigm");
1137
- if (fs4.existsSync(sentinelRoutesPath)) {
1316
+ const sentinelRoutesPath = path5.join(options.projectDir, ".paradigm");
1317
+ if (fs5.existsSync(sentinelRoutesPath)) {
1138
1318
  enabled.add(section);
1139
1319
  }
1140
1320
  } else if (section === "university") {
1141
1321
  enabled.add(section);
1142
1322
  } else if (section === "symphony") {
1143
- const mailDir = path4.join(process.env.HOME || "~", ".paradigm", "score");
1144
- if (fs4.existsSync(mailDir)) {
1323
+ const mailDir = path5.join(process.env.HOME || "~", ".paradigm", "score");
1324
+ if (fs5.existsSync(mailDir)) {
1145
1325
  enabled.add(section);
1146
1326
  }
1147
1327
  } else {
@@ -1170,6 +1350,7 @@ function createPlatformApp(options) {
1170
1350
  app.use("/api/symbols", createSymbolsRouter(options.projectDir));
1171
1351
  app.use("/api/graphs", createGraphsRouter(options.projectDir));
1172
1352
  app.get("/api/platform/overview", createOverviewHandler(options.projectDir));
1353
+ app.use("/api/canvas", createCanvasRouter(options.projectDir));
1173
1354
  app.use("/api/git", createGitRouter(options.projectDir));
1174
1355
  app.get("/api/platform/health", (_req, res) => {
1175
1356
  res.json({
@@ -1185,15 +1366,15 @@ function createPlatformApp(options) {
1185
1366
  res.json({ status: "ok", timestamp: (/* @__PURE__ */ new Date()).toISOString() });
1186
1367
  });
1187
1368
  app.set("agentRouterSlot", true);
1188
- let uiDistPath = path4.join(__dirname, "..", "platform-ui", "dist");
1189
- if (!fs4.existsSync(uiDistPath)) {
1190
- uiDistPath = path4.join(__dirname, "..", "..", "platform-ui", "dist");
1369
+ let uiDistPath = path5.join(__dirname, "..", "platform-ui", "dist");
1370
+ if (!fs5.existsSync(uiDistPath)) {
1371
+ uiDistPath = path5.join(__dirname, "..", "..", "platform-ui", "dist");
1191
1372
  }
1192
- if (fs4.existsSync(uiDistPath)) {
1373
+ if (fs5.existsSync(uiDistPath)) {
1193
1374
  app.use(express.static(uiDistPath));
1194
1375
  app.get("{*path}", (req, res, next) => {
1195
1376
  if (!req.path.startsWith("/api")) {
1196
- res.sendFile(path4.join(uiDistPath, "index.html"));
1377
+ res.sendFile(path5.join(uiDistPath, "index.html"));
1197
1378
  } else {
1198
1379
  next();
1199
1380
  }
@@ -1258,7 +1439,7 @@ async function startPlatformServer(options) {
1258
1439
  log.component("platform-server").warn("Docs routes failed to mount");
1259
1440
  }
1260
1441
  }
1261
- return new Promise((resolve, reject) => {
1442
+ return new Promise((resolve2, reject) => {
1262
1443
  httpServer.listen(options.port, () => {
1263
1444
  log.component("platform-server").success("Platform running", { url: `http://localhost:${options.port}` });
1264
1445
  log.component("platform-ws").success("WebSocket ready", { url: `ws://localhost:${options.port}/ws` });
@@ -1276,7 +1457,7 @@ async function startPlatformServer(options) {
1276
1457
  log.component("platform-server").warn("Could not open browser automatically");
1277
1458
  });
1278
1459
  }
1279
- resolve();
1460
+ resolve2();
1280
1461
  });
1281
1462
  httpServer.on("error", (err) => {
1282
1463
  if (err.code === "EADDRINUSE") {
@@ -3,7 +3,7 @@ import {
3
3
  getReindexToolsList,
4
4
  handleReindexTool,
5
5
  rebuildStaticFiles
6
- } from "./chunk-SU3WDCRR.js";
6
+ } from "./chunk-T3YGSZCI.js";
7
7
  import "./chunk-L27I3CPZ.js";
8
8
  import "./chunk-SDDCVUCV.js";
9
9
  import "./chunk-5VKJBNJL.js";
@@ -10,7 +10,7 @@ async function serveCommand(options) {
10
10
  const sections = options.sections ? options.sections.split(",").map((s) => s.trim()) : void 0;
11
11
  console.log(chalk.cyan("\n Starting Paradigm Platform...\n"));
12
12
  try {
13
- const { startPlatformServer } = await import("./platform-server-2D6S6YTK.js");
13
+ const { startPlatformServer } = await import("./platform-server-U5L2G3EU.js");
14
14
  await startPlatformServer({ port, projectDir, open: shouldOpen, sections });
15
15
  console.log(chalk.green(` Platform running at ${chalk.bold(`http://localhost:${port}`)}`));
16
16
  console.log(chalk.gray(" Press Ctrl+C to stop\n"));
@@ -278,6 +278,11 @@ workspace: "${relPath}"
278
278
  }
279
279
  }
280
280
  }
281
+ const portalPath = path.join(cwd, "portal.yaml");
282
+ if (!fs.existsSync(portalPath)) {
283
+ const defaultPortal = { version: "1.0.0", gates: {}, routes: {} };
284
+ fs.writeFileSync(portalPath, yaml.dump(defaultPortal, { lineWidth: -1, noRefs: true }), "utf8");
285
+ }
281
286
  const lorePath = path.join(cwd, ".paradigm", "lore");
282
287
  if (!fs.existsSync(lorePath)) {
283
288
  fs.mkdirSync(lorePath, { recursive: true });
@@ -385,7 +390,7 @@ workspace: "${relPath}"
385
390
  { path: ".paradigm/agents.yaml", desc: "Team agent configuration" },
386
391
  { path: ".purpose", desc: "Root feature definitions" },
387
392
  { path: ".paradigm/lore/", desc: "Project lore timeline", isDir: true },
388
- { path: "portal.yaml", desc: "Authorization gates", optional: true },
393
+ { path: "portal.yaml", desc: "Authorization gates" },
389
394
  { path: "CLAUDE.md", desc: "Claude Code AI instructions" },
390
395
  { path: "AGENTS.md", desc: "Universal AI agent instructions" },
391
396
  { path: ".cursor/rules/", desc: "Cursor AI instructions", isDir: true },
@@ -429,7 +434,6 @@ workspace: "${relPath}"
429
434
  console.log(chalk.white(` ${nextStep++}. `) + chalk.gray("Run ") + chalk.cyan(`paradigm shift --workspace "${options.workspace}"`) + chalk.gray(" in sibling projects"));
430
435
  }
431
436
  console.log(chalk.white(` ${nextStep++}. `) + chalk.gray("Edit ") + chalk.cyan(".purpose") + chalk.gray(" to define your features"));
432
- console.log(chalk.white(` ${nextStep++}. `) + chalk.gray("Create ") + chalk.cyan("portal.yaml") + chalk.gray(" if you have authorization"));
433
437
  console.log(chalk.white(` ${nextStep++}. `) + chalk.gray("Add ") + chalk.cyan(".purpose") + chalk.gray(" files to feature directories"));
434
438
  console.log(chalk.white(` ${nextStep++}. `) + chalk.gray("Run ") + chalk.cyan("paradigm shift --verify") + chalk.gray(" to check health"));
435
439
  console.log("");