Skip to content

Commit c953d74

Browse files
Patrick Roebuckclaude
andcommitted
release: Version 2.0.9 - CI passing with all linting fixes
Final release with complete CI/linting fixes: - Ruff linting: All checks pass (production + tests) - Black formatting: All files reformatted to standard - Test-specific exceptions: N806 variable naming allowed This version resolves all CI failures and maintains code quality without changing any functional behavior. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent 636cba6 commit c953d74

File tree

18 files changed

+143
-97
lines changed

18 files changed

+143
-97
lines changed

memdocs/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
Generate machine-friendly docs from code changes without bureaucratic overhead.
55
"""
66

7-
__version__ = "2.0.8"
7+
__version__ = "2.0.9"
88
__author__ = "Patrick Roebuck"
99
__license__ = "Apache-2.0"
1010

memdocs/cli_modules/commands/init_cmd.py

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -91,17 +91,15 @@ def _setup_mcp_infrastructure(cwd: Path) -> None:
9191
"args": ["serve", "--mcp"],
9292
"isBackground": True,
9393
"problemMatcher": [],
94-
"runOptions": {
95-
"runOn": "folderOpen"
96-
},
94+
"runOptions": {"runOn": "folderOpen"},
9795
"presentation": {
9896
"echo": False,
9997
"reveal": "never",
10098
"focus": False,
10199
"panel": "shared",
102100
"showReuseMessage": False,
103-
"clear": False
104-
}
101+
"clear": False,
102+
},
105103
},
106104
{
107105
"label": "Update MemDocs Memory",
@@ -112,8 +110,8 @@ def _setup_mcp_infrastructure(cwd: Path) -> None:
112110
"echo": True,
113111
"reveal": "always",
114112
"focus": False,
115-
"panel": "shared"
116-
}
113+
"panel": "shared",
114+
},
117115
},
118116
{
119117
"label": "Export MemDocs for Cursor",
@@ -124,8 +122,8 @@ def _setup_mcp_infrastructure(cwd: Path) -> None:
124122
"echo": True,
125123
"reveal": "always",
126124
"focus": False,
127-
"panel": "shared"
128-
}
125+
"panel": "shared",
126+
},
129127
},
130128
{
131129
"label": "MemDocs Stats",
@@ -136,20 +134,17 @@ def _setup_mcp_infrastructure(cwd: Path) -> None:
136134
"echo": True,
137135
"reveal": "always",
138136
"focus": True,
139-
"panel": "shared"
140-
}
141-
}
142-
]
137+
"panel": "shared",
138+
},
139+
},
140+
],
143141
}
144142

145143
tasks_file.write_text(json.dumps(tasks_config, indent=2), encoding="utf-8")
146144
out.success(f"Created [green]{tasks_file}[/green]")
147145

148146
# Create settings.json for auto-start
149-
settings_config = {
150-
"task.autoDetect": "on",
151-
"task.allowAutomaticTasks": "on"
152-
}
147+
settings_config = {"task.autoDetect": "on", "task.allowAutomaticTasks": "on"}
153148

154149
# Merge with existing settings if they exist
155150
if settings_file.exists():

memdocs/cli_modules/commands/query_cmd.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
def _get_memory_indexer():
1414
"""Lazy import to avoid circular dependency."""
1515
from memdocs import cli
16+
1617
return cli.MemoryIndexer
1718

1819

memdocs/cli_modules/commands/review_cmd.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ def _is_git_repo() -> bool:
7676
def _get_cli_classes():
7777
"""Lazy import to avoid circular dependency."""
7878
from memdocs import cli
79+
7980
return cli.Extractor, cli.MemoryIndexer, cli.PolicyEngine, cli.Summarizer
8081

8182

@@ -191,9 +192,7 @@ def review(
191192

192193
# Override config with CLI args (with validation)
193194
if max_files:
194-
validated_max_files = ConfigValidator.validate_positive_int(
195-
max_files, "max_files"
196-
)
195+
validated_max_files = ConfigValidator.validate_positive_int(max_files, "max_files")
197196
doc_config.policies.max_files_without_force = validated_max_files
198197
if escalate_on:
199198
# Validate and sanitize escalation rules
@@ -232,7 +231,9 @@ def review(
232231
sys.exit(1)
233232

234233
# Get CLI classes (lazy import)
235-
extractor_class, memory_indexer_class, policy_engine_class, summarizer_class = _get_cli_classes()
234+
extractor_class, memory_indexer_class, policy_engine_class, summarizer_class = (
235+
_get_cli_classes()
236+
)
236237

237238
out.print_header("MemDocs Review")
238239
out.step(f"Reviewing {len(paths)} path(s) for [cyan]{event}[/cyan] event")
@@ -266,7 +267,9 @@ def review(
266267

267268
# Summarize with AI
268269
with out.spinner("Generating documentation with Claude Sonnet 4.5"):
269-
summarizer = summarizer_class(model=doc_config.ai.model, max_tokens=doc_config.ai.max_tokens)
270+
summarizer = summarizer_class(
271+
model=doc_config.ai.model, max_tokens=doc_config.ai.max_tokens
272+
)
270273
doc_index, markdown_summary = summarizer.summarize(context, scope)
271274

272275
out.success("Documentation generated")

memdocs/cli_modules/commands/serve_cmd.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -210,9 +210,7 @@ def serve(
210210
"""
211211
# Check if memory exists
212212
if not docs_dir.exists() and not memory_dir.exists():
213-
out.warning(
214-
"No MemDocs memory found. Run 'memdocs review' first to generate memory."
215-
)
213+
out.warning("No MemDocs memory found. Run 'memdocs review' first to generate memory.")
216214
out.info("Starting server anyway for testing...")
217215

218216
# Daemon mode

memdocs/cli_modules/commands/stats_cmd.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
def _get_memory_indexer():
1515
"""Lazy import to avoid circular dependency."""
1616
from memdocs import cli
17+
1718
return cli.MemoryIndexer
1819

1920

memdocs/embeddings.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,9 +129,7 @@ def chunk_document(text: str, max_tokens: int = 512, overlap: int = 50) -> list[
129129
>>> # Each chunk has <= 512 tokens with 50 token overlap
130130
"""
131131
if max_tokens <= overlap:
132-
raise ValueError(
133-
f"max_tokens ({max_tokens}) must be greater than overlap ({overlap})"
134-
)
132+
raise ValueError(f"max_tokens ({max_tokens}) must be greater than overlap ({overlap})")
135133

136134
# Use cl100k_base encoding (used by OpenAI's text-embedding-ada-002 and similar models)
137135
# This encoding is also suitable for sentence-transformers models as an approximation

memdocs/mcp_server.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ async def serve_mcp() -> None:
257257

258258
# Use secure temporary file for logging
259259
log_file = tempfile.NamedTemporaryFile(
260-
mode='w', prefix='memdocs-mcp-', suffix='.log', delete=False
260+
mode="w", prefix="memdocs-mcp-", suffix=".log", delete=False
261261
)
262262
logging.basicConfig(level=logging.INFO, filename=log_file.name)
263263

memdocs/security.py

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,18 +44,15 @@ def validate_path(path: Path, base_dir: Path | None = None) -> Path:
4444
except ValueError:
4545
raise SecurityError(
4646
f"Attempts to escape base directory '{base_dir}'. Path traversal attacks are not allowed.",
47-
path
47+
path,
4848
)
4949

5050
# Check for suspicious patterns
5151
path_str = str(path)
5252
if ".." in path_str:
5353
# resolve() should handle this, but double-check
5454
if ".." in str(abs_path.relative_to(abs_path.anchor)):
55-
raise SecurityError(
56-
"Contains suspicious '..' traversal sequences",
57-
path
58-
)
55+
raise SecurityError("Contains suspicious '..' traversal sequences", path)
5956

6057
# Check for null bytes (path injection)
6158
if "\x00" in path_str:
@@ -95,7 +92,7 @@ def validate_write_path(path: Path, allowed_dirs: list[Path]) -> Path:
9592
allowed_str = ", ".join(str(d) for d in allowed_dirs)
9693
raise SecurityError(
9794
f"Not within allowed directories: {allowed_str}. Writing to arbitrary locations is not permitted.",
98-
path
95+
path,
9996
)
10097

10198

@@ -313,9 +310,7 @@ def validate_scope_level(scope: str) -> str:
313310
"""
314311
valid_scopes = ["file", "module", "repo"]
315312
if scope not in valid_scopes:
316-
raise ValueError(
317-
f"Invalid scope '{scope}'. Valid scopes: {', '.join(valid_scopes)}"
318-
)
313+
raise ValueError(f"Invalid scope '{scope}'. Valid scopes: {', '.join(valid_scopes)}")
319314
return scope
320315

321316
@staticmethod

memdocs/summarize.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,12 @@ class Summarizer:
102102
103103
Generate the YAML now:"""
104104

105-
def __init__(self, api_key: str | None = None, model: str = "claude-sonnet-4-5-20250929", max_tokens: int = DEFAULT_MAX_TOKENS):
105+
def __init__(
106+
self,
107+
api_key: str | None = None,
108+
model: str = "claude-sonnet-4-5-20250929",
109+
max_tokens: int = DEFAULT_MAX_TOKENS,
110+
):
106111
"""Initialize summarizer.
107112
108113
Args:

0 commit comments

Comments
 (0)