Commit Graph

33 Commits

Author SHA1 Message Date
Steve Yegge
e90e485e5b Fix bd-5ots: Eliminate N+1 query in scanIssues with batch label loading 2025-11-05 19:22:03 -08:00
Steve Yegge
05529fe4c0 Implement multi-repo hydration layer with mtime caching (bd-307)
- Add repo_mtimes table to track JSONL file modification times
- Implement HydrateFromMultiRepo() with mtime-based skip optimization
- Support tilde expansion for repo paths in config
- Add source_repo column via migration (not in base schema)
- Fix schema to allow migration on existing databases
- Comprehensive test coverage for hydration logic
- Resurrect missing parent issues bd-cb64c226 and bd-cbed9619

Implementation:
- internal/storage/sqlite/multirepo.go - Core hydration logic
- internal/storage/sqlite/multirepo_test.go - Test coverage
- docs/MULTI_REPO_HYDRATION.md - Documentation

Schema changes:
- source_repo column added via migration only (not base schema)
- repo_mtimes table for mtime caching
- All SELECT queries updated to include source_repo

Database recovery:
- Restored from 17 to 285 issues
- Created placeholder parents for orphaned hierarchical children

Amp-Thread-ID: https://ampcode.com/threads/T-faa1339a-14b2-426c-8e18-aa8be6f5cde6
Co-authored-by: Amp <amp@ampcode.com>
2025-11-04 23:12:41 -08:00
Steve Yegge
7d6d64d2c1 Refactor: Replace manual transaction handling with withTx() helper
Fixes bd-1b0a

Changes:
- Added withTx() helper in util.go for cleaner transaction handling
- Kept ExecInTransaction() as deprecated wrapper for backward compatibility
- Refactored all manual BEGIN/COMMIT/ROLLBACK blocks to use withTx():
  - events.go: AddComment
  - dirty.go: MarkIssuesDirty, ClearDirtyIssuesByID
  - labels.go: executeLabelOperation
  - dependencies.go: AddDependency, RemoveDependency
  - compact.go: ApplyCompaction

All tests pass.

Amp-Thread-ID: https://ampcode.com/threads/T-dfacc972-f6c8-4bb3-8997-faa079b5d070
Co-authored-by: Amp <amp@ampcode.com>
2025-11-02 12:55:47 -08:00
David Laing
50a324db85 Fix #202: Add dependency_type to bd show --json output (#203)
The JSON output from bd show now includes the dependency_type field
for both dependencies and dependents, enabling programmatic
differentiation between dependency types (blocks, related,
parent-child, discovered-from).

Implementation approach:
- Added IssueWithDependencyMetadata type with embedded Issue and
  DependencyType field
- Extended GetDependenciesWithMetadata and GetDependentsWithMetadata
  to include dependency type from SQL JOIN
- Made GetDependencies and GetDependents wrap the WithMetadata
  methods for backward compatibility
- Added scanIssuesWithDependencyType helper to handle scanning with
  dependency type field
- Updated bd show --json to use WithMetadata methods

Tests added:
- TestGetDependenciesWithMetadata - basic functionality
- TestGetDependentsWithMetadata - dependent retrieval
- TestGetDependenciesWithMetadataEmpty - edge case handling
- TestGetDependenciesWithMetadataMultipleTypes - multiple types

Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Happy <yesreply@happy.engineering>
2025-11-02 08:40:10 -08:00
Steve Yegge
d86f359e63 fix: DetectCycles SQL bug and add comprehensive tests
- Fix SQL query bug preventing cycle detection (bd-9f20)
  - Allow revisiting start node to complete cycle
  - Remove duplicate start_id concatenation in final SELECT
- Add cycle_detection_test.go with comprehensive test coverage (bd-cdf7)
  - Simple 2-node cycles
  - Complex multi-node cycles (4-node, 10-node)
  - Self-loops
  - Multiple independent cycles
  - Acyclic graphs (diamond, chain)
  - Empty graph and single node edge cases
  - Mixed dependency types

Improves sqlite package coverage: 68.2% → 69.1%
2025-11-01 22:51:58 -07:00
Nikolai Prokoschenko
c65cfa1ebd Add dependency and dependent counts to bd list JSON output (#198)
When using `bd list --json`, each issue now includes:
- `dependency_count`: Number of issues this issue depends on
- `dependent_count`: Number of issues that depend on this issue

This provides quick access to dependency relationship counts without
needing to fetch full dependency lists or run multiple bd show commands.

Performance:
- Uses single bulk query (GetDependencyCounts) instead of N individual queries
- Overhead: ~26% for 500 issues (24ms vs 19ms baseline)
- Avoids N+1 query problem that would have caused 2.2x slowdown

Implementation:
- Added GetDependencyCounts() to Storage interface for bulk counting
- Efficient SQLite query using UNION ALL + GROUP BY
- Memory storage implementation for testing
- Moved IssueWithCounts to types package to avoid duplication
- Both RPC and direct modes use optimized bulk query

Tests:
- Added comprehensive tests for GetDependencyCounts
- Tests cover: normal operation, empty list, nonexistent IDs
- All existing tests continue to pass

Backwards compatible: JSON structure is additive, all original fields preserved.

Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude <noreply@anthropic.com>
2025-11-01 19:59:15 -07:00
Steve Yegge
39d5608497 Merge branch 'main' of github.com:steveyegge/beads
# Conflicts:
#	.beads/beads.jsonl
2025-10-31 15:12:08 -07:00
Steve Yegge
ddab26315f Remove dead code found by deadcode analyzer
- Removed 5 unreachable functions (~200 LOC)
- computeIssueContentHash, shouldSkipExport from autoflush.go
- addDependencyUnchecked, removeDependencyIfExists from dependencies.go
- isUniqueConstraintError alias from util.go
- All tests still pass
- Closes bd-7c5915ae
2025-10-31 15:12:01 -07:00
Steve Yegge
aa567f6b9a feat: add Mermaid.js format for dependency tree visualization (#191)
Adds `bd dep tree --format mermaid` to export dependency trees as Mermaid.js flowcharts.

Features:
- Status indicators: ☐ open, ◧ in_progress, ⚠ blocked, ☑ closed
- Theme-agnostic design
- Works with --reverse flag
- Comprehensive unit tests following TDD

Co-authored-by: David Laing <david@davidlaing.com>
2025-10-31 15:11:29 -07:00
Steve Yegge
d9eb273e15 Complete bd-95: Add content-addressable identity (ContentHash field) 2025-10-28 18:57:16 -07:00
Steve Yegge
d2989dd0f3 Merge main into PR #160 - combine reverse mode with substring bugfix
Amp-Thread-ID: https://ampcode.com/threads/T-b2413b0e-2720-45b1-9b3d-acaa7d4cf9b4
Co-authored-by: Amp <amp@ampcode.com>
2025-10-27 13:07:12 -07:00
David Laing
8c2679a80e Fix substring bug in dependency tree cycle detection (#159)
* Add .worktrees/ to .gitignore

Prevents git worktree contents from being tracked in the repository.

* Fix substring bug in dependency tree cycle detection

The cycle detection in GetDependencyTree() was using a simple substring
match which incorrectly flagged valid nodes as cycles. For example,
"bd-1" would be blocked because "bd-10" contains "bd-1" as a substring.

This bug affects any beads project where issue IDs contain each other as
substrings (BD-1/BD-10, ISSUE-1/ISSUE-10, etc).

Changed from:
  AND t.path NOT LIKE '%' || i.id || '%'

To delimiter-aware checks that respect the → separator:
  AND t.path != i.id
  AND t.path NOT LIKE i.id || '→%'
  AND t.path NOT LIKE '%→' || i.id || '→%'
  AND t.path NOT LIKE '%→' || i.id

This ensures we only match complete issue IDs, not substrings.

Added TestGetDependencyTree_SubstringBug to demonstrate and prevent
regression of this issue. The test creates a chain from bd-10 to bd-1
and verifies all nodes appear in the dependency tree.

Discovered while testing dependency tree visualization with bd-1/bd-10.
2025-10-27 12:51:41 -07:00
David Laing
dd8f51c433 feat: add reverse mode to dependency tree traversal
- Add reverse parameter to GetDependencyTree interface
- Implement reverse SQL traversal (dependents vs dependencies)
- Add comprehensive test for reverse mode (TDD: test-first approach)
- Update existing test calls with reverse=false for backward compatibility

Reverse mode inverts tree direction to show dependents instead of dependencies:
- Normal: JOIN dependencies d ON i.id = d.depends_on_id (traverse UP)
- Reverse: JOIN dependencies d ON i.id = d.issue_id (traverse DOWN)

All storage tests passing. No regressions.
2025-10-27 09:25:57 +00:00
Steve Yegge
a02729ea57 Complete bd-164: Fix timestamp-only export deduplication
- Add export_hashes table to track last exported content state
- Implement GetExportHash/SetExportHash in storage interface
- Update shouldSkipExport to use export_hashes instead of dirty_issues
- Call SetExportHash after successful export
- Clean up dirty_issues table (remove content_hash column)
- Simplify MarkIssueDirty functions (no longer compute hashes)
- Update markIssuesDirtyTx signature (remove store parameter)

Testing:
- Timestamp-only updates are skipped during export ✓
- Real content changes trigger export ✓
- export_hashes table populated correctly ✓

Fixes bd-159, bd-164
2025-10-26 20:35:37 -07:00
Steve Yegge
a898df6915 WIP: bd-164 timestamp-only export deduplication (~80% complete)
Implemented content hash-based deduplication to skip exports when only
timestamps changed. Core logic complete, needs export_hashes table wiring.

Completed:
- Added computeIssueContentHash() excluding timestamps
- Created shouldSkipExport() logic
- Updated export loop to skip timestamp-only changes
- Added hash.go with content hashing
- Extended Storage interface

Remaining:
- Complete export_hashes table migration
- Add SetExportHash/GetExportHash to interface
- Revert content_hash from dirty_issues approach
- Wire up hash persistence in export
- Testing

See bd-164 notes for details.

Amp-Thread-ID: https://ampcode.com/threads/T-d70657d1-4433-4f7e-b10a-3fccf8bf17fb
Co-authored-by: Amp <amp@ampcode.com>
2025-10-26 20:29:10 -07:00
Steve Yegge
b855c444d4 Enable errcheck linter and fix all production code warnings
- Enabled errcheck linter (previously disabled)
- Set tests: false in .golangci.yml to focus on production code
- Fixed 27 errcheck warnings using Go best practices:
  * Database resources: defer func() { _ = rows.Close() }()
  * Transaction rollbacks: defer func() { _ = tx.Rollback() }()
  * Best-effort closers: _ = store.Close(), _ = client.Close()
  * File writes: proper error checking on Close()
  * Interactive input: handle EOF gracefully
  * File ops: ignore ENOENT on os.Remove()
- All tests pass
- Closes bd-58

Amp-Thread-ID: https://ampcode.com/threads/T-57c9afd3-9adf-40c2-8be7-3e493d200361
Co-authored-by: Amp <amp@ampcode.com>
2025-10-25 18:44:38 -07:00
Mark Wotton
dd8327ff2b Preserve dependency metadata during import (#141) 2025-10-24 00:34:52 -07:00
Steve Yegge
6e29eef0c2 Revert bd-191: Remove merged_into schema field
Use simpler approach for bd-190 merge feature:
- Close merged issues with reason 'Merged into bd-X'
- No schema changes or migrations needed
- Parseable close reason is cleaner than separate field

Also updated merge epic child issues with simplified design.
2025-10-21 17:48:09 -07:00
Steve Yegge
c3023cd5f7 Add daemon support for label commands and populate labels in issue queries
- Updated label CLI commands to support both daemon and direct modes
- Added label fetching to GetIssue() and scanIssues() methods
- All label operations (add, remove, list, list-all) work with daemon
- Closed bd-162 (label CLI commands), bd-166 (duplicate), bd-141 (daemon support)

Amp-Thread-ID: https://ampcode.com/threads/T-4858f62e-ad06-4cc7-ad05-17ee76861f86
Co-authored-by: Amp <amp@ampcode.com>
2025-10-19 21:14:23 -07:00
Steve Yegge
d2e34b863b Add --show-all-paths flag to bd dep tree
Implements bd-9: Allow users to view all paths through diamond dependencies
without deduplication. Useful for debugging complex dependency structures.

Changes:
- Added --show-all-paths flag to bd dep tree command
- Updated GetDependencyTree interface to accept showAllPaths parameter
- Modified deduplication logic to be conditional on flag
- Updated tests to pass new parameter

Amp-Thread-ID: https://ampcode.com/threads/T-43807dd5-8732-49ad-a839-cdb5dae70c35
Co-authored-by: Amp <amp@ampcode.com>
2025-10-18 11:52:57 -07:00
Steve Yegge
c3e3326bba Fix critical bugs: bd-169, bd-28, bd-393
- bd-169: Add -q/--quiet flag to bd init command
- bd-28: Improve error handling in RemoveDependency
  - Now checks RowsAffected and returns error if dependency doesn't exist
  - New removeDependencyIfExists() helper for collision remapping
- bd-393: CRITICAL - Fix auto-import skipping collisions
  - Auto-import was LOSING work from other workers
  - Now automatically remaps collisions to new IDs
  - Calls RemapCollisions() instead of skipping

All tests pass.

Amp-Thread-ID: https://ampcode.com/threads/T-cba86837-28db-47ce-94eb-67fade82376a
Co-authored-by: Amp <amp@ampcode.com>
2025-10-16 15:00:54 -07:00
Steve Yegge
4fe648d140 Fix bd-437: Use addDependencyUnchecked during collision resolution
When remapping dependencies during collision resolution, skip semantic
validation (like parent-child direction checks) since we're just updating
IDs on existing dependencies that were already validated.

Fixes parent-child validation error during import --resolve-collisions.
2025-10-16 13:42:47 -07:00
Steve Yegge
1e32041fe6 Implement cycle detection and prevention improvements
- Add diagnostic warnings when cycles detected after dep add (bd-309)
- Add semantic validation for parent-child dependency direction (bd-308)
- Document cycle handling behavior in code, README, and DESIGN (bd-310)

Changes:
- cmd/bd/dep.go: Add DetectCycles() call and warning after dep add
- internal/storage/sqlite/dependencies.go: Add parent-child direction validation and comprehensive cycle prevention comments
- internal/storage/sqlite/dependencies_test.go: Add TestParentChildValidation
- README.md: Add dependency types and cycle prevention section with examples
- DESIGN.md: Add detailed cycle prevention design rationale and trade-offs
2025-10-16 13:18:07 -07:00
Steve Yegge
b7f9e74574 feat: Implement cross-type cycle prevention in dependencies
- Remove type filter from cycle detection to check ALL dependency types
- Extract maxDependencyDepth=100 constant shared across AddDependency and DetectCycles
- Move cycle check before INSERT to avoid unnecessary write on failure
- Add comprehensive tests: self-dependency, related cycles, cross-type cycles
- Verify idx_dependencies_issue index exists for performance

Fixes bd-312. Prevents cross-type cycles (e.g., A blocks B, B parent-child A)
that previously hid work from ready list. Addresses oracle feedback for
proper implementation.
2025-10-16 10:59:25 -07:00
Steve Yegge
431792b633 fix: Deduplicate nodes in bd dep tree for diamond dependencies
Fixes bd-85 (GH-1): bd dep tree was showing duplicate nodes when
multiple paths existed to the same issue (diamond dependencies).

Changes:
- Add path tracking in recursive CTE to detect cycles
- Add cycle prevention via path LIKE check
- Add Go-side deduplication using seen map
- Show each node only once at its shallowest depth

The fix maintains backward compatibility and passes all 37 tests.

Created follow-up issues:
- bd-164: Add visual indicators for multi-parent nodes
- bd-165: Add --show-all-paths flag
- bd-166: Make maxDepth configurable

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-14 03:12:00 -07:00
Steve Yegge
e6be7dd3e8 feat: Add external_ref field for linking to external issue trackers
Add nullable external_ref TEXT field to link bd issues with external
systems like GitHub Issues, Jira, etc. Includes automatic schema
migration for backward compatibility.

Changes:
- Added external_ref column to issues table with feature-based migration
- Updated Issue struct with ExternalRef *string field
- Added --external-ref flag to bd create and bd update commands
- Updated all SQL queries across the codebase to include external_ref:
  - GetIssue, CreateIssue, UpdateIssue, SearchIssues
  - GetDependencies, GetDependents, GetDependencyTree
  - GetReadyWork, GetBlockedIssues, GetIssuesByLabel
- Added external_ref handling in import/export logic
- Follows existing patterns for nullable fields (sql.NullString)

This enables tracking relationships between bd issues and external
systems without requiring changes to existing databases or JSONL files.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-14 02:43:10 -07:00
Steve Yegge
81ab3c3d1b Refactor dependency dirty marking to use shared helper (bd-56)
Replace duplicated dirty-marking logic in AddDependency and
RemoveDependency with a new markIssuesDirtyTx helper function.
This improves code maintainability and ensures consistent behavior.

The Problem:
- AddDependency and RemoveDependency had ~20 lines of duplicated code
- Each manually prepared statements and marked issues dirty
- Violation of DRY principle
- Pattern was fragile if preparation failed

The Fix:
- Created markIssuesDirtyTx() helper in dirty.go
- Takes existing transaction and issue IDs
- Both functions now use: markIssuesDirtyTx(ctx, tx, []string{id1, id2})
- Reduced from 20 lines to 3 lines per function

Benefits:
- Eliminates code duplication (DRY)
- Single source of truth for transaction-based dirty marking
- More readable and maintainable
- Easier to modify behavior in future
- Consistent error messages

Changes:
- internal/storage/sqlite/dirty.go:129-154
  * Add markIssuesDirtyTx() helper function
- internal/storage/sqlite/dependencies.go:115-117, 147-149
  * Replace duplicated code with helper call in both functions

Testing:
- All existing tests pass ✓
- Verified both issues marked dirty with same timestamp ✓
- Dependency add/remove works correctly ✓

Impact:
- Cleaner, more maintainable codebase
- No functional changes, pure refactor
- Foundation for future improvements

Closes bd-56

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-14 00:35:43 -07:00
Steve Yegge
bafb2801c5 Implement incremental JSONL export with dirty issue tracking
Optimize auto-flush by tracking which issues have changed instead of
exporting the entire database on every flush. For large projects with
1000+ issues, this provides significant performance improvements.

Changes:
- Add dirty_issues table to schema with issue_id and marked_at columns
- Implement dirty tracking functions in new dirty.go file:
  * MarkIssueDirty() - Mark single issue as needing export
  * MarkIssuesDirty() - Batch mark multiple issues efficiently
  * GetDirtyIssues() - Query which issues need export
  * ClearDirtyIssues() - Clear tracking after successful export
  * GetDirtyIssueCount() - Monitor dirty issue count
- Update all CRUD operations to mark affected issues as dirty:
  * CreateIssue, UpdateIssue, DeleteIssue
  * AddDependency, RemoveDependency (marks both issues)
  * AddLabel, RemoveLabel, AddEvent
- Modify export to support incremental mode:
  * Add --incremental flag to export only dirty issues
  * Used by auto-flush for performance
  * Full export still available without flag
- Add Storage interface methods for dirty tracking

Performance impact: With incremental export, large databases only write
changed issues instead of regenerating entire JSONL file on every
auto-flush.

Closes bd-39

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-14 00:17:23 -07:00
Steve Yegge
3440899850 Fix code review issues bd-19 through bd-23
- bd-19: Fix import zero-value field handling using JSON presence detection
- bd-20: Add --strict flag for dependency import failures
- bd-21: Simplify getNextID SQL query (reduce params from 4 to 2)
- bd-22: Add validation/warning for malformed issue IDs
- bd-23: Optimize export dependency queries (fix N+1 problem)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-12 15:30:11 -07:00
Steve Yegge
8d3bbbcc52 Implement bd-10: Export/import dependencies in JSONL
Added dependency support to export/import workflow:

Changes:
- Added GetDependencyRecords() to Storage interface to get raw dependency records
- Extended Issue struct with Dependencies field (omitempty for backward compat)
- Modified export.go to populate dependencies for each issue
- Modified import.go to process dependencies in second pass after all issues exist
- All tests pass

Benefits:
- JSONL is now self-contained with full dependency information
- Enables proper collision resolution in future (bd-12+)
- Idempotent imports: existing dependencies are not duplicated
- Forward references handled: dependencies created after all issues exist

Example output:
{
  "id": "bd-10",
  "title": "...",
  "dependencies": [{
    "issue_id": "bd-10",
    "depends_on_id": "bd-9",
    "type": "parent-child",
    "created_at": "...",
    "created_by": "stevey"
  }]
}

Closes bd-10

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-12 15:08:05 -07:00
Steve Yegge
87ed7c8793 Polish for open-source release
Major improvements to code quality, documentation, and CI:

Code Quality:
- Add golangci-lint configuration with 13 linters
- Fix unchecked error returns in export/import/init
- Refactor duplicate scanIssues code
- Add package comments for all packages
- Add const block comments for exported constants
- Configure errcheck to allow idiomatic defer patterns

Documentation:
- Add comprehensive CONTRIBUTING.md with setup, testing, and workflow
- Fix QUICKSTART.md binary name references (beads → bd)
- Correct default database path documentation

CI/CD:
- Add GitHub Actions workflow for tests and linting
- Enable race detection and coverage reporting
- Automated quality checks on all PRs

All tests passing. Lint issues reduced from 117 to 103 (remaining are
idiomatic patterns and test code). Ready for open-source release.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-12 09:41:29 -07:00
Steve Yegge
15afb5ad17 Implement JSONL export/import and shift to text-first architecture
This is a fundamental architectural shift from binary SQLite to JSONL as
the source of truth for git workflows.

## New Features

- `bd export --format=jsonl` - Export issues to JSON Lines format
- `bd import` - Import issues from JSONL (create new, update existing)
- `--skip-existing` flag for import to only create new issues

## Architecture Change

**Before:** Binary SQLite database committed to git
**After:** JSONL text files as source of truth, SQLite as ephemeral cache

Benefits:
- Git-friendly text format with clean diffs
- AI-resolvable merge conflicts (append-only is 95% conflict-free)
- Human-readable issue tracking in git
- No binary merge conflicts

## Documentation

- Updated README with JSONL-first workflow and git hooks
- Added TEXT_FORMATS.md analyzing JSONL vs CSV vs binary
- Updated GIT_WORKFLOW.md with historical context
- .gitignore now excludes *.db, includes .beads/*.jsonl

## Implementation Details

- Export sorts issues by ID for consistent diffs
- Import handles both creates and updates atomically
- Proper handling of pointer fields (EstimatedMinutes)
- All tests passing

## Breaking Changes

- Database files (*.db) should now be gitignored
- Use export/import workflow for git collaboration
- Git hooks recommended for automation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-12 01:17:50 -07:00
Steve Yegge
704515125d Initial commit: Beads issue tracker with security fixes
Core features:
- Dependency-aware issue tracking with SQLite backend
- Ready work detection (issues with no open blockers)
- Dependency tree visualization
- Cycle detection and prevention
- Full audit trail
- CLI with colored output

Security and correctness fixes applied:
- Fixed SQL injection vulnerability in UpdateIssue (whitelisted fields)
- Fixed race condition in ID generation (added mutex)
- Fixed cycle detection to return full paths (not just issue IDs)
- Added cycle prevention in AddDependency (validates before commit)
- Added comprehensive input validation (priority, status, types, etc.)
- Fixed N+1 query in GetBlockedIssues (using GROUP_CONCAT)
- Improved query building in GetReadyWork (proper string joining)
- Fixed P0 priority filter bug (using Changed() instead of value check)

All critical and major issues from code review have been addressed.

🤖 Generated with Claude Code
2025-10-11 20:07:36 -07:00