From f5898528ee8a67318c4fad71868d1b1d1d703158 Mon Sep 17 00:00:00 2001 From: Steve Yegge Date: Sun, 23 Nov 2025 22:02:40 -0800 Subject: [PATCH] bd sync: 2025-11-23 22:02:40 --- .beads/beads.jsonl | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.beads/beads.jsonl b/.beads/beads.jsonl index 9bc520c6..bc26281b 100644 --- a/.beads/beads.jsonl +++ b/.beads/beads.jsonl @@ -242,7 +242,7 @@ {"id":"bd-85487065","content_hash":"f11f458db379288179b4c2434eacee8940eac910781a74c721c7e6e889f76bc1","title":"Add tests for internal/autoimport package","description":"Currently 0.0% coverage. Need tests for auto-import functionality that detects and imports updated JSONL files.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-29T14:06:18.154805-07:00","updated_at":"2025-11-08T22:42:08.862467-08:00","closed_at":"2025-11-08T18:06:25.811317-08:00","source_repo":"."} {"id":"bd-85d1","content_hash":"a82c0064b840eacb4896f68e73650a3e99aaeaffbb2a7269a857b6c4245b5572","title":"Add integration tests for multi-repo sync","description":"Test: Clone A deletes issue, Clone B imports Clone A's JSONL. Verify Clone B handles deletion gracefully with resurrection. Test concurrent imports with same orphans (should be idempotent). Test round-trip fidelity (export→delete parent→import→verify structure).","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-04T12:32:21.410318-08:00","updated_at":"2025-11-05T00:44:27.948465-08:00","closed_at":"2025-11-05T00:44:27.948467-08:00","source_repo":"."} {"id":"bd-8788","content_hash":"31af4635755d7ee1b09d75690de5e8d058417a176fd0b49490d3c968fb3a16a4","title":"Fix monitor-webui status filter","description":"","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-11-21T11:54:18.982820303-07:00","updated_at":"2025-11-21T11:54:36.091639066-07:00","closed_at":"2025-11-21T11:54:36.091639066-07:00","source_repo":"."} -{"id":"bd-879d","content_hash":"9716c230d9b2793bd1e51d9e3c380c06caf7b3e9a0dd20253764af19e3de7ac8","title":"Test issue 1","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-02T09:44:12.538697729Z","updated_at":"2025-11-02T09:45:20.76214671Z","closed_at":"2025-11-02T09:45:20.76214671Z","source_repo":".","dependencies":[{"issue_id":"bd-879d","depends_on_id":"bd-d3e5","type":"discovered-from","created_at":"2025-11-02T09:44:22.103468321Z","created_by":"mrdavidlaing"}]} +{"id":"bd-879d","content_hash":"9716c230d9b2793bd1e51d9e3c380c06caf7b3e9a0dd20253764af19e3de7ac8","title":"Test issue 1","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-02T09:44:12.538697729Z","updated_at":"2025-11-02T09:45:20.76214671Z","closed_at":"2025-11-02T09:45:20.76214671Z","source_repo":"."} {"id":"bd-87a0","content_hash":"b6c322852ff360ade9f0d46bb2af29a7cf3d3acc8b7469dcbb5d98bf48050240","title":"Publish @beads/bd package to npm registry","description":"Publish the npm package to the public npm registry:\n\n## Prerequisites\n- npm account created\n- Organization @beads created (or use different namespace)\n- npm login completed locally\n- Package tested locally (bd-f282 completed)\n\n## Publishing steps\n1. Verify package.json version matches current bd version\n2. Run npm pack and inspect tarball contents\n3. Test installation from tarball one more time\n4. Run npm publish --access public\n5. Verify package appears on https://www.npmjs.com/package/@beads/bd\n6. Test installation from registry: npm install -g @beads/bd\n\n## Post-publish\n- Add npm badge to README.md\n- Update CHANGELOG.md with npm package release\n- Announce in release notes\n\n## Note\n- May need to choose different name if @beads namespace unavailable\n- Alternative: beads-cli, bd-cli, or unscoped beads-issue-tracker","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-02T23:40:25.263569-08:00","updated_at":"2025-11-03T10:39:41.772338-08:00","closed_at":"2025-11-03T10:39:41.772338-08:00","source_repo":".","dependencies":[{"issue_id":"bd-87a0","depends_on_id":"bd-febc","type":"parent-child","created_at":"2025-11-02T23:40:33.014043-08:00","created_by":"daemon"}],"comments":[{"id":25,"issue_id":"bd-87a0","author":"stevey","text":"Package is ready to publish. All code complete and tested locally. Next steps: 1) npm login, 2) create @beads org if needed, 3) npm publish --access public. See npm-package/PUBLISHING.md for complete instructions.","created_at":"2025-11-24T04:54:24Z"}]} {"id":"bd-8900f145","content_hash":"4a07f36a9e5d24aaffb092c89e2273cb58f9de357d24eeb01fcde6a4079ba775","title":"Testing event-driven mode!","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-29T15:28:33.564871-07:00","updated_at":"2025-10-30T17:12:58.186325-07:00","closed_at":"2025-10-29T19:12:54.43368-07:00","source_repo":"."} {"id":"bd-8931","content_hash":"8e75edea7ed84a1c2b42662444a06f5406c6c9ae7b1412eaabffb1af9fd614a3","title":"Daemon gets stuck when auto-import blocked by git conflicts","description":"CRITICAL: The daemon enters a corrupt state that breaks RPC commands when auto-import is triggered but git pull fails due to uncommitted changes.\n\nImpact: This is a data integrity and usability issue that could cause users to lose trust in Beads. The daemon silently fails for certain commands while appearing healthy.\n\nReproduction:\n1. Make local changes to issues (creates uncommitted .beads/beads.jsonl)\n2. Remote has updates (JSONL newer, triggers auto-import)\n3. Daemon tries to pull but fails: 'cannot pull with rebase: You have unstaged changes'\n4. Daemon enters bad state - 'bd show' and other commands return EOF\n5. 'bd list' still works, daemon process is running, no errors logged\n\nTechnical details:\n- Auto-import check runs in handleRequest() before processing RPC commands\n- When import is blocked, it appears to corrupt daemon state\n- Likely: deadlock, unclosed transaction, or storage handle corruption\n- Panic recovery (server_lifecycle_conn.go:183) didn't catch anything - not a panic\n\nRequired fix:\n- Auto-import must not block RPC command execution\n- Handle git pull failures gracefully without corrupting state\n- Consider: skip auto-import if git is dirty, queue import for later, or use separate goroutine\n- Add timeout/circuit breaker for import operations\n- Log clear warnings when auto-import is skipped\n\nWithout this fix, users in collaborative environments will frequently encounter mysterious EOF errors that require daemon restarts.","status":"closed","priority":0,"issue_type":"bug","created_at":"2025-11-02T17:15:25.181425-08:00","updated_at":"2025-11-03T12:08:12.949061-08:00","closed_at":"2025-11-03T12:08:12.949064-08:00","source_repo":".","dependencies":[{"issue_id":"bd-8931","depends_on_id":"bd-1048","type":"blocks","created_at":"2025-11-02T17:15:25.181857-08:00","created_by":"stevey"}]} @@ -329,7 +329,7 @@ {"id":"bd-ayw","content_hash":"825e5540d42018f2d2cad08f79581eb1b819320bbde4802409111fda485d6d53","title":"Add 'When to use daemon mode' decision tree to daemon.md","description":"**Problem:**\nUsers (especially local-only developers) see daemon-related messages but don't understand:\n- What daemon mode does (git sync automation)\n- Whether they need it\n- Why they see \"daemon_unsupported\" messages\n\nRelated to issue #349 item #3.\n\n**Current state:**\ncommands/daemon.md explains WHAT daemon does but not WHEN to use it.\n\n**Proposed addition:**\nAdd a \"When to Use Daemon Mode\" section after line 20 in commands/daemon.md with clear decision criteria:\n\n**✅ You SHOULD use daemon mode if:**\n- Working in a team with git remote sync\n- Want automatic commit/push of issue changes\n- Need background auto-sync (5-second debounce)\n- Making frequent bd commands (performance benefit)\n\n**❌ You DON'T need daemon mode if:**\n- Solo developer with local-only tracking\n- Working in git worktrees (use --no-daemon)\n- Running one-off commands/scripts\n- Debugging database issues\n\n**Local-only users:** Direct mode is perfectly fine. Daemon mainly helps with git sync automation. You can use `bd sync` manually when needed.\n\n**Files to modify:**\n- commands/daemon.md (add section after line 20)","status":"closed","priority":3,"issue_type":"task","created_at":"2025-11-20T20:48:23.111621-05:00","updated_at":"2025-11-23T10:31:59.658108-08:00","closed_at":"2025-11-20T20:59:13.429263-05:00","source_repo":".","labels":["documentation","onboarding"],"comments":[{"id":29,"issue_id":"bd-ayw","author":"stevey","text":"Addresses GitHub issue #349 item 3: https://github.com/steveyegge/beads/issues/349\n\nLocal-only users see daemon-related messages without understanding when they need daemon mode vs when direct mode is sufficient. Need clear decision tree in daemon.md.","created_at":"2025-11-24T04:54:24Z"}]} {"id":"bd-az0m","content_hash":"91dd58e84b57c84ae065004ef4c15d0b5330935a5fde35eed489a93452feb2e9","title":"Issue 1","description":"","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-20T19:43:48.754145-05:00","updated_at":"2025-11-20T19:43:48.754145-05:00","closed_at":"2025-11-07T21:55:09.42865-08:00","source_repo":".","dependencies":[{"issue_id":"bd-az0m","depends_on_id":"bd-bvo2","type":"related","created_at":"2025-11-07T19:07:21.069031-08:00","created_by":"daemon"}]} {"id":"bd-azqv","content_hash":"b4e68adcec7b19f567ebee47f505ca6b529c17b4c4b885282cfc564e8a874f9f","title":"Ready issue","description":"","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-07T19:04:22.247039-08:00","updated_at":"2025-11-07T22:07:17.344986-08:00","closed_at":"2025-11-07T21:55:09.429024-08:00","source_repo":"."} -{"id":"bd-b0c8","content_hash":"87b423a42d509b9405b52b089b2ba92b33a90ad472d6d9094986b48715399a99","title":"Research hooks/skills approach for enforcing issue descriptions","description":"## Solution: Hooks/Skills (mentioned in discussion)\n\nResearch the hooks/skills system mentioned by riordanpawley in discussion #366:\nhttps://www.reddit.com/r/ClaudeAI/s/wrn2tjkMHX\n\n## Investigation Tasks\n\n1. Review the Reddit post to understand the approach\n2. Determine if beads hooks can enforce validation\n3. Check if Claude Code skills/hooks can intercept MCP calls\n4. Assess feasibility and user burden\n\n## Notes\n\nFrom discussion #366:\n\u003e I'm using a skills/hooks system to get Claude to do that kind of thing right similar to https://www.reddit.com/r/ClaudeAI/s/wrn2tjkMHX\n\nThis might be a client-side solution rather than server-side.\n\n## Deliverable\n\nDocument findings in issue notes, with recommendation on whether to pursue this approach.","status":"open","priority":3,"issue_type":"task","created_at":"2025-11-23T14:01:01.57079-08:00","updated_at":"2025-11-23T14:01:01.57079-08:00","source_repo":".","dependencies":[{"issue_id":"bd-b0c8","depends_on_id":"bd-0tr0","type":"discovered-from","created_at":"2025-11-23T14:01:01.572166-08:00","created_by":"daemon"}]} +{"id":"bd-b0c8","content_hash":"c36e12ae5ab15670ac6d9340f5e45e0ad361051a75a1f8f0b4f18e67b41071e1","title":"Research hooks/skills approach for enforcing issue descriptions","description":"## Solution: Hooks/Skills (mentioned in discussion)\n\nResearch the hooks/skills system mentioned by riordanpawley in discussion #366:\nhttps://www.reddit.com/r/ClaudeAI/s/wrn2tjkMHX\n\n## Investigation Tasks\n\n1. Review the Reddit post to understand the approach\n2. Determine if beads hooks can enforce validation\n3. Check if Claude Code skills/hooks can intercept MCP calls\n4. Assess feasibility and user burden\n\n## Notes\n\nFrom discussion #366:\n\u003e I'm using a skills/hooks system to get Claude to do that kind of thing right similar to https://www.reddit.com/r/ClaudeAI/s/wrn2tjkMHX\n\nThis might be a client-side solution rather than server-side.\n\n## Deliverable\n\nDocument findings in issue notes, with recommendation on whether to pursue this approach.","status":"closed","priority":3,"issue_type":"task","created_at":"2025-11-23T14:01:01.57079-08:00","updated_at":"2025-11-23T22:01:17.336296-08:00","closed_at":"2025-11-23T22:01:17.336296-08:00","source_repo":".","dependencies":[{"issue_id":"bd-b0c8","depends_on_id":"bd-0tr0","type":"discovered-from","created_at":"2025-11-23T14:01:01.572166-08:00","created_by":"daemon"}],"comments":[{"id":35,"issue_id":"bd-b0c8","author":"stevey","text":"## Research Findings: Hooks/Skills for Enforcing Issue Descriptions\n\n### Summary\nPreToolUse hooks are the right solution for enforcing non-empty descriptions when Claude creates beads issues via MCP. Skills cannot intercept or validate tool parameters.\n\n### Key Findings\n\n#### 1. Hooks vs Skills Capabilities\n\n**Hooks (Pre-execution validation):**\n- PreToolUse hooks execute BEFORE tool execution\n- Can approve, deny, or request user confirmation\n- Can validate and modify tool parameters via updatedInput\n- Work with MCP tools using matcher patterns like mcp__*__create_issue\n- Support bash commands and LLM-based evaluation\n\n**Skills (Guidance only):**\n- Provide contextual guidance to Claude's decision-making\n- Cannot intercept or validate tool calls\n- Restrict available tools but don't validate parameters\n- Operate at instruction level, not execution level\n\n#### 2. How to Enforce Non-Empty Descriptions\n\nThe beads MCP tool signature is:\n```python\n@mcp.tool(name=\"create\")\nasync def create_issue(\n title: str,\n description: str = \"\", # Optional, defaults to empty\n ...\n)\n```\n\nValidation Hook Example:\n```json\n{\n \"hooks\": {\n \"PreToolUse\": [\n {\n \"matcher\": \"mcp__beads__create\",\n \"hooks\": [\n {\n \"type\": \"command\",\n \"command\": \"bash -c 'jq -e \\\".tool_input.description and (.tool_input.description | length \u003e 0)\\\" \u0026\u0026 exit 0 || exit 2'\"\n }\n ]\n }\n ]\n }\n}\n```\n\nExit codes: 0=approve, 1=ask user, 2=deny with feedback\n\n#### 3. User Burden Assessment\n\n**Setup Burden: LOW**\n- One-time configuration in .claude/settings.json\n- Can use /hooks command for interactive setup\n- Requires basic bash/jq knowledge for validation logic\n\n**Runtime Burden: ZERO**\n- Hooks execute automatically on every matching tool call\n- No user action required\n- Claude receives immediate feedback if validation fails\n\n**Maintenance Burden: LOW**\n- Validation logic is simple and stable\n- No per-user configuration needed (project-level settings)\n- Works across all agents/sessions in the project\n\n#### 4. Current Hook Setup\n\nThe beads project already has hooks configured at /Users/stevey/ai/beads/.claude/settings.json with SessionStart hooks, demonstrating the infrastructure is in place.\n\n### Recommendation\n\nImplement a PreToolUse hook for beads MCP create tool:\n\n1. Add to .claude/settings.json in beads projects\n2. Use simple validation that denies empty descriptions\n3. Provide clear feedback to Claude about what's required\n4. Consider whether to block or auto-prompt for description\n\n**Advantages:**\n- Zero runtime burden for users\n- Catches the problem at the source (before execution)\n- Provides immediate feedback to Claude\n- Works consistently across all sessions\n- Can be configured at project or user level\n\n**Limitations:**\n- Only works in Claude Code (not other MCP clients)\n- Requires bash/jq for validation logic\n- Hook configuration must be set up by user\n\n### Next Steps\n\nIf pursuing this approach:\n1. Create example hook configuration\n2. Document in beads setup guide\n3. Consider adding to default .claude/settings.json during bd init\n4. Test with various Claude behaviors to ensure it works reliably\n","created_at":"2025-11-24T06:01:10Z"}]} {"id":"bd-b121","content_hash":"43f5615a81c6cd99e89ca8f3030003c895509243a4348f4ed1956a3328d8c3b1","title":"Fix :memory: database connection pool issue causing \"no such table\" errors","description":"Critical bug in v0.21.6 where :memory: databases with cache=shared create multiple connections in the pool, causing intermittent \"no such table\" errors. SQLite's shared cache for in-memory databases only works reliably with a single connection.\n\nRoot cause: Missing db.SetMaxOpenConns(1) after sql.Open() for :memory: databases.\n\nImpact: 37 test failures in VC project, affects all consumers using :memory: for testing.","status":"closed","priority":0,"issue_type":"bug","created_at":"2025-11-04T00:52:56.318619-08:00","updated_at":"2025-11-05T11:31:27.50439-08:00","closed_at":"2025-11-05T00:50:00.558124-08:00","source_repo":"."} {"id":"bd-b134","content_hash":"455202a74224066aca5a1e300d045ae99e5c4ba5c306c043fd4c4c70c4aea058","title":"Add tests for Integration Layer Implementation","description":"While implementing bd-wfmw, noticed missing tests","notes":"Reviewed existing coverage:\n- Basic test coverage exists in lib/test_beads_mail_adapter.py\n- Integration tests cover failure scenarios in tests/integration/test_mail_failures.py\n- Good coverage of: enabled/disabled modes, graceful degradation, 409 conflicts, HTTP errors, config\n- Missing: authorization headers detail, request body structure validation, concurrent reservation timing, TTL edge cases","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-08T00:20:30.804172-08:00","updated_at":"2025-11-08T02:17:04.046571-08:00","closed_at":"2025-11-08T02:17:04.046571-08:00","source_repo":".","dependencies":[{"issue_id":"bd-b134","depends_on_id":"bd-wfmw","type":"discovered-from","created_at":"2025-11-08T00:20:30.850776-08:00","created_by":"daemon"}]} {"id":"bd-b245","content_hash":"5ad06a3b7126d4a4eb779cd01319cc4541869f4295afcf6f91cf7d6d36078cb0","title":"Add migration registry and simplify New()","description":"Create migrations.go with Migration type and registry. Change New() to: openDB -\u003e initSchema -\u003e RunMigrations(db). This removes 8+ separate migrate functions from New().","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-01T11:41:14.862623-07:00","updated_at":"2025-11-02T12:55:59.954845-08:00","closed_at":"2025-11-02T12:55:59.954854-08:00","source_repo":"."} @@ -399,7 +399,6 @@ {"id":"bd-d19a","content_hash":"5ff9ba5e70c3e3eeaff40887421797e30dfb75e56e97fcaaf3f3d32332f22aa2","title":"Fix import failure on missing parent issues","description":"Import process fails atomically when JSONL references deleted parent issues. Implement hybrid solution: topological sorting + parent resurrection to handle deleted parents gracefully while maintaining referential integrity. See docs/import-bug-analysis-bd-3xq.md for full analysis.","status":"closed","priority":0,"issue_type":"epic","created_at":"2025-11-04T12:31:30.994759-08:00","updated_at":"2025-11-05T00:08:42.814239-08:00","closed_at":"2025-11-05T00:08:42.814243-08:00","source_repo":"."} {"id":"bd-d33c","content_hash":"d0820d5dd6ea4ab198e013861d3d7d01da701daa8ab8ec59ad5ef855e6f83b2b","title":"Separate process/lock/PID concerns into process.go","description":"Create internal/daemonrunner/process.go with: acquireDaemonLock, PID file read/write, stopDaemon, isDaemonRunning, getPIDFilePath, socket path helpers, version check.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-01T11:41:14.871122-07:00","updated_at":"2025-11-01T23:43:55.66159-07:00","closed_at":"2025-11-01T23:43:55.66159-07:00","source_repo":"."} {"id":"bd-d355a07d","content_hash":"e5e88defa034e6758f63ac603963209245ab74f531510366b25ebbf7b4be36b3","title":"Import validation falsely reports data loss on collision resolution","description":"## Problem\n\nPost-import validation reports 'data loss detected!' when import count reduces due to legitimate collision resolution.\n\n## Example\n\n```\nImport complete: 1 created, 8 updated, 142 unchanged, 19 skipped, 1 issues remapped\nPost-import validation failed: import reduced issue count: 165 → 164 (data loss detected!)\n```\n\nThis was actually successful collision resolution (bd-70419816 duplicated → remapped to-70419816), not data loss.\n\n## Impact\n\n- False alarms waste investigation time\n- Undermines confidence in import validation\n- Confuses users/agents about sync health\n\n## Solution\n\nImprove validation to distinguish:\n- Collision-resolution merges (expected count reduction)\n- Actual data loss (unexpected disappearance)\n\nTrack remapped issue count and adjust expected post-import count accordingly.","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-10-29T23:15:00.815227-07:00","updated_at":"2025-11-08T01:58:15.283088-08:00","closed_at":"2025-11-08T00:33:04.659308-08:00","source_repo":"."} -{"id":"bd-d3e5","content_hash":"2eaf57cb617922924aadb6b04366a3ef058d386752c65e8471f2704b512ea30a","title":"Test issue 2","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-02T09:44:17.116768539Z","updated_at":"2025-11-23T21:42:49.915748-08:00","closed_at":"2025-11-23T21:42:49.915751-08:00","source_repo":"."} {"id":"bd-d3f0","content_hash":"d759327f1a1e4817d3e8ec212fd6af2607d0bb5e654201a6fc3640ad0a3b18fd","title":"Add 'bd comment' as alias for 'bd comments add'","description":"The command 'bd comments add' is verbose and unintuitive. Add 'bd comment' as a shorter alias that works the same way.\n\n## Rationale\n- More natural: 'bd comment \u003cissue-id\u003e \u003ctext\u003e' reads better than 'bd comments add \u003cissue-id\u003e \u003ctext\u003e'\n- Matches user expectations: users naturally try 'bd comment' first\n- Follows convention: other commands like 'bd create', 'bd show', 'bd close' are verbs\n\n## Implementation\nCould be implemented as:\n1. A new command that wraps bd comments add\n2. An alias registered in cobra\n3. Keep 'bd comments add' for backwards compatibility\n\n## Examples\n```bash\nbd comment bd-1234 'This is a comment'\nbd comment bd-1234 'Multi-line comment' --body 'Additional details here'\n```","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-11-02T17:13:18.82563-08:00","updated_at":"2025-11-03T22:20:30.223939-08:00","closed_at":"2025-11-03T22:20:30.223939-08:00","source_repo":"."} {"id":"bd-d4ec5a82","content_hash":"e0f9aa493571fdb0b5fd578993165042ad224bb2c00186564337732e6221d529","title":"Add MCP functions for repair commands","description":"Add repair commands to beads-mcp for agent access:\n- beads_resolve_conflicts()\n- beads_find_duplicates()\n- beads_detect_pollution()\n- beads_validate()\n\nFiles: integrations/beads-mcp/src/beads_mcp/server.py","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-28T14:48:29.071495-07:00","updated_at":"2025-11-06T19:36:13.972786-08:00","closed_at":"2025-11-06T19:27:19.170894-08:00","source_repo":"."} {"id":"bd-d4i","content_hash":"41cafb4bfa5377a84005b08cddd3e703c1317e98ef32b050ddaabf1bdc7718c9","title":"Create tip system infrastructure for contextual hints","description":"Implement a tip/hint system that shows helpful contextual messages after successful commands. This is different from the existing error-path \"Hint:\" messages - tips appear on success paths to educate users about features they might not know about.","design":"## Implementation\n\nCreate `cmd/bd/tips.go` with:\n\n### Core Infrastructure\n```go\ntype Tip struct {\n ID string\n Condition func() bool // Should this tip be eligible?\n Message string\n Frequency time.Duration // Minimum gap between showings\n Priority int // Higher = shown first when eligible\n Probability float64 // 0.0 to 1.0 - chance of showing\n}\n\nfunc maybeShowTip(store storage.Storage) {\n if jsonOutput || quietMode {\n return // Respect output flags\n }\n \n tip := selectNextTip(store)\n if tip != nil {\n fmt.Fprintf(os.Stdout, \"\\n💡 Tip: %s\\n\", tip.Message)\n recordTipShown(store, tip.ID)\n }\n}\n\nfunc selectNextTip(store storage.Storage) *Tip {\n now := time.Now()\n var eligibleTips []Tip\n \n // Filter to eligible tips (condition + frequency check)\n for _, tip := range tips {\n if !tip.Condition() {\n continue\n }\n \n lastShown := getLastShown(store, tip.ID)\n if !lastShown.IsZero() \u0026\u0026 now.Sub(lastShown) \u003c tip.Frequency {\n continue\n }\n \n eligibleTips = append(eligibleTips, tip)\n }\n \n if len(eligibleTips) == 0 {\n return nil\n }\n \n // Sort by priority (highest first)\n sort.Slice(eligibleTips, func(i, j int) bool {\n return eligibleTips[i].Priority \u003e eligibleTips[j].Priority\n })\n \n // Apply probability roll (in priority order)\n for _, tip := range eligibleTips {\n if rand.Float64() \u003c tip.Probability {\n return \u0026tip\n }\n }\n \n return nil // No tips won probability roll\n}\n```\n\n### Probability Examples\n\n```go\n// High priority, high probability = shows often\n{Priority: 90, Probability: 0.8} // 80% chance when eligible\n\n// High priority, medium probability = important but not spammy\n{Priority: 100, Probability: 0.6} // 60% chance\n\n// Low priority, low probability = rare suggestion\n{Priority: 30, Probability: 0.3} // 30% chance\n```\n\n### Metadata Storage\nUse existing metadata table to track:\n- `tip_{id}_last_shown` - Timestamp of last display (RFC3339 format)\n- `tip_{id}_dismissed` - User permanently dismissed (future feature)\n\n### Integration Points\nCall `maybeShowTip()` at end of:\n- `bd list` - After showing issues\n- `bd ready` - After showing ready work\n- `bd create` - After creating issue\n- `bd show` - After showing issue details\n\n## Design Decisions\n- Tips shown on stdout (informational, not errors)\n- Respects `--json` and `--quiet` flags\n- Frequency enforces minimum gap between showings\n- Priority determines evaluation order\n- Probability reduces spam (not every eligible tip shows)\n- Store state in metadata table (no new files)\n- Deterministic seed for testing (optional BEADS_TIP_SEED env var)","acceptance_criteria":"- Tip infrastructure exists in cmd/bd/tips.go\n- Tips respect --json and --quiet flags\n- Frequency tracking works (no spam)\n- Metadata table stores tip state\n- Unit tests for tip selection logic\n- Documentation in code comments","status":"open","priority":2,"issue_type":"feature","created_at":"2025-11-11T23:29:15.693956-08:00","updated_at":"2025-11-11T23:49:50.812933-08:00","source_repo":"."}