Commit Graph

3478 Commits

Author SHA1 Message Date
Steve Yegge
f1007dc109 feat(list): show pin indicator for pinned issues (bd-18b)
Add pushpin emoji (📌) prefix to pinned issues in bd list output.
Updates all four output paths: daemon/direct modes, compact/long formats.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-19 00:35:48 -08:00
Steve Yegge
b1ba1c5315 feat(storage): add pinned field to issues schema
Add pinned column to the issues table to support persistent context markers
that should not be treated as work items (bd-7h5).

Changes:
- Add pinned column to schema.go CREATE TABLE
- Add migration 023_pinned_column.go for existing databases
- Update all issue queries to include pinned column
- Update scanIssues and scanIssuesWithDependencyType to handle pinned field
- Add Pinned field to types.Issue struct with JSON serialization
- Fix migrations_test.go to include pinned in legacy schema test

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-19 00:08:32 -08:00
Steve Yegge
8e6462d44c test(merge): add test for both sides adding same dependency
Ensures no duplicates when left and right independently add the same
dependency (not in base). Left version is preferred.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 23:24:31 -08:00
Steve Yegge
5ad1c80f7e fix(merge): proper 3-way merge for dependencies - removals win (bd-ndye)
CRITICAL: Fixed dependency resurrection bug that caused removed/orphaned
dependencies to keep coming back after sync.

Root cause: mergeDependencies() was doing a union (additive only) and
completely ignored the base parameter. This meant any dependency present
in either left or right would be included, even if it was intentionally
removed.

Fix: Proper 3-way merge where REMOVALS ARE AUTHORITATIVE:
- If dep was in base and removed by left OR right → stays removed
- If dep wasn't in base and added by left OR right → included
- If dep was in base and both still have it → included

This fixes months of issues with orphaned parent-child relationships
being resurrected during git sync operations.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 23:20:49 -08:00
Steve Yegge
45bb38770a chore: Bump version to 0.30.6
Updated all component versions:
- bd CLI: 0.30.5 → 0.30.6
- Plugin: 0.30.5 → 0.30.6
- MCP server: 0.30.5 → 0.30.6
- npm package: 0.30.5 → 0.30.6

Changes in this release:
- bd graph command shows dependency counts using subgraph formatting (bd-6v2)
- types.StatusPinned for persistent beads that survive cleanup
2025-12-18 22:46:14 -08:00
Steve Yegge
f4f51da007 feat(types): add StatusPinned for persistent beads (bd-6v2)
Add pinned status for beads that should stay open indefinitely:
- Add StatusPinned constant and update IsValid()
- Add PinnedIssues count to Statistics struct
- Protect pinned issues from bd close (requires --force)
- Show pinned count in bd stats output

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 21:55:54 -08:00
Charles P. Cross
8fa1eda207 fix(lint): add batch_ops.go to G201 exclusion
The batch_ops.go file uses fmt.Sprintf to build SQL queries with IN
clause expansion, same pattern as dependencies.go. The placeholders
are parameterized (?) making this safe, but gosec G201 flags it.

Add batch_ops.go to the existing G201 exclusion path regex.

This fixes CI lint failures affecting multiple open PRs.

Co-authored-by: Charles P. Cross <cpdata@users.noreply.github.com>
2025-12-18 21:28:20 -08:00
Charles P. Cross
77d8a995e8 feat(graph): use subgraph to display dependency counts
Restore the subgraph parameter in renderGraph (previously marked as
unused with _) and use it to display meaningful dependency information:

- Add computeDependencyCounts() to calculate blocks/blocked-by counts
- Add renderNodeBoxWithDeps() to render nodes with dependency info
- Show "blocks:N" when an issue blocks N other issues
- Show "needs:N" when an issue depends on N other issues
- Add dependency summary showing total blocking relationships

This makes the graph visualization more informative by showing how
issues relate to each other in the dependency chain.

Tests added:
- TestComputeDependencyCounts: verifies dependency counting logic
- TestRenderNodeBoxWithDeps: verifies box rendering with dep info

Co-authored-by: Charles P. Cross <cpdata@users.noreply.github.com>
2025-12-18 20:35:00 -08:00
Christian Catalan
cb5ebfc667 fix(init): update output to show hash-based ID format
The bd init and quickstart commands displayed outdated ID format
examples showing sequential IDs (prefix-1, prefix-2, ...) but beads
has used content-based hash IDs since bd-8e05.

Updated output now correctly shows:
  Issues will be named: prefix-<hash> (e.g., prefix-a3f2dd)

This matches the actual GenerateHashID implementation in
internal/types/id_generator.go which generates 6-8 char hex hashes.



test(init): update test expectations to match hash-based ID format

Tests were checking for the old sequential format (prefix-1, prefix-2)
but the code now outputs hash-based format (prefix-<hash>).

Co-authored-by: cc-vps <crcatala+vps@gmail.com>
2025-12-18 20:33:25 -08:00
Charles P. Cross
2b031b9441 fix(worktree): add -f flag to handle missing but registered state (#609)
Problem:
When the daemon auto-sync runs with --auto-commit --auto-push, the sync
branch pull operation consistently fails with:

  fatal: '.git/beads-worktrees/beads-metadata' is a missing but already
  registered worktree; use 'add -f' to override, or 'prune' or 'remove'
  to clear

This occurs because:
1. Daemon creates worktree at .git/beads-worktrees/<branch>
2. Git registers it in .git/worktrees/<branch>
3. After the operation, worktree contents are removed
4. Git registration persists, pointing to the now-empty path
5. Subsequent CreateBeadsWorktree calls fail because os.Stat() returns
   error (path missing), so no cleanup happens, then git worktree add
   fails because git still has it registered

Root cause:
The git worktree add commands in CreateBeadsWorktree() did not use the
-f (force) flag, which is needed to override the "missing but already
registered" state.

Solution:
Add -f flag to both git worktree add commands (for existing branch and
new branch cases). Per git documentation, -f overrides the safeguard
that prevents creating a worktree when the path is already registered
but missing.

The existing git worktree prune call (line 30-32) was intended to handle
this, but it runs before the path check and may not always clear the
registration in time. The -f flag provides a robust fallback.

Testing:
- All existing worktree tests pass
- Added regression test TestCreateBeadsWorktree_MissingButRegistered
  that simulates the exact issue #609 scenario

Fixes #609

Co-authored-by: Charles P. Cross <cpdata@users.noreply.github.com>
2025-12-18 20:29:32 -08:00
Steve Yegge
99e261c643 chore: gitignore Gas Town state.json
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 20:23:23 -08:00
Steve Yegge
3c04b763fd feat: add merge-request issue type for refinery processing
Add TypeMergeRequest as a valid issue type for tracking merge queue
entries. This enables the refinery to track merge requests with
structured metadata (branch, target, source_issue, worker, rig).

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 20:09:46 -08:00
Steve Yegge
9dc34da64a fix(storage): add batch ID conflict detection and fix schema indexes
- Add checkForExistingIDs function to detect duplicate IDs within batch
  and conflicts with existing database entries before insert
- Remove thread_id index creation from schema.go since thread_id column
  is added by migration 020_edge_consolidation.go

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 19:11:50 -08:00
Steve Yegge
2ea1b74f43 Merge beads-sync into main 2025-12-18 18:58:35 -08:00
Steve Yegge
f7c746adb9 feat: auto-protect forks from committing upstream issue database
When bd detects it's running in a fork (origin != steveyegge/beads),
automatically add .beads/issues.jsonl to .git/info/exclude.

This prevents contributors from accidentally including issue database
changes in their PRs. The exclusion is:
- Per-clone (doesn't modify tracked files
- One-time setup (checks if already excluded)
- Silent (only logs in debug mode)

Maintainers (origin = steveyegge/beads) are not affected.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
EOF
)
2025-12-18 18:56:59 -08:00
Steve Yegge
d2b9554651 bd sync: 2025-12-18 18:33:29 2025-12-18 18:33:29 -08:00
Aarya Reddy
efdfbac504 feat(mcp): consolidate admin tools to reduce token overhead (#634)
Consolidate 6 admin MCP tools into single 'admin' tool with action parameter for 79% token reduction.
2025-12-18 18:32:54 -08:00
Steve Yegge
1f4b55dacb Merge main into fix/ci-errors, resolve graph.go conflict 2025-12-18 18:30:47 -08:00
Andrei Onel
9382aa34fa Update CLI reference with new --body-file options (#627)
Documentation update for --body-file option
2025-12-18 18:25:09 -08:00
Steve Yegge
e0872ebbd0 fix(test): remove incorrect duplicate ID rollback test
The test expected CreateIssues to error on duplicate IDs, but the
implementation uses INSERT OR IGNORE which silently skips duplicates.
This is intentional behavior needed for JSONL import scenarios.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 18:24:28 -08:00
matt wilkie
fb16e504e6 Fix tests (bd-6ss and sub-issues) (#626)
Test coverage improvements for bd-6ss. Fixing failing test assumption in follow-up commit.
2025-12-18 18:23:30 -08:00
Charles P. Cross
5316559cf6 test(graph): add tests for graph utility functions
Add comprehensive tests for the new graph.go functions to meet
coverage threshold after rebase introduced 405 new lines:

- TestTruncateTitle: tests rune-safe title truncation
- TestPadRight: tests rune-safe string padding
- TestRenderNodeBox: tests ASCII box rendering for all status types
- TestComputeLayout: tests topological layout computation with
  dependencies

These tests cover the pure utility functions and basic graph layout
logic, bringing coverage from 44.7% to 45.1%.
2025-12-18 17:56:24 -05:00
Charles P. Cross
2b0a8cecdb fix(lint): mark unused subgraph parameter in renderGraph
The subgraph parameter was passed to renderGraph but not used in the
function body, causing an unparam lint error. Replace with _ to
indicate intentional non-use.
2025-12-18 17:47:03 -05:00
Charles P. Cross
ba8beb53b3 test(coverage): add tests to meet 45% CI threshold
Add comprehensive test coverage for previously untested functions:

internal/debug/debug_test.go:
- TestSetVerbose: tests SetVerbose() and its effect on Enabled()
- TestSetQuietAndIsQuiet: tests SetQuiet() and IsQuiet() functions
- TestPrintNormal: tests quiet mode suppression of normal output
- TestPrintlnNormal: tests quiet mode suppression of println output

internal/export/config_test.go (new file):
- TestLoadConfig: comprehensive tests for LoadConfig() including:
  - Default values when no config exists
  - Loading custom policies (both regular and auto-export)
  - Loading retry attempts, backoff, skip encoding errors, write manifest
  - Handling invalid/malformed config values gracefully

internal/export/policy_test.go:
- TestErrorPolicyString: tests String() method on ErrorPolicy
- TestNewManifest: tests manifest creation with proper defaults
- TestWriteManifest: tests manifest file writing and error handling

These tests bring coverage from 44.8% to 45.0%, meeting the CI threshold.
2025-12-18 17:45:49 -05:00
Charles P. Cross
cb59bb3ec8 fix(ci): resolve lint and test failures
Fix two CI failures that were blocking main:

1. Lint error in cmd/bd/onboard.go:126
   - Unchecked fmt.Fprintf return value
   - Fixed by explicitly ignoring with _, _

2. Test failures in internal/storage/sqlite
   - TestCreateIssues/duplicate_ID_error was passing but
     TestCreateIssuesRollback/rollback_on_conflict_with_existing_ID failed
   - Root cause: CreateIssues used INSERT OR IGNORE which silently
     ignored duplicate IDs instead of returning an error
   - Fixed by adding duplicate ID detection in EnsureIDs():
     a) Check for duplicates within the batch
     b) Check for conflicts with existing database IDs

Both fixes are minimal and targeted to unblock CI.
2025-12-18 17:45:49 -05:00
Steve Yegge
7f9ee3d1c4 fix(graph): traverse all dependency types, not just parent-child
The graph command now shows issues connected via any dependency type
(blocks, parent-child, etc.), not just parent-child relationships.

This makes bd graph useful for epics where children are connected via
blocks dependencies rather than hierarchical parent-child.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 13:51:26 -08:00
Steve Yegge
736389b6b7 bd sync: 2025-12-18 13:47:56 2025-12-18 13:47:56 -08:00
Steve Yegge
a89de1ac8b feat(graph): add bd graph command for ASCII DAG visualization
New command to visualize issue dependency graphs:
- Layered layout (Sugiyama-style) shows execution order
- Status coloring (open/in_progress/blocked/closed)
- Works with epics to show full subgraph
- Layer 0 = ready tasks (no blockers)

Usage: bd graph <issue-id>

Part of bd-r6a workflow system redesign.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 13:47:45 -08:00
Steve Yegge
125e36d529 refactor(onboard): simplify to minimal snippet pointing to bd prime
bd onboard now outputs a ~10 line snippet for AGENTS.md that points to
"bd prime" for full workflow context. This replaces the previous ~200
line static content that:

- Bloated AGENTS.md with instructions that loaded every session
- Got stale when bd was upgraded
- Wasted tokens when beads was not actively being used

The new approach:
- AGENTS.md gets minimal pointer (~20 tokens vs ~2000)
- bd prime provides dynamic, always-current workflow details
- Hooks auto-inject bd prime at session start

Also removes the --output flag for BD_GUIDE.md generation (obsolete).

Closes bd-gxq
Addresses GH#604

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 11:48:02 -08:00
Steve Yegge
acb3bbf7b6 bd sync: 2025-12-18 11:47:46 2025-12-18 11:47:46 -08:00
Steve Yegge
ecd46a6d6e Add tests for Decision 004 Phase 4 thread traversal functions
Tests findRepliesTo() and findReplies() helper functions in cmd/bd/show.go
that traverse message threads via dependencies. Covers:
- 3-message linear thread chain traversal (up and down)
- Thread root finding via repeated findRepliesTo() calls
- Branching threads (one message with multiple replies)
- Empty/standalone messages
- Nonexistent issue IDs
- Verification that only replies-to deps are followed

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 11:30:26 -08:00
Steve Yegge
8b581d6de3 bd sync: 2025-12-18 11:29:45 2025-12-18 11:29:45 -08:00
Steve Yegge
1951a2c5fe bd sync: 2025-12-18 11:28:36 2025-12-18 11:28:36 -08:00
Steve Yegge
6087cd438b fix(storage): race condition when reconnect closes db mid-query (GH#607)
Change reconnectMu from sync.Mutex to sync.RWMutex so read operations
can hold RLock during database access. This prevents reconnect() from
closing the connection while queries are in progress.

- GetIssue and SearchIssues now hold RLock during database operations
- Close() acquires write lock to coordinate with reconnect
- Add TestConcurrentReadsWithReconnect to verify the fix

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 11:28:13 -08:00
Steve Yegge
e0d8abe8c3 Add tests for Decision 004 Phase 4 edge schema consolidation
Tests added:
- TestTransactionAddDependency_RelatesTo: bidirectional relates-to in txn
- TestTransactionAddDependency_RepliesTo: thread_id preserved in txn
- TestRelateCommand: bd relate/unrelate CLI commands
- TestRelateCommandInit: command registration

Provides regression coverage for transaction.go fixes and relates-to behavior.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 11:25:17 -08:00
Steve Yegge
4981e84e86 Fix transaction.go AddDependency to match dependencies.go (Decision 004)
Code review found three issues where transaction.go diverged from the
main dependencies.go implementation:

1. Add relates-to exemption from cycle detection - bidirectional
   relationships are valid and should not trigger cycle errors

2. Add metadata and thread_id fields to INSERT - required for
   replies-to threading to work in transaction context

3. Update error message to match dependencies.go wording

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 11:15:16 -08:00
Steve Yegge
ee3d51fc21 Merge pull request #624 from marcodelpin/fix/schema-probe-dependencies-columns
fix(schema): add metadata and thread_id to dependencies expectedSchema
2025-12-18 11:15:04 -08:00
Steve Yegge
1b332ad10e Merge pull request #620 from qmx/fix-nix-vendor-hash
fix: update nix vendorHash for Go dependencies
2025-12-18 11:15:01 -08:00
Steve Yegge
332c9b9b8f Merge pull request #619 from qmx/add-push-configuration
feat: add no-push config to disable automatic git push
2025-12-18 11:14:56 -08:00
Steve Yegge
5981e6e752 bd sync: 2025-12-18 11:13:50 2025-12-18 11:13:50 -08:00
Steve Yegge
001ae4473f bd sync: 2025-12-18 11:09:54 2025-12-18 11:09:54 -08:00
Steve Yegge
8b0cd1ec66 refactor(import): remove redundant pre-batch deduplication layer
The early ID deduplication in the main loop (seenIDs check) already
prevents duplicate IDs from reaching newIssues. The pre-batch
deduplication was dead code that could never fire.

Keeping two layers:
1. Early dedup in main loop - catches duplicates in JSONL input
2. INSERT OR IGNORE at DB level - safety net for all code paths

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 11:09:26 -08:00
Steve Yegge
075a60f2b4 Merge pull request #625 from marcodelpin/fix/import-dedupe-by-id
fix(import): handle duplicate issue IDs in JSONL files gracefully
2025-12-18 11:08:32 -08:00
Marco Del Pin
973ecfc9e6 fix(lint): resolve golangci-lint errors for clean CI
Fixes 5 linting issues to allow PR checks to pass:
1. hooks.go: Explicitly ignore error in async goroutine
2. 022_drop_edge_columns.go: Handle deferred PRAGMA error
3. flags.go: Add nosec comment for validated file path
4. create_form.go: Fix American spelling (canceled vs cancelled)
5. create_form.go: Explicitly mark cmd parameter as required by cobra
These are pre-existing issues in the codebase, fixed here to
enable clean CI for the import deduplication fix.
🤖 Generated with Claude Code
2025-12-18 20:06:41 +01:00
Marco Del Pin
ef99f0700c fix(lint): resolve golangci-lint errors for clean CI
Fixes 5 linting issues to allow PR checks to pass:
1. hooks.go: Explicitly ignore error in async goroutine
2. 022_drop_edge_columns.go: Handle deferred PRAGMA error
3. flags.go: Add nosec comment for validated file path
4. create_form.go: Fix American spelling (canceled vs cancelled)
5. create_form.go: Explicitly mark cmd parameter as required by cobra
These are pre-existing issues in the codebase, fixed here to
enable clean CI for the schema probe fix.
🤖 Generated with Claude Code
2025-12-18 20:05:13 +01:00
Marco Del Pin
d5e569443d fix(schema): add metadata and thread_id to dependencies expectedSchema
**Problem:**
Schema compatibility probe was failing with "no such column: thread_id"
error when opening databases created before v0.30.5, even after running
migrations. This caused database initialization to fail.
**Root Cause:**
The migration 020_edge_consolidation.go correctly adds the metadata and
thread_id columns to the dependencies table, but schema_probe.go's
expectedSchema map was missing these columns in its validation list.
This caused verifySchemaCompatibility() to fail even though:
1. The columns existed in the actual schema (schema.go:51-52)
2. Migration 020 would add them if missing
3. The database was otherwise valid
**Solution:**
Updated expectedSchema in schema_probe.go to include "metadata" and
"thread_id" in the dependencies table column list. This aligns the schema
probe expectations with the actual schema definition and migration 020
behavior.
**Testing:**
 Tested on 5 databases across version range pre-0.17.5 → v0.30.5
   - All migrations completed successfully
   - Schema probe passes after migration
   - All bd commands work correctly
 No regressions in fresh database initialization
**Impact:**
- Fixes database initialization errors for users upgrading from v0.30.3
- No breaking changes or data migrations required
- Compatible with all existing databases
- Enables smooth migration path for all database versions
Fixes database migration issues reported in v0.30.5 upgrade path.
🤖 Generated with Claude Code
2025-12-18 19:32:26 +01:00
Marco Del Pin
dba9bb91c3 fix(import): handle duplicate issue IDs in JSONL files gracefully
Implements three-layer deduplication strategy to prevent UNIQUE
constraint errors during import:
1. Early deduplication during processing (importer.go)
2. Pre-batch deduplication (importer.go)
3. INSERT OR IGNORE with explicit error handling (issues.go)
**Problem:**
JSONL files with duplicate issue IDs caused import failures:
  Import failed: UNIQUE constraint failed: issues.id
**Root Cause:**
- Go SQLite driver returns errors even with INSERT OR IGNORE
- Only content hash was deduplicated, not IDs
- Multiple code paths affected (insertIssue, insertIssues)
**Solution:**
Layer 1: Early deduplication by ID in upsertIssues (lines 489-502)
Layer 2: Pre-batch deduplication (lines 713-726)
Layer 3: INSERT OR IGNORE + isUniqueConstraintError() helper
**Testing:**
- Multiple production databases tested
- 9 duplicates handled successfully
- 100% success rate on v0.30.5 databases
- Zero UNIQUE constraint errors
**Impact:**
- Enables importing JSONL with duplicate IDs
- Duplicate count shown in import statistics
- No breaking changes, backward compatible
🤖 Generated with Claude Code
2025-12-18 19:26:29 +01:00
Steve Yegge
d5a115a347 bd sync: 2025-12-18 02:49:16 2025-12-18 02:49:16 -08:00
Steve Yegge
51b3d3975f bd sync: 2025-12-18 02:48:19 2025-12-18 02:48:19 -08:00
Steve Yegge
7c8b69f5b3 Phase 4: Remove deprecated edge fields from Issue struct (Decision 004)
This is the final phase of the Edge Schema Consolidation. It removes
the deprecated edge fields (RepliesTo, RelatesTo, DuplicateOf, SupersededBy)
from the Issue struct and all related code.

Changes:
- Remove edge fields from types.Issue struct
- Remove edge field scanning from queries.go and transaction.go
- Update graph_links_test.go to use dependency API exclusively
- Update relate.go to use AddDependency/RemoveDependency
- Update show.go with helper functions for thread traversal via deps
- Update mail_test.go to verify thread links via dependencies
- Add migration 022 to drop columns from issues table
- Fix cycle detection to allow bidirectional relates-to links
- Fix migration 022 to disable foreign keys before table recreation

All edge relationships now use the dependencies table exclusively.
The old Issue fields are fully removed.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 02:48:13 -08:00