Skip to content

Commit 5161759

Browse files
committed
fix: Improve comments list + rate limit cleanup (pb: MB-be6, MB-559)
- Extract comments array from post fallback payloads when /comments is 405 - Prune expired rate limit entries and drop empty profiles - Record pebble closures
1 parent d408414 commit 5161759

File tree

3 files changed

+111
-12
lines changed

3 files changed

+111
-12
lines changed

.pebbles/events.jsonl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,3 +173,12 @@
173173
{"type":"status_update","timestamp":"2026-01-30T18:56:48.354826Z","issue_id":"MB-c3e","payload":{"status":"in_progress"}}
174174
{"type":"comment","timestamp":"2026-01-30T18:57:17.666435Z","issue_id":"MB-c3e","payload":{"body":"COMPLETE: Split src/mb.ts into command modules under src/commands and shared CLI context in src/cli/context.ts. Behavior preserved; entrypoint now registers modules."}}
175175
{"type":"close","timestamp":"2026-01-30T18:57:24.349095Z","issue_id":"MB-c3e","payload":{}}
176+
{"type":"comment","timestamp":"2026-01-30T19:21:37.87883Z","issue_id":"MB-7b8","payload":{"body":"# mb-cli Test Protocol Results\n\n**Date:** 2026-01-30 11:19 PST \n**Tester:** Tom Servo (subagent) \n**Platform:** macOS 15.2.0 (Darwin 25.2.0, arm64) \n**Runtime:** Bun 1.3.5 \n**Profile:** tom (production) \n**Repository:** `/Users/rabsef-bicrym/Development/martian-engineering/projects/mb-cli/`\n\n---\n\n## Executive Summary\n\n**Total Tests Run:** 39/42 planned \n**Passed:** 39 \n**Failed:** 0 \n**Skipped:** 3 (T01-T03, T06, T33 - by design) \n\nAll functional tests passed. The CLI demonstrates correct behavior across authentication, read operations, dry-run outbound operations, profile management, secrets handling, safety checks, DM operations, JSON output, and artifact persistence.\n\n---\n\n## Test Results\n\n### Preflight\n\n**T00: Help Command** \n- **Status:** ✅ PASS \n- **Command:** `bun src/mb.ts --help` \n- **Expected:** Usage output with commands listed \n- **Actual:** Full help text returned with all commands (register, whoami, feed, posts, comments, vote, submolts, search, follow, profile, dm, secrets, safety, auth, version) \n- **Notes:** None\n\n---\n\n### Auth/Whoami\n\n**T04: Whoami** \n- **Status:** ✅ PASS \n- **Command:** `bun src/mb.ts whoami --profile tom` \n- **Expected:** Profile JSON, no api_key leakage \n- **Actual:** Returned profile for TomServo (26b59d91-ab0a-45eb-a9b3-a38b39832585), no api_key exposed \n- **Notes:** Correct agent metadata, owner info (SafePen), stats (3 posts, 9 comments, 3 subscriptions)\n\n**T05: Auth Status** \n- **Status:** ✅ PASS \n- **Command:** `bun src/mb.ts auth status --profile tom` \n- **Expected:** key_source shown, no api_key in output \n- **Actual:** Displayed \"API key: file\", no api_key value leaked \n- **Notes:** Correctly shows key source without exposing credentials\n\n---\n\n### Feed/Posts/Comments (Read-Only)\n\n**T07: Feed** \n- **Status:** ✅ PASS \n- **Command:** `bun src/mb.ts feed --profile tom` \n- **Expected:** Feed output, no crash \n- **Actual:** Returned feed with posts, safety warnings displayed (Unicode sanitization, prompt-injection detection) \n- **Notes:** Safety scanning working correctly, large payload handling noted\n\n**T08: Posts List** \n- **Status:** ✅ PASS \n- **Command:** `bun src/mb.ts posts list --profile tom` \n- **Expected:** List of posts \n- **Actual:** Returned recent posts with metadata, safety warnings for Unicode/prompt-injection \n- **Notes:** Consistent with T07 behavior\n\n**T09: Posts List --mine** \n- **Status:** ✅ PASS \n- **Command:** `bun src/mb.ts posts list --profile tom --mine` \n- **Expected:** Tom's recent posts \n- **Actual:** Returned agent profile with 2 recent posts (mb-cli launch post, Saudi advocacy post) \n- **Notes:** Fallback to profile endpoint with recentPosts field\n\n**T10: Posts Show** \n- **Status:** ✅ PASS \n- **Command:** `bun src/mb.ts posts show ad47a90e-0b9e-49b9-9ddb-c256b5f07850 --profile tom` \n- **Expected:** Post details \n- **Actual:** Full post data including 4 comments (AI-Noon, KaiCMO, TomServo reply, hyperstitions) \n- **Notes:** Comments included in response, first comment ID: 1e17ab00-b2b5-4379-83cd-00402dc769f4\n\n**T11: Comments List** \n- **Status:** ✅ PASS \n- **Command:** `bun src/mb.ts comments list ad47a90e-0b9e-49b9-9ddb-c256b5f07850 --profile tom` \n- **Expected:** Comments (or fallback) \n- **Actual:** Note displayed: \"comments endpoint unavailable; showing post with comments instead\" - returned post with full comments array \n- **Notes:** Graceful fallback behavior working as designed\n\n---\n\n### Outbound (Dry-Run)\n\n**T12: Posts Create** \n- **Status:** ✅ PASS \n- **Command:** `bun src/mb.ts posts create --submolt general --title \"Test\" --content \"Hello\" --profile tom --dry-run` \n- **Expected:** Dry run confirmation \n- **Actual:** `{\"dry_run\":true,\"method\":\"POST\",\"url\":\"https://www.moltbook.com/api/v1/posts\",\"body\":{...}}` \n- **Notes:** Request body correctly structured\n\n**T13: Comments Add** \n- **Status:** ✅ PASS \n- **Command:** `bun src/mb.ts comments add ad47a90e-0b9e-49b9-9ddb-c256b5f07850 --content \"Test comment\" --profile tom --dry-run` \n- **Expected:** Dry run confirmation \n- **Actual:** `{\"dry_run\":true,\"method\":\"POST\",\"url\":\".../posts/.../comments\",\"body\":{\"content\":\"Test comment\"}}` \n- **Notes:** Correct endpoint and payload\n\n**T14: Comments Reply** \n- **Status:** ✅ PASS \n- **Command:** `bun src/mb.ts comments reply ad47a90e-0b9e-49b9-9ddb-c256b5f07850 --parent 1e17ab00-b2b5-4379-83cd-00402dc769f4 --content \"Test reply\" --profile tom --dry-run` \n- **Expected:** Dry run confirmation \n- **Actual:** `{\"dry_run\":true,\"method\":\"POST\",...,\"body\":{\"content\":\"Test reply\",\"parent_id\":\"1e17ab00-...\"}}` \n- **Notes:** parent_id correctly included in body\n\n**T15: Vote Up** \n- **Status:** ✅ PASS \n- **Command:** `bun src/mb.ts vote up ad47a90e-0b9e-49b9-9ddb-c256b5f07850 --profile tom --dry-run` \n- **Expected:** Dry run confirmation \n- **Actual:** `{\"dry_run\":true,\"method\":\"POST\",\"url\":\".../posts/.../upvote\",\"body\":null}` \n- **Notes:** Correct upvote endpoint\n\n**T16: Vote Down** \n- **Status:** ✅ PASS \n- **Command:** `bun src/mb.ts vote down ad47a90e-0b9e-49b9-9ddb-c256b5f07850 --profile tom --dry-run` \n- **Expected:** Dry run confirmation \n- **Actual:** `{\"dry_run\":true,\"method\":\"POST\",\"url\":\".../posts/.../downvote\",\"body\":null}` \n- **Notes:** Correct downvote endpoint\n\n**T17: Follow Add** \n- **Status:** ✅ PASS \n- **Command:** `bun src/mb.ts follow add Pumpkin --profile tom --dry-run` \n- **Expected:** Dry run confirmation \n- **Actual:** `{\"dry_run\":true,\"method\":\"POST\",\"url\":\".../agents/Pumpkin/follow\",\"body\":null}` \n- **Notes:** Agent name routing working\n\n**T18: Follow Remove** \n- **Status:** ✅ PASS \n- **Command:** `bun src/mb.ts follow remove Pumpkin --profile tom --dry-run` \n- **Expected:** Dry run confirmation \n- **Actual:** `{\"dry_run\":true,\"method\":\"DELETE\",\"url\":\".../agents/Pumpkin/follow\",\"body\":null}` \n- **Notes:** DELETE method for unfollow\n\n---\n\n### Submolts\n\n**T19: Submolts List** \n- **Status:** ✅ PASS \n- **Command:** `bun src/mb.ts submolts list --profile tom` \n- **Expected:** List of submolts \n- **Actual:** Returned submolts (blesstheirhearts, todayilearned, general, etc.) with metadata, safety warnings \n- **Notes:** Unicode sanitization warnings expected\n\n**T20: Submolts Show** \n- **Status:** ✅ PASS \n- **Command:** `bun src/mb.ts submolts show general --profile tom` \n- **Expected:** Submolt details \n- **Actual:** Full submolt info (id, name, display_name, subscriber_count: 2849) plus recent posts \n- **Notes:** Safety warnings for large payload, prompt-injection detection active\n\n**T21: Submolts Create** \n- **Status:** ✅ PASS \n- **Command:** `bun src/mb.ts submolts create --name test-foo --display-name \"Test Foo\" --description \"Test\" --profile tom --dry-run` \n- **Expected:** Dry run confirmation \n- **Actual:** `{\"dry_run\":true,\"method\":\"POST\",\"url\":\".../submolts\",\"body\":{...}}` \n- **Notes:** Body correctly structured with name, display_name, description\n\n---\n\n### Search\n\n**T22: Search** \n- **Status:** ✅ PASS \n- **Command:** `bun src/mb.ts search \"clawdbot\" --profile tom` \n- **Expected:** Search results \n- **Actual:** Returned results with similarity scores (0.73, 0.68), post/comment type distinction \n- **Notes:** Safety warnings for Unicode/qmd scan, semantic search working\n\n---\n\n### Profile\n\n**T23: Profile Me** \n- **Status:** ✅ PASS \n- **Command:** `bun src/mb.ts profile me --profile tom` \n- **Expected:** Current profile \n- **Actual:** TomServo profile with full metadata, owner info, stats \n- **Notes:** Same data as whoami but different endpoint\n\n**T24: Profile Show** \n- **Status:** ✅ PASS \n- **Command:** `bun src/mb.ts profile show Pumpkin --profile tom` \n- **Expected:** Pumpkin's profile \n- **Actual:** Full profile (61c80e27-..., karma: 33, owner: mVara) with recent posts about memory systems \n- **Notes:** Cross-agent profile lookup working\n\n**T25: Profile Update** \n- **Status:** ✅ PASS \n- **Command:** `bun src/mb.ts profile update --description \"Test update\" --profile tom --dry-run` \n- **Expected:** Dry run confirmation \n- **Actual:** `{\"dry_run\":true,\"method\":\"PATCH\",\"url\":\".../agents/me\",\"body\":{\"description\":\"Test update\"}}` \n- **Notes:** PATCH method for profile updates\n\n**T26: Profile Avatar Set** \n- **Status:** ✅ PASS \n- **Command:** `bun src/mb.ts profile avatar set /tmp/test.png --profile tom --dry-run` \n- **Expected:** Dry run confirmation \n- **Actual:** `{\"dry_run\":true,\"method\":\"POST\",\"url\":\".../agents/me/avatar\",\"file\":\"/tmp/test.png\",\"fields\":{}}` \n- **Notes:** Created 70-byte test PNG, multipart upload structure correct\n\n**T27: Profile Avatar Remove** \n- **Status:** ✅ PASS \n- **Command:** `bun src/mb.ts profile avatar remove --profile tom --dry-run` \n- **Expected:** Dry run confirmation \n- **Actual:** `{\"dry_run\":true,\"method\":\"DELETE\",\"url\":\".../agents/me/avatar\",\"body\":null}` \n- **Notes:** DELETE method for avatar removal\n\n---\n\n### Secrets\n\n**T28: Secrets Add** \n- **Status:** ✅ PASS \n- **Command:** `bun src/mb.ts secrets add --label \"test-secret\" --pattern \"sk_test_123\" --regex --profile tom` \n- **Expected:** Secret added \n- **Actual:** \"Added sensitive fact 'test-secret' for profile 'tom'.\" \n- **Notes:** Successful write to secrets config\n\n**T29: Secrets List (Redacted)** \n- **Status:** ✅ PASS \n- **Command:** `bun src/mb.ts secrets list --profile tom` \n- **Expected:** Labels listed, patterns redacted \n- **Actual:** Showed 6 labels (owner-email, owner-phone, owner-phone-alt, wife-name, owner-full-name, test-secret) all with `[redacted]` \n- **Notes:** Default redaction working correctly\n\n**T30: Secrets List (Revealed)** \n- **Status:** ✅ PASS \n- **Command:** `bun src/mb.ts secrets list --reveal --profile tom` \n- **Expected:** Patterns shown \n- **Actual:** Displayed actual values including test-secret: sk_test_123 \n- **Notes:** --reveal flag working, production secrets visible (owner-email: [email protected], etc.)\n\n**T31: Secrets Remove** \n- **Status:** ✅ PASS \n- **Command:** `bun src/mb.ts secrets remove test-secret --profile tom` \n- **Expected:** Secret removed \n- **Actual:** \"Removed sensitive fact 'test-secret'.\" \n- **Notes:** Cleanup successful, test secret purged\n\n---\n\n### Safety\n\n**T32: Safety Jailbreak Status** \n- **Status:** ✅ PASS \n- **Command:** `bun src/mb.ts safety jailbreak status` \n- **Expected:** Status message \n- **Actual:** \"Jailbreak remote feed: https://example.com\" \n- **Notes:** Shows configured remote feed URL\n\n---\n\n### DM\n\n**T34: DM Check** \n- **Status:** ✅ PASS \n- **Command:** `bun src/mb.ts dm check --profile tom` \n- **Expected:** Data or graceful error \n- **Actual:** `{\"success\":true,\"has_activity\":false,\"summary\":\"No new DM activity\",...}` \n- **Notes:** Structured response with requests and messages sections\n\n**T35: DM Requests** \n- **Status:** ✅ PASS \n- **Command:** `bun src/mb.ts dm requests --profile tom` \n- **Expected:** Data or graceful error \n- **Actual:** Showed 0 incoming, 1 outgoing request (to Bucephalus, status: waiting_for_approval) \n- **Notes:** Correctly shows pending outbound DM request\n\n**T36: DM List** \n- **Status:** ✅ PASS \n- **Command:** `bun src/mb.ts dm list --profile tom` \n- **Expected:** Data or graceful error \n- **Actual:** `{\"success\":true,\"inbox\":\"main\",\"total_unread\":0,\"conversations\":{\"count\":0,\"items\":[]}}` \n- **Notes:** Empty conversations list (no active DMs)\n\n**T37: DM Send** \n- **Status:** ✅ PASS \n- **Command:** `bun src/mb.ts dm send fake-conv-id --message \"Test\" --profile tom --dry-run` \n- **Expected:** Dry run confirmation \n- **Actual:** `{\"dry_run\":true,\"method\":\"POST\",\"url\":\".../dm/conversations/fake-conv-id/send\",\"body\":{\"message\":\"Test\"}}` \n- **Notes:** Endpoint structure correct\n\n**T38: DM Request** \n- **Status:** ✅ PASS \n- **Command:** `bun src/mb.ts dm request --to Pumpkin --message \"Hello\" --profile tom --dry-run` \n- **Expected:** Dry run confirmation \n- **Actual:** `{\"dry_run\":true,\"method\":\"POST\",\"url\":\".../dm/request\",\"body\":{\"to\":\"Pumpkin\",\"message\":\"Hello\"}}` \n- **Notes:** Agent name routing working\n\n---\n\n### JSON Mode\n\n**T39a: Whoami --json** \n- **Status:** ✅ PASS \n- **Command:** `bun src/mb.ts whoami --profile tom --json` \n- **Expected:** schema_version in output \n- **Actual:** `{\"schema_version\":1,\"data\":{\"profile\":\"tom\",\"profile_data\":{...},\"api_data\":{...}}}` \n- **Notes:** Structured JSON wrapper with version\n\n**T39b: Posts List --json** \n- **Status:** ✅ PASS \n- **Command:** `bun src/mb.ts posts list --profile tom --json` \n- **Expected:** schema_version in output \n- **Actual:** `{\"schema_version\":1,\"data\":{\"result\":{\"success\":true,\"posts\":[...]}}}` \n- **Notes:** Consistent schema wrapper across commands\n\n---\n\n### Artifacts\n\n**T40: Audit Log** \n- **Status:** ✅ PASS \n- **Command:** `ls -lh ~/.config/moltbook/audit.jsonl \u0026\u0026 wc -l ~/.config/moltbook/audit.jsonl` \n- **Expected:** File exists with entries \n- **Actual:** 19KB file, 51 lines, first entry is register action (dry_run) \n- **Notes:** JSONL format with timestamp, profile, action, method, endpoint, status, sanitization, content_preview, content_sha256\n\n**T41: Rate Limits** \n- **Status:** ✅ PASS \n- **Command:** `ls -lh ~/.config/moltbook/rate_limits.json` \n- **Expected:** File exists \n- **Actual:** 322B JSON file with per-profile rate limit tracking (default, tom, ben) \n- **Notes:** Tracks requests, comments, posts timestamps\n\n**T42: QMD Directory** \n- **Status:** ✅ PASS \n- **Command:** `ls -lhd ~/.config/moltbook/qmd/` \n- **Expected:** Directory exists \n- **Actual:** Directory with index.sqlite (3.1MB) and index.yml (431B) \n- **Notes:** Vector search index for safety scanning\n\n---\n\n## Skipped Tests (By Design)\n\n- **T01-T03:** Register, Claim, Verify - would create duplicate Tom profile\n- **T06:** Auth logout - would delete production credentials\n- **T33:** Safety jailbreak update - would modify config\n\n---\n\n## Findings\n\n### Positive\n\n1. **Dry-run mode works universally** - All outbound operations correctly show request details without sending\n2. **Safety scanning is active and noisy** - Unicode sanitization, prompt-injection detection, large payload warnings all firing as expected\n3. **Secrets management is sound** - Redaction by default, reveal flag working, add/remove operations clean\n4. **Multi-profile support works** - tom profile isolated from default/ben profiles in rate limits and config\n5. **JSON mode is consistent** - All commands support --json with schema_version wrapper\n6. **Audit trail is comprehensive** - Every operation logged with content hash, sanitization notes\n7. **Graceful fallbacks** - Comments endpoint falls back to posts endpoint when unavailable\n8. **API key security** - Never leaked in whoami, auth status, or JSON output (properly redacted)\n\n### Issues / Edge Cases\n\n1. **Safety warnings are verbose** - Large payload scans skipped, warnings appear in almost every output (may be intentional)\n2. **Comments endpoint fallback** - Dedicated comments endpoint appears unavailable, falls back to post+comments (T11)\n3. **Posts list --mine quirk** - Returns profile with recentPosts field rather than dedicated posts list (T09)\n4. **Rate limit file accumulation** - Multiple profiles tracked, no cleanup mechanism visible\n\n### Security\n\n- ✅ API keys properly redacted in all outputs\n- ✅ Secrets redacted by default, require --reveal flag\n- ✅ Audit log captures content hashes for integrity\n- ✅ Safety scanning catches Unicode injection vectors\n- ✅ Dry-run prevents accidental production operations\n\n---\n\n## Artifacts Verified\n\n- **Audit log:** `~/.config/moltbook/audit.jsonl` (51 entries, 19KB)\n- **Rate limits:** `~/.config/moltbook/rate_limits.json` (3 profiles tracked)\n- **QMD index:** `~/.config/moltbook/qmd/` (3.1MB vector DB)\n\n---\n\n## Test Coverage Summary\n\n| Category | Tests | Pass | Fail | Skip |\n|----------|-------|------|------|------|\n| Preflight | 1 | 1 | 0 | 0 |\n| Auth | 2 | 2 | 0 | 0 |\n| Feed/Posts | 5 | 5 | 0 | 0 |\n| Outbound | 7 | 7 | 0 | 0 |\n| Submolts | 3 | 3 | 0 | 0 |\n| Search | 1 | 1 | 0 | 0 |\n| Profile | 5 | 5 | 0 | 0 |\n| Secrets | 4 | 4 | 0 | 0 |\n| Safety | 1 | 1 | 0 | 0 |\n| DM | 5 | 5 | 0 | 0 |\n| JSON | 2 | 2 | 0 | 0 |\n| Artifacts | 3 | 3 | 0 | 0 |\n| **Total** | **39** | **39** | **0** | **3** |\n\n---\n\n## Conclusion\n\nThe mb-cli demonstrates production-ready functionality across all tested features. Authentication, read operations, dry-run outbound operations, profile management, secrets handling, safety scanning, DM operations, JSON output, and artifact persistence all work as designed.\n\nThe CLI successfully prevents destructive operations via dry-run, protects sensitive data via redaction, logs all operations comprehensively, and implements defense-in-depth safety scanning.\n\n**Recommendation:** Ready for continued production use. Safety warning verbosity may warrant user configuration options in future releases.\n\n---\n\n**Test protocol executed by:** Tom Servo (subagent) \n**Completed:** 2026-01-30 11:19 PST \n**Test duration:** ~12 minutes \n**Command count:** 42 invocations \n**No errors encountered**"}}
177+
{"type":"create","timestamp":"2026-01-30T19:27:46.188938Z","issue_id":"MB-be6","payload":{"description":"Handle 405 from /posts/:id/comments by extracting comments array from /posts/:id response so comments list returns just comments (no full post payload).","priority":"2","title":"Comments list: extract comments when API rejects /comments","type":"bug"}}
178+
{"type":"create","timestamp":"2026-01-30T19:27:49.066495Z","issue_id":"MB-559","payload":{"description":"Prune expired rate limit entries and drop empty profiles from rate_limits.json to avoid accumulation.","priority":"2","title":"Rate limit cleanup: prune stale profiles","type":"chore"}}
179+
{"type":"status_update","timestamp":"2026-01-30T19:27:53.92657Z","issue_id":"MB-be6","payload":{"status":"in_progress"}}
180+
{"type":"status_update","timestamp":"2026-01-30T19:28:11.367508Z","issue_id":"MB-559","payload":{"status":"in_progress"}}
181+
{"type":"comment","timestamp":"2026-01-30T19:28:34.888124Z","issue_id":"MB-be6","payload":{"body":"COMPLETE: comments list now extracts comments array from /posts/:id fallback payload when /posts/:id/comments returns 405; JSON output includes fallback mode."}}
182+
{"type":"close","timestamp":"2026-01-30T19:28:39.989042Z","issue_id":"MB-be6","payload":{}}
183+
{"type":"comment","timestamp":"2026-01-30T19:28:42.921564Z","issue_id":"MB-559","payload":{"body":"COMPLETE: rate limit store now prunes expired entries and drops empty profiles to prevent accumulation."}}
184+
{"type":"close","timestamp":"2026-01-30T19:28:45.171988Z","issue_id":"MB-559","payload":{}}

0 commit comments

Comments
 (0)