buildlog 0.6.1__py3-none-any.whl → 0.8.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- buildlog/__init__.py +1 -1
- buildlog/cli.py +589 -44
- buildlog/confidence.py +27 -0
- buildlog/core/__init__.py +12 -0
- buildlog/core/bandit.py +699 -0
- buildlog/core/operations.py +499 -11
- buildlog/distill.py +80 -1
- buildlog/engine/__init__.py +61 -0
- buildlog/engine/bandit.py +23 -0
- buildlog/engine/confidence.py +28 -0
- buildlog/engine/embeddings.py +28 -0
- buildlog/engine/experiments.py +619 -0
- buildlog/engine/types.py +31 -0
- buildlog/llm.py +461 -0
- buildlog/mcp/server.py +12 -6
- buildlog/mcp/tools.py +166 -13
- buildlog/render/__init__.py +19 -2
- buildlog/render/claude_md.py +74 -26
- buildlog/render/continue_dev.py +102 -0
- buildlog/render/copilot.py +100 -0
- buildlog/render/cursor.py +105 -0
- buildlog/render/tracking.py +20 -1
- buildlog/render/windsurf.py +95 -0
- buildlog/seeds.py +41 -0
- buildlog/skills.py +69 -6
- {buildlog-0.6.1.data → buildlog-0.8.0.data}/data/share/buildlog/copier.yml +0 -4
- buildlog-0.8.0.data/data/share/buildlog/template/buildlog/_TEMPLATE_QUICK.md +21 -0
- buildlog-0.8.0.dist-info/METADATA +151 -0
- buildlog-0.8.0.dist-info/RECORD +54 -0
- buildlog-0.6.1.dist-info/METADATA +0 -490
- buildlog-0.6.1.dist-info/RECORD +0 -41
- {buildlog-0.6.1.data → buildlog-0.8.0.data}/data/share/buildlog/post_gen.py +0 -0
- {buildlog-0.6.1.data → buildlog-0.8.0.data}/data/share/buildlog/template/buildlog/.gitkeep +0 -0
- {buildlog-0.6.1.data → buildlog-0.8.0.data}/data/share/buildlog/template/buildlog/2026-01-01-example.md +0 -0
- {buildlog-0.6.1.data → buildlog-0.8.0.data}/data/share/buildlog/template/buildlog/BUILDLOG_SYSTEM.md +0 -0
- {buildlog-0.6.1.data → buildlog-0.8.0.data}/data/share/buildlog/template/buildlog/_TEMPLATE.md +0 -0
- {buildlog-0.6.1.data → buildlog-0.8.0.data}/data/share/buildlog/template/buildlog/assets/.gitkeep +0 -0
- {buildlog-0.6.1.dist-info → buildlog-0.8.0.dist-info}/WHEEL +0 -0
- {buildlog-0.6.1.dist-info → buildlog-0.8.0.dist-info}/entry_points.txt +0 -0
- {buildlog-0.6.1.dist-info → buildlog-0.8.0.dist-info}/licenses/LICENSE +0 -0
buildlog/distill.py
CHANGED
|
@@ -8,6 +8,7 @@ __all__ = [
|
|
|
8
8
|
"distill_all",
|
|
9
9
|
"format_output",
|
|
10
10
|
"parse_improvements",
|
|
11
|
+
"parse_improvements_llm",
|
|
11
12
|
"parse_date_from_filename",
|
|
12
13
|
"iter_buildlog_entries",
|
|
13
14
|
]
|
|
@@ -19,7 +20,10 @@ from collections.abc import Iterator
|
|
|
19
20
|
from dataclasses import dataclass, field
|
|
20
21
|
from datetime import date, datetime, timezone
|
|
21
22
|
from pathlib import Path
|
|
22
|
-
from typing import Final, Literal, TypedDict
|
|
23
|
+
from typing import TYPE_CHECKING, Final, Literal, TypedDict
|
|
24
|
+
|
|
25
|
+
if TYPE_CHECKING:
|
|
26
|
+
from buildlog.llm import ExtractedRule, LLMBackend
|
|
23
27
|
|
|
24
28
|
logger = logging.getLogger(__name__)
|
|
25
29
|
|
|
@@ -191,6 +195,36 @@ def parse_improvements(content: str) -> dict[str, list[str]]:
|
|
|
191
195
|
return result
|
|
192
196
|
|
|
193
197
|
|
|
198
|
+
def parse_improvements_llm(content: str, backend: LLMBackend) -> list[ExtractedRule]:
|
|
199
|
+
"""Extract improvements using an LLM backend for richer extraction.
|
|
200
|
+
|
|
201
|
+
Sends the Improvements section to the LLM for structured extraction
|
|
202
|
+
of rules with severity, scope, applicability, and defensibility fields.
|
|
203
|
+
|
|
204
|
+
Args:
|
|
205
|
+
content: The full markdown content of a buildlog entry.
|
|
206
|
+
backend: An LLM backend implementing the LLMBackend protocol.
|
|
207
|
+
|
|
208
|
+
Returns:
|
|
209
|
+
List of ExtractedRule objects with rich metadata.
|
|
210
|
+
"""
|
|
211
|
+
# Extract the Improvements section
|
|
212
|
+
improvements_match = re.search(
|
|
213
|
+
r"^##\s+Improvements\s*\n(.*?)(?=^#{1,2}\s|\Z)",
|
|
214
|
+
content,
|
|
215
|
+
re.MULTILINE | re.DOTALL,
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
if not improvements_match:
|
|
219
|
+
return []
|
|
220
|
+
|
|
221
|
+
improvements_text = improvements_match.group(1).strip()
|
|
222
|
+
if not improvements_text:
|
|
223
|
+
return []
|
|
224
|
+
|
|
225
|
+
return backend.extract_rules(improvements_text)
|
|
226
|
+
|
|
227
|
+
|
|
194
228
|
def parse_date_from_filename(filename: str) -> str | None:
|
|
195
229
|
"""Extract date from buildlog filename (YYYY-MM-DD-slug.md format)."""
|
|
196
230
|
match = re.match(r"^(\d{4}-\d{2}-\d{2})-", filename)
|
|
@@ -290,6 +324,7 @@ def distill_all(
|
|
|
290
324
|
buildlog_dir: Path,
|
|
291
325
|
since: date | None = None,
|
|
292
326
|
category_filter: str | None = None,
|
|
327
|
+
llm: bool = False,
|
|
293
328
|
) -> DistillResult:
|
|
294
329
|
"""Parse all buildlog entries and aggregate patterns.
|
|
295
330
|
|
|
@@ -297,10 +332,23 @@ def distill_all(
|
|
|
297
332
|
buildlog_dir: Path to the buildlog directory.
|
|
298
333
|
since: If provided, only include entries from this date onward.
|
|
299
334
|
category_filter: If provided, only include patterns from this category.
|
|
335
|
+
llm: If True and an LLM backend is available, use LLM extraction.
|
|
336
|
+
Falls back to regex on failure or if no backend is available.
|
|
300
337
|
|
|
301
338
|
Returns:
|
|
302
339
|
DistillResult with aggregated patterns and statistics.
|
|
303
340
|
"""
|
|
341
|
+
# Resolve LLM backend if requested
|
|
342
|
+
llm_backend: LLMBackend | None = None
|
|
343
|
+
if llm:
|
|
344
|
+
from buildlog.llm import get_llm_backend
|
|
345
|
+
|
|
346
|
+
llm_backend = get_llm_backend(buildlog_dir=buildlog_dir)
|
|
347
|
+
if llm_backend is None:
|
|
348
|
+
logger.warning(
|
|
349
|
+
"--llm requested but no LLM provider available, using regex fallback"
|
|
350
|
+
)
|
|
351
|
+
|
|
304
352
|
patterns: dict[str, list[PatternDict]] = {cat: [] for cat in CATEGORIES}
|
|
305
353
|
by_month: dict[str, int] = {}
|
|
306
354
|
entry_count = 0
|
|
@@ -318,6 +366,37 @@ def distill_all(
|
|
|
318
366
|
month_key = _extract_month_key(date_str)
|
|
319
367
|
by_month[month_key] = by_month.get(month_key, 0) + 1
|
|
320
368
|
|
|
369
|
+
# Try LLM extraction first, fall back to regex
|
|
370
|
+
if llm_backend is not None:
|
|
371
|
+
try:
|
|
372
|
+
extracted = parse_improvements_llm(content, llm_backend)
|
|
373
|
+
if extracted:
|
|
374
|
+
# Convert ExtractedRule objects to standard PatternDict format
|
|
375
|
+
for rule in extracted:
|
|
376
|
+
cat = (
|
|
377
|
+
rule.category
|
|
378
|
+
if rule.category in CATEGORIES
|
|
379
|
+
else "architectural"
|
|
380
|
+
)
|
|
381
|
+
if cat not in patterns:
|
|
382
|
+
patterns[cat] = []
|
|
383
|
+
patterns[cat].append(
|
|
384
|
+
PatternDict(
|
|
385
|
+
insight=rule.rule,
|
|
386
|
+
source=str(entry_path),
|
|
387
|
+
date=date_str,
|
|
388
|
+
context=context,
|
|
389
|
+
)
|
|
390
|
+
)
|
|
391
|
+
continue # Skip regex if LLM succeeded
|
|
392
|
+
except Exception as e:
|
|
393
|
+
logger.warning(
|
|
394
|
+
"LLM extraction failed for %s, falling back to regex: %s",
|
|
395
|
+
entry_path,
|
|
396
|
+
e,
|
|
397
|
+
)
|
|
398
|
+
|
|
399
|
+
# Regex fallback (default behavior)
|
|
321
400
|
try:
|
|
322
401
|
improvements = parse_improvements(content)
|
|
323
402
|
except re.error as e:
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"""Buildlog Engine — agent-agnostic core for rule learning and experiment tracking.
|
|
2
|
+
|
|
3
|
+
This package provides the pure algorithmic core of buildlog without any
|
|
4
|
+
CLI, copier, or agent-specific rendering dependencies. Use it when you
|
|
5
|
+
want Thompson Sampling bandits, confidence scoring, embedding similarity,
|
|
6
|
+
or experiment tracking in your own tools.
|
|
7
|
+
|
|
8
|
+
Usage:
|
|
9
|
+
from buildlog.engine import ThompsonSamplingBandit, BetaParams
|
|
10
|
+
from buildlog.engine import calculate_confidence, ConfidenceMetrics
|
|
11
|
+
from buildlog.engine import start_session, end_session, log_mistake
|
|
12
|
+
from buildlog.engine.types import Skill, Session, Mistake, RewardEvent
|
|
13
|
+
|
|
14
|
+
Install:
|
|
15
|
+
pip install buildlog # engine is part of the base package
|
|
16
|
+
pip install buildlog[engine] # same thing — documents the namespace
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from buildlog.engine.bandit import BetaParams, ThompsonSamplingBandit
|
|
20
|
+
from buildlog.engine.confidence import (
|
|
21
|
+
ConfidenceConfig,
|
|
22
|
+
ConfidenceMetrics,
|
|
23
|
+
calculate_confidence,
|
|
24
|
+
get_confidence_tier,
|
|
25
|
+
merge_confidence_metrics,
|
|
26
|
+
)
|
|
27
|
+
from buildlog.engine.experiments import (
|
|
28
|
+
end_session,
|
|
29
|
+
experiment_report,
|
|
30
|
+
get_rewards,
|
|
31
|
+
log_mistake,
|
|
32
|
+
log_reward,
|
|
33
|
+
session_metrics,
|
|
34
|
+
start_session,
|
|
35
|
+
)
|
|
36
|
+
from buildlog.engine.types import Mistake, RewardEvent, Session, Skill
|
|
37
|
+
|
|
38
|
+
__all__ = [
|
|
39
|
+
# Bandit
|
|
40
|
+
"ThompsonSamplingBandit",
|
|
41
|
+
"BetaParams",
|
|
42
|
+
# Confidence
|
|
43
|
+
"calculate_confidence",
|
|
44
|
+
"get_confidence_tier",
|
|
45
|
+
"merge_confidence_metrics",
|
|
46
|
+
"ConfidenceMetrics",
|
|
47
|
+
"ConfidenceConfig",
|
|
48
|
+
# Experiments
|
|
49
|
+
"start_session",
|
|
50
|
+
"end_session",
|
|
51
|
+
"log_mistake",
|
|
52
|
+
"log_reward",
|
|
53
|
+
"get_rewards",
|
|
54
|
+
"session_metrics",
|
|
55
|
+
"experiment_report",
|
|
56
|
+
# Types
|
|
57
|
+
"Skill",
|
|
58
|
+
"Session",
|
|
59
|
+
"Mistake",
|
|
60
|
+
"RewardEvent",
|
|
61
|
+
]
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"""Re-export Thompson Sampling bandit from core.
|
|
2
|
+
|
|
3
|
+
Provides clean access to the bandit without reaching into core internals.
|
|
4
|
+
|
|
5
|
+
Usage:
|
|
6
|
+
from buildlog.engine.bandit import ThompsonSamplingBandit, BetaParams
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from buildlog.core.bandit import (
|
|
10
|
+
DEFAULT_CONTEXT,
|
|
11
|
+
DEFAULT_SEED_BOOST,
|
|
12
|
+
BanditState,
|
|
13
|
+
BetaParams,
|
|
14
|
+
ThompsonSamplingBandit,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
__all__ = [
|
|
18
|
+
"ThompsonSamplingBandit",
|
|
19
|
+
"BetaParams",
|
|
20
|
+
"BanditState",
|
|
21
|
+
"DEFAULT_SEED_BOOST",
|
|
22
|
+
"DEFAULT_CONTEXT",
|
|
23
|
+
]
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"""Re-export confidence scoring from buildlog.confidence.
|
|
2
|
+
|
|
3
|
+
Provides clean access to confidence calculation without reaching into
|
|
4
|
+
top-level module internals.
|
|
5
|
+
|
|
6
|
+
Usage:
|
|
7
|
+
from buildlog.engine.confidence import calculate_confidence, ConfidenceMetrics
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from buildlog.confidence import (
|
|
11
|
+
ConfidenceConfig,
|
|
12
|
+
ConfidenceMetrics,
|
|
13
|
+
ConfidenceTier,
|
|
14
|
+
add_contradiction,
|
|
15
|
+
calculate_confidence,
|
|
16
|
+
get_confidence_tier,
|
|
17
|
+
merge_confidence_metrics,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
__all__ = [
|
|
21
|
+
"calculate_confidence",
|
|
22
|
+
"get_confidence_tier",
|
|
23
|
+
"merge_confidence_metrics",
|
|
24
|
+
"add_contradiction",
|
|
25
|
+
"ConfidenceMetrics",
|
|
26
|
+
"ConfidenceConfig",
|
|
27
|
+
"ConfidenceTier",
|
|
28
|
+
]
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"""Re-export embedding backends from buildlog.embeddings.
|
|
2
|
+
|
|
3
|
+
Provides clean access to embedding similarity without reaching into
|
|
4
|
+
top-level module internals.
|
|
5
|
+
|
|
6
|
+
Usage:
|
|
7
|
+
from buildlog.engine.embeddings import similarity, TokenBackend
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from buildlog.embeddings import (
|
|
11
|
+
EmbeddingBackend,
|
|
12
|
+
OpenAIBackend,
|
|
13
|
+
SentenceTransformerBackend,
|
|
14
|
+
TokenBackend,
|
|
15
|
+
compute_embeddings,
|
|
16
|
+
get_backend,
|
|
17
|
+
similarity,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
__all__ = [
|
|
21
|
+
"EmbeddingBackend",
|
|
22
|
+
"TokenBackend",
|
|
23
|
+
"SentenceTransformerBackend",
|
|
24
|
+
"OpenAIBackend",
|
|
25
|
+
"get_backend",
|
|
26
|
+
"similarity",
|
|
27
|
+
"compute_embeddings",
|
|
28
|
+
]
|