fix: 6 bugs fixed, 67 tests added for session-manager and session-aliases

Bug fixes:
- utils.js: prevent duplicate 'g' flag in countInFile regex construction
- validate-agents.js: handle CRLF line endings in frontmatter parsing
- validate-hooks.js: handle \t and \\ escape sequences in inline JS validation
- session-aliases.js: prevent NaN in date sort when timestamps are missing
- session-aliases.js: persist rollback on rename failure instead of silent loss
- session-manager.js: require absolute paths in getSessionStats to prevent
  content strings ending with .tmp from being treated as file paths

New tests (164 total, up from 97):
- session-manager.test.js: 27 tests covering parseSessionFilename,
  parseSessionMetadata, getSessionStats, CRUD operations, getSessionSize,
  getSessionTitle, edge cases (null input, non-existent files, directories)
- session-aliases.test.js: 40 tests covering loadAliases (corrupted JSON,
  invalid structure), setAlias (validation, reserved names), resolveAlias,
  listAliases (sort, search, limit), deleteAlias, renameAlias, updateAliasTitle,
  resolveSessionAlias, getAliasesForSession, cleanupAliases, atomic write

Also includes hook-generated improvements:
- utils.d.ts: document that readStdinJson never rejects
- session-aliases.d.ts: fix updateAliasTitle type to accept null
- package-manager.js: add try-catch to setProjectPackageManager writeFile
This commit is contained in:
Affaan Mustafa
2026-02-12 15:50:04 -08:00
parent ff9a91319f
commit 76b271ab6b
11 changed files with 790 additions and 17 deletions

View File

@@ -17,7 +17,7 @@ function extractFrontmatter(content) {
if (!match) return null;
const frontmatter = {};
const lines = match[1].split('\n');
const lines = match[1].split(/\r?\n/);
for (const line of lines) {
const colonIdx = line.indexOf(':');
if (colonIdx > 0) {

View File

@@ -74,7 +74,7 @@ function validateHooks() {
const nodeEMatch = hook.command.match(/^node -e "(.*)"$/s);
if (nodeEMatch) {
try {
new vm.Script(nodeEMatch[1].replace(/\\"/g, '"').replace(/\\n/g, '\n'));
new vm.Script(nodeEMatch[1].replace(/\\"/g, '"').replace(/\\n/g, '\n').replace(/\\t/g, '\t').replace(/\\\\/g, '\\'));
} catch (syntaxErr) {
console.error(`ERROR: ${eventType}[${i}].hooks[${j}] has invalid inline JS: ${syntaxErr.message}`);
hasErrors = true;
@@ -113,7 +113,7 @@ function validateHooks() {
const nodeEMatch = h.command.match(/^node -e "(.*)"$/s);
if (nodeEMatch) {
try {
new vm.Script(nodeEMatch[1].replace(/\\"/g, '"').replace(/\\n/g, '\n'));
new vm.Script(nodeEMatch[1].replace(/\\"/g, '"').replace(/\\n/g, '\n').replace(/\\t/g, '\t').replace(/\\\\/g, '\\'));
} catch (syntaxErr) {
console.error(`ERROR: Hook ${i}.hooks[${j}] has invalid inline JS: ${syntaxErr.message}`);
hasErrors = true;