Round 125: Tests for readFile returning garbled strings (not null) on binary
files, output() handling undefined/NaN/Infinity as non-objects logged directly
(and JSON.stringify converting NaN/Infinity to null in objects), and loadAliases
with __proto__ key in JSON proving no prototype pollution occurs.
Total: 935 tests, all passing.
Round 124: Tests for findFiles matching dotfiles (unlike shell glob where *
excludes hidden files), getAllSessions strict date equality filter (wrong format
silently returns empty), and parseSessionMetadata title regex edge cases
(no space after #, ## heading, multiple H1, greedy \s+ crossing newlines).
Total: 932 tests, all passing.
Round 123: Tests for countInFile non-overlapping regex match behavior (aaa with
/aa/g returns 1 not 2), replaceInFile with $& and $$ substitution tokens in
replacement strings, and parseSessionMetadata CRLF section boundary bleed where
\n\n fails to match \r\n\r\n. Total: 929 tests, all passing.
Round 122: Tests for findFiles glob dot escaping (*.txt must not match filetxt),
listAliases limit=0/negative/NaN returning all due to JS falsy check, and
getSessionById matching old YYYY-MM-DD-session.tmp filenames via noIdMatch path.
Total: 926 tests, all passing.
- parseSessionFilename rejects Feb 29 in century non-leap years (1900, 2100) but accepts 2000/2400
- replaceInFile with /(?:)/g zero-width regex inserts at every position boundary
- parseSessionMetadata preserves raw markdown formatting (**bold**, `code`, _italic_) in titles
Total: 899 tests
Round 110: Tests for findFiles with unreadable root directory returning
empty array (vs Round 71 which tested subdirectory), parseSessionFilename
year 0000 exposing JS Date 0-99→1900-1999 mapping quirk, and uppercase
session ID rejection by [a-z0-9]{8,} regex. 890 tests total.
Round 109:
- appendFile creating new file in non-existent directory (ensureDir + appendFileSync)
- getExecCommand with ../ path traversal in binary (SAFE_NAME_REGEX allows ../)
- getAllSessions skips .tmp files that don't match session filename format
- grepFile with ^$ pattern verifies empty line matching including trailing newline phantom
- replaceInFile with self-reintroducing replacement confirms single-pass behavior
- setAlias with whitespace-only title exposes missing trim validation vs sessionPath
- countInFile with named capture groups verifies match(g) ignores group details
- grepFile with multiline (m) flag confirms flag is preserved unlike stripped g
- getAllSessions with array/object limit tests Number() coercion edge cases
- parseSessionMetadata: blank line within Completed section truncates items
due to regex lookahead (?=###|\n\n|$) stopping at \n\n boundary
- grepFile: sticky (y) flag not stripped like g flag, causing stateful
.test() behavior that misses matching lines
- getExecCommand: object args bypass SAFE_ARGS_REGEX (typeof !== 'string')
but coerce to "[object Object]" in command string
- findFiles with both maxAge AND recursive combined (option interaction test)
- parseSessionMetadata truncates item text at embedded ### due to lazy regex
- cleanupAliases callback returning 0 (falsy non-boolean) removes alias via !0 coercion
Total tests: 860
- replaceInFile returns true even when pattern doesn't match (silent rewrite)
- grepFile treats CR-only (\r) file as single line (splits on \n only)
- writeSessionContent(null) returns false (TypeError caught by try/catch)
- getSessionById(null) throws TypeError at line 297 (null.length)
- parseSessionFilename(null) throws TypeError at line 30 (null.match())
- findFiles with maxAge: -1 deterministically excludes all files
- getSessionStats: drive letter without slash (Z:nosession.tmp) treated as content
- countInFile: case-insensitive regex with g flag auto-appended (/foo/i → /foo/ig)
- countInFile: case-insensitive regex with g flag preserved (/foo/gi stays /foo/gi)
- Test countInFile returns 0 for object pattern type (non-string non-RegExp)
- Test getSessionStats treats Windows UNC path as content (not file path)
- Test detectFromPackageJson returns null for empty string packageManager field
Total tests: 836
- replaceInFile with empty replacement string verifies text deletion works
- parseSessionMetadata asserts date/started/lastUpdated are null when fields absent
- countInFile with valid file but non-matching pattern returns 0
Total: 824 tests
- utils.test.js: replaceInFile returns false on read-only file (catch block)
- session-manager.test.js: getAllSessions returns empty when sessions dir missing
- package-manager.test.js: getPackageManager falls through corrupted global config to npm default
788 tests total, all passing.
Cover createdTime/birthtime fallback in session-manager, readStdinJson
error event settled-flag guard in utils, renameAlias rollback on naming
conflict in session-aliases, and saveAliases backup preservation on
serialization failure. Total: 713 tests.
When --global or --project was followed by another flag (e.g., --global --project),
the flag was treated as a package manager name. Added pmName.startsWith('-') check
to both handlers. Added 20 tests across 4 test files covering argument validation,
ensureDir error propagation, runCommand stderr handling, and saveAliases failure paths.
Fix grepFile() silently skipping matches when called with /g flag regex.
The global flag makes .test() stateful, causing alternating match/miss
on consecutive matching lines. Strip g flag since per-line testing
doesn't need global state.
Add first-ever tests for evaluate-session.js (5 tests: short session,
long session, missing transcript, malformed stdin, env var fallback)
and suggest-compact.js (5 tests: counter increment, threshold trigger,
periodic suggestions, below-threshold silence, invalid threshold).
Windows cmd.exe treats single quotes literally, so `echo '...' | node -e '...'`
fails. Switched to execFileSync with the `input` option to pipe stdin data
directly without shell quoting issues.
- New skills: api-design, database-migrations, deployment-patterns
- validate-hooks.js: validate inline JS syntax in node -e hook commands
- utils.test.js: edge case tests for findFiles with null/undefined inputs
- README: update skill count to 35, add new skills to directory tree
- Fix 16 ESLint no-unused-vars errors across hook scripts and tests
- Add eslint-disable comment for intentional control-regex in ANSI stripper
- Update session file test to use getSessionIdShort() instead of hardcoded 'default'
(reflects PR #110's project-name fallback behavior)
- Add marketing/ to .gitignore (local drafts)
- Add skill-create-output.js (terminal output formatter)
All 69 tests now pass. CI should be green.