All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- Trailing
.in query crashed the tracer: A query like"appendo([1,2], [3,4], X)."was inlined verbatim into the generated wrapper as(appendo(…)., export_trace_json(…)), where the period inside the parens produced aSyntax error: Operand expected, unquoted comma or bar foundandrun_trace/0never got defined. The wrapper generator now strips a single trailing.from the query before inlining it. - Relative
consult/1paths broke:swiplwas being spawned withcwdset to the wrapper's temp dir, so any:- consult('../foo').in the user's file resolved against/var/folders/…instead of the source file's directory.ptvnow runsswiplwithcwdset to the source file's directory; the trace JSON output is written via an absolute path so it still lands in the temp dir regardless of cwd.
- Update check runs before the command, not after: The automatic update nudge now runs before ptv starts the trace, so the user can update first rather than waiting on a stale-version run.
- Seamless re-run after update: If the user accepts the update, ptv installs the new version and then re-execs itself with the same arguments (stdio inherited), so the original command runs transparently on the freshly installed binary. A guard env var prevents the re-run from triggering another check.
- Throttle temporarily disabled: The once-per-day cache is commented out in this release so every run exercises the npm registry check. It will be re-enabled in a follow-up.
- Automatic update check: After a normal run, ptv checks the npm registry for a newer release (throttled to at most once per day, with a cached result in between) and, if one exists, nudges the user with a
Y/nprompt to install it globally. Installation progress is shown with an animated terminal spinner. The check is silent and non-fatal on any error, is skipped when not running interactively (non-TTY), and can be disabled with--quiet.
- Backtracking misattribution:
REDOevents were dropped during parsing, so a goal that failed one clause and backtracked to another kept the failed attempt's subgoal steps. Those steps were then mislabeled against the surviving clause's subgoals (e.g. a failed10 < 6comparison rendered under the wrong goal, and recursive calls split into phantom sibling steps).REDOevents are now processed and the failed clause attempt is discarded from both the execution timeline and the call tree. - Internal variable mislabeling: When a clause argument was instantiated to a constant, positional variable-name alignment shifted and mapped the wrong name onto trailing internal variables — e.g.
gcd(X, Y1, D)rendered asgcd(10, Y1, Y1)instead ofgcd(10, Y1, D). Variable mapping is now structural (functor / argument / operator alignment). - Builtin goal results:
is/2steps now show the bound left-hand-side variable (e.g.Y1 = 6) instead of? = 6 is 16-10; comparison goals (<,>=, …) no longer emit a meaningless result line. - Call tree builtin goals:
is/2nodes display the resolved goal (e.g.6 is 16-10) instead of an unresolved internal variable (_3154 is 16-10).
- Internal variable leakage: Operator expressions (
is/2,>/2) in step headers and subgoal listings leaked raw Prolog internal variable names (e.g.,_778 is 2+1) instead of using clause variable names. Now uses parent's subgoal template for consistent display. - Debug mode variable consistency: In
--debugmode, step headers now use the same internal variable names as their parent's subgoal listing, with additiveV(_NNN)notation (e.g.,R(_2482) is 4 * 6). Previously showed mismatched internal vars from different frames. - Goal display comma spacing: Added space after comma in goal arguments (e.g.,
factorial(4, R)instead offactorial(4,R))
- Wrapper line offset bug: Source files with leading blank lines caused clause line numbers to be mapped incorrectly, resulting in wrong clause matching in the timeline (e.g., recursive clauses displayed as base case facts with wrong variable names and no unifications)
--treeflag: Call tree diagram (Mermaid) is now opt-in via--treeflag, reducing default output size- Regression tests for subgoalTemplate variable priority fix
- Timeline variable display bug: Child steps now correctly use the caller's variable name (from subgoalTemplate) instead of the matched clause's pattern. For example, when parent's subgoal is
t(X+1, X1)and it matches factt(X+0+1, X+1+0), the step now showst(1+0+1, X1)instead of incorrectly showingt(1+0+1, X+1+0)
- Call tree diagram is no longer included by default - use
--treeto include it - Updated
regenerate_examples.shto use--treeflag
- BREAKING: Removed
--show-internal-varsbackwards compatibility flag (use--debug:internal-varsinstead)
- Debug flag system: New
--debugand--debug:<flag>CLI options for extensible debugging features - Additive internal variable display: With
--debug:internal-vars, shows both clause variable names AND internal Prolog names (e.g.,Z (_2008) = value) instead of replacing one with the other - CLI integration tests: Comprehensive test suite covering flag parsing, output format, and error handling (19 new tests)
- Support for
--debug:*and--debug:allto enable all debug flags - Backwards compatibility:
--show-internal-varsstill works (maps to--debug:internal-vars)
- Renamed
--show-internal-varsto--debug:internal-vars(old flag still works) - Debug mode now shows internal vars additively rather than replacing clean names
- Updated help screen with debug flag documentation
- Updated README with operators example showing recursive tracing
- Complete internal variable cleanup: removed remaining internal Prolog variable names (_2008) from unifications section, subgoals display, and call tree results
- Result lines for facts with pattern outputs now show full pattern (e.g.,
X+1+0 = 1+1+0) instead of ellipsis (X+... = 1+1+0) - Removed unused function parameters causing TypeScript warnings
- New test suite for tree-formatter with pattern output display tests
- Additional timeline-formatter tests for pattern output display
- Clean Variable Display: Timeline and call tree now use clause variable names (X, Z, X1) instead of Prolog's internal names (_2008) by default, making traces much easier to follow
- --show-internal-vars flag: New CLI option to display Prolog's internal variable names for debugging purposes
- Result lines now show
=> Z = 1+1+1+1+0instead of=> _2008 = 1+1+1+1+0 - Call tree nodes show
Result: Z=valueinstead ofEXIT: _2008=value
- Subgoal Binding Context: When a subgoal uses a variable bound by a previous sibling step, the timeline now shows the template → instantiated form with a "where X = value (from Step N)" annotation, making the data flow between sibling subgoals explicit
- Nested Timeline Structure: Child calls are now visually nested inside their parent steps, showing the call stack hierarchy clearly
- New
flattenTimeline()utility function for backward compatibility and testing - New test suite for nested timeline structure validation
- Timeline Visualisation Redesign: Replaced flat sequential timeline with hierarchical nested format
- Results now appear AFTER child steps complete, matching actual Prolog execution order
- Query variable state (
A = ...) now only displays on root-level steps, preventing premature display - Simplified timeline builder architecture - single-pass tree construction instead of multi-pass flat array processing
- Reduced timeline.ts from ~1000 lines to ~400 lines through architectural cleanup
- Fixed premature query variable display where
A = resultappeared before subgoals were shown - Fixed confusing timeline where results appeared before the computation that produced them
- Fixed Mermaid diagram step numbers not matching timeline step numbers (tree builder now uses flattened timeline for mapping)
TimelineStepinterface now includeschildren: TimelineStep[]for nested structure- Timeline builder uses active call stack to track parent-child relationships
- Clause info backfilled from EXIT events when CALL events lack it
- Depth-first renumbering ensures consistent step numbers in nested output
- Tree builder receives flattened timeline for correct step number mapping
- Fixed timeline merging bug where steps appeared out of chronological order for recursive predicates with multiple calls at the same recursion level
- Synchronized call tree diagram step numbers with timeline steps - diagram now uses same step numbers (①②③) as timeline (1, 2, 3)
- Renumbered timeline steps to be continuous (1, 2, 3, ...) after merging CALL/EXIT pairs
- Added instantiated subgoal display showing variable substitutions (e.g.,
t(X+1, X1) → t(1+0+1+1, X1))
- Comprehensive unit tests for timeline merging with recursive predicates
- Test coverage for multiple calls at same recursion level (the bug scenario)
- Timeline builder now passes merged timeline to tree builder for correct step number mapping
- Regenerated build-info.ts with correct version (was showing 2.0.0 instead of 2.1.0)
- Build now correctly reports v2.1.1 in --copyright flag
- Timeline Redesign: Merged CALL/EXIT pairs into single steps, reducing timeline verbosity by ~50%
- Query Variable Tracking: Shows how query variables evolve through recursive execution (Russian doll pattern)
- Variable Binding Tracker: Event-driven tracker that processes trace events in chronological order
- Variable name extraction from queries (no longer hardcodes "X")
- List simplification for nested structures:
[1|[2|[3,4]]]→[1,2,3,4]
- Timeline steps now show: goal, clause, unifications, subgoals, and result in merged format
- Event processing order changed to chronological to capture intermediate states
- Subgoal tracking updated to work with merged timeline format
- New
VariableBindingTrackerclass for tracking bindings through parent_info - Timeline builder processes events in original order (CALL1, CALL2, CALL3, EXIT3, EXIT2, EXIT1)
- Added
specs/timeline-redesign.mddocumenting the implementation
- Variable Flow Tracking: Shows how variables bind and flow across execution steps
- Variable binding notes at EXIT steps (e.g., "R from Step 11 is now bound to 1")
- Parent frame information capture in tracer
- Enhanced timeline visualization with variable flow context
- BREAKING: Simplified output format - removed multiple detail levels (minimal, standard, detailed, full)
- BREAKING: Now generates single unified output with timeline and tree views
- Tracer now captures parent_info for better execution context
- Timeline builder includes variable flow analysis pass
- Updated all example outputs with new format
- Added
parent_infofield to trace events - Implemented
addVariableFlowNotes()method in timeline builder - Added
variableFlowNotesfield to TimelineStep interface - Enhanced timeline formatter to display variable flow information
- All 54 tests passing with new architecture
- Added gap-analysis.md documenting feature requirements
- Added variable-flow-implementation-plan.md with implementation details
- Updated README with new output format examples
- Fixed clause numbering inconsistency between tracer and display output
- Clause numbers now correctly map from wrapper file line numbers to source file line numbers
- Match boxes, node labels, and edge labels now show consistent clause numbering
- Resolves issue where tracer reported wrapper lines (e.g., 8,9,10) vs source lines (e.g., 26,27,28)
- Added
prologContentparameter toparseTraceJsonfunction for line number mapping - Enhanced
parseEventsfunction to usemapWrapperLineToSourcefor accurate clause mapping - Improved structural clause matching to work with exact tracer clause information
- Fixed Markdown auto-numbering issue in "Clauses Defined" section
- Clause numbers now display as "Line X:" format to prevent Markdown renderers from renumbering them
- Maintains original source file line numbers in documentation output
- Fixed missing clause matching visualisation for simple facts in detailed and full modes
- Fixed identical output between detailed and full detail levels - full now shows additional clause type information
- Improved match node creation for direct fact matches (e.g.,
t(0+1, A))
- Comprehensive test coverage for simple fact matching scenarios
- Enhanced unification display in match nodes for simple facts
- Additional clause type information in full detail mode
- Correct copyright year from 2024 to 2025
- Remove extra newline at start of copyright notice
- Correct author email address in package.json and copyright notice
- Copyright and version information display
- Build timestamp and git commit hash tracking
- Comprehensive changelog documentation
- Initial release of Prolog Trace Visualiser (ptv)
- Generate Mermaid diagrams from SWI-Prolog trace execution
- Four detail levels: minimal, standard, detailed, full
- Support for recursive predicate visualisation with match nodes
- Clause alignment between tracer output and visualisation
- Comprehensive test coverage (180+ tests)
- Global npm package installation support
- Built-in tracer integration with SWI-Prolog
- Query Visualisation: Transform Prolog execution traces into clear Mermaid flowcharts
- Detail Levels:
minimal: Basic execution flowstandard: Includes recursion indicatorsdetailed: Adds match nodes showing clause selectionfull: Complete trace with all backtracking paths
- Match Nodes: Show exactly which clauses are being matched during execution
- Recursion Detection: Automatic identification and highlighting of recursive calls
- Clause Alignment: Perfect synchronisation between trace events and clause references
- Built-in Filtering: Removes infrastructure predicates (catch/3, format/2) from output
- TypeScript implementation with comprehensive type safety
- Property-based testing with fast-check
- Integration tests for end-to-end functionality
- Robust error handling and parser warnings
- Cross-platform compatibility (macOS, Linux, Windows)
npm install -g prolog-trace-viz
ptv your-program.pl "your_query(X)"
- Factorial computation with recursion visualisation
- List membership with backtracking
- Append operations with unification details
- Arithmetic expression evaluation
This initial release establishes ptv as a comprehensive tool for visualising Prolog execution traces. The core architecture supports extensible detail levels and maintains perfect alignment between SWI-Prolog's internal clause numbering and the generated visualisations.
Key architectural decisions:
- Extract clause definitions directly from trace events rather than parsing source files
- Use predicate-based matching with heuristics for base vs recursive case detection
- Implement comprehensive filtering to hide infrastructure predicates
- Provide four distinct detail levels for different use cases
The tool has been tested extensively with property-based testing and includes comprehensive integration tests to ensure reliability across different Prolog programs and query patterns.