@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.
- package/dist/{chunk-SU3WDCRR.js → chunk-T3YGSZCI.js} +12 -0
- package/dist/conductor-CQVGTEQN.js +161 -0
- package/dist/{docs-J2BTKRVU.js → docs-AIY6VNF7.js} +1 -1
- package/dist/index.js +7 -7
- package/dist/mcp.js +2 -2
- package/dist/{platform-server-2D6S6YTK.js → platform-server-U5L2G3EU.js} +196 -15
- package/dist/{reindex-J5SEDVTT.js → reindex-KFUPB3ES.js} +1 -1
- package/dist/{serve-EFVRS4GA.js → serve-QWWJP2EW.js} +1 -1
- package/dist/{shift-VFG23DLA.js → shift-2NYRFVEZ.js} +6 -2
- package/dist/university-ui/assets/{index-BLWmLEDq.js → index-BjewBB6s.js} +2 -2
- package/dist/university-ui/assets/{index-BLWmLEDq.js.map → index-BjewBB6s.js.map} +1 -1
- package/dist/university-ui/index.html +1 -1
- package/package.json +1 -1
- package/platform-ui/dist/assets/AmbientSection-10pbwWjo.css +1 -0
- package/platform-ui/dist/assets/AmbientSection-WtHfNedO.js +1 -0
- package/platform-ui/dist/assets/CanvasSection-DwPTRdIN.js +9 -0
- package/platform-ui/dist/assets/CanvasSection-flMXU19z.css +1 -0
- package/platform-ui/dist/assets/{DocsSection-ByAgPzWV.js → DocsSection-BJc_ws4I.js} +1 -1
- package/platform-ui/dist/assets/{GitSection-BLovj9yT.js → GitSection-DhqBo1xc.js} +1 -1
- package/platform-ui/dist/assets/{GraphSection-C5PCPUFl.js → GraphSection-D9fhVnZ0.js} +1 -1
- package/platform-ui/dist/assets/{LoreSection-BftejTla.js → LoreSection-CwDDHrz9.js} +1 -1
- package/platform-ui/dist/assets/{SentinelSection-CnYcasN7.js → SentinelSection-Cl7e5oZ6.js} +1 -1
- package/platform-ui/dist/assets/{SymphonySection-BpmqCHeK.js → SymphonySection-BRoBaUSS.js} +1 -1
- package/platform-ui/dist/assets/TeamSection-CqSIMrKz.js +1 -0
- package/platform-ui/dist/assets/TeamSection-udxWQTcX.css +1 -0
- package/platform-ui/dist/assets/{index-G9JnWEs_.js → index-F0KL9xrN.js} +11 -11
- package/platform-ui/dist/index.html +1 -1
- 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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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
|
|
17
|
-
import * as
|
|
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 =
|
|
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 =
|
|
1137
|
-
if (
|
|
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 =
|
|
1144
|
-
if (
|
|
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 =
|
|
1189
|
-
if (!
|
|
1190
|
-
uiDistPath =
|
|
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 (
|
|
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(
|
|
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((
|
|
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
|
-
|
|
1460
|
+
resolve2();
|
|
1280
1461
|
});
|
|
1281
1462
|
httpServer.on("error", (err) => {
|
|
1282
1463
|
if (err.code === "EADDRINUSE") {
|
|
@@ -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-
|
|
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"
|
|
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("");
|