greprag 5.79.0 → 5.80.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/dist/commands/announce.js +97 -0
- package/dist/commands/init.js +14 -1
- package/dist/commands/reminder-registry.js +89 -1
- package/dist/hook.js +62 -3
- package/dist/index.js +8 -0
- package/package.json +1 -1
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/** `greprag announce` — print the full SessionStart announce.
|
|
3
|
+
*
|
|
4
|
+
* The Claude Code harness inlines only ~2KB of hook context (measured; see
|
|
5
|
+
* ANNOUNCE_INLINE_BUDGET). The recap hook therefore parks the complete announce
|
|
6
|
+
* under ~/.greprag/announce/<session>.md and inlines a pointer naming this
|
|
7
|
+
* command. Without it the overflow is unreachable — which is exactly the
|
|
8
|
+
* failure this exists to end.
|
|
9
|
+
*
|
|
10
|
+
* adr: adr/announce-inline-budget.md
|
|
11
|
+
*/
|
|
12
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
15
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
16
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
17
|
+
}
|
|
18
|
+
Object.defineProperty(o, k2, desc);
|
|
19
|
+
}) : (function(o, m, k, k2) {
|
|
20
|
+
if (k2 === undefined) k2 = k;
|
|
21
|
+
o[k2] = m[k];
|
|
22
|
+
}));
|
|
23
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
24
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
25
|
+
}) : function(o, v) {
|
|
26
|
+
o["default"] = v;
|
|
27
|
+
});
|
|
28
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
29
|
+
var ownKeys = function(o) {
|
|
30
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
31
|
+
var ar = [];
|
|
32
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
33
|
+
return ar;
|
|
34
|
+
};
|
|
35
|
+
return ownKeys(o);
|
|
36
|
+
};
|
|
37
|
+
return function (mod) {
|
|
38
|
+
if (mod && mod.__esModule) return mod;
|
|
39
|
+
var result = {};
|
|
40
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
41
|
+
__setModuleDefault(result, mod);
|
|
42
|
+
return result;
|
|
43
|
+
};
|
|
44
|
+
})();
|
|
45
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
46
|
+
exports.runAnnounce = runAnnounce;
|
|
47
|
+
const fs = __importStar(require("fs"));
|
|
48
|
+
const os = __importStar(require("os"));
|
|
49
|
+
const path = __importStar(require("path"));
|
|
50
|
+
const session_id_1 = require("../session-id");
|
|
51
|
+
function announceDir() {
|
|
52
|
+
return path.join(os.homedir(), '.greprag', 'announce');
|
|
53
|
+
}
|
|
54
|
+
/** Newest cached announce, by mtime. Used when no session id is given — the
|
|
55
|
+
* common case, since an agent asking for its own announce rarely wants to
|
|
56
|
+
* first go find its session id. */
|
|
57
|
+
function newestCached() {
|
|
58
|
+
try {
|
|
59
|
+
const dir = announceDir();
|
|
60
|
+
const files = fs.readdirSync(dir)
|
|
61
|
+
.filter(f => f.endsWith('.md'))
|
|
62
|
+
.map(f => ({ f, t: fs.statSync(path.join(dir, f)).mtimeMs }))
|
|
63
|
+
.sort((a, b) => b.t - a.t);
|
|
64
|
+
return files.length ? path.join(dir, files[0].f) : null;
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
function runAnnounce(args) {
|
|
71
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
72
|
+
process.stdout.write('greprag announce — print the full SessionStart announce\n\n'
|
|
73
|
+
+ 'USAGE\n'
|
|
74
|
+
+ ' greprag announce [--session <8hex>] [--path]\n\n'
|
|
75
|
+
+ ' The harness inlines only ~2KB of session-start context. The rest is\n'
|
|
76
|
+
+ ' parked on disk; this prints all of it.\n\n'
|
|
77
|
+
+ ' --session <8hex> a specific session (default: most recent)\n'
|
|
78
|
+
+ ' --path print the cache file path instead of its contents\n');
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
const i = args.indexOf('--session');
|
|
82
|
+
const wanted = i !== -1 ? args[i + 1] : undefined;
|
|
83
|
+
const file = wanted
|
|
84
|
+
? path.join(announceDir(), `${(0, session_id_1.truncateSessionId)(wanted) || wanted}.md`)
|
|
85
|
+
: newestCached();
|
|
86
|
+
if (!file || !fs.existsSync(file)) {
|
|
87
|
+
process.stderr.write('No cached announce found. It is written at SessionStart, so a session '
|
|
88
|
+
+ 'must have started since this greprag version was installed.\n');
|
|
89
|
+
process.exitCode = 1;
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
if (args.includes('--path')) {
|
|
93
|
+
process.stdout.write(file + '\n');
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
process.stdout.write(fs.readFileSync(file, 'utf-8').trimEnd() + '\n');
|
|
97
|
+
}
|
package/dist/commands/init.js
CHANGED
|
@@ -1459,13 +1459,26 @@ function applySettings(settings, apiKey) {
|
|
|
1459
1459
|
matcher: '',
|
|
1460
1460
|
hooks: [{ type: 'command', command: 'greprag-hook store', timeout: 10000 }],
|
|
1461
1461
|
};
|
|
1462
|
+
// Migrate stale installs onto the every-source matcher. `hasGrepragHook` only
|
|
1463
|
+
// asks whether a recap hook EXISTS, so an install written by an older version
|
|
1464
|
+
// kept its narrow matcher forever while init reported "already configured".
|
|
1465
|
+
// Field state 2026-09-03: `matcher: 'startup'`, so a resumed session — and
|
|
1466
|
+
// every /new and dashboard-dispatched agent — got no announce at all, Persona
|
|
1467
|
+
// included. Same failure and same fix as the Grok path above.
|
|
1468
|
+
// adr: adr/announce-inline-budget.md
|
|
1469
|
+
const retargetedRecap = settings.hooks.SessionStart
|
|
1470
|
+
? retargetGrepragHookMatcher(settings.hooks.SessionStart, 'recap', ['startup', 'startup|resume', 'startup|resume|compact', 'startup|clear|compact'], recapHook.matcher)
|
|
1471
|
+
: 0;
|
|
1472
|
+
if (retargetedRecap > 0) {
|
|
1473
|
+
changes.push(`Retargeted SessionStart recap matcher to every source (${retargetedRecap})`);
|
|
1474
|
+
}
|
|
1462
1475
|
if (!hasGrepragHook(settings.hooks.SessionStart, 'recap')) {
|
|
1463
1476
|
if (!settings.hooks.SessionStart)
|
|
1464
1477
|
settings.hooks.SessionStart = [];
|
|
1465
1478
|
settings.hooks.SessionStart.push(recapHook);
|
|
1466
1479
|
changes.push('Added SessionStart hook (memory recap + inbox digest)');
|
|
1467
1480
|
}
|
|
1468
|
-
else {
|
|
1481
|
+
else if (retargetedRecap === 0) {
|
|
1469
1482
|
changes.push('SessionStart hook already configured (skipped)');
|
|
1470
1483
|
}
|
|
1471
1484
|
if (!hasGrepragHook(settings.hooks.Stop, 'store')) {
|
|
@@ -5,10 +5,12 @@
|
|
|
5
5
|
* PURE over ReminderEnv — the hook assembles env (i/o) and emits the returned lines;
|
|
6
6
|
* a broken module never blocks a turn (fail-open per module). */
|
|
7
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
exports.compactReannounceModules = exports.commandModules = exports.promptModules = exports.harnessModules = exports.REGISTRY = void 0;
|
|
8
|
+
exports.ANNOUNCE_HARNESS_CAP = exports.ANNOUNCE_INLINE_BUDGET = exports.compactReannounceModules = exports.commandModules = exports.promptModules = exports.harnessModules = exports.REGISTRY = void 0;
|
|
9
9
|
exports.collectReminders = collectReminders;
|
|
10
10
|
exports.bootOrder = bootOrder;
|
|
11
11
|
exports.collectAnnounces = collectAnnounces;
|
|
12
|
+
exports.collectAnnounceBlocks = collectAnnounceBlocks;
|
|
13
|
+
exports.fitAnnounceBudget = fitAnnounceBudget;
|
|
12
14
|
const os_primer_reminder_1 = require("./os-primer-reminder");
|
|
13
15
|
const inbox_primer_reminder_1 = require("./inbox-primer-reminder");
|
|
14
16
|
const load_primer_reminder_1 = require("./load-primer-reminder");
|
|
@@ -147,3 +149,89 @@ function collectAnnounces(env, registry = exports.REGISTRY) {
|
|
|
147
149
|
}
|
|
148
150
|
return out;
|
|
149
151
|
}
|
|
152
|
+
/** Same as collectAnnounces, but keeps each block paired with the module that
|
|
153
|
+
* produced it so the budget fitter can rank and name them.
|
|
154
|
+
* adr: adr/announce-inline-budget.md */
|
|
155
|
+
function collectAnnounceBlocks(env, registry = exports.REGISTRY) {
|
|
156
|
+
const out = [];
|
|
157
|
+
for (const m of bootOrder(registry)) {
|
|
158
|
+
let a = null;
|
|
159
|
+
try {
|
|
160
|
+
a = m.announce(env);
|
|
161
|
+
}
|
|
162
|
+
catch {
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
if (a)
|
|
166
|
+
out.push({ id: m.id, text: a });
|
|
167
|
+
}
|
|
168
|
+
return out;
|
|
169
|
+
}
|
|
170
|
+
/** Bytes of SessionStart context a harness will actually inline. MEASURED, not
|
|
171
|
+
* guessed: Claude Code wraps any hook output over 2048 bytes in
|
|
172
|
+
* `<persisted-output>`, spills the full text to a tool-results file, and injects
|
|
173
|
+
* only "Preview (first 2KB)". This is true of BOTH raw stdout and the
|
|
174
|
+
* `additionalContext` envelope — the cap is on inline context, not the channel.
|
|
175
|
+
* Measured 2026-09-03 with an 80-marker ruler: markers 250..2000 arrived, 2250
|
|
176
|
+
* and beyond did not. 1800 leaves headroom for the harness's own wrapper text.
|
|
177
|
+
* adr: adr/announce-inline-budget.md */
|
|
178
|
+
exports.ANNOUNCE_INLINE_BUDGET = 1650;
|
|
179
|
+
/** The harness's hard ceiling. Past this, output is replaced by a 2KB preview and
|
|
180
|
+
* a `<persisted-output>` file reference. ANNOUNCE_INLINE_BUDGET must stay under
|
|
181
|
+
* it with room for the trailing memory-recap pointer. */
|
|
182
|
+
exports.ANNOUNCE_HARNESS_CAP = 2048;
|
|
183
|
+
/** Inline-worthiness ranking, most-keepable first. The rule: a block earns inline
|
|
184
|
+
* space when it is SHORT, SESSION-SPECIFIC, and available nowhere else. A block
|
|
185
|
+
* that is long, static, and already loadable on demand does not — it is exactly
|
|
186
|
+
* what `greprag load` exists for. Anything unlisted sorts last.
|
|
187
|
+
*
|
|
188
|
+
* Persona leads because it is 523 bytes of tenant-set speaking instructions that
|
|
189
|
+
* no other surface carries. The grepragOS laws are deliberately NOT here: 1753
|
|
190
|
+
* bytes of static doctrine that `greprag load os` already serves on demand, which
|
|
191
|
+
* until now consumed the entire budget and starved everything behind it. */
|
|
192
|
+
const ANNOUNCE_PRIORITY = [
|
|
193
|
+
'persona-announce',
|
|
194
|
+
'setup-warning',
|
|
195
|
+
'version-upgrade',
|
|
196
|
+
'enrichment-health',
|
|
197
|
+
'watcher-arm',
|
|
198
|
+
'skill-mirror-announce',
|
|
199
|
+
'delivery-control',
|
|
200
|
+
'doc-pointer-announce',
|
|
201
|
+
];
|
|
202
|
+
function announceRank(id) {
|
|
203
|
+
const i = ANNOUNCE_PRIORITY.indexOf(id);
|
|
204
|
+
return i === -1 ? ANNOUNCE_PRIORITY.length : i;
|
|
205
|
+
}
|
|
206
|
+
/** Fit the announce into the harness's inline budget.
|
|
207
|
+
*
|
|
208
|
+
* Returns the blocks that fit (restored to boot order, so a primer still precedes
|
|
209
|
+
* anything that depends on it) plus the ids that did not. The caller is expected
|
|
210
|
+
* to persist the FULL text and give the agent a way to read it — dropping content
|
|
211
|
+
* silently is the failure this whole mechanism exists to end.
|
|
212
|
+
*
|
|
213
|
+
* A single block larger than the budget is never emitted; it would blow the cap
|
|
214
|
+
* on its own and take everything after it down too. */
|
|
215
|
+
function fitAnnounceBudget(blocks, budget = exports.ANNOUNCE_INLINE_BUDGET, reserve = 0) {
|
|
216
|
+
const order = new Map(blocks.map((b, i) => [b.id, i]));
|
|
217
|
+
const ranked = [...blocks].sort((a, b) => {
|
|
218
|
+
const d = announceRank(a.id) - announceRank(b.id);
|
|
219
|
+
return d !== 0 ? d : (order.get(a.id) - order.get(b.id));
|
|
220
|
+
});
|
|
221
|
+
const kept = [];
|
|
222
|
+
const droppedIds = [];
|
|
223
|
+
let used = reserve;
|
|
224
|
+
const SEP = 2; // the '\n\n' join between blocks
|
|
225
|
+
for (const b of ranked) {
|
|
226
|
+
const cost = b.text.length + (kept.length ? SEP : 0);
|
|
227
|
+
if (used + cost <= budget) {
|
|
228
|
+
kept.push(b);
|
|
229
|
+
used += cost;
|
|
230
|
+
}
|
|
231
|
+
else {
|
|
232
|
+
droppedIds.push(b.id);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
kept.sort((a, b) => order.get(a.id) - order.get(b.id));
|
|
236
|
+
return { kept, droppedIds };
|
|
237
|
+
}
|
package/dist/hook.js
CHANGED
|
@@ -40,8 +40,10 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
40
40
|
};
|
|
41
41
|
})();
|
|
42
42
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
43
|
+
exports.announceCachePath = announceCachePath;
|
|
43
44
|
const path = __importStar(require("path"));
|
|
44
45
|
const fs = __importStar(require("fs"));
|
|
46
|
+
const os = __importStar(require("os"));
|
|
45
47
|
const crypto = __importStar(require("crypto"));
|
|
46
48
|
const proc_1 = require("./proc");
|
|
47
49
|
const docptr_refs_1 = require("./docptr-refs");
|
|
@@ -1334,6 +1336,43 @@ function grokSidecarHead(short, full) {
|
|
|
1334
1336
|
+ 'Chip: `greprag load grok-chip-spawn` then `greprag grok spawn`. Helper: spawn_subagent. Parent keeps ONE watch. Peers: `greprag inbox watchers` then `greprag send`.\n'
|
|
1335
1337
|
+ 'If a greprag inbox monitor is already listed, do not start another. Instant exit = already armed.\n\n';
|
|
1336
1338
|
}
|
|
1339
|
+
/** Where the full, unabridged announce is parked for on-demand reading.
|
|
1340
|
+
* adr: adr/announce-inline-budget.md */
|
|
1341
|
+
function announceCachePath(short) {
|
|
1342
|
+
return path.join(os.homedir(), '.greprag', 'announce', `${short}.md`);
|
|
1343
|
+
}
|
|
1344
|
+
/** Assemble the SessionStart announce so it SURVIVES the harness's inline cap.
|
|
1345
|
+
*
|
|
1346
|
+
* Writes the full text to the announce cache, inlines the highest-value blocks
|
|
1347
|
+
* that fit the budget, and — when anything was left out — appends one line that
|
|
1348
|
+
* NAMES the omitted sections and the command that prints them. The old behavior
|
|
1349
|
+
* emitted all 18.5KB and let the harness silently keep the first 2KB.
|
|
1350
|
+
*
|
|
1351
|
+
* Returns null when there is nothing to announce. */
|
|
1352
|
+
function buildInlineAnnounce(blocks, short) {
|
|
1353
|
+
if (!blocks.length)
|
|
1354
|
+
return null;
|
|
1355
|
+
const full = blocks.map(b => b.text).join('\n\n');
|
|
1356
|
+
if (short) {
|
|
1357
|
+
try {
|
|
1358
|
+
const file = announceCachePath(short);
|
|
1359
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
1360
|
+
fs.writeFileSync(file, full, 'utf-8');
|
|
1361
|
+
}
|
|
1362
|
+
catch { /* cache is a convenience; never block session start */ }
|
|
1363
|
+
}
|
|
1364
|
+
// Reserve room for the pointer line before fitting, so adding it can never be
|
|
1365
|
+
// what pushes the payload over the cap.
|
|
1366
|
+
const POINTER_RESERVE = 220;
|
|
1367
|
+
const { kept, droppedIds } = (0, reminder_registry_1.fitAnnounceBudget)(blocks, reminder_registry_1.ANNOUNCE_INLINE_BUDGET, POINTER_RESERVE);
|
|
1368
|
+
if (!droppedIds.length)
|
|
1369
|
+
return kept.map(b => b.text).join('\n\n') || null;
|
|
1370
|
+
const names = droppedIds.join(', ');
|
|
1371
|
+
const pointer = `[greprag announce — ${droppedIds.length} more section(s) not inlined `
|
|
1372
|
+
+ `(harness caps SessionStart context at ${reminder_registry_1.ANNOUNCE_INLINE_BUDGET}b): ${names}. `
|
|
1373
|
+
+ `Read them with \`greprag announce\`.]`;
|
|
1374
|
+
return [...kept.map(b => b.text), pointer].join('\n\n');
|
|
1375
|
+
}
|
|
1337
1376
|
function writeRecapOutput(text, mode, grokShort, grokFull) {
|
|
1338
1377
|
if (grokShort)
|
|
1339
1378
|
(0, grok_session_1.writeGrokSidecar)(grokShort, grokSidecarHead(grokShort, grokFull) + (text || ''));
|
|
@@ -1737,7 +1776,12 @@ async function recap(input, mode = 'plain', opts = {}) {
|
|
|
1737
1776
|
// adr: adr/monitor-resilience.md, docs/reminder-interrupt.md
|
|
1738
1777
|
if (opts.compact)
|
|
1739
1778
|
announceReg = (0, reminder_registry_1.compactReannounceModules)(announceReg);
|
|
1740
|
-
|
|
1779
|
+
// Fit the announce to what the harness will actually inline (2048 bytes; see
|
|
1780
|
+
// ANNOUNCE_INLINE_BUDGET). The full text is persisted first and the overflow is
|
|
1781
|
+
// NAMED, so nothing is lost silently — the failure this replaces was an 18.5KB
|
|
1782
|
+
// announce of which only the first ~2KB ever reached a session, with no signal
|
|
1783
|
+
// that the rest existed. adr: adr/announce-inline-budget.md
|
|
1784
|
+
const announceBlock = buildInlineAnnounce((0, reminder_registry_1.collectAnnounceBlocks)(announceEnv, announceReg), (0, session_id_1.truncateSessionId)(input.session_id));
|
|
1741
1785
|
if (opts.compact) {
|
|
1742
1786
|
writeRecapOutput(announceBlock ? announceBlock + '\n' : '', mode, grokShort, input.session_id);
|
|
1743
1787
|
return;
|
|
@@ -1773,7 +1817,17 @@ async function recap(input, mode = 'plain', opts = {}) {
|
|
|
1773
1817
|
parts.push(announceBlock);
|
|
1774
1818
|
parts.push('');
|
|
1775
1819
|
}
|
|
1776
|
-
|
|
1820
|
+
// The memory recap shares the SAME inline cap as the announce — it is appended
|
|
1821
|
+
// to the very payload the harness truncates. Inline it only if it fits in what
|
|
1822
|
+
// the announce left; otherwise name the command that prints it. Silently
|
|
1823
|
+
// emitting a body that pushes the payload over the cap is what made the whole
|
|
1824
|
+
// announce disappear. adr: adr/announce-inline-budget.md
|
|
1825
|
+
const usedSoFar = parts.join('\n').length;
|
|
1826
|
+
const roomForBody = reminder_registry_1.ANNOUNCE_INLINE_BUDGET - usedSoFar;
|
|
1827
|
+
parts.push(body.length <= roomForBody
|
|
1828
|
+
? body
|
|
1829
|
+
: '[greprag memory — session recap not inlined (over the SessionStart cap). '
|
|
1830
|
+
+ 'Read it with `greprag memory recap`.]');
|
|
1777
1831
|
writeRecapOutput(parts.join('\n') + '\n', mode, grokShort, input.session_id);
|
|
1778
1832
|
}
|
|
1779
1833
|
/** Arm-state detection moved LOCAL (2026-06-04). The former `isSessionArmed`
|
|
@@ -2233,7 +2287,12 @@ async function main() {
|
|
|
2233
2287
|
}
|
|
2234
2288
|
const harness = (0, harness_1.inferCurrentHarness)();
|
|
2235
2289
|
if (subcommand === 'recap') {
|
|
2236
|
-
|
|
2290
|
+
// ALWAYS additionalContext. Raw stdout is treated by the Claude Code harness
|
|
2291
|
+
// like command output: past ~2KB it spills to a file and injects a preview,
|
|
2292
|
+
// which silently ate ~89% of an 18.7KB announce (Persona sits at byte 10,841).
|
|
2293
|
+
// additionalContext is the documented injection channel. Grok keeps its
|
|
2294
|
+
// sidecar via the platform arg. adr: adr/announce-delivery-channel.md
|
|
2295
|
+
await recap(input, 'additionalContext', {
|
|
2237
2296
|
platform: harness === 'grok' ? 'grok' : undefined,
|
|
2238
2297
|
});
|
|
2239
2298
|
}
|
package/dist/index.js
CHANGED
|
@@ -299,6 +299,10 @@ function readProjectRegistry() {
|
|
|
299
299
|
* desk ensure idempotently spawn a detached desk-line if none is running
|
|
300
300
|
* desk status is a desk-line up + what local truth would it report now
|
|
301
301
|
* adr: adr/desk-line-relay.md */
|
|
302
|
+
async function runAnnounce(args) {
|
|
303
|
+
const { runAnnounce: run } = await Promise.resolve().then(() => __importStar(require('./commands/announce')));
|
|
304
|
+
run(args);
|
|
305
|
+
}
|
|
302
306
|
async function runDesk(args) {
|
|
303
307
|
ensureEnv(); // load ~/.greprag/.env so GREPRAG_API_KEY is present (self-heals in the detached child)
|
|
304
308
|
const sub = args[0] || 'status';
|
|
@@ -1906,6 +1910,10 @@ async function main() {
|
|
|
1906
1910
|
return;
|
|
1907
1911
|
}
|
|
1908
1912
|
case 'inbox': return inbox(subArgs);
|
|
1913
|
+
// The full SessionStart announce. The harness inlines only ~2KB of it, so the
|
|
1914
|
+
// overflow is parked here and the inline pointer names this command.
|
|
1915
|
+
// adr: adr/announce-inline-budget.md
|
|
1916
|
+
case 'announce': return runAnnounce(subArgs);
|
|
1909
1917
|
case 'desk': return runDesk(subArgs);
|
|
1910
1918
|
case 'email': return (0, email_1.runEmail)(subArgs);
|
|
1911
1919
|
case 'send': return send(subArgs);
|