Release 0.1.3 — fix issues #5, #6, #7, #8#12
Conversation
Long lowercase-hex tokens are shape-identical to the SHA digests that fill project memory, so the standalone high-entropy heuristic deliberately can't flag them. Add a labeled-hex-secret pattern that catches a 32+ char hex run only when it follows a credential label (bare token:, Authorization: without Bearer, X-...-Key:/X-...-Token: headers) the secret-assignment keyword list misses. Bare shas stay unflagged, preserving the original tradeoff. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013XgZNwHY4fx38VPBGVGbXM
memory_search(filters) and memory_record(payload) advertised opaque dict inputs, so FastMCP exposed no schema for keys/required fields. Add SearchFilters and RecordPayload TypedDicts (plus EvidenceItem) so the derived JSON Schema lists properties and marks title required. Required-ness is encoded via TypedDict inheritance, needing no Required import. Runtime behavior is unchanged; the mcp_core adapters still accept plain dicts. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013XgZNwHY4fx38VPBGVGbXM
When no .project-memory/ existed, search/guard/validate/scan_secrets/resume
raised FileNotFoundError while record/mark_status/note returned a structured
{ok:false,error} — same failure, two client contracts. And the raised message
embedded the absolute host path of the project parent.
Add _memory_missing() so every tool returns {ok:false,error}; resources keep
raising (the correct MCP resource contract) but now share a project-relative
message with no absolute path.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013XgZNwHY4fx38VPBGVGbXM
Eight cosmetic/correctness nits, none affecting stored data: - parser: clear 'tabs not allowed' error for tab-indented frontmatter - audit: drop double trailing newline (renderer no longer appends \n) - render_frontmatter: preserve non-canonical keys on re-render/status change - _stamped_inputs_hash: anchor to the generated header, not whole-file search - load_manifest: unquote values so quoted scalars compare correctly - validate: no redundant identity pass alongside a duplicate-id fail - resume: render future handoff timestamps as clock-skew, not negative days - _omitted_note: word the omission reason (per-section cap vs token budget) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013XgZNwHY4fx38VPBGVGbXM
Ships the four bug-review fixes (#5 labeled-hex secret scanning, #6 TypedDict MCP input schemas, #7 unified MCP error contract + host-path-leak fix, #8 cleanup batch) as crumb-kit 0.1.3. Bumps the package version in pyproject.toml, __init__.py, and cli.py _FALLBACK_VERSION, and syncs the RELEASING note. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013XgZNwHY4fx38VPBGVGbXM
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 437b5167d5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| import os | ||
| import sys | ||
| from pathlib import Path | ||
| from typing import TypedDict |
There was a problem hiding this comment.
Import TypedDict from typing_extensions for FastMCP
Because crumb-kit[mcp] is supported on Python 3.10/3.11, these new tool schemas can break the optional MCP server on those runtimes: FastMCP/Pydantic v2 rejects typing.TypedDict before Python 3.12 while deriving JSON schemas, so build_server() can fail when registering memory_search or memory_record. Use typing_extensions.TypedDict for the structured schemas to keep the advertised MCP extra usable on supported Python versions.
Useful? React with 👍 / 👎.
Resolves the four issues deferred from the full-codebase bug review (#4) and bumps the package to crumb-kit 0.1.3 for a PyPI release.
Fixes
labeled-hex-secretpattern that flags a 32+ char hex run only when it follows a credential label (token:,Authorization:without "Bearer",X-…-Key:/X-…-Token:headers). Bare git shas /inputs_hashdigests stay unflagged, preserving the deliberate tradeoff in_looks_high_entropy.memory_searchfilters andmemory_recordpayload now useTypedDicts (SearchFilters,RecordPayload,EvidenceItem), so FastMCP derives a real JSON Schema with properties and a requiredtitle. Required-ness is encoded via TypedDict inheritance — no new dependency. Runtime behavior unchanged.{ok: false, error}on a missing memory store (via a new_memory_missinghelper), matchingmemory_record/memory_mark_status. The message is project-relative and no longer leaks the absolute host path. Resources still raise (the correct MCP resource contract) but share the same message.auditdouble trailing newline; non-canonical frontmatter keys preserved on a status change;inputs_hashread only from the generated source-header; manifest values unquoted; no redundant identitypassalongside a duplicate-id fail; future-dated handoffs render as a clock-skew note instead of a negative age; accurate omitted-note wording (per-section cap vs token budget).Release
0.1.2 → 0.1.3inpyproject.toml,breadcrumbs/__init__.py, andbreadcrumbs/cli.py(_FALLBACK_VERSION); CHANGELOG entry added; RELEASING note synced.Verification
test_secrets.py,test_mcp.py, andtest_bugfixes.py.python -m buildclean,twine checkPASSED for wheel + sdist, bundled templates 17/4, and an installed-binary smoke test reportsbreadcrumbs 0.1.3 (record schema_version 1)with workinginit/validate.🤖 Generated with Claude Code
Generated by Claude Code