@veewo/claw 0.2.22 → 0.2.24
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 +1 -1
- package/dist/cli.js +185 -16
- package/dist/cli.js.map +1 -1
- package/dist/codex-driver.d.ts +2 -2
- package/dist/codex-driver.js +1 -1
- package/dist/command-service.js +9 -1
- package/dist/command-service.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -51,7 +51,7 @@ claw plan create "Ephemeral harness" --scope session --goal "Use plan and Goal w
|
|
|
51
51
|
|
|
52
52
|
New project tasks are grouped under `.claw/tasks/YYYY-MM-DD/`. On the first `claw context` call of each local calendar day, claw performs a lock-protected maintenance pass: it removes expired entries from `.claw/runtime/tmp/`, removes workflow task directories that exceed the task TTL even when incomplete, moves eligible date-scoped task folders into the archive, applies `maxTasksToKeep` and archive TTL, removes expired or invalid bindings, and sweeps expired session workflows. This is lazy maintenance, not a background scheduler.
|
|
53
53
|
|
|
54
|
-
`--scope session` stores the workflow in a user-level directory keyed by the platform session id, so it works without a project `.claw` directory and recovers across cwd changes. It preserves plan/task/subplan/Goal behavior while disabling project knowledge capture, memory
|
|
54
|
+
`--scope session` stores the workflow in a user-level directory keyed by the platform session id, so it works without a project `.claw` directory and recovers across cwd changes. It preserves plan/task/subplan/Goal behavior while disabling project knowledge capture and project retention. When the session's frozen origin belongs to a valid claw project, its terminal transition refreshes that project's memory and enabled GitNexus index; otherwise it creates no refresh state. Use `claw session clean` for the current session or `claw session clean --expired` for the seven-day TTL sweep.
|
|
55
55
|
|
|
56
56
|
Projects can add reusable templates directly under `.claw/templates` with `.json`, `.js`, `.mjs`, or `.cjs` files. Put `defaultPlanTemplate` in `.claw/project.json` for a shared team default, or in `.claw/project-override.json` for a local personal override.
|
|
57
57
|
|
package/dist/cli.js
CHANGED
|
@@ -6,7 +6,7 @@ import { createInterface } from "node:readline";
|
|
|
6
6
|
import { pathToFileURL } from "node:url";
|
|
7
7
|
import { createHash } from "node:crypto";
|
|
8
8
|
import { spawn, spawnSync } from "node:child_process";
|
|
9
|
-
import { buildDirectWorkflowGuidance, appendKnowledgeTaskConclusions, buildKnowledgeAtomicDispatch, buildKnowledgeDelegateDispatch, buildKnowledgeAssignmentTemplate, buildKnowledgeWriterAssignments, DEFAULT_MAX_TASKS_TO_KEEP, checkProjectProtocol, ClawError, assertRootPlanCreateAllowedForPlan, buildPlanWorkflowGuidance, buildMemoryIndex, buildSessionStartDefaultPrompt, buildSessionStartRecoveredPrompt, editPlan, ensureProjectProtocol, enforceTaskRetention, findKnowledgeFinalizationJobPath, findTaskDirectory, runDailyMaintenance, ingestTruth, initProject, getTemplateTaskDoneChoices, resolvePlanTemplateFile, resolvePlanEffectiveConfig, resolveKnowledgeWriterForHost, resolveProjectContext, resolveWorkflowProjectContext, resolveSessionWorkflowContext, deleteSessionWorkflow, sweepExpiredSessionWorkflows, resolveSessionBoundPlan, resolveContext, resolveSeedPlanTemplate, searchMemoryAsync, warmProjectMemoryEmbedding, showPlan, createSubplan, createPlanRef, switchTask, tryCaptureKnowledgeStop, claimKnowledgeFinalizationJob, doneKnowledgeFinalizationJob, readKnowledgeFinalizationJob, waitForKnowledgeFinalizationJobReady, listKnowledgeFinalizationJobs, listRetryableKnowledgeFinalizationJobs, normalizeTruthMarkdownEncoding, recordKnowledgeFinalizationResult, unbindSession, writePlan, } from "@veewo/claw-core";
|
|
9
|
+
import { buildDirectWorkflowGuidance, appendKnowledgeTaskConclusions, buildKnowledgeAtomicDispatch, buildKnowledgeDelegateDispatch, buildKnowledgeAssignmentTemplate, buildDirectKnowledgeAssignments, buildKnowledgeWriterAssignments, DEFAULT_MAX_TASKS_TO_KEEP, checkProjectProtocol, ClawError, assertRootPlanCreateAllowedForPlan, buildPlanWorkflowGuidance, buildMemoryIndex, buildSessionStartDefaultPrompt, buildSessionStartRecoveredPrompt, editPlan, ensureProjectProtocol, enforceTaskRetention, findKnowledgeFinalizationJobPath, findTaskDirectory, runDailyMaintenance, ingestTruth, initProject, getTemplateTaskDoneChoices, resolvePlanTemplateFile, resolvePlanEffectiveConfig, resolveThreadGoalPlan, resolveKnowledgeWriterForHost, resolveProjectContext, resolveWorkflowProjectContext, resolveSessionWorkflowContext, deleteSessionWorkflow, sweepExpiredSessionWorkflows, resolveSessionBoundPlan, resolveContext, resolveSeedPlanTemplate, searchMemoryAsync, warmProjectMemoryEmbedding, showPlan, createSubplan, createPlanRef, switchTask, tryCaptureKnowledgeStop, claimKnowledgeFinalizationJob, doneKnowledgeFinalizationJob, readKnowledgeFinalizationJob, waitForKnowledgeFinalizationJobReady, listKnowledgeFinalizationJobs, listRetryableKnowledgeFinalizationJobs, normalizeTruthMarkdownEncoding, governKnowledgeMarkdownPaths, resolveKnowledgeDocUpdateSnapshot, recordKnowledgeFinalizationResult, unbindSession, writePlan, } from "@veewo/claw-core";
|
|
10
10
|
import { buildCodexDriverEnvelope } from "./codex-driver.js";
|
|
11
11
|
import { buildCodexHostActions } from "./codex-host-actions.js";
|
|
12
12
|
import { checkCodexRuntime, resolveCodexSdkEntryPath } from "./codex-runtime.js";
|
|
@@ -333,8 +333,28 @@ const COMMAND_HELP = {
|
|
|
333
333
|
},
|
|
334
334
|
knowledge: {
|
|
335
335
|
usage: ["{script} knowledge <subcommand> [options]"],
|
|
336
|
-
description: "
|
|
336
|
+
description: "Commands for queued knowledge finalization jobs and explicit same-agent knowledge capture.",
|
|
337
337
|
subcommands: {
|
|
338
|
+
prepare: {
|
|
339
|
+
usage: ["{script} knowledge prepare --source agent-memory --project-root <path>"],
|
|
340
|
+
description: "Read the current project configuration and return the immutable assignment projection for one explicit manual knowledge capture. It never initializes, repairs, or mutates the project.",
|
|
341
|
+
summary: "Prepare explicit same-agent knowledge capture.",
|
|
342
|
+
options: [
|
|
343
|
+
{ flag: "--source agent-memory", detail: "(required) Only source supported by the manual same-agent route." },
|
|
344
|
+
{ flag: "--project-root <path>", detail: "(required) Project root used to resolve current team and personal configuration." },
|
|
345
|
+
],
|
|
346
|
+
},
|
|
347
|
+
complete: {
|
|
348
|
+
usage: ["{script} knowledge complete --source agent-memory --project-root <path> --config-fingerprint <hash> [--changed-truth <absolute-path> ...]"],
|
|
349
|
+
description: "Validate the prepared configuration, govern declared canonical paths, normalize knowledge encoding, and queue the existing completion refresh without creating a report or job.",
|
|
350
|
+
summary: "Complete explicit same-agent knowledge capture.",
|
|
351
|
+
options: [
|
|
352
|
+
{ flag: "--source agent-memory", detail: "(required) Only source supported by the manual same-agent route." },
|
|
353
|
+
{ flag: "--project-root <path>", detail: "(required) Project root used to resolve current configuration." },
|
|
354
|
+
{ flag: "--config-fingerprint <hash>", detail: "(required) Fingerprint returned by knowledge prepare." },
|
|
355
|
+
{ flag: "--changed-truth <absolute-path>", detail: "Canonical Truth or ADR Markdown path changed by this capture (repeatable)." },
|
|
356
|
+
],
|
|
357
|
+
},
|
|
338
358
|
wait: {
|
|
339
359
|
usage: ["{script} knowledge wait --project-root <path> --finalize-id <id> [--session-key <key>] [--timeout-ms <n>]"],
|
|
340
360
|
description: "Wait for Stop capture to create a knowledge finalization job. This command does not create or inspect session bindings.",
|
|
@@ -1024,6 +1044,24 @@ function readCindyKnowledgeClaimCaptureInput() {
|
|
|
1024
1044
|
async function runKnowledge(args) {
|
|
1025
1045
|
const subcommand = args.shift();
|
|
1026
1046
|
switch (subcommand) {
|
|
1047
|
+
case "prepare": {
|
|
1048
|
+
const source = readRequiredFlag(args, "--source");
|
|
1049
|
+
const projectRoot = path.resolve(readRequiredFlag(args, "--project-root"));
|
|
1050
|
+
assertNoRemainingArgs(args, "knowledge prepare");
|
|
1051
|
+
assertDirectKnowledgeSource(source);
|
|
1052
|
+
printJson(prepareDirectKnowledgeCapture(projectRoot));
|
|
1053
|
+
return;
|
|
1054
|
+
}
|
|
1055
|
+
case "complete": {
|
|
1056
|
+
const source = readRequiredFlag(args, "--source");
|
|
1057
|
+
const projectRoot = path.resolve(readRequiredFlag(args, "--project-root"));
|
|
1058
|
+
const configFingerprint = readRequiredFlag(args, "--config-fingerprint");
|
|
1059
|
+
const changedTruth = readRepeatedFlag(args, "--changed-truth");
|
|
1060
|
+
assertNoRemainingArgs(args, "knowledge complete");
|
|
1061
|
+
assertDirectKnowledgeSource(source);
|
|
1062
|
+
printJson(completeDirectKnowledgeCapture({ projectRoot, configFingerprint, changedTruth }));
|
|
1063
|
+
return;
|
|
1064
|
+
}
|
|
1027
1065
|
case "list": {
|
|
1028
1066
|
const projectRoot = path.resolve(readRequiredFlag(args, "--project-root"));
|
|
1029
1067
|
const sessionKey = readOptionalFlag(args, "--session-key");
|
|
@@ -1205,6 +1243,98 @@ async function runKnowledge(args) {
|
|
|
1205
1243
|
throw new ClawError("PROJECT_CONFIG_INVALID", `Unknown knowledge subcommand "${subcommand ?? ""}".`);
|
|
1206
1244
|
}
|
|
1207
1245
|
}
|
|
1246
|
+
function prepareDirectKnowledgeCapture(projectRoot) {
|
|
1247
|
+
const project = resolveProjectContext(projectRoot);
|
|
1248
|
+
const ownerSessionKey = resolveOwnerSessionKey() ?? undefined;
|
|
1249
|
+
if (ownerSessionKey && resolveSessionBoundPlan(project, ownerSessionKey)) {
|
|
1250
|
+
throw new ClawError("KNOWLEDGE_DIRECT_WORKFLOW_ACTIVE", "Manual knowledge capture cannot run while this session has an active claw workflow.");
|
|
1251
|
+
}
|
|
1252
|
+
const writer = project.projectConfig?.knowledgeWriter;
|
|
1253
|
+
const docUpdate = resolveKnowledgeDocUpdateSnapshot(project);
|
|
1254
|
+
const assignments = buildDirectKnowledgeAssignments({ writer, ...(docUpdate ? { docUpdate } : {}) });
|
|
1255
|
+
for (const assignment of assignments) {
|
|
1256
|
+
for (const resourcePath of [assignment.contractPath, assignment.formatPath]) {
|
|
1257
|
+
if (resourcePath && (!fs.existsSync(resourcePath) || !fs.statSync(resourcePath).isFile())) {
|
|
1258
|
+
throw new ClawError("KNOWLEDGE_DIRECT_RESOURCE_MISSING", "A required knowledge-capture contract resource is unavailable.", { resourcePath });
|
|
1259
|
+
}
|
|
1260
|
+
}
|
|
1261
|
+
}
|
|
1262
|
+
const configFingerprint = directKnowledgeConfigFingerprint({ project, assignments, docUpdate });
|
|
1263
|
+
return {
|
|
1264
|
+
ok: true,
|
|
1265
|
+
command: "knowledge.prepare",
|
|
1266
|
+
schemaVersion: 1,
|
|
1267
|
+
source: "agent-memory",
|
|
1268
|
+
project: { projectRoot: project.projectRoot, truthDir: project.truthDir },
|
|
1269
|
+
configFingerprint,
|
|
1270
|
+
assignments,
|
|
1271
|
+
refresh: {
|
|
1272
|
+
operations: ["memory.reindex.project", ...(project.projectConfig?.gitnexus === true ? ["gitnexus.refresh"] : [])],
|
|
1273
|
+
},
|
|
1274
|
+
};
|
|
1275
|
+
}
|
|
1276
|
+
function completeDirectKnowledgeCapture(input) {
|
|
1277
|
+
const prepared = prepareDirectKnowledgeCapture(input.projectRoot);
|
|
1278
|
+
if (prepared.configFingerprint !== input.configFingerprint) {
|
|
1279
|
+
throw new ClawError("KNOWLEDGE_DIRECT_CONFIG_CHANGED", "Knowledge-capture configuration changed after prepare; run knowledge prepare again before completion.", { expected: input.configFingerprint, actual: prepared.configFingerprint });
|
|
1280
|
+
}
|
|
1281
|
+
const project = resolveProjectContext(input.projectRoot);
|
|
1282
|
+
const relativePaths = input.changedTruth.map((candidate) => relativeTruthPath(project.truthDir, candidate));
|
|
1283
|
+
const builtin = prepared.assignments.find((assignment) => assignment.kind === "builtin");
|
|
1284
|
+
const governance = builtin
|
|
1285
|
+
? governKnowledgeMarkdownPaths({
|
|
1286
|
+
truthDir: project.truthDir,
|
|
1287
|
+
relativePaths,
|
|
1288
|
+
datedSectionsToKeep: builtin.datedSectionsToKeep ?? 6,
|
|
1289
|
+
})
|
|
1290
|
+
: { changedFiles: 0, compactedFiles: 0, removedSections: 0, files: [] };
|
|
1291
|
+
const truthEncoding = normalizeTruthMarkdownEncoding(project);
|
|
1292
|
+
const refresh = queueCompletionRefresh({
|
|
1293
|
+
cwd: project.projectRoot,
|
|
1294
|
+
taskName: "knowledge-capture",
|
|
1295
|
+
includeTaskRetention: false,
|
|
1296
|
+
statusLabel: "knowledge-capture",
|
|
1297
|
+
});
|
|
1298
|
+
return {
|
|
1299
|
+
ok: true,
|
|
1300
|
+
command: "knowledge.complete",
|
|
1301
|
+
source: "agent-memory",
|
|
1302
|
+
configFingerprint: prepared.configFingerprint,
|
|
1303
|
+
changedTruth: relativePaths,
|
|
1304
|
+
governance,
|
|
1305
|
+
truthEncoding,
|
|
1306
|
+
asyncRefresh: refresh.asyncRefresh,
|
|
1307
|
+
};
|
|
1308
|
+
}
|
|
1309
|
+
function assertDirectKnowledgeSource(source) {
|
|
1310
|
+
if (source !== "agent-memory") {
|
|
1311
|
+
throw new ClawError("PROJECT_CONFIG_INVALID", 'Manual knowledge capture supports only --source agent-memory.');
|
|
1312
|
+
}
|
|
1313
|
+
}
|
|
1314
|
+
function relativeTruthPath(truthDir, candidate) {
|
|
1315
|
+
const root = path.resolve(truthDir);
|
|
1316
|
+
const target = path.resolve(candidate);
|
|
1317
|
+
const relative = path.relative(root, target);
|
|
1318
|
+
if (!relative || relative.startsWith("..") || path.isAbsolute(relative) || !/\.md$/iu.test(relative)) {
|
|
1319
|
+
throw new ClawError("KNOWLEDGE_DIRECT_PATH_INVALID", "Changed knowledge paths must be Markdown files inside the resolved truth directory.", { candidate, truthDir: root });
|
|
1320
|
+
}
|
|
1321
|
+
return relative.replaceAll("\\", "/");
|
|
1322
|
+
}
|
|
1323
|
+
function directKnowledgeConfigFingerprint(input) {
|
|
1324
|
+
const payload = {
|
|
1325
|
+
schemaVersion: 1,
|
|
1326
|
+
truthDir: path.resolve(input.project.truthDir),
|
|
1327
|
+
assignments: input.assignments.map((assignment) => ({
|
|
1328
|
+
kind: assignment.kind,
|
|
1329
|
+
skill: assignment.skill ?? null,
|
|
1330
|
+
datedSectionsToKeep: assignment.datedSectionsToKeep ?? null,
|
|
1331
|
+
})),
|
|
1332
|
+
externalDocPaths: input.docUpdate?.externalDocPaths ?? [],
|
|
1333
|
+
gitnexus: input.project.projectConfig?.gitnexus === true,
|
|
1334
|
+
memoryRefresh: input.project.projectConfig?.memory?.enabled !== false,
|
|
1335
|
+
};
|
|
1336
|
+
return `sha256:${createHash("sha256").update(JSON.stringify(payload)).digest("hex")}`;
|
|
1337
|
+
}
|
|
1208
1338
|
async function runPlan(args, effectiveHost) {
|
|
1209
1339
|
const subcommand = args.shift();
|
|
1210
1340
|
switch (subcommand) {
|
|
@@ -1223,7 +1353,7 @@ async function runPlan(args, effectiveHost) {
|
|
|
1223
1353
|
throw new ClawError("PROJECT_CONFIG_INVALID", "plan create requires a title. Use `claw plan create \"<title>\"` or `claw plan create --title \"<title>\"`.");
|
|
1224
1354
|
}
|
|
1225
1355
|
const ownerSessionKey = resolveOwnerSessionKey();
|
|
1226
|
-
assertDirectRootPlanCreateAllowed(process.cwd(), ownerSessionKey);
|
|
1356
|
+
assertDirectRootPlanCreateAllowed(process.cwd(), ownerSessionKey, scope);
|
|
1227
1357
|
await preparePlanCreateWorkflow(process.cwd(), ownerSessionKey, effectiveHost, scope);
|
|
1228
1358
|
const result = await writePlan({
|
|
1229
1359
|
cwd: process.cwd(),
|
|
@@ -1235,6 +1365,15 @@ async function runPlan(args, effectiveHost) {
|
|
|
1235
1365
|
ownerSessionKey: ownerSessionKey ?? undefined,
|
|
1236
1366
|
host: effectiveHost,
|
|
1237
1367
|
});
|
|
1368
|
+
if (ownerSessionKey && scope !== "session") {
|
|
1369
|
+
const sessionProject = resolveSessionWorkflowContext(ownerSessionKey);
|
|
1370
|
+
if (sessionProject) {
|
|
1371
|
+
const relativePlanPath = path.relative(sessionProject.clawDir, result.planPath);
|
|
1372
|
+
if (relativePlanPath.startsWith("..") || path.isAbsolute(relativePlanPath)) {
|
|
1373
|
+
unbindSession(sessionProject, ownerSessionKey);
|
|
1374
|
+
}
|
|
1375
|
+
}
|
|
1376
|
+
}
|
|
1238
1377
|
assertNoRemainingArgs(args, "plan create");
|
|
1239
1378
|
printJson(compactPlanCommandResult("plan.create", result, effectiveHost));
|
|
1240
1379
|
return;
|
|
@@ -1260,8 +1399,8 @@ async function runPlan(args, effectiveHost) {
|
|
|
1260
1399
|
&& effectiveHost !== "cindy") {
|
|
1261
1400
|
throw new ClawError("PROJECT_CONFIG_INVALID", 'knowledgeWriter.executionPolicy "subagent" is supported only by the Codex or Cindy host.', { host: effectiveHost ?? null });
|
|
1262
1401
|
}
|
|
1263
|
-
const
|
|
1264
|
-
?
|
|
1402
|
+
const terminalRefresh = entersEndTerminal
|
|
1403
|
+
? preparePlanTerminalRefresh(process.cwd(), ownerSessionKey)
|
|
1265
1404
|
: undefined;
|
|
1266
1405
|
const result = await editPlan({
|
|
1267
1406
|
cwd: process.cwd(),
|
|
@@ -1283,7 +1422,7 @@ async function runPlan(args, effectiveHost) {
|
|
|
1283
1422
|
writer: effectiveWriter,
|
|
1284
1423
|
})
|
|
1285
1424
|
: undefined;
|
|
1286
|
-
const completionRefresh =
|
|
1425
|
+
const completionRefresh = queueTerminalRefreshIfEntered(result, terminalRefresh);
|
|
1287
1426
|
printJson(compactPlanCommandResult("plan.edit", result, effectiveHost, completionRefresh, false, knowledgeDispatch));
|
|
1288
1427
|
if (result.operationChain?.status === "partial")
|
|
1289
1428
|
process.exitCode = 1;
|
|
@@ -1371,7 +1510,7 @@ async function runPlan(args, effectiveHost) {
|
|
|
1371
1510
|
&& effectiveHost !== "cindy") {
|
|
1372
1511
|
throw new ClawError("PROJECT_CONFIG_INVALID", 'knowledgeWriter.executionPolicy "subagent" is supported only by the Codex or Cindy host.', { host: effectiveHost ?? null });
|
|
1373
1512
|
}
|
|
1374
|
-
const
|
|
1513
|
+
const terminalRefresh = preparePlanTerminalRefresh(process.cwd(), ownerSessionKey);
|
|
1375
1514
|
const result = await editPlan({
|
|
1376
1515
|
cwd: process.cwd(),
|
|
1377
1516
|
...target,
|
|
@@ -1390,7 +1529,7 @@ async function runPlan(args, effectiveHost) {
|
|
|
1390
1529
|
writer: effectiveWriter,
|
|
1391
1530
|
})
|
|
1392
1531
|
: undefined;
|
|
1393
|
-
const completionRefresh =
|
|
1532
|
+
const completionRefresh = queueTerminalRefreshIfEntered(result, terminalRefresh);
|
|
1394
1533
|
printJson(compactPlanCommandResult("plan.done", result, effectiveHost, completionRefresh, false, knowledgeDispatch));
|
|
1395
1534
|
return;
|
|
1396
1535
|
}
|
|
@@ -1439,6 +1578,7 @@ async function runPlanLeave(args, effectiveHost) {
|
|
|
1439
1578
|
const ownerSessionKey = resolveOwnerSessionKey() ?? undefined;
|
|
1440
1579
|
const target = readPlanMutationTarget(args);
|
|
1441
1580
|
assertNoRemainingArgs(args, "plan leave");
|
|
1581
|
+
const terminalRefresh = preparePlanTerminalRefresh(process.cwd(), ownerSessionKey);
|
|
1442
1582
|
const result = await editPlan({
|
|
1443
1583
|
cwd: process.cwd(),
|
|
1444
1584
|
...target,
|
|
@@ -1447,7 +1587,8 @@ async function runPlanLeave(args, effectiveHost) {
|
|
|
1447
1587
|
host: effectiveHost,
|
|
1448
1588
|
ownerSessionKey,
|
|
1449
1589
|
});
|
|
1450
|
-
|
|
1590
|
+
const completionRefresh = queueTerminalRefreshIfEntered(result, terminalRefresh);
|
|
1591
|
+
printJson(compactPlanCommandResult("plan.leave", result, effectiveHost, completionRefresh, true));
|
|
1451
1592
|
}
|
|
1452
1593
|
async function runPlanSync(args, effectiveHost) {
|
|
1453
1594
|
const ownerSessionKey = resolveOwnerSessionKey() ?? undefined;
|
|
@@ -1458,12 +1599,20 @@ async function runPlanSync(args, effectiveHost) {
|
|
|
1458
1599
|
return;
|
|
1459
1600
|
}
|
|
1460
1601
|
const project = resolveWorkflowProjectContext(process.cwd(), ownerSessionKey);
|
|
1602
|
+
const goalPlan = resolveThreadGoalPlan({
|
|
1603
|
+
cwd: process.cwd(),
|
|
1604
|
+
taskName: result.taskName,
|
|
1605
|
+
focusedPlan: result.plan,
|
|
1606
|
+
ownerSessionKey,
|
|
1607
|
+
});
|
|
1461
1608
|
const workflowGuidance = await buildPlanWorkflowGuidance({
|
|
1462
1609
|
taskName: result.taskName,
|
|
1463
1610
|
planFile: result.planFile,
|
|
1464
1611
|
plan: result.plan,
|
|
1465
1612
|
projectRoot: project.projectRoot,
|
|
1466
1613
|
projectConfig: project.projectConfig,
|
|
1614
|
+
goalPlan,
|
|
1615
|
+
goalProjectConfig: resolvePlanEffectiveConfig(project.projectConfig, goalPlan),
|
|
1467
1616
|
scope: project.scope,
|
|
1468
1617
|
previousStatus: "process.wait",
|
|
1469
1618
|
host: effectiveHost,
|
|
@@ -1642,7 +1791,10 @@ async function runContextCommand(args, cwd = process.cwd(), ownerSessionKey = re
|
|
|
1642
1791
|
let corrected = false;
|
|
1643
1792
|
let fixedPaths = [];
|
|
1644
1793
|
const sessionProject = resolveSessionWorkflowContext(ownerSessionKey ?? undefined);
|
|
1645
|
-
|
|
1794
|
+
const sessionPlanPath = sessionProject && ownerSessionKey
|
|
1795
|
+
? resolveSessionBoundPlan(sessionProject, ownerSessionKey)
|
|
1796
|
+
: null;
|
|
1797
|
+
if (sessionProject && sessionPlanPath) {
|
|
1646
1798
|
const maintenance = effectiveHost
|
|
1647
1799
|
? null
|
|
1648
1800
|
: runDailyMaintenance(sessionProject, {
|
|
@@ -2199,10 +2351,14 @@ async function preparePlanCreateWorkflow(cwd, ownerSessionKey, effectiveHost, re
|
|
|
2199
2351
|
}
|
|
2200
2352
|
await prepareProjectWorkflow(cwd, ownerSessionKey, effectiveHost, project);
|
|
2201
2353
|
}
|
|
2202
|
-
function assertDirectRootPlanCreateAllowed(cwd, ownerSessionKey) {
|
|
2354
|
+
function assertDirectRootPlanCreateAllowed(cwd, ownerSessionKey, requestedScope) {
|
|
2203
2355
|
if (!ownerSessionKey)
|
|
2204
2356
|
return;
|
|
2205
|
-
const project =
|
|
2357
|
+
const project = requestedScope === "session"
|
|
2358
|
+
? resolveSessionWorkflowContext(ownerSessionKey)
|
|
2359
|
+
: tryResolveHookProject(cwd);
|
|
2360
|
+
if (!project)
|
|
2361
|
+
return;
|
|
2206
2362
|
const planPath = resolveSessionBoundPlan(project, ownerSessionKey);
|
|
2207
2363
|
if (!planPath)
|
|
2208
2364
|
return;
|
|
@@ -2604,7 +2760,7 @@ function buildSessionStartAdditionalContext(context, sessionCwd, effectiveHost)
|
|
|
2604
2760
|
if (activeWorkflow) {
|
|
2605
2761
|
const prompt = buildRecoveredWorkflowAdditionalContext(activeWorkflow, versionSyncPrompt);
|
|
2606
2762
|
const recoverySyncPrompt = effectiveHost === "codex" && activeWorkflow.planStatus === "process.active"
|
|
2607
|
-
? "Before continuing, run `claw plan sync` once through the fixed Codex driver to restore
|
|
2763
|
+
? "Before continuing, run `claw plan sync` once through the fixed Codex driver to restore focused-plan progress and reconcile the root-plan Goal."
|
|
2608
2764
|
: "";
|
|
2609
2765
|
const promptWithSync = recoverySyncPrompt ? `${prompt}\n${recoverySyncPrompt}` : prompt;
|
|
2610
2766
|
const promptWithSearch = searchGuidance ? `${promptWithSync}\n${searchGuidance}` : promptWithSync;
|
|
@@ -3315,11 +3471,24 @@ function readRepeatedIntegerFlag(args, flag) {
|
|
|
3315
3471
|
function failMissingNumericFlag(flag) {
|
|
3316
3472
|
throw new ClawError("PROJECT_CONFIG_INVALID", `Missing required flag ${flag}.`, { flag });
|
|
3317
3473
|
}
|
|
3318
|
-
function
|
|
3474
|
+
function preparePlanTerminalRefresh(cwd, ownerSessionKey) {
|
|
3319
3475
|
const workflowProject = resolveWorkflowProjectContext(cwd, ownerSessionKey);
|
|
3320
|
-
|
|
3476
|
+
const refreshProject = tryResolveHookProject(workflowProject.projectRoot);
|
|
3477
|
+
if (!refreshProject)
|
|
3321
3478
|
return undefined;
|
|
3322
|
-
return
|
|
3479
|
+
return {
|
|
3480
|
+
queue: (taskName) => queueCompletionRefresh({
|
|
3481
|
+
cwd: refreshProject.projectRoot,
|
|
3482
|
+
taskName,
|
|
3483
|
+
includeTaskRetention: workflowProject.scope !== "session",
|
|
3484
|
+
}),
|
|
3485
|
+
};
|
|
3486
|
+
}
|
|
3487
|
+
function queueTerminalRefreshIfEntered(result, terminalRefresh) {
|
|
3488
|
+
if (!terminalRefresh || result.previousPlanStatus.startsWith("end.") || !result.planStatus.startsWith("end.")) {
|
|
3489
|
+
return undefined;
|
|
3490
|
+
}
|
|
3491
|
+
return terminalRefresh.queue(result.taskName);
|
|
3323
3492
|
}
|
|
3324
3493
|
function queueCompletionRefresh(input) {
|
|
3325
3494
|
const project = resolveProjectContext(input.cwd);
|