agent-method 1.5.12 → 1.5.15
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/wwa.js +1 -1
- package/docs/internal/doc-tokens.yaml +1 -1
- package/lib/cli/add.js +170 -96
- package/lib/cli/casestudy.js +152 -92
- package/lib/cli/close.js +164 -141
- package/lib/cli/helpers.js +13 -0
- package/lib/cli/record.js +81 -59
- package/lib/cli/upgrade.js +144 -2
- package/lib/init.js +1 -2
- package/lib/mcp-server.js +842 -1
- package/package.json +1 -1
package/lib/cli/close.js
CHANGED
|
@@ -10,173 +10,196 @@ import { resolveTokensPath, resolveDocsMapPath, resolveIndexPath, resolveFeature
|
|
|
10
10
|
const __filename = fileURLToPath(import.meta.url);
|
|
11
11
|
const __dirname = dirname(__filename);
|
|
12
12
|
|
|
13
|
-
export function
|
|
14
|
-
|
|
15
|
-
.command("close [directory]")
|
|
16
|
-
.description("Show session close checklist, cascade reminders, and project snapshot")
|
|
17
|
-
.option("--json", "Output as JSON")
|
|
18
|
-
.option("--internal-registry", "Include docs/internal/doc-registry.yaml health in management output")
|
|
19
|
-
.action(async (directory, opts) => {
|
|
20
|
-
directory = directory || ".";
|
|
21
|
-
const d = resolve(directory);
|
|
13
|
+
export async function runClose(directory, options = {}) {
|
|
14
|
+
const d = resolve(directory || ".");
|
|
22
15
|
|
|
23
|
-
|
|
24
|
-
|
|
16
|
+
const checklist = [];
|
|
17
|
+
const warnings = [];
|
|
25
18
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
19
|
+
// 1. Check SESSION-LOG.md exists
|
|
20
|
+
const sessionLog = findSessionLog(d);
|
|
21
|
+
if (sessionLog) {
|
|
22
|
+
checklist.push({ item: "SESSION-LOG.md exists", ok: true });
|
|
23
|
+
} else {
|
|
24
|
+
checklist.push({ item: "SESSION-LOG.md exists", ok: false });
|
|
25
|
+
warnings.push("No SESSION-LOG.md found — create one to track session metrics");
|
|
26
|
+
}
|
|
34
27
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
28
|
+
// 2. Check STATE.md exists and has current position
|
|
29
|
+
const statePath = join(d, "STATE.md");
|
|
30
|
+
if (existsSync(statePath)) {
|
|
31
|
+
checklist.push({ item: "STATE.md exists", ok: true });
|
|
32
|
+
} else {
|
|
33
|
+
checklist.push({ item: "STATE.md exists", ok: false });
|
|
34
|
+
warnings.push("No STATE.md found — decisions may be lost between sessions");
|
|
35
|
+
}
|
|
43
36
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
37
|
+
// 3. Check PLAN.md for incomplete steps
|
|
38
|
+
const planPath = join(d, "PLAN.md");
|
|
39
|
+
if (existsSync(planPath)) {
|
|
40
|
+
const planContent = readFileSync(planPath, "utf-8");
|
|
41
|
+
const todoSteps = (planContent.match(/\|\s*todo\s*\|/gi) || []).length;
|
|
42
|
+
if (todoSteps > 0) {
|
|
43
|
+
checklist.push({
|
|
44
|
+
item: `PLAN.md has ${todoSteps} incomplete step(s)`,
|
|
45
|
+
ok: false,
|
|
46
|
+
});
|
|
47
|
+
} else {
|
|
48
|
+
checklist.push({ item: "PLAN.md — all steps complete", ok: true });
|
|
49
|
+
}
|
|
50
|
+
}
|
|
58
51
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
52
|
+
// 4. Check Management files
|
|
53
|
+
const digestPath = join(d, "Management", "DIGEST.md");
|
|
54
|
+
if (existsSync(digestPath)) {
|
|
55
|
+
checklist.push({ item: "Management/DIGEST.md exists", ok: true });
|
|
56
|
+
}
|
|
64
57
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
58
|
+
// 5. Check SUMMARY.md
|
|
59
|
+
const summaryPath = join(d, "SUMMARY.md");
|
|
60
|
+
if (existsSync(summaryPath)) {
|
|
61
|
+
checklist.push({ item: "SUMMARY.md exists for audit entry", ok: true });
|
|
62
|
+
}
|
|
70
63
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
} else {
|
|
88
|
-
const vLine = /^(version: .+)$/m;
|
|
89
|
-
raw = raw.replace(vLine, `$1\nlast_verified: "${today}"`);
|
|
90
|
-
}
|
|
91
|
-
safeWriteFile(protocolPath, raw, "utf-8");
|
|
92
|
-
} catch (_) {
|
|
93
|
-
cascadeReminders = getDefaultReminders();
|
|
94
|
-
}
|
|
64
|
+
// Build cascade reminders from PROTOCOL.yaml or fallback to defaults.
|
|
65
|
+
// If PROTOCOL.yaml has an empty close_check list, fall back to defaults so
|
|
66
|
+
// the user always sees helpful reminders.
|
|
67
|
+
let cascadeReminders;
|
|
68
|
+
const protocolPath = join(d, ".context", "PROTOCOL.yaml");
|
|
69
|
+
if (existsSync(protocolPath)) {
|
|
70
|
+
try {
|
|
71
|
+
const yaml = (await import("js-yaml")).default;
|
|
72
|
+
let raw = readFileSync(protocolPath, "utf-8");
|
|
73
|
+
const parsed = yaml.load(raw);
|
|
74
|
+
cascadeReminders = parsed?.close_check || getDefaultReminders();
|
|
75
|
+
// Update last_verified timestamp (comment-preserving)
|
|
76
|
+
const today = new Date().toISOString().slice(0, 10);
|
|
77
|
+
const lvPattern = /^(last_verified:) .+$/m;
|
|
78
|
+
if (lvPattern.test(raw)) {
|
|
79
|
+
raw = raw.replace(lvPattern, `$1 "${today}"`);
|
|
95
80
|
} else {
|
|
96
|
-
|
|
81
|
+
const vLine = /^(version: .+)$/m;
|
|
82
|
+
raw = raw.replace(vLine, `$1\nlast_verified: "${today}"`);
|
|
97
83
|
}
|
|
84
|
+
safeWriteFile(protocolPath, raw, "utf-8");
|
|
85
|
+
} catch (_) {
|
|
86
|
+
cascadeReminders = getDefaultReminders();
|
|
87
|
+
}
|
|
88
|
+
} else {
|
|
89
|
+
cascadeReminders = getDefaultReminders();
|
|
90
|
+
}
|
|
98
91
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
92
|
+
// If we still have no reminders (empty array), use defaults.
|
|
93
|
+
if (!cascadeReminders || cascadeReminders.length === 0) {
|
|
94
|
+
cascadeReminders = getDefaultReminders();
|
|
95
|
+
}
|
|
103
96
|
|
|
104
|
-
|
|
105
|
-
|
|
97
|
+
// Compute project snapshot — methodology reference data
|
|
98
|
+
const snapshot = await computeProjectSnapshot(d);
|
|
106
99
|
|
|
107
|
-
|
|
108
|
-
|
|
100
|
+
// Update project doc-tokens.yaml regardless of output mode
|
|
101
|
+
const tokenUpdateResult = await updateProjectTokens(d, snapshot);
|
|
109
102
|
|
|
110
|
-
|
|
111
|
-
|
|
103
|
+
// Update INDEX.yaml metrics
|
|
104
|
+
const indexUpdateResult = await updateIndexMetrics(d, snapshot);
|
|
112
105
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
// doc-review module not available — skip silently
|
|
124
|
-
}
|
|
125
|
-
}
|
|
106
|
+
// Load internal registry if requested
|
|
107
|
+
let internalRegistry = null;
|
|
108
|
+
if (options.internalRegistry) {
|
|
109
|
+
try {
|
|
110
|
+
const { loadInternalRegistry } = await import("./doc-review.js");
|
|
111
|
+
internalRegistry = await loadInternalRegistry(d);
|
|
112
|
+
} catch {
|
|
113
|
+
// doc-review module not available — skip silently
|
|
114
|
+
}
|
|
115
|
+
}
|
|
126
116
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
117
|
+
// Always write management files (close-snapshot.yaml + STATUS.md) at close.
|
|
118
|
+
const writeResults = await writeManagementFiles(
|
|
119
|
+
d,
|
|
120
|
+
snapshot,
|
|
121
|
+
checklist,
|
|
122
|
+
cascadeReminders,
|
|
123
|
+
internalRegistry
|
|
124
|
+
);
|
|
135
125
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
126
|
+
return {
|
|
127
|
+
directory: d,
|
|
128
|
+
checklist,
|
|
129
|
+
warnings,
|
|
130
|
+
cascadeReminders,
|
|
131
|
+
snapshot,
|
|
132
|
+
tokensUpdated: !!tokenUpdateResult,
|
|
133
|
+
indexUpdated: !!indexUpdateResult,
|
|
134
|
+
writeResults,
|
|
135
|
+
internalRegistryLoaded: !!internalRegistry,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export function register(program) {
|
|
140
|
+
program
|
|
141
|
+
.command("close [directory]")
|
|
142
|
+
.description("Show session close checklist, cascade reminders, and project snapshot")
|
|
143
|
+
.option("--json", "Output as JSON")
|
|
144
|
+
.option(
|
|
145
|
+
"--internal-registry",
|
|
146
|
+
"Include docs/internal/doc-registry.yaml health in management output"
|
|
147
|
+
)
|
|
148
|
+
.action(async (directory, opts) => {
|
|
149
|
+
const d = directory || ".";
|
|
150
|
+
try {
|
|
151
|
+
const result = await runClose(d, {
|
|
152
|
+
internalRegistry: opts.internalRegistry,
|
|
153
|
+
});
|
|
142
154
|
|
|
143
|
-
|
|
155
|
+
if (opts.json) {
|
|
156
|
+
console.log(JSON.stringify(result, null, 2));
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
144
159
|
|
|
145
|
-
|
|
146
|
-
const icon = item.ok ? "[x]" : "[ ]";
|
|
147
|
-
console.log(` ${icon} ${item.item}`);
|
|
148
|
-
}
|
|
160
|
+
console.log("\n Session Close Checklist\n");
|
|
149
161
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
console.log(` ! ${w}`);
|
|
162
|
+
for (const item of result.checklist) {
|
|
163
|
+
const icon = item.ok ? "[x]" : "[ ]";
|
|
164
|
+
console.log(` ${icon} ${item.item}`);
|
|
154
165
|
}
|
|
155
|
-
}
|
|
156
166
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
167
|
+
if (result.warnings.length > 0) {
|
|
168
|
+
console.log("\n Warnings:");
|
|
169
|
+
for (const w of result.warnings) {
|
|
170
|
+
console.log(` ! ${w}`);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
161
173
|
|
|
162
|
-
|
|
163
|
-
|
|
174
|
+
console.log("\n Cascade reminders:");
|
|
175
|
+
for (const r of result.cascadeReminders) {
|
|
176
|
+
console.log(` - ${r}`);
|
|
177
|
+
}
|
|
164
178
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
}
|
|
179
|
+
// Print project snapshot
|
|
180
|
+
printSnapshot(result.snapshot);
|
|
168
181
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
182
|
+
if (result.tokensUpdated) {
|
|
183
|
+
console.log("\n Updated doc-tokens.yaml with current project metrics.");
|
|
184
|
+
}
|
|
172
185
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
186
|
+
if (result.indexUpdated) {
|
|
187
|
+
console.log(" Updated INDEX.yaml with current project metrics.");
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
if (result.writeResults) {
|
|
191
|
+
console.log("\n Management files written:");
|
|
192
|
+
if (result.writeResults.snapshotYaml)
|
|
193
|
+
console.log(` - ${result.writeResults.snapshotYaml}`);
|
|
194
|
+
if (result.writeResults.statusMd)
|
|
195
|
+
console.log(` - ${result.writeResults.statusMd}`);
|
|
196
|
+
}
|
|
178
197
|
|
|
179
|
-
|
|
198
|
+
console.log("");
|
|
199
|
+
} catch (e) {
|
|
200
|
+
console.error(e.message || "wwa close failed.");
|
|
201
|
+
process.exit(1);
|
|
202
|
+
}
|
|
180
203
|
});
|
|
181
204
|
}
|
|
182
205
|
|
package/lib/cli/helpers.js
CHANGED
|
@@ -22,6 +22,19 @@ export const pkg = _pkg;
|
|
|
22
22
|
/** Package root directory (two levels up from lib/cli/). */
|
|
23
23
|
export const packageRoot = resolve(__dirname, "..", "..");
|
|
24
24
|
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
// Archive and naming invariant (all wwa commands)
|
|
27
|
+
// ---------------------------------------------------------------------------
|
|
28
|
+
//
|
|
29
|
+
// Canonical names persist in the working directory: CLAUDE.md, .cursorrules,
|
|
30
|
+
// AGENT.md, registry/doc-tokens.yaml, etc. Wwa never writes versioned names
|
|
31
|
+
// (e.g. CLAUDE.v2.md or doc-tokens.v2.yaml) into the project root. When we
|
|
32
|
+
// need to keep a previous version, we put it under the archive subdirectory
|
|
33
|
+
// only (e.g. .wwa-archive/entry-points/CLAUDE.v2.md).
|
|
34
|
+
|
|
35
|
+
/** Archive root for versioned/archived copies. Versioned filenames exist only under this tree. */
|
|
36
|
+
export const WWA_ARCHIVE_DIR = ".wwa-archive";
|
|
37
|
+
|
|
25
38
|
// ---------------------------------------------------------------------------
|
|
26
39
|
// Project type aliases
|
|
27
40
|
// ---------------------------------------------------------------------------
|
package/lib/cli/record.js
CHANGED
|
@@ -11,6 +11,71 @@ import {
|
|
|
11
11
|
parseLastRunContent,
|
|
12
12
|
} from "./report-helpers.js";
|
|
13
13
|
|
|
14
|
+
/**
|
|
15
|
+
* Core implementation for `wwa record` and MCP write-safe tools.
|
|
16
|
+
*/
|
|
17
|
+
export async function runRecord(directory, options = {}) {
|
|
18
|
+
const dir = resolve(directory || ".");
|
|
19
|
+
const dryRun = !!options.dryRun;
|
|
20
|
+
|
|
21
|
+
const content = readLastRunSummary(dir);
|
|
22
|
+
if (!content) {
|
|
23
|
+
const msg =
|
|
24
|
+
"No recent CLI output to record. Run a wwa command (e.g. wwa route '…', wwa scan) first.";
|
|
25
|
+
const error = new Error(msg);
|
|
26
|
+
error.code = "NO_LAST_RUN";
|
|
27
|
+
throw error;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const parsed = parseLastRunContent(content);
|
|
31
|
+
if (!parsed) {
|
|
32
|
+
const msg = "Last run file was invalid; nothing to record.";
|
|
33
|
+
const error = new Error(msg);
|
|
34
|
+
error.code = "INVALID_LAST_RUN";
|
|
35
|
+
throw error;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const date = parsed.timestamp.slice(0, 10);
|
|
39
|
+
const block = [
|
|
40
|
+
"",
|
|
41
|
+
`### CLI run — ${date} — ${parsed.command}`,
|
|
42
|
+
"",
|
|
43
|
+
`Command: wwa ${parsed.command}`,
|
|
44
|
+
`Input: ${parsed.inputRef}`,
|
|
45
|
+
`Summary: ${parsed.summary}`,
|
|
46
|
+
"",
|
|
47
|
+
].join("\n");
|
|
48
|
+
|
|
49
|
+
const sessionLog = findSessionLog(dir);
|
|
50
|
+
if (!sessionLog) {
|
|
51
|
+
const msg = "No SESSION-LOG.md found. Create it or run from project root.";
|
|
52
|
+
const error = new Error(msg);
|
|
53
|
+
error.code = "NO_SESSION_LOG";
|
|
54
|
+
throw error;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (dryRun) {
|
|
58
|
+
return {
|
|
59
|
+
directory: dir,
|
|
60
|
+
target: sessionLog,
|
|
61
|
+
block: block.trim(),
|
|
62
|
+
dryRun: true,
|
|
63
|
+
recorded: false,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const existing = readFileSync(sessionLog, "utf-8");
|
|
68
|
+
safeWriteFile(sessionLog, existing + block, "utf-8");
|
|
69
|
+
clearLastRunSummary(dir);
|
|
70
|
+
|
|
71
|
+
return {
|
|
72
|
+
directory: dir,
|
|
73
|
+
target: sessionLog,
|
|
74
|
+
dryRun: false,
|
|
75
|
+
recorded: true,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
14
79
|
export function register(program) {
|
|
15
80
|
program
|
|
16
81
|
.command("record [directory]")
|
|
@@ -19,80 +84,37 @@ export function register(program) {
|
|
|
19
84
|
.option("--dry-run", "Show what would be appended without writing")
|
|
20
85
|
.option("--json", "Output as JSON")
|
|
21
86
|
.action(async (directory, cmd) => {
|
|
22
|
-
const opts = typeof cmd?.opts === "function" ? cmd.opts() :
|
|
23
|
-
|
|
24
|
-
|
|
87
|
+
const opts = typeof cmd?.opts === "function" ? cmd.opts() : cmd || {};
|
|
88
|
+
// Prefer explicit directory argument over option default so tests and callers
|
|
89
|
+
// can target a specific project root without being affected by cwd state.
|
|
90
|
+
const dir = resolve(directory || opts.directory || ".");
|
|
25
91
|
|
|
26
|
-
|
|
27
|
-
const
|
|
28
|
-
"No recent CLI output to record. Run a wwa command (e.g. wwa route '…', wwa scan) first.";
|
|
29
|
-
if (opts.json) {
|
|
30
|
-
console.log(JSON.stringify({ recorded: false, error: msg }, null, 2));
|
|
31
|
-
} else {
|
|
32
|
-
console.log(`\n ${msg}\n`);
|
|
33
|
-
}
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
92
|
+
try {
|
|
93
|
+
const result = await runRecord(dir, { dryRun: opts.dryRun });
|
|
36
94
|
|
|
37
|
-
const parsed = parseLastRunContent(content);
|
|
38
|
-
if (!parsed) {
|
|
39
|
-
const msg = "Last run file was invalid; nothing to record.";
|
|
40
95
|
if (opts.json) {
|
|
41
|
-
console.log(JSON.stringify(
|
|
42
|
-
|
|
43
|
-
console.log(`\n ${msg}\n`);
|
|
96
|
+
console.log(JSON.stringify(result, null, 2));
|
|
97
|
+
return;
|
|
44
98
|
}
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const date = parsed.timestamp.slice(0, 10);
|
|
49
|
-
const block = [
|
|
50
|
-
"",
|
|
51
|
-
`### CLI run — ${date} — ${parsed.command}`,
|
|
52
|
-
"",
|
|
53
|
-
`Command: wwa ${parsed.command}`,
|
|
54
|
-
`Input: ${parsed.inputRef}`,
|
|
55
|
-
`Summary: ${parsed.summary}`,
|
|
56
|
-
"",
|
|
57
|
-
].join("\n");
|
|
58
99
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
if (
|
|
63
|
-
console.log(
|
|
64
|
-
} else {
|
|
65
|
-
console.log(`\n ${msg}\n`);
|
|
100
|
+
if (result.dryRun) {
|
|
101
|
+
console.log("\n Dry run — would append to", result.target);
|
|
102
|
+
console.log(result.block);
|
|
103
|
+
} else if (result.recorded) {
|
|
104
|
+
console.log("\n Recorded last CLI run to SESSION-LOG.md.\n");
|
|
66
105
|
}
|
|
67
|
-
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
if (opts.dryRun) {
|
|
106
|
+
} catch (e) {
|
|
71
107
|
if (opts.json) {
|
|
72
108
|
console.log(
|
|
73
109
|
JSON.stringify(
|
|
74
|
-
{
|
|
110
|
+
{ recorded: false, error: e.message, code: e.code || null },
|
|
75
111
|
null,
|
|
76
112
|
2
|
|
77
113
|
)
|
|
78
114
|
);
|
|
79
115
|
} else {
|
|
80
|
-
console.log(
|
|
81
|
-
console.log(block);
|
|
116
|
+
console.log(`\n ${e.message}\n`);
|
|
82
117
|
}
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
const existing = readFileSync(sessionLog, "utf-8");
|
|
87
|
-
safeWriteFile(sessionLog, existing + block, "utf-8");
|
|
88
|
-
clearLastRunSummary(dir);
|
|
89
|
-
|
|
90
|
-
if (opts.json) {
|
|
91
|
-
console.log(
|
|
92
|
-
JSON.stringify({ recorded: true, target: sessionLog }, null, 2)
|
|
93
|
-
);
|
|
94
|
-
} else {
|
|
95
|
-
console.log("\n Recorded last CLI run to SESSION-LOG.md.\n");
|
|
96
118
|
}
|
|
97
119
|
});
|
|
98
120
|
}
|