Skip to content

Release 0.1.3 — fix issues #5, #6, #7, #8#12

Merged
jumbodaddystack merged 5 commits into
mainfrom
claude/github-issues-investigation-x4gns2
Jun 27, 2026
Merged

Release 0.1.3 — fix issues #5, #6, #7, #8#12
jumbodaddystack merged 5 commits into
mainfrom
claude/github-issues-investigation-x4gns2

Conversation

@jumbodaddystack

Copy link
Copy Markdown
Owner

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

  • Secret scanner misses bare lowercase-hex tokens (intentional tradeoff — needs a decision) #5 — Secret scanner misses bare lowercase-hex tokens. Added a labeled-hex-secret pattern 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_hash digests stay unflagged, preserving the deliberate tradeoff in _looks_high_entropy.
  • MCP: tool inputs are opaque dicts — define structured input schemas #6 — Opaque dict tool inputs. memory_search filters and memory_record payload now use TypedDicts (SearchFilters, RecordPayload, EvidenceItem), so FastMCP derives a real JSON Schema with properties and a required title. Required-ness is encoded via TypedDict inheritance — no new dependency. Runtime behavior unchanged.
  • MCP: inconsistent raise-vs-return error contract + host path leak #7 — Inconsistent raise-vs-return contract + host-path leak. All MCP tools now return {ok: false, error} on a missing memory store (via a new _memory_missing helper), matching memory_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.
  • Low-severity cleanup batch from full bug review (#4) #8 — Low-severity cleanup batch (8 items): clear "tabs are not allowed" parser error; removed the audit double trailing newline; non-canonical frontmatter keys preserved on a status change; inputs_hash read only from the generated source-header; manifest values unquoted; no redundant identity pass alongside 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

  • Version bumped 0.1.2 → 0.1.3 in pyproject.toml, breadcrumbs/__init__.py, and breadcrumbs/cli.py (_FALLBACK_VERSION); CHANGELOG entry added; RELEASING note synced.

Verification

  • Full suite green: 261 tests pass (1 SDK-gated skip), including 17 new regression tests across test_secrets.py, test_mcp.py, and test_bugfixes.py.
  • Local release pipeline mirror passed: python -m build clean, twine check PASSED for wheel + sdist, bundled templates 17/4, and an installed-binary smoke test reports breadcrumbs 0.1.3 (record schema_version 1) with working init / validate.

After merge, publishing to PyPI is a manual step (create GitHub Release v0.1.3 or run Actions → release → Run workflow).

🤖 Generated with Claude Code


Generated by Claude Code

claude added 5 commits June 27, 2026 13:35
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

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread breadcrumbs/mcp_server.py
import os
import sys
from pathlib import Path
from typing import TypedDict

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

@jumbodaddystack jumbodaddystack merged commit 8e0e039 into main Jun 27, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants