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

@@ -252,7 +252,7 @@ function listAliases(options = {}) {
}));
// Sort by updated time (newest first)
aliases.sort((a, b) => new Date(b.updatedAt || b.createdAt) - new Date(a.updatedAt || a.createdAt));
aliases.sort((a, b) => (new Date(b.updatedAt || b.createdAt || 0).getTime() || 0) - (new Date(a.updatedAt || a.createdAt || 0).getTime() || 0));
// Apply search filter
if (search) {
@@ -337,7 +337,9 @@ function renameAlias(oldAlias, newAlias) {
// Restore old alias and remove new alias on failure
data.aliases[oldAlias] = aliasData;
delete data.aliases[newAlias];
return { success: false, error: 'Failed to rename alias' };
// Attempt to persist the rollback
saveAliases(data);
return { success: false, error: 'Failed to save renamed alias — rolled back to original' };
}
/**
@@ -359,17 +361,21 @@ function resolveSessionAlias(aliasOrId) {
/**
* Update alias title
* @param {string} alias - Alias name
* @param {string} title - New title
* @param {string|null} title - New title (string or null to clear)
* @returns {object} Result with success status
*/
function updateAliasTitle(alias, title) {
if (title !== null && typeof title !== 'string') {
return { success: false, error: 'Title must be a string or null' };
}
const data = loadAliases();
if (!data.aliases[alias]) {
return { success: false, error: `Alias '${alias}' not found` };
}
data.aliases[alias].title = title;
data.aliases[alias].title = title || null;
data.aliases[alias].updatedAt = new Date().toISOString();
if (saveAliases(data)) {