All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog.
- npm audit fix - resolve hono, path-to-regexp CVEs
- unblock 3 plugin releases
- Bump handlebars in /plugins/plugin-test-harness
- Bump hono in /plugins/plugin-test-harness
- Bump picomatch in /plugins/plugin-test-harness
- Bump the all-dependencies group across 1 directory with 7 updates
- Bump flatted in /plugins/plugin-test-harness
- bump express-rate-limit in /plugins/plugin-test-harness
- bump @hono/node-server in /plugins/plugin-test-harness
- bump ts-jest to 29.4.9 in both plugin lock files
- update remaining L3Digital-Net references
- update org references from L3Digital-Net to L3DigitalNet
- apply audit findings — isError, CHANGELOG, README, UX
- README: fix structural issues and update docs path references
- Cleaned up writing style and documentation consistency
pth_delete_testtool (v0.6.5): remove a test by ID and clear its result history
- Updated tool count expectation to 20 (
pth_delete_testbrings the total from 19) - MCP array/number coercion and pinned test protection (v0.6.4)
- Three dogfooding bugs — bump to v0.6.3
- Four bugs from PTH dogfooding — bump to v0.6.2
pth_delete_test: Remove a test from the suite by ID. Also clears its result history from the in-sessionResultsTrackerto prevent orphaned entries from skewing pass/fail counts.
- MCP non-string parameter serialization: Claude Code's MCP client sends array and number parameters as JSON strings. Added
z.preprocess(parseJsonString, ...)tofilesinpth_get_test_impactandpth_apply_fix, andz.coerce.number()fordurationMsinpth_record_result— all now accept both native types and their string-encoded equivalents pth_generate_testsoverwrites manual test edits: addedpinned?: booleantoPthTest.pth_edit_testnow setspinned: trueautomatically;pth_generate_testsskips pinned tests and reports them as "(N pinned)" in the summary
- Plugin scanner false positive: strip single-line comments before regex scan — the
TOOL_NAME_PATTERNcomment inplugin-scanner.tsitself was matched, injectingtool_nameas a fake new component in the gap analysis pth_start_session_valid_inputwrong expectation: renamed to "rejects when session already active", flipped tosuccess: false— this is the correct behavior and a valid error-path testpth_resume_session_valid_inputwrong expectation: renamed to "rejects invalid branch format", flipped tosuccess: false—branch: maincorrectly fails the PTH session branch format guard
pth_edit_testaccepts blank testId: added.min(1)to Zod schema and a whitespace guard in dispatch — empty or whitespace-only testId now returnsisError: truepth_reload_pluginorphans MCP context when testing itself: process kill is now deferred 500ms viasetTimeoutso the success response can be sent over stdio before SIGTERM arrives- Schema-generated stubs cause ID collisions across sessions:
pth_create_testinput YAML now usespth_list_tests(a real tool) and a timestamp suffix; scenario stubs get unique IDs on eachpth_generate_testscall
- Three artifact stub tests (
test-value,generated_test,scenario_stub_for_pth_record_result) removed from persistent store — generator left-overs usingtool: example(non-existent)
${CLAUDE_PLUGIN_ROOT}ENOENT on schema discovery:fetchToolSchemasFromMcpServernow expands${CLAUDE_PLUGIN_ROOT}in.mcp.jsonargs before callingspawn(). Claude Code substitutes this variable at load time, butspawn()does not invoke a shell so the literal token caused ENOENT on the child process.- "Connection closed" when PTH runs as Claude Code MCP server: child processes spawned for schema discovery were inheriting the parent's fd 2 (a live Unix socket to Claude Code). Added
stderr: 'pipe'toStdioClientTransportand drain the pipe to prevent backpressure stalls. - Missing-required-field tests returned success instead of
isError: true: tool dispatch now validates args against each tool's Zod schema before routing. Invalid args return{ isError: true }so MCP clients can distinguish validation errors from successful tool execution without string-parsing the response text. pth_record_result_valid_inputscenario: fixed expectation and isError handling for unknown testId
- Persistent storage at
~/.pth/PLUGIN_NAME/: tests, results history, session reports, iteration history, fix history, and plugin snapshots now survive across sessions - Gap analysis at
pth_start_session: compares saved plugin snapshot vs current source files to surface new/modified/removed components without requiring a live server pth_generate_testsnow accepts optionaltools[]parameter for gap-targeted test generation (only generate tests for specific new/modified tools from gap analysis)pth_preflightreports whether a persistent store exists for the plugin- Rich end-session summary with convergence table, fixes applied, and test outcomes
resumeSessionnow loads tests from the persistent store (~/.pth/PLUGIN_NAME/tests/) instead of the worktree — persistent store is the authoritative test sourceendSessionpersists all session artifacts to~/.pth/PLUGIN_NAME/before worktree removal, and cleans the worktree's.pth/directory to prevent stale data loadingpth_end_sessionresponse now includes the persistent store path and session report location
pth_preflightstale active-session verdict: verdict now correctly reflects an active session — returns⚠ Session already activeinstead of✓ OK — ready to start a sessionwhen a live session lock is detected. Discovered via PTH self-test run.
pth_generate_testsnow auto-discovers tool schemas by spawning the target MCP server and callingtools/list— no longer requires Claude to manually passtoolSchemas. Fixes incomplete test generation when the plugin has more tools than Claude's active tool registry (e.g. 106 tools on linux-sysadmin-mcp vs. 27 previously generated).- New
fetchToolSchemasFromMcpServerfunction inshared/source-analyzer.tsusingStdioClientTransport+Clientfrom the MCP SDK
pth_apply_fix: detect whengit addsilently stages nothing (gitignored paths) and throw a clearGIT_ERRORwith the attempted paths instead of a misleadingBUILD_FAILEDfrom the subsequent commit (BUG-5)pth_apply_fix:BUILD_FAILEDfromrunOrThrowon git operations now correctly converted toGIT_ERRORincommitFilescatch block (BUG-5)pth_reload_plugin: runnpm installbefore build whennode_modulesis absent in worktree — worktrees are clean checkouts with no inherited dependencies (BUG-6)
pth_start_sessionnow rejects if an active session lock is held by a live process (BUG-1)pth_resume_sessionnow validates branch haspth/prefix before proceeding (BUG-2, BUG-3)pth_generate_testsnow upserts existing tests instead of throwing on duplicate IDs (BUG-4)
- Updated Plugin Test Harness documentation and implementation notes
- Enhanced plugin management and git integration
- Updated path variable names for consistency and clarity
- Used
${CLAUDE_PLUGIN_ROOT}in.mcp.jsonargs - Committed
dist/so MCP server works after install
revertCommitnow handlessession-state.jsonconflicts — stashes dirty state before reverting, resolvessession-state.jsonwith--ours, uses--allow-emptyfor already-neutralised commits that are net no-ops after conflict resolutionapplyFixnow usescommitFiles(stage only written files) instead ofcommitAll(git add -A), preventingsession-state.jsonfrom contaminating fix commits and causing conflicts during later revertspth_reload_pluginnow syncs new build to versioned cache viaonBuildSuccesscallback before killing the process — previously the restarted process loaded the stale binary from cachedetectBuildSystemis now called on the plugin subdirectory path within the worktree, not the worktree root — previously nopackage.jsonwas found and the build step was silently skipped- Parser now honours explicit
idfield in YAML test definitions; falls back toslugify(name)only whenidis absent or not a slug-safe string
commitFiles()ingit.tsfor staging a specific list of files (replacescommitAllin fix commits)getInstallPath()incache-sync.ts— readsinstalled_plugins.jsonto resolve the versioned cache path for a plugingetAllTools()intool-registry.ts— returns all registered tools statically; session-gating is enforced at dispatch time
- Expose all tools statically at startup — Claude Code caches the MCP tool list at session start, so dynamic activation via
notifications/tools/list_changedwas unreliable; session-gating is now enforced at dispatch time instead createBranchnow usesgit branchinstead ofgit checkout -bto avoid switching HEAD beforegit worktree add, which caused the worktree creation to fail and left the repo on the pth branch
- Improved tool output formatting and error handling
- CI workflow and marketplace entry
- Plugin manifest, MCP config, and README
- All 16 session tools wired to their implementations
- Session manager: start, resume, end, preflight
- MCP server foundation with dynamic tool registry
- Test generator from tool schemas and plugin source
- Cache sync, plugin builder, and SIGTERM-based reloader
- Fix applicator with git commit trailers and fix history tracker
- Results tracker and convergence detection
- Test YAML types, parser, and test store
- Session state persister and report generator
- Plugin detector: mode detection, build system,
.mcp.jsonparsing - Git integration: branch, worktree, commit with trailers
- Shared error types, logger, and exec utilities
- Design doc and implementation plan
- Sample fixtures:
sample-mcp-plugin,broken-mcp-plugin,sample-hook-plugin
- Version 0.1.0 — initial public release
- Correct README API signatures and YAML schema
- Python3 fallback in
write-guard.sh - Fixed diff base and skipped test count in session tool handlers
- Rolled back branch and worktree on
startSessionfailure - Fixed session manager edge cases: empty commit, lock cleanup, preflight errors
- Scoped session state to
createServerfactory and added notification error handling - Converted Zod schemas to JSON Schema for MCP wire format
- Extracted
slugifyto shared util and improved generator test coverage - Fixed cache sync error type, rsync fallback, and process termination
- Fixed fix history parser and added tracker test coverage
- Fixed oscillating detection window and added missing tracker test coverage
- Fixed parser error handling and test store duplicate guard
- Removed TOCTOU in
readMcpConfig— usereadFile+ENOENT check instead ofaccess+readFile - Added
INVALID_PLUGINerror code, fixedreadMcpConfigparse error handling, added shell/tsconfig language detection - Implemented
getLogsinceoption (was declared but silently ignored) - Fixed
commitAllregex for hyphenated branches, added GIT_ERROR wrapping, loggedremoveWorktreefailures - Narrowed
ExecResult.exitCodetonumber(always mapped by fallback) - Fixed
exec.tssignal handling, spawn error surfacing, and env merge - Resolved ESM/CJS config inconsistency and added missing
typescript-eslintdep