Releases: ypollak2/chronicle
v1.0.4
Changelog
All notable changes to Chronicle are documented here.
Format follows Keep a Changelog.
Versioning follows Semantic Versioning.
[1.0.4] — 2026-04-15
Added
Claude Code integration — eliminate per-session context loss
chronicle setup --tool=claude-codenow registers Chronicle as an MCP server and adds SessionStart hook.claude/mcp.jsoncreated withchronicle mcpserver definition.claude/settings.jsoncreated withchronicle inject --format=markdownSessionStart hook- Global hook also added to
~/.claude/settings.json— auto-injects.lore/decisions in every project - Ensures all 35+ documented architectural decisions available at session start, no knowledge loss between Claude Code invocations
Fixed
Duplicate hook cleanup
- Removed duplicate system Python hooks (
python3 /path/to/hook.py) in favor of venv versions - Fixes "2 dashboards" issue where llm-router hooks ran twice per session
- Impact: cleaner hook execution, eliminates redundant model invocations
[1.0.3] — 2026-04-12
Fixed
Claude Code provider — stdin piping bug
- Previous invocation
claude -p -passed the literal string-as the message instead of reading from stdin - Fixed to
claude --print --output-format text --allowedTools ""with prompt piped via stdin --allowedTools ""prevents the model from using tools during extraction (faster, deterministic)- Also accepts
--llm claudeas an alias for--llm claude-code
Codex provider — incorrect subcommand
- Previous invocation
codex exec --full-auto -used a non-existent subcommand - Fixed to
codex --approval-mode full-auto --quietwith prompt via stdin - Added JSON extraction fallback: strips any status lines Codex prepends before the JSON block
detectProvider() improvements
- Detects
CLAUDE_CODE_ENTRYPOINT/CLAUDE_CODE_SESSION_IDenv vars to preferclaude-codewhen running inside a Claude Code session - Subscription CLIs (
claude,codex) now rank before API keys — free providers always win - Ollama liveness check added to auto-detection (probes
localhost:11434instead of assuming availability)
Changed
README rewritten for clarity
- New headline: "Your AI coding assistant keeps forgetting everything. Chronicle fixes that."
- Problem/solution framing at the top — table showing what gets lost each session
- LLM provider table updated: subscription CLIs shown first with "Free — uses your existing plan"
[1.0.2] — 2026-04-12
Added
Auto-install git hooks on first use
- When any
chroniclecommand runs in a git repo that has.lore/but no Chronicle hooks, hooks are silently installed automatically — nochronicle hooks installneeded - Check is a fast file-stat (no LLM, no output to the user)
- Skipped for internal commands (
capture,enrich-commit,merge-driver,mcp,quickstart,hooks)
pre-push hook — local .lore/ auto-update
- New git hook that runs
chronicle processsynchronously before eachgit push - If
.lore/changed, commits the updates with[skip ci]so the remote always receives a fresh store - Uses existing local LLM credentials — no GitHub Actions secret or separate API key needed
chronicle hooks removealso removes the pre-push hook
chronicle.yml simplified
- CI workflow no longer needs an LLM API key or GitHub secret
- Reduced to a lightweight
chronicle verify --max-lag 10freshness gate - All
.lore/updates now happen locally via the pre-push hook
Docs updated to v1.0.x
- README: version badge → v1.0.1, full commands table with all 26 commands across 5 groups
- CHANGELOG: v1.0.0 and v1.0.1 entries added
- ARCHITECTURE: correct store structure, package tree, release process, decision lifecycle, eval harness sections; shipped tool adapters (removed stale "Phase 4" labels)
[1.0.1] — 2026-04-12
Fixed
CI build — missing source files (add.ts, ingest.ts)
add.tsandingest.tswere referenced bycli.tsbut missing from the dist bundle, causingCJS Build failed: Could not resolve './commands/add.js'in the v1.0.0 release workflow- Added the missing files so the tsup bundle compiles clean
Release workflow — remove npm publish
- Removed
Publish to npmstep andregistry-urlfromsetup-node; the npm registry requires a paid org account for publish - Chronicle now publishes exclusively to PyPI + GitHub Release; no npm publish
Eval suite and CI fixes committed to repo
.lore/.eval.json20-case RAG eval suite added to repo- CI matrix updated: removed
--extra agnofromuv sync, added agno integration test to ignore list (fixes Python 3.12/3.13 CI hang)
[1.0.0] — 2026-04-12
Production-ready milestone. Chronicle can now maintain itself — the .lore/ store is bootstrapped, the GitHub Actions workflow processes every commit automatically, and the RAG quality gate (eval harness) certifies the store works.
Added
chronicle quickstart — interactive setup wizard
- Guides a new user from zero to a working
.lore/in ~5 minutes - Steps: git repo check →
chronicle init→chronicle migrate→chronicle hooks install→chronicle setup→ next-steps summary --yesflag for unattended/CI mode
chronicle migrate — schema migration command
- Upgrades
.lore/stores from any prior schema version to current (v1→v5) - Idempotent — safe to run multiple times
- Migrations covered:
index.mdcreation (v2),.extraction-cache.jsonrename (v3),low-confidence.mdcreation (v4), evolution era deduplication (v5)
chronicle decision — decision lifecycle management
chronicle decision list— display all decisions with current lifecycle status tagschronicle decision deprecate "<title>"— mark a decision as deprecated (adds<!-- status:deprecated -->tag)chronicle decision supersede "<title>" --by "<new>"— mark as superseded with forward referencechronicle decision promote "<title>"— lift a low-confidence decision into the maindecisions.md
chronicle verify fix — trivial commit exclusion
verifynow usesgetCommits()scanner (same filters asinit) sochore,docs, and lockfile commits are not counted as "unprocessed" — prevents false-positive staleness alerts in CI
Changed
chronicle eval --initbootstraps eval cases from existing decisions and rejections (was previously empty)chronicle injectfilters deprecated/superseded decisions from the output by default (lifecycle-aware injection)- Internal:
findLoreRoottest isolation via temp-dir rename pattern (CI reliability)
Tests
- Total: 223+ tests passing across 10 suites
- Self-dogfood:
chronicle evalon Chronicle's own.lore/— all 4 KPIs pass (100% recall, 100% rejection hit, MRR=1.000, 0% false confidence)
[0.13.0] — 2026-04-12
Added
Pipeline integration tests (#42)
process --dry-runtests: verifies commit counting against a real git repo withMIN_DIFF_LINES-compliant commitsinject → doctor → verifychain: full downstream pipeline with pre-built.lore/fixture, no LLM calls neededchronicle searchtests: keyword fallback with--textflag,--json, exit code coverage
chronicle search defaults to hybrid semantic mode (#47)
- Hybrid search (α=0.7 semantic + 0.3 keyword) is now the default when
@huggingface/transformersis installed - Silently falls back to keyword search when transformers are not available (
semanticSearchreturns null) - New
--textflag forces keyword-only mode --semanticflag preserved for pure vector similarity mode
chronicle doctor — 3 new integrity checks (#43)
- Check 7: orphaned ADR detection — warns when
.lore/decisions/files are not linked fromdecisions.md - Check 8: evolution integrity — detects the corruption pattern where all eras show identical decision counts
- Check 9:
process.logbounds — warns when log exceeds 500 lines
chronicle process — bounded log (#46)
process.logis auto-truncated to 500 lines after each run (keeps tail, discards oldest entries)truncateLog()utility at end ofprocess.ts
chronicle init generates index.md (#41)
- Reads
package.json(walks up 2 levels) for name, description, version - Generates structured
index.mdwith Key Constraints and Architecture template sections chronicle injectwarns on stderr whenindex.mdis missing
Fixed
evolution.md era deduplication (#40)
getDecisionsInRange()used inclusive lower bound — same-date decisions flooded all eras sharing that date- Fix: genesis era keeps
date >= from; all later eras usedate > from(exclusive) - Row filter changed from
!l.includes('Decision')(broke when titles contained "Decision") to checking first table cell specifically
Tests
- New pipeline integration tests in
cli-smoke.test.ts— 14 new tests across 3 describe blocks - Evolution regression: "does not repeat same-date decisions across multiple same-day eras"
- Doctor integrity checks: 6 new tests (orphaned ADRs, evolution corruption, process.log bounds)
- Total: 223 tests passing
[0.12.0] — 2026-04-12
Added
chronicle status command
- Single-line health summary:
◆ chronicle │ N decisions · N rejected · N ADRs · N sessions │ ✓ N unprocessed - Shows
· N low-confidenceand· ⚠ N extraction errorswhen non-zero --jsonflag for machine-readable output (CI, scripting, status bars)
Decision DAG — Mermaid renderer (chronicle relate --diagram)
buildMermaidDAG(graph)renders the full decision relation graph as aflowchart TDMermaid block- Labeled edges:
depends-on(solid),supersedes(dashed),related-to(dotted) - Sanitizes double-quotes in decision titles; handles all edge types and isolated nodes
Confidence threshold filtering (chronicle process --min-confidence)
--min-confidence <n>(default0.5)...
v1.0.3
Changelog
All notable changes to Chronicle are documented here.
Format follows Keep a Changelog.
Versioning follows Semantic Versioning.
[1.0.3] — 2026-04-12
Fixed
Claude Code provider — stdin piping bug
- Previous invocation
claude -p -passed the literal string-as the message instead of reading from stdin - Fixed to
claude --print --output-format text --allowedTools ""with prompt piped via stdin --allowedTools ""prevents the model from using tools during extraction (faster, deterministic)- Also accepts
--llm claudeas an alias for--llm claude-code
Codex provider — incorrect subcommand
- Previous invocation
codex exec --full-auto -used a non-existent subcommand - Fixed to
codex --approval-mode full-auto --quietwith prompt via stdin - Added JSON extraction fallback: strips any status lines Codex prepends before the JSON block
detectProvider() improvements
- Detects
CLAUDE_CODE_ENTRYPOINT/CLAUDE_CODE_SESSION_IDenv vars to preferclaude-codewhen running inside a Claude Code session - Subscription CLIs (
claude,codex) now rank before API keys — free providers always win - Ollama liveness check added to auto-detection (probes
localhost:11434instead of assuming availability)
Changed
README rewritten for clarity
- New headline: "Your AI coding assistant keeps forgetting everything. Chronicle fixes that."
- Problem/solution framing at the top — table showing what gets lost each session
- LLM provider table updated: subscription CLIs shown first with "Free — uses your existing plan"
[1.0.2] — 2026-04-12
Added
Auto-install git hooks on first use
- When any
chroniclecommand runs in a git repo that has.lore/but no Chronicle hooks, hooks are silently installed automatically — nochronicle hooks installneeded - Check is a fast file-stat (no LLM, no output to the user)
- Skipped for internal commands (
capture,enrich-commit,merge-driver,mcp,quickstart,hooks)
pre-push hook — local .lore/ auto-update
- New git hook that runs
chronicle processsynchronously before eachgit push - If
.lore/changed, commits the updates with[skip ci]so the remote always receives a fresh store - Uses existing local LLM credentials — no GitHub Actions secret or separate API key needed
chronicle hooks removealso removes the pre-push hook
chronicle.yml simplified
- CI workflow no longer needs an LLM API key or GitHub secret
- Reduced to a lightweight
chronicle verify --max-lag 10freshness gate - All
.lore/updates now happen locally via the pre-push hook
Docs updated to v1.0.x
- README: version badge → v1.0.1, full commands table with all 26 commands across 5 groups
- CHANGELOG: v1.0.0 and v1.0.1 entries added
- ARCHITECTURE: correct store structure, package tree, release process, decision lifecycle, eval harness sections; shipped tool adapters (removed stale "Phase 4" labels)
[1.0.1] — 2026-04-12
Fixed
CI build — missing source files (add.ts, ingest.ts)
add.tsandingest.tswere referenced bycli.tsbut missing from the dist bundle, causingCJS Build failed: Could not resolve './commands/add.js'in the v1.0.0 release workflow- Added the missing files so the tsup bundle compiles clean
Release workflow — remove npm publish
- Removed
Publish to npmstep andregistry-urlfromsetup-node; the npm registry requires a paid org account for publish - Chronicle now publishes exclusively to PyPI + GitHub Release; no npm publish
Eval suite and CI fixes committed to repo
.lore/.eval.json20-case RAG eval suite added to repo- CI matrix updated: removed
--extra agnofromuv sync, added agno integration test to ignore list (fixes Python 3.12/3.13 CI hang)
[1.0.0] — 2026-04-12
Production-ready milestone. Chronicle can now maintain itself — the .lore/ store is bootstrapped, the GitHub Actions workflow processes every commit automatically, and the RAG quality gate (eval harness) certifies the store works.
Added
chronicle quickstart — interactive setup wizard
- Guides a new user from zero to a working
.lore/in ~5 minutes - Steps: git repo check →
chronicle init→chronicle migrate→chronicle hooks install→chronicle setup→ next-steps summary --yesflag for unattended/CI mode
chronicle migrate — schema migration command
- Upgrades
.lore/stores from any prior schema version to current (v1→v5) - Idempotent — safe to run multiple times
- Migrations covered:
index.mdcreation (v2),.extraction-cache.jsonrename (v3),low-confidence.mdcreation (v4), evolution era deduplication (v5)
chronicle decision — decision lifecycle management
chronicle decision list— display all decisions with current lifecycle status tagschronicle decision deprecate "<title>"— mark a decision as deprecated (adds<!-- status:deprecated -->tag)chronicle decision supersede "<title>" --by "<new>"— mark as superseded with forward referencechronicle decision promote "<title>"— lift a low-confidence decision into the maindecisions.md
chronicle verify fix — trivial commit exclusion
verifynow usesgetCommits()scanner (same filters asinit) sochore,docs, and lockfile commits are not counted as "unprocessed" — prevents false-positive staleness alerts in CI
Changed
chronicle eval --initbootstraps eval cases from existing decisions and rejections (was previously empty)chronicle injectfilters deprecated/superseded decisions from the output by default (lifecycle-aware injection)- Internal:
findLoreRoottest isolation via temp-dir rename pattern (CI reliability)
Tests
- Total: 223+ tests passing across 10 suites
- Self-dogfood:
chronicle evalon Chronicle's own.lore/— all 4 KPIs pass (100% recall, 100% rejection hit, MRR=1.000, 0% false confidence)
[0.13.0] — 2026-04-12
Added
Pipeline integration tests (#42)
process --dry-runtests: verifies commit counting against a real git repo withMIN_DIFF_LINES-compliant commitsinject → doctor → verifychain: full downstream pipeline with pre-built.lore/fixture, no LLM calls neededchronicle searchtests: keyword fallback with--textflag,--json, exit code coverage
chronicle search defaults to hybrid semantic mode (#47)
- Hybrid search (α=0.7 semantic + 0.3 keyword) is now the default when
@huggingface/transformersis installed - Silently falls back to keyword search when transformers are not available (
semanticSearchreturns null) - New
--textflag forces keyword-only mode --semanticflag preserved for pure vector similarity mode
chronicle doctor — 3 new integrity checks (#43)
- Check 7: orphaned ADR detection — warns when
.lore/decisions/files are not linked fromdecisions.md - Check 8: evolution integrity — detects the corruption pattern where all eras show identical decision counts
- Check 9:
process.logbounds — warns when log exceeds 500 lines
chronicle process — bounded log (#46)
process.logis auto-truncated to 500 lines after each run (keeps tail, discards oldest entries)truncateLog()utility at end ofprocess.ts
chronicle init generates index.md (#41)
- Reads
package.json(walks up 2 levels) for name, description, version - Generates structured
index.mdwith Key Constraints and Architecture template sections chronicle injectwarns on stderr whenindex.mdis missing
Fixed
evolution.md era deduplication (#40)
getDecisionsInRange()used inclusive lower bound — same-date decisions flooded all eras sharing that date- Fix: genesis era keeps
date >= from; all later eras usedate > from(exclusive) - Row filter changed from
!l.includes('Decision')(broke when titles contained "Decision") to checking first table cell specifically
Tests
- New pipeline integration tests in
cli-smoke.test.ts— 14 new tests across 3 describe blocks - Evolution regression: "does not repeat same-date decisions across multiple same-day eras"
- Doctor integrity checks: 6 new tests (orphaned ADRs, evolution corruption, process.log bounds)
- Total: 223 tests passing
[0.12.0] — 2026-04-12
Added
chronicle status command
- Single-line health summary:
◆ chronicle │ N decisions · N rejected · N ADRs · N sessions │ ✓ N unprocessed - Shows
· N low-confidenceand· ⚠ N extraction errorswhen non-zero --jsonflag for machine-readable output (CI, scripting, status bars)
Decision DAG — Mermaid renderer (chronicle relate --diagram)
buildMermaidDAG(graph)renders the full decision relation graph as aflowchart TDMermaid block- Labeled edges:
depends-on(solid),supersedes(dashed),related-to(dotted) - Sanitizes double-quotes in decision titles; handles all edge types and isolated nodes
Confidence threshold filtering (chronicle process --min-confidence)
--min-confidence <n>(default0.5) — decisions below threshold are quarantined to.lore/low-confidence.mdrather than discarded or silently accepted- "Preserve but quarantine" pattern: low-confidence results remain reviewable
.lore/low-confidence.mdadded to store structure (STORE_FILESmap in@chronicle/core)chronicle statussurfaces low-confidence count
Extraction error tracking
callWithRetryaccepts an optionalctx: { errors: number }ref threaded through concurrent batches- On exhaustion (3 failed attempts),
ctx.errorsis incremented — distinguishes "no decisions found" from "LLM returned malformed JSON" chronicle processpassesextractionCtxand logserrors:Nto.lore/process.logchronicle statusreads the last log entry and surfaces extraction errors
GitHub Actions job summary
chronicle.ymlwrites a markdown table to$GITHUB_STEP_SUMMARYafter each `chro...
v1.0.2
Changelog
All notable changes to Chronicle are documented here.
Format follows Keep a Changelog.
Versioning follows Semantic Versioning.
[1.0.2] — 2026-04-12
Added
Auto-install git hooks on first use
- When any
chroniclecommand runs in a git repo that has.lore/but no Chronicle hooks, hooks are silently installed automatically — nochronicle hooks installneeded - Check is a fast file-stat (no LLM, no output to the user)
- Skipped for internal commands (
capture,enrich-commit,merge-driver,mcp,quickstart,hooks)
pre-push hook — local .lore/ auto-update
- New git hook that runs
chronicle processsynchronously before eachgit push - If
.lore/changed, commits the updates with[skip ci]so the remote always receives a fresh store - Uses existing local LLM credentials — no GitHub Actions secret or separate API key needed
chronicle hooks removealso removes the pre-push hook
chronicle.yml simplified
- CI workflow no longer needs an LLM API key or GitHub secret
- Reduced to a lightweight
chronicle verify --max-lag 10freshness gate - All
.lore/updates now happen locally via the pre-push hook
Docs updated to v1.0.x
- README: version badge → v1.0.1, full commands table with all 26 commands across 5 groups
- CHANGELOG: v1.0.0 and v1.0.1 entries added
- ARCHITECTURE: correct store structure, package tree, release process, decision lifecycle, eval harness sections; shipped tool adapters (removed stale "Phase 4" labels)
[1.0.1] — 2026-04-12
Fixed
CI build — missing source files (add.ts, ingest.ts)
add.tsandingest.tswere referenced bycli.tsbut missing from the dist bundle, causingCJS Build failed: Could not resolve './commands/add.js'in the v1.0.0 release workflow- Added the missing files so the tsup bundle compiles clean
Release workflow — remove npm publish
- Removed
Publish to npmstep andregistry-urlfromsetup-node; the npm registry requires a paid org account for publish - Chronicle now publishes exclusively to PyPI + GitHub Release; no npm publish
Eval suite and CI fixes committed to repo
.lore/.eval.json20-case RAG eval suite added to repo- CI matrix updated: removed
--extra agnofromuv sync, added agno integration test to ignore list (fixes Python 3.12/3.13 CI hang)
[1.0.0] — 2026-04-12
Production-ready milestone. Chronicle can now maintain itself — the .lore/ store is bootstrapped, the GitHub Actions workflow processes every commit automatically, and the RAG quality gate (eval harness) certifies the store works.
Added
chronicle quickstart — interactive setup wizard
- Guides a new user from zero to a working
.lore/in ~5 minutes - Steps: git repo check →
chronicle init→chronicle migrate→chronicle hooks install→chronicle setup→ next-steps summary --yesflag for unattended/CI mode
chronicle migrate — schema migration command
- Upgrades
.lore/stores from any prior schema version to current (v1→v5) - Idempotent — safe to run multiple times
- Migrations covered:
index.mdcreation (v2),.extraction-cache.jsonrename (v3),low-confidence.mdcreation (v4), evolution era deduplication (v5)
chronicle decision — decision lifecycle management
chronicle decision list— display all decisions with current lifecycle status tagschronicle decision deprecate "<title>"— mark a decision as deprecated (adds<!-- status:deprecated -->tag)chronicle decision supersede "<title>" --by "<new>"— mark as superseded with forward referencechronicle decision promote "<title>"— lift a low-confidence decision into the maindecisions.md
chronicle verify fix — trivial commit exclusion
verifynow usesgetCommits()scanner (same filters asinit) sochore,docs, and lockfile commits are not counted as "unprocessed" — prevents false-positive staleness alerts in CI
Changed
chronicle eval --initbootstraps eval cases from existing decisions and rejections (was previously empty)chronicle injectfilters deprecated/superseded decisions from the output by default (lifecycle-aware injection)- Internal:
findLoreRoottest isolation via temp-dir rename pattern (CI reliability)
Tests
- Total: 223+ tests passing across 10 suites
- Self-dogfood:
chronicle evalon Chronicle's own.lore/— all 4 KPIs pass (100% recall, 100% rejection hit, MRR=1.000, 0% false confidence)
[0.13.0] — 2026-04-12
Added
Pipeline integration tests (#42)
process --dry-runtests: verifies commit counting against a real git repo withMIN_DIFF_LINES-compliant commitsinject → doctor → verifychain: full downstream pipeline with pre-built.lore/fixture, no LLM calls neededchronicle searchtests: keyword fallback with--textflag,--json, exit code coverage
chronicle search defaults to hybrid semantic mode (#47)
- Hybrid search (α=0.7 semantic + 0.3 keyword) is now the default when
@huggingface/transformersis installed - Silently falls back to keyword search when transformers are not available (
semanticSearchreturns null) - New
--textflag forces keyword-only mode --semanticflag preserved for pure vector similarity mode
chronicle doctor — 3 new integrity checks (#43)
- Check 7: orphaned ADR detection — warns when
.lore/decisions/files are not linked fromdecisions.md - Check 8: evolution integrity — detects the corruption pattern where all eras show identical decision counts
- Check 9:
process.logbounds — warns when log exceeds 500 lines
chronicle process — bounded log (#46)
process.logis auto-truncated to 500 lines after each run (keeps tail, discards oldest entries)truncateLog()utility at end ofprocess.ts
chronicle init generates index.md (#41)
- Reads
package.json(walks up 2 levels) for name, description, version - Generates structured
index.mdwith Key Constraints and Architecture template sections chronicle injectwarns on stderr whenindex.mdis missing
Fixed
evolution.md era deduplication (#40)
getDecisionsInRange()used inclusive lower bound — same-date decisions flooded all eras sharing that date- Fix: genesis era keeps
date >= from; all later eras usedate > from(exclusive) - Row filter changed from
!l.includes('Decision')(broke when titles contained "Decision") to checking first table cell specifically
Tests
- New pipeline integration tests in
cli-smoke.test.ts— 14 new tests across 3 describe blocks - Evolution regression: "does not repeat same-date decisions across multiple same-day eras"
- Doctor integrity checks: 6 new tests (orphaned ADRs, evolution corruption, process.log bounds)
- Total: 223 tests passing
[0.12.0] — 2026-04-12
Added
chronicle status command
- Single-line health summary:
◆ chronicle │ N decisions · N rejected · N ADRs · N sessions │ ✓ N unprocessed - Shows
· N low-confidenceand· ⚠ N extraction errorswhen non-zero --jsonflag for machine-readable output (CI, scripting, status bars)
Decision DAG — Mermaid renderer (chronicle relate --diagram)
buildMermaidDAG(graph)renders the full decision relation graph as aflowchart TDMermaid block- Labeled edges:
depends-on(solid),supersedes(dashed),related-to(dotted) - Sanitizes double-quotes in decision titles; handles all edge types and isolated nodes
Confidence threshold filtering (chronicle process --min-confidence)
--min-confidence <n>(default0.5) — decisions below threshold are quarantined to.lore/low-confidence.mdrather than discarded or silently accepted- "Preserve but quarantine" pattern: low-confidence results remain reviewable
.lore/low-confidence.mdadded to store structure (STORE_FILESmap in@chronicle/core)chronicle statussurfaces low-confidence count
Extraction error tracking
callWithRetryaccepts an optionalctx: { errors: number }ref threaded through concurrent batches- On exhaustion (3 failed attempts),
ctx.errorsis incremented — distinguishes "no decisions found" from "LLM returned malformed JSON" chronicle processpassesextractionCtxand logserrors:Nto.lore/process.logchronicle statusreads the last log entry and surfaces extraction errors
GitHub Actions job summary
chronicle.ymlwrites a markdown table to$GITHUB_STEP_SUMMARYafter eachchronicle processrun- Table shows: decisions, rejections, ADRs, sessions, unprocessed commits, low-confidence, extraction errors
Changed
evolutioneras now sort decisions by risk level (high → medium → low) before renderingrenderEvolutionMarkdownhides the "Most changed files" section when decisions exist — file churn is noise when decisions tell the storygetDecisionsInRangenow correctly filters by date range; handles both legacy format (title in col[0]) and current format (date in col[0])chronicle injectuses the two most-recent evolution eras (previously used the oldest era)
Fixed
- Removed
'two-pass'fromExtractionStrategytype — it was typed as valid but threw"not implemented"at runtime chronicle statuscrash:'low-confidence'was missing fromSTORE_FILESmap, causinglorePath(root, undefined)at runtime
Tests
- New
semantic-search.test.ts— 7 tests covering null embed fallback, empty corpus, hybrid mode,buildEmbeddingIndex - New
cli-smoke.test.tsfreshness block — 3 tests: unprocessed detection, cache-hit zero, exit-1 on lag callWithRetryctx tests — 6 new tests: success, empty[], retry-then-succeed, exhaustion increments ctx,[]does not increment ctx, accumulation across batchesevolution.test.ts— 4 new tests: risk ordering, keyFiles suppression when decisions exist, keyFiles shown when no decisions, date-range filtering- Total: 202 tests p...
v1.0.1
Changelog
All notable changes to Chronicle are documented here.
Format follows Keep a Changelog.
Versioning follows Semantic Versioning.
[0.13.0] — 2026-04-12
Added
Pipeline integration tests (#42)
process --dry-runtests: verifies commit counting against a real git repo withMIN_DIFF_LINES-compliant commitsinject → doctor → verifychain: full downstream pipeline with pre-built.lore/fixture, no LLM calls neededchronicle searchtests: keyword fallback with--textflag,--json, exit code coverage
chronicle search defaults to hybrid semantic mode (#47)
- Hybrid search (α=0.7 semantic + 0.3 keyword) is now the default when
@huggingface/transformersis installed - Silently falls back to keyword search when transformers are not available (
semanticSearchreturns null) - New
--textflag forces keyword-only mode --semanticflag preserved for pure vector similarity mode
chronicle doctor — 3 new integrity checks (#43)
- Check 7: orphaned ADR detection — warns when
.lore/decisions/files are not linked fromdecisions.md - Check 8: evolution integrity — detects the corruption pattern where all eras show identical decision counts
- Check 9:
process.logbounds — warns when log exceeds 500 lines
chronicle process — bounded log (#46)
process.logis auto-truncated to 500 lines after each run (keeps tail, discards oldest entries)truncateLog()utility at end ofprocess.ts
chronicle init generates index.md (#41)
- Reads
package.json(walks up 2 levels) for name, description, version - Generates structured
index.mdwith Key Constraints and Architecture template sections chronicle injectwarns on stderr whenindex.mdis missing
Fixed
evolution.md era deduplication (#40)
getDecisionsInRange()used inclusive lower bound — same-date decisions flooded all eras sharing that date- Fix: genesis era keeps
date >= from; all later eras usedate > from(exclusive) - Row filter changed from
!l.includes('Decision')(broke when titles contained "Decision") to checking first table cell specifically
Tests
- New pipeline integration tests in
cli-smoke.test.ts— 14 new tests across 3 describe blocks - Evolution regression: "does not repeat same-date decisions across multiple same-day eras"
- Doctor integrity checks: 6 new tests (orphaned ADRs, evolution corruption, process.log bounds)
- Total: 223 tests passing
[0.12.0] — 2026-04-12
Added
chronicle status command
- Single-line health summary:
◆ chronicle │ N decisions · N rejected · N ADRs · N sessions │ ✓ N unprocessed - Shows
· N low-confidenceand· ⚠ N extraction errorswhen non-zero --jsonflag for machine-readable output (CI, scripting, status bars)
Decision DAG — Mermaid renderer (chronicle relate --diagram)
buildMermaidDAG(graph)renders the full decision relation graph as aflowchart TDMermaid block- Labeled edges:
depends-on(solid),supersedes(dashed),related-to(dotted) - Sanitizes double-quotes in decision titles; handles all edge types and isolated nodes
Confidence threshold filtering (chronicle process --min-confidence)
--min-confidence <n>(default0.5) — decisions below threshold are quarantined to.lore/low-confidence.mdrather than discarded or silently accepted- "Preserve but quarantine" pattern: low-confidence results remain reviewable
.lore/low-confidence.mdadded to store structure (STORE_FILESmap in@chronicle/core)chronicle statussurfaces low-confidence count
Extraction error tracking
callWithRetryaccepts an optionalctx: { errors: number }ref threaded through concurrent batches- On exhaustion (3 failed attempts),
ctx.errorsis incremented — distinguishes "no decisions found" from "LLM returned malformed JSON" chronicle processpassesextractionCtxand logserrors:Nto.lore/process.logchronicle statusreads the last log entry and surfaces extraction errors
GitHub Actions job summary
chronicle.ymlwrites a markdown table to$GITHUB_STEP_SUMMARYafter eachchronicle processrun- Table shows: decisions, rejections, ADRs, sessions, unprocessed commits, low-confidence, extraction errors
Changed
evolutioneras now sort decisions by risk level (high → medium → low) before renderingrenderEvolutionMarkdownhides the "Most changed files" section when decisions exist — file churn is noise when decisions tell the storygetDecisionsInRangenow correctly filters by date range; handles both legacy format (title in col[0]) and current format (date in col[0])chronicle injectuses the two most-recent evolution eras (previously used the oldest era)
Fixed
- Removed
'two-pass'fromExtractionStrategytype — it was typed as valid but threw"not implemented"at runtime chronicle statuscrash:'low-confidence'was missing fromSTORE_FILESmap, causinglorePath(root, undefined)at runtime
Tests
- New
semantic-search.test.ts— 7 tests covering null embed fallback, empty corpus, hybrid mode,buildEmbeddingIndex - New
cli-smoke.test.tsfreshness block — 3 tests: unprocessed detection, cache-hit zero, exit-1 on lag callWithRetryctx tests — 6 new tests: success, empty[], retry-then-succeed, exhaustion increments ctx,[]does not increment ctx, accumulation across batchesevolution.test.ts— 4 new tests: risk ordering, keyFiles suppression when decisions exist, keyFiles shown when no decisions, date-range filtering- Total: 202 tests passing
[0.9.0] — 2026-04-11
Added
Decision relationship DAG (chronicle relate) (I1)
chronicle relate "<title>" --depends-on "<title>"— record that a decision builds on anotherchronicle relate "<title>" --supersedes "<title>"— mark an old decision as replacedchronicle relate "<title>" --related-to "<title>"— soft cross-reference between decisionschronicle relate --list— print the full relation graph across all decisions- Relations stored as
<!-- relations:{...} -->inline HTML comments indecisions.mdrows (backward-compatible with existing stores) applyRelationToContent,buildRelationGraph,getRelatedRows,parseRelations,serializeRelations,addRelationToRow,removeRelationFromRow,extractTitleFromRowexported from@chronicle/core
Business/product context layer (chronicle context) (I2)
chronicle context add --goal|--constraint|--team|--stack|--non-goal <text>— add a fact to.lore/context.mdchronicle context remove ...— remove a context factchronicle context show— print current project contextchronicle context edit— opencontext.mdin$EDITORchronicle injectnow prepends the project context block at the top of every outputreadContext,writeContext,addContextFact,removeContextFact,formatContextForInjectexported from@chronicle/core
Ownership tracking (chronicle who) (I3)
chronicle who <file>— show owner(s) and all recorded decisions + risks for a file- Reads CODEOWNERS automatically (checks
CODEOWNERS,.github/CODEOWNERS,.gitlab/CODEOWNERS) - Falls back to
.lore/ownership.md(format:- \pattern`: @owner`) chronicle capturenow stamps<!-- author:email -->on each captured decision rowchronicle inject --filesnow includes a## File Ownershipsection when ownership is definedloadOwnership,getOwnersForFile,parseAuthorFromRow,setAuthorOnRow,buildOwnershipSection,writeLoreOwnershipexported from@chronicle/core
CI / Server-side automation
chronicle verify— CI gate: exits 1 when.lore/lags by more than--max-lagcommits (default 5);--jsonfor machine-readable outputchronicle process— batch processor for GitHub Actions: processes all uncached commits in one pass, writes.lore/process.log, exits 1 on LLM errors.github/workflows/chronicle.yml— official GitHub Actions workflow that triggers on push to main, runschronicle process, and commits updated.lore/back with[skip ci]— closes the "repo maintains itself" loop
Comprehensive test suite (149 tests across 9 suites)
extraction-parsing.test.ts— 21 tests covering malformed JSON, HTML-wrapped responses, null fields, truncated output, code block variations, and prompt completenessranker.test.ts— 26 tests forparseDecisionsTable,scoreRow(file match, age decay, risk/confidence bonus),rankDecisions(sort order, semantic blend, topN),estimateTokens,trimToTokenBudgetrag-quality.test.ts— 28 behavioral tests: "does the store contain the right knowledge?" — decisions completeness, rejections format, risks content, evolution eras, deep ADR structure, inject output ranking, staleness, token budget, relations DAG, business contextpipeline.test.ts— 10 end-to-end integration tests using real git repos (temp fixture) + mock LLM: feature commit → decisions.md, security → high-risk, rejection → rejected.md, noise filtering, store write correctness, deep ADR creation, cache prevents re-processingfixtures.ts— shared fixture factory:buildProjectRepo()(7-commit git repo covering all change types),buildPopulatedLore()(pre-populated.lore/for inject tests),buildMockLLM()(keyword-aware mock returning realistic ExtractionResults)
Fixed
parseExtractionResponsenow filters non-object elements from arrays (LLM hallucination of[1, 2, 3]no longer passes through as decisions)scoreRowrecentFiles matching now uses prefix matching: a row affectingsrc/auth/correctly matches a recent filesrc/auth/jwt.ts- Extraction cache now marks noise commits (zero results) as processed, preventing re-querying on the second pass
buildExtractionPromptnow includes the commit hash in the prompt so the LLM can return it in each result object (enabling accurate cache k...
v0.13.0 — Correctness & Pipeline Quality
What's new
Correctness fixes
- Evolution era deduplication —
getDecisionsInRange()used inclusive lower bound, causing same-date decisions to appear in every era. Fixed: genesis era usesdate >= from, later eras usedate > from(exclusive). Runchronicle evolution --regento regenerate. chronicle initnow generatesindex.md— readspackage.jsonfor project name/description/version; generates structured template with Key Constraints and Architecture sections.chronicle injectwarns when missing.
New checks in chronicle doctor
- Orphaned ADR detection — warns when
.lore/decisions/files are not linked fromdecisions.md - Evolution integrity — detects corruption when all eras show identical decision counts
process.logbounds — warns when log exceeds 500 lines
chronicle search now uses hybrid mode by default
- Hybrid semantic + keyword search (α=0.7) runs when
@huggingface/transformersis installed - Silently falls back to keyword search otherwise
- New
--textflag forces keyword-only mode
Bounded process.log
- Auto-truncated to 500 lines after each
chronicle processrun
Tests
223 passing (up from 209)
Breaking changes
Existing evolution.md files built with v0.12 may show duplicate decisions across eras. Run chronicle evolution --regen to fix.
v0.12.0 — Status Command, Decision DAG & Extraction Quality
What's New
chronicle status command
Single-line health summary: decisions, ADRs, sessions, unprocessed commit count, low-confidence quarantine, and extraction errors. Supports --json for CI/scripting.
◆ chronicle │ 30 decisions · 6 rejected · 3 ADRs · 0 sessions │ ✓ 0 unprocessed
Decision DAG — Mermaid diagram renderer
chronicle relate --diagram renders your decision relation graph as a Mermaid flowchart TD block, showing depends-on, supersedes, and related-to edges with labeled arrows.
Extraction quality improvements
- Few-shot examples in the extraction prompt (decision, rejection, noise) anchor model calibration
- JSON retry with exponential backoff — up to 3 attempts (1s/2s) on malformed JSON; clean
[]accepted immediately - Diff truncation — diffs >3000 chars are trimmed and flagged with a
NOTEheader so the LLM knows context is partial - Confidence threshold (
--min-confidence, default 0.5) — results below threshold go to.lore/low-confidence.mdrather than being silently discarded injectcontext fix — now uses the two most-recent evolution eras instead of the oldest, so AI context reflects current state
CI observability
chronicle process in GitHub Actions now writes a markdown table to $GITHUB_STEP_SUMMARY showing decisions added, ADRs, unprocessed commits, and extraction errors.
Bug fixes
- Remove
'two-pass'fromExtractionStrategy(was typed valid but threw at runtime) evolutiondate-range filtering now works correctly- Evolution eras sort decisions by risk (high → medium → low)
- keyFiles section hidden when decisions exist (file churn is noise when decisions tell the story)
Install
pip install --upgrade chronicle-devFull Changelog
https://github.com/yalipollak/chronicle/compare/v0.9.1...v0.12.0
v0.9.1
Changelog
All notable changes to Chronicle are documented here.
Format follows Keep a Changelog.
Versioning follows Semantic Versioning.
[0.9.0] — 2026-04-11
Added
Decision relationship DAG (chronicle relate) (I1)
chronicle relate "<title>" --depends-on "<title>"— record that a decision builds on anotherchronicle relate "<title>" --supersedes "<title>"— mark an old decision as replacedchronicle relate "<title>" --related-to "<title>"— soft cross-reference between decisionschronicle relate --list— print the full relation graph across all decisions- Relations stored as
<!-- relations:{...} -->inline HTML comments indecisions.mdrows (backward-compatible with existing stores) applyRelationToContent,buildRelationGraph,getRelatedRows,parseRelations,serializeRelations,addRelationToRow,removeRelationFromRow,extractTitleFromRowexported from@chronicle/core
Business/product context layer (chronicle context) (I2)
chronicle context add --goal|--constraint|--team|--stack|--non-goal <text>— add a fact to.lore/context.mdchronicle context remove ...— remove a context factchronicle context show— print current project contextchronicle context edit— opencontext.mdin$EDITORchronicle injectnow prepends the project context block at the top of every outputreadContext,writeContext,addContextFact,removeContextFact,formatContextForInjectexported from@chronicle/core
Ownership tracking (chronicle who) (I3)
chronicle who <file>— show owner(s) and all recorded decisions + risks for a file- Reads CODEOWNERS automatically (checks
CODEOWNERS,.github/CODEOWNERS,.gitlab/CODEOWNERS) - Falls back to
.lore/ownership.md(format:- \pattern`: @owner`) chronicle capturenow stamps<!-- author:email -->on each captured decision rowchronicle inject --filesnow includes a## File Ownershipsection when ownership is definedloadOwnership,getOwnersForFile,parseAuthorFromRow,setAuthorOnRow,buildOwnershipSection,writeLoreOwnershipexported from@chronicle/core
CI / Server-side automation
chronicle verify— CI gate: exits 1 when.lore/lags by more than--max-lagcommits (default 5);--jsonfor machine-readable outputchronicle process— batch processor for GitHub Actions: processes all uncached commits in one pass, writes.lore/process.log, exits 1 on LLM errors.github/workflows/chronicle.yml— official GitHub Actions workflow that triggers on push to main, runschronicle process, and commits updated.lore/back with[skip ci]— closes the "repo maintains itself" loop
Comprehensive test suite (149 tests across 9 suites)
extraction-parsing.test.ts— 21 tests covering malformed JSON, HTML-wrapped responses, null fields, truncated output, code block variations, and prompt completenessranker.test.ts— 26 tests forparseDecisionsTable,scoreRow(file match, age decay, risk/confidence bonus),rankDecisions(sort order, semantic blend, topN),estimateTokens,trimToTokenBudgetrag-quality.test.ts— 28 behavioral tests: "does the store contain the right knowledge?" — decisions completeness, rejections format, risks content, evolution eras, deep ADR structure, inject output ranking, staleness, token budget, relations DAG, business contextpipeline.test.ts— 10 end-to-end integration tests using real git repos (temp fixture) + mock LLM: feature commit → decisions.md, security → high-risk, rejection → rejected.md, noise filtering, store write correctness, deep ADR creation, cache prevents re-processingfixtures.ts— shared fixture factory:buildProjectRepo()(7-commit git repo covering all change types),buildPopulatedLore()(pre-populated.lore/for inject tests),buildMockLLM()(keyword-aware mock returning realistic ExtractionResults)
Fixed
parseExtractionResponsenow filters non-object elements from arrays (LLM hallucination of[1, 2, 3]no longer passes through as decisions)scoreRowrecentFiles matching now uses prefix matching: a row affectingsrc/auth/correctly matches a recent filesrc/auth/jwt.ts- Extraction cache now marks noise commits (zero results) as processed, preventing re-querying on the second pass
buildExtractionPromptnow includes the commit hash in the prompt so the LLM can return it in each result object (enabling accurate cache keying)- Evolution test updated:
buildEvolutioncorrectly synthesizes a singlev0.1 (initial)era for repos with no git tags (time-based era synthesis was added in v0.3.0 but the test expectation was not updated)
[0.8.0] — 2026-04-11
Added
Multi-source knowledge ingestion
chronicle add — register additional knowledge sources:
--repo <path|url>— secondary git repo (clones remotes to~/.chronicle/repos/); decisions extracted immediately--dir <path>— local directory (.md,.ts,.py,.go, etc.)--url <url>— web page (HTML stripped to text)--pdf <path>— PDF file (text PDFs; requires optionalpdf-parse)--list/--remove <id>— manage registered sources- Source registry persisted at
.lore/sources.json
chronicle ingest — index dir/url/pdf sources into .lore/chunks/{sourceId}/:
- Chunks text at ~500-token boundaries (paragraph-aware)
- Skips already-ingested sources unless
--force --id <id>to re-ingest a single source
Unified search (M4)
chronicle searchnow also scans.lore/chunks/in keyword mode- Semantic/hybrid modes already work across all embedded content
Git merge driver for decisions.md (M5)
chronicle hooks installnow registersmerge.chronicle-decisionsin.git/config- Adds
.lore/decisions*.md merge=chronicle-decisionsto.gitattributes chronicle merge-driver <base> <ours> <theirs>(internal, called by git):- Union-merges table rows from both branches
- Deduplicates by title (keeps newest date)
- Exits 0 → conflict-free merge; exits 1 → unresolvable
Source abstraction layer (@chronicle/core)
SourceConfig,SourceType,SourceRegistrytypesloadSourceRegistry,saveSourceRegistry,addSource,removeSource,listSources,getSource,markIngested,deriveSourceIdchunkText,ingestDir,ingestUrl,ingestPdffromingestor.ts
[0.7.0] — 2026-04-11
Added
Local embedding engine (@chronicle/core)
embed(text)/embedBatch(texts)— MiniLM-L6-v2 via@huggingface/transformers(22MB, fully offline)cosineSimilarity(a, b)— dot product on normalized vectorsloadEmbeddingCache/saveEmbeddingCache— SHA-256 content-keyed JSON cache at.lore/embeddings.jsongetEmbeddings(texts, cache)— batch embedding with cache deduplication (only new content is embedded)@huggingface/transformersis anoptionalDependency— Chronicle works without it, embedding features degrade gracefully to heuristic mode
Semantic search (chronicle search)
--semantic— pure vector similarity search using MiniLM embeddings--hybrid— linear blend: 0.7 × semantic + 0.3 × keyword score- Visual score bar output (█░░░ style) with source attribution
- Graceful fallback to keyword search with install hint if transformers not available
Semantic inject ranking (chronicle inject)
--query <text>— natural language query that re-ranks decision rows by semantic similarity- Phase 2 ranker:
0.6 × semantic + 0.4 × heuristicblend when--queryprovided buildSemanticScores(rows, query)exported from@chronicle/core
Incremental vector index (post-commit hook)
buildEmbeddingIndex(root)— indexes all decisions, rejects, risks; skips cached content- Called automatically by
chronicle captureafter each commit (only new decisions are embedded)
RAG quality harness (chronicle eval)
chronicle eval— runs 4 KPI checks: Decision Recall, Rejection Hit Rate, Semantic MRR@5, False Confidence Ratechronicle eval --init— bootstraps.lore/.eval.jsonfrom existing decisions (ready to run immediately)--jsonfor machine-readable output;--verbosefor per-case details- Exits 1 if any KPI is below target (suitable for CI)
- KPI targets: Recall ≥ 80%, Rejection Hit ≥ 90%, MRR@5 ≥ 0.70, False Confidence ≤ 10%
Changed
rankDecisions()now acceptssemanticScores?: Map<string, number>for hybrid scoring
[0.6.0] — 2026-04-11
Added
Relevance-ranked inject (chronicle inject)
--top <n>— return only the N most relevant decisions (ranked by heuristic score)--tokens <n>— auto-trim output to fit within N tokens (~4 chars/token)--min-confidence <n>— omit decisions below a confidence threshold (0.0–1.0)rankDecisions()in@chronicle/core— heuristic scoring: file match ×3, recent file ×1, risk bonus (high=+2, medium=+1), age decay, confidence bonustrimToTokenBudget()— greedy section trimmer with partial truncation fallback
Confidence scores on decisions
- LLM extraction now returns a
confidencefield (0.0–1.0) per decision - Stored as
<!-- confidence:0.72 -->inline HTML comments indecisions.mdrows - Backward-compatible: existing stores default to
confidence=1.0
Staleness detection (chronicle inject --no-stale)
- Automatically flags decisions whose affected files have been significantly modified since the decision was recorded
- One-shot
git log --name-onlyscan builds aFileModMap— no per-decision git calls - Stale decisions annotated with
<!-- stale -->and surfaced as a⚠️ Potentially Stale Decisionswarning block in inject output - Disable with
--no-stalefor faster runs without git access
Session history index (chronicle session save)
- Every
session savenow rebuilds.lore/sessions/_index.md— a compact markdown table of all sessions chronicle injectincludes...
v0.5.4
Changelog
All notable changes to Chronicle are documented here.
Format follows Keep a Changelog.
Versioning follows Semantic Versioning.
[0.5.0] — 2026-04-10
Added
New Commands
chronicle doctor— validates.lore/health: checks for missing files, broken ADR links, cache integrity, and git hook installationchronicle search <query>— full-text search across all.lore/markdown files with highlighted matches and file:line context;--jsonflag for machine outputchronicle serve [--port]— zero-dependency local web viewer (dark theme, sidebar nav, live search); opens in browser automaticallychronicle session save|list|show— save and browse session notes in.lore/sessions/; supports piped input for auto-summaries
Parallel Extraction
extractFromCommits()now runs LLM batches concurrently (defaultconcurrency=4for API providers,1for Ollama)--concurrency <n>flag oninitanddeepenfor manual override- Benchmark: 4 batches in parallel → ~4× speedup vs sequential for Anthropic/Gemini/OpenAI
Progressive History (--limit)
chronicle init --limit <n>— cap initial scan to N most recent commitschronicle deepen --limit <n>— process additional batches incrementally- Enables fast first-run (20 commits → ~5s with API) then deepening as needed
LLM Provider Updates
- Gemini updated to
gemini-2.5-flashwiththinkingBudget: 0(thinking mode disabled for structured extraction — 8× faster) - All providers now defensively handle partial LLM responses (missing
title,affects,riskfields no longer crash)
Null-safety fixes
buildStore,formatDeepADR,formatDecisionEntry,formatRejectionEntryall handle LLM responses missing optional fields- Cache fallback: results matched to commits by
hashfield, with positional fallback
Fixed
deepennow accepts--llm,--limit,--concurrency(was hardcoded to anthropic, no limit)git logdelimiter changed from|to\x1f(ASCII unit separator) — fixes parsing for repos with|in commit subjects
[0.4.0] — 2026-04-10
Added
Semantic Clustering Extraction (strategy: 'clustered')
extractFilesFromDiff()— parsesdiff --git a/X b/Xheaders to extract the file set touched by a commitclusterCommitsByFileOverlap()— groups commits into cohesive clusters where all members share at least one touched file- Isolated commits (no file overlap with neighbours) are batched together up to 4 per group to avoid excessive LLM calls
- Clusters respect
MAX_CLUSTER_SIZE=8andMAX_CLUSTER_CHARS=8000to stay within LLM context limits strategyClustered()— runs one LLM call per semantic cluster instead of per fixed-size batch- Pass
{ strategy: 'clustered' }toextractFromCommits()to use the new strategy
Why it matters: The v1 simple strategy could batch "add JWT auth" with unrelated CSS tweaks. The clustered strategy ensures the LLM sees a coherent feature narrative — all commits that touched auth/ together — yielding richer rationale extraction.
Tests
- 8 new clustering tests: file parsing, overlap detection, singleton merging, MAX_CLUSTER_SIZE cap, LLM call count
- Total: 64 tests passing (58 TS + 6 Python)
[0.3.0] — 2025-04-10
Added
Evolution Records (chronicle evolution)
buildEvolution()— groups git history into eras (one per release tag + current untagged work)- Each era contains: decisions made, rejections logged, most-changed files, date range
renderEvolutionMarkdown()— renders eras to human+AI-readable.lore/evolution.mdmergeWithExisting()— preserves manually-written> summaryfields when regeneratingchronicle evolution --regen— force-rebuild;--view— print to stdout- Auto-generates
evolution.mdat the end ofchronicle init - Evolution included in
chronicle injectoutput (first era, compact)
Terminal Status Indicator
- Before every write command:
◆ chronicle │ N decisions · N rejected · N ADRs · last capture: Xm ago - After every write command:
◆ chronicle wrote +N decisions, +N rejections(only if something changed) - Written to stderr — doesn't pollute
chronicle injectstdout pipe - Active for:
init,deepen,setup,diagram,evolution,capture
Tests
- 12 evolution tests: tag detection, era chaining, HEAD detection, rendering, merge behavior
- Total: 62 tests passing (56 TS + 6 Python)
[0.2.0] — 2025-04-10
Added
Tool adapters (chronicle setup --tool=<name>)
claude-code/openclaw— MCP server config (.claude/mcp.json) + SessionStart/Stop hooks (.claude/settings.json); merges with existing configcursor— generates.cursorruleswith current.lore/contextaider— writes.aider.conf.ymlwith--readentries for.lore/files; idempotentgemini-cli— generatesGEMINI.mdwith compressed contextcopilot— generates.github/copilot-instructions.mdcodex— appends Chronicle context toAGENTS.mdopencode— writes.opencode.jsonwithcontextFilesentriestrae/factory— universal pipe instructions (chronicle inject | <tool>)chronicle setupwith no args lists all available integrationschronicle setup --allinstalls every adapter at once
ASCII Diagrams (chronicle diagram)
- All diagrams are plain
.txtfiles — render anywhere (terminal, GitHub, AI context windows) architecture.txt— module tree grouped by directory, relationships from decision logdependencies.txt— import graph from source files; highlights high-blast-radius files (≥3 dependents)evolution.txt— timeline from git tags + dated decision entries, grouped by year
Tests
- 11 adapter tests covering install, idempotency, merge behavior, pipe tools
- Total: 50 tests passing (44 TS + 6 Python)
Changed
- Diagram files use
.txtextension instead of.mmd— ASCII format, no renderer needed
Unreleased
Planned
- Phase 8 (v3): Two-pass extraction (cheap LLM filter → quality model for complex decisions)
0.1.0 — 2025-04-10
Initial release of Chronicle — AI-native development memory.
Added
Core (@chronicle/core)
store.ts— file-based markdown store withfindLoreRoot(walks up like git),readStore,writeStore,appendToStore,writeDeepDecision,initStorescanner.ts— git history scanner with noise filtering (chore/style/docs/test prefixes), diff size threshold (≥20 changed lines), diff capping (4000 chars), tag detectionextractor.ts— LLM extraction engine with pluggable strategy pattern; v1simplestrategy (batches of 6, ≤5000 chars);clusteredandtwo-passslots reserved for v2/v3cache.ts— SHA-keyed JSON file cache; prevents reprocessing commits across runsExtractionCacheinterface for swappable cache backends (in-memory, file, future SQLite)
CLI (chronicle-dev)
chronicle init [--depth]— bootstraps.lore/from git history; progressive scan defaults to 6 monthschronicle inject [--files] [--full] [--format]— outputs compressed context to stdout; scopes to relevant files; supportsmarkdown,xml,plainformatschronicle deepen [--depth]— extends scan further back without reprocessing cached commitschronicle hooks install/remove— installspost-commit(async decision capture) andprepare-commit-msg(risk annotation) git hooks- Internal
chronicle captureandchronicle enrich-commitcommands (invoked by hooks)
MCP Server (@chronicle/mcp)
chronicle_get_context— injects compressed project context; scopes to files if specifiedchronicle_log_decision— AI logs architectural choices mid-sessionchronicle_log_rejection— AI logs abandoned approaches (crown jewel: prevents future repetition)chronicle_get_risks— returns blast-radius info before touching a filechronicle_save_session— summarizes session to.lore/sessions/YYYY-MM-DD.md
Python wrapper (chronicle-dev on PyPI)
- Thin subprocess wrapper; delegates all logic to Node CLI
- Detects Node ≥ 20; falls back to
npx chronicle-devif not globally installed - Entry point:
chroniclecommand identical to npm version
Project
.lore/store structure:index.md,decisions.md,decisions/,rejected.md,risks.md,evolution.md,diagrams/,sessions/- Hub-and-spoke ADR model: shallow decisions inline, complex decisions in
decisions/<slug>.md ARCHITECTURE.md— full system design documentation- GitHub Actions CI (test on every push/PR) and Release (publish npm + PyPI on tag)
- Vitest test suite for core package (store, extractor, scanner)
- pytest suite for Python wrapper
Architecture decisions
- Markdown-only store: no vector DB, no embeddings — plain files readable by any LLM
- Commit SHA cache ensures bootstrap is idempotent and cost-efficient
- Strategy pattern in extractor: v1 ships today, v2/v3 are drop-in replacements
- Python package delegates to Node — single source of truth, no duplication
v0.5.2
Changelog
All notable changes to Chronicle are documented here.
Format follows Keep a Changelog.
Versioning follows Semantic Versioning.
[0.5.0] — 2026-04-10
Added
New Commands
chronicle doctor— validates.lore/health: checks for missing files, broken ADR links, cache integrity, and git hook installationchronicle search <query>— full-text search across all.lore/markdown files with highlighted matches and file:line context;--jsonflag for machine outputchronicle serve [--port]— zero-dependency local web viewer (dark theme, sidebar nav, live search); opens in browser automaticallychronicle session save|list|show— save and browse session notes in.lore/sessions/; supports piped input for auto-summaries
Parallel Extraction
extractFromCommits()now runs LLM batches concurrently (defaultconcurrency=4for API providers,1for Ollama)--concurrency <n>flag oninitanddeepenfor manual override- Benchmark: 4 batches in parallel → ~4× speedup vs sequential for Anthropic/Gemini/OpenAI
Progressive History (--limit)
chronicle init --limit <n>— cap initial scan to N most recent commitschronicle deepen --limit <n>— process additional batches incrementally- Enables fast first-run (20 commits → ~5s with API) then deepening as needed
LLM Provider Updates
- Gemini updated to
gemini-2.5-flashwiththinkingBudget: 0(thinking mode disabled for structured extraction — 8× faster) - All providers now defensively handle partial LLM responses (missing
title,affects,riskfields no longer crash)
Null-safety fixes
buildStore,formatDeepADR,formatDecisionEntry,formatRejectionEntryall handle LLM responses missing optional fields- Cache fallback: results matched to commits by
hashfield, with positional fallback
Fixed
deepennow accepts--llm,--limit,--concurrency(was hardcoded to anthropic, no limit)git logdelimiter changed from|to\x1f(ASCII unit separator) — fixes parsing for repos with|in commit subjects
[0.4.0] — 2026-04-10
Added
Semantic Clustering Extraction (strategy: 'clustered')
extractFilesFromDiff()— parsesdiff --git a/X b/Xheaders to extract the file set touched by a commitclusterCommitsByFileOverlap()— groups commits into cohesive clusters where all members share at least one touched file- Isolated commits (no file overlap with neighbours) are batched together up to 4 per group to avoid excessive LLM calls
- Clusters respect
MAX_CLUSTER_SIZE=8andMAX_CLUSTER_CHARS=8000to stay within LLM context limits strategyClustered()— runs one LLM call per semantic cluster instead of per fixed-size batch- Pass
{ strategy: 'clustered' }toextractFromCommits()to use the new strategy
Why it matters: The v1 simple strategy could batch "add JWT auth" with unrelated CSS tweaks. The clustered strategy ensures the LLM sees a coherent feature narrative — all commits that touched auth/ together — yielding richer rationale extraction.
Tests
- 8 new clustering tests: file parsing, overlap detection, singleton merging, MAX_CLUSTER_SIZE cap, LLM call count
- Total: 64 tests passing (58 TS + 6 Python)
[0.3.0] — 2025-04-10
Added
Evolution Records (chronicle evolution)
buildEvolution()— groups git history into eras (one per release tag + current untagged work)- Each era contains: decisions made, rejections logged, most-changed files, date range
renderEvolutionMarkdown()— renders eras to human+AI-readable.lore/evolution.mdmergeWithExisting()— preserves manually-written> summaryfields when regeneratingchronicle evolution --regen— force-rebuild;--view— print to stdout- Auto-generates
evolution.mdat the end ofchronicle init - Evolution included in
chronicle injectoutput (first era, compact)
Terminal Status Indicator
- Before every write command:
◆ chronicle │ N decisions · N rejected · N ADRs · last capture: Xm ago - After every write command:
◆ chronicle wrote +N decisions, +N rejections(only if something changed) - Written to stderr — doesn't pollute
chronicle injectstdout pipe - Active for:
init,deepen,setup,diagram,evolution,capture
Tests
- 12 evolution tests: tag detection, era chaining, HEAD detection, rendering, merge behavior
- Total: 62 tests passing (56 TS + 6 Python)
[0.2.0] — 2025-04-10
Added
Tool adapters (chronicle setup --tool=<name>)
claude-code/openclaw— MCP server config (.claude/mcp.json) + SessionStart/Stop hooks (.claude/settings.json); merges with existing configcursor— generates.cursorruleswith current.lore/contextaider— writes.aider.conf.ymlwith--readentries for.lore/files; idempotentgemini-cli— generatesGEMINI.mdwith compressed contextcopilot— generates.github/copilot-instructions.mdcodex— appends Chronicle context toAGENTS.mdopencode— writes.opencode.jsonwithcontextFilesentriestrae/factory— universal pipe instructions (chronicle inject | <tool>)chronicle setupwith no args lists all available integrationschronicle setup --allinstalls every adapter at once
ASCII Diagrams (chronicle diagram)
- All diagrams are plain
.txtfiles — render anywhere (terminal, GitHub, AI context windows) architecture.txt— module tree grouped by directory, relationships from decision logdependencies.txt— import graph from source files; highlights high-blast-radius files (≥3 dependents)evolution.txt— timeline from git tags + dated decision entries, grouped by year
Tests
- 11 adapter tests covering install, idempotency, merge behavior, pipe tools
- Total: 50 tests passing (44 TS + 6 Python)
Changed
- Diagram files use
.txtextension instead of.mmd— ASCII format, no renderer needed
Unreleased
Planned
- Phase 8 (v3): Two-pass extraction (cheap LLM filter → quality model for complex decisions)
0.1.0 — 2025-04-10
Initial release of Chronicle — AI-native development memory.
Added
Core (@chronicle/core)
store.ts— file-based markdown store withfindLoreRoot(walks up like git),readStore,writeStore,appendToStore,writeDeepDecision,initStorescanner.ts— git history scanner with noise filtering (chore/style/docs/test prefixes), diff size threshold (≥20 changed lines), diff capping (4000 chars), tag detectionextractor.ts— LLM extraction engine with pluggable strategy pattern; v1simplestrategy (batches of 6, ≤5000 chars);clusteredandtwo-passslots reserved for v2/v3cache.ts— SHA-keyed JSON file cache; prevents reprocessing commits across runsExtractionCacheinterface for swappable cache backends (in-memory, file, future SQLite)
CLI (chronicle-dev)
chronicle init [--depth]— bootstraps.lore/from git history; progressive scan defaults to 6 monthschronicle inject [--files] [--full] [--format]— outputs compressed context to stdout; scopes to relevant files; supportsmarkdown,xml,plainformatschronicle deepen [--depth]— extends scan further back without reprocessing cached commitschronicle hooks install/remove— installspost-commit(async decision capture) andprepare-commit-msg(risk annotation) git hooks- Internal
chronicle captureandchronicle enrich-commitcommands (invoked by hooks)
MCP Server (@chronicle/mcp)
chronicle_get_context— injects compressed project context; scopes to files if specifiedchronicle_log_decision— AI logs architectural choices mid-sessionchronicle_log_rejection— AI logs abandoned approaches (crown jewel: prevents future repetition)chronicle_get_risks— returns blast-radius info before touching a filechronicle_save_session— summarizes session to.lore/sessions/YYYY-MM-DD.md
Python wrapper (chronicle-dev on PyPI)
- Thin subprocess wrapper; delegates all logic to Node CLI
- Detects Node ≥ 20; falls back to
npx chronicle-devif not globally installed - Entry point:
chroniclecommand identical to npm version
Project
.lore/store structure:index.md,decisions.md,decisions/,rejected.md,risks.md,evolution.md,diagrams/,sessions/- Hub-and-spoke ADR model: shallow decisions inline, complex decisions in
decisions/<slug>.md ARCHITECTURE.md— full system design documentation- GitHub Actions CI (test on every push/PR) and Release (publish npm + PyPI on tag)
- Vitest test suite for core package (store, extractor, scanner)
- pytest suite for Python wrapper
Architecture decisions
- Markdown-only store: no vector DB, no embeddings — plain files readable by any LLM
- Commit SHA cache ensures bootstrap is idempotent and cost-efficient
- Strategy pattern in extractor: v1 ships today, v2/v3 are drop-in replacements
- Python package delegates to Node — single source of truth, no duplication
v0.5.1
Changelog
All notable changes to Chronicle are documented here.
Format follows Keep a Changelog.
Versioning follows Semantic Versioning.
[0.5.0] — 2026-04-10
Added
New Commands
chronicle doctor— validates.lore/health: checks for missing files, broken ADR links, cache integrity, and git hook installationchronicle search <query>— full-text search across all.lore/markdown files with highlighted matches and file:line context;--jsonflag for machine outputchronicle serve [--port]— zero-dependency local web viewer (dark theme, sidebar nav, live search); opens in browser automaticallychronicle session save|list|show— save and browse session notes in.lore/sessions/; supports piped input for auto-summaries
Parallel Extraction
extractFromCommits()now runs LLM batches concurrently (defaultconcurrency=4for API providers,1for Ollama)--concurrency <n>flag oninitanddeepenfor manual override- Benchmark: 4 batches in parallel → ~4× speedup vs sequential for Anthropic/Gemini/OpenAI
Progressive History (--limit)
chronicle init --limit <n>— cap initial scan to N most recent commitschronicle deepen --limit <n>— process additional batches incrementally- Enables fast first-run (20 commits → ~5s with API) then deepening as needed
LLM Provider Updates
- Gemini updated to
gemini-2.5-flashwiththinkingBudget: 0(thinking mode disabled for structured extraction — 8× faster) - All providers now defensively handle partial LLM responses (missing
title,affects,riskfields no longer crash)
Null-safety fixes
buildStore,formatDeepADR,formatDecisionEntry,formatRejectionEntryall handle LLM responses missing optional fields- Cache fallback: results matched to commits by
hashfield, with positional fallback
Fixed
deepennow accepts--llm,--limit,--concurrency(was hardcoded to anthropic, no limit)git logdelimiter changed from|to\x1f(ASCII unit separator) — fixes parsing for repos with|in commit subjects
[0.4.0] — 2026-04-10
Added
Semantic Clustering Extraction (strategy: 'clustered')
extractFilesFromDiff()— parsesdiff --git a/X b/Xheaders to extract the file set touched by a commitclusterCommitsByFileOverlap()— groups commits into cohesive clusters where all members share at least one touched file- Isolated commits (no file overlap with neighbours) are batched together up to 4 per group to avoid excessive LLM calls
- Clusters respect
MAX_CLUSTER_SIZE=8andMAX_CLUSTER_CHARS=8000to stay within LLM context limits strategyClustered()— runs one LLM call per semantic cluster instead of per fixed-size batch- Pass
{ strategy: 'clustered' }toextractFromCommits()to use the new strategy
Why it matters: The v1 simple strategy could batch "add JWT auth" with unrelated CSS tweaks. The clustered strategy ensures the LLM sees a coherent feature narrative — all commits that touched auth/ together — yielding richer rationale extraction.
Tests
- 8 new clustering tests: file parsing, overlap detection, singleton merging, MAX_CLUSTER_SIZE cap, LLM call count
- Total: 64 tests passing (58 TS + 6 Python)
[0.3.0] — 2025-04-10
Added
Evolution Records (chronicle evolution)
buildEvolution()— groups git history into eras (one per release tag + current untagged work)- Each era contains: decisions made, rejections logged, most-changed files, date range
renderEvolutionMarkdown()— renders eras to human+AI-readable.lore/evolution.mdmergeWithExisting()— preserves manually-written> summaryfields when regeneratingchronicle evolution --regen— force-rebuild;--view— print to stdout- Auto-generates
evolution.mdat the end ofchronicle init - Evolution included in
chronicle injectoutput (first era, compact)
Terminal Status Indicator
- Before every write command:
◆ chronicle │ N decisions · N rejected · N ADRs · last capture: Xm ago - After every write command:
◆ chronicle wrote +N decisions, +N rejections(only if something changed) - Written to stderr — doesn't pollute
chronicle injectstdout pipe - Active for:
init,deepen,setup,diagram,evolution,capture
Tests
- 12 evolution tests: tag detection, era chaining, HEAD detection, rendering, merge behavior
- Total: 62 tests passing (56 TS + 6 Python)
[0.2.0] — 2025-04-10
Added
Tool adapters (chronicle setup --tool=<name>)
claude-code/openclaw— MCP server config (.claude/mcp.json) + SessionStart/Stop hooks (.claude/settings.json); merges with existing configcursor— generates.cursorruleswith current.lore/contextaider— writes.aider.conf.ymlwith--readentries for.lore/files; idempotentgemini-cli— generatesGEMINI.mdwith compressed contextcopilot— generates.github/copilot-instructions.mdcodex— appends Chronicle context toAGENTS.mdopencode— writes.opencode.jsonwithcontextFilesentriestrae/factory— universal pipe instructions (chronicle inject | <tool>)chronicle setupwith no args lists all available integrationschronicle setup --allinstalls every adapter at once
ASCII Diagrams (chronicle diagram)
- All diagrams are plain
.txtfiles — render anywhere (terminal, GitHub, AI context windows) architecture.txt— module tree grouped by directory, relationships from decision logdependencies.txt— import graph from source files; highlights high-blast-radius files (≥3 dependents)evolution.txt— timeline from git tags + dated decision entries, grouped by year
Tests
- 11 adapter tests covering install, idempotency, merge behavior, pipe tools
- Total: 50 tests passing (44 TS + 6 Python)
Changed
- Diagram files use
.txtextension instead of.mmd— ASCII format, no renderer needed
Unreleased
Planned
- Phase 8 (v3): Two-pass extraction (cheap LLM filter → quality model for complex decisions)
0.1.0 — 2025-04-10
Initial release of Chronicle — AI-native development memory.
Added
Core (@chronicle/core)
store.ts— file-based markdown store withfindLoreRoot(walks up like git),readStore,writeStore,appendToStore,writeDeepDecision,initStorescanner.ts— git history scanner with noise filtering (chore/style/docs/test prefixes), diff size threshold (≥20 changed lines), diff capping (4000 chars), tag detectionextractor.ts— LLM extraction engine with pluggable strategy pattern; v1simplestrategy (batches of 6, ≤5000 chars);clusteredandtwo-passslots reserved for v2/v3cache.ts— SHA-keyed JSON file cache; prevents reprocessing commits across runsExtractionCacheinterface for swappable cache backends (in-memory, file, future SQLite)
CLI (chronicle-dev)
chronicle init [--depth]— bootstraps.lore/from git history; progressive scan defaults to 6 monthschronicle inject [--files] [--full] [--format]— outputs compressed context to stdout; scopes to relevant files; supportsmarkdown,xml,plainformatschronicle deepen [--depth]— extends scan further back without reprocessing cached commitschronicle hooks install/remove— installspost-commit(async decision capture) andprepare-commit-msg(risk annotation) git hooks- Internal
chronicle captureandchronicle enrich-commitcommands (invoked by hooks)
MCP Server (@chronicle/mcp)
chronicle_get_context— injects compressed project context; scopes to files if specifiedchronicle_log_decision— AI logs architectural choices mid-sessionchronicle_log_rejection— AI logs abandoned approaches (crown jewel: prevents future repetition)chronicle_get_risks— returns blast-radius info before touching a filechronicle_save_session— summarizes session to.lore/sessions/YYYY-MM-DD.md
Python wrapper (chronicle-dev on PyPI)
- Thin subprocess wrapper; delegates all logic to Node CLI
- Detects Node ≥ 20; falls back to
npx chronicle-devif not globally installed - Entry point:
chroniclecommand identical to npm version
Project
.lore/store structure:index.md,decisions.md,decisions/,rejected.md,risks.md,evolution.md,diagrams/,sessions/- Hub-and-spoke ADR model: shallow decisions inline, complex decisions in
decisions/<slug>.md ARCHITECTURE.md— full system design documentation- GitHub Actions CI (test on every push/PR) and Release (publish npm + PyPI on tag)
- Vitest test suite for core package (store, extractor, scanner)
- pytest suite for Python wrapper
Architecture decisions
- Markdown-only store: no vector DB, no embeddings — plain files readable by any LLM
- Commit SHA cache ensures bootstrap is idempotent and cost-efficient
- Strategy pattern in extractor: v1 ships today, v2/v3 are drop-in replacements
- Python package delegates to Node — single source of truth, no duplication