Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .jules/bolt.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,7 @@
## 2025-07-17 - Grouped I/O in scripts/init.py
**Learning:** Performing multiple consecutive file reads/writes on the same files (`pyproject.toml`, `mkdocs.yml`) causes redundant disk I/O overhead.
**Action:** Group file modifications by file path to perform exactly one read and one write operation per file.

## 2025-07-17 - Batch Git Config Subprocess Invocations in scripts/init.py
**Learning:** Sequential `subprocess` querying of Git configuration parameters (`user.name`, `user.email`, `github.user`) during interactive CLI initialization is slow (~3x overhead). Running a single batch subprocess query via `git config --get-regexp` and caching the result reduces the initialization delay significantly. Additionally, using an initialization flag prevents redundant subprocess calls when all configs are missing (e.g. in empty or CI environments).
**Action:** Cache git configuration queries globally on first use with an explicit initialization flag.
7 changes: 6 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,9 @@ Every field in a Pydantic model or pydantic-settings class must be documented us
from uuid import uuid4
from pydantic import BaseModel, Field


class Item(BaseModel, populate_by_name=True, alias_generator=to_camel):
id: str = Field(description="Unique item identifier.", default_factory=lambda:str(uuid4()))
id: str = Field(description="Unique item identifier.", default_factory=lambda: str(uuid4()))
name: str = Field(description="Human-readable item name.")
```

Expand All @@ -167,6 +168,7 @@ from uuid import uuid4
from pydantic import BaseModel, Field
from pydantic.alias_generators import to_camel


class Item(BaseModel, populate_by_name=True, alias_generator=to_camel):
item_id: str = Field(description="Unique item identifier.", default_factory=str(uuid4()))
# Accepts {"itemId": "..."} from JSON; attribute is item.item_id
Expand All @@ -181,8 +183,11 @@ Do not use `model_config = ConfigDict(...)` or `model_config = SettingsConfigDic
```python
# Good
class Item(BaseModel, extra="allow", populate_by_name=True, alias_generator=to_camel): ...


class Settings(BaseSettings, case_sensitive=False): ...


# Bad
class Item(BaseModel):
model_config = ConfigDict(extra="allow")
Expand Down
27 changes: 23 additions & 4 deletions scripts/init.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,31 @@

from click import ClickException, UsageError, command, confirm, echo, option, secho

_GIT_CONFIG_CACHE: dict[str, str] = {}
_GIT_CONFIG_INITIALIZED: bool = False


def _get_git_config(key: str) -> str:
try:
return subprocess.check_output(["/usr/bin/git", "config", key], text=True, timeout=5).strip() # noqa: S603
except (subprocess.CalledProcessError, FileNotFoundError, subprocess.TimeoutExpired):
return ""
global _GIT_CONFIG_CACHE, _GIT_CONFIG_INITIALIZED
if not _GIT_CONFIG_INITIALIZED:
_GIT_CONFIG_INITIALIZED = True
try:
# Batch query user/github git config keys in a single subprocess call to optimize initialization startup
res = subprocess.run(
["/usr/bin/git", "config", "--get-regexp", "^(user\\.name|user\\.email|github\\.user)$"],
capture_output=True,
text=True,
timeout=5,
check=False,
) # noqa: S603
if res.returncode == 0:
for line in res.stdout.strip().splitlines():
if " " in line:
k, v = line.split(" ", 1)
_GIT_CONFIG_CACHE[k] = v.strip()
except (subprocess.SubprocessError, FileNotFoundError):
pass
return _GIT_CONFIG_CACHE.get(key, "")


def _get_default_github() -> str:
Expand Down