overlord-cli 3.23.0 → 3.25.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/bin/_cli/auth.mjs +12 -6
- package/bin/_cli/credentials.mjs +36 -20
- package/bin/_cli/protocol.mjs +42 -6
- package/bin/_cli/setup.mjs +7 -7
- package/package.json +1 -1
- package/plugins/overlord/scripts/overlord-mcp.mjs +44 -12
- package/plugins/overlord/skills/overlord-ticket-workflow/SKILL.md +1 -1
package/bin/_cli/auth.mjs
CHANGED
|
@@ -5,9 +5,15 @@ import { execFileSync } from 'node:child_process';
|
|
|
5
5
|
import crypto from 'node:crypto';
|
|
6
6
|
import http from 'node:http';
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
buildAuthHeaders,
|
|
10
|
+
clearCredentials,
|
|
11
|
+
getDefaultOverlordUrl,
|
|
12
|
+
loadCredentials,
|
|
13
|
+
loadRuntime,
|
|
14
|
+
saveCredentials
|
|
15
|
+
} from './credentials.mjs';
|
|
9
16
|
|
|
10
|
-
const DEFAULT_OVERLORD_URL = process.env.OVERLORD_URL ?? 'https://ovld.ai';
|
|
11
17
|
const DEFAULT_CLI_REDIRECT_URI = 'http://127.0.0.1:45619/callback';
|
|
12
18
|
const DEFAULT_DEVICE_POLL_INTERVAL_SECONDS = 5;
|
|
13
19
|
|
|
@@ -412,13 +418,13 @@ export async function authLoginViaOAuthLoopback(platformUrl, localSecret) {
|
|
|
412
418
|
// Public auth commands
|
|
413
419
|
// ---------------------------------------------------------------------------
|
|
414
420
|
|
|
415
|
-
export function resolveLoginPlatformUrl(runtime =
|
|
416
|
-
return process.env.OVERLORD_URL ?? runtime?.platform_url ??
|
|
421
|
+
export function resolveLoginPlatformUrl(runtime = null) {
|
|
422
|
+
return process.env.OVERLORD_URL ?? runtime?.platform_url ?? getDefaultOverlordUrl();
|
|
417
423
|
}
|
|
418
424
|
|
|
419
425
|
export async function authLogin() {
|
|
420
|
-
const
|
|
421
|
-
const
|
|
426
|
+
const platformUrl = resolveLoginPlatformUrl();
|
|
427
|
+
const runtime = loadRuntime(platformUrl);
|
|
422
428
|
const localSecret = runtime?.local_secret ?? process.env.OVERLORD_LOCAL_SECRET ?? '';
|
|
423
429
|
|
|
424
430
|
console.log('Starting Overlord CLI authorization...\n');
|
package/bin/_cli/credentials.mjs
CHANGED
|
@@ -5,11 +5,13 @@
|
|
|
5
5
|
import fs from 'node:fs';
|
|
6
6
|
import os from 'node:os';
|
|
7
7
|
import path from 'node:path';
|
|
8
|
+
import { fileURLToPath } from 'node:url';
|
|
8
9
|
|
|
9
10
|
const CREDENTIALS_DIR = path.join(os.homedir(), '.ovld');
|
|
10
11
|
const CREDENTIALS_FILE = path.join(CREDENTIALS_DIR, 'credentials.json');
|
|
11
12
|
const RUNTIME_FILE_PATTERN = /^runtime\..+\.json$/;
|
|
12
|
-
const
|
|
13
|
+
const HOSTED_OVERLORD_URL = 'https://www.ovld.ai';
|
|
14
|
+
const LOCAL_DEV_OVERLORD_URL = 'http://localhost:3000';
|
|
13
15
|
const LOCAL_SECRET_HEADER = 'X-Overlord-Local-Secret';
|
|
14
16
|
|
|
15
17
|
/**
|
|
@@ -139,6 +141,14 @@ function isLocalhostUrl(value) {
|
|
|
139
141
|
}
|
|
140
142
|
}
|
|
141
143
|
|
|
144
|
+
function isLocalDevOverlordUrl(value) {
|
|
145
|
+
try {
|
|
146
|
+
return new URL(value).origin === LOCAL_DEV_OVERLORD_URL;
|
|
147
|
+
} catch {
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
142
152
|
function isSupportedPlatformUrl(value) {
|
|
143
153
|
try {
|
|
144
154
|
const parsed = new URL(value);
|
|
@@ -198,37 +208,33 @@ export function buildAuthHeaders(token, localSecret) {
|
|
|
198
208
|
return headers;
|
|
199
209
|
}
|
|
200
210
|
|
|
211
|
+
export function getDefaultOverlordUrl() {
|
|
212
|
+
return isLocalDevCli() ? LOCAL_DEV_OVERLORD_URL : HOSTED_OVERLORD_URL;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function isLocalDevCli() {
|
|
216
|
+
const sourcePath = fileURLToPath(import.meta.url);
|
|
217
|
+
return !sourcePath.split(path.sep).includes('node_modules');
|
|
218
|
+
}
|
|
219
|
+
|
|
201
220
|
/**
|
|
202
221
|
* Resolve the overlord URL and agent token from credentials file or env vars.
|
|
203
222
|
* @returns {{ platformUrl: string, agentToken: string }}
|
|
204
223
|
*/
|
|
205
224
|
export function resolveAuth() {
|
|
206
225
|
const creds = loadCredentials();
|
|
207
|
-
const connectorUrlFromEnv = normalizePlatformUrl(process.env.OVERLORD_CONNECTOR_URL);
|
|
208
226
|
const overlordUrlFromEnv = normalizePlatformUrl(process.env.OVERLORD_URL);
|
|
209
|
-
const overlordUrlFromCreds =
|
|
210
|
-
|
|
211
|
-
const
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
: null;
|
|
215
|
-
const targetedRuntime = loadRuntime(runtimeTarget ?? null);
|
|
216
|
-
const fallbackRuntime = targetedRuntime ?? loadRuntime(null);
|
|
217
|
-
const runtime =
|
|
218
|
-
targetedRuntime && isLocalhostUrl(targetedRuntime.platform_url)
|
|
219
|
-
? targetedRuntime
|
|
220
|
-
: fallbackRuntime && isLocalhostUrl(fallbackRuntime.platform_url)
|
|
221
|
-
? fallbackRuntime
|
|
222
|
-
: targetedRuntime;
|
|
227
|
+
const overlordUrlFromCreds = normalizeStoredPlatformUrl(creds?.platform_url);
|
|
228
|
+
|
|
229
|
+
const runtime = overlordUrlFromEnv && isLocalhostUrl(overlordUrlFromEnv)
|
|
230
|
+
? loadRuntime(overlordUrlFromEnv)
|
|
231
|
+
: null;
|
|
223
232
|
const runtimeOverlordUrl = runtime?.platform_url;
|
|
224
233
|
|
|
225
234
|
const platformUrl =
|
|
226
|
-
connectorUrlFromEnv ??
|
|
227
|
-
(overlordUrlFromEnv && isLocalhostUrl(overlordUrlFromEnv) ? overlordUrlFromEnv : undefined) ??
|
|
228
|
-
runtimeOverlordUrl ??
|
|
229
235
|
overlordUrlFromEnv ??
|
|
230
236
|
overlordUrlFromCreds ??
|
|
231
|
-
|
|
237
|
+
getDefaultOverlordUrl();
|
|
232
238
|
const localSecret =
|
|
233
239
|
runtime &&
|
|
234
240
|
runtime.local_secret &&
|
|
@@ -260,8 +266,18 @@ function normalizePlatformUrl(value) {
|
|
|
260
266
|
try {
|
|
261
267
|
const parsed = new URL(trimmed);
|
|
262
268
|
if (!isSupportedPlatformUrl(parsed.toString())) return undefined;
|
|
269
|
+
if (parsed.protocol === 'https:' && parsed.hostname === 'ovld.ai') {
|
|
270
|
+
return HOSTED_OVERLORD_URL;
|
|
271
|
+
}
|
|
263
272
|
return parsed.origin;
|
|
264
273
|
} catch {
|
|
265
274
|
return undefined;
|
|
266
275
|
}
|
|
267
276
|
}
|
|
277
|
+
|
|
278
|
+
function normalizeStoredPlatformUrl(value) {
|
|
279
|
+
const normalized = normalizePlatformUrl(value);
|
|
280
|
+
if (!normalized) return undefined;
|
|
281
|
+
if (isLocalhostUrl(normalized) && !isLocalDevOverlordUrl(normalized)) return undefined;
|
|
282
|
+
return normalized;
|
|
283
|
+
}
|
package/bin/_cli/protocol.mjs
CHANGED
|
@@ -189,6 +189,37 @@ function readJsonFile(filePath, label) {
|
|
|
189
189
|
}
|
|
190
190
|
}
|
|
191
191
|
|
|
192
|
+
async function readTextFromStdin(label) {
|
|
193
|
+
const chunks = [];
|
|
194
|
+
try {
|
|
195
|
+
for await (const chunk of process.stdin) {
|
|
196
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk)));
|
|
197
|
+
}
|
|
198
|
+
} catch (err) {
|
|
199
|
+
throw new Error(
|
|
200
|
+
`${label}: could not read stdin: ${err instanceof Error ? err.message : String(err)}`
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
return Buffer.concat(chunks).toString('utf8');
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
async function readJsonFileOrStdin(filePath, label) {
|
|
207
|
+
if (filePath !== '-') {
|
|
208
|
+
return readJsonFile(filePath, label);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
try {
|
|
212
|
+
return JSON.parse(await readTextFromStdin(label));
|
|
213
|
+
} catch (err) {
|
|
214
|
+
if (err instanceof Error && err.message.startsWith(`${label}: could not read stdin`)) {
|
|
215
|
+
throw err;
|
|
216
|
+
}
|
|
217
|
+
throw new Error(
|
|
218
|
+
`${label}: could not parse stdin: ${err instanceof Error ? err.message : String(err)}`
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
192
223
|
// ---------------------------------------------------------------------------
|
|
193
224
|
// changeRationales helper
|
|
194
225
|
// ---------------------------------------------------------------------------
|
|
@@ -200,7 +231,10 @@ function readJsonFile(filePath, label) {
|
|
|
200
231
|
*/
|
|
201
232
|
async function resolveChangeRationales(flags) {
|
|
202
233
|
if (flags['change-rationales-file']) {
|
|
203
|
-
return
|
|
234
|
+
return await readJsonFileOrStdin(
|
|
235
|
+
String(flags['change-rationales-file']),
|
|
236
|
+
'--change-rationales-file'
|
|
237
|
+
);
|
|
204
238
|
}
|
|
205
239
|
if (flags['change-rationales-json']) {
|
|
206
240
|
try {
|
|
@@ -624,7 +658,7 @@ async function protocolDeliver(args) {
|
|
|
624
658
|
if (!sessionKey) throw new Error('--session-key is required (or set SESSION_KEY)');
|
|
625
659
|
if (!ticketId) throw new Error('--ticket-id is required (or set TICKET_ID)');
|
|
626
660
|
const deliverPayload = flags['payload-file']
|
|
627
|
-
?
|
|
661
|
+
? await readJsonFileOrStdin(String(flags['payload-file']), '--payload-file')
|
|
628
662
|
: null;
|
|
629
663
|
const summary = deliverPayload?.summary ??
|
|
630
664
|
(flags['summary-file']
|
|
@@ -642,7 +676,7 @@ async function protocolDeliver(args) {
|
|
|
642
676
|
throw new Error('Use either --payload-file or --artifacts-json, not both');
|
|
643
677
|
}
|
|
644
678
|
if (flags['artifacts-file']) {
|
|
645
|
-
artifacts =
|
|
679
|
+
artifacts = await readJsonFileOrStdin(String(flags['artifacts-file']), '--artifacts-file');
|
|
646
680
|
} else if (flags['artifacts-json']) {
|
|
647
681
|
try {
|
|
648
682
|
artifacts = JSON.parse(String(flags['artifacts-json']));
|
|
@@ -1144,14 +1178,15 @@ deliver:
|
|
|
1144
1178
|
--session-key <key>
|
|
1145
1179
|
--ticket-id <id>
|
|
1146
1180
|
--summary <text> or --summary-file <path>
|
|
1147
|
-
or: --payload-file <path
|
|
1181
|
+
or: --payload-file <path|-> containing { summary, artifacts, changeRationales }
|
|
1148
1182
|
Optional:
|
|
1149
1183
|
--artifacts-json <json>
|
|
1150
|
-
--artifacts-file <path
|
|
1184
|
+
--artifacts-file <path|->
|
|
1151
1185
|
--change-rationales-json <json>
|
|
1152
|
-
--change-rationales-file <path
|
|
1186
|
+
--change-rationales-file <path|->
|
|
1153
1187
|
--skip-file-change-check Bypass local git vs changeRationales validation
|
|
1154
1188
|
Notes:
|
|
1189
|
+
Use --payload-file - to read the full delivery JSON from stdin without creating a scratch file.
|
|
1155
1190
|
Do not combine --payload-file with --artifacts-json/--artifacts-file or change-rationale flags.
|
|
1156
1191
|
In a git workspace, deliver validates that changed files are represented by changeRationales unless skipped.
|
|
1157
1192
|
|
|
@@ -1243,6 +1278,7 @@ Examples:
|
|
|
1243
1278
|
ovld protocol deliver --session-key <key> --ticket-id <id> --summary "Done"
|
|
1244
1279
|
ovld protocol deliver --session-key <key> --ticket-id <id> --summary "Done" --artifacts-file ./artifacts.json
|
|
1245
1280
|
ovld protocol deliver --session-key <key> --ticket-id <id> --payload-file ./deliver.json
|
|
1281
|
+
ovld protocol deliver --session-key <key> --ticket-id <id> --payload-file -
|
|
1246
1282
|
ovld protocol deliver --session-key <key> --ticket-id <id> --summary "Done" --skip-file-change-check
|
|
1247
1283
|
ovld protocol deliver --session-key <key> --ticket-id <id> --summary "Done" --timeout 60000
|
|
1248
1284
|
`);
|
package/bin/_cli/setup.mjs
CHANGED
|
@@ -84,11 +84,11 @@ If you receive a prompt with a specified ticket ID, adhere to the following. If
|
|
|
84
84
|
--change-rationales-json '[{"label":"Short reviewer title","file_path":"path/to/file.ts","summary":"What changed.","why":"Why it changed.","impact":"Behavioral impact.","hunks":[{"header":"@@ -10,6 +10,14 @@"}]}]'
|
|
85
85
|
\`\`\`
|
|
86
86
|
|
|
87
|
-
For larger or quote-sensitive deliveries, prefer a single JSON
|
|
87
|
+
For larger or quote-sensitive deliveries, prefer a single JSON payload on stdin:
|
|
88
88
|
\`\`\`bash
|
|
89
|
-
ovld protocol deliver --session-key <sessionKey> --ticket-id $TICKET_ID --payload-file
|
|
89
|
+
ovld protocol deliver --session-key <sessionKey> --ticket-id $TICKET_ID --payload-file -
|
|
90
90
|
\`\`\`
|
|
91
|
-
|
|
91
|
+
This avoids creating a scratch delivery file that needs cleanup. If your runtime cannot provide stdin directly, \`--payload-file ./deliver.json\` remains supported; treat that file as ephemeral scratch data, never commit it, and remove it after delivery.
|
|
92
92
|
|
|
93
93
|
## Change Rationales
|
|
94
94
|
|
|
@@ -96,7 +96,7 @@ Always include \`changeRationales\` when delivering. Optionally include them on
|
|
|
96
96
|
|
|
97
97
|
Before delivering, make sure every meaningful git-tracked file change is represented in \`changeRationales\`; do not send \`file_changes\` as an artifact.
|
|
98
98
|
|
|
99
|
-
These are structured protocol payloads that Overlord stores as first-class rows in the \`file_changes\` table. Prefer inline JSON or the dedicated command below. For
|
|
99
|
+
These are structured protocol payloads that Overlord stores as first-class rows in the \`file_changes\` table. Prefer inline JSON or the dedicated command below. For larger full delivery payloads, prefer \`--payload-file -\` so summary, artifacts, and change rationales stay in one JSON document without creating a temporary file. Ordinary deliver artifacts should use \`next_steps\`, \`test_results\`, \`migration\`, \`note\`, \`url\`, or \`decision\`.
|
|
100
100
|
|
|
101
101
|
\`\`\`bash
|
|
102
102
|
ovld protocol record-change-rationales --session-key <sessionKey> --ticket-id $TICKET_ID \\\\
|
|
@@ -158,11 +158,11 @@ If you receive a prompt with a specified ticket ID, adhere to the following. If
|
|
|
158
158
|
--artifacts-json '[{"type":"next_steps","label":"Next steps","content":"..."}]' \\\\
|
|
159
159
|
--change-rationales-json '[{"label":"Short reviewer title","file_path":"path/to/file.ts","summary":"What changed.","why":"Why it changed.","impact":"Behavioral impact.","hunks":[{"header":"@@ -10,6 +10,14 @@"}]}]'
|
|
160
160
|
\`\`\`
|
|
161
|
-
If you use \`--payload-file\`, \`--artifacts-file\`, or \`--change-rationales-file\`
|
|
161
|
+
For larger delivery JSON, prefer \`--payload-file -\` and stream the full payload on stdin so no scratch file needs to be created or removed. If you use \`--payload-file\`, \`--artifacts-file\`, or \`--change-rationales-file\` with a real path, treat that file as ephemeral scratch data outside the repository and remove it after delivery. Do not leave delivery JSON checked into the worktree.
|
|
162
162
|
|
|
163
163
|
## Change Rationales
|
|
164
164
|
|
|
165
|
-
Always include \`changeRationales\` when delivering. Before delivering, make sure every meaningful git-tracked file change is represented in \`changeRationales\`; do not send \`file_changes\` as an artifact. Record only meaningful behavioral changes. Overlord stores these as structured rows in the \`file_changes\` table. If you need a JSON file for transport, keep it ephemeral and out of the repository.
|
|
165
|
+
Always include \`changeRationales\` when delivering. Before delivering, make sure every meaningful git-tracked file change is represented in \`changeRationales\`; do not send \`file_changes\` as an artifact. Record only meaningful behavioral changes. Overlord stores these as structured rows in the \`file_changes\` table. For larger delivery payloads, prefer \`--payload-file -\` with stdin. If you need a JSON file for transport, keep it ephemeral and out of the repository.
|
|
166
166
|
|
|
167
167
|
\`\`\`bash
|
|
168
168
|
ovld protocol record-change-rationales --session-key <sessionKey> --ticket-id $TICKET_ID \\\\
|
|
@@ -231,7 +231,7 @@ When done, deliver with artifacts and change rationales:
|
|
|
231
231
|
\`\`\`bash
|
|
232
232
|
ovld protocol deliver --session-key <sessionKey> --ticket-id $TICKET_ID --summary "Narrative: what you did, next steps." --artifacts-json '[{"type":"next_steps","label":"Next steps","content":"..."}]' --change-rationales-json '[{"label":"Short reviewer title","file_path":"path/to/file.ts","summary":"What changed.","why":"Why it changed.","impact":"Behavioral impact.","hunks":[{"header":"@@ -10,6 +10,14 @@"}]}]'
|
|
233
233
|
\`\`\`
|
|
234
|
-
If you use a JSON file for delivery transport, keep it ephemeral scratch data outside the repository and remove it after the protocol call.
|
|
234
|
+
For larger delivery JSON, prefer \`--payload-file -\` with stdin so no scratch file needs to be created or removed. If you use a JSON file for delivery transport, keep it ephemeral scratch data outside the repository and remove it after the protocol call.
|
|
235
235
|
|
|
236
236
|
Rules:
|
|
237
237
|
- Always attach first and deliver last.
|
package/package.json
CHANGED
|
@@ -7,6 +7,27 @@ const execFileAsync = promisify(execFile);
|
|
|
7
7
|
const OVLD_BIN = process.env.OVLD_BIN?.trim() || 'ovld';
|
|
8
8
|
const PROTOCOL_VERSION = '2025-06-18';
|
|
9
9
|
|
|
10
|
+
function execFileWithOptionalInput(file, args, options, input) {
|
|
11
|
+
if (input === undefined) {
|
|
12
|
+
return execFileAsync(file, args, options);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return new Promise((resolve, reject) => {
|
|
16
|
+
const child = execFile(file, args, options, (error, stdout, stderr) => {
|
|
17
|
+
if (error) {
|
|
18
|
+
error.stdout = stdout;
|
|
19
|
+
error.stderr = stderr;
|
|
20
|
+
reject(error);
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
resolve({ stdout, stderr });
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
child.stdin?.end(input);
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
10
31
|
const tools = [
|
|
11
32
|
{
|
|
12
33
|
name: 'discover_project',
|
|
@@ -239,7 +260,8 @@ const tools = [
|
|
|
239
260
|
},
|
|
240
261
|
{
|
|
241
262
|
name: 'deliver_ticket',
|
|
242
|
-
description:
|
|
263
|
+
description:
|
|
264
|
+
'Deliver final work back into Overlord with summary, artifacts, and change rationales. Large payloads are streamed to the CLI through stdin, so this tool does not create delivery scratch files.',
|
|
243
265
|
inputSchema: {
|
|
244
266
|
type: 'object',
|
|
245
267
|
properties: {
|
|
@@ -255,11 +277,14 @@ const tools = [
|
|
|
255
277
|
toCliFlags: args => ({
|
|
256
278
|
'session-key': args.session_key,
|
|
257
279
|
'ticket-id': args.ticket_id,
|
|
258
|
-
|
|
259
|
-
'artifacts-json': args.artifacts,
|
|
260
|
-
'change-rationales-json': args.change_rationales,
|
|
280
|
+
'payload-file': '-',
|
|
261
281
|
'skip-file-change-check': args.skip_file_change_check
|
|
262
282
|
}),
|
|
283
|
+
toCliStdin: args => JSON.stringify({
|
|
284
|
+
summary: args.summary,
|
|
285
|
+
...(Array.isArray(args.artifacts) ? { artifacts: args.artifacts } : {}),
|
|
286
|
+
...(Array.isArray(args.change_rationales) ? { changeRationales: args.change_rationales } : {})
|
|
287
|
+
}),
|
|
263
288
|
subcommand: 'deliver'
|
|
264
289
|
},
|
|
265
290
|
{
|
|
@@ -490,17 +515,24 @@ function cliArgsFromFlags(flags) {
|
|
|
490
515
|
}
|
|
491
516
|
|
|
492
517
|
async function runProtocol(tool, args) {
|
|
493
|
-
const
|
|
518
|
+
const toolArgs = args ?? {};
|
|
519
|
+
const cliArgs = ['protocol', tool.subcommand, ...cliArgsFromFlags(tool.toCliFlags(toolArgs))];
|
|
520
|
+
const stdin = typeof tool.toCliStdin === 'function' ? tool.toCliStdin(toolArgs) : undefined;
|
|
494
521
|
|
|
495
522
|
try {
|
|
496
|
-
const { stdout, stderr } = await
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
523
|
+
const { stdout, stderr } = await execFileWithOptionalInput(
|
|
524
|
+
OVLD_BIN,
|
|
525
|
+
cliArgs,
|
|
526
|
+
{
|
|
527
|
+
cwd: process.cwd(),
|
|
528
|
+
env: {
|
|
529
|
+
...process.env,
|
|
530
|
+
AGENT_IDENTIFIER: process.env.AGENT_IDENTIFIER ?? 'codex-overlord-plugin'
|
|
531
|
+
},
|
|
532
|
+
maxBuffer: 20 * 1024 * 1024
|
|
501
533
|
},
|
|
502
|
-
|
|
503
|
-
|
|
534
|
+
stdin
|
|
535
|
+
);
|
|
504
536
|
|
|
505
537
|
const trimmed = stdout.trim();
|
|
506
538
|
const data = trimmed ? JSON.parse(trimmed) : {};
|
|
@@ -15,7 +15,7 @@ Overlord plugin.
|
|
|
15
15
|
and stop.
|
|
16
16
|
6. Deliver last with `ovld protocol deliver`, including meaningful `changeRationales` for every
|
|
17
17
|
behavioral git-tracked change.
|
|
18
|
-
If you need `--payload-file`, `--artifacts-file`, or `--change-rationales-file
|
|
18
|
+
For larger delivery JSON, prefer `--payload-file -` and stream the full payload on stdin so no scratch file needs to be created or removed. If you need `--payload-file`, `--artifacts-file`, or `--change-rationales-file` with a real path, treat that JSON as ephemeral scratch data, not as a repository file. Remove it after delivery and never commit it.
|
|
19
19
|
|
|
20
20
|
## Rules
|
|
21
21
|
|