Skip to content

feat(cli): add timeline --format md - #182

Merged
theDakshJaitly merged 5 commits into
mex-memory:mainfrom
abhinav-phi:feat/timeline-md-format
Sep 17, 2026
Merged

theDakshJaitly merged 5 commits into
mex-memory:mainfrom
abhinav-phi:feat/timeline-md-format

Conversation

@abhinav-phi

Copy link
Copy Markdown
Contributor

Resolves #55.

What

mex timeline --format md renders the (already-filterable — --since, --type, --limit all compose) timeline as a Markdown table:

| Date | Type | Event | Files |
|---|---|---|---|
| 2026-09-09 | decision | chose the bounded resolver | `ROUTER.md` |
  • Messages are escaped (pipes → \|, line breaks → spaces) so a message cannot break the table; file paths render as inline code.
  • An empty log emits _No events found._ — valid Markdown, still readable when pasted.
  • --json takes precedence (unchanged); the default terminal output is byte-identical when --format is absent.

Tests

Three new cases in test/events.test.ts: table shape + escaping with a pipe-bearing message and a file column, empty-log placeholder, and default output unchanged. npm run typecheck green.

Renders the filtered timeline as a Markdown table (Date, Type, Event,
Files) suitable for piping into reports and standup notes. Pipes and
line breaks inside a message are escaped so it cannot break the table;
an empty log emits an italic placeholder. The default terminal output
is untouched when --format is absent.

Resolves mex-memory#55
@abhinav-phi
abhinav-phi force-pushed the feat/timeline-md-format branch from 798aca7 to 8e3fadc Compare September 12, 2026 17:17
@abhinav-phi

Copy link
Copy Markdown
Contributor Author

Rebase note: main rewrote runTimeline while this PR was open (bounded output: selected + truncated + sourceTruncated from #189/#193's work). The --format md branch was re-aimed at the new shape rather than the old filtered list:

  • it renders selected (so --limit and the 8 MiB/10k output bound apply to Markdown exactly as they do to the terminal view);
  • the two omission notes now appear in Markdown too, as italic lines mirroring the terminal's dim lines, so a pasted table never silently hides an omission;
  • the empty-table placeholder (_No events found._) and the untouched default terminal output stand as before.

All 30 events tests and the abstention golden pass locally; CI green on the rebased head (check 22.22.0/24, hub-browser, release-performance, storage-portability macos+windows). Ready for review.

@theDakshJaitly theDakshJaitly left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requesting changes for the four inline findings. The CLI currently drops the new format option, so mex timeline --format md still prints ordinary terminal output. The Markdown renderer also needs to preserve omission notices, correctly encode table cells, and enforce the output limit after rendering.

Validation: applied the exact PR diff to main in an isolated checkout; 53 existing events/public API tests, typecheck, build, and diff checks passed. Targeted probes reproduced the four issues. CLI forwarding was also checked on the PR head.

Comment thread src/cli.ts
.command("timeline")
.description("Read bounded recent project notes (latest 8 MiB / 10,000 log lines)")
.option("--json", "Output events as JSON")
.option("--format <format>", "Output format: md for a Markdown table (piped into reports)")

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] Forward the format option to the timeline handler

The action below builds a new options object for runTimeline but never includes format: opts.format. As a result, the built CLI accepts mex timeline --format md and exits successfully while still printing ordinary terminal text; the new renderer is unreachable through the advertised command. Please forward the option and add a test invoking the actual CLI, since the new tests call runTimeline directly and bypass this dispatch.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 7de394c: the CLI now forwards format. The built-CLI regression checks Markdown dispatch, default output, and JSON precedence. Child processes and the outer test are bounded in a03a4ba/f08fbd1; the exact test passes locally. Final-head CI is green: https://github.com/mex-memory/mex/actions/runs/35165138729

Comment thread src/events.ts Outdated
Comment on lines +176 to +178
if (selected.length === 0) {
console.log("_No events found._");
return;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Preserve omission notices when the selected result is empty

This early return skips both truncated and sourceTruncated notices. A matching event with a 70,000-character message is excluded by the output budget and produces only _No events found._; likewise, a query matching only an older entry outside the retained 10,000-line window hides the incomplete source scan. Please emit the applicable omission notices even when no rows are selected, and distinguish an omitted matching event from a genuinely empty result.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 7de394c. Empty selection now retains both omission notices and distinguishes budget-omitted matches from no matches. Added regressions for oversized entries and matches outside the retained history window.

Comment thread src/events.ts Outdated
Comment on lines +183 to +184
const message = e.message.replace(/\|/g, "\\|").replace(/\r?\n/g, " ");
const files = e.files.length ? e.files.map((f) => `\`${f}\``).join(", ") : "—";

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Encode messages and file paths as Markdown table cells

File paths are inserted verbatim inside single backticks, so accepted paths containing a pipe (such as src/a|b.ts), newline, or backtick break the table or code span. The message escaping also fails when a pipe already has a backslash before it, and leaves bare carriage returns intact. These cases reproduce with the renderer and a Markdown table parser. Please use table-aware encoding for both messages and paths, handling backslashes, CR/LF, and code-span delimiters, and test the rendered cell contents.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 7de394c. Messages and paths handle pipes, backslashes, CR/LF, and backtick runs. Regression tests parse the output with GFM and verify four cells and round-tripped content.

Comment thread src/events.ts Outdated
for (const e of selected) {
const message = e.message.replace(/\|/g, "\\|").replace(/\r?\n/g, " ");
const files = e.files.length ? e.files.map((f) => `\`${f}\``).join(", ") : "—";
console.log(`| ${e.timestamp.slice(0, 10)} | ${e.kind} | ${message} | ${files} |`);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Apply the byte limit to the rendered Markdown

The shared selection budget measures JSON serialization, but Markdown escaping can make the emitted rows substantially larger. A single accepted message containing 40,000 pipe characters produces 80,081 UTF-8 bytes here, exceeding the 65,536-byte output limit. Please budget the actual escaped rows together with the table header and omission notices before emitting them, and report when a complete row cannot fit.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 7de394c. Markdown rows are budgeted after escaping, including UTF-8 bytes, headers, newlines, and notices; oversized rows are omitted whole. All 48 events tests pass, including the byte-boundary cases. Final-head CI is green; @theDakshJaitly could you re-review?

@abhinav-phi

Copy link
Copy Markdown
Contributor Author

hi all four review points are fixed and pushed

the cli forwards the format option so timeline with format md actually renders markdown

empty selections keep both omission notices and budget omitted results are separate from no matches

messages and file paths are encoded as proper table cells handling pipes backslashes newlines and backtick runs

the byte limit applies to the rendered markdown and oversized rows are dropped whole

the events suite passes fully and final head ci is green

could you re review when you get time

@theDakshJaitly theDakshJaitly left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-reviewed the updated commits against all four requested changes. CLI format forwarding, omission notices for empty selections, GFM cell encoding, and the rendered 64 KiB output bound are now fixed. No remaining findings.

Verified the complete PR patch on current main: 91 focused tests passed, including the original review probes, the built-CLI output regression, public API coverage, and CLI smoke tests. Build, workspace typecheck, and diff checks passed; default and JSON output remain unchanged. CI is green on this head.

@theDakshJaitly
theDakshJaitly merged commit a33f28a into mex-memory:main Sep 17, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add mex timeline --format md

2 participants