@vibecompass/vibecompass 0.15.0 → 0.16.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/CHANGELOG.md +118 -0
- package/README.md +71 -0
- package/package.json +1 -1
- package/src/brief-keywords.js +203 -0
- package/src/brief-lifecycle.js +638 -0
- package/src/brief-render.js +341 -0
- package/src/brief-settings.js +160 -0
- package/src/brief.js +1557 -0
- package/src/cli.js +269 -3
- package/src/decision-lineage.js +1717 -0
- package/src/generators/agent-files/template.js +2 -1
- package/src/index.js +34 -0
- package/src/project-memory.js +30 -4
- package/src/read-model.js +92 -2
- package/src/scaffold.js +10 -2
- package/src/session.js +30 -0
package/src/cli.js
CHANGED
|
@@ -5,6 +5,9 @@ import { pathToFileURL } from 'node:url';
|
|
|
5
5
|
import { connectHostedProjectMemory, initializeProjectMemory, setDefaultSyncTarget } from './init.js';
|
|
6
6
|
import { preflightDocsReview } from './docs-review.js';
|
|
7
7
|
import { planDocsUpdate, renderDocsUpdatePlan } from './docs-update.js';
|
|
8
|
+
import { buildSessionBrief, resolveBriefRequest } from './brief.js';
|
|
9
|
+
import { generateLaneBrief, inspectLaneBrief } from './brief-lifecycle.js';
|
|
10
|
+
import { renderBrief } from './brief-render.js';
|
|
8
11
|
import { resolveConnectHostedCliOptions, resolveInitCliOptions } from './setup.js';
|
|
9
12
|
import { readFile } from 'node:fs/promises';
|
|
10
13
|
import path from 'node:path';
|
|
@@ -167,6 +170,7 @@ export async function runCli(argv, io = createDefaultIo(), runtime = {}) {
|
|
|
167
170
|
io.stdout.write(`Runtime: port ${result.runtime.port}, temp dir ${result.runtime.tmpDir}\n`);
|
|
168
171
|
io.stdout.write('Export into a shell with: eval "$(vibecompass lane-env)" (D-282; pass --session <lane-id> when multiple lanes are active; use --worktree for independently runnable same-repo lanes).\n');
|
|
169
172
|
}
|
|
173
|
+
writeLifecycleBriefResult(io, result.brief);
|
|
170
174
|
writeWarnings(io, result.warnings);
|
|
171
175
|
writeAgentFileSyncResult(io, result.agentFileSync);
|
|
172
176
|
return 0;
|
|
@@ -314,6 +318,94 @@ export async function runCli(argv, io = createDefaultIo(), runtime = {}) {
|
|
|
314
318
|
return 0;
|
|
315
319
|
}
|
|
316
320
|
|
|
321
|
+
if (parsed.command === 'brief' && (parsed.options.write || parsed.options.check)) {
|
|
322
|
+
// Lane brief (D-364): --write regenerates the lane's brief.md under the
|
|
323
|
+
// lane root's lock; --check reports its freshness and writes nothing. A
|
|
324
|
+
// --source-root is only ever read.
|
|
325
|
+
await writeCompatibilityPreflightWarnings(io, parsed.options, runtime);
|
|
326
|
+
const cwd = runtime.cwd ? path.resolve(runtime.cwd) : process.cwd();
|
|
327
|
+
const request = await resolveBriefRequest({
|
|
328
|
+
rootDir: parsed.options.rootDir,
|
|
329
|
+
sessionId: parsed.options.sessionId,
|
|
330
|
+
cwd,
|
|
331
|
+
});
|
|
332
|
+
if (!request.laneId) {
|
|
333
|
+
throw new Error(`brief ${parsed.options.write ? '--write' : '--check'} needs an active lane: pass --session <lane-id>, or run it from a lane worktree.`);
|
|
334
|
+
}
|
|
335
|
+
const sourceRootDir = parsed.options.sourceRootDir ? path.resolve(cwd, parsed.options.sourceRootDir) : undefined;
|
|
336
|
+
if (parsed.options.check) {
|
|
337
|
+
const inspection = await inspectLaneBrief({
|
|
338
|
+
rootDir: request.rootDir,
|
|
339
|
+
laneId: request.laneId,
|
|
340
|
+
sourceRootDir,
|
|
341
|
+
sourceSessionId: parsed.options.sourceSessionId,
|
|
342
|
+
});
|
|
343
|
+
if (parsed.options.json) {
|
|
344
|
+
io.stdout.write(`${JSON.stringify({
|
|
345
|
+
lane_id: request.laneId,
|
|
346
|
+
path: inspection.path,
|
|
347
|
+
exists: inspection.exists,
|
|
348
|
+
stale: inspection.stale,
|
|
349
|
+
reasons: inspection.reasons,
|
|
350
|
+
status: inspection.status,
|
|
351
|
+
generated_at: inspection.generatedAt,
|
|
352
|
+
}, null, 2)}\n`);
|
|
353
|
+
} else {
|
|
354
|
+
const state = !inspection.exists ? 'missing' : inspection.stale ? 'stale' : 'current';
|
|
355
|
+
io.stdout.write(`Brief: ${state}${inspection.status ? ` (status ${inspection.status}${inspection.generatedAt ? `, generated ${inspection.generatedAt}` : ''})` : ''} — ${inspection.path}\n`);
|
|
356
|
+
for (const reason of inspection.exists ? inspection.reasons : []) {
|
|
357
|
+
io.stdout.write(`- ${reason}\n`);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
writeWarnings(io, request.warnings);
|
|
361
|
+
return 0;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
const generated = await generateLaneBrief({
|
|
365
|
+
rootDir: request.rootDir,
|
|
366
|
+
laneId: request.laneId,
|
|
367
|
+
sourceRootDir,
|
|
368
|
+
sourceSessionId: parsed.options.sourceSessionId,
|
|
369
|
+
...(parsed.options.budget !== undefined ? { budget: parsed.options.budget } : {}),
|
|
370
|
+
});
|
|
371
|
+
if (parsed.options.json) {
|
|
372
|
+
io.stdout.write(`${JSON.stringify({ lane_id: request.laneId, ...generated }, null, 2)}\n`);
|
|
373
|
+
} else {
|
|
374
|
+
const from = generated.source?.adapter ? ` from ${generated.source.root_dir}` : '';
|
|
375
|
+
io.stdout.write(`Brief: ${generated.status}${generated.state === 'written' ? '' : ` (${generated.state}: ${generated.reason})`} — wrote ${generated.path}${from}\n`);
|
|
376
|
+
}
|
|
377
|
+
writeWarnings(io, [...request.warnings, ...generated.warnings]);
|
|
378
|
+
return generated.state === 'written' ? 0 : 1;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
if (parsed.command === 'brief') {
|
|
382
|
+
// Strictly read-only (plan task A3): no manifest refresh, state write,
|
|
383
|
+
// lane write, or agent-file sync, so it is safe against a legacy root.
|
|
384
|
+
await writeCompatibilityPreflightWarnings(io, parsed.options, runtime);
|
|
385
|
+
const request = await resolveBriefRequest({
|
|
386
|
+
rootDir: parsed.options.rootDir,
|
|
387
|
+
sessionId: parsed.options.sessionId,
|
|
388
|
+
...(runtime.cwd ? { cwd: runtime.cwd } : {}),
|
|
389
|
+
});
|
|
390
|
+
const result = await buildSessionBrief({
|
|
391
|
+
rootDir: request.rootDir,
|
|
392
|
+
laneId: request.laneId,
|
|
393
|
+
task: parsed.options.task,
|
|
394
|
+
files: parsed.options.files,
|
|
395
|
+
featureSlugs: parsed.options.featureSlugs,
|
|
396
|
+
claims: parsed.options.claims,
|
|
397
|
+
budget: parsed.options.budget,
|
|
398
|
+
});
|
|
399
|
+
const markdown = renderBrief(result);
|
|
400
|
+
if (parsed.options.json) {
|
|
401
|
+
io.stdout.write(`${JSON.stringify({ ...result, lane_source: request.laneSource, cli_warnings: request.warnings, markdown }, null, 2)}\n`);
|
|
402
|
+
} else {
|
|
403
|
+
io.stdout.write(markdown);
|
|
404
|
+
}
|
|
405
|
+
writeWarnings(io, request.warnings);
|
|
406
|
+
return 0;
|
|
407
|
+
}
|
|
408
|
+
|
|
317
409
|
if (parsed.command === 'close-session' || parsed.command === 'end-session') {
|
|
318
410
|
await writeCompatibilityPreflightWarnings(io, parsed.options, runtime);
|
|
319
411
|
const result = await closeProjectSession({
|
|
@@ -360,6 +452,9 @@ export async function runCli(argv, io = createDefaultIo(), runtime = {}) {
|
|
|
360
452
|
io.stdout.write('Read next:\n');
|
|
361
453
|
io.stdout.write(`- ${result.wipFilePath}\n`);
|
|
362
454
|
io.stdout.write(`- ${result.handoffFilePath}\n`);
|
|
455
|
+
if (result.brief?.path && result.brief.state !== 'off' && !(result.brief.state === 'failed' && !result.brief.status)) {
|
|
456
|
+
io.stdout.write(`- ${result.brief.path} (session brief — read before planning)\n`);
|
|
457
|
+
}
|
|
363
458
|
if (result.latestFinalizedSessionPath) {
|
|
364
459
|
io.stdout.write(`- ${result.latestFinalizedSessionPath} (latest finalized note)\n`);
|
|
365
460
|
}
|
|
@@ -377,6 +472,7 @@ export async function runCli(argv, io = createDefaultIo(), runtime = {}) {
|
|
|
377
472
|
io.stdout.write(`- ${lane.id}: ${lane.workingOn ?? 'No summary recorded'}\n`);
|
|
378
473
|
}
|
|
379
474
|
}
|
|
475
|
+
writeLifecycleBriefResult(io, result.brief);
|
|
380
476
|
}
|
|
381
477
|
writeWarnings(io, result.warnings);
|
|
382
478
|
writeAgentFileSyncResult(io, result.agentFileSync);
|
|
@@ -824,6 +920,10 @@ export function parseCliArgs(argv) {
|
|
|
824
920
|
return parseDocsUpdateArgs(rest);
|
|
825
921
|
}
|
|
826
922
|
|
|
923
|
+
if (command === 'brief') {
|
|
924
|
+
return parseBriefArgs(rest);
|
|
925
|
+
}
|
|
926
|
+
|
|
827
927
|
if (command === 'close-session' || command === 'end-session') {
|
|
828
928
|
return parseCloseSessionArgs(rest);
|
|
829
929
|
}
|
|
@@ -1100,6 +1200,10 @@ function parseStartSessionArgs(argv) {
|
|
|
1100
1200
|
if (token.startsWith('--worktree=')) {
|
|
1101
1201
|
throw new Error('Flag "--worktree" takes no value; the worktree container is fixed to <workspace>/worktrees/<lane-id> (D-279).');
|
|
1102
1202
|
}
|
|
1203
|
+
if (token === '--no-brief') {
|
|
1204
|
+
parsed.brief = false;
|
|
1205
|
+
continue;
|
|
1206
|
+
}
|
|
1103
1207
|
|
|
1104
1208
|
const value = argv[index + 1];
|
|
1105
1209
|
if (value === undefined) {
|
|
@@ -1857,6 +1961,105 @@ function parseDocsUpdateArgs(argv) {
|
|
|
1857
1961
|
};
|
|
1858
1962
|
}
|
|
1859
1963
|
|
|
1964
|
+
function parseBriefArgs(argv) {
|
|
1965
|
+
const parsed = {
|
|
1966
|
+
files: [],
|
|
1967
|
+
featureSlugs: [],
|
|
1968
|
+
claims: [],
|
|
1969
|
+
};
|
|
1970
|
+
|
|
1971
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
1972
|
+
const token = argv[index];
|
|
1973
|
+
if (token === '--json') {
|
|
1974
|
+
parsed.json = true;
|
|
1975
|
+
continue;
|
|
1976
|
+
}
|
|
1977
|
+
if (token === '--write' || token === '--check') {
|
|
1978
|
+
parsed[token.slice(2)] = true;
|
|
1979
|
+
continue;
|
|
1980
|
+
}
|
|
1981
|
+
|
|
1982
|
+
if (!token.startsWith('--')) {
|
|
1983
|
+
throw new Error(`Unexpected argument "${token}".`);
|
|
1984
|
+
}
|
|
1985
|
+
|
|
1986
|
+
const value = argv[index + 1];
|
|
1987
|
+
if (value === undefined || value.startsWith('--')) {
|
|
1988
|
+
throw new Error(`Flag "${token}" requires a value.`);
|
|
1989
|
+
}
|
|
1990
|
+
index += 1;
|
|
1991
|
+
|
|
1992
|
+
switch (token) {
|
|
1993
|
+
case '--root':
|
|
1994
|
+
parsed.rootDir = value;
|
|
1995
|
+
break;
|
|
1996
|
+
case '--session':
|
|
1997
|
+
parsed.sessionId = value;
|
|
1998
|
+
break;
|
|
1999
|
+
case '--source-root':
|
|
2000
|
+
parsed.sourceRootDir = value;
|
|
2001
|
+
break;
|
|
2002
|
+
case '--source-session':
|
|
2003
|
+
parsed.sourceSessionId = value;
|
|
2004
|
+
break;
|
|
2005
|
+
case '--task':
|
|
2006
|
+
parsed.task = value;
|
|
2007
|
+
break;
|
|
2008
|
+
case '--files':
|
|
2009
|
+
case '--file':
|
|
2010
|
+
// `--files a b c` and repeated `--files a --files b` both work.
|
|
2011
|
+
parsed.files.push(value);
|
|
2012
|
+
while (argv[index + 1] !== undefined && !argv[index + 1].startsWith('--')) {
|
|
2013
|
+
index += 1;
|
|
2014
|
+
parsed.files.push(argv[index]);
|
|
2015
|
+
}
|
|
2016
|
+
break;
|
|
2017
|
+
case '--feature':
|
|
2018
|
+
parsed.featureSlugs.push(value);
|
|
2019
|
+
break;
|
|
2020
|
+
case '--claim':
|
|
2021
|
+
parsed.claims.push(value);
|
|
2022
|
+
break;
|
|
2023
|
+
case '--budget':
|
|
2024
|
+
if (!/^\d+$/.test(value)) {
|
|
2025
|
+
throw new Error(`--budget must be a whole number of estimated tokens (got "${value}").`);
|
|
2026
|
+
}
|
|
2027
|
+
parsed.budget = Number(value);
|
|
2028
|
+
break;
|
|
2029
|
+
default:
|
|
2030
|
+
throw new Error(`Unknown flag "${token}".`);
|
|
2031
|
+
}
|
|
2032
|
+
}
|
|
2033
|
+
|
|
2034
|
+
if (parsed.write && parsed.check) {
|
|
2035
|
+
throw new Error('Choose one of --write (regenerate the lane brief) or --check (report its freshness).');
|
|
2036
|
+
}
|
|
2037
|
+
if (parsed.write || parsed.check) {
|
|
2038
|
+
const laneDerived = [
|
|
2039
|
+
parsed.task !== undefined && '--task',
|
|
2040
|
+
parsed.files.length > 0 && '--files',
|
|
2041
|
+
parsed.featureSlugs.length > 0 && '--feature',
|
|
2042
|
+
parsed.claims.length > 0 && '--claim',
|
|
2043
|
+
parsed.check && parsed.budget !== undefined && '--budget',
|
|
2044
|
+
].filter(Boolean);
|
|
2045
|
+
if (laneDerived.length > 0) {
|
|
2046
|
+
throw new Error(
|
|
2047
|
+
`${laneDerived.join(', ')} cannot be combined with ${parsed.write ? '--write' : '--check'}: a lane brief takes its task from the lane's working-on, its files from the lane's claims, and its features from the lane's feature slugs (update them with continue-session --working-on or the lane metadata).`,
|
|
2048
|
+
);
|
|
2049
|
+
}
|
|
2050
|
+
} else if (parsed.sourceRootDir || parsed.sourceSessionId) {
|
|
2051
|
+
throw new Error('--source-root and --source-session apply only to --write or --check; to print a brief of another root, pass --root.');
|
|
2052
|
+
}
|
|
2053
|
+
if (parsed.sourceSessionId && !parsed.sourceRootDir) {
|
|
2054
|
+
throw new Error('--source-session requires --source-root.');
|
|
2055
|
+
}
|
|
2056
|
+
|
|
2057
|
+
return {
|
|
2058
|
+
command: 'brief',
|
|
2059
|
+
options: parsed,
|
|
2060
|
+
};
|
|
2061
|
+
}
|
|
2062
|
+
|
|
1860
2063
|
function parseListSessionsArgs(argv) {
|
|
1861
2064
|
const parsed = {};
|
|
1862
2065
|
|
|
@@ -2130,6 +2333,10 @@ function parseContinueSessionArgs(argv) {
|
|
|
2130
2333
|
parsed.json = true;
|
|
2131
2334
|
continue;
|
|
2132
2335
|
}
|
|
2336
|
+
if (token === '--no-brief') {
|
|
2337
|
+
parsed.brief = false;
|
|
2338
|
+
continue;
|
|
2339
|
+
}
|
|
2133
2340
|
|
|
2134
2341
|
const value = argv[index + 1];
|
|
2135
2342
|
if (value === undefined) {
|
|
@@ -2147,6 +2354,12 @@ function parseContinueSessionArgs(argv) {
|
|
|
2147
2354
|
case '--session':
|
|
2148
2355
|
parsed.sessionId = value;
|
|
2149
2356
|
break;
|
|
2357
|
+
case '--source-root':
|
|
2358
|
+
parsed.sourceRootDir = value;
|
|
2359
|
+
break;
|
|
2360
|
+
case '--source-session':
|
|
2361
|
+
parsed.sourceSessionId = value;
|
|
2362
|
+
break;
|
|
2150
2363
|
case '--working-on':
|
|
2151
2364
|
parsed.workingOn = value;
|
|
2152
2365
|
break;
|
|
@@ -2179,6 +2392,13 @@ function parseContinueSessionArgs(argv) {
|
|
|
2179
2392
|
parsed.sessionId = positional[0];
|
|
2180
2393
|
}
|
|
2181
2394
|
|
|
2395
|
+
if (parsed.brief === false && (parsed.sourceRootDir || parsed.sourceSessionId)) {
|
|
2396
|
+
throw new Error('--no-brief cannot be combined with --source-root or --source-session.');
|
|
2397
|
+
}
|
|
2398
|
+
if (parsed.sourceSessionId && !parsed.sourceRootDir) {
|
|
2399
|
+
throw new Error('--source-session requires --source-root.');
|
|
2400
|
+
}
|
|
2401
|
+
|
|
2182
2402
|
return {
|
|
2183
2403
|
command: 'continue-session',
|
|
2184
2404
|
options: parsed,
|
|
@@ -2890,6 +3110,31 @@ function writeWarnings(io, warnings = []) {
|
|
|
2890
3110
|
}
|
|
2891
3111
|
}
|
|
2892
3112
|
|
|
3113
|
+
/** One status line for the lifecycle brief (D-364); failures also arrive as warnings. */
|
|
3114
|
+
function writeLifecycleBriefResult(io, brief) {
|
|
3115
|
+
if (!brief) return;
|
|
3116
|
+
const location = brief.path ? ` — ${brief.path}` : '';
|
|
3117
|
+
const from = brief.source?.adapter ? ` (from ${brief.source.root_dir})` : '';
|
|
3118
|
+
switch (brief.state) {
|
|
3119
|
+
case 'off':
|
|
3120
|
+
io.stdout.write(`Brief: off (${brief.reason})\n`);
|
|
3121
|
+
return;
|
|
3122
|
+
case 'kept':
|
|
3123
|
+
io.stdout.write(`Brief: current, kept (status ${brief.status ?? 'unknown'}${brief.generatedAt ? `, generated ${brief.generatedAt}` : ''})${location}\n`);
|
|
3124
|
+
return;
|
|
3125
|
+
case 'regenerated':
|
|
3126
|
+
io.stdout.write(`Brief: regenerated, ${brief.status}${from} (was stale: ${(brief.staleReasons ?? []).join('; ') || 'unknown'})${location}\n`);
|
|
3127
|
+
return;
|
|
3128
|
+
case 'written':
|
|
3129
|
+
io.stdout.write(`Brief: ${brief.status}${from}${location}\n`);
|
|
3130
|
+
return;
|
|
3131
|
+
default:
|
|
3132
|
+
io.stdout.write(brief.status
|
|
3133
|
+
? `Brief: incomplete (${brief.state}: ${brief.reason})${location}\n`
|
|
3134
|
+
: 'Brief: not written (see warning)\n');
|
|
3135
|
+
}
|
|
3136
|
+
}
|
|
3137
|
+
|
|
2893
3138
|
function splitAssignment(value, flagName) {
|
|
2894
3139
|
const separatorIndex = value.indexOf('=');
|
|
2895
3140
|
if (separatorIndex <= 0 || separatorIndex === value.length - 1) {
|
|
@@ -2919,10 +3164,14 @@ function usageText() {
|
|
|
2919
3164
|
' vibecompass status [options]',
|
|
2920
3165
|
' vibecompass refresh-workflow [--dry-run|--apply] [options]',
|
|
2921
3166
|
' vibecompass docs-update [--session <lane-id>] [options]',
|
|
2922
|
-
' vibecompass
|
|
3167
|
+
' vibecompass brief --task <text> [--files <repo:path>...] [--feature <slug>] [--claim <path>] [--session <lane-id>] [--budget <n>] [--json] [options]',
|
|
3168
|
+
' Read-only session brief: relevant memory, packed into an estimated token budget',
|
|
3169
|
+
' vibecompass brief --write|--check [--session <lane-id>] [--source-root <path> [--source-session <lane-id>]] [--budget <n>] [--json] [options]',
|
|
3170
|
+
' Regenerate the lane\'s sessions/active/<lane-id>/brief.md, or report whether it is stale (D-364)',
|
|
3171
|
+
' vibecompass start-session --id <lane-id> --working-on <text> [--branch <name> [--worktree]] [--no-brief] [options]',
|
|
2923
3172
|
' vibecompass close-session --title <text> --completed <text> --architecture-docs <status> --decision-log <status> --session-maintenance <status> [options]',
|
|
2924
3173
|
' vibecompass end-session --title <text> --completed <text> --architecture-docs <status> --decision-log <status> --session-maintenance <status> [options] # alias',
|
|
2925
|
-
' vibecompass continue-session [<lane-id>] [--session <lane-id>] [--working-on <text>] [--json] [options]',
|
|
3174
|
+
' vibecompass continue-session [<lane-id>] [--session <lane-id>] [--working-on <text>] [--no-brief | --source-root <path>] [--json] [options]',
|
|
2926
3175
|
' vibecompass list-sessions [--json] [options]',
|
|
2927
3176
|
' vibecompass switch-session <id> [options]',
|
|
2928
3177
|
' vibecompass rebuild-active-index [--current <lane-id>] [options]',
|
|
@@ -3048,6 +3297,7 @@ function usageText() {
|
|
|
3048
3297
|
' --last-thing-completed <text> Optional override for the CLAUDE.md current-session block',
|
|
3049
3298
|
' --blockers <text> Optional current blockers summary',
|
|
3050
3299
|
' --next-session-should <text> Optional current-session handoff summary',
|
|
3300
|
+
' --no-brief Skip the lane brief for this command (sessions/active/<lane-id>/brief.md; D-359, D-364); lifecycle commands write it only when project.yaml sets brief.enabled: true (opt-in, D-368)',
|
|
3051
3301
|
'',
|
|
3052
3302
|
'Close-session options (also accepted by end-session):',
|
|
3053
3303
|
' --root <path> Project-memory root. Explicit --root wins; otherwise the nearest worktree lane marker supplies it, else .compass',
|
|
@@ -3075,7 +3325,23 @@ function usageText() {
|
|
|
3075
3325
|
' --last-thing-completed <text> Optional override for the CLAUDE.md current-session block',
|
|
3076
3326
|
' --blockers <text> Optional current blockers summary',
|
|
3077
3327
|
' --next-session-should <text> Optional current-session handoff summary',
|
|
3078
|
-
' --json Print the resume result (lane, paths, runtime, other lanes, warnings) as JSON',
|
|
3328
|
+
' --json Print the resume result (lane, paths, runtime, other lanes, brief, warnings) as JSON',
|
|
3329
|
+
' --no-brief Leave the lane brief as it is; with project.yaml brief.enabled: true (opt-in, D-368) resume keeps a current brief and regenerates a missing or stale one',
|
|
3330
|
+
' --source-root <path> D-255 dual-root dogfood: build the brief from this memory root\'s matching lane (same id, session date, and number) and write it only into this lane; the source root is only read',
|
|
3331
|
+
' --source-session <lane-id> With --source-root: the source lane id, which must equal the resumed lane',
|
|
3332
|
+
'',
|
|
3333
|
+
'Brief options:',
|
|
3334
|
+
' --root <path> Project-memory root. Explicit --root wins; otherwise the nearest worktree lane marker supplies it, else .compass',
|
|
3335
|
+
' --session <lane-id> Lane to brief. Omitted: nearest worktree lane marker, else the single active lane; 2+ active lanes require --session or a marker (D-277)',
|
|
3336
|
+
' --task <text> Task text (print mode). Omitted: the lane\'s working-on',
|
|
3337
|
+
' --files <repo:path>... Files the task touches (print mode)',
|
|
3338
|
+
' --feature <slug>, --claim <path> Repeatable feature slug and path claim (print mode)',
|
|
3339
|
+
' --budget <n> Estimated-token budget (default 6000, minimum 800)',
|
|
3340
|
+
' --write Regenerate the lane\'s brief.md from its working-on, claims, and feature slugs, under the root lock',
|
|
3341
|
+
' --check Report whether the lane\'s brief.md is current or stale against its header bindings; writes nothing',
|
|
3342
|
+
' --source-root <path> With --write/--check: read this memory root\'s matching lane instead (D-255 dogfood); never written',
|
|
3343
|
+
' --source-session <lane-id> With --source-root: the source lane id, which must equal the lane being briefed',
|
|
3344
|
+
' --json Print the result as JSON',
|
|
3079
3345
|
'',
|
|
3080
3346
|
'List/switch-session options:',
|
|
3081
3347
|
' --root <path> Project-memory root. Defaults to .compass',
|