memory-journal-mcp 7.4.0 → 7.6.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/README.md +130 -98
- package/dist/{chunk-5ZA77VUW.js → chunk-NSEHC6MZ.js} +3361 -1253
- package/dist/{chunk-P5V2VY6N.js → chunk-SV3CKPMF.js} +9872 -7659
- package/dist/cli.js +236 -52
- package/dist/index.d.ts +272 -161
- package/dist/index.js +2 -4
- package/dist/tools-QF7CPU2H.js +1 -0
- package/dist/worker-script.js +113 -23
- package/package.json +5 -2
- package/skills/README.md +2 -0
- package/skills/github-commander/SKILL.md +1 -0
- package/skills/github-commander/workflows/copilot-audit.md +50 -0
- package/skills/github-copilot-cli/SKILL.md +64 -0
- package/skills/package.json +2 -1
- package/dist/chunk-OKOVZ5QE.js +0 -28
- package/dist/chunk-WXDEVIFL.js +0 -1745
- package/dist/github-integration-YODGZH3K.js +0 -1
- package/dist/tools-WZUENKJ6.js +0 -3
package/dist/cli.js
CHANGED
|
@@ -1,26 +1,31 @@
|
|
|
1
|
-
import { VERSION, createServer } from './chunk-
|
|
2
|
-
import {
|
|
3
|
-
import './chunk-OKOVZ5QE.js';
|
|
4
|
-
import { logger } from './chunk-WXDEVIFL.js';
|
|
1
|
+
import { VERSION, DEFAULT_AUDIT_LOG_MAX_SIZE_BYTES, createServer } from './chunk-NSEHC6MZ.js';
|
|
2
|
+
import { logger } from './chunk-SV3CKPMF.js';
|
|
5
3
|
import { Command } from 'commander';
|
|
4
|
+
import * as path from 'path';
|
|
6
5
|
import * as fs from 'fs';
|
|
6
|
+
import { z } from 'zod';
|
|
7
7
|
|
|
8
|
-
function
|
|
8
|
+
function parseConfigIntRequired(value, name, min, max) {
|
|
9
|
+
const parsed = parseInt(value, 10);
|
|
10
|
+
if (Number.isNaN(parsed)) {
|
|
11
|
+
throw new Error(`Invalid required numeric configuration for ${name}: ${value}`);
|
|
12
|
+
}
|
|
13
|
+
if (min !== void 0 && parsed < min) {
|
|
14
|
+
throw new Error(`Configuration ${name} must be at least ${min}`);
|
|
15
|
+
}
|
|
16
|
+
if (max !== void 0 && parsed > max) {
|
|
17
|
+
throw new Error(`Configuration ${name} must be at most ${max}`);
|
|
18
|
+
}
|
|
19
|
+
return parsed;
|
|
20
|
+
}
|
|
21
|
+
function resolveDbPath(envPath, defaultName) {
|
|
9
22
|
if (envPath) return envPath;
|
|
10
|
-
|
|
11
|
-
const testPath = `./test-server/${testName}`;
|
|
12
|
-
if (fs.existsSync(rootPath)) return rootPath;
|
|
13
|
-
if (fs.existsSync(testPath)) return testPath;
|
|
14
|
-
return rootPath;
|
|
23
|
+
return `./${defaultName}`;
|
|
15
24
|
}
|
|
16
|
-
var defaultDbPath = resolveDbPath(
|
|
17
|
-
process.env["DB_PATH"],
|
|
18
|
-
"memory_journal.db",
|
|
19
|
-
"test-memory-journal.db"
|
|
20
|
-
);
|
|
25
|
+
var defaultDbPath = resolveDbPath(process.env["DB_PATH"], "memory_journal.db");
|
|
21
26
|
var defaultTeamDbPath = process.env["TEAM_DB_PATH"] ? process.env["TEAM_DB_PATH"] : void 0;
|
|
22
27
|
var program = new Command();
|
|
23
|
-
program.name("memory-journal-mcp").description("Project context management for AI-assisted development").version(VERSION).option("--transport <type>", "Transport type: stdio or http", "stdio").option("--port <number>", "HTTP port (for http transport)", "3000").option("--server-host <host>", "Server bind host for HTTP transport (default: localhost)").option("--stateless", "Use stateless HTTP mode (no session management)").option("--db <path>", "Database path (env: DB_PATH)", defaultDbPath).option("--team-db <path>", "Team database path (env: TEAM_DB_PATH)", defaultTeamDbPath).option("--tool-filter <filter>", 'Tool filter string (e.g., "starter", "core,search")').option("--default-project <number>", "Default GitHub Project number").option("--auto-rebuild-index", "Rebuild vector index on server startup").option("--cors-origin <origin>", "CORS allowed origin for HTTP transport (default:
|
|
28
|
+
program.name("memory-journal-mcp").description("Project context management for AI-assisted development").version(VERSION).option("--transport <type>", "Transport type: stdio or http", "stdio").option("--port <number>", "HTTP port (for http transport)", "3000").option("--server-host <host>", "Server bind host for HTTP transport (default: localhost)").option("--stateless", "Use stateless HTTP mode (no session management)").option("--db <path>", "Database path (env: DB_PATH)", defaultDbPath).option("--team-db <path>", "Team database path (env: TEAM_DB_PATH)", defaultTeamDbPath).option("--tool-filter <filter>", 'Tool filter string (e.g., "starter", "core,search")').option("--default-project <number>", "Default GitHub Project number").option("--auto-rebuild-index", "Rebuild vector index on server startup").option("--cors-origin <origin>", "CORS allowed origin for HTTP transport (default: none)").option("--enable-hsts", "Enable HSTS header for HTTP transport (use when behind HTTPS)").option(
|
|
24
29
|
"--auth-token <token>",
|
|
25
30
|
"Bearer token for HTTP transport authentication (env: MCP_AUTH_TOKEN)"
|
|
26
31
|
).option("--log-level <level>", "Log level: debug, info, warning, error", "info").option(
|
|
@@ -39,10 +44,6 @@ program.name("memory-journal-mcp").description("Project context management for A
|
|
|
39
44
|
"--digest-interval <minutes>",
|
|
40
45
|
"Analytics digest interval in minutes, HTTP only (0 = disabled; recommended: 1440 for daily)",
|
|
41
46
|
"0"
|
|
42
|
-
).option(
|
|
43
|
-
"--sandbox-mode <mode>",
|
|
44
|
-
'Code Mode sandbox: "worker" (production, default) or "vm" (lightweight)',
|
|
45
|
-
"worker"
|
|
46
47
|
).option(
|
|
47
48
|
"--codemode-max-result-size <bytes>",
|
|
48
49
|
"Maximum Code Mode result size in bytes (default: 102400 / 100KB, env: CODE_MODE_MAX_RESULT_SIZE)"
|
|
@@ -50,10 +51,19 @@ program.name("memory-journal-mcp").description("Project context management for A
|
|
|
50
51
|
"--oauth-clock-tolerance <seconds>",
|
|
51
52
|
"OAuth clock tolerance in seconds (default: 60)",
|
|
52
53
|
"60"
|
|
54
|
+
).option(
|
|
55
|
+
"--oauth-allow-plaintext-loopback",
|
|
56
|
+
"Allow plaintext loopback OAuth issuer (env: OAUTH_ALLOW_PLAINTEXT_LOOPBACK)"
|
|
57
|
+
).option("--trust-proxy", "Trust reverse proxy headers (e.g. X-Forwarded-For env: TRUST_PROXY)").option(
|
|
58
|
+
"--public-origin <url>",
|
|
59
|
+
"Public origin URL for webhook verification and OAuth redirects (env: PUBLIC_ORIGIN)"
|
|
53
60
|
).option(
|
|
54
61
|
"--audit-log <path>",
|
|
55
62
|
'Enable audit logging to the specified JSONL file path, or "stderr" for container mode (env: AUDIT_LOG_PATH)'
|
|
56
|
-
).option(
|
|
63
|
+
).option(
|
|
64
|
+
"--no-audit-redact",
|
|
65
|
+
"Disable redaction of tool arguments from audit entries (env: AUDIT_REDACT=false)"
|
|
66
|
+
).option(
|
|
57
67
|
"--audit-reads",
|
|
58
68
|
"Enable audit logging for read-scoped tool calls (default: off, env: AUDIT_READS)"
|
|
59
69
|
).option(
|
|
@@ -64,6 +74,12 @@ program.name("memory-journal-mcp").description("Project context management for A
|
|
|
64
74
|
"--instruction-level <level>",
|
|
65
75
|
"Briefing depth: essential, standard, full (env: INSTRUCTION_LEVEL)",
|
|
66
76
|
"standard"
|
|
77
|
+
).option(
|
|
78
|
+
"--allowed-io-roots <paths>",
|
|
79
|
+
"Comma-separated absolute paths or JSON array of paths for strict filesystem jailing (env: ALLOWED_IO_ROOTS)"
|
|
80
|
+
).option(
|
|
81
|
+
"--codemode-internal-full-access",
|
|
82
|
+
"Bypass tool filter constraints within the Code Mode sandbox (env: CODEMODE_INTERNAL_FULL_ACCESS)"
|
|
67
83
|
).option(
|
|
68
84
|
"--briefing-entries <count>",
|
|
69
85
|
"Number of journal entries in briefing (env: BRIEFING_ENTRY_COUNT)",
|
|
@@ -109,9 +125,27 @@ program.name("memory-journal-mcp").description("Project context management for A
|
|
|
109
125
|
).option(
|
|
110
126
|
"--workflow-summary <text>",
|
|
111
127
|
"Workflow summary for memory://workflows resource (env: MEMORY_JOURNAL_WORKFLOW_SUMMARY)"
|
|
128
|
+
).option(
|
|
129
|
+
"--flag-vocabulary <terms>",
|
|
130
|
+
"Comma-separated flag vocabulary for Hush Protocol (env: FLAG_VOCABULARY, default: blocker,needs_review,help_requested,fyi)"
|
|
112
131
|
).action(
|
|
113
132
|
async (options) => {
|
|
114
133
|
logger.setLevel(options.logLevel);
|
|
134
|
+
const sensitiveEnvVars = [
|
|
135
|
+
"GITHUB_TOKEN",
|
|
136
|
+
"MCP_AUTH_TOKEN",
|
|
137
|
+
"OAUTH_ISSUER",
|
|
138
|
+
"OAUTH_JWKS_URI"
|
|
139
|
+
];
|
|
140
|
+
for (const envVar of sensitiveEnvVars) {
|
|
141
|
+
if (process.env[envVar]?.startsWith("CHANGEME_")) {
|
|
142
|
+
logger.error(
|
|
143
|
+
`FATAL: Insecure configuration detected. ${envVar} contains default placeholder value. Please update your environment variables.`,
|
|
144
|
+
{ module: "CLI" }
|
|
145
|
+
);
|
|
146
|
+
process.exit(1);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
115
149
|
const host = options.serverHost ?? process.env["MCP_HOST"] ?? process.env["HOST"] ?? void 0;
|
|
116
150
|
logger.info("Starting Memory Journal MCP Server", {
|
|
117
151
|
module: "CLI",
|
|
@@ -130,94 +164,244 @@ program.name("memory-journal-mcp").description("Project context management for A
|
|
|
130
164
|
const auditConfig = auditLogPath ? {
|
|
131
165
|
enabled: true,
|
|
132
166
|
logPath: auditLogPath,
|
|
133
|
-
redact: options.auditRedact ?? process.env["AUDIT_REDACT"] === "true",
|
|
167
|
+
redact: options.auditRedact ?? (process.env["AUDIT_REDACT"] ? process.env["AUDIT_REDACT"] === "true" : true),
|
|
134
168
|
auditReads: options.auditReads ?? process.env["AUDIT_READS"] === "true",
|
|
135
|
-
maxSizeBytes:
|
|
169
|
+
maxSizeBytes: parseConfigIntRequired(
|
|
136
170
|
process.env["AUDIT_LOG_MAX_SIZE"] ?? options.auditLogMaxSize,
|
|
137
|
-
|
|
171
|
+
"audit-log-max-size",
|
|
172
|
+
1024
|
|
138
173
|
)
|
|
139
174
|
} : void 0;
|
|
140
175
|
await createServer({
|
|
141
176
|
transport: options.transport,
|
|
142
|
-
port:
|
|
177
|
+
port: parseConfigIntRequired(options.port, "port", 1, 65535),
|
|
143
178
|
host,
|
|
144
179
|
statelessHttp: options.stateless === true,
|
|
145
180
|
dbPath: options.db,
|
|
146
181
|
teamDbPath: options.teamDb,
|
|
147
182
|
toolFilter: options.toolFilter,
|
|
148
|
-
defaultProjectNumber: options.defaultProject ?
|
|
183
|
+
defaultProjectNumber: options.defaultProject ? parseConfigIntRequired(options.defaultProject, "default-project", 1) : process.env["DEFAULT_PROJECT_NUMBER"] ? parseConfigIntRequired(
|
|
184
|
+
process.env["DEFAULT_PROJECT_NUMBER"],
|
|
185
|
+
"DEFAULT_PROJECT_NUMBER",
|
|
186
|
+
1
|
|
187
|
+
) : void 0,
|
|
149
188
|
autoRebuildIndex: options.autoRebuildIndex ?? process.env["AUTO_REBUILD_INDEX"] === "true",
|
|
150
189
|
corsOrigins: options.corsOrigin ? options.corsOrigin.split(",").map((s) => s.trim()) : void 0,
|
|
151
190
|
enableHSTS: options.enableHsts ?? process.env["MCP_ENABLE_HSTS"] === "true",
|
|
152
191
|
authToken: options.authToken,
|
|
153
192
|
scheduler: {
|
|
154
|
-
backupIntervalMinutes:
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
193
|
+
backupIntervalMinutes: parseConfigIntRequired(
|
|
194
|
+
options.backupInterval,
|
|
195
|
+
"backup-interval",
|
|
196
|
+
0
|
|
197
|
+
),
|
|
198
|
+
keepBackups: parseConfigIntRequired(
|
|
199
|
+
options.keepBackups,
|
|
200
|
+
"keep-backups",
|
|
201
|
+
1,
|
|
202
|
+
100
|
|
203
|
+
),
|
|
204
|
+
vacuumIntervalMinutes: parseConfigIntRequired(
|
|
205
|
+
options.vacuumInterval,
|
|
206
|
+
"vacuum-interval",
|
|
207
|
+
0
|
|
208
|
+
),
|
|
209
|
+
rebuildIndexIntervalMinutes: parseConfigIntRequired(
|
|
210
|
+
options.rebuildIndexInterval,
|
|
211
|
+
"rebuild-index-interval",
|
|
212
|
+
0
|
|
213
|
+
),
|
|
214
|
+
digestIntervalMinutes: parseConfigIntRequired(
|
|
215
|
+
options.digestInterval,
|
|
216
|
+
"digest-interval",
|
|
217
|
+
0
|
|
218
|
+
)
|
|
159
219
|
},
|
|
160
|
-
sandboxMode: options.sandboxMode,
|
|
161
220
|
// OAuth 2.1
|
|
162
221
|
oauthEnabled: options.oauthEnabled ?? process.env["OAUTH_ENABLED"] === "true",
|
|
163
222
|
oauthIssuer: options.oauthIssuer ?? process.env["OAUTH_ISSUER"],
|
|
164
223
|
oauthAudience: options.oauthAudience ?? process.env["OAUTH_AUDIENCE"],
|
|
165
224
|
oauthJwksUri: options.oauthJwksUri ?? process.env["OAUTH_JWKS_URI"],
|
|
166
|
-
oauthClockTolerance:
|
|
225
|
+
oauthClockTolerance: parseConfigIntRequired(
|
|
167
226
|
process.env["OAUTH_CLOCK_TOLERANCE"] ?? options.oauthClockTolerance,
|
|
168
|
-
|
|
227
|
+
"oauth-clock-tolerance",
|
|
228
|
+
0,
|
|
229
|
+
3600
|
|
169
230
|
),
|
|
231
|
+
allowPlaintextLoopbackOAuth: options.oauthAllowPlaintextLoopback ?? process.env["OAUTH_ALLOW_PLAINTEXT_LOOPBACK"] === "true",
|
|
232
|
+
trustProxy: options.trustProxy ?? process.env["TRUST_PROXY"] === "true",
|
|
233
|
+
publicOrigin: options.publicOrigin ?? process.env["PUBLIC_ORIGIN"],
|
|
234
|
+
codemodeInternalFullAccess: options.codemodeInternalFullAccess ?? process.env["CODEMODE_INTERNAL_FULL_ACCESS"] === "true",
|
|
170
235
|
// Project Registry
|
|
171
236
|
projectRegistry: (() => {
|
|
172
237
|
const raw = process.env["PROJECT_REGISTRY"];
|
|
173
238
|
if (!raw) return void 0;
|
|
239
|
+
if (raw.length > 51200) {
|
|
240
|
+
throw new Error(
|
|
241
|
+
"PROJECT_REGISTRY environment variable exceeds size limit (50KB)"
|
|
242
|
+
);
|
|
243
|
+
}
|
|
174
244
|
try {
|
|
175
|
-
|
|
245
|
+
const registrySchema = z.record(
|
|
246
|
+
z.string(),
|
|
247
|
+
z.object({
|
|
248
|
+
path: z.string().min(1),
|
|
249
|
+
project_number: z.number().nullable().optional()
|
|
250
|
+
}).strict()
|
|
251
|
+
);
|
|
252
|
+
const parsed = JSON.parse(raw);
|
|
253
|
+
const deepClean = (obj) => {
|
|
254
|
+
if (obj === null || typeof obj !== "object") return obj;
|
|
255
|
+
if (Array.isArray(obj)) return obj.map(deepClean);
|
|
256
|
+
const out = {};
|
|
257
|
+
for (const key of Object.keys(obj)) {
|
|
258
|
+
if (key === "__proto__" || key === "constructor" || key === "prototype")
|
|
259
|
+
continue;
|
|
260
|
+
out[key] = deepClean(obj[key]);
|
|
261
|
+
}
|
|
262
|
+
return out;
|
|
263
|
+
};
|
|
264
|
+
const safeParsed = deepClean(parsed);
|
|
265
|
+
const validated = registrySchema.parse(safeParsed);
|
|
266
|
+
for (const key of Object.keys(validated)) {
|
|
267
|
+
const entry = validated[key];
|
|
268
|
+
if (!entry?.path) continue;
|
|
269
|
+
if (!path.isAbsolute(entry.path)) {
|
|
270
|
+
throw new Error(
|
|
271
|
+
`Project registry path must be an absolute path: ${entry.path}`
|
|
272
|
+
);
|
|
273
|
+
}
|
|
274
|
+
const resolvedPath = path.resolve(entry.path);
|
|
275
|
+
try {
|
|
276
|
+
const stat = fs.lstatSync(resolvedPath);
|
|
277
|
+
if (stat.isSymbolicLink()) {
|
|
278
|
+
throw new Error(
|
|
279
|
+
`Project registry path cannot be a symlink (symlink traversal protection): ${resolvedPath}`
|
|
280
|
+
);
|
|
281
|
+
}
|
|
282
|
+
if (!stat.isDirectory()) {
|
|
283
|
+
throw new Error(
|
|
284
|
+
`Project registry path is not a directory: ${resolvedPath}`
|
|
285
|
+
);
|
|
286
|
+
}
|
|
287
|
+
} catch (e) {
|
|
288
|
+
const errMsg = e instanceof Error ? e.message : String(e);
|
|
289
|
+
throw new Error(
|
|
290
|
+
`Project registry path does not exist or cannot be accessed: ${resolvedPath} (${errMsg})`,
|
|
291
|
+
{ cause: e }
|
|
292
|
+
);
|
|
293
|
+
}
|
|
294
|
+
entry.path = resolvedPath;
|
|
295
|
+
}
|
|
296
|
+
return validated;
|
|
176
297
|
} catch (e) {
|
|
177
298
|
const errName = e instanceof Error ? e.message : String(e);
|
|
178
299
|
throw new Error(
|
|
179
|
-
`Failed to parse PROJECT_REGISTRY environment variable. Must be valid JSON: ${errName}`,
|
|
300
|
+
`Failed to parse PROJECT_REGISTRY environment variable. Must be valid JSON and safe paths: ${errName}`,
|
|
180
301
|
{ cause: e }
|
|
181
302
|
);
|
|
182
303
|
}
|
|
183
304
|
})(),
|
|
305
|
+
// Allowed IO Roots
|
|
306
|
+
allowedIoRoots: (() => {
|
|
307
|
+
const raw = options.allowedIoRoots ?? process.env["ALLOWED_IO_ROOTS"];
|
|
308
|
+
if (!raw) return void 0;
|
|
309
|
+
if (raw.length > 51200) {
|
|
310
|
+
throw new Error(
|
|
311
|
+
"ALLOWED_IO_ROOTS configuration exceeds size limit (50KB)"
|
|
312
|
+
);
|
|
313
|
+
}
|
|
314
|
+
try {
|
|
315
|
+
if (raw.trim().startsWith("[")) {
|
|
316
|
+
const parsed = JSON.parse(raw);
|
|
317
|
+
if (Array.isArray(parsed) && parsed.every((p) => typeof p === "string" && path.isAbsolute(p))) {
|
|
318
|
+
const result = parsed;
|
|
319
|
+
for (const p of result) {
|
|
320
|
+
try {
|
|
321
|
+
if (!fs.existsSync(p)) {
|
|
322
|
+
console.warn(
|
|
323
|
+
`
|
|
324
|
+
[WARN] ALLOWED_IO_ROOTS path does not exist: ${p}
|
|
325
|
+
`
|
|
326
|
+
);
|
|
327
|
+
}
|
|
328
|
+
} catch {
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
return result;
|
|
332
|
+
}
|
|
333
|
+
throw new Error("Must be an array of absolute paths");
|
|
334
|
+
}
|
|
335
|
+
const parts = raw.split(",").map((s) => s.trim()).filter(Boolean);
|
|
336
|
+
if (parts.some((p) => !path.isAbsolute(p))) {
|
|
337
|
+
throw new Error("All paths must be absolute");
|
|
338
|
+
}
|
|
339
|
+
for (const p of parts) {
|
|
340
|
+
try {
|
|
341
|
+
if (!fs.existsSync(p)) {
|
|
342
|
+
console.warn(
|
|
343
|
+
`
|
|
344
|
+
[WARN] ALLOWED_IO_ROOTS path does not exist: ${p}
|
|
345
|
+
`
|
|
346
|
+
);
|
|
347
|
+
}
|
|
348
|
+
} catch {
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
return parts;
|
|
352
|
+
} catch (e) {
|
|
353
|
+
const errName = e instanceof Error ? e.message : String(e);
|
|
354
|
+
throw new Error(`Invalid ALLOWED_IO_ROOTS configuration: ${errName}`, {
|
|
355
|
+
cause: e
|
|
356
|
+
});
|
|
357
|
+
}
|
|
358
|
+
})(),
|
|
184
359
|
// Briefing configuration
|
|
185
360
|
briefingConfig: {
|
|
186
|
-
entryCount:
|
|
361
|
+
entryCount: parseConfigIntRequired(
|
|
187
362
|
process.env["BRIEFING_ENTRY_COUNT"] ?? options.briefingEntries,
|
|
188
|
-
|
|
363
|
+
"briefing-entries"
|
|
189
364
|
),
|
|
190
|
-
summaryCount:
|
|
365
|
+
summaryCount: parseConfigIntRequired(
|
|
191
366
|
process.env["BRIEFING_SUMMARY_COUNT"] ?? options.briefingSummaries,
|
|
192
|
-
|
|
367
|
+
"briefing-summaries"
|
|
193
368
|
),
|
|
194
369
|
includeTeam: options.briefingIncludeTeam ?? process.env["BRIEFING_INCLUDE_TEAM"] === "true",
|
|
195
|
-
issueCount:
|
|
370
|
+
issueCount: parseConfigIntRequired(
|
|
196
371
|
process.env["BRIEFING_ISSUE_COUNT"] ?? options.briefingIssues,
|
|
197
|
-
|
|
372
|
+
"briefing-issues"
|
|
198
373
|
),
|
|
199
|
-
prCount:
|
|
374
|
+
prCount: parseConfigIntRequired(
|
|
200
375
|
process.env["BRIEFING_PR_COUNT"] ?? options.briefingPrs,
|
|
201
|
-
|
|
376
|
+
"briefing-prs"
|
|
202
377
|
),
|
|
203
378
|
prStatusBreakdown: options.briefingPrStatus ?? process.env["BRIEFING_PR_STATUS"] === "true",
|
|
204
|
-
milestoneCount:
|
|
379
|
+
milestoneCount: parseConfigIntRequired(
|
|
205
380
|
process.env["BRIEFING_MILESTONE_COUNT"] ?? options.briefingMilestones,
|
|
206
|
-
|
|
381
|
+
"briefing-milestones"
|
|
207
382
|
),
|
|
208
|
-
rulesFilePath: options.rulesFile
|
|
209
|
-
skillsDirPath: options.skillsDir
|
|
210
|
-
workflowCount:
|
|
383
|
+
rulesFilePath: options.rulesFile ? path.resolve(process.cwd(), options.rulesFile) : process.env["RULES_FILE_PATH"] ? path.resolve(process.cwd(), process.env["RULES_FILE_PATH"]) : void 0,
|
|
384
|
+
skillsDirPath: options.skillsDir ? path.resolve(process.cwd(), options.skillsDir) : process.env["SKILLS_DIR_PATH"] ? path.resolve(process.cwd(), process.env["SKILLS_DIR_PATH"]) : void 0,
|
|
385
|
+
workflowCount: parseConfigIntRequired(
|
|
211
386
|
process.env["BRIEFING_WORKFLOW_COUNT"] ?? options.briefingWorkflows,
|
|
212
|
-
|
|
387
|
+
"briefing-workflows"
|
|
213
388
|
),
|
|
214
389
|
workflowStatusBreakdown: options.briefingWorkflowStatus ?? process.env["BRIEFING_WORKFLOW_STATUS"] === "true",
|
|
215
390
|
copilotReviews: options.briefingCopilot ?? process.env["BRIEFING_COPILOT_REVIEWS"] === "true",
|
|
216
391
|
workflowSummary: options.workflowSummary ?? process.env["MEMORY_JOURNAL_WORKFLOW_SUMMARY"] ?? void 0,
|
|
217
|
-
defaultProjectNumber: options.defaultProject ?
|
|
392
|
+
defaultProjectNumber: options.defaultProject ? parseConfigIntRequired(options.defaultProject, "default-project", 1) : process.env["DEFAULT_PROJECT_NUMBER"] ? parseConfigIntRequired(
|
|
393
|
+
process.env["DEFAULT_PROJECT_NUMBER"],
|
|
394
|
+
"DEFAULT_PROJECT_NUMBER",
|
|
395
|
+
1
|
|
396
|
+
) : void 0
|
|
218
397
|
},
|
|
219
398
|
instructionLevel: options.instructionLevel !== "standard" ? options.instructionLevel : process.env["INSTRUCTION_LEVEL"] ?? "standard",
|
|
220
|
-
auditConfig
|
|
399
|
+
auditConfig,
|
|
400
|
+
flagVocabulary: (() => {
|
|
401
|
+
const raw = options.flagVocabulary ?? process.env["FLAG_VOCABULARY"];
|
|
402
|
+
if (!raw) return void 0;
|
|
403
|
+
return raw.split(",").map((s) => s.trim().toLowerCase()).filter(Boolean);
|
|
404
|
+
})()
|
|
221
405
|
});
|
|
222
406
|
} catch (error) {
|
|
223
407
|
logger.error("Failed to start server", {
|