Skip to content

chore(core/docs): changelog automation, ref alignment, constants unification, safety sweeps - #169

Merged
flyingrobots merged 42 commits into
mainfrom
feat/changelog-and-sweep-4
Sep 19, 2025
Merged

flyingrobots merged 42 commits into
mainfrom
feat/changelog-and-sweep-4

Conversation

@flyingrobots

@flyingrobots flyingrobots commented Sep 15, 2025 •

Copy link
Copy Markdown
Owner

This PR addresses the latest architecture/API and safety review items and adds a small CHANGELOG workflow.

Highlights

  • Changelog automation

    • tools/changelog/add_entry.py (daily dev log entries with time + short SHA)
    • Make target: make changelog-add m="One-liner" n="Optional note"
    • pre-push hook: blocks pushes to main without CHANGELOG updates (bypass: HOOKS_BYPASS=1 git push)
    • docs/DEV_SETUP.md updated with hook setup and usage
  • Journal + refs alignment

    • Added GITMIND_EDGES_REF_PREFIX (refs/gitmind/edges/)
    • New helper gm_build_ref(out, sz, prefix, branch) for safe ref construction + branch validation
    • Writer/reader now build refs via gm_build_ref
  • Constants unification

    • Removed duplicate core/include/gitmind/constants.h (public constants live in include/gitmind/constants.h)
    • Moved CBOR constants to include/gitmind/cbor/constants_cbor.h and removed internal duplicate
    • Include order adjusted (public include/ first)
  • Path + safety sweeps

    • Normalized GM_PATH_MAX=4096, removed *2 path buffers, added bounds-checked ref/path building with gm_snprintf
    • Replaced lingering ZERO_SHA string writes with safe defaults; no baked SHA strings in core logic
    • Added extern "C" wrappers to public headers; attribution.h now includes edge_attributed.h to avoid duplication
  • Tests

    • Cache query e2e (fanout/fanin after rebuild)
    • Journal mixed CBOR (covered in prior PRs)
  • Docs

    • Expanded “talk shop” docs with Mermaid diagrams
    • Recorded rejected suggestions: keep deprec macros (one release), keep c_std=c23 for CI/tooling alignment

Why

  • Enforce OID-first semantics consistently
  • Remove public/internal drift (constants)
  • Harden ref/path construction and eliminate unsafe libc usage in core
  • Establish a light but effective CHANGELOG habit

Follow-ups

  • Purge the remaining raw libc calls in core (replace with gm_* wrappers) and add truncation tests
  • Add journal ref construction tests (branch validation and bounds)
  • Optional CI check mirroring the local pre-push CHANGELOG guard
  • Consider a simple hash mixer for cache map to reduce pathological clustering; document distribution invariants

Summary by CodeRabbit

  • New Features

    • Enforced pre-push changelog & worksheet checks with bypass, local CI runner, new Make targets (changelog-add, md-verify, ci-local, docs-verify), and workflows to seed/apply review worksheets plus auto-label docs PRs.
  • Refactor

    • Safer memory/string handling, centralized ref-builder, OID‑first migration (binary OID in cache metadata), unified error/result semantics and added unused-result (nodiscard) annotations.
  • Tests

    • New unit tests for ref utils, OID-fallback equality, shard distribution, branch-name limits, and tree-size.
  • Documentation

    • Wide front-matter standardization, new docs and tooling (CBOR debug, review seeding, features ledger), templates, and automated ledger updates.

…ardening(cache): replace strcpy ZERO oid with gm_snprintf
…ants to include/gitmind/cbor; remove duplicate constants.h; set GM_PATH_MAX=4096; add gm_build_ref and align edges ref prefix
@coderabbitai

coderabbitai Bot commented Sep 15, 2025 •

Copy link
Copy Markdown
Contributor

Important

Review skipped

Review was skipped due to path filters

⛔ Files ignored due to path filters (1)
  • docs/features/images/task_dag.svg is excluded by !**/*.svg

CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including **/dist/** will override the default block on the dist directory, by removing the pattern from both the lists.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

Replaces the git-lfs pre-push hook with a Bash hook enforcing CHANGELOG and worksheet checks (HOOKS_BYPASS), introduces gm_build_ref and ref validation, migrates internals to OID-first and safer gm_* memory/string utilities, annotates results with GM_NODISCARD, maps legacy GM_* error macros to GM_ERR_*, adds tests and review‑seeding/worksheet tooling, and performs a large docs/front‑matter and CI/tooling sweep.

Changes

Cohort / File(s) Summary
Git hooks & policy
​.githooks/pre-push
New Bash pre-push enforcing CHANGELOG updates for pushes to refs/heads/main, worksheet validation for docs/code-reviews edits, HOOKS_BYPASS bypass; removes prior git-lfs delegation.
Pre-commit & one‑thing
​.pre-commit-config.yaml, tools/quality/check_one_thing.py
Adds local pre-commit hooks (frontmatter, curate-agents, one-thing, features-update) and a staged-file checker enforcing “one typedef per file”.
Make targets & local CI
Makefile, tools/ci/ci_local.sh
New targets (md-verify, changelog-add, ci-local, docs-verify, header-compile, features-update, seed-review, apply-feedback); md-lint runs extra doc checks; ci_local.sh implements Docker-first local CI with clang-tidy and a host fallback.
Build wiring & tests
meson.build, meson_options.txt, tools/gauntlet/Dockerfile.gauntlet
Move options to meson_options.txt, default to c2x, add force_local_builds; add core/src/util/ref.c to lib, new unit tests and libgit2 dependency updates, set GITMIND_DOCKER in gauntlet images.
Ref util API
core/include/gitmind/util/ref.h, core/src/util/ref.c
New public API int gm_build_ref(char *out, size_t out_sz, const char *prefix, const char *branch) with validation, safe formatting and explicit error codes.
Public headers & annotations
core/include/* (types.h, result.h, cache.h, journal.h, cbor/cbor.h, edge.h, edge_attributed.h, attribution.h)
Expose libgit2 OID info, increase GM_PATH_MAX, add GM_NODISCARD and annotate many APIs, add binary journal-tip OID (hex deprecated), add gm_edge_decode_cbor_ex, remove gm_lane_type_t, forward-declare attributed edge type.
Constants / prefix changes
include/gitmind/constants_internal.h, (removed) core/include/gitmind/constants.h
Remove legacy constants header; make SHA hex-size conditional on GIT_OID_HEXSZ; add GITMIND_EDGES_REF_PREFIX.
Cache internals
core/src/cache/* (builder.c, query.c, tree_builder.c, bitmap.c, tree_size.c)
OID-first handling with libgit2 formatting, new OID hash mixing, safer gm_* memory/string utilities, gm_build_ref usage for refs, error-code mapping to GM_ERR_*, persist binary + textual journal-tip, reduce oversized stack buffers.
Journal reader & writer
core/src/journal/reader.c, core/src/journal/writer.c
Use gm_build_ref with GITMIND_EDGES_REF_PREFIX, add CBOR debug tracing via GITMIND_CBOR_DEBUG, use safe memory APIs, writer supports GITMIND_TEST_BRANCH override for tests.
Edge encoding/decoding & hooks
core/src/edge/*, core/src/hooks/*
Prefer OID fields in CBOR with legacy-SHA backfill, OID-first equality semantics, replace unsafe memset/strncpy/memcpy with gm_mem*/gm_strcpy_safe, update error-code mappings to GM_ERR_*.
Error codes / memory safety
multiple core sources
Replace legacy GM_* error macros with GM_ERR_* variants and adopt gm_memset_safe/gm_memcpy_span/gm_strcpy_safe across sources.
Tests added/updated
core/tests/unit/*
New/updated tests: test_cache_shard_distribution, test_edge_oid_fallback, test_ref_utils, test_cache_branch_limits, test_cache_tree_size; adapt to libgit2 API and OID-first semantics.
Docs front‑matter & new pages
docs/..., README.md, CONTRIBUTING.md, AGENTS.md, docs/DEV_SETUP.md, docs/operations/Environment_Variables.md
Large sweep adding YAML front matter to many docs, new docs (CI_STRATEGY, Ref_Name_Validation, Features_Ledger, CBOR_Debugging, Review_Seeding, TECHNICAL, etc.), DEV_SETUP/Environment_Variables include HOOKS_BYPASS and CI guidance; README/CONTRIBUTING rework.
Review‑seeding & worksheet tooling + workflows
tools/docs/check_titles.py, tools/review/*, tools/review/check_worksheets.py, .github/workflows/*, .coderabbit.yml, .github/labeler.yml
Add frontmatter/title checker, seed-feedback generator/apply scripts, worksheet validator, workflows (auto-seed, seed-review, apply-feedback), CodeRabbit config, and labeler rules for docs PRs.
Agent/docs automation & progress tooling
tools/agents/curate_recent.py, scripts/update_progress.py
Tools to curate AGENTS.md, auto-update features progress bars and README, used by CI/workflows.
Misc tooling & cleanup
tools/quality/*, .github/*, AGENTS.md, src/.gitignore
New quality scripts, workflows (labeling, update-ledger), AGENTS.md curation/policies, and removal of src/.gitignore contents.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Dev as Developer
  participant Git as Git client
  participant Hook as pre-push hook

  Note over Hook: pre-push enforces main CHANGELOG + worksheet checks

  Dev->>Git: git push <remote> <refspec>
  Git->>Hook: invoke pre-push (args + stdin refs)
  Hook->>Hook: if HOOKS_BYPASS=1 -> exit 0
  Hook->>Hook: parse args, read ref-updates
  Hook->>Hook: for each ref -> if ref != refs/heads/main -> skip
  Hook->>Hook: compute range (remote..local or local^..local)
  Hook->>Git: git diff --name-only <range>
  alt CHANGELOG present
    Hook-->>Dev: exit 0
  else
    Hook-->>Dev: stderr guidance + suggested make/HOOKS_BYPASS, exit 1
  end
Loading
sequenceDiagram
  autonumber
  participant Ctx as gm_context_t
  participant Cache as gm_cache_load_meta
  participant Util as gm_build_ref
  participant Git as libgit2

  Note over Cache: OID-first cache ref resolution with legacy fallback

  Ctx->>Cache: gm_cache_load_meta(branch)
  Cache->>Util: gm_build_ref(out, sz, GITMIND_EDGES_REF_PREFIX, branch)
  alt build ok
    Cache->>Git: resolve ref -> oid
    alt oid found
      Cache->>Cache: populate journal_tip_oid_bin + journal_tip_oid
    else legacy path
      Cache->>Git: find legacy ref -> populate meta from legacy ref
    end
  else
    Cache-->>Ctx: return error
  end
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related PRs

Poem

I nibble refs and guard the push tonight,
I stitch OIDs first and make the buffers tight.
I hop through docs and seed each review,
I trace CBOR bytes and run the tests too.
— a rabbit, pleased: safe code, green checks 🐇✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Description Check ⚠️ Warning The PR description contains a thorough narrative of changes, rationale, and follow-ups but does not follow the repository's required description template: it omits the explicit "Related Issue" line, the "Type of Change" checkbox block, the structured "Testing" checkboxes, and the final "Checklist" items the template requires. Because the repository enforces that template structure for consistent reviews and automated gating, the description cannot be considered compliant as-is. For those reasons this check fails. Please update the PR body to exactly follow the repository template: add a short "Description" summary, include a "Related Issue" line (e.g., "Fixes #") if applicable, mark the appropriate "Type of Change" checkbox(es), complete the "Testing" section with which tests were added/updated and whether they pass locally/CI, and fill the final "Checklist" entries so reviewers and any automated checks can validate compliance.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The title concisely names the principal themes of the changeset—changelog automation, ref alignment, constants unification, and safety sweeps—which directly map to the hooks/docs updates, gm_build_ref/ref changes, constants/header consolidation, and memory-safety work described in the PR. It is a single, clear sentence and is not misleading. While it enumerates multiple concerns (the PR is large), it accurately reflects the main areas touched and is acceptable for a broad chore change.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 28

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (17)
core/include/gitmind/types.h (1)

23-27: Avoid fallback defining GIT_OID_RAWSZ; enforce compile-time check to prevent mismatches.

Silently defaulting to 20 risks ABI/size mismatches if libgit2 is built with SHA‑256 (32). Gate on libgit2’s define and assert allowed sizes.

-#ifndef GIT_OID_RAWSZ
-#define GIT_OID_RAWSZ 20
-#endif
-#define GM_OID_RAWSZ GIT_OID_RAWSZ
+#if !defined(GIT_OID_RAWSZ)
+# error "libgit2 must define GIT_OID_RAWSZ; include <git2/oid.h> before this header."
+#endif
+#if (GIT_OID_RAWSZ != 20) && (GIT_OID_RAWSZ != 32)
+# error "Unsupported GIT_OID_RAWSZ; expected 20 (SHA-1) or 32 (SHA-256)."
+#endif
+#define GM_OID_RAWSZ GIT_OID_RAWSZ
docs/quality/local-ci-parity.md (1)

42-46: Remove duplicated bullets in Notes.
The two bullets about clang-tidy exclusion and PR validation are repeated.

- - CI clang‑tidy excludes `core/src/hooks/`; local scripts mirror that.
- - For PRs, validate locally first, then push and check GitHub checks with `gh pr view`.
docs/code-reviews/rejected-suggestions/4d28721c4b98c6dd29f475d5a1974c2fd2d95a1a_feat-cli-safety-e2e_166_angle-includes.md (1)

17-17: Fix doubled bullet prefix (“- - …”).

Use a single “- ” for the list item.

- - We keep project headers included with quotes for consistency across CLI sources. Switching this single header to angle brackets would introduce inconsistency without functional benefit.
+ - We keep project headers included with quotes for consistency across CLI sources. Switching this single header to angle brackets would introduce inconsistency without functional benefit.
docs/code-reviews/rejected-suggestions/4d28721c4b98c6dd29f475d5a1974c2fd2d95a1a_feat-cli-safety-e2e_166_e2e-refactor.md (1)

17-17: Fix doubled bullet prefix (“- - …”).

Use a single “- ” for the list item.

- - The current script already honors GIT_MIND and common build locations. Larger refactors (e.g., richer reporting or temp dirs) will be addressed alongside test coverage changes.
+ - The current script already honors GIT_MIND and common build locations. Larger refactors (e.g., richer reporting or temp dirs) will be addressed alongside test coverage changes.
docs/audits/vision-drift.md (1)

101-101: Replace placeholder “Last reviewed: ” with an actual date or derive from front matter.

Either render from last_updated or set a concrete ISO date.

-Last reviewed: <set-on-commit>
+Last reviewed: 2025-09-15
core/src/cache/tree_builder.c (1)

68-75: Consistent handling of path-too-long cases.

process_fs_entry returns GM_ERR_BUFFER_TOO_SMALL on overflow; elsewhere lstat failures are skipped (GM_OK). Confirm this strict failure is intentional; if not, consider skipping with a warning for resilience.

docs/code-reviews/rejected-suggestions/4d28721c4b98c6dd29f475d5a1974c2fd2d95a1a_feat-cli-safety-e2e_166_umbrella-safety-include.md (1)

17-17: Fix accidental double list marker (“- - …”).

Removes markdownlint noise and renders as a single bullet.

-- - Safety utilities are CLI‑only and not part of the core public API we want consumers to depend on. Keeping them out of the umbrella avoids accidental external coupling.
+- Safety utilities are CLI‑only and not part of the core public API we want consumers to depend on. Keeping them out of the umbrella avoids accidental external coupling.
docs/code-reviews/rejected-suggestions/4d28721c4b98c6dd29f475d5a1974c2fd2d95a1a_feat-cli-safety-e2e_166_markdownlint.md (1)

17-17: Fix accidental double list marker (“- - …”).

Aligns with markdownlint expectations for lists.

-- - The project does not enforce markdownlint in CI; current README renders well and existing docs checks (links/TOC) pass. We'll adopt markdownlint rules repo‑wide in a docs sweep rather than piecemeal edits here.
+- The project does not enforce markdownlint in CI; current README renders well and existing docs checks (links/TOC) pass. We'll adopt markdownlint rules repo‑wide in a docs sweep rather than piecemeal edits here.
docs/architecture/deprecations/legacy-sha-fields.md (1)

44-49: Review the migration timeline and grace period.

The migration plan mentions "After one minor release" but doesn't specify clear version targets or timeline. Consider adding specific version numbers or dates for the deprecation phases.

-3. After one minor release, remove `src_sha`/`tgt_sha` from public structs and drop legacy CBOR keys from writers (readers may retain legacy acceptance for another cycle if needed).
+3. Target for v0.3.0: remove `src_sha`/`tgt_sha` from public structs and drop legacy CBOR keys from writers (readers may retain legacy acceptance through v0.4.0 if needed).
docs/enforcer/reviews/2025-06-22-review.md (2)

60-67: Review the union-based error message suggestion.

The proposed union structure for error messages seems unnecessarily complex for most use cases. Consider whether this optimization is needed or if a simpler approach would suffice.

-union { char small[48]; char *heap; } msg;
-uint16_t len;
-bool heap_alloc;
+char *msg;  // Always heap allocated
+size_t len;
+size_t capacity;

This simpler approach avoids the complexity of managing small string optimization while still preventing truncation.


94-96: Shell pattern could be more robust.

The grep pattern for checking TODOs might miss some variations and could be refined.

-grep -nE "(TODO|FIXME|XXX)" $(git ls-files '*.c' '*.h') && \
+rg -nE '\b(TODO|FIXME|XXX|HACK|BUG)\b' --type=c --type=h && \

Using rg with word boundaries is more precise and faster than grep.

docs/enforcer/gameplans/02-memory-architecture-revolution.md (1)

158-162: Consider safer RAII macro pattern.

The GM_WITH_ARENA macro could have issues with nested usage or early returns. Consider a more robust implementation.

-#define GM_WITH_ARENA(arena, size, name) \
-    for (gm_arena_t *arena = gm_arena_create(size, name); \
-         arena; \
-         gm_arena_destroy(arena), arena = NULL)
+#define GM_WITH_ARENA(arena, size, name) \
+    for (gm_arena_t *arena = gm_arena_create(size, name), *_cleanup = arena; \
+         arena; \
+         gm_arena_destroy(_cleanup), arena = NULL)

This prevents issues if arena is modified within the loop body.

docs/architecture/tombstone-visual.md (1)

11-208: Action: reconcile tombstone docs with implementation

Documentation states tombstones are edges with negative confidence, but the code enforces confidence in 0.0–1.0 (see include/gitmind/constants.h — GM_ERR_INVALID_CONF) and attribution filters use float min_confidence/max_confidence (include/gitmind/attribution.h). No tombstone/negative-confidence usage found. Either update the docs to describe the actual tombstone encoding (e.g., a flag/tag) or modify validation/filtering to support negative-confidence tombstones and add tests.

core/src/journal/reader.c (1)

33-33: Remove obsolete constant definition.

The REFS_GITMIND_PREFIX constant on Line 33 is no longer used since the code now uses GITMIND_EDGES_REF_PREFIX via gm_build_ref. This should be removed to avoid confusion.

-#define REFS_GITMIND_PREFIX "refs/gitmind/edges/"
docs/specs/Technical_Specifications.md (3)

40-57: API contracts: document gm_build_ref and ref-prefix constant to match PR objectives.

Specs mention deterministic, safe ref construction elsewhere in the PR. Add the ref builder and error semantics here.

 ## API Contracts
 
 Library (C):
 
 ```c
 // Normalize UTF-8 to NFC; returns length written (0 on error)
 size_t gm_utf8_nfc(char* dst, size_t dst_size, const char* src);
 
 // Deterministic 64-bit IDs for semantics
 uint64_t gm_sem_type_id(const char* type_name_utf8);
 uint64_t gm_sem_lane_id(const char* lane_name_utf8);
 
+// Build a fully-qualified ref name safely: out <- prefix + branch
+// Returns 0 on success; negative error codes on failure (e.g., GM_ERR_BUFFER_TOO_SMALL, GM_ERR_INVALID_BRANCH)
+int gm_build_ref(char* out, size_t out_sz, const char* prefix, const char* branch);
+
 // Append attributed edge (names-as-truth)
 int gm_edge_append(const gm_edge_attributed_t* edge);
 
 // List edges with filters by names; output iterator-based
 int gm_list(const gm_list_filter_t* filter, gm_edge_iter_t* out_iter);
Please confirm exact signature and error codes, then update.

---

`25-39`: **Surface constants used by the new flows.**

Call out buffer/path max and ref prefix to keep consumers aligned.

```diff
 ## Implementation Approach
@@
 - Advice
   - Minimal schema; merge via hybrid CRDT with LWW scalars and OR-Set collections
   - Application limited to `symmetric` and `implies` initially
+
+### Constants
+- `GM_PATH_MAX = 4096` (normalized; governs ref/path buffers)
+- `GITMIND_EDGES_REF_PREFIX = "refs/gitmind/edges/"` (reserved namespace for cache/journal artifacts)

71-76: Add language identifiers to fenced blocks (MD040).

Use “text” for CBOR shapes to satisfy markdownlint.

-```
+```text
 [ src_sha(20), tgt_sha(20), confidence(u16-half), timestamp(u64),
   src_path(tstr), tgt_path(tstr), ulid(tstr),
   type_name(tstr), lane_name(tstr), attribution(map) ]

- +text
{ kind: tstr, subject: tstr, props: map, ulid: tstr, ts: u64, actor: tstr }

Also applies to: 79-81

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1410219 and 5965e14.

📒 Files selected for processing (107)
  • .githooks/pre-push (1 hunks)
  • .pre-commit-config.yaml (1 hunks)
  • Makefile (1 hunks)
  • core/include/gitmind/constants.h (0 hunks)
  • core/include/gitmind/types.h (1 hunks)
  • core/include/gitmind/util/ref.h (1 hunks)
  • core/src/cache/builder.c (1 hunks)
  • core/src/cache/query.c (1 hunks)
  • core/src/cache/tree_builder.c (1 hunks)
  • core/src/journal/reader.c (2 hunks)
  • core/src/journal/writer.c (2 hunks)
  • core/src/util/ref.c (1 hunks)
  • docs/CI_STRATEGY.md (1 hunks)
  • docs/DEV_SETUP.md (2 hunks)
  • docs/Legacy_Mapping.md (1 hunks)
  • docs/PRDs/PRD-co-thought-mcp-service.md (1 hunks)
  • docs/PRDs/PRD-git-mind-semantics-time-travel-prototype.md (1 hunks)
  • docs/README.md (2 hunks)
  • docs/adr/0001-first-class-semantics.md (1 hunks)
  • docs/adr/0002-docs-reorganization.md (1 hunks)
  • docs/adult_swim.md (1 hunks)
  • docs/api/gitmind-api-reference.md (1 hunks)
  • docs/architecture/MIGRATION_PHILOSOPHY.md (1 hunks)
  • docs/architecture/MODULAR_RESTRUCTURE_PLAN.md (1 hunks)
  • docs/architecture/README.md (1 hunks)
  • docs/architecture/System_Architecture.md (1 hunks)
  • docs/architecture/attribution-integration-guide.md (1 hunks)
  • docs/architecture/attribution-system.md (1 hunks)
  • docs/architecture/attribution-use-cases.md (1 hunks)
  • docs/architecture/augments-system.md (1 hunks)
  • docs/architecture/bitmap-cache-design.md (1 hunks)
  • docs/architecture/cache-migration-oid-only.md (1 hunks)
  • docs/architecture/deprecations/legacy-sha-fields.md (1 hunks)
  • docs/architecture/journal-architecture-pivot.md (1 hunks)
  • docs/architecture/tombstone-visual.md (1 hunks)
  • docs/audits/vision-drift.md (1 hunks)
  • docs/charter/Project_Charter.md (1 hunks)
  • docs/cli/README.md (1 hunks)
  • docs/cli/combined_markdown.md (1 hunks)
  • docs/cli/gitmind-cache-rebuild.md (1 hunks)
  • docs/cli/gitmind-install-hooks.md (1 hunks)
  • docs/cli/gitmind-link.md (1 hunks)
  • docs/cli/gitmind-list.md (1 hunks)
  • docs/cli/gitmind.md (1 hunks)
  • docs/code-review/CLAUDE.md (1 hunks)
  • docs/code-reviews/rejected-suggestions/1d234c5614f96272eca5e9607d84b3655080546b_feat-cli-safety-e2e_166_valgrind-suppression-link.md (1 hunks)
  • docs/code-reviews/rejected-suggestions/4d28721c4b98c6dd29f475d5a1974c2fd2d95a1a_feat-cli-safety-e2e_166_angle-includes.md (1 hunks)
  • docs/code-reviews/rejected-suggestions/4d28721c4b98c6dd29f475d5a1974c2fd2d95a1a_feat-cli-safety-e2e_166_consumed-length.md (1 hunks)
  • docs/code-reviews/rejected-suggestions/4d28721c4b98c6dd29f475d5a1974c2fd2d95a1a_feat-cli-safety-e2e_166_e2e-refactor.md (1 hunks)
  • docs/code-reviews/rejected-suggestions/4d28721c4b98c6dd29f475d5a1974c2fd2d95a1a_feat-cli-safety-e2e_166_markdownlint.md (1 hunks)
  • docs/code-reviews/rejected-suggestions/4d28721c4b98c6dd29f475d5a1974c2fd2d95a1a_feat-cli-safety-e2e_166_replace-macros-with-literals.md (1 hunks)
  • docs/code-reviews/rejected-suggestions/4d28721c4b98c6dd29f475d5a1974c2fd2d95a1a_feat-cli-safety-e2e_166_umbrella-safety-include.md (1 hunks)
  • docs/code-reviews/rejected-suggestions/608bc03_main_cstd-c23-only.md (1 hunks)
  • docs/code-reviews/rejected-suggestions/608bc03_main_deprec-macros-augment.md (1 hunks)
  • docs/code-reviews/rejected-suggestions/ef52094_migration-finish-core-cleanup_PR164_detached-head-behavior.md (1 hunks)
  • docs/code-reviews/rejected-suggestions/ef52094_migration-finish-core-cleanup_PR165_move-test-prototypes-private.md (1 hunks)
  • docs/code-reviews/rejected-suggestions/ef52094_migration-finish-core-cleanup_PR165_reserve-extra-byte.md (1 hunks)
  • docs/code-reviews/rejected-suggestions/ef52094_migration-finish-core-cleanup_PR166_missing-umbrella-apis.md (1 hunks)
  • docs/deployment/Deployment.md (1 hunks)
  • docs/enforcer/BEFORE_WE_BEGIN.md (1 hunks)
  • docs/enforcer/build-these-in.md (1 hunks)
  • docs/enforcer/dev-journals/2025-06-22-foundations.md (1 hunks)
  • docs/enforcer/dev-journals/2025-06-23-foundations-and-shame.md (1 hunks)
  • docs/enforcer/dev-journals/2026-06-24.md (1 hunks)
  • docs/enforcer/gameplans/01-error-handling-revolution.md (1 hunks)
  • docs/enforcer/gameplans/02-memory-architecture-revolution.md (1 hunks)
  • docs/enforcer/gameplans/03-observability-built-in.md (1 hunks)
  • docs/enforcer/gameplans/04-testing-infrastructure-uplift.md (1 hunks)
  • docs/enforcer/gameplans/05-config-convention-overhaul.md (1 hunks)
  • docs/enforcer/gameplans/06-plugin-extensibility-hooks.md (1 hunks)
  • docs/enforcer/gameplans/07-security-hygiene-as-code.md (1 hunks)
  • docs/enforcer/gameplans/08-devex-internal-cli.md (1 hunks)
  • docs/enforcer/gameplans/09-domain-language-purity.md (1 hunks)
  • docs/enforcer/gameplans/10-future-proofing-without-yagni.md (1 hunks)
  • docs/enforcer/gameplans/11-gitmind-metadata-layer.md (1 hunks)
  • docs/enforcer/reviews/2025-06-22-review.md (1 hunks)
  • docs/enforcer/specs/01-error-types-spec.md (1 hunks)
  • docs/enforcer/specs/02-domain-types-spec.md (1 hunks)
  • docs/enforcer/specs/03-security-primitives-spec.md (1 hunks)
  • docs/operations/Environment_Variables.md (1 hunks)
  • docs/planning/Milestones.md (1 hunks)
  • docs/planning/Product_Roadmap.md (1 hunks)
  • docs/planning/Release_Plans.md (1 hunks)
  • docs/planning/Sprint_Plans.md (1 hunks)
  • docs/quality/Markdown_Style_Guide.md (1 hunks)
  • docs/quality/SOLID_DRY_REPORT.md (1 hunks)
  • docs/quality/TIDY_CLANG_CRUSADE.md (1 hunks)
  • docs/quality/local-ci-parity.md (1 hunks)
  • docs/quality/static-analysis-guide.md (1 hunks)
  • docs/quality/tools-vs-custom-checks.md (1 hunks)
  • docs/requirements/Requirements.md (1 hunks)
  • docs/risk/Risk_Register.md (1 hunks)
  • docs/sitrep/2025-06-24/ci-sitrep.md (1 hunks)
  • docs/specs/Technical_Specifications.md (1 hunks)
  • docs/talk-shop/centralized-cbor-keys-and-public-apis.md (1 hunks)
  • docs/talk-shop/deterministic-merges-crdt-advice.md (1 hunks)
  • docs/talk-shop/hardening-mindset.md (1 hunks)
  • docs/talk-shop/journal-first-cbor-commits.md (1 hunks)
  • docs/talk-shop/oid-first-migration.md (1 hunks)
  • docs/testing/Test_Plan.md (1 hunks)
  • docs/wish-list-features/brain-storms/CLAUDE_DEEP_THOUGHTS_FINAL.md (1 hunks)
  • docs/wish-list-features/brain-storms/plugins.md (1 hunks)
  • docs/wish-list-features/plugins2.0/00-summary.md (1 hunks)
  • docs/wish-list-features/plugins2.0/01-requirements.md (1 hunks)
  • docs/wish-list-features/plugins2.0/02-tech-design.md (1 hunks)
  • docs/wish-list-features/plugins2.0/03-api.md (1 hunks)
  • docs/wish-list-features/plugins2.0/04-test-plan.md (1 hunks)
⛔ Files not processed due to max files limit (6)
  • docs/wish-list-features/plugins2.0/05-security.md
  • include/gitmind/cbor/constants_cbor.h
  • include/gitmind/constants_internal.h
  • meson.build
  • tools/changelog/add_entry.py
  • tools/docs/check_frontmatter.py
💤 Files with no reviewable changes (1)
  • core/include/gitmind/constants.h
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{c,cc,cpp,cxx,h,hpp,hxx,m,mm}

📄 CodeRabbit inference engine (CLAUDE.md)

NEVER use NOLINT to suppress clang-tidy warnings; ALWAYS fix the underlying issue

Files:

  • core/include/gitmind/util/ref.h
  • core/src/cache/builder.c
  • core/include/gitmind/types.h
  • core/src/util/ref.c
  • core/src/cache/tree_builder.c
  • core/src/journal/reader.c
  • core/src/journal/writer.c
  • core/src/cache/query.c
core/**

📄 CodeRabbit inference engine (AGENTS.md)

Add new code under core/ (C23 library: include/ for public headers, src/ for implementation, tests/ for unit tests)

Files:

  • core/include/gitmind/util/ref.h
  • core/src/cache/builder.c
  • core/include/gitmind/types.h
  • core/src/util/ref.c
  • core/src/cache/tree_builder.c
  • core/src/journal/reader.c
  • core/src/journal/writer.c
  • core/src/cache/query.c
{core,src,apps,include}/**/*.{c,h}

📄 CodeRabbit inference engine (AGENTS.md)

{core,src,apps,include}/**/*.{c,h}: Use C23 with warnings-as-errors; forbid VLAs and variable shadowing; require explicit function prototypes
Follow .clang-format (LLVM-based, 4 spaces, 80 columns, pointer alignment right)
Function and variable names in lower_snake_case with gm_ prefix
Macro names in UPPER_SNAKE case
Type names end with _t
Prefer specific header includes; follow include ordering as enforced by .clang-format
Introduce no new clang-tidy warnings (lint via tools/docker-clang-tidy.sh)

Files:

  • core/include/gitmind/util/ref.h
  • core/src/cache/builder.c
  • core/include/gitmind/types.h
  • core/src/util/ref.c
  • core/src/cache/tree_builder.c
  • core/src/journal/reader.c
  • core/src/journal/writer.c
  • core/src/cache/query.c
{include,core,src,apps}/**/*.h

📄 CodeRabbit inference engine (AGENTS.md)

Header guards must begin with GITMIND_ and remain stable

Files:

  • core/include/gitmind/util/ref.h
  • core/include/gitmind/types.h
core/**/*.{c,h}

📄 CodeRabbit inference engine (AGENTS.md)

Prefer OID-first APIs in new core code: use git_oid (typedef gm_oid_t) and compare via git_oid_cmp

Files:

  • core/include/gitmind/util/ref.h
  • core/src/cache/builder.c
  • core/include/gitmind/types.h
  • core/src/util/ref.c
  • core/src/cache/tree_builder.c
  • core/src/journal/reader.c
  • core/src/journal/writer.c
  • core/src/cache/query.c
**/*.md

📄 CodeRabbit inference engine (AGENTS.md)

Comply with repository markdown lint rules (.markdownlint.jsonc); use make md-lint / make md-fix

Files:

  • docs/cli/gitmind-install-hooks.md
  • docs/architecture/attribution-system.md
  • docs/code-reviews/rejected-suggestions/4d28721c4b98c6dd29f475d5a1974c2fd2d95a1a_feat-cli-safety-e2e_166_e2e-refactor.md
  • docs/wish-list-features/plugins2.0/00-summary.md
  • docs/architecture/journal-architecture-pivot.md
  • docs/enforcer/gameplans/10-future-proofing-without-yagni.md
  • docs/Legacy_Mapping.md
  • docs/enforcer/gameplans/07-security-hygiene-as-code.md
  • docs/architecture/attribution-integration-guide.md
  • docs/adult_swim.md
  • docs/architecture/augments-system.md
  • docs/testing/Test_Plan.md
  • docs/architecture/attribution-use-cases.md
  • docs/cli/gitmind-list.md
  • docs/planning/Product_Roadmap.md
  • docs/code-reviews/rejected-suggestions/ef52094_migration-finish-core-cleanup_PR166_missing-umbrella-apis.md
  • docs/planning/Sprint_Plans.md
  • docs/quality/local-ci-parity.md
  • docs/risk/Risk_Register.md
  • docs/enforcer/gameplans/01-error-handling-revolution.md
  • docs/architecture/MODULAR_RESTRUCTURE_PLAN.md
  • docs/enforcer/gameplans/03-observability-built-in.md
  • docs/wish-list-features/plugins2.0/04-test-plan.md
  • docs/audits/vision-drift.md
  • docs/enforcer/gameplans/11-gitmind-metadata-layer.md
  • docs/wish-list-features/brain-storms/plugins.md
  • docs/architecture/README.md
  • docs/enforcer/gameplans/04-testing-infrastructure-uplift.md
  • docs/enforcer/gameplans/05-config-convention-overhaul.md
  • docs/architecture/MIGRATION_PHILOSOPHY.md
  • docs/code-reviews/rejected-suggestions/ef52094_migration-finish-core-cleanup_PR165_reserve-extra-byte.md
  • docs/cli/gitmind-link.md
  • docs/enforcer/BEFORE_WE_BEGIN.md
  • docs/enforcer/gameplans/09-domain-language-purity.md
  • docs/wish-list-features/plugins2.0/01-requirements.md
  • docs/enforcer/specs/01-error-types-spec.md
  • docs/code-reviews/rejected-suggestions/4d28721c4b98c6dd29f475d5a1974c2fd2d95a1a_feat-cli-safety-e2e_166_angle-includes.md
  • docs/enforcer/specs/02-domain-types-spec.md
  • docs/wish-list-features/plugins2.0/03-api.md
  • docs/code-reviews/rejected-suggestions/4d28721c4b98c6dd29f475d5a1974c2fd2d95a1a_feat-cli-safety-e2e_166_replace-macros-with-literals.md
  • docs/api/gitmind-api-reference.md
  • docs/quality/static-analysis-guide.md
  • docs/code-reviews/rejected-suggestions/608bc03_main_deprec-macros-augment.md
  • docs/enforcer/dev-journals/2026-06-24.md
  • docs/talk-shop/journal-first-cbor-commits.md
  • docs/deployment/Deployment.md
  • docs/CI_STRATEGY.md
  • docs/quality/Markdown_Style_Guide.md
  • docs/wish-list-features/plugins2.0/02-tech-design.md
  • docs/cli/gitmind.md
  • docs/PRDs/PRD-co-thought-mcp-service.md
  • docs/quality/tools-vs-custom-checks.md
  • docs/operations/Environment_Variables.md
  • docs/planning/Milestones.md
  • docs/enforcer/gameplans/02-memory-architecture-revolution.md
  • docs/enforcer/gameplans/06-plugin-extensibility-hooks.md
  • docs/enforcer/dev-journals/2025-06-22-foundations.md
  • docs/PRDs/PRD-git-mind-semantics-time-travel-prototype.md
  • docs/talk-shop/oid-first-migration.md
  • docs/code-reviews/rejected-suggestions/ef52094_migration-finish-core-cleanup_PR165_move-test-prototypes-private.md
  • docs/requirements/Requirements.md
  • docs/enforcer/reviews/2025-06-22-review.md
  • docs/talk-shop/centralized-cbor-keys-and-public-apis.md
  • docs/adr/0002-docs-reorganization.md
  • docs/architecture/bitmap-cache-design.md
  • docs/enforcer/build-these-in.md
  • docs/code-review/CLAUDE.md
  • docs/sitrep/2025-06-24/ci-sitrep.md
  • docs/architecture/deprecations/legacy-sha-fields.md
  • docs/code-reviews/rejected-suggestions/ef52094_migration-finish-core-cleanup_PR164_detached-head-behavior.md
  • docs/planning/Release_Plans.md
  • docs/talk-shop/hardening-mindset.md
  • docs/wish-list-features/brain-storms/CLAUDE_DEEP_THOUGHTS_FINAL.md
  • docs/code-reviews/rejected-suggestions/4d28721c4b98c6dd29f475d5a1974c2fd2d95a1a_feat-cli-safety-e2e_166_markdownlint.md
  • docs/architecture/System_Architecture.md
  • docs/cli/combined_markdown.md
  • docs/enforcer/dev-journals/2025-06-23-foundations-and-shame.md
  • docs/cli/gitmind-cache-rebuild.md
  • docs/cli/README.md
  • docs/README.md
  • docs/enforcer/gameplans/08-devex-internal-cli.md
  • docs/specs/Technical_Specifications.md
  • docs/quality/TIDY_CLANG_CRUSADE.md
  • docs/enforcer/specs/03-security-primitives-spec.md
  • docs/code-reviews/rejected-suggestions/608bc03_main_cstd-c23-only.md
  • docs/quality/SOLID_DRY_REPORT.md
  • docs/architecture/tombstone-visual.md
  • docs/code-reviews/rejected-suggestions/4d28721c4b98c6dd29f475d5a1974c2fd2d95a1a_feat-cli-safety-e2e_166_umbrella-safety-include.md
  • docs/code-reviews/rejected-suggestions/4d28721c4b98c6dd29f475d5a1974c2fd2d95a1a_feat-cli-safety-e2e_166_consumed-length.md
  • docs/architecture/cache-migration-oid-only.md
  • docs/DEV_SETUP.md
  • docs/talk-shop/deterministic-merges-crdt-advice.md
  • docs/adr/0001-first-class-semantics.md
  • docs/code-reviews/rejected-suggestions/1d234c5614f96272eca5e9607d84b3655080546b_feat-cli-safety-e2e_166_valgrind-suppression-link.md
  • docs/charter/Project_Charter.md
docs/**/*.md

📄 CodeRabbit inference engine (AGENTS.md)

Docs must pass link and TOC checks (tools/docs/check_docs.py --mode link|toc)

Files:

  • docs/cli/gitmind-install-hooks.md
  • docs/architecture/attribution-system.md
  • docs/code-reviews/rejected-suggestions/4d28721c4b98c6dd29f475d5a1974c2fd2d95a1a_feat-cli-safety-e2e_166_e2e-refactor.md
  • docs/wish-list-features/plugins2.0/00-summary.md
  • docs/architecture/journal-architecture-pivot.md
  • docs/enforcer/gameplans/10-future-proofing-without-yagni.md
  • docs/Legacy_Mapping.md
  • docs/enforcer/gameplans/07-security-hygiene-as-code.md
  • docs/architecture/attribution-integration-guide.md
  • docs/adult_swim.md
  • docs/architecture/augments-system.md
  • docs/testing/Test_Plan.md
  • docs/architecture/attribution-use-cases.md
  • docs/cli/gitmind-list.md
  • docs/planning/Product_Roadmap.md
  • docs/code-reviews/rejected-suggestions/ef52094_migration-finish-core-cleanup_PR166_missing-umbrella-apis.md
  • docs/planning/Sprint_Plans.md
  • docs/quality/local-ci-parity.md
  • docs/risk/Risk_Register.md
  • docs/enforcer/gameplans/01-error-handling-revolution.md
  • docs/architecture/MODULAR_RESTRUCTURE_PLAN.md
  • docs/enforcer/gameplans/03-observability-built-in.md
  • docs/wish-list-features/plugins2.0/04-test-plan.md
  • docs/audits/vision-drift.md
  • docs/enforcer/gameplans/11-gitmind-metadata-layer.md
  • docs/wish-list-features/brain-storms/plugins.md
  • docs/architecture/README.md
  • docs/enforcer/gameplans/04-testing-infrastructure-uplift.md
  • docs/enforcer/gameplans/05-config-convention-overhaul.md
  • docs/architecture/MIGRATION_PHILOSOPHY.md
  • docs/code-reviews/rejected-suggestions/ef52094_migration-finish-core-cleanup_PR165_reserve-extra-byte.md
  • docs/cli/gitmind-link.md
  • docs/enforcer/BEFORE_WE_BEGIN.md
  • docs/enforcer/gameplans/09-domain-language-purity.md
  • docs/wish-list-features/plugins2.0/01-requirements.md
  • docs/enforcer/specs/01-error-types-spec.md
  • docs/code-reviews/rejected-suggestions/4d28721c4b98c6dd29f475d5a1974c2fd2d95a1a_feat-cli-safety-e2e_166_angle-includes.md
  • docs/enforcer/specs/02-domain-types-spec.md
  • docs/wish-list-features/plugins2.0/03-api.md
  • docs/code-reviews/rejected-suggestions/4d28721c4b98c6dd29f475d5a1974c2fd2d95a1a_feat-cli-safety-e2e_166_replace-macros-with-literals.md
  • docs/api/gitmind-api-reference.md
  • docs/quality/static-analysis-guide.md
  • docs/code-reviews/rejected-suggestions/608bc03_main_deprec-macros-augment.md
  • docs/enforcer/dev-journals/2026-06-24.md
  • docs/talk-shop/journal-first-cbor-commits.md
  • docs/deployment/Deployment.md
  • docs/CI_STRATEGY.md
  • docs/quality/Markdown_Style_Guide.md
  • docs/wish-list-features/plugins2.0/02-tech-design.md
  • docs/cli/gitmind.md
  • docs/PRDs/PRD-co-thought-mcp-service.md
  • docs/quality/tools-vs-custom-checks.md
  • docs/operations/Environment_Variables.md
  • docs/planning/Milestones.md
  • docs/enforcer/gameplans/02-memory-architecture-revolution.md
  • docs/enforcer/gameplans/06-plugin-extensibility-hooks.md
  • docs/enforcer/dev-journals/2025-06-22-foundations.md
  • docs/PRDs/PRD-git-mind-semantics-time-travel-prototype.md
  • docs/talk-shop/oid-first-migration.md
  • docs/code-reviews/rejected-suggestions/ef52094_migration-finish-core-cleanup_PR165_move-test-prototypes-private.md
  • docs/requirements/Requirements.md
  • docs/enforcer/reviews/2025-06-22-review.md
  • docs/talk-shop/centralized-cbor-keys-and-public-apis.md
  • docs/adr/0002-docs-reorganization.md
  • docs/architecture/bitmap-cache-design.md
  • docs/enforcer/build-these-in.md
  • docs/code-review/CLAUDE.md
  • docs/sitrep/2025-06-24/ci-sitrep.md
  • docs/architecture/deprecations/legacy-sha-fields.md
  • docs/code-reviews/rejected-suggestions/ef52094_migration-finish-core-cleanup_PR164_detached-head-behavior.md
  • docs/planning/Release_Plans.md
  • docs/talk-shop/hardening-mindset.md
  • docs/wish-list-features/brain-storms/CLAUDE_DEEP_THOUGHTS_FINAL.md
  • docs/code-reviews/rejected-suggestions/4d28721c4b98c6dd29f475d5a1974c2fd2d95a1a_feat-cli-safety-e2e_166_markdownlint.md
  • docs/architecture/System_Architecture.md
  • docs/cli/combined_markdown.md
  • docs/enforcer/dev-journals/2025-06-23-foundations-and-shame.md
  • docs/cli/gitmind-cache-rebuild.md
  • docs/cli/README.md
  • docs/README.md
  • docs/enforcer/gameplans/08-devex-internal-cli.md
  • docs/specs/Technical_Specifications.md
  • docs/quality/TIDY_CLANG_CRUSADE.md
  • docs/enforcer/specs/03-security-primitives-spec.md
  • docs/code-reviews/rejected-suggestions/608bc03_main_cstd-c23-only.md
  • docs/quality/SOLID_DRY_REPORT.md
  • docs/architecture/tombstone-visual.md
  • docs/code-reviews/rejected-suggestions/4d28721c4b98c6dd29f475d5a1974c2fd2d95a1a_feat-cli-safety-e2e_166_umbrella-safety-include.md
  • docs/code-reviews/rejected-suggestions/4d28721c4b98c6dd29f475d5a1974c2fd2d95a1a_feat-cli-safety-e2e_166_consumed-length.md
  • docs/architecture/cache-migration-oid-only.md
  • docs/DEV_SETUP.md
  • docs/talk-shop/deterministic-merges-crdt-advice.md
  • docs/adr/0001-first-class-semantics.md
  • docs/code-reviews/rejected-suggestions/1d234c5614f96272eca5e9607d84b3655080546b_feat-cli-safety-e2e_166_valgrind-suppression-link.md
  • docs/charter/Project_Charter.md
🧠 Learnings (25)
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/include/gitmind/hooks/augment.h : Public hook APIs should use the `gm_hook_` prefix; keep header guard stable to avoid breaking includes

Applied to files:

  • core/include/gitmind/util/ref.h
📚 Learning: 2025-09-14T09:27:33.266Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-14T09:27:33.266Z
Learning: Tag all memories saved to MEMORY BANKS with at least #git-mind

Applied to files:

  • docs/cli/gitmind-install-hooks.md
  • docs/cli/gitmind-list.md
  • docs/cli/gitmind.md
  • docs/cli/README.md
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/src/journal/*.c : Add strict bounds checking for all CBOR parsing paths (lengths, indices, and buffer limits)

Applied to files:

  • core/src/cache/builder.c
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/src/journal/*.c : Validate allocation sizes before malloc and check the result immediately; avoid patterns that compute size then defer validation

Applied to files:

  • core/src/cache/builder.c
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/include/gitmind/types.h : Define and consistently use the alias `typedef git_oid gm_oid_t` as the canonical OID type

Applied to files:

  • core/include/gitmind/types.h
  • docs/talk-shop/oid-first-migration.md
  • docs/architecture/cache-migration-oid-only.md
📚 Learning: 2025-09-15T01:21:16.867Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-15T01:21:16.867Z
Learning: Applies to core/**/*.{c,h} : Prefer OID-first APIs in new core code: use git_oid (typedef gm_oid_t) and compare via git_oid_cmp

Applied to files:

  • core/include/gitmind/types.h
  • docs/talk-shop/oid-first-migration.md
📚 Learning: 2025-09-13T03:13:54.145Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-13T03:13:54.145Z
Learning: Run build, tests, clang-tidy (via tools/docker-clang-tidy.sh), and gauntlet locally before proposing changes; keep changes zero-warnings and formatted

Applied to files:

  • docs/quality/local-ci-parity.md
  • docs/quality/TIDY_CLANG_CRUSADE.md
📚 Learning: 2025-09-13T03:13:54.145Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-13T03:13:54.145Z
Learning: Use Meson/Ninja for build and tests; run lint and gauntlet locally; keep diffs minimal and pass CI with zero new clang-tidy warnings

Applied to files:

  • docs/quality/local-ci-parity.md
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/src/journal/*.c : Do not hardcode CBOR field key magic numbers; use centralized definitions from `gitmind/cbor/keys.h`

Applied to files:

  • docs/code-reviews/rejected-suggestions/ef52094_migration-finish-core-cleanup_PR165_reserve-extra-byte.md
  • docs/talk-shop/journal-first-cbor-commits.md
  • docs/talk-shop/centralized-cbor-keys-and-public-apis.md
  • core/src/journal/reader.c
  • core/src/journal/writer.c
📚 Learning: 2025-09-13T03:13:54.145Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-13T03:13:54.145Z
Learning: Applies to include/gitmind.h : Maintain umbrella API at include/gitmind.h

Applied to files:

  • docs/api/gitmind-api-reference.md
  • core/src/journal/reader.c
📚 Learning: 2025-09-15T01:21:16.866Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-15T01:21:16.866Z
Learning: Applies to include/{gitmind.h,gitmind/**/*.h} : Public headers must be umbrella-safe: compile standalone, maintain correct include order, have stable GITMIND_* header guards, and provide extern "C" when included from C++

Applied to files:

  • docs/api/gitmind-api-reference.md
  • core/src/journal/reader.c
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/include/gitmind/hooks/augment.h : Remove or timebox deprecated compatibility macros rather than keeping them indefinitely

Applied to files:

  • docs/code-reviews/rejected-suggestions/608bc03_main_deprec-macros-augment.md
📚 Learning: 2025-09-15T01:21:16.866Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-15T01:21:16.866Z
Learning: Applies to docs/**/*.md : Docs must pass link and TOC checks (tools/docs/check_docs.py --mode link|toc)

Applied to files:

  • .pre-commit-config.yaml
  • docs/README.md
  • Makefile
📚 Learning: 2025-09-15T01:21:16.866Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-15T01:21:16.866Z
Learning: Applies to **/*.md : Comply with repository markdown lint rules (.markdownlint.jsonc); use make md-lint / make md-fix

Applied to files:

  • docs/quality/Markdown_Style_Guide.md
  • Makefile
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/src/cache/*.{c,h} : Maintain consistent OID-centric naming for hash utilities and constants (e.g., `oid_hash()`, `OID_HASH_MULTIPLIER`)

Applied to files:

  • docs/talk-shop/oid-first-migration.md
  • core/src/cache/query.c
  • docs/architecture/cache-migration-oid-only.md
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/src/{cache,edge}/*.c : Use `git_oid_cmp()` for OID equality and `git_oid_raw()` when byte-access is required; avoid `memcmp` on OIDs directly

Applied to files:

  • docs/talk-shop/oid-first-migration.md
  • core/src/cache/query.c
  • docs/architecture/cache-migration-oid-only.md
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/include/gitmind/edge.h : Avoid struct bloat in `gm_edge_t`; do not store both legacy SHA arrays and OIDs long-term—phase out legacy SHA fields

Applied to files:

  • docs/talk-shop/oid-first-migration.md
  • docs/architecture/deprecations/legacy-sha-fields.md
  • core/src/journal/reader.c
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/src/edge/edge.c : When both OID and SHA are present, validate internal consistency (detect mismatches) rather than silently accepting either

Applied to files:

  • docs/architecture/deprecations/legacy-sha-fields.md
📚 Learning: 2025-09-14T09:27:33.266Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-14T09:27:33.266Z
Learning: DEVLOGs: write freely about ideas, problems noticed, insights, and memories you want to keep

Applied to files:

  • docs/wish-list-features/brain-storms/CLAUDE_DEEP_THOUGHTS_FINAL.md
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/src/journal/reader.c : Split overly long CBOR decoder functions (e.g., `gm_edge_attributed_decode_cbor_ex`) into smaller units for maintainability

Applied to files:

  • core/src/journal/reader.c
📚 Learning: 2025-09-13T03:13:54.145Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-13T03:13:54.145Z
Learning: Applies to include/gitmind/**/*.h : Public, namespaced headers live under include/gitmind/

Applied to files:

  • core/src/journal/reader.c
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/src/journal/writer.c : Base64-encode CBOR payloads in commit messages to prevent binary corruption

Applied to files:

  • core/src/journal/writer.c
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/**/meson.build : Do not hardcode `c_std=c23`; detect compiler support or provide a compatible minimum standard with feature checks

Applied to files:

  • docs/code-reviews/rejected-suggestions/608bc03_main_cstd-c23-only.md
📚 Learning: 2025-09-14T09:27:33.266Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-14T09:27:33.266Z
Learning: NEVER circumvent git hooks

Applied to files:

  • .githooks/pre-push
  • docs/DEV_SETUP.md
📚 Learning: 2025-09-14T09:27:33.266Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-14T09:27:33.266Z
Learning: NEVER alter, disable, or otherwise circumvent git hooks or tests

Applied to files:

  • docs/DEV_SETUP.md
🧬 Code graph analysis (6)
core/include/gitmind/util/ref.h (1)
core/src/util/ref.c (1)
  • gm_build_ref (18-31)
core/src/cache/builder.c (1)
core/include/gitmind/security/string.h (1)
  • gm_snprintf (74-80)
core/src/util/ref.c (1)
core/include/gitmind/security/string.h (1)
  • gm_snprintf (74-80)
core/src/journal/reader.c (1)
core/src/util/ref.c (1)
  • gm_build_ref (18-31)
core/src/journal/writer.c (1)
core/src/util/ref.c (1)
  • gm_build_ref (18-31)
core/src/cache/query.c (1)
core/include/gitmind/security/string.h (1)
  • gm_snprintf (74-80)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: lint-and-sanitize

Comment thread .githooks/pre-push Outdated
#endif
#define GM_OID_RAWSZ GIT_OID_RAWSZ
#define GM_PATH_MAX 256
#define GM_PATH_MAX 4096

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

GM_PATH_MAX = 4096 looks good; verify no lingering doubled buffers or PATH_MAX use.

This aligns with the PR intent. Please sweep for GM_PATH_MAX*2, PATH_MAX, and oversized static buffers to avoid regressions.

Run:


🏁 Script executed:

#!/bin/bash
set -euo pipefail
# Find doubled buffers and PATH_MAX usage
rg -nP --type=c --type=h -C2 '\bGM_PATH_MAX\s*\*\s*2\b|\bPATH_MAX\b'
# Grep for suspicious large fixed path buffers (may be fine; review hits)
rg -nP --type=c --type=h -C2 '\bchar\s+\w+\s*\[\s*(4096|8192|16384)\s*\]'

Length of output: 704


GM_PATH_MAX = 4096 — resolve GM_PATH_MAX*2 usage

  • core/src/cache/tree_builder.c:180 — char full_path[GM_PATH_MAX * 2]; Replace with a computed allocation (malloc/asprintf) or compute the required length and cap with GM_PATH_MAX; avoid static GM_PATH_MAX * 2.
  • No PATH_MAX usages found. The only other large static buffer is test-only: core/tests/unit/test_sha256.c:151 (char large_data[8192]).

Comment on lines +58 to +59
char full_path[GM_PATH_MAX];
char entry_rel_path[GM_PATH_MAX];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

⚠️ Potential issue

Unify path buffer sizing; remove doubled buffer.

Goal states “removed doubled buffers.” Here, process_fs_entry uses GM_PATH_MAX while process_directory_entry still uses GM_PATH_MAX*2. Use GM_PATH_MAX in both for consistent bounds/behavior.

-    char full_path[GM_PATH_MAX * 2];
+    char full_path[GM_PATH_MAX];

Also applies to: 180-180

🤖 Prompt for AI Agents
In core/src/cache/tree_builder.c around lines 58-59 (and also at line 180), the
code currently declares path buffers with inconsistent sizes (some using
GM_PATH_MAX*2); change those declarations so both use GM_PATH_MAX to unify path
buffer sizing, replacing any GM_PATH_MAX*2 instances with GM_PATH_MAX and ensure
any related uses/strncpy/strncat calls respect GM_PATH_MAX bounds.

Comment thread core/src/util/ref.c Outdated
Comment thread core/src/util/ref.c Outdated
Comment on lines +8 to +16
static int branch_valid(const char *b) {
if (!b || !*b) return 0;
for (const char *p = b; *p; ++p) {
if (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r') return 0;
if (*p == '/') return 0; /* tree path not allowed here */
}
if (b[0] == '.' && b[1] == '.' ) return 0; /* no .. */
return 1;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

⚠️ Potential issue

Harden validator and follow naming convention (gm_ prefix).

Current checks miss several Git refname constraints and the function name violates our gm_ prefix rule. Tighten validation and rename the helper.

Apply:

-static int branch_valid(const char *b) {
-    if (!b || !*b) return 0;
-    for (const char *p = b; *p; ++p) {
-        if (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r') return 0;
-        if (*p == '/') return 0; /* tree path not allowed here */
-    }
-    if (b[0] == '.' && b[1] == '.' ) return 0; /* no .. */
-    return 1;
-}
+static int gm_branch_valid(const char *b) {
+    if (!b || !*b) return 0;
+    char prev = '\0';
+    char last = '\0';
+    for (const unsigned char *p = (const unsigned char *)b; *p; ++p) {
+        unsigned char c = *p;
+        if (c <= 0x20 || c == 0x7F) return 0;             /* no control/space */
+        if (c == '/') return 0;                           /* single-segment only */
+        switch (c) {                                      /* reserved chars */
+            case '~': case '^': case ':': case '?':
+            case '*': case '[': case '\\':
+                return 0;
+        }
+        if (prev == '.' && c == '.') return 0;            /* no ".." anywhere */
+        if (prev == '@' && c == '{') return 0;            /* no "@{" */
+        prev = (char)c;
+        last = (char)c;
+    }
+    if (last == '.') return 0;                            /* no trailing '.' */
+    return 1;
+}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
static int branch_valid(const char *b) {
if (!b || !*b) return 0;
for (const char *p = b; *p; ++p) {
if (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r') return 0;
if (*p == '/') return 0; /* tree path not allowed here */
}
if (b[0] == '.' && b[1] == '.' ) return 0; /* no .. */
return 1;
}
static int gm_branch_valid(const char *b) {
if (!b || !*b) return 0;
char prev = '\0';
char last = '\0';
for (const unsigned char *p = (const unsigned char *)b; *p; ++p) {
unsigned char c = *p;
if (c <= 0x20 || c == 0x7F) return 0; /* no control/space */
if (c == '/') return 0; /* single-segment only */
switch (c) { /* reserved chars */
case '~': case '^': case ':': case '?':
case '*': case '[': case '\\':
return 0;
}
if (prev == '.' && c == '.') return 0; /* no ".." anywhere */
if (prev == '@' && c == '{') return 0; /* no "@{" */
prev = (char)c;
last = (char)c;
}
if (last == '.') return 0; /* no trailing '.' */
return 1;
}
🤖 Prompt for AI Agents
In core/src/util/ref.c around lines 8 to 16, rename branch_valid to
gm_branch_valid to follow the gm_ naming convention and harden its validation to
match Git refname constraints: ensure name is non-NULL and non-empty, reject any
ASCII control chars (<= 0x20) or DEL (0x7F), reject spaces/tabs/newlines, reject
characters: '~', '^', ':', '?', '*', '[', '\\', and the sequence "@{", reject
any component separator issues (no leading or trailing '/', no consecutive '/'
sequences), disallow names that start or end with a dot or contain a component
equal to "." or "..", reject names that end with ".lock", and reject names
containing '/' followed by or preceding '.' where that would create invalid
components; update all call sites to use the new gm_branch_valid symbol.

Comment thread docs/wish-list-features/plugins2.0/02-tech-design.md
Comment thread docs/wish-list-features/plugins2.0/03-api.md
Comment thread docs/wish-list-features/plugins2.0/04-test-plan.md
Comment thread Makefile
Comment thread Makefile Outdated
@flyingrobots

Copy link
Copy Markdown
Owner Author

Thanks for the thorough pass, CodeRabbit — addressed below and documented per repo policy.

Rejected suggestions (documented):

  • Keep canonical CHANGELOG.md in repo root; do not accept variants in pre-push guard.
    • docs/code-reviews/rejected-suggestions/5965e14_feat-changelog-and-sweep-4_PR169_pre-push-changelog-variants.md
  • Keep md-verify as a convenience alias (may aggregate more checks later).
    • docs/code-reviews/rejected-suggestions/5965e14_feat-changelog-and-sweep-4_PR169_md-verify-alias.md
  • Leave .PHONY ordering unchanged (cosmetic; avoid churn in this PR).
    • docs/code-reviews/rejected-suggestions/5965e14_feat-changelog-and-sweep-4_PR169_phony-ordering.md

Accepted/queued:

  • Replace GM_PATH_MAX * 2 buffers in core/src/cache/tree_builder.c with bounded builders (or dynamic sizing). Will land on this branch.

Open point:

  • Branch validation in gm_build_ref: current intent is a single-segment lane name (no '/'). I’ll add tests + docs to make the constraint explicit; if we need to support Git-style branch refs with '/', we can adjust in a follow-up.

@flyingrobots

Copy link
Copy Markdown
Owner Author

Update: gm_build_ref now allows Git-style refs and validates via libgit2 (git_reference_normalize_name). Rejects leading "refs/" in branch input to prevent double prefixing. Tests updated in core/tests/unit/test_ref_utils.c.

@flyingrobots

Copy link
Copy Markdown
Owner Author

Applied: removed GM_PATH_MAX*2 in core/src/cache/tree_builder.c (now GM_PATH_MAX) and included gitmind/security/string.h for gm_snprintf prototype.]}

@flyingrobots

Copy link
Copy Markdown
Owner Author

CI fix attempt:

  • Meson: switch default c_std to c2x (Meson supports c2x broadly; still enables C23 features like nullptr). This should fix setup failures in clang-20 gating and build-test.
  • Move Meson options from meson.build to meson_options.txt (Meson 1.x requires this), unblocking lint-and-sanitize matrix builds.

If this still trips clang-tidy or coverage thresholds, I will iterate on those logs next.

@flyingrobots

Copy link
Copy Markdown
Owner Author

Docs updated:

  • CI strategy: clarified C23 target expressed via Meson c2x.
  • Review artifact note: clarified c2x as an implementation detail; policy remains C23 gating.
  • New doc: docs/architecture/Ref_Name_Validation.md documenting gm_build_ref semantics (Git-style shorthands, libgit2 validation, double-prefix guard).
  • Gauntlet: set GITMIND_DOCKER=1 in Dockerfile to satisfy Meson host-build guard inside gating containers.

Also added test_ref_utils to Meson so CI runs the new ref tests.

@flyingrobots

Copy link
Copy Markdown
Owner Author

CI fixes applied:

  • README.md: conformed to markdownlint rules (underscore emphasis/strong, removed inline

    , fixed blockquote spacing/trailing spaces, removed trailing ? in heading). Also corrected a stray code fence terminator.

  • Meson: removed option() calls from meson.build (now in meson_options.txt). This resolves clang-tidy job setup failure.
  • Gauntlet: exported GITMIND_DOCKER=1 in gating images to satisfy Meson host-build guard.

I will watch the rerun. If anything else trips (clang-tidy/coverage), I will address next.

@flyingrobots

Copy link
Copy Markdown
Owner Author

Docs/env + local CI rig:

  • Documented env vars (GITMIND_CI_IMAGE, HOOKS_BYPASS) in docs/operations/Environment_Variables.md.
  • Added a local CI script: tools/ci/ci_local.sh that mirrors the C-Core Gate workflow: markdownlint + docs checks, containerized build + unit + E2E, and a clang-tidy pass using the CI image.
  • Make target: make ci-local to run it.
  • Fixed ToC check for new docs: added ToC to docs/architecture/Ref_Name_Validation.md.

Markdownlint sweep: README fixed; broader repo lint runs via ci-local target.

…ADME lint fixes

- Meson: switch to c2x and move options to meson_options.txt (unblocks setup)
- Gauntlet: export GITMIND_DOCKER=1 in gating images
- CI local rig: add tools/ci/ci_local.sh + Make target ci-local; mirror C-Core Gate
- Docs: env vars (GITMIND_CI_IMAGE, HOOKS_BYPASS), CI strategy note (c2x for C23), ref name validation doc with ToC
- README: markdownlint compliance (underscore emphasis/strong, spacing, code fence)
- Core: gm_build_ref uses libgit2 validation, allows Git-style shorthands, rejects leading refs/
- Tests: add/enable test_ref_utils; fix tree_builder buffer (GM_PATH_MAX)

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 23

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (16)
core/src/hooks/post-commit.c (1)

76-86: Realloc bug: updated pointer not propagated to caller

read_file_entry takes char **files, but calls grow_files_array(&files,...). Any realloc updates only the callee’s local pointer; the caller’s files remains stale, leading to use-after-free/corruption after a grow.

Minimal fix: pass files as char *** and write through.

-static int read_file_entry(char **files, size_t *count, size_t *capacity,
-                           char *line, ssize_t len) {
+static int read_file_entry(char ***files, size_t *count, size_t *capacity,
+                           char *line, ssize_t len) {
@@
-    if (*count >= *capacity) {
-        int error = grow_files_array(&files, capacity);
+    if (*count >= *capacity) {
+        int error = grow_files_array(files, capacity);
         if (error != GM_OK) {
             return error;
         }
     }
@@
-    files[*count] = strdup(line);
-    if (!files[*count]) {
+    (*files)[*count] = strdup(line);
+    if (!(*files)[*count]) {
         return GM_NO_MEMORY;
     }
@@
-    (*count)++;
+    (*count)++;
     return GM_OK;
 }

And update the call site:

-        error = read_file_entry(files, &count, &capacity, line, read);
+        error = read_file_entry(&files, &count, &capacity, line, read);

Also applies to: 118-121

include/gitmind/constants_internal.h (1)

17-22: Consolidate path buffer constants to avoid drift.

PATH_BUFFER_SIZE duplicates GM_PATH_MAX (now 4096). Prefer a single source (GM_PATH_MAX) to prevent inconsistencies.

core/include/gitmind/result.h (2)

4-5: Add extern "C" guard for public header umbrella safety.

Public headers must be C++‑friendly. Wrap declarations with extern "C".

 #ifndef GITMIND_RESULT_H
 #define GITMIND_RESULT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
@@
-#endif /* GITMIND_RESULT_H */
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* GITMIND_RESULT_H */

131-139: Fix comment vs. implementation mismatch in GM_TRY.

Comment says “uses __auto_type” but the macro uses typeof. Either update the comment or gate the macro to use __auto_type when available and typeof as fallback.

Minimal change (comment only):

- * Uses __auto_type (GNU extension) to work with any result type.
+ * Uses typeof (GNU/Clang extension) to work with any result type.
core/src/hooks/augment.c (2)

158-163: Check ULID generation result.

gm_ulid_generate likely returns a status. Fail early if it errors.

-    gm_ulid_generate(edge.ulid);
+    if (gm_ulid_generate(edge.ulid) != GM_OK) {
+        return GM_ERR_UNKNOWN;
+    }

26-73: Tighten libgit2 object flow (optional).

gm_hook_get_blob_sha does an extra lookup: revparse → id → commit_lookup. You can revparse directly to a commit (or peel) and skip one call. Not blocking.

core/src/edge/edge.c (3)

34-39: Remove NOLINT suppressions; fix root cause instead.

NOLINT is forbidden by guidelines.

-        // NOLINTNEXTLINE(misc-include-cleaner)
         ctx->time_ops->clock_gettime(CLOCK_REALTIME, &time_spec);
@@
-        // NOLINTNEXTLINE(misc-include-cleaner)
         (void)clock_gettime(CLOCK_REALTIME, &time_spec);

96-109: OID construction may read past src_sha on SHA‑256 builds.

git_oid_fromraw reads GIT_OID_RAWSZ bytes; src_sha is GM_SHA1_SIZE. Zero‑pad a local buffer first.

-    gm_result_void_t src_result = resolve_sha(ctx, src_path, edge.src_sha);
+    gm_result_void_t src_result = resolve_sha(ctx, src_path, edge.src_sha);
     if (!src_result.ok) {
         return (gm_result_edge_t){.ok = false, .u.err = src_result.u.err};
     }
-    git_oid_fromraw(&edge.src_oid, edge.src_sha);
+    uint8_t src_raw[GM_OID_RAWSZ]; gm_memset_safe(src_raw, sizeof src_raw, 0, sizeof src_raw);
+    (void)gm_memcpy_span(src_raw, sizeof src_raw, edge.src_sha, GM_SHA1_SIZE);
+    git_oid_fromraw(&edge.src_oid, src_raw);
@@
-    gm_result_void_t tgt_result = resolve_sha(ctx, tgt_path, edge.tgt_sha);
+    gm_result_void_t tgt_result = resolve_sha(ctx, tgt_path, edge.tgt_sha);
     if (!tgt_result.ok) {
         return (gm_result_edge_t){.ok = false, .u.err = tgt_result.u.err};
     }
-    git_oid_fromraw(&edge.tgt_oid, edge.tgt_sha);
+    uint8_t tgt_raw[GM_OID_RAWSZ]; gm_memset_safe(tgt_raw, sizeof tgt_raw, 0, sizeof tgt_raw);
+    (void)gm_memcpy_span(tgt_raw, sizeof tgt_raw, edge.tgt_sha, GM_SHA1_SIZE);
+    git_oid_fromraw(&edge.tgt_oid, tgt_raw);

332-345: Encode includes OID fields but decoder ignores them.

Decoding will fail on unknown keys; add OID cases to the switch.

     const uint8_t *src_raw = git_oid_raw(&edge->src_oid);
     const uint8_t *tgt_raw = git_oid_raw(&edge->tgt_oid);
     if (src_raw == NULL) src_raw = edge->src_sha; /* fallback */
     if (tgt_raw == NULL) tgt_raw = edge->tgt_sha; /* fallback */
     result = write_cbor_bytes(GM_CBOR_KEY_SRC_OID, buffer, available, &offset, src_raw, GM_OID_RAWSZ);

…and in decode_cbor_field:

 switch (key) {
@@
+    case GM_CBOR_KEY_SRC_OID: {
+        uint8_t raw[GM_OID_RAWSZ];
+        gm_result_void_t r = gm_cbor_read_bytes(buffer, offset, len, raw, GM_OID_RAWSZ);
+        if (!r.ok) return gm_err_void(r.u.err);
+        git_oid_fromraw(&edge->src_oid, raw);
+        return gm_ok_void();
+    }
+    case GM_CBOR_KEY_TGT_OID: {
+        uint8_t raw[GM_OID_RAWSZ];
+        gm_result_void_t r = gm_cbor_read_bytes(buffer, offset, len, raw, GM_OID_RAWSZ);
+        if (!r.ok) return gm_err_void(r.u.err);
+        git_oid_fromraw(&edge->tgt_oid, raw);
+        return gm_ok_void();
+    }
core/src/journal/reader.c (3)

109-113: gm_memset_safe usage is incorrect (missing size args).

Pass dst size and count per signature.

-    gm_memset_safe(&edge, 0, sizeof(edge));
+    gm_memset_safe(&edge, sizeof(edge), 0, sizeof(edge));

325-332: Propagate gm_build_ref error instead of collapsing to BUFFER_TOO_SMALL.

Improves diagnosability and aligns with normalized error scheme.

-    if (gm_build_ref(ref_name, sizeof(ref_name), GITMIND_EDGES_REF_PREFIX, branch) != GM_OK) {
-        return GM_ERR_BUFFER_TOO_SMALL;
-    }
+    int rc = gm_build_ref(ref_name, sizeof(ref_name), GITMIND_EDGES_REF_PREFIX, branch);
+    if (rc != GM_OK) {
+        return rc;
+    }

56-101: Use gm_ helpers in conversion for consistency (optional).*

Replace manual loops with gm_memcpy_span/gm_strcpy_safe.

-    for (size_t i = 0; i < GM_SHA1_SIZE; i++) {
-        attributed->src_sha[i] = legacy->src_sha[i];
-        attributed->tgt_sha[i] = legacy->tgt_sha[i];
-    }
+    (void)gm_memcpy_span(attributed->src_sha, GM_SHA1_SIZE, legacy->src_sha, GM_SHA1_SIZE);
+    (void)gm_memcpy_span(attributed->tgt_sha, GM_SHA1_SIZE, legacy->tgt_sha, GM_SHA1_SIZE);
@@
-    size_t src_len = strlen(legacy->src_path);
-    if (src_len >= sizeof(attributed->src_path)) {
-        src_len = sizeof(attributed->src_path) - 1;
-    }
-    for (size_t i = 0; i < src_len; i++) {
-        attributed->src_path[i] = legacy->src_path[i];
-    }
-    attributed->src_path[src_len] = '\0';
+    (void)gm_strcpy_safe(attributed->src_path, sizeof attributed->src_path, legacy->src_path);
@@
-    size_t tgt_len = strlen(legacy->tgt_path);
-    if (tgt_len >= sizeof(attributed->tgt_path)) {
-        tgt_len = sizeof(attributed->tgt_path) - 1;
-    }
-    for (size_t i = 0; i < tgt_len; i++) {
-        attributed->tgt_path[i] = legacy->tgt_path[i];
-    }
-    attributed->tgt_path[tgt_len] = '\0';
+    (void)gm_strcpy_safe(attributed->tgt_path, sizeof attributed->tgt_path, legacy->tgt_path);
@@
-    size_t ulid_len = strlen(legacy->ulid);
-    if (ulid_len >= sizeof(attributed->ulid)) {
-        ulid_len = sizeof(attributed->ulid) - 1;
-    }
-    for (size_t i = 0; i < ulid_len; i++) {
-        attributed->ulid[i] = legacy->ulid[i];
-    }
-    attributed->ulid[ulid_len] = '\0';
+    (void)gm_strcpy_safe(attributed->ulid, sizeof attributed->ulid, legacy->ulid);
core/src/cache/builder.c (1)

151-155: Unify OID hex buffer size constant.

Prefer a single constant to avoid SHA-1/SHA‑256 drift.

Apply this diff:

 static int oid_to_hex(const gm_oid_t *oid, char *out, size_t out_size) {
-    if (out_size < SHA_HEX_SIZE) return GM_INVALID_ARG;
+    if (out_size < GM_CACHE_OID_STRING_SIZE) return GM_INVALID_ARG;
     (void)git_oid_tostr(out, out_size, oid);
     return GM_OK;
 }
@@
-            char sha_hex[SHA_HEX_SIZE];
+            char sha_hex[GM_CACHE_OID_STRING_SIZE];

Also applies to: 169-176

core/src/cache/query.c (3)

231-245: Use unified OID hex size.

Avoid SHA_HEX_SIZE drift.

Apply this diff:

-    char sha_hex[SHA_HEX_SIZE];
+    char sha_hex[GM_CACHE_OID_STRING_SIZE];
@@
-        git_oid_tostr(sha_hex, sizeof sha_hex, &tmp);
+        git_oid_tostr(sha_hex, sizeof sha_hex, &tmp);

293-313: Avoid raw memcmp on OIDs in hot path.

Prefer git_oid_cmp for correctness and clarity; precompute target OID once to avoid per-edge conversions.

Apply this diff:

-typedef struct {
-    const uint8_t *target_sha;
+typedef struct {
+    gm_oid_t target_oid;
@@
-    const uint8_t *edge_sha = state->check_source
-        ? git_oid_raw(&edge->src_oid)
-        : git_oid_raw(&edge->tgt_oid);
-
-    /* Check if this edge matches our query */
-    if (memcmp(edge_sha, state->target_sha, GM_OID_RAWSZ) == 0) {
+    const gm_oid_t *edge_oid = state->check_source
+        ? &edge->src_oid
+        : &edge->tgt_oid;
+    if (git_oid_cmp(edge_oid, &state->target_oid) == 0) {

And in fallback_journal_scan initialization:

-    journal_scan_state_t state = {
-        .target_sha = sha,
-        .edges = malloc(INITIAL_EDGE_CAPACITY * sizeof(gm_edge_t)),
+    journal_scan_state_t state = {
+        .edges = malloc(INITIAL_EDGE_CAPACITY * sizeof(gm_edge_t)),
         .capacity = INITIAL_EDGE_CAPACITY,
         .count = 0,
         .check_source = check_source};
+    git_oid_fromraw(&state.target_oid, sha);

485-493: Build ref with gm_build_ref (consistency and bounds).

Unify with the rest of the file.

Apply this diff:

-        {
-            int rn = gm_snprintf(ref_name, sizeof(ref_name), "%s%s", GM_CACHE_REF_PREFIX, branch);
-            if (rn < 0 || (size_t)rn >= sizeof(ref_name)) {
-                /* fall back to estimate below */
-                rc = -1;
-            }
-        }
+        {
+            int brc = gm_build_ref(ref_name, sizeof(ref_name), GM_CACHE_REF_PREFIX, branch);
+            if (brc != GM_OK) {
+                /* fall back to estimate below */
+                rc = -1;
+            }
+        }
♻️ Duplicate comments (4)
core/src/cache/tree_builder.c (1)

55-61: Good: unified buffer sizing and safe snprintf.

Switched to GM_PATH_MAX and gm_snprintf with bounds checks. This addresses earlier feedback about GM_PATH_MAX*2.

core/src/util/ref.c (1)

11-43: Harden gm_build_ref: clear out on failure and map errors precisely.

Prevents partial refs and improves error fidelity.

 int gm_build_ref(char *out, size_t out_sz, const char *prefix,
                  const char *branch) {
-    if (!out || out_sz == 0 || !prefix || !branch) {
+    if (!out || out_sz == 0 || !prefix || !branch) {
         return GM_ERR_INVALID_ARGUMENT;
     }
-    if (*branch == '\0') {
+    out[0] = '\0';
+    if (*branch == '\0') {
         return GM_ERR_INVALID_ARGUMENT;
     }
     /* Require shorthand branch (no leading "refs/") to avoid double prefixing */
-    if (branch[0] == 'r' && branch[1] == 'e' && branch[2] == 'f' &&
-        branch[3] == 's' && branch[4] == '/') {
+    if (strncmp(branch, "refs/", 5) == 0) {
         return GM_ERR_INVALID_ARGUMENT;
     }
 
     char candidate[REF_NAME_BUFFER_SIZE];
-    int rn = gm_snprintf(candidate, sizeof candidate, "%s%s", prefix, branch);
-    if (rn < 0 || (size_t)rn >= sizeof candidate) {
-        return GM_ERR_BUFFER_TOO_SMALL;
+    int rn = gm_snprintf(candidate, sizeof candidate, "%s%s", prefix, branch);
+    if (rn < 0) {
+        return GM_ERR_INVALID_ARGUMENT;
+    }
+    if ((size_t)rn >= sizeof candidate) {
+        return GM_ERR_BUFFER_TOO_SMALL;
     }
 
     char normalized[REF_NAME_BUFFER_SIZE];
     int nrc = git_reference_normalize_name(
         normalized, sizeof normalized, candidate, 0);
     if (nrc != 0) {
         return GM_ERR_INVALID_ARGUMENT;
     }
 
-    rn = gm_snprintf(out, out_sz, "%s", normalized);
-    if (rn < 0 || (size_t)rn >= out_sz) {
-        return GM_ERR_BUFFER_TOO_SMALL;
+    rn = gm_snprintf(out, out_sz, "%s", normalized);
+    if (rn < 0) {
+        out[0] = '\0';
+        return GM_ERR_INVALID_ARGUMENT;
+    }
+    if ((size_t)rn >= out_sz) {
+        out[0] = '\0';
+        return GM_ERR_BUFFER_TOO_SMALL;
     }
     return GM_OK;
 }
Makefile (2)

27-28: md-verify alias remains redundant.

Prior feedback stands; if kept, consider folding in extra checks to justify the alias.


42-42: PHONY list update: acknowledged.

No further action given prior decision to keep ordering.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5965e14 and 4e9444a.

📒 Files selected for processing (29)
  • Makefile (1 hunks)
  • README.md (6 hunks)
  • core/include/gitmind/cache.h (2 hunks)
  • core/include/gitmind/result.h (1 hunks)
  • core/include/gitmind/util/ref.h (1 hunks)
  • core/src/cache/builder.c (8 hunks)
  • core/src/cache/query.c (10 hunks)
  • core/src/cache/tree_builder.c (3 hunks)
  • core/src/edge/edge.c (3 hunks)
  • core/src/hooks/augment.c (2 hunks)
  • core/src/hooks/post-commit.c (2 hunks)
  • core/src/journal/reader.c (5 hunks)
  • core/src/util/ref.c (1 hunks)
  • core/tests/unit/test_cache_shard_distribution.c (1 hunks)
  • core/tests/unit/test_edge_oid_fallback.c (1 hunks)
  • core/tests/unit/test_ref_utils.c (1 hunks)
  • docs/CI_STRATEGY.md (1 hunks)
  • docs/architecture/Ref_Name_Validation.md (1 hunks)
  • docs/code-review/CLAUDE.md (2 hunks)
  • docs/code-reviews/rejected-suggestions/5965e14_feat-changelog-and-sweep-4_PR169_md-verify-alias.md (1 hunks)
  • docs/code-reviews/rejected-suggestions/5965e14_feat-changelog-and-sweep-4_PR169_phony-ordering.md (1 hunks)
  • docs/code-reviews/rejected-suggestions/5965e14_feat-changelog-and-sweep-4_PR169_pre-push-changelog-variants.md (1 hunks)
  • docs/code-reviews/rejected-suggestions/608bc03_main_cstd-c23-only.md (2 hunks)
  • docs/operations/Environment_Variables.md (3 hunks)
  • include/gitmind/constants_internal.h (2 hunks)
  • meson.build (4 hunks)
  • meson_options.txt (1 hunks)
  • tools/ci/ci_local.sh (1 hunks)
  • tools/gauntlet/Dockerfile.gauntlet (2 hunks)
🧰 Additional context used
📓 Path-based instructions (10)
**/*.{c,cc,cpp,cxx,h,hpp,hxx,m,mm}

📄 CodeRabbit inference engine (CLAUDE.md)

NEVER use NOLINT to suppress clang-tidy warnings; ALWAYS fix the underlying issue

Files:

  • core/src/hooks/augment.c
  • core/src/hooks/post-commit.c
  • core/tests/unit/test_ref_utils.c
  • core/tests/unit/test_cache_shard_distribution.c
  • core/include/gitmind/cache.h
  • core/src/util/ref.c
  • core/src/edge/edge.c
  • core/tests/unit/test_edge_oid_fallback.c
  • core/include/gitmind/util/ref.h
  • include/gitmind/constants_internal.h
  • core/src/journal/reader.c
  • core/src/cache/builder.c
  • core/src/cache/tree_builder.c
  • core/include/gitmind/result.h
  • core/src/cache/query.c
core/**

📄 CodeRabbit inference engine (AGENTS.md)

Add new code under core/ (C23 library: include/ for public headers, src/ for implementation, tests/ for unit tests)

Files:

  • core/src/hooks/augment.c
  • core/src/hooks/post-commit.c
  • core/tests/unit/test_ref_utils.c
  • core/tests/unit/test_cache_shard_distribution.c
  • core/include/gitmind/cache.h
  • core/src/util/ref.c
  • core/src/edge/edge.c
  • core/tests/unit/test_edge_oid_fallback.c
  • core/include/gitmind/util/ref.h
  • core/src/journal/reader.c
  • core/src/cache/builder.c
  • core/src/cache/tree_builder.c
  • core/include/gitmind/result.h
  • core/src/cache/query.c
{core,src,apps,include}/**/*.{c,h}

📄 CodeRabbit inference engine (AGENTS.md)

{core,src,apps,include}/**/*.{c,h}: Use C23 with warnings-as-errors; forbid VLAs and variable shadowing; require explicit function prototypes
Follow .clang-format (LLVM-based, 4 spaces, 80 columns, pointer alignment right)
Function and variable names in lower_snake_case with gm_ prefix
Macro names in UPPER_SNAKE case
Type names end with _t
Prefer specific header includes; follow include ordering as enforced by .clang-format
Introduce no new clang-tidy warnings (lint via tools/docker-clang-tidy.sh)

Files:

  • core/src/hooks/augment.c
  • core/src/hooks/post-commit.c
  • core/tests/unit/test_ref_utils.c
  • core/tests/unit/test_cache_shard_distribution.c
  • core/include/gitmind/cache.h
  • core/src/util/ref.c
  • core/src/edge/edge.c
  • core/tests/unit/test_edge_oid_fallback.c
  • core/include/gitmind/util/ref.h
  • include/gitmind/constants_internal.h
  • core/src/journal/reader.c
  • core/src/cache/builder.c
  • core/src/cache/tree_builder.c
  • core/include/gitmind/result.h
  • core/src/cache/query.c
core/**/*.{c,h}

📄 CodeRabbit inference engine (AGENTS.md)

Prefer OID-first APIs in new core code: use git_oid (typedef gm_oid_t) and compare via git_oid_cmp

Files:

  • core/src/hooks/augment.c
  • core/src/hooks/post-commit.c
  • core/tests/unit/test_ref_utils.c
  • core/tests/unit/test_cache_shard_distribution.c
  • core/include/gitmind/cache.h
  • core/src/util/ref.c
  • core/src/edge/edge.c
  • core/tests/unit/test_edge_oid_fallback.c
  • core/include/gitmind/util/ref.h
  • core/src/journal/reader.c
  • core/src/cache/builder.c
  • core/src/cache/tree_builder.c
  • core/include/gitmind/result.h
  • core/src/cache/query.c
core/tests/unit/test_*.c

📄 CodeRabbit inference engine (AGENTS.md)

Unit tests live in core/tests/unit/ and are named test_.c; keep tests deterministic and isolated

Files:

  • core/tests/unit/test_ref_utils.c
  • core/tests/unit/test_cache_shard_distribution.c
  • core/tests/unit/test_edge_oid_fallback.c
**/*.md

📄 CodeRabbit inference engine (AGENTS.md)

Comply with repository markdown lint rules (.markdownlint.jsonc); use make md-lint / make md-fix

Files:

  • docs/code-reviews/rejected-suggestions/5965e14_feat-changelog-and-sweep-4_PR169_pre-push-changelog-variants.md
  • docs/code-reviews/rejected-suggestions/5965e14_feat-changelog-and-sweep-4_PR169_phony-ordering.md
  • docs/code-reviews/rejected-suggestions/5965e14_feat-changelog-and-sweep-4_PR169_md-verify-alias.md
  • docs/architecture/Ref_Name_Validation.md
  • docs/code-review/CLAUDE.md
  • docs/operations/Environment_Variables.md
  • docs/code-reviews/rejected-suggestions/608bc03_main_cstd-c23-only.md
  • docs/CI_STRATEGY.md
  • README.md
docs/**/*.md

📄 CodeRabbit inference engine (AGENTS.md)

Docs must pass link and TOC checks (tools/docs/check_docs.py --mode link|toc)

Files:

  • docs/code-reviews/rejected-suggestions/5965e14_feat-changelog-and-sweep-4_PR169_pre-push-changelog-variants.md
  • docs/code-reviews/rejected-suggestions/5965e14_feat-changelog-and-sweep-4_PR169_phony-ordering.md
  • docs/code-reviews/rejected-suggestions/5965e14_feat-changelog-and-sweep-4_PR169_md-verify-alias.md
  • docs/architecture/Ref_Name_Validation.md
  • docs/code-review/CLAUDE.md
  • docs/operations/Environment_Variables.md
  • docs/code-reviews/rejected-suggestions/608bc03_main_cstd-c23-only.md
  • docs/CI_STRATEGY.md
{include,core,src,apps}/**/*.h

📄 CodeRabbit inference engine (AGENTS.md)

Header guards must begin with GITMIND_ and remain stable

Files:

  • core/include/gitmind/cache.h
  • core/include/gitmind/util/ref.h
  • include/gitmind/constants_internal.h
  • core/include/gitmind/result.h
include/gitmind/**/*.h

📄 CodeRabbit inference engine (AGENTS.md)

Place namespaced public headers under include/gitmind/

Files:

  • include/gitmind/constants_internal.h
include/{gitmind.h,gitmind/**/*.h}

📄 CodeRabbit inference engine (AGENTS.md)

Public headers must be umbrella-safe: compile standalone, maintain correct include order, have stable GITMIND_* header guards, and provide extern "C" when included from C++

Files:

  • include/gitmind/constants_internal.h
🧠 Learnings (30)
📓 Common learnings
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/src/{cache,edge}/*.c : Use `git_oid_cmp()` for OID equality and `git_oid_raw()` when byte-access is required; avoid `memcmp` on OIDs directly
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/src/**/*.c : Normalize error handling to a single scheme (prefer `GM_OK`/`GM_ERR_*`) and avoid mixing raw libgit2 error codes
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-15T01:21:16.867Z
Learning: Applies to core/**/*.{c,h} : Prefer OID-first APIs in new core code: use git_oid (typedef gm_oid_t) and compare via git_oid_cmp
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/include/gitmind/hooks/augment.h : Public hook APIs should use the `gm_hook_` prefix; keep header guard stable to avoid breaking includes

Applied to files:

  • core/src/hooks/augment.c
  • core/src/hooks/post-commit.c
  • core/include/gitmind/util/ref.h
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/include/gitmind/hooks/augment.h : Remove or timebox deprecated compatibility macros rather than keeping them indefinitely

Applied to files:

  • core/src/hooks/augment.c
📚 Learning: 2025-09-13T03:13:54.145Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-13T03:13:54.145Z
Learning: Applies to include/gitmind.h : Maintain umbrella API at include/gitmind.h

Applied to files:

  • core/src/hooks/augment.c
  • core/src/hooks/post-commit.c
  • core/include/gitmind/cache.h
  • core/src/edge/edge.c
  • core/include/gitmind/util/ref.h
  • include/gitmind/constants_internal.h
  • core/src/journal/reader.c
  • core/src/cache/builder.c
  • core/src/cache/tree_builder.c
  • core/src/cache/query.c
📚 Learning: 2025-09-15T01:21:16.866Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-15T01:21:16.866Z
Learning: Applies to include/{gitmind.h,gitmind/**/*.h} : Public headers must be umbrella-safe: compile standalone, maintain correct include order, have stable GITMIND_* header guards, and provide extern "C" when included from C++

Applied to files:

  • core/src/hooks/augment.c
  • core/src/journal/reader.c
  • core/src/cache/tree_builder.c
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/include/gitmind/edge.h : Avoid struct bloat in `gm_edge_t`; do not store both legacy SHA arrays and OIDs long-term—phase out legacy SHA fields

Applied to files:

  • core/src/hooks/augment.c
  • core/include/gitmind/cache.h
  • core/src/edge/edge.c
  • core/tests/unit/test_edge_oid_fallback.c
  • include/gitmind/constants_internal.h
  • core/src/journal/reader.c
  • core/src/cache/builder.c
  • core/src/cache/query.c
📚 Learning: 2025-09-13T03:13:54.145Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-13T03:13:54.145Z
Learning: Applies to {include,core/include}/**/*.h : Header guards use GITMIND_* naming

Applied to files:

  • core/src/hooks/post-commit.c
  • core/include/gitmind/cache.h
  • core/src/cache/tree_builder.c
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/src/cache/*.{c,h} : Maintain consistent OID-centric naming for hash utilities and constants (e.g., `oid_hash()`, `OID_HASH_MULTIPLIER`)

Applied to files:

  • core/tests/unit/test_cache_shard_distribution.c
  • core/include/gitmind/cache.h
  • core/src/cache/builder.c
📚 Learning: 2025-09-13T03:13:54.145Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-13T03:13:54.145Z
Learning: Applies to core/tests/unit/test_*.c : Unit tests live in core/tests/unit/ and are named test_<module>.c; keep tests deterministic and isolated

Applied to files:

  • core/tests/unit/test_cache_shard_distribution.c
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/src/{cache,edge}/*.c : Use `git_oid_cmp()` for OID equality and `git_oid_raw()` when byte-access is required; avoid `memcmp` on OIDs directly

Applied to files:

  • core/tests/unit/test_cache_shard_distribution.c
  • core/include/gitmind/cache.h
  • core/tests/unit/test_edge_oid_fallback.c
  • core/src/cache/builder.c
  • core/src/cache/query.c
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/include/gitmind/types.h : Define and consistently use the alias `typedef git_oid gm_oid_t` as the canonical OID type

Applied to files:

  • core/include/gitmind/cache.h
📚 Learning: 2025-09-15T01:21:16.867Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-15T01:21:16.867Z
Learning: Applies to core/**/*.{c,h} : Prefer OID-first APIs in new core code: use git_oid (typedef gm_oid_t) and compare via git_oid_cmp

Applied to files:

  • core/include/gitmind/cache.h
  • core/tests/unit/test_edge_oid_fallback.c
  • core/src/cache/builder.c
📚 Learning: 2025-09-13T03:13:54.145Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-13T03:13:54.145Z
Learning: Use Meson/Ninja for build and tests; run lint and gauntlet locally; keep diffs minimal and pass CI with zero new clang-tidy warnings

Applied to files:

  • tools/ci/ci_local.sh
  • meson.build
📚 Learning: 2025-09-13T03:13:54.145Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-13T03:13:54.145Z
Learning: Run build, tests, clang-tidy (via tools/docker-clang-tidy.sh), and gauntlet locally before proposing changes; keep changes zero-warnings and formatted

Applied to files:

  • tools/ci/ci_local.sh
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/**/*.c : Use bounded string functions (e.g., `gm_snprintf`) and ensure explicit NUL termination on all string operations

Applied to files:

  • core/src/util/ref.c
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/src/edge/edge.c : `gm_edge_equal()` must not use OR-style fallback; if OIDs are present use them exclusively, otherwise compare legacy fields—never consider objects equal when OIDs differ

Applied to files:

  • core/src/edge/edge.c
  • core/tests/unit/test_edge_oid_fallback.c
  • core/src/journal/reader.c
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/**/meson.build : Do not hardcode `c_std=c23`; detect compiler support or provide a compatible minimum standard with feature checks

Applied to files:

  • docs/code-review/CLAUDE.md
  • docs/code-reviews/rejected-suggestions/608bc03_main_cstd-c23-only.md
  • meson.build
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/src/edge/edge.c : When both OID and SHA are present, validate internal consistency (detect mismatches) rather than silently accepting either

Applied to files:

  • core/tests/unit/test_edge_oid_fallback.c
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/src/journal/*.c : Do not hardcode CBOR field key magic numbers; use centralized definitions from `gitmind/cbor/keys.h`

Applied to files:

  • include/gitmind/constants_internal.h
  • core/src/journal/reader.c
📚 Learning: 2025-09-14T09:27:33.266Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-14T09:27:33.266Z
Learning: NEVER alter, disable, or otherwise circumvent git hooks or tests

Applied to files:

  • docs/operations/Environment_Variables.md
📚 Learning: 2025-09-14T09:27:33.266Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-14T09:27:33.266Z
Learning: NEVER circumvent git hooks

Applied to files:

  • docs/operations/Environment_Variables.md
📚 Learning: 2025-09-15T01:21:16.866Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-15T01:21:16.866Z
Learning: Applies to {core,src,apps,include}/**/*.{c,h} : Use C23 with warnings-as-errors; forbid VLAs and variable shadowing; require explicit function prototypes

Applied to files:

  • docs/code-reviews/rejected-suggestions/608bc03_main_cstd-c23-only.md
📚 Learning: 2025-09-13T03:13:54.145Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-13T03:13:54.145Z
Learning: Applies to {core,include}/**/*.{c,h} : Language: C23 with warnings-as-errors; no VLAs; no variable shadowing; use explicit prototypes

Applied to files:

  • docs/code-reviews/rejected-suggestions/608bc03_main_cstd-c23-only.md
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/src/journal/reader.c : Split overly long CBOR decoder functions (e.g., `gm_edge_attributed_decode_cbor_ex`) into smaller units for maintainability

Applied to files:

  • core/src/journal/reader.c
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/src/journal/*.c : Add strict bounds checking for all CBOR parsing paths (lengths, indices, and buffer limits)

Applied to files:

  • core/src/journal/reader.c
📚 Learning: 2025-09-13T03:13:54.145Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-13T03:13:54.145Z
Learning: Applies to include/gitmind/**/*.h : Public, namespaced headers live under include/gitmind/

Applied to files:

  • core/src/journal/reader.c
  • core/src/cache/tree_builder.c
📚 Learning: 2025-09-15T01:21:16.866Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-15T01:21:16.866Z
Learning: Applies to {include,core,src,apps}/**/*.h : Header guards must begin with GITMIND_ and remain stable

Applied to files:

  • core/src/cache/tree_builder.c
📚 Learning: 2025-09-15T01:21:16.866Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-15T01:21:16.866Z
Learning: Applies to **/*.md : Comply with repository markdown lint rules (.markdownlint.jsonc); use make md-lint / make md-fix

Applied to files:

  • Makefile
📚 Learning: 2025-09-15T01:21:16.866Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-15T01:21:16.866Z
Learning: Applies to docs/**/*.md : Docs must pass link and TOC checks (tools/docs/check_docs.py --mode link|toc)

Applied to files:

  • Makefile
📚 Learning: 2025-09-14T09:27:33.266Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-14T09:27:33.266Z
Learning: Tag all memories saved to MEMORY BANKS with at least #git-mind

Applied to files:

  • README.md
🧬 Code graph analysis (12)
core/src/hooks/augment.c (1)
core/include/gitmind/util/memory.h (1)
  • gm_strcpy_safe (113-138)
core/src/hooks/post-commit.c (1)
core/include/gitmind/security/memory.h (1)
  • gm_memset_safe (47-59)
core/tests/unit/test_ref_utils.c (2)
core/src/util/ref.c (1)
  • gm_build_ref (11-43)
core/include/gitmind/util/memory.h (1)
  • gm_strcpy_safe (113-138)
core/tests/unit/test_cache_shard_distribution.c (1)
core/tests/unit/test_edge_oid_fallback.c (1)
  • main (10-36)
core/src/util/ref.c (1)
core/include/gitmind/security/string.h (1)
  • gm_snprintf (74-80)
core/src/edge/edge.c (2)
core/include/gitmind/security/memory.h (1)
  • gm_memset_safe (47-59)
core/include/gitmind/util/memory.h (1)
  • gm_strcpy_safe (113-138)
core/tests/unit/test_edge_oid_fallback.c (1)
core/src/edge/edge.c (1)
  • gm_edge_equal (130-155)
core/include/gitmind/util/ref.h (1)
core/src/util/ref.c (1)
  • gm_build_ref (11-43)
core/src/journal/reader.c (3)
core/include/gitmind/security/memory.h (1)
  • gm_memset_safe (47-59)
core/include/gitmind/util/memory.h (2)
  • gm_memcpy_span (32-47)
  • gm_strcpy_safe (113-138)
core/src/util/ref.c (1)
  • gm_build_ref (11-43)
core/src/cache/builder.c (3)
core/src/util/ref.c (1)
  • gm_build_ref (11-43)
core/include/gitmind/security/memory.h (1)
  • gm_memset_safe (47-59)
core/include/gitmind/util/memory.h (1)
  • gm_strcpy_safe (113-138)
core/include/gitmind/result.h (1)
core/include/gitmind/cache/bitmap.h (1)
  • nodiscard (44-48)
core/src/cache/query.c (3)
core/src/util/ref.c (1)
  • gm_build_ref (11-43)
core/include/gitmind/security/memory.h (1)
  • gm_memset_safe (47-59)
core/include/gitmind/util/memory.h (2)
  • gm_strcpy_safe (113-138)
  • gm_memcpy_span (32-47)
🪛 GitHub Actions: Core Quality Checks
meson.build

[error] 294-294: meson.build:294:17: ERROR: Tried to create target "test_ref_utils", but a target of that name already exists.

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Compat Canaries (non-blocking) (gcc-12)
  • GitHub Check: Compat Canaries (non-blocking) (clang-19)
  • GitHub Check: Compat Canaries (non-blocking) (gcc-13)
  • GitHub Check: Compat Canaries (non-blocking) (clang-18)
🔇 Additional comments (27)
tools/gauntlet/Dockerfile.gauntlet (1)

8-8: LGTM: Explicit container context flag

Setting GITMIND_DOCKER=1 in both bases is consistent with the Meson host‑build guard. Ensure no code paths treat this as a security bypass outside CI.

If not already, confirm Meson/build scripts only use GITMIND_DOCKER to relax “host build” checks and not to skip tests.

Also applies to: 119-119

docs/code-reviews/rejected-suggestions/5965e14_feat-changelog-and-sweep-4_PR169_pre-push-changelog-variants.md (1)

1-33: LGTM: Clear decision record

Front matter looks valid; rationale is concise. Ensure the link passes docs link checks.

Run: make md-lint && tools/docs/check_docs.py --mode link --paths docs

docs/code-review/CLAUDE.md (1)

1-9: LGTM: Build notes align with CI policy

Front matter and C23/c2x note are consistent with the CI strategy. Keep this in sync with CI_STRATEGY to avoid drift.

Run: make md-lint && tools/docs/check_docs.py --mode toc --paths docs

Also applies to: 139-139

docs/code-reviews/rejected-suggestions/5965e14_feat-changelog-and-sweep-4_PR169_phony-ordering.md (1)

1-32: LGTM: Cosmetic-only rejection captured

No lint blockers anticipated. Include in docs index if applicable.

docs/CI_STRATEGY.md (1)

1-9: LGTM: CI gating and canary split documented

Content matches the introduced compiler matrix and deterministic Docker approach. Mermaid block looks well-formed.

Please run: make md-lint && tools/docs/check_docs.py --mode link --paths docs

Also applies to: 15-46, 48-75

docs/code-reviews/rejected-suggestions/608bc03_main_cstd-c23-only.md (1)

1-31: LGTM: Policy clarified (C23 target via c2x)

Note about c2x expressing C23 semantics is accurate and matches CI gating.

meson_options.txt (1)

1-5: Options added — verified usage; confirm defaults

Options look fine. meson.build reads get_option('enable_io'|'enable_time'|'enable_util'|'enable_utf8') and appends -DGITMIND_ENABLE_* cargs (meson.build lines 49, 52, 55, 58). meson_options.txt sets enable_utf8=true and the others=false — confirm the utf8-on default is intentional.

docs/code-reviews/rejected-suggestions/5965e14_feat-changelog-and-sweep-4_PR169_md-verify-alias.md (1)

1-33: LGTM for archive note.

Front matter and rationale read clean; link to the original discussion included. No blockers.

README.md (1)

20-25: LGTM — messaging tweaks and lint-friendly emphasis.

Text edits improve clarity and should satisfy markdownlint. No action needed.

core/src/cache/tree_builder.c (1)

176-182: Good: consistent GM_PATH_MAX in directory entry path building.

Consistent sizing reduces surprises and matches GM_PATH_MAX=4096.

core/src/hooks/augment.c (1)

85-113: LOOKBACK_LIMIT is defined; confirm GM_AUGMENT_LOOKBACK_LIMIT's numeric value
LOOKBACK_LIMIT is aliased to GM_AUGMENT_LOOKBACK_LIMIT in core/include/gitmind/hooks/augment.h:28 — verify the actual numeric value of GM_AUGMENT_LOOKBACK_LIMIT is intentional and appropriate for journal scans.

core/tests/unit/test_ref_utils.c (2)

12-21: Good coverage for valid/invalid branches.

Happy path and “refs/heads/*” rejection look correct.


29-35: String copy truncation test is precise.

Covers return code and termination semantics well.

core/src/edge/edge.c (1)

186-195: Format function looks correct.

Bounds-checked gm_snprintf with clear error mapping.

core/tests/unit/test_edge_oid_fallback.c (1)

27-33: LGTM.

Covers both fallback and OID-preferred paths.

core/src/journal/reader.c (1)

154-165: Good migration to gm_ safe copies.*

Byte-size checked copies reduce UB risk.

core/include/gitmind/cache.h (1)

13-13: Include gm_oid_t: LGTM.

Brings gm_oid_t into scope for public API; matches OID-first direction.

Makefile (2)

38-41: ci-local helper: LGTM.

Provides parity with gate; nice.


23-25: Docs checks in md-lint: LGTM.
Confirmed tools/docs/check_frontmatter.py and tools/docs/check_docs.py exist under tools/docs; Makefile invocations are correct.

core/src/cache/builder.c (2)

34-35: New includes: LGTM.

Ref/ref/memory helpers are appropriate here.


142-149: get_oid_prefix: LGTM.

Correct hex fmt, bounds, and NUL-termination.

core/src/cache/query.c (3)

27-28: New includes: LGTM.

Consistent with ref/memory helpers.


40-49: get_sha_prefix: LGTM.

Correct hex derivation and termination.


104-110: Use gm_build_ref for cache ref: LGTM.

Safety improvement over snprintf.

meson.build (3)

116-116: Include order change: LGTM.

Public include/ first is consistent with guidelines.


3-3: Verify c_std=c2x support or add fallback (meson.build: line 3).
Verification failed here: cc --version returned "cc: command not found". Confirm the target toolchain accepts "c2x" or add a Meson probe that falls back to "c23"/"c17" (e.g., test-compile or detect support and set default_options accordingly).


294-294: Duplicate Meson target 'test_ref_utils' — remove to unblock CI. Remove the duplicate executable('test_ref_utils') in meson.build (line 294) and re-run 'meson setup' to confirm; local verification failed (meson: command not found).

Comment thread core/include/gitmind/cache.h Outdated
Comment thread core/include/gitmind/util/ref.h
Comment thread core/src/cache/builder.c
Comment on lines +72 to 86
/* Hash function for OID: lightweight mixing for better distribution */
static size_t oid_hash(const gm_oid_t *oid, size_t size) {
size_t hash = 0;
const uint8_t *raw = git_oid_raw(oid);
uint32_t x = 0x9E3779B9u; /* golden ratio */
for (int i = 0; i < GM_OID_RAWSZ; i++) {
hash = (hash * OID_HASH_MULTIPLIER) + raw[i];
x ^= raw[i];
x *= 0x85EBCA6Bu; /* mix */
x ^= (x >> 13);
}
return hash % size;
/* final avalanche */
x ^= x >> 16;
x *= 0x7FEB352Du;
x ^= x >> 15;
return (size_t)(x % (uint32_t)size);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Hash: add size>0 guard.

Defensive check avoids UB on modulo if misused.

Apply this diff:

 static size_t oid_hash(const gm_oid_t *oid, size_t size) {
+    if (size == 0) return 0;
     const uint8_t *raw = git_oid_raw(oid);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/* Hash function for OID: lightweight mixing for better distribution */
static size_t oid_hash(const gm_oid_t *oid, size_t size) {
size_t hash = 0;
const uint8_t *raw = git_oid_raw(oid);
uint32_t x = 0x9E3779B9u; /* golden ratio */
for (int i = 0; i < GM_OID_RAWSZ; i++) {
hash = (hash * OID_HASH_MULTIPLIER) + raw[i];
x ^= raw[i];
x *= 0x85EBCA6Bu; /* mix */
x ^= (x >> 13);
}
return hash % size;
/* final avalanche */
x ^= x >> 16;
x *= 0x7FEB352Du;
x ^= x >> 15;
return (size_t)(x % (uint32_t)size);
}
/* Hash function for OID: lightweight mixing for better distribution */
static size_t oid_hash(const gm_oid_t *oid, size_t size) {
if (size == 0) return 0;
const uint8_t *raw = git_oid_raw(oid);
uint32_t x = 0x9E3779B9u; /* golden ratio */
for (int i = 0; i < GM_OID_RAWSZ; i++) {
x ^= raw[i];
x *= 0x85EBCA6Bu; /* mix */
x ^= (x >> 13);
}
/* final avalanche */
x ^= x >> 16;
x *= 0x7FEB352Du;
x ^= x >> 15;
return (size_t)(x % (uint32_t)size);
}
🤖 Prompt for AI Agents
In core/src/cache/builder.c around lines 72 to 86, the oid_hash function
performs a modulo by size without verifying size>0 which can cause UB; add a
defensive guard at the start of the function that checks if size is zero and
returns a safe default (e.g. 0) before any modulo is performed, otherwise
proceed with the existing hash computation and return the computed value modulo
size.

Comment thread core/src/cache/builder.c
Comment thread core/src/cache/builder.c
Comment thread Makefile
Comment thread meson.build
Comment thread meson.build
Comment thread tools/ci/ci_local.sh
Comment on lines +21 to +31
if ! command -v docker >/dev/null 2>&1; then
echo "⚠️ Docker not found. Falling back to host build (override guard)."
export GITMIND_ALLOW_HOST_BUILD=1
CC=${CC:-clang}
echo "==> Host build with $CC"
rm -rf build-local
CC=$CC meson setup build-local
ninja -C build-local
ninja -C build-local test
exit 0
fi

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Prefer meson test for clearer logs on host builds.

meson test surfaces failures with --print-errorlogs.

   CC=${CC:-clang}
   echo "==> Host build with $CC"
   rm -rf build-local
   CC=$CC meson setup build-local
-  ninja -C build-local
-  ninja -C build-local test
+  ninja -C build-local
+  meson test -C build-local --print-errorlogs
   exit 0
🤖 Prompt for AI Agents
In tools/ci/ci_local.sh around lines 21 to 31, the host-build branch runs tests
with "ninja -C build-local test" which doesn't surface detailed failure logs;
replace that test invocation with "meson test -C build-local --print-errorlogs"
so meson prints error logs on failures, ensuring you still configure and build
with meson/ninja as before and then run the meson test command with the
--print-errorlogs flag.

Comment thread tools/ci/ci_local.sh
Comment on lines +56 to +67
echo "==> clang-tidy (diff-guard style)"
cd /workspace
cp "$BUILD_DIR/compile_commands.json" . || true
if command -v clang-tidy >/dev/null 2>&1; then
clang-tidy -quiet -p . --config-file=quality/.clang-tidy \
$(git ls-files "core/**/*.c" "core/**/*.h" | grep -v -E "(test_|_test\\.|/tests/|core/src/hooks/)") \
| tee clang-tidy-report-full.txt || true
grep -E "^/.*core/|^core/" clang-tidy-report-full.txt > clang-tidy-report.txt || true
echo "clang-tidy finished (report: clang-tidy-report.txt)"
else
echo "clang-tidy not found in image; skipping"
fi

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

clang-tidy invocation is fine; handle empty file list safely (optional).

Guard so clang-tidy isn’t called with zero paths.

-    if command -v clang-tidy >/dev/null 2>&1; then
-      clang-tidy -quiet -p . --config-file=quality/.clang-tidy \
-        $(git ls-files "core/**/*.c" "core/**/*.h" | grep -v -E "(test_|_test\\.|/tests/|core/src/hooks/)") \
+    if command -v clang-tidy >/dev/null 2>&1; then
+      FILES=$(git ls-files "core/**/*.c" "core/**/*.h" | grep -v -E "(test_|_test\\.|/tests/|core/src/hooks/)" || true)
+      if [ -n "$FILES" ]; then
+        clang-tidy -quiet -p . --config-file=quality/.clang-tidy $FILES \
         | tee clang-tidy-report-full.txt || true
-      grep -E "^/.*core/|^core/" clang-tidy-report-full.txt > clang-tidy-report.txt || true
-      echo "clang-tidy finished (report: clang-tidy-report.txt)"
+        grep -E "^/.*core/|^core/" clang-tidy-report-full.txt > clang-tidy-report.txt || true
+        echo "clang-tidy finished (report: clang-tidy-report.txt)"
+      else
+        echo "No core/*.c,h files to analyze"
+      fi
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
echo "==> clang-tidy (diff-guard style)"
cd /workspace
cp "$BUILD_DIR/compile_commands.json" . || true
if command -v clang-tidy >/dev/null 2>&1; then
clang-tidy -quiet -p . --config-file=quality/.clang-tidy \
$(git ls-files "core/**/*.c" "core/**/*.h" | grep -v -E "(test_|_test\\.|/tests/|core/src/hooks/)") \
| tee clang-tidy-report-full.txt || true
grep -E "^/.*core/|^core/" clang-tidy-report-full.txt > clang-tidy-report.txt || true
echo "clang-tidy finished (report: clang-tidy-report.txt)"
else
echo "clang-tidy not found in image; skipping"
fi
echo "==> clang-tidy (diff-guard style)"
cd /workspace
cp "$BUILD_DIR/compile_commands.json" . || true
if command -v clang-tidy >/dev/null 2>&1; then
FILES=$(git ls-files "core/**/*.c" "core/**/*.h" | grep -v -E "(test_|_test\\.|/tests/|core/src/hooks/)" || true)
if [ -n "$FILES" ]; then
clang-tidy -quiet -p . --config-file=quality/.clang-tidy $FILES \
| tee clang-tidy-report-full.txt || true
grep -E "^/.*core/|^core/" clang-tidy-report-full.txt > clang-tidy-report.txt || true
echo "clang-tidy finished (report: clang-tidy-report.txt)"
else
echo "No core/*.c,h files to analyze"
fi
else
echo "clang-tidy not found in image; skipping"
fi
🤖 Prompt for AI Agents
In tools/ci/ci_local.sh around lines 56 to 67, the script may invoke clang-tidy
with an empty path list; capture the result of git ls-files into a variable,
check if that variable is non-empty, and only run clang-tidy when there are
files to check (otherwise echo a message and skip); keep the existing behavior
of writing reports and grepping them, and ensure the variable is quoted when
expanded to avoid word-splitting issues.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4e9444a and 00adcb8.

📒 Files selected for processing (1)
  • AGENTS.md (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.md

📄 CodeRabbit inference engine (AGENTS.md)

Comply with repository markdown lint rules (.markdownlint.jsonc); use make md-lint / make md-fix

Files:

  • AGENTS.md
🧠 Learnings (1)
📓 Common learnings
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/src/{cache,edge}/*.c : Use `git_oid_cmp()` for OID equality and `git_oid_raw()` when byte-access is required; avoid `memcmp` on OIDs directly
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/src/**/*.c : Normalize error handling to a single scheme (prefer `GM_OK`/`GM_ERR_*`) and avoid mixing raw libgit2 error codes
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Compat Canaries (non-blocking) (gcc-13)
  • GitHub Check: Compat Canaries (non-blocking) (clang-19)
  • GitHub Check: Compat Canaries (non-blocking) (clang-18)
  • GitHub Check: Compat Canaries (non-blocking) (gcc-12)
  • GitHub Check: lint-and-sanitize
🔇 Additional comments (1)
AGENTS.md (1)

72-79: Entry reads well and matches the PR scope.

Good, concise coverage of CI, Meson tweaks, ref validation, safety changes, and docs updates.

Comment thread AGENTS.md Outdated
Comment on lines +72 to +76
2025-09-15
- CI/CD: Fixed C-Core Gate failures. README now complies with markdownlint (underscore emphasis/strong, blockquote spacing, no inline HTML wrappers, code fence fixes, heading punctuation). Added local CI rig `tools/ci/ci_local.sh` and `make ci-local` to mirror C-Core Gate (markdownlint + docs checks, Dockerized build/tests/E2E, clang-tidy pass).
- Build: Switched Meson `c_std` from `c23` to `c2x` (Meson-compatible while targeting C23). Moved `option()`s to `meson_options.txt`. Set `GITMIND_DOCKER=1` in gauntlet Dockerfile to satisfy the Meson host-build guard inside gating containers. Registered new unit test target `test_ref_utils` in `meson.build`.
- Core (refs): `gm_build_ref` now accepts Git-style branch shorthands (slashes allowed), validates the combined ref via libgit2 `git_reference_normalize_name`, and rejects leading `refs/` to prevent double-prefixing. Updated header docs and added unit tests.
- Core (path safety): Removed `GM_PATH_MAX * 2` buffer in `core/src/cache/tree_builder.c`; now uses `GM_PATH_MAX` and bounded `gm_snprintf`.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Promote date lines to subheadings and add a blank line before the list (improves TOC and lint).

This makes dates linkable in the generated ToC and satisfies common MD rules for list spacing.

Apply:

-2025-09-15
+### 2025-09-15
+

Optionally do the same for the 2025-09-14 block for consistency.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
2025-09-15
- CI/CD: Fixed C-Core Gate failures. README now complies with markdownlint (underscore emphasis/strong, blockquote spacing, no inline HTML wrappers, code fence fixes, heading punctuation). Added local CI rig `tools/ci/ci_local.sh` and `make ci-local` to mirror C-Core Gate (markdownlint + docs checks, Dockerized build/tests/E2E, clang-tidy pass).
- Build: Switched Meson `c_std` from `c23` to `c2x` (Meson-compatible while targeting C23). Moved `option()`s to `meson_options.txt`. Set `GITMIND_DOCKER=1` in gauntlet Dockerfile to satisfy the Meson host-build guard inside gating containers. Registered new unit test target `test_ref_utils` in `meson.build`.
- Core (refs): `gm_build_ref` now accepts Git-style branch shorthands (slashes allowed), validates the combined ref via libgit2 `git_reference_normalize_name`, and rejects leading `refs/` to prevent double-prefixing. Updated header docs and added unit tests.
- Core (path safety): Removed `GM_PATH_MAX * 2` buffer in `core/src/cache/tree_builder.c`; now uses `GM_PATH_MAX` and bounded `gm_snprintf`.
### 2025-09-15
- CI/CD: Fixed C-Core Gate failures. README now complies with markdownlint (underscore emphasis/strong, blockquote spacing, no inline HTML wrappers, code fence fixes, heading punctuation). Added local CI rig `tools/ci/ci_local.sh` and `make ci-local` to mirror C-Core Gate (markdownlint + docs checks, Dockerized build/tests/E2E, clang-tidy pass).
- Build: Switched Meson `c_std` from `c23` to `c2x` (Meson-compatible while targeting C23). Moved `option()`s to `meson_options.txt`. Set `GITMIND_DOCKER=1` in gauntlet Dockerfile to satisfy the Meson host-build guard inside gating containers. Registered new unit test target `test_ref_utils` in `meson.build`.
- Core (refs): `gm_build_ref` now accepts Git-style branch shorthands (slashes allowed), validates the combined ref via libgit2 `git_reference_normalize_name`, and rejects leading `refs/` to prevent double-prefixing. Updated header docs and added unit tests.
- Core (path safety): Removed `GM_PATH_MAX * 2` buffer in `core/src/cache/tree_builder.c`; now uses `GM_PATH_MAX` and bounded `gm_snprintf`.
🤖 Prompt for AI Agents
In AGENTS.md around lines 72 to 76, the release date line should be promoted to
a Markdown subheading and a blank line must be inserted before the following
bullet list to make the date linkable in the TOC and satisfy markdown lint
rules; change the plain date line into a level-3 (or consistent) heading (e.g.,
"### 2025-09-15") and add one blank line between that heading and the subsequent
list items, and optionally apply the same change to the 2025-09-14 block for
consistency.

Comment thread AGENTS.md Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 23

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (24)
core/src/cache/tree_size.c (3)

18-18: Remove NOLINT suppression; refactor to satisfy clang-tidy.

Repo policy forbids NOLINT. Split the function or switch to an explicit stack to address recursion/complexity warnings.

Minimal step now:

-/* NOLINTNEXTLINE(misc-no-recursion,readability-function-cognitive-complexity) */
 static int calculate_tree_size_recursive(git_repository *repo,

Follow-up (recommended): hoist a single git_odb* from the top-level and pass it through recursion to avoid reopening the ODB per blob/tree.


67-81: Handle symlinks and submodules; reuse an opened ODB.

Mode check only covers BLOB, skipping LINK and COMMIT (submodule) entries. Also, repeatedly opening the ODB inside the loop is unnecessary overhead.

Apply:

-        } else if (mode == GIT_FILEMODE_BLOB) {
+        } else if (mode == GIT_FILEMODE_BLOB || mode == GIT_FILEMODE_LINK || mode == GIT_FILEMODE_COMMIT) {
             /* Add blob size */
-            git_odb *odb2 = NULL;
-            ret = git_repository_odb(&odb2, repo);
+            git_odb *odb2 = NULL;
+            ret = git_repository_odb(&odb2, repo);
             if (ret == 0) {
                 size_t blob_size;
                 git_object_t blob_type;
                 ret = git_odb_read_header(&blob_size, &blob_type, odb2,
                                           entry_oid);
                 if (ret == 0) {
                     *total_size += blob_size;
                 }
                 git_odb_free(odb2);
             }

Further improvement: open git_odb once before the loop and pass it down to child calls to avoid per-entry opens.


89-93: Validate pointers before use.

Guard size_bytes and tree_oid; return GM_ERR_INVALID_ARG (or repo standard) on nulls.

Outside selected lines, add:

if (!repo || !tree_oid || !size_bytes) return GM_ERR_INVALID_ARG;
core/tests/unit/test_cache_query.c (2)

9-15: Add stdlib include for setenv (next change) and align with safety guard.

You’ll need <stdlib.h> for setenv in this test.

Outside selected lines, add:

#include <stdlib.h>

27-31: Fix failing assert by disabling the safety guard in tests.

gm_journal_append likely fails under the host safety guard. Explicitly set GITMIND_SAFETY=off (or GITMIND_DOCKER=1) in the test.

Apply:

 int main(void) {
     printf("test_cache_query... ");
     git_libgit2_init();
+    /* Test-only: bypass host safety guard */
+    setenv("GITMIND_SAFETY", "off", 1);
+    setenv("GITMIND_DOCKER", "1", 1);

If gm_journal_append requires a specific branch, ensure the journal writer targets "testq" consistently (or set it in ctx if supported).

docs/operations/CBOR_Debugging.md (1)

1-32: LGTM — front matter present; scope and usage clear.

Consider linking to docs/operations/Environment_Variables.md for a single source of truth on runtime flags.

core/src/edge/attributed.c (2)

172-183: Bug: OID bytes fallback is unreachable and can emit zero OIDs.

src_raw/tgt_raw are always non‑NULL (struct field address), so the ternary never falls back to legacy SHA. If e->src_oid/e->tgt_oid are zero, you’ll encode 20 zero bytes.

Apply this diff to use proper zero checks and libgit2 accessors, and to guard SHA‑256 builds:

-    const uint8_t *src_raw = (const uint8_t *)e->src_oid.id;
-    const uint8_t *tgt_raw = (const uint8_t *)e->tgt_oid.id;
+    const uint8_t *src_raw = git_oid_is_zero(&e->src_oid) ? NULL : git_oid_raw(&e->src_oid);
+    const uint8_t *tgt_raw = git_oid_is_zero(&e->tgt_oid) ? NULL : git_oid_raw(&e->tgt_oid);

     r = gm_cbor_write_uint(GM_CBOR_KEY_SRC_OID, buffer + offset, avail - offset);
     if (!r.ok) return gm_err_void(r.u.err); offset += r.u.val;
-    r = gm_cbor_write_bytes(buffer + offset, avail - offset, src_raw ? src_raw : e->src_sha, GM_OID_RAWSZ);
+#if GM_OID_RAWSZ != GM_SHA1_SIZE
+    if (!src_raw) return gm_err_void(GM_ERROR(GM_ERR_INVALID_ARGUMENT, "Missing src OID in SHA-256 mode"));
+    r = gm_cbor_write_bytes(buffer + offset, avail - offset, src_raw, GM_OID_RAWSZ);
+#else
+    r = gm_cbor_write_bytes(buffer + offset, avail - offset, src_raw ? src_raw : e->src_sha, GM_OID_RAWSZ);
+#endif
     if (!r.ok) return gm_err_void(r.u.err); offset += r.u.val;

     r = gm_cbor_write_uint(GM_CBOR_KEY_TGT_OID, buffer + offset, avail - offset);
     if (!r.ok) return gm_err_void(r.u.err); offset += r.u.val;
-    r = gm_cbor_write_bytes(buffer + offset, avail - offset, tgt_raw ? tgt_raw : e->tgt_sha, GM_OID_RAWSZ);
+#if GM_OID_RAWSZ != GM_SHA1_SIZE
+    if (!tgt_raw) return gm_err_void(GM_ERROR(GM_ERR_INVALID_ARGUMENT, "Missing tgt OID in SHA-256 mode"));
+    r = gm_cbor_write_bytes(buffer + offset, avail - offset, tgt_raw, GM_OID_RAWSZ);
+#else
+    r = gm_cbor_write_bytes(buffer + offset, avail - offset, tgt_raw ? tgt_raw : e->tgt_sha, GM_OID_RAWSZ);
+#endif
     if (!r.ok) return gm_err_void(r.u.err); offset += r.u.val;

26-79: “Half‑float” conversion is incorrect; implement true IEEE‑754 binary16 or rename.

Scaling by 0x3C00 doesn’t produce IEEE‑754 half; it breaks round‑trips and interop.

Apply this diff to implement proper binary16 encode/decode (round‑to‑nearest‑even):

-/* Constants for confidence conversion */
-#define CONFIDENCE_SCALE 0x3C00 /* 1.0 in IEEE-754 half-float */
+/* IEEE‑754 binary16 helpers */
+static inline uint16_t gm_float_to_f16(float f) {
+    union { float f; uint32_t u; } v = { .f = f };
+    uint32_t sign = (v.u >> 31) & 0x1;
+    int32_t  exp  = (int32_t)((v.u >> 23) & 0xFF) - 127 + 15;
+    uint32_t mant = v.u & 0x7FFFFF;
+    if (exp <= 0) {
+        if (exp < -10) return (uint16_t)(sign << 15);
+        mant = (mant | 0x800000u) >> (1 - exp);
+        uint16_t frac = (uint16_t)((mant + 0x1000u) >> 13);
+        return (uint16_t)((sign << 15) | frac);
+    } else if (exp >= 0x1F) {
+        /* Inf/NaN clamp (no NaN payload) */
+        return (uint16_t)((sign << 15) | 0x7C00u);
+    } else {
+        uint16_t frac = (uint16_t)((mant + 0x1000u) >> 13);
+        return (uint16_t)((sign << 15) | ((uint16_t)exp << 10) | frac);
+    }
+}
+
+static inline float gm_f16_to_float(uint16_t h) {
+    uint32_t sign = (h >> 15) & 0x1;
+    uint32_t exp  = (h >> 10) & 0x1F;
+    uint32_t mant = h & 0x3FF;
+    uint32_t u;
+    if (exp == 0) {
+        if (mant == 0) u = sign << 31;
+        else {
+            /* subnormal */
+            while ((mant & 0x400u) == 0) { mant <<= 1; exp--; }
+            mant &= 0x3FFu; exp++;
+            u = (sign << 31) | ((exp + 127 - 15) << 23) | (mant << 13);
+        }
+    } else if (exp == 0x1F) {
+        u = (sign << 31) | 0x7F800000u | (mant << 13);
+    } else {
+        u = (sign << 31) | ((exp + 127 - 15) << 23) | (mant << 13);
+    }
+    union { uint32_t u; float f; } v = { .u = u };
+    return v.f;
+}
@@
-uint16_t gm_confidence_to_half_float(float confidence) {
+uint16_t gm_confidence_to_half_float(float confidence) {
     /* Clamp to valid range */
     if (confidence < GM_CONFIDENCE_MIN) {
         confidence = GM_CONFIDENCE_MIN;
     }
     if (confidence > GM_CONFIDENCE_MAX) {
         confidence = GM_CONFIDENCE_MAX;
     }
-
-    /* Simple conversion: scale to half-float representation */
-    return (uint16_t)(confidence * (float)CONFIDENCE_SCALE);
+    return gm_float_to_f16(confidence);
 }
@@
-float gm_confidence_from_half_float(uint16_t half_float) {
-    return (float)half_float / (float)CONFIDENCE_SCALE;
-}
+float gm_confidence_from_half_float(uint16_t half_float) {
+    return gm_f16_to_float(half_float);
+}

If you intended a compact fixed‑point, rename API/comments accordingly to avoid IEEE‑754 claims.

core/src/cache/tree_builder.c (3)

200-207: Mode filter OK. Consider symlink policy explicitness.

You skip non-directories; if symlinks should be included/excluded deterministically, document or add a flag.


229-231: Bug: error code is swallowed. Return rc as-is.

return rc < 0 ? GM_ERR_UNKNOWN : GM_OK; converts non‑negative error codes (your GM_ERR_*) into OK.

-    return rc < 0 ? GM_ERR_UNKNOWN : GM_OK;
+    return rc;

45-55: Replace git_blob_create_from_workdir(...) with git_blob_create_fromdisk(...) (or pass repo-relative paths).

git_blob_create_from_workdir expects a path relative to the repository workdir; builder.c creates an absolute temp dir via mkdtemp (CACHE_TEMP_DIR -> /tmp/...), and gm_build_tree_from_directory passes those absolute paths into add_file_to_tree which calls git_blob_create_from_workdir. Use git_blob_create_fromdisk(&blob_oid, repo, file_path) or ensure dir_path is repo-relative. Locations: core/src/cache/tree_builder.c (add_file_to_tree, ~lines 45–55); core/src/cache/builder.c (cache_prepare_rebuild mkdtemp, ~lines 259–260).

core/src/cache/bitmap.c (4)

102-106: Use length-checked Roaring deserializer to prevent OOB reads.

roaring_bitmap_deserialize() doesn't know the buffer length. Switch to a safe API that takes the payload size; otherwise a truncated or malformed buffer can lead to undefined reads.

Apply:

-    *bitmap = roaring_bitmap_deserialize((const char *)(buffer + header_size));
+    size_t payload_len = size - header_size;
+#if defined(ROARING_HAVE_PORTABLE_SAFE)
+    *bitmap = roaring_bitmap_portable_deserialize_safe(
+        (const char *)(buffer + header_size), payload_len);
+#else
+    /* Fallback: still use native deserialize, but guard with a minimal size check */
+    if (payload_len == 0) {
+        return GM_ERR_UNKNOWN;
+    }
+    *bitmap = roaring_bitmap_deserialize((const char *)(buffer + header_size));
+#endif

165-168: Return a more specific error for invalid file sizes.

GM_ERR_UNKNOWN hides the cause. Prefer GM_ERR_INVALID_FORMAT for corrupt/invalid bitmap sizes.

-        return GM_ERR_UNKNOWN;
+        return GM_ERR_INVALID_FORMAT;

28-35: Guard against size_t overflow when allocating the array.

If cardinality exceeds SIZE_MAX / sizeof(uint32_t), malloc() may wrap. Add a bounds check and return NULL with *count = 0.

-    uint32_t *array = malloc(cardinality * sizeof(uint32_t));
+    if (cardinality > SIZE_MAX / sizeof(uint32_t)) {
+        *count = 0;
+        return NULL;
+    }
+    uint32_t *array = malloc((size_t)cardinality * sizeof(uint32_t));

Also applies to: 34-38


74-78: Differentiate serialization failure from “unknown” errors.

A short write from roaring_bitmap_serialize is a serialization error, not “unknown.” Consider GM_ERR_INVALID_FORMAT (or add GM_ERR_SERIALIZE_FAILED if you have it).

-        return GM_ERR_UNKNOWN;
+        return GM_ERR_INVALID_FORMAT;
core/src/journal/writer.c (2)

206-208: Preserve failure causes from encoder/commit paths.

Set result to the specific error before goto cleanup to avoid opaque GM_ERR_UNKNOWN.

-        if (encoder(edge, cbor_buffer + offset, &cbor_edge_size) != GM_OK) {
-            goto cleanup;
-        }
+        {
+            int enc_rc = encoder(edge, cbor_buffer + offset, &cbor_edge_size);
+            if (enc_rc != GM_OK) { result = enc_rc; goto cleanup; }
+        }
...
-            if (create_journal_commit(&jctx, cbor_buffer, offset,
-                                      &commit_oid) != GM_OK) {
-                goto cleanup;
-            }
+            {
+                int cr = create_journal_commit(&jctx, cbor_buffer, offset, &commit_oid);
+                if (cr != GM_OK) { result = cr; goto cleanup; }
+            }
...
-        if (create_journal_commit(&jctx, cbor_buffer, offset, &commit_oid) !=
-            GM_OK) {
-            goto cleanup;
-        }
+        {
+            int cr = create_journal_commit(&jctx, cbor_buffer, offset, &commit_oid);
+            if (cr != GM_OK) { result = cr; goto cleanup; }
+        }

Also applies to: 215-218, 225-227


284-293: Validate ref with libgit2 before use.

Accepting arbitrary ref risks invalid ref names. Normalize first; reject invalids.

-    /* Copy ref name securely */
-    size_t ref_len = strlen(ref);
-    if (ref_len >= sizeof(jctx.ref_name)) {
-        ref_len = sizeof(jctx.ref_name) - 1;
-    }
-    for (size_t i = 0; i < ref_len; i++) {
-        jctx.ref_name[i] = ref[i];
-    }
-    jctx.ref_name[ref_len] = '\0';
+    /* Normalize and validate ref name */
+    char normalized[REF_NAME_BUFFER_SIZE];
+    int nrc = git_reference_normalize_name(
+        normalized, sizeof normalized, ref, 0);
+    if (nrc != 0) {
+        return GM_ERR_INVALID_ARGUMENT;
+    }
+    int rn = gm_snprintf(jctx.ref_name, sizeof jctx.ref_name, "%s", normalized);
+    if (rn < 0 || (size_t)rn >= sizeof jctx.ref_name) {
+        return GM_ERR_BUFFER_TOO_SMALL;
+    }
core/src/edge/edge.c (1)

342-351: Encode OIDs or fall back based on zero-ness; NULL check never triggers.

edge->src_oid.id is never NULL. Use git_oid_is_zero() to choose SHA fallback. Prefer a helper to fetch raw bytes (if available).

-    const uint8_t *src_raw = (const uint8_t *)edge->src_oid.id;
-    const uint8_t *tgt_raw = (const uint8_t *)edge->tgt_oid.id;
-    if (src_raw == NULL) src_raw = edge->src_sha; /* fallback */
-    if (tgt_raw == NULL) tgt_raw = edge->tgt_sha; /* fallback */
+    const uint8_t *src_raw = git_oid_is_zero(&edge->src_oid)
+                                 ? edge->src_sha
+                                 : (const uint8_t *)edge->src_oid.id; /* or git_oid_raw(&edge->src_oid) */
+    const uint8_t *tgt_raw = git_oid_is_zero(&edge->tgt_oid)
+                                 ? edge->tgt_sha
+                                 : (const uint8_t *)edge->tgt_oid.id; /* or git_oid_raw(&edge->tgt_oid) */
core/src/journal/reader.c (1)

65-105: Prefer safe helpers over manual loops in legacy→attributed copy.

Use gm_memcpy_span/gm_strcpy_safe to reduce hand-rolled loops and keep consistent bounds checks.

-    for (size_t i = 0; i < GM_SHA1_SIZE; i++) {
-        attributed->src_sha[i] = legacy->src_sha[i];
-        attributed->tgt_sha[i] = legacy->tgt_sha[i];
-    }
+    (void)gm_memcpy_span(attributed->src_sha, GM_SHA1_SIZE,
+                         legacy->src_sha, GM_SHA1_SIZE);
+    (void)gm_memcpy_span(attributed->tgt_sha, GM_SHA1_SIZE,
+                         legacy->tgt_sha, GM_SHA1_SIZE);
...
-    size_t src_len = strlen(legacy->src_path);
-    if (src_len >= sizeof(attributed->src_path)) {
-        src_len = sizeof(attributed->src_path) - 1;
-    }
-    for (size_t i = 0; i < src_len; i++) {
-        attributed->src_path[i] = legacy->src_path[i];
-    }
-    attributed->src_path[src_len] = '\0';
+    (void)gm_strcpy_safe(attributed->src_path, sizeof(attributed->src_path),
+                         legacy->src_path);
...
-    size_t tgt_len = strlen(legacy->tgt_path);
-    if (tgt_len >= sizeof(attributed->tgt_path)) {
-        tgt_len = sizeof(attributed->tgt_path) - 1;
-    }
-    for (size_t i = 0; i < tgt_len; i++) {
-        attributed->tgt_path[i] = legacy->tgt_path[i];
-    }
-    attributed->tgt_path[tgt_len] = '\0';
+    (void)gm_strcpy_safe(attributed->tgt_path, sizeof(attributed->tgt_path),
+                         legacy->tgt_path);
...
-    size_t ulid_len = strlen(legacy->ulid);
-    if (ulid_len >= sizeof(attributed->ulid)) {
-        ulid_len = sizeof(attributed->ulid) - 1;
-    }
-    for (size_t i = 0; i < ulid_len; i++) {
-        attributed->ulid[i] = legacy->ulid[i];
-    }
-    attributed->ulid[ulid_len] = '\0';
+    (void)gm_strcpy_safe(attributed->ulid, sizeof(attributed->ulid),
+                         legacy->ulid);
core/include/gitmind/cbor/cbor.h (1)

4-11: Public header missing extern "C" guards.

All public headers must be umbrella-safe; add C++ guards to prevent name mangling.

Apply this diff:

 #ifndef GITMIND_CBOR_CBOR_H
 #define GITMIND_CBOR_CBOR_H

 #include <gitmind/result.h>
 #include <stddef.h>
 #include <stdint.h>

+#ifdef __cplusplus
+extern "C" {
+#endif
@@
-#endif /* GITMIND_CBOR_CBOR_H */
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GITMIND_CBOR_CBOR_H */
core/src/cache/builder.c (1)

171-179: Check gm_snprintf results (defensive).

We’re ignoring truncation here; add return checks to catch path overflow early.

Apply this diff:

-            (void)gm_snprintf(path, sizeof(path), "%s/%s/%s.%s", temp_dir,
-                              prefix, sha_hex, suffix);
+            int rn = gm_snprintf(path, sizeof(path), "%s/%s/%s.%s", temp_dir,
+                                 prefix, sha_hex, suffix);
+            if (rn < 0 || (size_t)rn >= sizeof(path)) {
+                return GM_ERR_BUFFER_TOO_SMALL;
+            }
core/src/cache/query.c (2)

290-296: Prefer git_oid_cmp over memcmp for OID equality.

Per project guidance, compare OIDs via libgit2. Avoid raw memcmp on ids.

Apply this diff:

-    const uint8_t *edge_sha = state->check_source
-        ? (const uint8_t *)edge->src_oid.id
-        : (const uint8_t *)edge->tgt_oid.id;
+    const gm_oid_t *edge_oid = state->check_source ? &edge->src_oid : &edge->tgt_oid;
@@
-    if (memcmp(edge_sha, state->target_sha, GM_OID_RAWSZ) == 0) {
+    gm_oid_t target_oid;
+    git_oid_fromraw(&target_oid, state->target_sha);
+    if (git_oid_cmp(edge_oid, &target_oid) == 0) {

This keeps state->target_sha unchanged; only the callback logic is updated.


486-496: Unify ref construction: use gm_build_ref here too.

Avoid manual string concat to ensure validation and normalization.

Apply this diff:

-        char ref_name[REF_NAME_BUFFER_SIZE];
-        {
-            int rn = gm_snprintf(ref_name, sizeof(ref_name), "%s%s", GM_CACHE_REF_PREFIX, branch);
-            if (rn < 0 || (size_t)rn >= sizeof(ref_name)) {
-                /* fall back to estimate below */
-                rc = -1;
-            }
-        }
+        char ref_name[REF_NAME_BUFFER_SIZE];
+        {
+            int brc = gm_build_ref(ref_name, sizeof(ref_name), GM_CACHE_REF_PREFIX, branch);
+            if (brc != GM_OK) {
+                rc = -1; /* fall back to estimate below */
+            }
+        }
meson.build (1)

161-255: Link missing tests against libgit2_dep in meson.build

Add libgit2_dep to the dependencies array for these test executables in meson.build: test_sha256, test_random, test_edge_equal_semantics, test_journal_safety.

♻️ Duplicate comments (14)
core/src/hooks/post-commit.c (1)

12-12: Use angle brackets for public header include.

Prevents accidental local shadowing and follows repo include-ordering.

Apply this diff:

-#include "gitmind/security/memory.h"
+#include <gitmind/security/memory.h>
core/src/hooks/augment.c (1)

155-156: Handle gm_strcpy_safe truncation instead of ignoring return value.

Apply this diff:

-    (void)gm_strcpy_safe(edge.src_path, GM_PATH_MAX, file_path);
-    (void)gm_strcpy_safe(edge.tgt_path, GM_PATH_MAX, file_path);
+    if (gm_strcpy_safe(edge.src_path, GM_PATH_MAX, file_path) < 0 ||
+        gm_strcpy_safe(edge.tgt_path, GM_PATH_MAX, file_path) < 0) {
+        return GM_ERR_BUFFER_TOO_SMALL;
+    }
tools/ci/ci_local.sh (3)

20-30: Prefer meson test for clearer logs on host builds.

   CC=${CC:-clang}
   echo "==> Host build with $CC"
   rm -rf build-local
   CC=$CC meson setup build-local
-  ninja -C build-local
-  ninja -C build-local test
+  ninja -C build-local
+  meson test -C build-local --print-errorlogs
   exit 0

53-60: Guard clang-tidy when no files match; quote vars.

-    if command -v clang-tidy >/dev/null 2>&1; then
-      clang-tidy -quiet -p . --config-file=quality/.clang-tidy \
-        $(git ls-files "core/**/*.c" "core/**/*.h" | grep -v -E "(test_|_test\\.|/tests/|core/src/hooks/)") \
-        | tee clang-tidy-report-full.txt || true
-      grep -E "^/.*core/|^core/" clang-tidy-report-full.txt > clang-tidy-report.txt || true
-      echo "clang-tidy finished (report: clang-tidy-report.txt)"
+    if command -v clang-tidy >/dev/null 2>&1; then
+      FILES="$(git ls-files "core/**/*.c" "core/**/*.h" | grep -v -E "(test_|_test\\.|/tests/|core/src/hooks/)" || true)"
+      if [ -n "$FILES" ]; then
+        clang-tidy -quiet -p . --config-file=quality/.clang-tidy $FILES \
+          | tee clang-tidy-report-full.txt || true
+        grep -E "^/.*core/|^core/" clang-tidy-report-full.txt > clang-tidy-report.txt || true
+        echo "clang-tidy finished (report: clang-tidy-report.txt)"
+      else
+        echo "No core/*.c,h files to analyze"
+      fi
     else
       echo "clang-tidy not found in image; skipping"
     fi

47-47: Use meson test in container for error logs.

-    ninja -C "$BUILD_DIR" test
+    meson test -C "$BUILD_DIR" --print-errorlogs
AGENTS.md (2)

96-116: Promote date to an H3 and add a blank line (TOC + lint).

Matches earlier guidance; makes dates linkable and satisfies list-spacing rules.

-2025-09-15
+### 2025-09-15
+

145-147: Resolve duplicate “## Agent Activity Log” heading.

There are two H2s with the same text (earlier at Line 94). Rename or merge to avoid duplicate-heading lint errors.

-## Agent Activity Log
+## Historical Activity Log
core/tests/unit/test_cache_shard_distribution.c (1)

18-46: Type nits: use size_t for indices and related comparisons.

Prevents signed/unsigned mismatches and aligns with standard loop patterns.

 static void random_oid(gm_oid_t *oid) {
     uint8_t raw[GM_OID_RAWSZ];
-    for (int i = 0; i < GM_OID_RAWSZ; i++) raw[i] = (uint8_t)(lcg_next() & 0xFF);
+    for (size_t i = 0; i < (size_t)GM_OID_RAWSZ; i++)
+        raw[i] = (uint8_t)(lcg_next() & 0xFF);
     git_oid_fromraw(oid, raw);
 }
@@
-    for (int i = 0; i < N; i++) {
+    for (size_t i = 0; i < (size_t)N; i++) {
         gm_oid_t oid = {0};
         random_oid(&oid);
         const uint8_t *raw = (const uint8_t *)oid.id;
         buckets[raw[0]]++;
     }
@@
-    uint32_t max_bucket = 0;
-    for (int i = 0; i < 256; i++) {
+    uint32_t max_bucket = 0;
+    for (size_t i = 0; i < 256; i++) {
         if (buckets[i] > max_bucket) max_bucket = buckets[i];
     }
core/src/edge/edge.c (1)

48-50: gm_memset_safe fix looks correct now.

Signature/order is correct; previous arity issue resolved.

docs/operations/Environment_Variables.md (1)

82-88: Strengthen HOOKS_BYPASS guidance (maintainers/emergencies only + reference required).

Reiterate prior feedback and add an explicit requirement to reference an issue/PR when bypassing.

 - `HOOKS_BYPASS`
-  - Purpose: Bypass local git hooks (e.g., the pre‑push CHANGELOG guard) in emergencies.
+  - Purpose: Emergency‑only bypass for local git hooks (e.g., the pre‑push CHANGELOG guard). Maintainers only.
   - Usage: `HOOKS_BYPASS=1 git push`
-  - Notes: Do not make a habit of bypassing hooks; update the CHANGELOG instead.
+  - Notes: Avoid routine use. Prefer updating the CHANGELOG. If used, reference an issue/PR in the push description (e.g., "refs: #123").

Optionally enforce this in .githooks/pre-push: when HOOKS_BYPASS=1, require a non-empty ISSUE_OR_PR env var and fail otherwise.

core/include/gitmind/cache.h (2)

47-54: Public struct layout change breaks ABI; move new field to the end or bump SONAME.

Inserting journal_tip_oid_bin before existing fields reorders the struct. Preserve ABI by appending at tail and keep hex field deprecated.

Apply this diff:

 typedef struct {
     uint64_t journal_tip_time; /**< Timestamp of last processed journal commit */
-    gm_oid_t journal_tip_oid_bin; /**< OID of last processed journal commit (preferred) */
-    char journal_tip_oid[GM_CACHE_OID_STRING_SIZE];  /**< [DEPRECATED] OID hex string of last processed journal commit */
+    char journal_tip_oid[GM_CACHE_OID_STRING_SIZE];  /**< @deprecated Hex OID of last processed journal commit; prefer journal_tip_oid_bin */
     uint64_t edge_count;       /**< Total edges in cache */
     uint64_t build_time_ms;    /**< Time to build cache (milliseconds) */
     uint32_t shard_bits;       /**< Number of bits for sharding */
     uint32_t version;          /**< Cache format version */
     char branch[GM_CACHE_BRANCH_NAME_SIZE];           /**< Branch name */
+    gm_oid_t journal_tip_oid_bin; /**< OID of last processed journal commit (preferred) */
 } gm_cache_meta_t;

If ABI break is acceptable for this release, document and bump the version accordingly instead.


34-35: Branch name size vs. truncation policy: clarify or enlarge.

Either increase GM_CACHE_BRANCH_NAME_SIZE or document that callers must pre-validate; otherwise detect overflow and return an error in setters/constructors.

Would you like me to scan for all gm_strcpy_safe(meta.branch, …) callsites and patch them to reject truncation?

core/src/cache/builder.c (2)

74-88: Hash: add size>0 guard and use git_oid_raw().

Avoid UB on modulo by zero and prefer libgit2 accessor over struct internals. This was raised previously and remains.

Apply this diff:

 /* Hash function for OID: lightweight mixing for better distribution */
 static size_t oid_hash(const gm_oid_t *oid, size_t size) {
-    const uint8_t *raw = (const uint8_t *)oid->id;
+    if (size == 0) return 0;
+    const uint8_t *raw = git_oid_raw(oid);
     uint32_t x = 0x9E3779B9u; /* golden ratio */
     for (int i = 0; i < GM_OID_RAWSZ; i++) {
         x ^= raw[i];
         x *= 0x85EBCA6Bu;      /* mix */
         x ^= (x >> 13);
     }
@@
-    return (size_t)(x % (uint32_t)size);
+    return (size_t)(x % (uint32_t)size);
 }

469-470: Branch truncation: detect or reject instead of silent truncate.

gm_strcpy_safe may truncate 64+ char branches; either increase GM_CACHE_BRANCH_NAME_SIZE or fail fast.

Apply this diff:

-    (void)gm_strcpy_safe(meta.branch, GM_CACHE_BRANCH_NAME_SIZE, branch);
+    if (strlen(branch) >= GM_CACHE_BRANCH_NAME_SIZE) {
+        rc = GM_ERR_INVALID_ARGUMENT;
+        goto cleanup;
+    }
+    (void)gm_strcpy_safe(meta.branch, GM_CACHE_BRANCH_NAME_SIZE, branch);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 00adcb8 and 056a167.

📒 Files selected for processing (35)
  • .pre-commit-config.yaml (1 hunks)
  • AGENTS.md (3 hunks)
  • CONTRIBUTING.md (1 hunks)
  • README.md (7 hunks)
  • core/include/gitmind/cache.h (8 hunks)
  • core/include/gitmind/cbor/cbor.h (6 hunks)
  • core/include/gitmind/edge.h (1 hunks)
  • core/include/gitmind/edge_attributed.h (0 hunks)
  • core/include/gitmind/journal.h (6 hunks)
  • core/include/gitmind/result.h (1 hunks)
  • core/include/gitmind/types.h (2 hunks)
  • core/src/cache/bitmap.c (4 hunks)
  • core/src/cache/builder.c (12 hunks)
  • core/src/cache/query.c (18 hunks)
  • core/src/cache/tree_builder.c (7 hunks)
  • core/src/cache/tree_size.c (1 hunks)
  • core/src/edge/attributed.c (2 hunks)
  • core/src/edge/edge.c (7 hunks)
  • core/src/hooks/augment.c (6 hunks)
  • core/src/hooks/post-commit.c (2 hunks)
  • core/src/journal/reader.c (8 hunks)
  • core/src/journal/writer.c (4 hunks)
  • core/tests/unit/test_cache_meta.c (1 hunks)
  • core/tests/unit/test_cache_query.c (1 hunks)
  • core/tests/unit/test_cache_shard_distribution.c (1 hunks)
  • core/tests/unit/test_edge_attributed_cbor.c (1 hunks)
  • core/tests/unit/test_journal_mixed_cbor.c (2 hunks)
  • docs/TECHNICAL.md (1 hunks)
  • docs/operations/CBOR_Debugging.md (1 hunks)
  • docs/operations/Environment_Variables.md (4 hunks)
  • include/gitmind/attribution.h (1 hunks)
  • meson.build (7 hunks)
  • meson_options.txt (1 hunks)
  • tools/ci/ci_local.sh (1 hunks)
  • tools/quality/check_one_thing.py (1 hunks)
💤 Files with no reviewable changes (1)
  • core/include/gitmind/edge_attributed.h
🧰 Additional context used
📓 Path-based instructions (10)
**/*.{c,cc,cpp,cxx,h,hpp,hxx,m,mm}

📄 CodeRabbit inference engine (CLAUDE.md)

NEVER use NOLINT to suppress clang-tidy warnings; ALWAYS fix the underlying issue

Files:

  • core/tests/unit/test_edge_attributed_cbor.c
  • core/src/cache/tree_size.c
  • core/tests/unit/test_cache_shard_distribution.c
  • core/src/hooks/post-commit.c
  • core/include/gitmind/cbor/cbor.h
  • core/tests/unit/test_cache_query.c
  • core/include/gitmind/edge.h
  • include/gitmind/attribution.h
  • core/tests/unit/test_journal_mixed_cbor.c
  • core/src/edge/attributed.c
  • core/src/journal/reader.c
  • core/include/gitmind/types.h
  • core/src/cache/bitmap.c
  • core/src/journal/writer.c
  • core/tests/unit/test_cache_meta.c
  • core/src/cache/tree_builder.c
  • core/include/gitmind/cache.h
  • core/src/cache/query.c
  • core/include/gitmind/journal.h
  • core/src/hooks/augment.c
  • core/src/cache/builder.c
  • core/src/edge/edge.c
  • core/include/gitmind/result.h
core/**

📄 CodeRabbit inference engine (AGENTS.md)

Add new code under core/ (C23 library: include/ for public headers, src/ for implementation, tests/ for unit tests)

Files:

  • core/tests/unit/test_edge_attributed_cbor.c
  • core/src/cache/tree_size.c
  • core/tests/unit/test_cache_shard_distribution.c
  • core/src/hooks/post-commit.c
  • core/include/gitmind/cbor/cbor.h
  • core/tests/unit/test_cache_query.c
  • core/include/gitmind/edge.h
  • core/tests/unit/test_journal_mixed_cbor.c
  • core/src/edge/attributed.c
  • core/src/journal/reader.c
  • core/include/gitmind/types.h
  • core/src/cache/bitmap.c
  • core/src/journal/writer.c
  • core/tests/unit/test_cache_meta.c
  • core/src/cache/tree_builder.c
  • core/include/gitmind/cache.h
  • core/src/cache/query.c
  • core/include/gitmind/journal.h
  • core/src/hooks/augment.c
  • core/src/cache/builder.c
  • core/src/edge/edge.c
  • core/include/gitmind/result.h
{core,src,apps,include}/**/*.{c,h}

📄 CodeRabbit inference engine (AGENTS.md)

{core,src,apps,include}/**/*.{c,h}: Use C23 with warnings-as-errors; forbid VLAs and variable shadowing; require explicit function prototypes
Follow .clang-format (LLVM-based, 4 spaces, 80 columns, pointer alignment right)
Function and variable names in lower_snake_case with gm_ prefix
Macro names in UPPER_SNAKE case
Type names end with _t
Prefer specific header includes; follow include ordering as enforced by .clang-format
Introduce no new clang-tidy warnings (lint via tools/docker-clang-tidy.sh)

Files:

  • core/tests/unit/test_edge_attributed_cbor.c
  • core/src/cache/tree_size.c
  • core/tests/unit/test_cache_shard_distribution.c
  • core/src/hooks/post-commit.c
  • core/include/gitmind/cbor/cbor.h
  • core/tests/unit/test_cache_query.c
  • core/include/gitmind/edge.h
  • include/gitmind/attribution.h
  • core/tests/unit/test_journal_mixed_cbor.c
  • core/src/edge/attributed.c
  • core/src/journal/reader.c
  • core/include/gitmind/types.h
  • core/src/cache/bitmap.c
  • core/src/journal/writer.c
  • core/tests/unit/test_cache_meta.c
  • core/src/cache/tree_builder.c
  • core/include/gitmind/cache.h
  • core/src/cache/query.c
  • core/include/gitmind/journal.h
  • core/src/hooks/augment.c
  • core/src/cache/builder.c
  • core/src/edge/edge.c
  • core/include/gitmind/result.h
core/tests/unit/test_*.c

📄 CodeRabbit inference engine (AGENTS.md)

Unit tests live in core/tests/unit/ and are named test_.c; keep tests deterministic and isolated

Files:

  • core/tests/unit/test_edge_attributed_cbor.c
  • core/tests/unit/test_cache_shard_distribution.c
  • core/tests/unit/test_cache_query.c
  • core/tests/unit/test_journal_mixed_cbor.c
  • core/tests/unit/test_cache_meta.c
core/**/*.{c,h}

📄 CodeRabbit inference engine (AGENTS.md)

Prefer OID-first APIs in new core code: use git_oid (typedef gm_oid_t) and compare via git_oid_cmp

Files:

  • core/tests/unit/test_edge_attributed_cbor.c
  • core/src/cache/tree_size.c
  • core/tests/unit/test_cache_shard_distribution.c
  • core/src/hooks/post-commit.c
  • core/include/gitmind/cbor/cbor.h
  • core/tests/unit/test_cache_query.c
  • core/include/gitmind/edge.h
  • core/tests/unit/test_journal_mixed_cbor.c
  • core/src/edge/attributed.c
  • core/src/journal/reader.c
  • core/include/gitmind/types.h
  • core/src/cache/bitmap.c
  • core/src/journal/writer.c
  • core/tests/unit/test_cache_meta.c
  • core/src/cache/tree_builder.c
  • core/include/gitmind/cache.h
  • core/src/cache/query.c
  • core/include/gitmind/journal.h
  • core/src/hooks/augment.c
  • core/src/cache/builder.c
  • core/src/edge/edge.c
  • core/include/gitmind/result.h
**/*.md

📄 CodeRabbit inference engine (AGENTS.md)

Comply with repository markdown lint rules (.markdownlint.jsonc); use make md-lint / make md-fix

Files:

  • docs/operations/CBOR_Debugging.md
  • docs/TECHNICAL.md
  • docs/operations/Environment_Variables.md
  • CONTRIBUTING.md
  • README.md
  • AGENTS.md
docs/**/*.md

📄 CodeRabbit inference engine (AGENTS.md)

Docs must pass link and TOC checks (tools/docs/check_docs.py --mode link|toc)

Files:

  • docs/operations/CBOR_Debugging.md
  • docs/TECHNICAL.md
  • docs/operations/Environment_Variables.md
{include,core,src,apps}/**/*.h

📄 CodeRabbit inference engine (AGENTS.md)

Header guards must begin with GITMIND_ and remain stable

Files:

  • core/include/gitmind/cbor/cbor.h
  • core/include/gitmind/edge.h
  • include/gitmind/attribution.h
  • core/include/gitmind/types.h
  • core/include/gitmind/cache.h
  • core/include/gitmind/journal.h
  • core/include/gitmind/result.h
include/gitmind/**/*.h

📄 CodeRabbit inference engine (AGENTS.md)

Place namespaced public headers under include/gitmind/

Files:

  • include/gitmind/attribution.h
include/{gitmind.h,gitmind/**/*.h}

📄 CodeRabbit inference engine (AGENTS.md)

Public headers must be umbrella-safe: compile standalone, maintain correct include order, have stable GITMIND_* header guards, and provide extern "C" when included from C++

Files:

  • include/gitmind/attribution.h
🧠 Learnings (32)
📓 Common learnings
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/src/{cache,edge}/*.c : Use `git_oid_cmp()` for OID equality and `git_oid_raw()` when byte-access is required; avoid `memcmp` on OIDs directly
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/src/{cache,edge}/*.c : Use `git_oid_cmp()` for OID equality and `git_oid_raw()` when byte-access is required; avoid `memcmp` on OIDs directly

Applied to files:

  • core/tests/unit/test_edge_attributed_cbor.c
  • docs/TECHNICAL.md
  • core/tests/unit/test_cache_shard_distribution.c
  • core/src/edge/attributed.c
  • core/include/gitmind/types.h
  • core/tests/unit/test_cache_meta.c
  • core/include/gitmind/cache.h
  • core/src/cache/query.c
  • core/src/cache/builder.c
  • core/src/edge/edge.c
  • AGENTS.md
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/src/edge/edge.c : `gm_edge_equal()` must not use OR-style fallback; if OIDs are present use them exclusively, otherwise compare legacy fields—never consider objects equal when OIDs differ

Applied to files:

  • core/tests/unit/test_edge_attributed_cbor.c
  • core/src/edge/attributed.c
  • core/src/cache/query.c
  • core/src/hooks/augment.c
  • core/src/cache/builder.c
  • core/src/edge/edge.c
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/include/gitmind/edge.h : Avoid struct bloat in `gm_edge_t`; do not store both legacy SHA arrays and OIDs long-term—phase out legacy SHA fields

Applied to files:

  • core/tests/unit/test_edge_attributed_cbor.c
  • docs/TECHNICAL.md
  • core/include/gitmind/edge.h
  • include/gitmind/attribution.h
  • core/tests/unit/test_journal_mixed_cbor.c
  • core/src/edge/attributed.c
  • core/src/journal/reader.c
  • core/include/gitmind/types.h
  • core/src/journal/writer.c
  • core/include/gitmind/cache.h
  • core/src/cache/query.c
  • core/src/hooks/augment.c
  • core/src/cache/builder.c
  • core/src/edge/edge.c
  • AGENTS.md
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/src/edge/edge.c : When both OID and SHA are present, validate internal consistency (detect mismatches) rather than silently accepting either

Applied to files:

  • core/tests/unit/test_edge_attributed_cbor.c
  • core/src/edge/attributed.c
  • core/src/cache/query.c
  • core/src/cache/builder.c
  • core/src/edge/edge.c
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/src/journal/reader.c : Split overly long CBOR decoder functions (e.g., `gm_edge_attributed_decode_cbor_ex`) into smaller units for maintainability

Applied to files:

  • docs/operations/CBOR_Debugging.md
  • core/include/gitmind/cbor/cbor.h
  • core/include/gitmind/edge.h
  • core/src/edge/attributed.c
  • core/src/journal/reader.c
  • core/include/gitmind/cache.h
  • core/src/edge/edge.c
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/src/journal/*.c : Do not hardcode CBOR field key magic numbers; use centralized definitions from `gitmind/cbor/keys.h`

Applied to files:

  • docs/operations/CBOR_Debugging.md
  • core/include/gitmind/cbor/cbor.h
  • core/tests/unit/test_journal_mixed_cbor.c
  • core/src/edge/attributed.c
  • core/src/journal/reader.c
  • core/src/journal/writer.c
  • core/include/gitmind/journal.h
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/src/journal/*.c : Add strict bounds checking for all CBOR parsing paths (lengths, indices, and buffer limits)

Applied to files:

  • docs/operations/CBOR_Debugging.md
  • core/src/journal/reader.c
  • core/src/journal/writer.c
  • core/src/cache/builder.c
📚 Learning: 2025-09-15T01:21:16.867Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-15T01:21:16.867Z
Learning: Applies to core/**/*.{c,h} : Prefer OID-first APIs in new core code: use git_oid (typedef gm_oid_t) and compare via git_oid_cmp

Applied to files:

  • docs/TECHNICAL.md
  • core/src/edge/attributed.c
  • core/include/gitmind/types.h
  • core/include/gitmind/cache.h
  • core/src/cache/builder.c
  • core/src/edge/edge.c
  • AGENTS.md
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/src/cache/*.{c,h} : Maintain consistent OID-centric naming for hash utilities and constants (e.g., `oid_hash()`, `OID_HASH_MULTIPLIER`)

Applied to files:

  • core/tests/unit/test_cache_shard_distribution.c
  • core/src/edge/attributed.c
  • core/include/gitmind/types.h
  • core/include/gitmind/cache.h
  • core/src/cache/query.c
  • core/src/cache/builder.c
  • AGENTS.md
📚 Learning: 2025-09-13T03:13:54.145Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-13T03:13:54.145Z
Learning: Applies to core/tests/unit/test_*.c : Unit tests live in core/tests/unit/ and are named test_<module>.c; keep tests deterministic and isolated

Applied to files:

  • core/tests/unit/test_cache_shard_distribution.c
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/include/gitmind/hooks/augment.h : Public hook APIs should use the `gm_hook_` prefix; keep header guard stable to avoid breaking includes

Applied to files:

  • core/src/hooks/post-commit.c
  • include/gitmind/attribution.h
  • core/include/gitmind/types.h
  • core/include/gitmind/journal.h
  • core/src/hooks/augment.c
📚 Learning: 2025-09-15T01:21:16.866Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-15T01:21:16.866Z
Learning: Applies to include/{gitmind.h,gitmind/**/*.h} : Public headers must be umbrella-safe: compile standalone, maintain correct include order, have stable GITMIND_* header guards, and provide extern "C" when included from C++

Applied to files:

  • core/src/hooks/post-commit.c
  • core/tests/unit/test_cache_query.c
  • core/tests/unit/test_journal_mixed_cbor.c
  • core/src/journal/reader.c
  • core/src/cache/tree_builder.c
  • core/src/hooks/augment.c
  • core/src/cache/builder.c
  • AGENTS.md
📚 Learning: 2025-09-15T01:21:16.866Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-15T01:21:16.866Z
Learning: Applies to {include,core,src,apps}/**/*.h : Header guards must begin with GITMIND_ and remain stable

Applied to files:

  • core/src/hooks/post-commit.c
  • docs/operations/Environment_Variables.md
  • core/src/cache/builder.c
  • AGENTS.md
📚 Learning: 2025-09-13T03:13:54.145Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-13T03:13:54.145Z
Learning: Applies to include/gitmind/**/*.h : Public, namespaced headers live under include/gitmind/

Applied to files:

  • core/src/hooks/post-commit.c
  • core/tests/unit/test_cache_query.c
  • core/src/journal/reader.c
  • core/src/cache/tree_builder.c
📚 Learning: 2025-09-13T03:13:54.145Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-13T03:13:54.145Z
Learning: Applies to {include,core/include}/**/*.h : Header guards use GITMIND_* naming

Applied to files:

  • core/src/hooks/post-commit.c
  • core/tests/unit/test_cache_query.c
  • core/src/cache/tree_builder.c
  • docs/operations/Environment_Variables.md
  • core/src/cache/builder.c
📚 Learning: 2025-09-15T01:21:16.866Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-15T01:21:16.866Z
Learning: Applies to include/gitmind/**/*.h : Place namespaced public headers under include/gitmind/

Applied to files:

  • core/src/hooks/post-commit.c
📚 Learning: 2025-09-13T03:13:54.145Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-13T03:13:54.145Z
Learning: Applies to include/gitmind.h : Maintain umbrella API at include/gitmind.h

Applied to files:

  • core/src/hooks/post-commit.c
  • core/tests/unit/test_cache_query.c
  • include/gitmind/attribution.h
  • core/tests/unit/test_journal_mixed_cbor.c
  • core/src/journal/reader.c
  • core/include/gitmind/types.h
  • core/src/journal/writer.c
  • core/src/cache/tree_builder.c
  • core/include/gitmind/cache.h
  • core/src/cache/query.c
  • core/include/gitmind/journal.h
  • core/src/hooks/augment.c
  • core/src/cache/builder.c
  • core/src/edge/edge.c
📚 Learning: 2025-09-13T03:13:54.145Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-13T03:13:54.145Z
Learning: Applies to {core,include}/**/*.{c,h} : Formatting: follow .clang-format (LLVM-based, 4 spaces, 80 cols, pointer alignment right); pre-commit enforces clang-format

Applied to files:

  • core/src/hooks/post-commit.c
📚 Learning: 2025-09-13T03:13:54.145Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-13T03:13:54.145Z
Learning: Run build, tests, clang-tidy (via tools/docker-clang-tidy.sh), and gauntlet locally before proposing changes; keep changes zero-warnings and formatted

Applied to files:

  • tools/ci/ci_local.sh
  • CONTRIBUTING.md
  • AGENTS.md
📚 Learning: 2025-09-13T03:13:54.145Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-13T03:13:54.145Z
Learning: Use Meson/Ninja for build and tests; run lint and gauntlet locally; keep diffs minimal and pass CI with zero new clang-tidy warnings

Applied to files:

  • tools/ci/ci_local.sh
  • CONTRIBUTING.md
  • meson.build
  • AGENTS.md
📚 Learning: 2025-09-15T01:21:16.866Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-15T01:21:16.866Z
Learning: Applies to {core,src,apps,include}/**/*.{c,h} : Introduce no new clang-tidy warnings (lint via tools/docker-clang-tidy.sh)

Applied to files:

  • tools/ci/ci_local.sh
📚 Learning: 2025-09-15T01:21:16.866Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-15T01:21:16.866Z
Learning: Applies to docs/**/*.md : Docs must pass link and TOC checks (tools/docs/check_docs.py --mode link|toc)

Applied to files:

  • .pre-commit-config.yaml
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/include/gitmind/types.h : Define and consistently use the alias `typedef git_oid gm_oid_t` as the canonical OID type

Applied to files:

  • include/gitmind/attribution.h
  • core/src/edge/attributed.c
  • core/include/gitmind/types.h
  • core/include/gitmind/cache.h
  • core/src/cache/builder.c
  • AGENTS.md
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/src/**/*.c : Normalize error handling to a single scheme (prefer `GM_OK`/`GM_ERR_*`) and avoid mixing raw libgit2 error codes

Applied to files:

  • core/src/cache/bitmap.c
  • AGENTS.md
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/src/journal/writer.c : Base64-encode CBOR payloads in commit messages to prevent binary corruption

Applied to files:

  • core/src/journal/writer.c
📚 Learning: 2025-09-14T09:27:33.266Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-14T09:27:33.266Z
Learning: NEVER alter, disable, or otherwise circumvent git hooks or tests

Applied to files:

  • docs/operations/Environment_Variables.md
📚 Learning: 2025-09-14T09:27:33.266Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-14T09:27:33.266Z
Learning: NEVER circumvent git hooks

Applied to files:

  • docs/operations/Environment_Variables.md
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/include/gitmind/hooks/augment.h : Remove or timebox deprecated compatibility macros rather than keeping them indefinitely

Applied to files:

  • core/src/hooks/augment.c
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/**/meson.build : Do not hardcode `c_std=c23`; detect compiler support or provide a compatible minimum standard with feature checks

Applied to files:

  • meson.build
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/**/*.c : Use bounded string functions (e.g., `gm_snprintf`) and ensure explicit NUL termination on all string operations

Applied to files:

  • core/src/cache/builder.c
📚 Learning: 2025-09-14T09:27:33.266Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-14T09:27:33.266Z
Learning: Tag all memories saved to MEMORY BANKS with at least #git-mind

Applied to files:

  • README.md
🧬 Code graph analysis (13)
core/tests/unit/test_cache_shard_distribution.c (2)
core/tests/unit/test_cache_query.c (1)
  • main (27-74)
core/tests/unit/test_edge_oid_fallback.c (1)
  • main (10-36)
core/src/hooks/post-commit.c (1)
core/include/gitmind/security/memory.h (1)
  • gm_memset_safe (47-59)
core/include/gitmind/cbor/cbor.h (2)
core/src/cbor/cbor.c (6)
  • gm_cbor_read_uint (122-150)
  • gm_cbor_read_bytes (190-244)
  • gm_cbor_read_text (247-309)
  • gm_cbor_write_uint (312-374)
  • gm_cbor_write_bytes (377-424)
  • gm_cbor_write_text (427-475)
core/include/gitmind/result.h (3)
  • gm_result_void_t (83-85)
  • gm_result_size_t (74-76)
  • gm_result_size_t (99-101)
core/include/gitmind/edge.h (1)
core/src/edge/edge.c (1)
  • gm_edge_decode_cbor_ex (505-507)
core/src/journal/reader.c (3)
core/include/gitmind/security/memory.h (1)
  • gm_memset_safe (47-59)
core/include/gitmind/util/memory.h (2)
  • gm_memcpy_span (32-47)
  • gm_strcpy_safe (113-138)
core/src/util/ref.c (1)
  • gm_build_ref (11-43)
core/src/journal/writer.c (1)
core/src/util/ref.c (1)
  • gm_build_ref (11-43)
core/include/gitmind/cache.h (2)
core/src/cache/builder.c (1)
  • gm_cache_rebuild (490-496)
core/src/cache/query.c (5)
  • gm_cache_query_fanout (446-450)
  • gm_cache_query_fanin (453-457)
  • gm_cache_load_meta (97-169)
  • gm_cache_is_stale (172-225)
  • gm_cache_stats (471-516)
core/src/cache/query.c (3)
core/src/util/ref.c (1)
  • gm_build_ref (11-43)
core/include/gitmind/security/memory.h (1)
  • gm_memset_safe (47-59)
core/include/gitmind/util/memory.h (2)
  • gm_strcpy_safe (113-138)
  • gm_memcpy_span (32-47)
core/include/gitmind/journal.h (2)
core/src/journal/reader.c (2)
  • gm_journal_read (356-360)
  • gm_journal_read_attributed (363-367)
core/src/journal/writer.c (3)
  • gm_journal_append (255-259)
  • gm_journal_append_attributed (262-268)
  • gm_journal_create_commit (271-296)
core/src/hooks/augment.c (1)
core/include/gitmind/util/memory.h (1)
  • gm_strcpy_safe (113-138)
core/src/cache/builder.c (3)
core/src/util/ref.c (1)
  • gm_build_ref (11-43)
core/include/gitmind/security/memory.h (1)
  • gm_memset_safe (47-59)
core/include/gitmind/util/memory.h (1)
  • gm_strcpy_safe (113-138)
core/src/edge/edge.c (3)
core/include/gitmind/security/memory.h (1)
  • gm_memset_safe (47-59)
core/include/gitmind/util/memory.h (1)
  • gm_strcpy_safe (113-138)
core/src/cbor/cbor.c (1)
  • gm_cbor_read_bytes (190-244)
core/include/gitmind/result.h (1)
core/include/gitmind/cache/bitmap.h (1)
  • nodiscard (44-48)
🪛 GitHub Actions: Core Quality Checks
core/tests/unit/test_cache_query.c

[error] 51-51: Assertion 'rc == GM_OK' failed in test_cache_query (core/tests/unit/test_cache_query.c:51).

core/tests/unit/test_journal_mixed_cbor.c

[error] 78-78: ASan memory leak detected: 112 byte(s) leaked in test_journal_mixed_cbor.

🪛 GitHub Actions: C-Core Gate
AGENTS.md

[error] 16-16: MD050/strong-style Strong style [Expected: underscore; Actual: asterisk]

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Compat Canaries (non-blocking) (gcc-13)

Comment thread .pre-commit-config.yaml
Comment on lines +29 to +39
- id: docs-frontmatter-check
name: docs: frontmatter check
entry: python3 tools/docs/check_frontmatter.py
language: python
files: ^docs/.*\.md$
- id: one-thing
name: policy: one-thing (1 file = 1 thing)
entry: python3 tools/quality/check_one_thing.py
language: python
pass_filenames: false
files: ^(include/|core/include/|core/src/).*(\.(c|h))$

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Pin Python version for new hooks; consider push-stage for policy gate.

Add language_version: python3 to avoid system-Python drift, and (optionally) run the One‑Thing policy on push as well.

Apply:

-    - id: docs-frontmatter-check
+    - id: docs-frontmatter-check
       name: docs: frontmatter check
       entry: python3 tools/docs/check_frontmatter.py
-      language: python
+      language: python
+      language_version: python3
       files: ^docs/.*\.md$
-    - id: one-thing
+    - id: one-thing
       name: policy: one-thing (1 file = 1 thing)
       entry: python3 tools/quality/check_one_thing.py
-      language: python
+      language: python
+      language_version: python3
       pass_filenames: false
       files: ^(include/|core/include/|core/src/).*(\.(c|h))$
+      # Optional: also enforce on push
+      # stages: [commit, push]
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- id: docs-frontmatter-check
name: docs: frontmatter check
entry: python3 tools/docs/check_frontmatter.py
language: python
files: ^docs/.*\.md$
- id: one-thing
name: policy: one-thing (1 file = 1 thing)
entry: python3 tools/quality/check_one_thing.py
language: python
pass_filenames: false
files: ^(include/|core/include/|core/src/).*(\.(c|h))$
- id: docs-frontmatter-check
name: docs: frontmatter check
entry: python3 tools/docs/check_frontmatter.py
language: python
language_version: python3
files: ^docs/.*\.md$
- id: one-thing
name: policy: one-thing (1 file = 1 thing)
entry: python3 tools/quality/check_one_thing.py
language: python
language_version: python3
pass_filenames: false
files: ^(include/|core/include/|core/src/).*(\.(c|h))$
# Optional: also enforce on push
# stages: [commit, push]
🤖 Prompt for AI Agents
.pre-commit-config.yaml lines 29-39: the two Python hooks don't pin a Python
runtime; add language_version: python3 under each hook to ensure consistent
interpreter usage, and optionally add stages: [push] to the one-thing hook
(policy: one-thing) if you want it to run at push as well as commit; update the
docs-frontmatter-check and one-thing hook entries accordingly.

Comment thread AGENTS.md
Comment on lines +106 to +108
/* Internal extension: decode and report bytes consumed */
int gm_edge_decode_cbor_ex(const uint8_t *buffer, size_t len, gm_edge_t *edge, size_t *consumed);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Don’t expose “internal” symbol in public API without gating.

Either move to an internal header or gate as experimental to avoid locking ABI.

Apply this diff:

-/* Internal extension: decode and report bytes consumed */
-int gm_edge_decode_cbor_ex(const uint8_t *buffer, size_t len, gm_edge_t *edge, size_t *consumed);
+/* Internal extension: decode and report bytes consumed (experimental; not stable API) */
+#ifdef GITMIND_EXPERIMENTAL
+int gm_edge_decode_cbor_ex(const uint8_t *buffer, size_t len,
+                           gm_edge_t *edge, size_t *consumed);
+#endif

If kept public, consider a gm_result_* return type for consistency.

🤖 Prompt for AI Agents
In core/include/gitmind/edge.h around lines 106 to 108, the internal helper
gm_edge_decode_cbor_ex is being exposed in the public API; either move this
declaration to an internal header (e.g.,
core/include/gitmind/internal/edge_internal.h) and update callers to include
that internal header, or gate it as experimental by wrapping it with an API
visibility/experimental macro (e.g., GM_EXPERIMENTAL) and documenting it as
non-ABI-stable; if you decide to keep it in the public header, change its
signature to return a gm_result_* style enum for consistency and update all
callers to handle that result type.

Comment on lines +46 to +56
/* Attributes */
#if defined(__has_c_attribute)
# if __has_c_attribute(nodiscard)
# define GM_NODISCARD [[nodiscard]]
# else
# define GM_NODISCARD
# endif
#else
# define GM_NODISCARD
#endif

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add GCC/Clang fallback for GM_NODISCARD.

If [[nodiscard]] isn’t available and __has_c_attribute is missing, we silently drop the warning. Provide a portable fallback to attribute((warn_unused_result)) to keep guarantees on older compilers.

 #if defined(__has_c_attribute)
 #  if __has_c_attribute(nodiscard)
 #    define GM_NODISCARD [[nodiscard]]
 #  else
-#    define GM_NODISCARD
+#    define GM_NODISCARD
 #  endif
 #else
-#  define GM_NODISCARD
+#  define GM_NODISCARD
 #endif
+
+/* Fallback for compilers without __has_c_attribute but supporting GCC/Clang attrs */
+#ifndef GM_NODISCARD
+#  if defined(__GNUC__) || defined(__clang__)
+#    define GM_NODISCARD __attribute__((warn_unused_result))
+#  else
+#    define GM_NODISCARD
+#  endif
+#endif

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In core/include/gitmind/result.h around lines 46 to 56, the GM_NODISCARD macro
currently only uses [[nodiscard]] when __has_c_attribute is present and
otherwise becomes empty; add a portable fallback that defines GM_NODISCARD as
__attribute__((warn_unused_result)) when compiling with GCC or Clang (detect via
__has_attribute or compiler built-ins like __GNUC__ or __clang__), otherwise
leave it empty; ensure the checks prefer __has_c_attribute and __has_attribute
if available, then fall back to compiler-specific macros so older GCC/Clang
versions still get a warn-unused-result warning.

Comment on lines +58 to 113
GM_NODISCARD static inline gm_result_void_t gm_ok_void(void) {
return (gm_result_void_t){.ok = true, .u.val = 0};
}

static inline gm_result_ptr_t gm_ok_ptr(void *val) {
GM_NODISCARD static inline gm_result_ptr_t gm_ok_ptr(void *val) {
return (gm_result_ptr_t){.ok = true, .u.val = val};
}

static inline gm_result_int_t gm_ok_int(int val) {
GM_NODISCARD static inline gm_result_int_t gm_ok_int(int val) {
return (gm_result_int_t){.ok = true, .u.val = val};
}

static inline gm_result_bool_t gm_ok_bool(bool val) {
GM_NODISCARD static inline gm_result_bool_t gm_ok_bool(bool val) {
return (gm_result_bool_t){.ok = true, .u.val = val};
}

static inline gm_result_size_t gm_ok_size(size_t val) {
GM_NODISCARD static inline gm_result_size_t gm_ok_size(size_t val) {
return (gm_result_size_t){.ok = true, .u.val = val};
}

static inline gm_result_u32_t gm_ok_u32(uint32_t val) {
GM_NODISCARD static inline gm_result_u32_t gm_ok_u32(uint32_t val) {
return (gm_result_u32_t){.ok = true, .u.val = val};
}

/* Error constructors */
static inline gm_result_void_t gm_err_void(gm_error_t *err) {
GM_NODISCARD static inline gm_result_void_t gm_err_void(gm_error_t *err) {
return (gm_result_void_t){.ok = false, .u.err = err};
}

static inline gm_result_ptr_t gm_err_ptr(gm_error_t *err) {
GM_NODISCARD static inline gm_result_ptr_t gm_err_ptr(gm_error_t *err) {
return (gm_result_ptr_t){.ok = false, .u.err = err};
}

static inline gm_result_int_t gm_err_int(gm_error_t *err) {
GM_NODISCARD static inline gm_result_int_t gm_err_int(gm_error_t *err) {
return (gm_result_int_t){.ok = false, .u.err = err};
}

static inline gm_result_bool_t gm_err_bool(gm_error_t *err) {
GM_NODISCARD static inline gm_result_bool_t gm_err_bool(gm_error_t *err) {
return (gm_result_bool_t){.ok = false, .u.err = err};
}

static inline gm_result_size_t gm_err_size(gm_error_t *err) {
GM_NODISCARD static inline gm_result_size_t gm_err_size(gm_error_t *err) {
return (gm_result_size_t){.ok = false, .u.err = err};
}

static inline gm_result_u32_t gm_err_u32(gm_error_t *err) {
GM_NODISCARD static inline gm_result_u32_t gm_err_u32(gm_error_t *err) {
return (gm_result_u32_t){.ok = false, .u.err = err};
}

static inline gm_result_u64_t gm_ok_u64(uint64_t val) {
GM_NODISCARD static inline gm_result_u64_t gm_ok_u64(uint64_t val) {
return (gm_result_u64_t){.ok = true, .u.val = val};
}

static inline gm_result_u64_t gm_err_u64(gm_error_t *err) {
GM_NODISCARD static inline gm_result_u64_t gm_err_u64(gm_error_t *err) {
return (gm_result_u64_t){.ok = false, .u.err = err};
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Good: consistent [[nodiscard]] on result constructors.

This will surface accidental ignored results at call sites. No functional concerns.

Minor: for readability, keep ok_* group contiguous (move gm_ok_u64 above the “Error constructors” block).

🤖 Prompt for AI Agents
core/include/gitmind/result.h lines 58-113: the gm_ok_u64() constructor is
placed after the error constructors, breaking the contiguous grouping of "ok_*"
functions; move the GM_NODISCARD static inline gm_result_u64_t
gm_ok_u64(uint64_t val) { ... } definition so it appears with the other gm_ok_*
constructors (i.e., above the "/* Error constructors */" comment) and leave
gm_err_u64() in the error constructors block unchanged.

Comment thread meson_options.txt
Comment on lines +1 to +9
# Feature toggles
option('enable_io', type: 'boolean', value: false, description: 'Enable IO public headers')
option('enable_time', type: 'boolean', value: false, description: 'Enable time public headers')
option('enable_util', type: 'boolean', value: false, description: 'Enable util public headers')
option('enable_utf8', type: 'boolean', value: true, description: 'Enable UTF-8 public headers')

# Safety override (dangerous): allow building on host instead of Docker/CI
option('force_local_builds', type: 'boolean', value: false,
description: 'Allow host builds (dangerous; use Docker by default)')

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Consider Meson “feature” options for better tri-state control.

Using type: 'feature' allows enabled/disabled/auto and integrates with dependency handling. Keep defaults the same.

-option('enable_io', type: 'boolean', value: false, description: 'Enable IO public headers')
-option('enable_time', type: 'boolean', value: false, description: 'Enable time public headers')
-option('enable_util', type: 'boolean', value: false, description: 'Enable util public headers')
-option('enable_utf8', type: 'boolean', value: true, description: 'Enable UTF-8 public headers')
+option('enable_io', type: 'feature', value: 'disabled', description: 'Enable IO public headers')
+option('enable_time', type: 'feature', value: 'disabled', description: 'Enable time public headers')
+option('enable_util', type: 'feature', value: 'disabled', description: 'Enable util public headers')
+option('enable_utf8', type: 'feature', value: 'enabled', description: 'Enable UTF-8 public headers')

Please confirm meson.build consumes these options via get_option() and handles feature types.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# Feature toggles
option('enable_io', type: 'boolean', value: false, description: 'Enable IO public headers')
option('enable_time', type: 'boolean', value: false, description: 'Enable time public headers')
option('enable_util', type: 'boolean', value: false, description: 'Enable util public headers')
option('enable_utf8', type: 'boolean', value: true, description: 'Enable UTF-8 public headers')
# Safety override (dangerous): allow building on host instead of Docker/CI
option('force_local_builds', type: 'boolean', value: false,
description: 'Allow host builds (dangerous; use Docker by default)')
# Feature toggles
option('enable_io', type: 'feature', value: 'disabled', description: 'Enable IO public headers')
option('enable_time', type: 'feature', value: 'disabled', description: 'Enable time public headers')
option('enable_util', type: 'feature', value: 'disabled', description: 'Enable util public headers')
option('enable_utf8', type: 'feature', value: 'enabled', description: 'Enable UTF-8 public headers')
# Safety override (dangerous): allow building on host instead of Docker/CI
option('force_local_builds', type: 'boolean', value: false,
description: 'Allow host builds (dangerous; use Docker by default)')

Comment thread meson.build
project('git-mind', 'c',
version: '0.6.0',
default_options: ['c_std=c23', 'warning_level=3', 'werror=true'])
default_options: ['c_std=c2x', 'warning_level=3', 'werror=true'])

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Don’t hardcode c_std=c2x; detect and select the highest supported standard.

Hardcoding can break older toolchains or non-GCC/Clang setups. Probe support and add the best flag instead.

-project('git-mind', 'c',
-        version: '0.6.0',
-        default_options: ['c_std=c2x', 'warning_level=3', 'werror=true'])
+project('git-mind', 'c',
+        version: '0.6.0',
+        default_options: ['warning_level=3', 'werror=true'])
+
+# Select the highest C standard the compiler supports (prefer C23/2x)
+cc = meson.get_compiler('c')
+std_candidates = ['-std=c2x', '-std=gnu2x', '-std=c23', '-std=gnu23']
+std_supported = cc.get_supported_arguments(std_candidates)
+if std_supported.length() == 0
+  error('A C23-capable compiler is required (supports one of: c2x/gnu2x/c23/gnu23).')
+endif
+add_project_arguments(std_supported[0], language: 'c')

Committable suggestion skipped: line range outside the PR's diff.

Comment thread meson.build
Comment on lines +8 to +12
in_docker = run_command('sh', '-lc', '[ "$GITMIND_DOCKER" = "1" ] && echo 1 || echo 0', check: false).stdout().strip() == '1'
in_ci = run_command('sh', '-lc', '[ -n "$GITHUB_ACTIONS" ] && echo 1 || echo 0', check: false).stdout().strip() == '1'
env_override = run_command('sh', '-lc', '[ "$GITMIND_ALLOW_HOST_BUILD" = "1" ] && echo 1 || echo 0', check: false).stdout().strip() == '1'
force_local = get_option('force_local_builds')
if not in_docker and not in_ci and not env_override and not force_local

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Avoid spawning shells to read env; use meson.get_env().

Cheaper, more portable, and easier to reason about.

-in_docker = run_command('sh', '-lc', '[ "$GITMIND_DOCKER" = "1" ] && echo 1 || echo 0', check: false).stdout().strip() == '1'
-in_ci = run_command('sh', '-lc', '[ -n "$GITHUB_ACTIONS" ] && echo 1 || echo 0', check: false).stdout().strip() == '1'
-env_override = run_command('sh', '-lc', '[ "$GITMIND_ALLOW_HOST_BUILD" = "1" ] && echo 1 || echo 0', check: false).stdout().strip() == '1'
+in_docker = meson.get_env('GITMIND_DOCKER') == '1'
+in_ci = meson.get_env('GITHUB_ACTIONS') != ''
+env_override = meson.get_env('GITMIND_ALLOW_HOST_BUILD') == '1'

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In meson.build around lines 8 to 12, the code spawns shells with run_command to
read environment variables (GITMIND_DOCKER, GITHUB_ACTIONS,
GITMIND_ALLOW_HOST_BUILD); replace those run_command calls with
meson.get_env('VAR_NAME') and compare the returned string (or check for
non-empty) to produce the same booleans (e.g., in_docker =
meson.get_env('GITMIND_DOCKER') == '1', in_ci = meson.get_env('GITHUB_ACTIONS')
!= '' or == '1' depending on semantics, env_override =
meson.get_env('GITMIND_ALLOW_HOST_BUILD') == '1'), keep force_local =
get_option('force_local_builds') and the final if condition unchanged so no
shells are spawned and behavior is preserved.

Comment thread meson.build
Comment on lines +363 to 364
c_args : ['-include', '../' + hdr],
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Make -include header path robust for out-of-tree build dirs.

Using '../' assumes a one-level build dir. Prefer an absolute path via join_paths(meson.source_root(), …).

-    c_args : ['-include', '../' + hdr],
+    c_args : ['-include', join_paths(meson.source_root(), hdr)],
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
c_args : ['-include', '../' + hdr],
)
c_args : ['-include', join_paths(meson.source_root(), hdr)],
)
🤖 Prompt for AI Agents
In meson.build around lines 363-364, the -include argument currently prepends
'../' to hdr which assumes a single-level out-of-tree build directory; replace
that relative '../' concatenation with an absolute source-root-based path using
join_paths(meson.source_root(), <relative-path-to-header-or-hdr>) and pass that
resulting path to c_args (e.g. build the include path via join_paths and use it
instead of '../' + hdr) so the include works for arbitrary out-of-tree build
locations.

Comment on lines +23 to +24
ROOT = Path(__file__).resolve().parents[2]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Remove unused constant ROOT.

Dead code; keep the script minimal.

-ROOT = Path(__file__).resolve().parents[2]
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
ROOT = Path(__file__).resolve().parents[2]
🤖 Prompt for AI Agents
In tools/quality/check_one_thing.py around lines 23 to 24, the constant ROOT is
defined but never used; remove the dead-code declaration. Delete the line that
defines ROOT = Path(__file__).resolve().parents[2] and any associated unused
imports if Path is only required for that constant, keeping the script minimal
and ensuring no other code references ROOT after removal.

…ize cache meta + query tests; add test branch override

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (7)
core/tests/unit/test_journal_safety.c (2)

4-12: Add missing stdlib include (C23: malloc/free prototypes).

Without #include <stdlib.h>, this won’t compile with warnings-as-errors (implicit decls removed in C23).

 #include <assert.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <sodium.h>

46-90: Add fallback and rel_type tests to close gaps.

Cover: (1) both OIDs zero → SHA fallback equal/not-equal, (2) only one side has OIDs → still fallback to SHA, (3) rel_type mismatch.

Add this helper and invoke it from main:

static void test_edge_equal_fallback_and_reltype(void) {
    printf("test_edge_equal_fallback_and_reltype... ");
    gm_edge_t x = (gm_edge_t){0}, y = (gm_edge_t){0};
    x.rel_type = y.rel_type = GM_REL_IMPLEMENTS;

    /* No OIDs -> SHA fallback: equal */
    memset(x.src_sha, 0x10, GM_SHA1_SIZE);
    memset(y.src_sha, 0x10, GM_SHA1_SIZE);
    memset(x.tgt_sha, 0x20, GM_SHA1_SIZE);
    memset(y.tgt_sha, 0x20, GM_SHA1_SIZE);
    assert(gm_edge_equal(&x, &y));

    /* Only one side has OIDs -> still SHA fallback: equal */
    uint8_t raw[GM_OID_RAWSZ]; memset(raw, 0xCC, sizeof raw);
    git_oid_fromraw(&x.src_oid, raw);
    git_oid_fromraw(&x.tgt_oid, raw);
    assert(gm_edge_equal(&x, &y));

    /* Fallback path with differing SHAs -> not equal */
    memset(y.src_sha, 0x21, GM_SHA1_SIZE);
    assert(!gm_edge_equal(&x, &y));

    /* Relationship type mismatch -> not equal */
    y = x; /* equal OIDs/SHAs */
    y.rel_type = x.rel_type + 1;
    assert(!gm_edge_equal(&x, &y));

    printf("OK\n");
}

/* In main(): after test_edge_equal_oid_preferred(); */
test_edge_equal_fallback_and_reltype();

I can push a patch if you prefer.

core/tests/unit/test_cache_query.c (1)

4-8: Include stdlib.h for getenv/putenv prototypes.

Prevents implicit decl errors and standardizes across platforms.

 #include <assert.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <git2.h>
AGENTS.md (1)

38-41: Normalize list indentation.

Leading spaces before “- ” can trip linters.

- - Markdown linter: `make md-lint` (check) and `make md-fix` (autofix) — uses `.markdownlint.jsonc`
- - Header guards lint: `meson run -C build lint_header_guards`
- - Public headers compile check: `ninja -C build header-compile`
+- Markdown linter: `make md-lint` (check) and `make md-fix` (autofix) — uses `.markdownlint.jsonc`
+- Header guards lint: `meson run -C build lint_header_guards`
+- Public headers compile check: `ninja -C build header-compile`
core/src/journal/writer.c (1)

105-106: Remove stale “unused” note.

cbor_len is used below; the cast is misleading.

-    (void)cbor_len; /* Unused for now */
meson.build (1)

339-355: Add util/ref.h to public header compile checks.

Ensures the new public API is covered by the standalone header build.

Apply:

   'core/include/gitmind/time/time.h',
+  'core/include/gitmind/util/ref.h',
   'core/include/gitmind/util/memory.h',
core/src/edge/edge.c (1)

337-342: Don't treat git_oid.id as nullable — check for zero OIDs and fallback to legacy SHA.

git_oid.id is a fixed-size array (never NULL). At core/src/edge/edge.c:337-342 and core/src/edge/attributed.c:173-179 the code tests the casted .id pointer for NULL — that will never be true, so zero OIDs are written as all-zero bytes instead of falling back to src_sha/tgt_sha. Replace the NULL-pointer checks with git_oid_is_zero(&edge->src_oid)/git_oid_is_zero(&edge->tgt_oid) (or an explicit byte-zero check) and use edge->src_sha/edge->tgt_sha when the OID is zero.

♻️ Duplicate comments (12)
AGENTS.md (3)

156-156: Resolve duplicate H2 “Agent Activity Log”.

Rename the later section to avoid duplicate-heading lint.

-## Agent Activity Log
+## Historical Activity Log

15-18: Fix MD050: use underscores for bold in admonition.

 > [!WARNING]
-> **DO NOT BUILD GITMIND OUTSIDE OF DOCKER**
+> __DO NOT BUILD GITMIND OUTSIDE OF DOCKER__

94-98: Promote the date to a subheading and add a blank line (ToC/linking).

-2025-09-15
+### 2025-09-15
+
core/src/journal/writer.c (1)

52-56: Propagate gm_build_ref’s actual error code.

Don’t coerce all failures to BUFFER_TOO_SMALL.

-    if (nref != GM_OK) {
-        return GM_ERR_BUFFER_TOO_SMALL;
-    }
+    if (nref != GM_OK) {
+        return nref;
+    }
core/src/util/ref.c (1)

11-18: Zero output deterministically and map snprintf errors precisely.

Avoid partial output on failure; return specific errors.

 int gm_build_ref(char *out, size_t out_sz, const char *prefix,
                  const char *branch) {
-    if (!out || out_sz == 0 || !prefix || !branch) {
+    if (!out || out_sz == 0 || !prefix || !branch) {
         return GM_ERR_INVALID_ARGUMENT;
     }
+    out[0] = '\0';
     if (*branch == '\0') {
         return GM_ERR_INVALID_ARGUMENT;
     }
docs/operations/Environment_Variables.md (1)

88-94: Tighten HOOKS_BYPASS guidance: maintainers/emergencies only + require an issue/PR reference.

Aligns with prior feedback and reduces casual bypass.

Apply:

 - `HOOKS_BYPASS`
-  - Purpose: Bypass local git hooks (e.g., the pre‑push CHANGELOG guard) in emergencies.
-  - Usage: `HOOKS_BYPASS=1 git push`
-  - Notes: Do not make a habit of bypassing hooks; update the CHANGELOG instead.
+  - Purpose: Emergency‑only bypass for local git hooks (e.g., the pre‑push CHANGELOG guard). Maintainers only.
+  - Usage: `HOOKS_BYPASS=1 ISSUE_OR_PR=#123 git push`
+  - Notes: Avoid routine use. Prefer updating the CHANGELOG. If used, reference an issue/PR in the push description.

Optionally update .githooks/pre-push to require ISSUE_OR_PR when HOOKS_BYPASS is set; I can provide a patch if desired.

meson.build (3)

3-3: Don’t hardcode c_std=c2x; probe and pick the highest supported standard.

Prevents toolchain breakage while still preferring C23.

Apply:

-project('git-mind', 'c',
-        version: '0.6.0',
-        default_options: ['c_std=c2x', 'warning_level=3', 'werror=true'])
+project('git-mind', 'c',
+        version: '0.6.0',
+        default_options: ['warning_level=3', 'werror=true'])

Then insert after Line 6:

+cc = meson.get_compiler('c')
+std_candidates = ['-std=c2x', '-std=gnu2x', '-std=c23', '-std=gnu23']
+std_supported = cc.get_supported_arguments(std_candidates)
+if std_supported.length() == 0
+  error('A C23-capable compiler is required (supports one of: c2x/gnu2x/c23/gnu23).')
+endif
+add_project_arguments(std_supported[0], language: 'c')

8-10: Avoid spawning shells for env reads; use meson.get_env().

Simpler, faster, and more portable.

Apply:

-in_docker = run_command('sh', '-lc', '[ "$GITMIND_DOCKER" = "1" ] && echo 1 || echo 0', check: false).stdout().strip() == '1'
-in_ci = run_command('sh', '-lc', '[ -n "$GITHUB_ACTIONS" ] && echo 1 || echo 0', check: false).stdout().strip() == '1'
-env_override = run_command('sh', '-lc', '[ "$GITMIND_ALLOW_HOST_BUILD" = "1" ] && echo 1 || echo 0', check: false).stdout().strip() == '1'
+in_docker = meson.get_env('GITMIND_DOCKER') == '1'
+in_ci = meson.get_env('GITHUB_ACTIONS') != ''
+env_override = meson.get_env('GITMIND_ALLOW_HOST_BUILD') == '1'

363-364: Make -include path robust for out‑of‑tree builds.

Use an absolute source‑root path.

Apply:

-    c_args : ['-include', '../' + hdr],
+    c_args : ['-include', join_paths(meson.source_root(), hdr)],
core/src/edge/edge.c (3)

47-50: Fix incorrect gm_memset_safe parameter order.

The function signature requires (dst, dstsz, val, n) but the current call passes parameters in the wrong order, which will cause a compilation error.

Based on the signature in core/include/gitmind/security/memory.h, apply this fix:

 static void edge_init_defaults(gm_edge_t *edge) {
-    (void)gm_memset_safe(edge, sizeof(gm_edge_t), 0, sizeof(gm_edge_t));
+    gm_memset_safe(edge, sizeof(*edge), 0, sizeof(*edge));
     edge->confidence = DefaultConfidence;
 }

135-144: Remove dangerous SHA fallback when OIDs differ.

When both OIDs are present and not equal, the function should return false immediately. The current logic incorrectly falls back to comparing legacy SHAs even when OIDs differ, violating the principle documented in learnings.

Apply this fix to enforce OID-first semantics:

-    /* Source: if both OIDs present, they must match; otherwise fallback to legacy SHA */
+    /* Source: if both OIDs present, they must match; only use SHA when OID missing */
     if (!git_oid_is_zero(&edge_a->src_oid) && !git_oid_is_zero(&edge_b->src_oid)) {
         if (git_oid_cmp(&edge_a->src_oid, &edge_b->src_oid) != 0) {
             return false;
         }
     } else {
         if (memcmp(edge_a->src_sha, edge_b->src_sha, GM_SHA1_SIZE) != 0) {
             return false;
         }
     }

146-155: Remove dangerous SHA fallback for target OIDs.

Same issue as source OIDs - when both target OIDs are present and differ, return false immediately without SHA fallback.

Apply this fix:

-    /* Target: same rule as Source */
+    /* Target: if both OIDs present, they must match; only use SHA when OID missing */
     if (!git_oid_is_zero(&edge_a->tgt_oid) && !git_oid_is_zero(&edge_b->tgt_oid)) {
         if (git_oid_cmp(&edge_a->tgt_oid, &edge_b->tgt_oid) != 0) {
             return false;
         }
     } else {
         if (memcmp(edge_a->tgt_sha, edge_b->tgt_sha, GM_SHA1_SIZE) != 0) {
             return false;
         }
     }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 056a167 and bc4c086.

📒 Files selected for processing (9)
  • AGENTS.md (3 hunks)
  • core/src/edge/edge.c (7 hunks)
  • core/src/journal/writer.c (5 hunks)
  • core/src/util/ref.c (1 hunks)
  • core/tests/unit/test_cache_meta.c (1 hunks)
  • core/tests/unit/test_cache_query.c (2 hunks)
  • core/tests/unit/test_journal_safety.c (1 hunks)
  • docs/operations/Environment_Variables.md (4 hunks)
  • meson.build (7 hunks)
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{c,cc,cpp,cxx,h,hpp,hxx,m,mm}

📄 CodeRabbit inference engine (CLAUDE.md)

NEVER use NOLINT to suppress clang-tidy warnings; ALWAYS fix the underlying issue

Files:

  • core/tests/unit/test_journal_safety.c
  • core/src/util/ref.c
  • core/src/edge/edge.c
  • core/tests/unit/test_cache_query.c
  • core/src/journal/writer.c
  • core/tests/unit/test_cache_meta.c
core/**

📄 CodeRabbit inference engine (AGENTS.md)

Add new code under core/ (C23 library: include/ for public headers, src/ for implementation, tests/ for unit tests)

Files:

  • core/tests/unit/test_journal_safety.c
  • core/src/util/ref.c
  • core/src/edge/edge.c
  • core/tests/unit/test_cache_query.c
  • core/src/journal/writer.c
  • core/tests/unit/test_cache_meta.c
{core,src,apps,include}/**/*.{c,h}

📄 CodeRabbit inference engine (AGENTS.md)

{core,src,apps,include}/**/*.{c,h}: Use C23 with warnings-as-errors; forbid VLAs and variable shadowing; require explicit function prototypes
Follow .clang-format (LLVM-based, 4 spaces, 80 columns, pointer alignment right)
Function and variable names in lower_snake_case with gm_ prefix
Macro names in UPPER_SNAKE case
Type names end with _t
Prefer specific header includes; follow include ordering as enforced by .clang-format
Introduce no new clang-tidy warnings (lint via tools/docker-clang-tidy.sh)

Files:

  • core/tests/unit/test_journal_safety.c
  • core/src/util/ref.c
  • core/src/edge/edge.c
  • core/tests/unit/test_cache_query.c
  • core/src/journal/writer.c
  • core/tests/unit/test_cache_meta.c
core/tests/unit/test_*.c

📄 CodeRabbit inference engine (AGENTS.md)

Unit tests live in core/tests/unit/ and are named test_.c; keep tests deterministic and isolated

Files:

  • core/tests/unit/test_journal_safety.c
  • core/tests/unit/test_cache_query.c
  • core/tests/unit/test_cache_meta.c
core/**/*.{c,h}

📄 CodeRabbit inference engine (AGENTS.md)

Prefer OID-first APIs in new core code: use git_oid (typedef gm_oid_t) and compare via git_oid_cmp

Files:

  • core/tests/unit/test_journal_safety.c
  • core/src/util/ref.c
  • core/src/edge/edge.c
  • core/tests/unit/test_cache_query.c
  • core/src/journal/writer.c
  • core/tests/unit/test_cache_meta.c
**/*.md

📄 CodeRabbit inference engine (AGENTS.md)

Comply with repository markdown lint rules (.markdownlint.jsonc); use make md-lint / make md-fix

Files:

  • AGENTS.md
  • docs/operations/Environment_Variables.md
docs/**/*.md

📄 CodeRabbit inference engine (AGENTS.md)

Docs must pass link and TOC checks (tools/docs/check_docs.py --mode link|toc)

Files:

  • docs/operations/Environment_Variables.md
🧠 Learnings (23)
📓 Common learnings
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/src/{cache,edge}/*.c : Use `git_oid_cmp()` for OID equality and `git_oid_raw()` when byte-access is required; avoid `memcmp` on OIDs directly
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/src/edge/edge.c : `gm_edge_equal()` must not use OR-style fallback; if OIDs are present use them exclusively, otherwise compare legacy fields—never consider objects equal when OIDs differ

Applied to files:

  • core/tests/unit/test_journal_safety.c
  • core/src/edge/edge.c
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/src/edge/edge.c : When both OID and SHA are present, validate internal consistency (detect mismatches) rather than silently accepting either

Applied to files:

  • core/tests/unit/test_journal_safety.c
  • core/src/edge/edge.c
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/include/gitmind/edge.h : Avoid struct bloat in `gm_edge_t`; do not store both legacy SHA arrays and OIDs long-term—phase out legacy SHA fields

Applied to files:

  • core/tests/unit/test_journal_safety.c
  • core/src/edge/edge.c
  • AGENTS.md
  • core/src/journal/writer.c
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/src/{cache,edge}/*.c : Use `git_oid_cmp()` for OID equality and `git_oid_raw()` when byte-access is required; avoid `memcmp` on OIDs directly

Applied to files:

  • core/tests/unit/test_journal_safety.c
  • core/src/edge/edge.c
  • core/tests/unit/test_cache_query.c
  • AGENTS.md
  • core/tests/unit/test_cache_meta.c
📚 Learning: 2025-09-15T01:21:16.867Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-15T01:21:16.867Z
Learning: Applies to core/**/*.{c,h} : Prefer OID-first APIs in new core code: use git_oid (typedef gm_oid_t) and compare via git_oid_cmp

Applied to files:

  • core/tests/unit/test_journal_safety.c
  • core/src/edge/edge.c
  • AGENTS.md
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/**/*.c : Use bounded string functions (e.g., `gm_snprintf`) and ensure explicit NUL termination on all string operations

Applied to files:

  • core/src/util/ref.c
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/src/journal/reader.c : Split overly long CBOR decoder functions (e.g., `gm_edge_attributed_decode_cbor_ex`) into smaller units for maintainability

Applied to files:

  • core/src/edge/edge.c
📚 Learning: 2025-09-13T03:13:54.145Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-13T03:13:54.145Z
Learning: Applies to include/gitmind.h : Maintain umbrella API at include/gitmind.h

Applied to files:

  • core/src/edge/edge.c
  • core/src/journal/writer.c
📚 Learning: 2025-09-15T01:21:16.866Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-15T01:21:16.866Z
Learning: Applies to **/*.md : Comply with repository markdown lint rules (.markdownlint.jsonc); use make md-lint / make md-fix

Applied to files:

  • AGENTS.md
📚 Learning: 2025-09-13T03:13:54.145Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-13T03:13:54.145Z
Learning: Use Meson/Ninja for build and tests; run lint and gauntlet locally; keep diffs minimal and pass CI with zero new clang-tidy warnings

Applied to files:

  • AGENTS.md
  • meson.build
📚 Learning: 2025-09-13T03:13:54.145Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-13T03:13:54.145Z
Learning: Run build, tests, clang-tidy (via tools/docker-clang-tidy.sh), and gauntlet locally before proposing changes; keep changes zero-warnings and formatted

Applied to files:

  • AGENTS.md
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/src/**/*.c : Normalize error handling to a single scheme (prefer `GM_OK`/`GM_ERR_*`) and avoid mixing raw libgit2 error codes

Applied to files:

  • AGENTS.md
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/include/gitmind/types.h : Define and consistently use the alias `typedef git_oid gm_oid_t` as the canonical OID type

Applied to files:

  • AGENTS.md
📚 Learning: 2025-09-15T01:21:16.866Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-15T01:21:16.866Z
Learning: Applies to {include,core,src,apps}/**/*.h : Header guards must begin with GITMIND_ and remain stable

Applied to files:

  • AGENTS.md
  • docs/operations/Environment_Variables.md
📚 Learning: 2025-09-15T01:21:16.866Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-15T01:21:16.866Z
Learning: Applies to include/{gitmind.h,gitmind/**/*.h} : Public headers must be umbrella-safe: compile standalone, maintain correct include order, have stable GITMIND_* header guards, and provide extern "C" when included from C++

Applied to files:

  • AGENTS.md
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/src/cache/*.{c,h} : Maintain consistent OID-centric naming for hash utilities and constants (e.g., `oid_hash()`, `OID_HASH_MULTIPLIER`)

Applied to files:

  • AGENTS.md
📚 Learning: 2025-09-14T09:27:33.266Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-14T09:27:33.266Z
Learning: NEVER alter, disable, or otherwise circumvent git hooks or tests

Applied to files:

  • docs/operations/Environment_Variables.md
📚 Learning: 2025-09-13T03:13:54.145Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-13T03:13:54.145Z
Learning: Applies to {include,core/include}/**/*.h : Header guards use GITMIND_* naming

Applied to files:

  • docs/operations/Environment_Variables.md
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/src/journal/writer.c : Base64-encode CBOR payloads in commit messages to prevent binary corruption

Applied to files:

  • core/src/journal/writer.c
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/src/journal/*.c : Do not hardcode CBOR field key magic numbers; use centralized definitions from `gitmind/cbor/keys.h`

Applied to files:

  • core/src/journal/writer.c
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/src/journal/*.c : Add strict bounds checking for all CBOR parsing paths (lengths, indices, and buffer limits)

Applied to files:

  • core/src/journal/writer.c
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/**/meson.build : Do not hardcode `c_std=c23`; detect compiler support or provide a compatible minimum standard with feature checks

Applied to files:

  • meson.build
🧬 Code graph analysis (4)
core/tests/unit/test_journal_safety.c (1)
core/src/edge/edge.c (1)
  • gm_edge_equal (130-159)
core/src/util/ref.c (1)
core/include/gitmind/security/string.h (1)
  • gm_snprintf (74-80)
core/src/edge/edge.c (3)
core/include/gitmind/security/memory.h (1)
  • gm_memset_safe (47-59)
core/include/gitmind/util/memory.h (1)
  • gm_strcpy_safe (113-138)
core/src/cbor/cbor.c (1)
  • gm_cbor_read_bytes (190-244)
core/src/journal/writer.c (2)
core/src/util/ref.c (1)
  • gm_build_ref (11-43)
core/include/gitmind/security/memory.h (1)
  • gm_memcpy_safe (23-35)
🪛 GitHub Actions: Core Quality Checks
core/tests/unit/test_cache_query.c

[error] 67-67: use of undeclared identifier 'setenv'; did you mean 'getenv'? (Compiler: clang during ninja build; Command: clang -Itest_cache_query.p -I. -I.. -I../include -I../core/include -fdiagnostics-color=always -fsanitize=address -fno-omit-frame-pointer -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wextra -Wpedantic -Werror -std=c2x -O0 -g -ffreestanding -fstrict-flex-arrays=3 -Wdouble-promotion -Wpedantic -Wvla -Wshadow -Wstrict-prototypes -Wconversion -Wsign-conversion -Wfloat-equal -Wpointer-arith -Wcast-align -Wwrite-strings -Wmissing-prototypes -Wmissing-declarations -Wredundant-decls -Wnested-externs -Winline -fno-common -fstrict-aliasing -DGITMIND_ENABLE_UTF8 -fsanitize=address -fno-omit-frame-pointer -g -pthread -MD -MQ test_cache_query.p/core_tests_unit_test_cache_query.c.o -MF test_cache_query.p/core_tests_unit_test_cache_query.c.o.d -o test_cache_query.p/core_tests_unit_test_cache_query.c.o -c ../core/tests/unit/test_cache_query.c)


[error] 67-67: too many arguments to function call, expected single argument '__name', have 3 arguments. (Compiler: clang during ninja build; Command: clang -Itest_cache_query.p -I. -I.. -I../include -I../core/include -fdiagnostics-color=always -fsanitize=address -fno-omit-frame-pointer -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wextra -Wpedantic -Werror -std=c2x -O0 -g -ffreestanding -fstrict-flex-arrays=3 -Wdouble-promotion -Wpedantic -Wvla -Wshadow -Wstrict-prototypes -Wconversion -Wsign-conversion -Wfloat-equal -Wpointer-arith -Wcast-align -Wwrite-strings -Wmissing-prototypes -Wmissing-declarations -Wredundant-decls -Wnested-externs -Winline -fno-common -fstrict-aliasing -DGITMIND_ENABLE_UTF8 -fsanitize=address -fno-omit-frame-pointer -g -pthread -MD -MQ test_cache_query.p/core_tests_unit_test_cache_query.c.o -MF test_cache_query.p/core_tests_unit_test_cache_query.c.o.d -o test_cache_query.p/core_tests_unit_test_cache_query.c.o -c ../core/tests/unit/test_cache_query.c)

meson.build

[warning] 368-368: WARNING: Trying to use ['address'] sanitizer on Clang with b_lundef. This will probably not work. Try setting b_lundef to false instead.

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Compat Canaries (non-blocking) (gcc-12)
  • GitHub Check: Compat Canaries (non-blocking) (clang-18)
  • GitHub Check: Compat Canaries (non-blocking) (clang-19)
  • GitHub Check: Compat Canaries (non-blocking) (gcc-13)
🔇 Additional comments (16)
core/tests/unit/test_journal_safety.c (1)

72-76: Both-differ case is good and aligns with OID-first contract.

core/tests/unit/test_cache_meta.c (2)

21-24: Confirm libgit2 API: git_treebuilder_new signature varies by version.

Many libgit2 releases use git_treebuilder_new(&tb, source_tree) (no repo param). Verify CI image’s libgit2 matches this call or adjust accordingly.

Would you like me to grep headers in the CI image or check the pinned libgit2 version to ensure compatibility?


30-39: LGTM: commit-from-IDs + explicit legacy ref is clear.

Direct commit creation and then git_reference_create to the legacy path simplifies the test and avoids ref side effects.

core/src/journal/writer.c (1)

185-196: LGTM: env-based branch override for tests.

Simple, safe, and contained to tests; gm_build_ref will validate downstream.

docs/operations/Environment_Variables.md (3)

1-10: Front‑matter looks good.

Metadata is complete and current.


32-36: Verified — default CI image matches workflows and local CI.
docs/operations/Environment_Variables.md default gitmind/ci:clang-20 matches the fallbacks used in .github/workflows/c_core.yml and tools/ci/ci_local.sh.


82-87: Update docs: GITMIND_TEST_BRANCH is an unconditional test override when set — not only for repos without HEAD.

core/src/journal/writer.c reads getenv("GITMIND_TEST_BRANCH") and prefers it over the current branch when non-empty (around line 185); update docs/operations/Environment_Variables.md to remove the "repo has no HEAD" qualification and state that the env var overrides the branch when set.

Likely an incorrect or invalid review comment.

meson.build (4)

126-127: LGTM: core/src/util/ref.c added to sources.

Matches the new gm_build_ref API usage elsewhere.


130-130: LGTM: include order favors public headers.

This aligns with the constants unification work.


292-308: LGTM: new unit tests registered and linked correctly.

Targets and deps look consistent.


332-335: LGTM: test registrations.

No duplicates observed in this block.

core/src/edge/edge.c (5)

13-14: ✅ Good security hardening with memory safety headers.

The addition of gitmind/security/memory.h and gitmind/util/memory.h aligns with the PR's safety sweeps objective, providing safe memory operations to replace potentially vulnerable raw operations.


111-113: ✅ Proper safe string operations for path fields.

Good use of gm_strcpy_safe with appropriate bounds checking for both source and target paths, replacing potentially unsafe string operations.


337-348: ✅ Good OID-first CBOR encoding with safe fallback.

The encoding correctly prefers OID fields while maintaining backward compatibility with SHA fallback when OIDs are unavailable. The cast to const uint8_t* is appropriate for accessing raw OID bytes.


427-440: ✅ Proper CBOR decoding for new OID fields.

The implementation correctly decodes the new OID fields from CBOR, using temporary buffers and git_oid_fromraw to populate the edge's OID fields.


477-482: ✅ Appropriate OID backfill from legacy SHA.

Good defensive programming - backfilling OIDs from legacy SHA fields when missing ensures consistent internal state after decoding older CBOR data.

Comment thread core/src/util/ref.c
Comment thread core/tests/unit/test_cache_query.c Outdated
Comment on lines +16 to +46
/* kept for reference; unused after env branch override */
__attribute__((unused)) static void ensure_branch_with_commit(git_repository *repo, const char *branch) {
git_treebuilder *tb = NULL;
git_oid tree_oid, commit_oid;
git_signature *sig = NULL;
int rc;

rc = git_treebuilder_new(&tb, repo, NULL);
assert(rc == 0);
rc = git_treebuilder_write(&tree_oid, tb);
git_treebuilder_free(tb);
assert(rc == 0);

rc = git_signature_now(&sig, "tester", "tester@example.com");
assert(rc == 0);

char refname[128];
snprintf(refname, sizeof refname, "refs/heads/%s", branch);

git_tree *tree = NULL;
rc = git_tree_lookup(&tree, repo, &tree_oid);
assert(rc == 0);
rc = git_commit_create(&commit_oid, repo, refname, sig, sig, NULL,
"init", tree, 0, NULL);
git_tree_free(tree);
git_signature_free(sig);
assert(rc == 0);

rc = git_repository_set_head(repo, refname);
assert(rc == 0);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick

Drop the unused helper to keep tests lean.

Even with attribute((unused)), this dead code adds noise.

-/* kept for reference; unused after env branch override */
-__attribute__((unused)) static void ensure_branch_with_commit(git_repository *repo, const char *branch) {
-    git_treebuilder *tb = NULL;
-    git_oid tree_oid, commit_oid;
-    git_signature *sig = NULL;
-    int rc;
-    rc = git_treebuilder_new(&tb, repo, NULL);
-    assert(rc == 0);
-    rc = git_treebuilder_write(&tree_oid, tb);
-    git_treebuilder_free(tb);
-    assert(rc == 0);
-    rc = git_signature_now(&sig, "tester", "tester@example.com");
-    assert(rc == 0);
-    char refname[128];
-    snprintf(refname, sizeof refname, "refs/heads/%s", branch);
-    git_tree *tree = NULL;
-    rc = git_tree_lookup(&tree, repo, &tree_oid);
-    assert(rc == 0);
-    rc = git_commit_create(&commit_oid, repo, refname, sig, sig, NULL,
-                           "init", tree, 0, NULL);
-    git_tree_free(tree);
-    git_signature_free(sig);
-    assert(rc == 0);
-    rc = git_repository_set_head(repo, refname);
-    assert(rc == 0);
-}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/* kept for reference; unused after env branch override */
__attribute__((unused)) static void ensure_branch_with_commit(git_repository *repo, const char *branch) {
git_treebuilder *tb = NULL;
git_oid tree_oid, commit_oid;
git_signature *sig = NULL;
int rc;
rc = git_treebuilder_new(&tb, repo, NULL);
assert(rc == 0);
rc = git_treebuilder_write(&tree_oid, tb);
git_treebuilder_free(tb);
assert(rc == 0);
rc = git_signature_now(&sig, "tester", "tester@example.com");
assert(rc == 0);
char refname[128];
snprintf(refname, sizeof refname, "refs/heads/%s", branch);
git_tree *tree = NULL;
rc = git_tree_lookup(&tree, repo, &tree_oid);
assert(rc == 0);
rc = git_commit_create(&commit_oid, repo, refname, sig, sig, NULL,
"init", tree, 0, NULL);
git_tree_free(tree);
git_signature_free(sig);
assert(rc == 0);
rc = git_repository_set_head(repo, refname);
assert(rc == 0);
}
🤖 Prompt for AI Agents
In core/tests/unit/test_cache_query.c around lines 16 to 46, the static helper
function ensure_branch_with_commit is unused and should be removed to reduce
dead code; delete the entire function definition (including the
__attribute__((unused)) declaration and its body) and ensure no remaining
references exist elsewhere in the file or tests; run the unit tests to confirm
no breakage.

Comment thread core/tests/unit/test_cache_query.c Outdated
Comment on lines +64 to 71
/* OIDs differ but legacy SHAs match => OID-first: not equal */
gm_edge_t c = a, d = a;
uint8_t other_raw[GM_OID_RAWSZ];
memset(other_raw, 0xBB, sizeof other_raw);
git_oid_fromraw(&c.src_oid, other_raw);
git_oid_fromraw(&d.tgt_oid, other_raw);
assert(gm_edge_equal(&c, &d));
assert(!gm_edge_equal(&c, &d));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick

OID-first semantics correct; add src-only and tgt-only mismatch asserts for precision.

Current case changes both ends; add single-end deltas too.

     git_oid_fromraw(&c.src_oid, other_raw);
     git_oid_fromraw(&d.tgt_oid, other_raw);
     assert(!gm_edge_equal(&c, &d));
+
+    /* Only source OID differs -> not equal */
+    gm_edge_t c2 = a, d2 = a;
+    git_oid_fromraw(&c2.src_oid, other_raw);
+    assert(!gm_edge_equal(&c2, &d2));
+
+    /* Only target OID differs -> not equal */
+    gm_edge_t c3 = a, d3 = a;
+    git_oid_fromraw(&d3.tgt_oid, other_raw);
+    assert(!gm_edge_equal(&c3, &d3));
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/* OIDs differ but legacy SHAs match => OID-first: not equal */
gm_edge_t c = a, d = a;
uint8_t other_raw[GM_OID_RAWSZ];
memset(other_raw, 0xBB, sizeof other_raw);
git_oid_fromraw(&c.src_oid, other_raw);
git_oid_fromraw(&d.tgt_oid, other_raw);
assert(gm_edge_equal(&c, &d));
assert(!gm_edge_equal(&c, &d));
/* OIDs differ but legacy SHAs match => OID-first: not equal */
gm_edge_t c = a, d = a;
uint8_t other_raw[GM_OID_RAWSZ];
memset(other_raw, 0xBB, sizeof other_raw);
git_oid_fromraw(&c.src_oid, other_raw);
git_oid_fromraw(&d.tgt_oid, other_raw);
assert(!gm_edge_equal(&c, &d));
/* Only source OID differs -> not equal */
gm_edge_t c2 = a, d2 = a;
git_oid_fromraw(&c2.src_oid, other_raw);
assert(!gm_edge_equal(&c2, &d2));
/* Only target OID differs -> not equal */
gm_edge_t c3 = a, d3 = a;
git_oid_fromraw(&d3.tgt_oid, other_raw);
assert(!gm_edge_equal(&c3, &d3));
🤖 Prompt for AI Agents
In core/tests/unit/test_journal_safety.c around lines 64 to 71, the test only
covers the case where both endpoints are changed; add two additional cases to
assert mismatches when only one endpoint differs: clone 'a' into a new gm_edge_t
(e.g., e), change only e.src_oid to other_raw and assert !gm_edge_equal(&e, &a);
then clone 'a' into another gm_edge_t (e.g., f), change only f.tgt_oid to
other_raw and assert !gm_edge_equal(&f, &a). Ensure you reuse the existing
other_raw and keep the same memset and git_oid_fromraw pattern so each
single-end delta is validated.

Comment on lines +45 to +50
- `GITMIND_CBOR_DEBUG`
- Purpose: Enable verbose CBOR decode tracing in the journal reader.
- Used by: `core/src/journal/reader.c`.
- Values: `1`, `true`, or `yes` (case-insensitive) to enable; anything else disables.
- Notes: Prints offsets and decode attempts to `stderr`; use only for debugging.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick

Add an explicit “no CI/production” caution for CBOR debug.

This reduces accidental sensitive/verbose logging in shared environments.

Apply:

-  - Notes: Prints offsets and decode attempts to `stderr`; use only for debugging.
+  - Notes: Prints offsets and decode attempts to `stderr`; use only for debugging. Avoid enabling in CI or production; logs may include decoded payload details.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- `GITMIND_CBOR_DEBUG`
- Purpose: Enable verbose CBOR decode tracing in the journal reader.
- Used by: `core/src/journal/reader.c`.
- Values: `1`, `true`, or `yes` (case-insensitive) to enable; anything else disables.
- Notes: Prints offsets and decode attempts to `stderr`; use only for debugging.
- `GITMIND_CBOR_DEBUG`
- Purpose: Enable verbose CBOR decode tracing in the journal reader.
- Used by: `core/src/journal/reader.c`.
- Values: `1`, `true`, or `yes` (case-insensitive) to enable; anything else disables.
- Notes: Prints offsets and decode attempts to `stderr`; use only for debugging. Avoid enabling in CI or production; logs may include decoded payload details.
🤖 Prompt for AI Agents
In docs/operations/Environment_Variables.md around lines 45–50, add an explicit
caution directly after the "Notes" line warning that GITMIND_CBOR_DEBUG must not
be enabled in CI or production; state that it produces verbose output to stderr,
can expose sensitive data and overwhelm logs, and should only be used in
local/dev debugging sessions. Update the wording to be short and prescriptive
(e.g., "Do not enable in CI or production; local debugging only") and, if
desired, suggest using feature flags or guarded local-only scripts to set this
env var.

Comment thread meson.build
Comment on lines 1 to 4
project('git-mind', 'c',
version: '0.6.0',
default_options: ['c_std=c23', 'warning_level=3', 'werror=true'])
default_options: ['c_std=c2x', 'warning_level=3', 'werror=true'])

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick

ASAN + Clang warning: set b_lundef=false in sanitized builds.

CI shows “Trying to use ['address'] sanitizer on Clang with b_lundef…”. Pass -Db_lundef=false in the ASAN job (or create a dedicated sanitized configure step) to avoid link failures.

If desired, I can draft the workflow tweak for the sanitized job.

🤖 Prompt for AI Agents
In meson.build around lines 1 to 4, the CI sanitized build is failing on Clang
due to b_lundef being true; update the sanitized CI job to pass -Db_lundef=false
to meson configure (or add a dedicated sanitized configure step that includes
-Db_lundef=false) so the AddressSanitizer build on Clang links successfully.

@flyingrobots

Copy link
Copy Markdown
Owner Author

Update:\n- Enforced Docker-only builds with Meson gate + warning blocks.\n- Finalized OID-first equality and aligned tests.\n- Hardened ref building for cross-libgit2 compatibility.\n- Stabilized cache_meta/cache_query tests for bare repos.\n- Local CI (Docker) is green: 24/24 tests pass.\n- Re-ran failing workflows (C-Core Gate, Core Quality Checks). Will monitor.\n\nIf any CI issue persists, I’ll patch swiftly to green.

ghost left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
core/tests/unit/test_cache_query.c (1)

1-107: Remove internal libgit2 <git2/sys/...> includes

Replace the internal includes with public libgit2 headers (e.g. <git2/commit.h> or rely on <git2.h>) and remove these lines:

  • core/tests/unit/test_cache_query.c:10 — #include <git2/sys/commit.h>
  • core/tests/unit/test_cache_meta.c:8 — #include <git2/sys/commit.h>
♻️ Duplicate comments (1)
core/src/util/ref.c (1)

12-54: Build canonical refs via git_reference_normalize_name; remove ad‑hoc checks.

Leverage libgit2 normalization, keep deterministic output, and map snprintf errors precisely. This also matches the PR’s stated behavior.

Apply:

 int gm_build_ref(char *out, size_t out_sz, const char *prefix,
                  const char *branch) {
-    if (!out || out_sz == 0 || !prefix || !branch) {
-        return GM_ERR_INVALID_ARGUMENT;
-    }
-    if (*branch == '\0') {
-        return GM_ERR_INVALID_ARGUMENT;
-    }
-    /* Require shorthand branch (no leading "refs/") to avoid double prefixing */
-    if (branch[0] == 'r' && branch[1] == 'e' && branch[2] == 'f' &&
-        branch[3] == 's' && branch[4] == '/') {
-        return GM_ERR_INVALID_ARGUMENT;
-    }
-
-    char candidate[REF_NAME_BUFFER_SIZE];
-    int rn = gm_snprintf(candidate, sizeof candidate, "%s%s", prefix, branch);
-    if (rn < 0 || (size_t)rn >= sizeof candidate) {
-        return GM_ERR_BUFFER_TOO_SMALL;
-    }
-
-    /* Minimal validity checks without libgit2 dependency */
-    {
-        const char *p = branch;
-        if (*p == '/' || p[strlen(p) - 1] == '/') {
-            return GM_ERR_INVALID_ARGUMENT;
-        }
-        for (; *p; ++p) {
-            const char c = *p;
-            if (c == '~' || c == '^' || c == ':' || c == '?' ||
-                c == '[' || c == '*' || c == '\\') {
-                return GM_ERR_INVALID_ARGUMENT;
-            }
-        }
-        if (strstr(branch, "..") != NULL) return GM_ERR_INVALID_ARGUMENT;
-        if (strstr(branch, "@{") != NULL) return GM_ERR_INVALID_ARGUMENT;
-    }
-
-    rn = gm_snprintf(out, out_sz, "%s", candidate);
-    if (rn < 0 || (size_t)rn >= out_sz) {
-        return GM_ERR_BUFFER_TOO_SMALL;
-    }
-    return GM_OK;
+    if (!out || out_sz == 0 || !prefix || !branch) return GM_ERR_INVALID_ARGUMENT;
+    out[0] = '\0';
+    if (*branch == '\0') return GM_ERR_INVALID_ARGUMENT;
+    /* Require shorthand branch (no leading "refs/") to avoid double prefixing */
+    if (strncmp(branch, "refs/", 5) == 0) return GM_ERR_INVALID_ARGUMENT;
+
+    char candidate[REF_NAME_BUFFER_SIZE];
+    int rn = gm_snprintf(candidate, sizeof candidate, "%s%s", prefix, branch);
+    if (rn < 0) return GM_ERR_INVALID_ARGUMENT;
+    if ((size_t)rn >= sizeof candidate) return GM_ERR_BUFFER_TOO_SMALL;
+
+    char normalized[REF_NAME_BUFFER_SIZE];
+    if (git_reference_normalize_name(normalized, sizeof normalized, candidate, 0) != 0) {
+        out[0] = '\0';
+        return GM_ERR_INVALID_ARGUMENT;
+    }
+
+    rn = gm_snprintf(out, out_sz, "%s", normalized);
+    if (rn < 0) { out[0] = '\0'; return GM_ERR_INVALID_ARGUMENT; }
+    if ((size_t)rn >= out_sz) { out[0] = '\0'; return GM_ERR_BUFFER_TOO_SMALL; }
+    return GM_OK;
 }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bc4c086 and e4f3f90.

📒 Files selected for processing (2)
  • core/src/util/ref.c (1 hunks)
  • core/tests/unit/test_cache_query.c (2 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{c,cc,cpp,cxx,h,hpp,hxx,m,mm}

📄 CodeRabbit inference engine (CLAUDE.md)

NEVER use NOLINT to suppress clang-tidy warnings; ALWAYS fix the underlying issue

Files:

  • core/tests/unit/test_cache_query.c
  • core/src/util/ref.c
core/**

📄 CodeRabbit inference engine (AGENTS.md)

Add new code under core/ (C23 library: include/ for public headers, src/ for implementation, tests/ for unit tests)

Files:

  • core/tests/unit/test_cache_query.c
  • core/src/util/ref.c
{core,src,apps,include}/**/*.{c,h}

📄 CodeRabbit inference engine (AGENTS.md)

{core,src,apps,include}/**/*.{c,h}: Use C23 with warnings-as-errors; forbid VLAs and variable shadowing; require explicit function prototypes
Follow .clang-format (LLVM-based, 4 spaces, 80 columns, pointer alignment right)
Function and variable names in lower_snake_case with gm_ prefix
Macro names in UPPER_SNAKE case
Type names end with _t
Prefer specific header includes; follow include ordering as enforced by .clang-format
Introduce no new clang-tidy warnings (lint via tools/docker-clang-tidy.sh)

Files:

  • core/tests/unit/test_cache_query.c
  • core/src/util/ref.c
core/tests/unit/test_*.c

📄 CodeRabbit inference engine (AGENTS.md)

Unit tests live in core/tests/unit/ and are named test_.c; keep tests deterministic and isolated

Files:

  • core/tests/unit/test_cache_query.c
core/**/*.{c,h}

📄 CodeRabbit inference engine (AGENTS.md)

Prefer OID-first APIs in new core code: use git_oid (typedef gm_oid_t) and compare via git_oid_cmp

Files:

  • core/tests/unit/test_cache_query.c
  • core/src/util/ref.c
🧠 Learnings (4)
📓 Common learnings
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/src/{cache,edge}/*.c : Use `git_oid_cmp()` for OID equality and `git_oid_raw()` when byte-access is required; avoid `memcmp` on OIDs directly
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/src/{cache,edge}/*.c : Use `git_oid_cmp()` for OID equality and `git_oid_raw()` when byte-access is required; avoid `memcmp` on OIDs directly

Applied to files:

  • core/tests/unit/test_cache_query.c
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/**/*.c : Use bounded string functions (e.g., `gm_snprintf`) and ensure explicit NUL termination on all string operations

Applied to files:

  • core/src/util/ref.c
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/src/**/*.c : Normalize error handling to a single scheme (prefer `GM_OK`/`GM_ERR_*`) and avoid mixing raw libgit2 error codes

Applied to files:

  • core/src/util/ref.c
🧬 Code graph analysis (1)
core/src/util/ref.c (1)
core/include/gitmind/security/string.h (1)
  • gm_snprintf (74-80)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Compat Canaries (non-blocking) (clang-19)
  • GitHub Check: Compat Canaries (non-blocking) (clang-18)
  • GitHub Check: Compat Canaries (non-blocking) (gcc-12)
  • GitHub Check: Compat Canaries (non-blocking) (gcc-13)
  • GitHub Check: lint-and-sanitize
🔇 Additional comments (2)
core/tests/unit/test_cache_query.c (1)

67-67: LGTM: explicit test branch creation fixes prior env/setenv CI issue.

This removes the need for env overrides and stabilizes the test.

core/src/util/ref.c (1)

10-11: Confirm git_reference_normalize_name availability in CI — gate or provide a fallback

  • meson.build currently has libgit2_dep = dependency('libgit2', required : true) (≈line 79) and no code-level check for git_reference_normalize_name; either add a minimum libgit2 version requirement in meson.build or add a configure-time feature check (compile-time/cc.has_function) and a runtime/compile fallback.
  • Verify the CI image (default IMAGE gitmind/ci:clang-20 in tools/ci/ci_local.sh) includes the libgit2 dev package with the required symbol.

Comment thread core/src/util/ref.c
Comment on lines +20 to +24
/* Require shorthand branch (no leading "refs/") to avoid double prefixing */
if (branch[0] == 'r' && branch[1] == 'e' && branch[2] == 'f' &&
branch[3] == 's' && branch[4] == '/') {
return GM_ERR_INVALID_ARGUMENT;
}

ghost Sep 16, 2025

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick

Stale comment contradicts implementation.

“without libgit2 dependency” no longer applies after including <git2.h>. Remove or update.

🤖 Prompt for AI Agents
In core/src/util/ref.c around lines 20 to 24, the file comment that claims the
code is “without libgit2 dependency” is now stale because git2.h is included;
remove or update that comment to reflect that libgit2 is used (or reword to
explain why this check is independent of libgit2), and ensure the comment no
longer contradicts the current implementation.

#include <git2.h>

#include "gitmind/cache.h"
#include <git2/sys/commit.h>

ghost Sep 16, 2025

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Avoid internal libgit2 headers; use public API.

Replace sys header with the public header (or drop entirely since <git2.h> is included).

Apply:

-#include <git2/sys/commit.h>
+#include <git2/commit.h>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
#include <git2/sys/commit.h>
#include <git2/commit.h>
🤖 Prompt for AI Agents
In core/tests/unit/test_cache_query.c at line 10, an internal header
<git2/sys/commit.h> is included; remove this internal sys header and either rely
on the already included public <git2.h> or, if you need commit-specific symbols,
include the public <git2/commit.h> instead.

Comment on lines +32 to +34
char refname[128];
snprintf(refname, sizeof refname, "refs/heads/%s", branch);

ghost Sep 16, 2025

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick

Minor: prefer gm_snprintf in core tests for consistency.

Not critical for tests, but aligns with repo’s safety wrappers.

Apply:

-    snprintf(refname, sizeof refname, "refs/heads/%s", branch);
+    gm_snprintf(refname, sizeof refname, "refs/heads/%s", branch);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
char refname[128];
snprintf(refname, sizeof refname, "refs/heads/%s", branch);
char refname[128];
gm_snprintf(refname, sizeof refname, "refs/heads/%s", branch);
🤖 Prompt for AI Agents
In core/tests/unit/test_cache_query.c around lines 32 to 34, the test uses
snprintf to format refname; replace the call with the repository's safer wrapper
gm_snprintf using the same buffer and size arguments (gm_snprintf(refname,
sizeof refname, "refs/heads/%s", branch)) so tests follow the project's
consistency and safety conventions.

Comment on lines +35 to +43
/* Create a commit object and then a direct ref to it */
rc = git_commit_create_from_ids(&commit_oid, repo, NULL, sig, sig, NULL,
"init", &tree_oid, 0, NULL);
git_signature_free(sig);
assert(rc == 0);
git_reference *ref = NULL;
rc = git_reference_create(&ref, repo, refname, &commit_oid, 1, "init");
if (ref) git_reference_free(ref);
assert(rc == 0);

ghost Sep 16, 2025

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Use portable commit creation; drop dependency on commit-from-ids + manual ref create.

Prefer git_commit_create with a looked-up tree and update_ref=refname. This removes the need for internal headers and is widely supported.

Apply:

-    /* Create a commit object and then a direct ref to it */
-    rc = git_commit_create_from_ids(&commit_oid, repo, NULL, sig, sig, NULL,
-                                    "init", &tree_oid, 0, NULL);
-    git_signature_free(sig);
-    assert(rc == 0);
-    git_reference *ref = NULL;
-    rc = git_reference_create(&ref, repo, refname, &commit_oid, 1, "init");
-    if (ref) git_reference_free(ref);
-    assert(rc == 0);
+    /* Create a commit at refname using the public API */
+    git_tree *tree = NULL;
+    rc = git_tree_lookup(&tree, repo, &tree_oid);
+    assert(rc == 0);
+    rc = git_commit_create(&commit_oid, repo, refname, sig, sig, NULL,
+                           "init", tree, 0, NULL);
+    git_tree_free(tree);
+    git_signature_free(sig);
+    assert(rc == 0);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/* Create a commit object and then a direct ref to it */
rc = git_commit_create_from_ids(&commit_oid, repo, NULL, sig, sig, NULL,
"init", &tree_oid, 0, NULL);
git_signature_free(sig);
assert(rc == 0);
git_reference *ref = NULL;
rc = git_reference_create(&ref, repo, refname, &commit_oid, 1, "init");
if (ref) git_reference_free(ref);
assert(rc == 0);
/* Create a commit at refname using the public API */
git_tree *tree = NULL;
rc = git_tree_lookup(&tree, repo, &tree_oid);
assert(rc == 0);
rc = git_commit_create(&commit_oid, repo, refname, sig, sig, NULL,
"init", tree, 0, NULL);
git_tree_free(tree);
git_signature_free(sig);
assert(rc == 0);
🤖 Prompt for AI Agents
In core/tests/unit/test_cache_query.c around lines 35 to 43, the test currently
builds a commit via git_commit_create_from_ids then manually creates a
reference; replace this with a portable git_commit_create call that looks up the
tree (git_tree_lookup or git_object_peel+lookup), passes the looked-up tree OID
into git_commit_create and uses the update_ref parameter set to refname so the
ref is created atomically; remove the manual git_reference_create call and
adjust cleanup to free the tree/commit signature objects as needed.

Comment on lines +45 to +47
rc = git_repository_set_head(repo, refname);
assert(rc == 0);
}

ghost Sep 16, 2025

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick

Optional: set_head likely redundant after git_commit_create.

git_commit_create updates refname; HEAD is already pointing there when update_ref is used. Safe to keep, but can be removed.

🤖 Prompt for AI Agents
In core/tests/unit/test_cache_query.c around lines 45 to 47, the explicit call
to git_repository_set_head(repo, refname) is redundant because git_commit_create
already updates the ref (via update_ref) and HEAD will point there; remove the
git_repository_set_head call (or if you prefer to keep it for clarity, replace
it with a short comment stating it is optional/redundant) so the test relies on
the commit-created ref update and avoids unnecessary API calls.

J. Kirby Ross added 2 commits September 16, 2025 04:46
…ds, cache meta ABI, branch length checks, path buffers, safe strcpy checks, include style); update review log
…ng fixes (ref zeroing, comments, front matter/headers/titles)

ghost left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 16

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
core/src/hooks/augment.c (2)

97-106: realloc growth: add overflow and OOM-safe handling.

Double-check new_capacity overflow and use a temporary before assigning.

-            size_t new_capacity = ctx->capacity * ARRAY_GROWTH_FACTOR;
+            size_t new_capacity = ctx->capacity * ARRAY_GROWTH_FACTOR;
+            if (new_capacity < ctx->capacity) {
+                return GM_ERR_OUT_OF_MEMORY; /* overflow */
+            }
             gm_edge_t *new_edges =
                 realloc(ctx->edges, new_capacity * sizeof(gm_edge_t));
             if (!new_edges) {
                 return GM_ERR_OUT_OF_MEMORY;
             }

215-239: Simplify merge detection.

You can avoid git_repository_head() and use HEAD OID directly.

-    /* Get HEAD */
-    error = git_repository_head(&head_ref, repo);
-    if (error < 0) {
-        return GM_ERR_UNKNOWN;
-    }
-
-    /* Get commit */
-    git_oid oid;
-    error = git_reference_name_to_id(&oid, repo, "HEAD");
-    git_reference_free(head_ref);
+    git_oid oid;
+    int error = git_reference_name_to_id(&oid, repo, "HEAD");
     if (error < 0) {
         return GM_ERR_UNKNOWN;
     }
core/src/cache/builder.c (2)

168-178: Check gm_snprintf results for path truncation.

Propagate GM_ERR_BUFFER_TOO_SMALL if any path formatting truncates.

-            (void)gm_snprintf(path, sizeof(path), "%s/%s", temp_dir, prefix);
+            int rn = gm_snprintf(path, sizeof(path), "%s/%s", temp_dir, prefix);
+            if (rn < 0 || (size_t)rn >= sizeof(path)) return GM_ERR_BUFFER_TOO_SMALL;
             (void)mkdir(path, DIR_PERMS_NORMAL);
@@
-            (void)gm_snprintf(path, sizeof(path), "%s/%s/%s.%s", temp_dir,
-                              prefix, sha_hex, suffix);
+            rn = gm_snprintf(path, sizeof(path), "%s/%s/%s.%s",
+                             temp_dir, prefix, sha_hex, suffix);
+            if (rn < 0 || (size_t)rn >= sizeof(path)) return GM_ERR_BUFFER_TOO_SMALL;

43-44: Unused constant.

OID_HASH_MULTIPLIER is defined but unused; remove or use it in hashing.

♻️ Duplicate comments (6)
core/src/hooks/post-commit.c (2)

12-12: Public header switched to angle brackets — resolved

This addresses the earlier note about using angle brackets for public headers. Looks good.


232-232: gm_memset_safe usage is correct

Correct 4‑arg signature and full-struct zeroing before field assignment. This resolves the prior compile/runtime concern.

core/src/hooks/augment.c (2)

58-58: Unify NOT_FOUND error code.

Return GM_ERR_NOT_FOUND here to match other branches.

-        return GM_NOT_FOUND;
+        return GM_ERR_NOT_FOUND;

7-7: Use angle brackets for public header include.

Change quotes to angle brackets for public headers to follow include conventions.

-#include "gitmind/util/memory.h"
+#include <gitmind/util/memory.h>
core/src/cache/builder.c (2)

74-88: oid_hash: guard size==0 and use git_oid_raw().

Prevent modulo by zero and use the public accessor for OID bytes.

 /* Hash function for OID: lightweight mixing for better distribution */
 static size_t oid_hash(const gm_oid_t *oid, size_t size) {
-    const uint8_t *raw = (const uint8_t *)oid->id;
+    if (size == 0) return 0;
+    const uint8_t *raw = (const uint8_t *)git_oid_raw(oid);
     uint32_t x = 0x9E3779B9u; /* golden ratio */
     for (int i = 0; i < GM_OID_RAWSZ; i++) {
         x ^= raw[i];
         x *= 0x85EBCA6Bu;      /* mix */
         x ^= (x >> 13);
     }
     /* final avalanche */
     x ^= x >> 16;
     x *= 0x7FEB352Du;
     x ^= x >> 15;
     return (size_t)(x % (uint32_t)size);
 }

153-157: oid_to_hex: wrong size constant and return code.

Use GM_OID_HEX_CHARS+1 (or GM_CACHE_OID_STRING_SIZE) and return GM_ERR_BUFFER_TOO_SMALL on insufficient buffer.

 static int oid_to_hex(const gm_oid_t *oid, char *out, size_t out_size) {
-    if (out_size < SHA_HEX_SIZE) return GM_ERR_INVALID_ARGUMENT;
+    if (out_size < (GM_OID_HEX_CHARS + 1)) return GM_ERR_BUFFER_TOO_SMALL;
     (void)git_oid_tostr(out, out_size, oid);
     return GM_OK;
 }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e4f3f90 and 2504517.

📒 Files selected for processing (9)
  • .githooks/pre-push (1 hunks)
  • core/include/gitmind/cache.h (7 hunks)
  • core/include/gitmind/util/ref.h (1 hunks)
  • core/src/cache/builder.c (12 hunks)
  • core/src/hooks/augment.c (6 hunks)
  • core/src/hooks/post-commit.c (2 hunks)
  • docs/code-reviews/CLAUDE.md (2 hunks)
  • docs/code-reviews/PR169/e4f3f906eb454cb103eb8cc6899df8dfbf6e2349.md (1 hunks)
  • docs/templates/code-review-feedback.md (1 hunks)
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{c,cc,cpp,cxx,h,hpp,hxx,m,mm}

📄 CodeRabbit inference engine (CLAUDE.md)

NEVER use NOLINT to suppress clang-tidy warnings; ALWAYS fix the underlying issue

Files:

  • core/include/gitmind/util/ref.h
  • core/src/hooks/post-commit.c
  • core/include/gitmind/cache.h
  • core/src/cache/builder.c
  • core/src/hooks/augment.c
core/**

📄 CodeRabbit inference engine (AGENTS.md)

Add new code under core/ (C23 library: include/ for public headers, src/ for implementation, tests/ for unit tests)

Files:

  • core/include/gitmind/util/ref.h
  • core/src/hooks/post-commit.c
  • core/include/gitmind/cache.h
  • core/src/cache/builder.c
  • core/src/hooks/augment.c
{core,src,apps,include}/**/*.{c,h}

📄 CodeRabbit inference engine (AGENTS.md)

{core,src,apps,include}/**/*.{c,h}: Use C23 with warnings-as-errors; forbid VLAs and variable shadowing; require explicit function prototypes
Follow .clang-format (LLVM-based, 4 spaces, 80 columns, pointer alignment right)
Function and variable names in lower_snake_case with gm_ prefix
Macro names in UPPER_SNAKE case
Type names end with _t
Prefer specific header includes; follow include ordering as enforced by .clang-format
Introduce no new clang-tidy warnings (lint via tools/docker-clang-tidy.sh)

Files:

  • core/include/gitmind/util/ref.h
  • core/src/hooks/post-commit.c
  • core/include/gitmind/cache.h
  • core/src/cache/builder.c
  • core/src/hooks/augment.c
{include,core,src,apps}/**/*.h

📄 CodeRabbit inference engine (AGENTS.md)

Header guards must begin with GITMIND_ and remain stable

Files:

  • core/include/gitmind/util/ref.h
  • core/include/gitmind/cache.h
core/**/*.{c,h}

📄 CodeRabbit inference engine (AGENTS.md)

Prefer OID-first APIs in new core code: use git_oid (typedef gm_oid_t) and compare via git_oid_cmp

Files:

  • core/include/gitmind/util/ref.h
  • core/src/hooks/post-commit.c
  • core/include/gitmind/cache.h
  • core/src/cache/builder.c
  • core/src/hooks/augment.c
**/*.md

📄 CodeRabbit inference engine (AGENTS.md)

Comply with repository markdown lint rules (.markdownlint.jsonc); use make md-lint / make md-fix

Files:

  • docs/templates/code-review-feedback.md
  • docs/code-reviews/CLAUDE.md
  • docs/code-reviews/PR169/e4f3f906eb454cb103eb8cc6899df8dfbf6e2349.md
docs/**/*.md

📄 CodeRabbit inference engine (AGENTS.md)

Docs must pass link and TOC checks (tools/docs/check_docs.py --mode link|toc)

Files:

  • docs/templates/code-review-feedback.md
  • docs/code-reviews/CLAUDE.md
  • docs/code-reviews/PR169/e4f3f906eb454cb103eb8cc6899df8dfbf6e2349.md
🧠 Learnings (22)
📓 Common learnings
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/src/{cache,edge}/*.c : Use `git_oid_cmp()` for OID equality and `git_oid_raw()` when byte-access is required; avoid `memcmp` on OIDs directly
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/include/gitmind/hooks/augment.h : Public hook APIs should use the `gm_hook_` prefix; keep header guard stable to avoid breaking includes

Applied to files:

  • core/include/gitmind/util/ref.h
  • core/src/hooks/post-commit.c
  • core/src/hooks/augment.c
📚 Learning: 2025-09-13T03:13:54.145Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-13T03:13:54.145Z
Learning: Applies to include/gitmind.h : Maintain umbrella API at include/gitmind.h

Applied to files:

  • core/include/gitmind/util/ref.h
  • core/src/hooks/post-commit.c
  • core/include/gitmind/cache.h
  • core/src/cache/builder.c
  • core/src/hooks/augment.c
📚 Learning: 2025-09-15T01:21:16.866Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-15T01:21:16.866Z
Learning: Applies to include/{gitmind.h,gitmind/**/*.h} : Public headers must be umbrella-safe: compile standalone, maintain correct include order, have stable GITMIND_* header guards, and provide extern "C" when included from C++

Applied to files:

  • core/include/gitmind/util/ref.h
  • core/src/hooks/post-commit.c
  • core/src/cache/builder.c
  • core/src/hooks/augment.c
📚 Learning: 2025-09-15T01:21:16.866Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-15T01:21:16.866Z
Learning: Applies to {include,core,src,apps}/**/*.h : Header guards must begin with GITMIND_ and remain stable

Applied to files:

  • core/include/gitmind/util/ref.h
  • core/src/hooks/post-commit.c
  • core/src/cache/builder.c
  • core/src/hooks/augment.c
📚 Learning: 2025-09-13T03:13:54.145Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-13T03:13:54.145Z
Learning: Applies to {include,core/include}/**/*.h : Header guards use GITMIND_* naming

Applied to files:

  • core/include/gitmind/util/ref.h
  • core/src/hooks/post-commit.c
  • core/src/cache/builder.c
  • core/src/hooks/augment.c
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/**/meson.build : Do not hardcode `c_std=c23`; detect compiler support or provide a compatible minimum standard with feature checks

Applied to files:

  • docs/code-reviews/CLAUDE.md
📚 Learning: 2025-09-14T09:27:33.266Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-14T09:27:33.266Z
Learning: NEVER circumvent git hooks

Applied to files:

  • .githooks/pre-push
📚 Learning: 2025-09-13T03:13:54.145Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-13T03:13:54.145Z
Learning: Applies to include/gitmind/**/*.h : Public, namespaced headers live under include/gitmind/

Applied to files:

  • core/src/hooks/post-commit.c
  • core/src/hooks/augment.c
📚 Learning: 2025-09-15T01:21:16.866Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-15T01:21:16.866Z
Learning: Applies to include/gitmind/**/*.h : Place namespaced public headers under include/gitmind/

Applied to files:

  • core/src/hooks/post-commit.c
  • core/src/hooks/augment.c
📚 Learning: 2025-09-13T03:13:54.145Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-13T03:13:54.145Z
Learning: Applies to {core,include}/**/*.{c,h} : Formatting: follow .clang-format (LLVM-based, 4 spaces, 80 cols, pointer alignment right); pre-commit enforces clang-format

Applied to files:

  • core/src/hooks/post-commit.c
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/src/{cache,edge}/*.c : Use `git_oid_cmp()` for OID equality and `git_oid_raw()` when byte-access is required; avoid `memcmp` on OIDs directly

Applied to files:

  • core/include/gitmind/cache.h
  • core/src/cache/builder.c
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/src/cache/*.{c,h} : Maintain consistent OID-centric naming for hash utilities and constants (e.g., `oid_hash()`, `OID_HASH_MULTIPLIER`)

Applied to files:

  • core/include/gitmind/cache.h
  • core/src/cache/builder.c
📚 Learning: 2025-09-15T01:21:16.867Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-15T01:21:16.867Z
Learning: Applies to core/**/*.{c,h} : Prefer OID-first APIs in new core code: use git_oid (typedef gm_oid_t) and compare via git_oid_cmp

Applied to files:

  • core/include/gitmind/cache.h
  • core/src/cache/builder.c
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/include/gitmind/types.h : Define and consistently use the alias `typedef git_oid gm_oid_t` as the canonical OID type

Applied to files:

  • core/include/gitmind/cache.h
  • core/src/cache/builder.c
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/include/gitmind/edge.h : Avoid struct bloat in `gm_edge_t`; do not store both legacy SHA arrays and OIDs long-term—phase out legacy SHA fields

Applied to files:

  • core/include/gitmind/cache.h
  • core/src/cache/builder.c
  • core/src/hooks/augment.c
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/src/journal/reader.c : Split overly long CBOR decoder functions (e.g., `gm_edge_attributed_decode_cbor_ex`) into smaller units for maintainability

Applied to files:

  • core/include/gitmind/cache.h
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/src/journal/*.c : Add strict bounds checking for all CBOR parsing paths (lengths, indices, and buffer limits)

Applied to files:

  • core/src/cache/builder.c
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/src/edge/edge.c : When both OID and SHA are present, validate internal consistency (detect mismatches) rather than silently accepting either

Applied to files:

  • core/src/cache/builder.c
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/src/edge/edge.c : `gm_edge_equal()` must not use OR-style fallback; if OIDs are present use them exclusively, otherwise compare legacy fields—never consider objects equal when OIDs differ

Applied to files:

  • core/src/cache/builder.c
  • core/src/hooks/augment.c
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/**/*.c : Use bounded string functions (e.g., `gm_snprintf`) and ensure explicit NUL termination on all string operations

Applied to files:

  • core/src/cache/builder.c
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/include/gitmind/hooks/augment.h : Remove or timebox deprecated compatibility macros rather than keeping them indefinitely

Applied to files:

  • core/src/hooks/augment.c
🧬 Code graph analysis (5)
core/include/gitmind/util/ref.h (1)
core/src/util/ref.c (1)
  • gm_build_ref (12-54)
core/src/hooks/post-commit.c (1)
core/include/gitmind/security/memory.h (1)
  • gm_memset_safe (47-59)
core/include/gitmind/cache.h (2)
core/src/cache/builder.c (1)
  • gm_cache_rebuild (494-500)
core/src/cache/query.c (5)
  • gm_cache_query_fanout (446-450)
  • gm_cache_query_fanin (453-457)
  • gm_cache_load_meta (97-169)
  • gm_cache_is_stale (172-225)
  • gm_cache_stats (471-516)
core/src/cache/builder.c (3)
core/src/util/ref.c (1)
  • gm_build_ref (12-54)
core/include/gitmind/security/memory.h (1)
  • gm_memset_safe (47-59)
core/include/gitmind/util/memory.h (1)
  • gm_strcpy_safe (113-138)
core/src/hooks/augment.c (1)
core/include/gitmind/util/memory.h (1)
  • gm_strcpy_safe (113-138)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Compat Canaries (non-blocking) (clang-18)
  • GitHub Check: Compat Canaries (non-blocking) (clang-19)
  • GitHub Check: Compat Canaries (non-blocking) (gcc-12)
  • GitHub Check: Compat Canaries (non-blocking) (gcc-13)
  • GitHub Check: lint-and-sanitize
🔇 Additional comments (8)
docs/templates/code-review-feedback.md (1)

1-8: Front matter: quote placeholders; ensure it passes front‑matter checks.

Quote dynamic placeholders to avoid YAML parsing surprises and confirm accepted values for status.

 ---
-title: {filename}
-description: Preserved review artifacts and rationale.
+title: "{filename}"
+description: "Preserved review artifacts and rationale."
 audience: [contributors]
 domain: [quality]
 tags: [review]
 status: archive
 ---

Verification: previous script failed with "check_docs.py: error: unrecognized arguments: --paths". Use positional paths instead — run:

#!/bin/bash
# Front matter + docs checks for this file
python3 tools/docs/check_docs.py --mode link docs/templates/code-review-feedback.md || exit 1
python3 tools/docs/check_docs.py --mode toc  docs/templates/code-review-feedback.md || exit 1
# Lint (scoped if supported), else full:
if make -n md-lint 2>/dev/null | grep -q md-lint; then make md-lint; fi
docs/code-reviews/CLAUDE.md (1)

1-9: Front matter polish: align title with H1 and refresh last_updated

Apply the diff below to docs/code-reviews/CLAUDE.md (lines 1–9). Validation couldn't be completed in the sandbox (make: command not found); re-run the doc lint/ToC/link checks locally or in CI.

---
-title: Code Review Notes
+title: Code Review: migration/finish-core-cleanup Branch
 description: Code review guidelines and context.
 audience: [contributors]
 domain: [quality]
 tags: [review]
 status: archive
-last_updated: 2025-09-15
+last_updated: 2025-09-16
---
core/src/hooks/augment.c (2)

154-158: Good: path truncation now fails.

Checking gm_strcpy_safe and returning GM_ERR_BUFFER_TOO_SMALL is correct.


90-91: Incorrect — LOOKBACK_LIMIT is defined; no action needed.
core/include/gitmind/hooks/augment.h defines GM_AUGMENT_LOOKBACK_LIMIT and aliases LOOKBACK_LIMIT to it (see line 28), so the guard in core/src/hooks/augment.c is valid.

Likely an incorrect or invalid review comment.

core/src/cache/builder.c (2)

496-497: Good input validation.

Returning GM_ERR_INVALID_ARGUMENT for null ctx/repo/branch matches public API contracts.


389-393: Use gm_build_ref for stats too; avoid uninitialized ref_name on error.

Replace manual snprintf with gm_build_ref and short-circuit on failure.

-        char ref_name[REF_NAME_BUFFER_SIZE];
-        {
-            int rn = gm_snprintf(ref_name, sizeof(ref_name), "%s%s", GM_CACHE_REF_PREFIX, branch);
-            if (rn < 0 || (size_t)rn >= sizeof(ref_name)) {
-                /* fall back to estimate below */
-                rc = -1;
-            }
-        }
+        char ref_name[REF_NAME_BUFFER_SIZE];
+        int brc = gm_build_ref(ref_name, sizeof(ref_name), GM_CACHE_REF_PREFIX, branch);
+        if (brc != GM_OK) {
+            rc = -1; /* fall back to estimate */
+        }
 
-        git_oid cache_oid;
-        rc = git_reference_name_to_id(&cache_oid, repo, ref_name);
+        git_oid cache_oid;
+        if (rc == 0) { /* only attempt if ref_name is valid */
+            rc = git_reference_name_to_id(&cache_oid, repo, ref_name);
+        }
⛔ Skipped due to learnings
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/src/{cache,edge}/*.c : Use `git_oid_cmp()` for OID equality and `git_oid_raw()` when byte-access is required; avoid `memcmp` on OIDs directly
core/include/gitmind/cache.h (2)

47-47: Deprecation tag looks good.

Deprecated hex string retained; binary OID added at struct tail preserves ABI.


60-116: NODISCARD usage: LGTM.

Annotating non-void APIs with GM_NODISCARD is appropriate for error-aware callers.

Comment thread .githooks/pre-push
Comment on lines +13 to +24
while read -r local_ref local_sha remote_ref remote_sha; do
# Only enforce for pushes to main
if [[ "$remote_ref" == "refs/heads/main" ]]; then
# Determine the range to inspect
range=""
if [[ "$remote_sha" == "0000000000000000000000000000000000000000" ]]; then
# New branch/update; check last commit only
range="$local_sha^..$local_sha"
else
range="$remote_sha..$local_sha"
fi

ghost Sep 16, 2025

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Skip deletions to main.

If local_sha is all zeros (branch deletion), skip enforcement.

   while read -r local_ref local_sha remote_ref remote_sha; do
     # Only enforce for pushes to main
     if [[ "$remote_ref" == "refs/heads/main" ]]; then
+      # Skip deletions
+      if [[ "$local_sha" == "0000000000000000000000000000000000000000" ]]; then
+        continue
+      fi
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
while read -r local_ref local_sha remote_ref remote_sha; do
# Only enforce for pushes to main
if [[ "$remote_ref" == "refs/heads/main" ]]; then
# Determine the range to inspect
range=""
if [[ "$remote_sha" == "0000000000000000000000000000000000000000" ]]; then
# New branch/update; check last commit only
range="$local_sha^..$local_sha"
else
range="$remote_sha..$local_sha"
fi
while read -r local_ref local_sha remote_ref remote_sha; do
# Only enforce for pushes to main
if [[ "$remote_ref" == "refs/heads/main" ]]; then
# Skip deletions
if [[ "$local_sha" == "0000000000000000000000000000000000000000" ]]; then
continue
fi
# Determine the range to inspect
range=""
if [[ "$remote_sha" == "0000000000000000000000000000000000000000" ]]; then
# New branch/update; check last commit only
range="$local_sha^..$local_sha"
else
range="$remote_sha..$local_sha"
fi
🤖 Prompt for AI Agents
.githooks/pre-push around lines 13 to 24: the hook treats a local_sha of all
zeros (branch deletion) as a new-branch case and proceeds to enforce checks
against main; detect when local_sha equals
0000000000000000000000000000000000000000 and skip enforcement by continuing the
loop (i.e., do not set a range or run checks for deletions to main), leaving
other logic unchanged.

Comment thread .githooks/pre-push
Comment on lines +18 to +23
# New branch/update; check last commit only
range="$local_sha^..$local_sha"
else
range="$remote_sha..$local_sha"
fi

ghost Sep 16, 2025

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

New-branch range: handle root commits safely.

Use diff-tree on the new commit instead of local^..local to avoid failures on root commits.

-      range="$local_sha^..$local_sha"
+      range="$local_sha"
+      changelog_names="$(git diff-tree --no-commit-id --name-only -r "$local_sha")"
+    else
+      range="$remote_sha..$local_sha"
+      changelog_names="$(git diff --name-only "$range")"
-    else
-      range="$remote_sha..$local_sha"
-    fi
+    fi

Then test changelog_names instead of invoking git diff twice.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if [[ "$remote_sha" == "0000000000000000000000000000000000000000" ]]; then
# New branch/update; check last commit only
range="$local_sha^..$local_sha"
else
range="$remote_sha..$local_sha"
fi
if [[ "$remote_sha" == "0000000000000000000000000000000000000000" ]]; then
# New branch/update; check last commit only
range="$local_sha"
changelog_names="$(git diff-tree --no-commit-id --name-only -r "$local_sha")"
else
range="$remote_sha..$local_sha"
changelog_names="$(git diff --name-only "$range")"
fi
🤖 Prompt for AI Agents
In .githooks/pre-push around lines 18-23, the new-branch handling uses
"$local_sha^..$local_sha" which breaks for root commits and the script currently
invokes git diff twice; replace the new-branch range logic to obtain changed
files from the single new commit using git diff-tree (or equivalent
single-commit name-only listing) for "$local_sha" instead of using the caret
range, and then use that single result (changelog_names) for subsequent checks
rather than calling git diff a second time; ensure the existing-branch path
still uses the remote..local diff to populate changelog_names.

Comment thread .githooks/pre-push
Comment on lines +26 to +33
if ! git diff --name-only "$range" | grep -iqE '(^|.*/)(CHANGELOG|CHANGES)(\.md)?$'; then
echo "[pre-push] No changelog file updated for push to main ($range)." >&2
echo " Expected one of: CHANGELOG.md, CHANGES.md, or variants (case-insensitive)." >&2
echo " Run: make changelog-add m=\"<one-liner>\"" >&2
echo " Or bypass once: HOOKS_BYPASS=1 git push" >&2
status=1
fi
fi

ghost Sep 16, 2025

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick

Handle filenames with newlines; reuse computed names.

Use the already captured changelog_names and avoid a second git call; optionally use -z and map to newline if you later need robustness.

-    if ! git diff --name-only "$range" | grep -iqE '(^|.*/)(CHANGELOG|CHANGES)(\.md)?$'; then
+    if ! printf '%s\n' "$changelog_names" | grep -iqE '(^|.*/)?(CHANGELOG|CHANGES)(\.md)?$'; then
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# Match common variants: CHANGELOG, CHANGES, with optional .md, case-insensitive, with or without paths
if ! git diff --name-only "$range" | grep -iqE '(^|.*/)(CHANGELOG|CHANGES)(\.md)?$'; then
echo "[pre-push] No changelog file updated for push to main ($range)." >&2
echo " Expected one of: CHANGELOG.md, CHANGES.md, or variants (case-insensitive)." >&2
echo " Run: make changelog-add m=\"<one-liner>\"" >&2
echo " Or bypass once: HOOKS_BYPASS=1 git push" >&2
status=1
fi
# Match common variants: CHANGELOG, CHANGES, with optional .md, case-insensitive, with or without paths
if ! printf '%s\n' "$changelog_names" | grep -iqE '(^|.*/)?(CHANGELOG|CHANGES)(\.md)?$'; then
echo "[pre-push] No changelog file updated for push to main ($range)." >&2
echo " Expected one of: CHANGELOG.md, CHANGES.md, or variants (case-insensitive)." >&2
echo " Run: make changelog-add m=\"<one-liner>\"" >&2
echo " Or bypass once: HOOKS_BYPASS=1 git push" >&2
status=1
fi
🤖 Prompt for AI Agents
.githooks/pre-push lines 26-33: the script is making a second git call and can
mis-handle filenames with newlines; reuse the already-captured changelog_names
variable instead of calling git diff again, and perform matching in a NUL-safe
way by using the NUL-separated names (git diff --name-only -z) or by printing
changelog_names with printf '%s\n' to feed grep; then run grep with the
appropriate flags (-z for NUL-separated input or regular grep for
newline-separated) and the same regex, set status=1 when no match, and avoid
invoking git twice.

Comment on lines +52 to 54
char branch[GM_CACHE_BRANCH_NAME_SIZE]; /**< Branch name (may be truncated if too long) */
gm_oid_t journal_tip_oid_bin; /**< OID of last processed journal commit (preferred). Added at struct tail to preserve ABI layout. */
} gm_cache_meta_t;

ghost Sep 16, 2025

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick

Branch field doc inconsistent with implementation.

Builder rejects long branch names; update comment to reflect “reject on overflow” instead of “may be truncated”.

-    char branch[GM_CACHE_BRANCH_NAME_SIZE];           /**< Branch name (may be truncated if too long) */
+    char branch[GM_CACHE_BRANCH_NAME_SIZE];           /**< Branch name (rejected if >= limit; no truncation) */
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
char branch[GM_CACHE_BRANCH_NAME_SIZE]; /**< Branch name (may be truncated if too long) */
gm_oid_t journal_tip_oid_bin; /**< OID of last processed journal commit (preferred). Added at struct tail to preserve ABI layout. */
} gm_cache_meta_t;
char branch[GM_CACHE_BRANCH_NAME_SIZE]; /**< Branch name (rejected if >= limit; no truncation) */
gm_oid_t journal_tip_oid_bin; /**< OID of last processed journal commit (preferred). Added at struct tail to preserve ABI layout. */
} gm_cache_meta_t;
🤖 Prompt for AI Agents
In core/include/gitmind/cache.h around lines 52 to 54, the branch field comment
incorrectly says the branch "may be truncated if too long" while the
implementation/builder rejects names that overflow; update the comment to state
that branch names exceeding GM_CACHE_BRANCH_NAME_SIZE are rejected/causes an
error (no truncation) and reflect the actual behavior (e.g., "Branch name; names
longer than GM_CACHE_BRANCH_NAME_SIZE are rejected/validation fails") so the doc
matches implementation and ABI expectations.

Comment on lines +17 to +19
* Validation uses libgit2's git_reference_normalize_name on the combined ref.
* Returns GM_OK or error code.
*/

ghost Sep 16, 2025

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick

Doc mismatch with implementation (libgit2 normalization).

Header says validation uses git_reference_normalize_name, but implementation performs minimal local checks. Align the comment or update implementation.

- * Validation uses libgit2's git_reference_normalize_name on the combined ref.
+ * Validation performs minimal local checks; callers must treat return!=GM_OK
+ * as invalid and may optionally perform libgit2 normalization/lookup.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
* Validation uses libgit2's git_reference_normalize_name on the combined ref.
* Returns GM_OK or error code.
*/
* Validation performs minimal local checks; callers must treat return!=GM_OK
* as invalid and may optionally perform libgit2 normalization/lookup.
* Returns GM_OK or error code.
*/
🤖 Prompt for AI Agents
core/include/gitmind/util/ref.h lines 17-19: the header claims validation uses
libgit2's git_reference_normalize_name but the implementation only does minimal
local checks; either update the comment to accurately describe the current
local-check behavior or change the implementation to call
git_reference_normalize_name on the combined ref and propagate libgit2 errors.
If you change the implementation, include the libgit2 header, build the combined
ref string as the comment describes, call git_reference_normalize_name, handle
NULL/err returns and translate them into the function's error codes, and add
unit tests; if you change the comment, rewrite the docstring to state that only
simple/local validation is performed and remove the reference to
git_reference_normalize_name.

Comment thread docs/templates/code-review-feedback.md
Comment thread docs/templates/code-review-feedback.md Outdated
Comment thread docs/templates/code-review-feedback.md
Comment thread docs/templates/code-review-feedback.md Outdated
Comment thread docs/templates/code-review-feedback.md Outdated
J. Kirby Ross added 3 commits September 16, 2025 05:03
…gets; add title/H1 checker; add manual workflow to seed review docs

ghost left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (6)
docs/legacy/src/attribution.md (6)

11-14: Add a clear legacy disclaimer and pointer to current doc

Since this page is archived, add a short callout to steer readers to the current architecture doc. This also respects the Obsidian callout preference.

 # Attribution System
+
+> [!WARNING]-
+> Legacy/archived notes. Concepts here may differ from the current implementation.
+> See: docs/architecture/attribution-system.md for up‑to‑date design and APIs.

34-44: Mark enum as legacy and cross‑reference unified constants

Constants were centralized in include/gitmind/constants.h. Flag this as a legacy sketch and link to the canonical header to avoid drift.

-```c
+```c
+/* Legacy sketch; see include/gitmind/constants.h for authoritative values/names */
 typedef enum {
     GM_SOURCE_HUMAN        = 0,    /* Human-created edge */
     GM_SOURCE_AI_CLAUDE    = 1,    /* Claude AI via MCP */
     GM_SOURCE_AI_GPT      = 2,    /* GPT-4 or similar */
     GM_SOURCE_AI_OTHER    = 3,    /* Other AI systems */
     GM_SOURCE_SYSTEM      = 4,    /* System-generated (e.g., AUGMENTS) */
     GM_SOURCE_IMPORT      = 5,    /* Imported from external source */
     GM_SOURCE_UNKNOWN     = 255   /* Unknown source */
 } gm_source_type_t;

Please also confirm enum names match current code (post “constants unification”).

---

`56-62`: **Lane identifiers: verify against unified public constants**

Ensure GM_LANE_* names reflect those in include/gitmind/constants.h after the unification; otherwise add a mapping note here.

---

`92-102`: **Fenced block language + schema note**

- Add a language to satisfy markdownlint fenced-code-language.
- Consider noting the schema version and pointing to include/gitmind/cbor/constants_cbor.h.


```diff
-```
+```text
 [
   source_sha, tgt_sha, rel_type, confidence, timestamp,
   src_path, tgt_path, ulid,
   source_type, author, session_id, flags, lane  // New fields
 ]

+Note: See include/gitmind/cbor/constants_cbor.h for field keys and schema/versioning.


---

`104-109`: **Env var naming inconsistent with repo convention**

Elsewhere docs use GITMIND_* (e.g., GITMIND_CI_IMAGE). Here it’s GIT_MIND_*. Unify to avoid confusion, or explicitly document both if the code supports aliases.


```diff
-- `GIT_MIND_SOURCE`: Set source type (human, claude, gpt, system)
-- `GIT_MIND_AUTHOR`: Override author identification
-- `GIT_MIND_SESSION`: Group edges in same session
+- `GITMIND_SOURCE`: Set source type (human, claude, gpt, system)
+- `GITMIND_AUTHOR`: Override author identification
+- `GITMIND_SESSION`: Group edges in same session

If the code truly expects GIT_MIND_*, flip the diff accordingly and add a note in Environment_Variables.md.


110-121: Clarify accepted values/case and use neutral example

Document the accepted values and case-sensitivity for the SOURCE var and avoid vendor-specific addresses in examples.

-```bash
-export GIT_MIND_SOURCE=claude
-export GIT_MIND_AUTHOR=claude@anthropic
-export GIT_MIND_SESSION=conv_abc123
-```
+```bash
+# Accepted values: human | claude | gpt | system | other  (case-insensitive? verify)
+export GITMIND_SOURCE=claude
+export GITMIND_AUTHOR=agent@example.com
+export GITMIND_SESSION=conv_abc123
+```

If aliases (e.g., GIT_MIND_* vs GITMIND_*) are supported, mention both explicitly.

📜 Review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8b603ef and 2e11fb1.

📒 Files selected for processing (6)
  • docs/architecture/attribution-system.md (2 hunks)
  • docs/features/Features_Ledger.md (1 hunks)
  • docs/legacy/src/attribution.md (1 hunks)
  • docs/legacy/src/edge.md (1 hunks)
  • docs/legacy/src/sha.md (1 hunks)
  • src/.gitignore (0 hunks)
💤 Files with no reviewable changes (1)
  • src/.gitignore
✅ Files skipped from review due to trivial changes (2)
  • docs/legacy/src/edge.md
  • docs/legacy/src/sha.md
🚧 Files skipped from review as they are similar to previous changes (2)
  • docs/architecture/attribution-system.md
  • docs/features/Features_Ledger.md
🧰 Additional context used
📓 Path-based instructions (2)
**/*.md

📄 CodeRabbit inference engine (AGENTS.md)

Comply with repository markdown lint rules (.markdownlint.jsonc); use make md-lint / make md-fix

Files:

  • docs/legacy/src/attribution.md
docs/**/*.md

📄 CodeRabbit inference engine (AGENTS.md)

Docs must pass link and TOC checks (tools/docs/check_docs.py --mode link|toc)

Files:

  • docs/legacy/src/attribution.md
🧠 Learnings (1)
📓 Common learnings
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-13T03:13:54.145Z
Learning: Run build, tests, clang-tidy (via tools/docker-clang-tidy.sh), and gauntlet locally before proposing changes; keep changes zero-warnings and formatted
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/src/**/*.c : Normalize error handling to a single scheme (prefer `GM_OK`/`GM_ERR_*`) and avoid mixing raw libgit2 error codes
Learnt from: flyingrobots
PR: neuroglyph/git-mind#169
File: docs/templates/code-review-feedback.md:26-33
Timestamp: 2025-09-16T17:10:27.450Z
Learning: The user (flyingrobots) uses Obsidian to view/edit Markdown files and prefers to keep Obsidian-specific syntax like collapsible callout markers (e.g., `[!NOTE]-` for collapsible callouts) even if they're not GitHub-compatible.
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Compat Canaries (non-blocking) (gcc-12)
  • GitHub Check: Compat Canaries (non-blocking) (clang-19)
  • GitHub Check: Compat Canaries (non-blocking) (clang-18)
  • GitHub Check: Compat Canaries (non-blocking) (gcc-13)
🔇 Additional comments (1)
docs/legacy/src/attribution.md (1)

1-9: Verify front-matter keys with docs checker

Sandbox run failed (make not found); checks couldn't be executed. Run locally and confirm that status: archive (vs. archived) and the audience/domain arrays are accepted by tools/docs/check_docs.py.

Run locally:

  • make md-lint
  • python3 tools/docs/check_docs.py --mode link
  • python3 tools/docs/check_docs.py --mode toc
  • rg -n '^(status|audience|domain):' -C1 docs/ | sed -n '1,200p'

File: docs/legacy/src/attribution.md (lines 1-9)

ghost left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
docs/architecture/MODULAR_RESTRUCTURE_PLAN.md (1)

17-21: Fix TOC entries/anchors to match actual headings (will fail docs TOC check).

Current TOC lists Goals/Plan/Milestones/Compatibility, which don’t exist. Replace with the real section headings.

Apply:

- - [Executive Summary](#executive-summary)
- - [Goals](#goals)
- - [Plan](#plan)
- - [Milestones](#milestones)
- - [Compatibility](#compatibility)
+ - [Executive Summary](#executive-summary)
+ - [Current Problems](#current-problems)
+ - [Proposed Architecture](#proposed-architecture)
+ - [Core Library Design](#core-library-design)
+ - [Migration Strategy ("3 Birds, 1 Stone")](#migration-strategy-3-birds-1-stone)
+ - [Quality Enforcement](#quality-enforcement)
+ - [File-by-File Migration Example](#file-by-file-migration-example)
+ - [Success Metrics](#success-metrics)
+ - [Backwards Compatibility](#backwards-compatibility)
+ - [Open Questions](#open-questions)
+ - [Next Steps](#next-steps)
♻️ Duplicate comments (1)
docs/cli/combined_markdown.md (1)

9-9: Aggregate flag present — thanks for closing the loop.

This addresses the earlier suggestion to mark compiled pages.

🧹 Nitpick comments (16)
docs/tutorial.md (1)

44-46: Minor: separate command from output for readability.

Use distinct fenced blocks (bash vs text) so linters and renderers don’t colorize output as shell.

-```bash
-$ "$GIT_MIND" list --from README.md
-README.md -> core/src/main.c (documents)
-```
+```bash
+$ "$GIT_MIND" list --from README.md
+```
+```text
+README.md -> core/src/main.c (documents)
+```
docs/architecture/MODULAR_RESTRUCTURE_PLAN.md (6)

65-75: Fix directory tree: avoid “core/src” under “core/”; move public header under top-level include/.

Aligns with repo convention: public headers in include/gitmind/ (umbrella include/gitmind.h), sources in core/src.

Apply:

-│   ├── include/
-│   │   └── gitmind.h         # THE single header (amalgamated)
-│   ├── core/src/             # Source files (post-migration)
+│   ├── src/                  # Source files (post-migration)
@@
-│       └── amalgamate.py     # Combines sources into single header
+│       └── amalgamate.py     # Combines sources into single header
+│
+├── include/
+│   └── gitmind.h             # THE single header (amalgamated)

112-126: Single-header snippet: add extern "C" for C++ and avoid repo-internal .c paths.

Use extern "C" in public headers and reference src/ paths to match the corrected tree (or note that amalgamation inlines sources).

Apply:

 /* gitmind.h - Single header git-mind library */
 #ifndef GITMIND_H
 #define GITMIND_H
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #ifdef GITMIND_IMPLEMENTATION
   /* Implementation details */
-  #include "core/src/edge/edge.c"
-  #include "core/src/cbor/cbor.c"
+  /* In amalgamated builds these are inlined; paths shown for clarity */
+  #include "src/edge/edge.c"
+  #include "src/cbor/cbor.c"
   /* ... */
 #else
   /* Public API only */
   /* ... declarations ... */
 #endif
-
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
 #endif /* GITMIND_H */

96-96: Remove trailing spaces (markdownlint MD009).

“- CBOR encoding/decoding␠␠” has two trailing spaces; they render as a hard line break.

-- CBOR encoding/decoding  
+- CBOR encoding/decoding

186-189: “Before Migration” path should reflect pre-move location.

Use src/edge/edge.c (before), not core/src/edge/edge.c.

-// core/src/edge/edge.c
+// src/edge/edge.c

3-11: Front matter looks good; consider adding a stable slug for link stability.

Optional: add slug to avoid title‑derived anchor drift.

 last_updated: 2025-09-15
 ---
+slug: modular-architecture-restructure-plan

232-245: Backwards-compat note: include path guidance should match umbrella include.

Consider showing include <gitmind.h> explicitly to reinforce the new public API.

-- Old `#include "gitmind/*.h"` → `#include "gitmind.h"`
+- Old `#include "gitmind/*.h"` → `#include <gitmind.h>`
docs/wish-list-features/brain-storms/CLAUDE_ULTRATHINKS_GITMIND_FUTURE.md (3)

790-797: Swap real Ethereum address for a neutral placeholder in examples.

Using a well-known live address can distract or imply endorsement. Prefer a dummy zero-address or clearly fake value.

-gm_contract_t *contract = gm_blockchain_connect(
-    "ethereum",
-    "0x742d35Cc6634C0532925a3b844Bc8e70387bEaE"
-);
+gm_contract_t *contract = gm_blockchain_connect(
+    "ethereum",
+    "0x0000000000000000000000000000000000000000" /* placeholder */
+);

1750-1791: Tone tweak for public docs (optional).

If this file is user-facing, consider softening the final tagline to meet broad comms guidelines and markdown linters that flag profanity in headings/strong emphases.

-__LET'S MAKE GIT-MIND FUCKING LEGENDARY! 🚀__
+__LET'S MAKE GIT-MIND ABSOLUTELY LEGENDARY! 🚀__

49-56: Use OID-first gm_oid_t in docs example

Replace the SHA-specific gm_sha1_t/commit_sha with gm_oid_t/commit_oid to align with the repo's OID-first policy (occurrence: docs/wish-list-features/brain-storms/CLAUDE_ULTRATHINKS_GITMIND_FUTURE.md: line 51).

-    gm_sha1_t commit_sha;
+    gm_oid_t commit_oid;
docs/cli/combined_markdown.md (3)

321-324: Normalize the “AUGMENTS” relation casing or document case-sensitivity.

Examples mix AUGMENTS (upper) and augments (lower). If the CLI is case-sensitive, standardize and state the convention; if it’s case-insensitive, note that too to avoid user confusion.

Also applies to: 642-644, 1017-1020


1099-1103: Note: example uses Bash process substitution.

Readers on shells without process substitution may be confused. Add a one-liner note above the snippet.

 ### Test Coverage Discovery
 ```bash
-# What files lack tests?
+# What files lack tests?
+# Note: requires Bash (process substitution).
 $ comm -23 \
     <(git ls-files core/src/ | sort) \
     <(git mind list --type tests --format tsv | cut -f2 | sort)

---

`137-147`: **Cross-link ref naming/validation doc where refs are introduced.**

When mentioning refs/gitmind/edges/<branch>, add a short parenthetical link to docs/architecture/Ref_Name_Validation.md for discoverability.

</blockquote></details>
<details>
<summary>apps/cli/list.md (1)</summary><blockquote>

`112-116`: **Globbing example: quoted pattern won’t expand in most shells**

If the CLI expects the shell to expand globs, drop the quotes; if the CLI implements its own globbing, add a note saying quotes are intentional.

```diff
-git-mind list "core/src/*.c"
+git-mind list core/src/*.c
+# If tool does its own globbing, keep quotes and add:
+# (Pattern is parsed by git-mind; quotes prevent shell expansion.)
docs/cli/gitmind-link.md (1)

10-10: Optional: bump last_updated to today if you touch the file again.

If you apply the front‑matter move, consider updating last_updated to 2025-09-18.

docs/cli/gitmind-list.md (1)

8-8: Optional: refresh last_updated if more edits land.

Consider setting last_updated to 2025-09-18 on next content change.

📜 Review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2e11fb1 and b39e24f.

📒 Files selected for processing (20)
  • README.md (10 hunks)
  • apps/cli/list.md (5 hunks)
  • docs/PRDs/PRD-co-thought-mcp-service.md (2 hunks)
  • docs/TECHNICAL.md.md (1 hunks)
  • docs/adult_swim.md (2 hunks)
  • docs/api/gitmind-api-reference.md (3 hunks)
  • docs/architecture/MODULAR_RESTRUCTURE_PLAN.md (4 hunks)
  • docs/cli/combined_markdown.md (21 hunks)
  • docs/cli/gitmind-cache-rebuild.md (3 hunks)
  • docs/cli/gitmind-install-hooks.md (2 hunks)
  • docs/cli/gitmind-link.md (6 hunks)
  • docs/cli/gitmind-list.md (10 hunks)
  • docs/cli/gitmind.md (4 hunks)
  • docs/enforcer/gameplans/05-config-convention-overhaul.md (2 hunks)
  • docs/enforcer/gameplans/09-domain-language-purity.md (3 hunks)
  • docs/features/Features_Ledger.md (1 hunks)
  • docs/quality/static-analysis-guide.md (2 hunks)
  • docs/talk-shop/Graph-Lvl-Up-Tank.md (1 hunks)
  • docs/tutorial.md (2 hunks)
  • docs/wish-list-features/brain-storms/CLAUDE_ULTRATHINKS_GITMIND_FUTURE.md (1 hunks)
✅ Files skipped from review due to trivial changes (3)
  • docs/TECHNICAL.md.md
  • docs/api/gitmind-api-reference.md
  • docs/adult_swim.md
🚧 Files skipped from review as they are similar to previous changes (10)
  • docs/cli/gitmind-install-hooks.md
  • docs/talk-shop/Graph-Lvl-Up-Tank.md
  • docs/enforcer/gameplans/05-config-convention-overhaul.md
  • docs/quality/static-analysis-guide.md
  • docs/features/Features_Ledger.md
  • docs/PRDs/PRD-co-thought-mcp-service.md
  • docs/cli/gitmind.md
  • docs/enforcer/gameplans/09-domain-language-purity.md
  • docs/cli/gitmind-cache-rebuild.md
  • README.md
🧰 Additional context used
📓 Path-based instructions (2)
**/*.md

📄 CodeRabbit inference engine (AGENTS.md)

Comply with repository markdown lint rules (.markdownlint.jsonc); use make md-lint / make md-fix

Files:

  • docs/tutorial.md
  • docs/wish-list-features/brain-storms/CLAUDE_ULTRATHINKS_GITMIND_FUTURE.md
  • apps/cli/list.md
  • docs/cli/gitmind-list.md
  • docs/cli/combined_markdown.md
  • docs/architecture/MODULAR_RESTRUCTURE_PLAN.md
  • docs/cli/gitmind-link.md
docs/**/*.md

📄 CodeRabbit inference engine (AGENTS.md)

Docs must pass link and TOC checks (tools/docs/check_docs.py --mode link|toc)

Files:

  • docs/tutorial.md
  • docs/wish-list-features/brain-storms/CLAUDE_ULTRATHINKS_GITMIND_FUTURE.md
  • docs/cli/gitmind-list.md
  • docs/cli/combined_markdown.md
  • docs/architecture/MODULAR_RESTRUCTURE_PLAN.md
  • docs/cli/gitmind-link.md
🧠 Learnings (10)
📓 Common learnings
Learnt from: flyingrobots
PR: neuroglyph/git-mind#169
File: docs/templates/code-review-feedback.md:26-33
Timestamp: 2025-09-16T17:10:27.450Z
Learning: The user (flyingrobots) uses Obsidian to view/edit Markdown files and prefers to keep Obsidian-specific syntax like collapsible callout markers (e.g., `[!NOTE]-` for collapsible callouts) even if they're not GitHub-compatible.
📚 Learning: 2025-09-13T03:13:54.145Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-13T03:13:54.145Z
Learning: Applies to include/gitmind.h : Maintain umbrella API at include/gitmind.h

Applied to files:

  • apps/cli/list.md
  • docs/cli/gitmind-list.md
  • docs/cli/combined_markdown.md
  • docs/architecture/MODULAR_RESTRUCTURE_PLAN.md
📚 Learning: 2025-09-14T09:27:33.266Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-14T09:27:33.266Z
Learning: Tag all memories saved to MEMORY BANKS with at least #git-mind

Applied to files:

  • docs/cli/gitmind-list.md
📚 Learning: 2025-09-15T01:21:16.866Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-15T01:21:16.866Z
Learning: Applies to {include,core,src,apps}/**/*.h : Header guards must begin with GITMIND_ and remain stable

Applied to files:

  • docs/cli/gitmind-list.md
  • docs/cli/combined_markdown.md
  • docs/architecture/MODULAR_RESTRUCTURE_PLAN.md
📚 Learning: 2025-09-13T03:13:54.145Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-13T03:13:54.145Z
Learning: Applies to {include,core/include}/**/*.h : Header guards use GITMIND_* naming

Applied to files:

  • docs/cli/gitmind-list.md
  • docs/cli/combined_markdown.md
  • docs/architecture/MODULAR_RESTRUCTURE_PLAN.md
📚 Learning: 2025-09-15T01:21:16.866Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-15T01:21:16.866Z
Learning: Applies to include/{gitmind.h,gitmind/**/*.h} : Public headers must be umbrella-safe: compile standalone, maintain correct include order, have stable GITMIND_* header guards, and provide extern "C" when included from C++

Applied to files:

  • docs/cli/gitmind-list.md
  • docs/cli/combined_markdown.md
  • docs/architecture/MODULAR_RESTRUCTURE_PLAN.md
📚 Learning: 2025-09-13T03:13:54.145Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-13T03:13:54.145Z
Learning: Applies to include/gitmind/**/*.h : Public, namespaced headers live under include/gitmind/

Applied to files:

  • docs/architecture/MODULAR_RESTRUCTURE_PLAN.md
📚 Learning: 2025-09-15T01:21:16.866Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-15T01:21:16.866Z
Learning: Applies to core/** : Add new code under core/ (C23 library: include/ for public headers, src/ for implementation, tests/ for unit tests)

Applied to files:

  • docs/architecture/MODULAR_RESTRUCTURE_PLAN.md
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/include/gitmind/edge.h : Avoid struct bloat in `gm_edge_t`; do not store both legacy SHA arrays and OIDs long-term—phase out legacy SHA fields

Applied to files:

  • docs/architecture/MODULAR_RESTRUCTURE_PLAN.md
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/src/edge/edge.c : `gm_edge_equal()` must not use OR-style fallback; if OIDs are present use them exclusively, otherwise compare legacy fields—never consider objects equal when OIDs differ

Applied to files:

  • docs/architecture/MODULAR_RESTRUCTURE_PLAN.md
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Compat Canaries (non-blocking) (gcc-13)
🔇 Additional comments (8)
docs/tutorial.md (1)

33-35: Confirm 'documents' link type and example target existence

  • Path update in docs/tutorial.md (example "Created: README.md -[documents]-> core/src/main.c") is fine.
  • docs/cli/gitmind-link.md contains no reference to "documents" — confirm "documents" is a supported --type value and update the CLI docs if it is.
  • core/src/main.c is not present in this checkout — ensure the example points to an in-repo file or clarify it's a built/generated path.
docs/architecture/MODULAR_RESTRUCTURE_PLAN.md (1)

15-21: Run docs TOC & link checks (use positional file args).

check_docs.py takes file path(s) as positional args (not --files); CI may lack make — run:
python3 tools/docs/check_docs.py --mode toc docs/architecture/MODULAR_RESTRUCTURE_PLAN.md
python3 tools/docs/check_docs.py --mode link docs/architecture/MODULAR_RESTRUCTURE_PLAN.md

docs/cli/combined_markdown.md (1)

1-10: Front matter now precedes SPDX header — add license metadata and verify scanners.

YAML front matter is fine, but some license scanners expect SPDX/license metadata at the top; add explicit fields and confirm scanner behavior.

File: docs/cli/combined_markdown.md (lines 1–10)

Apply this diff to enrich front matter (keeps HTML comments too):

 ---
 title: README.md
 description: Combined CLI reference content for convenience and offline browsing.
 audience: [users, developers]
 domain: [cli]
 tags: [cli]
 status: draft
 last_updated: 2025-09-15
 aggregate: true
+license: LicenseRef-MIND-UCAL-1.0
+copyright: "© 2025 J. Kirby Ross / Neuroglyph Collective"
 ---

Validation — I attempted to run the suggested checks but the sandbox failed with: "/bin/bash: line 3: make: command not found". Re-run these locally/CI and paste output if you want me to re-verify:

make md-lint
python3 tools/docs/check_docs.py --mode link --paths docs/cli/combined_markdown.md
python3 tools/docs/check_docs.py --mode toc  --paths docs/cli/combined_markdown.md
rg -nP '(?<!core/)src/' docs/cli/combined_markdown.md || true
apps/cli/list.md (2)

332-332: LGTM: path migration reflected in stats example

The switch to core/src/main.c is consistent with the rest of this doc.


210-211: Propagate include path fix across examples

Replace occurrences of include/api.h with the public umbrella header include/gitmind.h. Do not blindly replace include/parser.h with include/gitmind/parser.h — include/gitmind/parser.h is not present in this branch; either use include/gitmind.h or add the correct public parser header.

Affected locations: apps/cli/list.md (lines 40, 210, 217, 220, 224, 233–234, 339), docs/legacy/src/edge.md:175.

-IMPLEMENTS: core/src/main.c -> include/api.h
+IMPLEMENTS: core/src/main.c -> include/gitmind.h
-{"type":"implements","src":"core/src/main.c","tgt":"include/api.h",...}
+{"type":"implements","src":"core/src/main.c","tgt":"include/gitmind.h",...}
-implements,core/src/main.c,include/api.h,1.0,1720000000000
+implements,core/src/main.c,include/gitmind.h,1.0,1720000000000
-  "core/src/main.c" -> "include/api.h" [label="implements"];
+  "core/src/main.c" -> "include/gitmind.h" [label="implements"];
-  core/src/main.c -> include/api.h
+  core/src/main.c -> include/gitmind.h
docs/cli/gitmind-list.md (2)

58-62: core/src path migration looks good across examples.

The updated examples are coherent and match the repo-wide move.

Also applies to: 127-131, 138-152, 160-171, 178-199, 205-207, 230-233, 303-314, 330-330


1-9: Approve — front matter placement correct; docs checks passed.
check_frontmatter.py (--base docs) and check_docs.py (link, toc) on docs/cli/gitmind-list.md returned OK.

docs/cli/gitmind-link.md (1)

47-49: Approve — path updates to core/src are consistent.
Examples were uniformly migrated from src/... to core/src/...; verified 20 occurrences in docs/cli/gitmind-link.md (lines 47–49, 90–97, 103–113, 119–122, 128–130, 135–137, 170–172, 215–219, 240–241).

Comment thread apps/cli/list.md
Comment on lines +40 to 43
IMPLEMENTS: core/src/main.c -> include/api.h
REFERENCES: README.md -> docs/design.md
DEPENDS_ON: Makefile -> src/main.c
DEPENDS_ON: Makefile -> core/src/main.c

ghost Sep 18, 2025

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

🧩 Analysis chain

Align include path with public headers layout

Examples still show include/api.h. Public headers live under include/gitmind/. Update example to avoid confusing users.

Apply:

-IMPLEMENTS: core/src/main.c -> include/api.h
+IMPLEMENTS: core/src/main.c -> include/gitmind.h

🏁 Script executed:

#!/bin/bash
# Verify which public headers actually exist
fd -HI -t f '^api\.h$' include | sed 's/^/FOUND api.h: /' || true
fd -HI -t f '^gitmind\.h$' include | sed 's/^/FOUND gitmind.h: /' || true

Length of output: 34


Align include path with public headers layout

Examples still show include/api.h. Public headers live under include/gitmind/ — update example to avoid confusing users.

Apply:

-IMPLEMENTS: core/src/main.c -> include/api.h
+IMPLEMENTS: core/src/main.c -> include/gitmind.h
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
IMPLEMENTS: core/src/main.c -> include/api.h
REFERENCES: README.md -> docs/design.md
DEPENDS_ON: Makefile -> src/main.c
DEPENDS_ON: Makefile -> core/src/main.c
IMPLEMENTS: core/src/main.c -> include/gitmind.h
REFERENCES: README.md -> docs/design.md
DEPENDS_ON: Makefile -> core/src/main.c
🤖 Prompt for AI Agents
In apps/cli/list.md around lines 40 to 43, the example includes reference to
include/api.h which is incorrect given public headers live under
include/gitmind/; update the example lines to use the proper public header path
(e.g., include/gitmind/api.h) and scan the surrounding example block for any
other occurrences of include/api.h and replace them accordingly so documentation
matches the public headers layout.

Comment on lines +178 to 180
$ git mind link core/src/parser.c docs/parsing.md --type implements
$ git mind link core/src/lexer.c core/src/parser.c --type feeds
$ git mind cache-rebuild

ghost Sep 18, 2025

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

🧩 Analysis chain

Path/ref alignment and CLI examples look consistent. Please run doc checks.

All updated paths use core/src and refs/gitmind/..., matching PR objectives.

Use this focused check to catch any stragglers and broken anchors:

Also applies to: 192-192, 476-478, 550-552, 594-600, 606-616, 621-625, 632-640, 718-722, 743-743, 846-850, 915-918, 926-930, 935-940, 949-951, 956-959, 966-970, 975-978, 984-987, 993-995, 1090-1090, 1101-1102, 1118-1118, 1291-1297, 1300-1302, 1308-1317, 1334-1336, 1347-1347


🏁 Script executed:

#!/bin/bash
set -euo pipefail
# Link + ToC checks (repository script)
python3 tools/docs/check_docs.py --mode link --paths docs/cli/combined_markdown.md
python3 tools/docs/check_docs.py --mode toc  --paths docs/cli/combined_markdown.md

# Ensure examples consistently use 'git mind ' (space) form
rg -nP 'git-mind\s' docs/cli/combined_markdown.md || true

Length of output: 109


🏁 Script executed:

#!/bin/bash
set -uo pipefail
echo "=== Running docs/link check ==="
python3 tools/docs/check_docs.py --mode link docs/cli/combined_markdown.md || echo "check_docs.py --mode link exited with $?"
echo "=== Running docs/toc check ==="
python3 tools/docs/check_docs.py --mode toc docs/cli/combined_markdown.md || echo "check_docs.py --mode toc exited with $?"
echo "=== Searching for hyphenated 'git-mind' occurrences ==="
rg -nP 'git-mind\s' docs/cli/combined_markdown.md || echo "no 'git-mind ' matches"
echo "=== Searching for spaced 'git mind' occurrences ==="
rg -nP 'git mind\s' docs/cli/combined_markdown.md || echo "no 'git mind ' matches"
echo "=== Searching for 'core/src' occurrences ==="
rg -n 'core/src' docs/cli/combined_markdown.md || echo "no 'core/src' matches"
echo "=== Searching for 'refs/gitmind' occurrences ==="
rg -n 'refs/gitmind' docs/cli/combined_markdown.md || echo "no 'refs/gitmind' matches"

Length of output: 13804


Docs link/toc OK — standardize CLI name to "git mind" (space)

check_docs.py --mode link/toc exited successfully. The file mixes hyphenated "git-mind" in TOC/section titles (e.g. lines 16, 38) with the spaced CLI form "git mind" in examples (e.g. lines 168, 178–180). Replace "git-mind" → "git mind" in headings/TOC and any CLI references for consistency.

🤖 Prompt for AI Agents
In docs/cli/combined_markdown.md around lines 178 to 180, headings/TOC and some
CLI references use the hyphenated form "git-mind" while examples use the spaced
form "git mind"; update all headings, TOC entries, and any CLI mentions to use
the standardized "git mind" (space) form so the document is consistent—search
the file for "git-mind" and replace with "git mind" in titles, TOC lines, and
inline CLI snippets, leaving other text unchanged.

Comment thread docs/cli/gitmind-link.md
Comment on lines +3 to +11
---
title: git-mind link
description: Create a semantic connection between two paths.
audience: [users, developers]
domain: [cli]
tags: [cli, link]
status: stable
last_updated: 2025-09-15
---

ghost Sep 18, 2025

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

🧩 Analysis chain

Move YAML front matter to the very top; place SPDX/copyright after it.

Front matter starts at Line 3 but is preceded by HTML comments on Lines 1–2. This violates the repo’s front‑matter rule and can fail docs/CI checks.

Apply this diff:

-<!-- SPDX-License-Identifier: LicenseRef-MIND-UCAL-1.0 -->
-<!-- © 2025 J. Kirby Ross / Neuroglyph Collective -->
 ---
 title: git-mind link
 description: Create a semantic connection between two paths.
 audience: [users, developers]
 domain: [cli]
 tags: [cli, link]
 status: stable
 last_updated: 2025-09-15
 ---
+
+<!-- SPDX-License-Identifier: LicenseRef-MIND-UCAL-1.0 -->
+<!-- © 2025 J. Kirby Ross / Neuroglyph Collective -->

Also applies to: 1-2


🏁 Script executed:

#!/bin/bash
set -euo pipefail
python3 tools/docs/check_frontmatter.py docs/cli/gitmind-link.md
python3 tools/docs/check_docs.py --mode link --base docs
python3 tools/docs/check_docs.py --mode toc  --base docs

Length of output: 124


🏁 Script executed:

#!/bin/bash
set -euo pipefail
f="docs/cli/gitmind-link.md"

echo "== file head (first 30 lines) =="
nl -ba "$f" | sed -n '1,30p'

echo
echo "== lines containing only '---' (line numbers) =="
awk 'NR<=200{if($0=="---"){print NR}}' "$f" || true

echo
if [ -f tools/docs/check_frontmatter.py ]; then
  echo "== running check_frontmatter.py --base docs =="
  python3 tools/docs/check_frontmatter.py --base docs || true
else
  echo "tools/docs/check_frontmatter.py not found"
fi

if [ -f tools/docs/check_docs.py ]; then
  echo "== running check_docs.py link/toc =="
  python3 tools/docs/check_docs.py --mode link --base docs || true
  python3 tools/docs/check_docs.py --mode toc --base docs || true
else
  echo "tools/docs/check_docs.py not found"
fi

Length of output: 73


🏁 Script executed:

#!/bin/bash
set -euo pipefail
f="docs/cli/gitmind-link.md"

if [ ! -f "$f" ]; then
  echo "MISSING: $f"
  exit 0
fi

echo "== file exists: $f =="
wc -l "$f" || true

echo
echo "== lines 1-30 =="
sed -n '1,30p' "$f" || true

echo
echo "== lines starting with '<!--' (with numbers) =="
grep -n '^<!--' "$f" || true

echo
echo "== lines that are exactly '---' (with numbers) =="
grep -n '^---$' "$f" || true

echo
echo "== first 12 lines with visible EOL marker =="
sed -n '1,12p' "$f" | sed -e 's/$/␤/' -e 's/^/→ /' || true

Length of output: 1405


Move YAML front matter to the very top; place SPDX/copyright after it.

Front matter opens at line 3 but is preceded by HTML comments on lines 1–2 — this violates the repo front‑matter rule and can fail docs CI.

File: docs/cli/gitmind-link.md — comments at lines 1–2; front matter opens at line 3 and closes at line 11.

-<!-- SPDX-License-Identifier: LicenseRef-MIND-UCAL-1.0 -->
-<!-- © 2025 J. Kirby Ross / Neuroglyph Collective -->
 ---
 title: git-mind link
 description: Create a semantic connection between two paths.
 audience: [users, developers]
 domain: [cli]
 tags: [cli, link]
 status: stable
 last_updated: 2025-09-15
 ---
+
+<!-- SPDX-License-Identifier: LicenseRef-MIND-UCAL-1.0 -->
+<!-- © 2025 J. Kirby Ross / Neuroglyph Collective -->
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
---
title: git-mind link
description: Create a semantic connection between two paths.
audience: [users, developers]
domain: [cli]
tags: [cli, link]
status: stable
last_updated: 2025-09-15
---
---
title: git-mind link
description: Create a semantic connection between two paths.
audience: [users, developers]
domain: [cli]
tags: [cli, link]
status: stable
last_updated: 2025-09-15
---
<!-- SPDX-License-Identifier: LicenseRef-MIND-UCAL-1.0 -->
<!-- © 2025 J. Kirby Ross / Neuroglyph Collective -->
🤖 Prompt for AI Agents
In docs/cli/gitmind-link.md around lines 1 to 11, the YAML front matter
currently starts at line 3 but is preceded by HTML comments on lines 1–2 which
violates the repo rule; move the entire YAML block (lines 3–11) to the very top
of the file (starting at line 1), then place any SPDX/copyright or
license/copyright comments immediately after the closing --- of the front
matter, and remove or relocate the original HTML comments so no content precedes
the front matter.

Comment on lines +481 to 483
"core/src/auth.c",
GM_PREDICT_DEPENDENCIES | GM_PREDICT_IMPLEMENTS
);

ghost Sep 18, 2025

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

🧩 Analysis chain

LGTM on path migration; please sweep remaining examples for consistency.

The change to "core/src/auth.c" matches the repo’s core/src move. Do a quick sweep in this doc (and optionally docs/) for stale "src/.c" examples to avoid mixed conventions. Consider a brief note up top that paths in snippets mirror the current repo layout.


🏁 Script executed:

#!/bin/bash
# Find stale path examples (should be core/src/* now)
rg -nP '\bsrc/[A-Za-z0-9_./-]+\.c\b' docs/wish-list-features/brain-storms/CLAUDE_ULTRATHINKS_GITMIND_FUTURE.md

# Optional: repo‑wide doc sweep for stale src/ paths (excluding core/src/)
rg -nP '\bsrc/(?!auth\.c|main\.c)[A-Za-z0-9_./-]+\.c\b' docs

Length of output: 110


🏁 Script executed:

#!/bin/bash
# Show matches in the specific file
rg -n '\bsrc/[A-Za-z0-9_./-]+\.c\b' docs/wish-list-features/brain-storms/CLAUDE_ULTRATHINKS_GITMIND_FUTURE.md || true

# Repo-wide doc sweep for src/*.c examples (then filter out core/src/)
rg -n '\bsrc/[A-Za-z0-9_./-]+\.c\b' docs || true
rg -n '\bsrc/[A-Za-z0-9_./-]+\.c\b' docs | rg -v 'core/src/' || true

Length of output: 27238


Sweep docs for stale "src/*.c" paths — standardize on core/src/

Multiple docs still reference "src/…" (replace with "core/src/…") and add a one-line note that snippet paths mirror the current repo layout. Fix examples in (non‑exhaustive): docs/tutorial.md, docs/legacy/src/edge.md, docs/architecture/attribution-integration-guide.md, docs/enforcer/gameplans/03-observability-built-in.md, docs/enforcer/gameplans/04-testing-infrastructure-uplift.md, docs/cli/gitmind.md, docs/cli/gitmind-list.md, docs/operations/Environment_Variables.md, docs/architecture/MODULAR_RESTRUCTURE_PLAN.md.

🤖 Prompt for AI Agents
In docs/wish-list-features/brain-storms/CLAUDE_ULTRATHINKS_GITMIND_FUTURE.md
around lines 481-483, several documentation snippets reference "src/…" paths
that are now stale; update those references to "core/src/…" everywhere,
including the example files called out (docs/tutorial.md,
docs/legacy/src/edge.md, docs/architecture/attribution-integration-guide.md,
docs/enforcer/gameplans/03-observability-built-in.md,
docs/enforcer/gameplans/04-testing-infrastructure-uplift.md,
docs/cli/gitmind.md, docs/cli/gitmind-list.md,
docs/operations/Environment_Variables.md,
docs/architecture/MODULAR_RESTRUCTURE_PLAN.md), and add a one-line note in the
docs (near the top of docs or the examples section) stating that snippet paths
mirror the current repository layout so future moves should update paths
accordingly.

ghost left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 5

♻️ Duplicate comments (3)
meson.build (3)

3-3: Don’t hardcode c_std; probe and select the best supported standard.

Improves portability across toolchains and aligns with prior guidance.

-        default_options: ['c_std=c2x', 'warning_level=3', 'werror=true'])
+        default_options: ['warning_level=3', 'werror=true'])

Insert below the project() call:

cc = meson.get_compiler('c')
std_candidates = ['-std=c2x', '-std=gnu2x', '-std=c23', '-std=gnu23']
std_supported = cc.get_supported_arguments(std_candidates)
if std_supported.length() == 0
  error('A C23-capable compiler is required (one of: c2x/gnu2x/c23/gnu23).')
endif
add_project_arguments(std_supported[0], language: 'c')

8-10: Avoid spawning shells to read env; use meson.get_env.

Cheaper and more portable; preserves behavior.

-in_docker = run_command('sh', '-lc', '[ "$GITMIND_DOCKER" = "1" ] && echo 1 || echo 0', check: false).stdout().strip() == '1'
-in_ci = run_command('sh', '-lc', '[ -n "$GITHUB_ACTIONS" ] && echo 1 || echo 0', check: false).stdout().strip() == '1'
-env_override = run_command('sh', '-lc', '[ "$GITMIND_ALLOW_HOST_BUILD" = "1" ] && echo 1 || echo 0', check: false).stdout().strip() == '1'
+in_docker = meson.get_env('GITMIND_DOCKER') == '1'
+in_ci = meson.get_env('GITHUB_ACTIONS') != ''
+env_override = meson.get_env('GITMIND_ALLOW_HOST_BUILD') == '1'

377-377: Make -include header path robust for out-of-tree builds.

Use join_paths with source_root to avoid '../' assumptions.

-    c_args : ['-include', '../' + hdr],
+    c_args : ['-include', join_paths(meson.source_root(), hdr)],
🧹 Nitpick comments (6)
core/tests/unit/test_cache_tree_size.c (2)

29-31: Use a unique temp repo path (avoid collisions and filesystem residue).

Hardcoding "./.gm_cache_tree_tmp" can clash across runs and leaves artifacts. Use mkdtemp (or a gm_* wrapper) and assert directory creation.

-    git_repository *repo = NULL;
-    int rc = git_repository_init(&repo, "./.gm_cache_tree_tmp", true);
+    git_repository *repo = NULL;
+    char tmpdir[] = "/tmp/gm_cache_tree_XXXXXX";
+    assert(mkdtemp(tmpdir) != NULL);
+    int rc = git_repository_init(&repo, tmpdir, true);

Add (outside this hunk) at the top:

#include <stdlib.h>

76-81: Use uint64_t for expected to avoid width mismatch.

Small, but keeps types aligned with total on 32/64-bit.

-    size_t expected = 0;
-    expected += object_size(repo, &root_tree_oid);
-    expected += object_size(repo, &nested_tree_oid);
-    expected += object_size(repo, &root_blob_oid);
-    expected += object_size(repo, &nested_blob_oid);
+    uint64_t expected = 0;
+    expected += (uint64_t)object_size(repo, &root_tree_oid);
+    expected += (uint64_t)object_size(repo, &nested_tree_oid);
+    expected += (uint64_t)object_size(repo, &root_blob_oid);
+    expected += (uint64_t)object_size(repo, &nested_blob_oid);
core/tests/unit/test_cache_branch_limits.c (3)

35-36: Bounds-check refname and prefer gm_snprintf + GM_PATH_MAX.

Prevents silent truncation when branch names approach limits.

-    char refname[256];
+    char refname[GM_PATH_MAX];
@@
-    snprintf(refname, sizeof refname, "refs/heads/%s", branch);
+    int n = gm_snprintf(refname, sizeof refname, "refs/heads/%s", branch);
+    assert(n > 0 && (size_t)n < sizeof refname);

Add (outside this hunk) near includes:

#include "gitmind/constants.h"
#include "gitmind/security/string.h"

Also applies to: 47-47


67-69: Use a unique temp bare repo dir.

Same rationale as the other test: avoid path collisions and leftovers.

-    git_repository *repo = NULL;
-    int rc = git_repository_init(&repo, "./.gm_cache_branch_tmp", true);
+    git_repository *repo = NULL;
+    char tmpdir[] = "/tmp/gm_cache_branch_XXXXXX";
+    assert(mkdtemp(tmpdir) != NULL);
+    int rc = git_repository_init(&repo, tmpdir, true);

Add (outside this hunk) at the top if not present:

#include <stdlib.h>

92-93: Check ULID generation result.

gm_ulid_generate returns a result; assert ok to catch unexpected failures.

-    (void)gm_ulid_generate(edge.ulid);
+    gm_result_ulid_t ulr = gm_ulid_generate(edge.ulid);
+    assert(ulr.ok);
docs/features/Features_Ledger.md (1)

156-156: Normalize status names to the canonical set.

Use “v1.0.0” instead of “V1” to match the Status Model.

-| 🧰 | Safe String/Memory | Core | — | core/include/gitmind/util | v1.0.0 | 0.4 | V1 | 90% | █████████░ | Safe wrappers adopted in hot paths. | Sweep stragglers; docs. | Unit | Security uplift. |
+| 🧰 | Safe String/Memory | Core | — | core/include/gitmind/util | v1.0.0 | 0.4 | v1.0.0 | 90% | █████████░ | Safe wrappers adopted in hot paths. | Sweep stragglers; docs. | Unit | Security uplift. |
-| 🧪 | Worksheet Gates | DX | docs/tools | tools/review | Alpha | 0.3 | V1 | 90% | █████████░ | Pre‑push checks for placeholders + decisions. | Heuristics later (optional). | Scripted | Keeps quality high. |
+| 🧪 | Worksheet Gates | DX | docs/tools | tools/review | Alpha | 0.3 | v1.0.0 | 90% | █████████░ | Pre‑push checks for placeholders + decisions. | Heuristics later (optional). | Scripted | Keeps quality high. |

Also applies to: 179-179

📜 Review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b39e24f and 288db48.

📒 Files selected for processing (4)
  • core/tests/unit/test_cache_branch_limits.c (1 hunks)
  • core/tests/unit/test_cache_tree_size.c (1 hunks)
  • docs/features/Features_Ledger.md (1 hunks)
  • meson.build (7 hunks)
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{c,cc,cpp,cxx,h,hpp,hxx,m,mm}

📄 CodeRabbit inference engine (CLAUDE.md)

NEVER use NOLINT to suppress clang-tidy warnings; ALWAYS fix the underlying issue

Files:

  • core/tests/unit/test_cache_tree_size.c
  • core/tests/unit/test_cache_branch_limits.c
core/**

📄 CodeRabbit inference engine (AGENTS.md)

Add new code under core/ (C23 library: include/ for public headers, src/ for implementation, tests/ for unit tests)

Files:

  • core/tests/unit/test_cache_tree_size.c
  • core/tests/unit/test_cache_branch_limits.c
{core,src,apps,include}/**/*.{c,h}

📄 CodeRabbit inference engine (AGENTS.md)

{core,src,apps,include}/**/*.{c,h}: Use C23 with warnings-as-errors; forbid VLAs and variable shadowing; require explicit function prototypes
Follow .clang-format (LLVM-based, 4 spaces, 80 columns, pointer alignment right)
Function and variable names in lower_snake_case with gm_ prefix
Macro names in UPPER_SNAKE case
Type names end with _t
Prefer specific header includes; follow include ordering as enforced by .clang-format
Introduce no new clang-tidy warnings (lint via tools/docker-clang-tidy.sh)

Files:

  • core/tests/unit/test_cache_tree_size.c
  • core/tests/unit/test_cache_branch_limits.c
core/tests/unit/test_*.c

📄 CodeRabbit inference engine (AGENTS.md)

Unit tests live in core/tests/unit/ and are named test_.c; keep tests deterministic and isolated

Files:

  • core/tests/unit/test_cache_tree_size.c
  • core/tests/unit/test_cache_branch_limits.c
core/**/*.{c,h}

📄 CodeRabbit inference engine (AGENTS.md)

Prefer OID-first APIs in new core code: use git_oid (typedef gm_oid_t) and compare via git_oid_cmp

Files:

  • core/tests/unit/test_cache_tree_size.c
  • core/tests/unit/test_cache_branch_limits.c
**/*.md

📄 CodeRabbit inference engine (AGENTS.md)

Comply with repository markdown lint rules (.markdownlint.jsonc); use make md-lint / make md-fix

Files:

  • docs/features/Features_Ledger.md
docs/**/*.md

📄 CodeRabbit inference engine (AGENTS.md)

Docs must pass link and TOC checks (tools/docs/check_docs.py --mode link|toc)

Files:

  • docs/features/Features_Ledger.md
🧠 Learnings (3)
📓 Common learnings
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/core/src/**/*.c : Normalize error handling to a single scheme (prefer `GM_OK`/`GM_ERR_*`) and avoid mixing raw libgit2 error codes
Learnt from: flyingrobots
PR: neuroglyph/git-mind#169
File: docs/templates/code-review-feedback.md:26-33
Timestamp: 2025-09-16T17:10:27.450Z
Learning: The user (flyingrobots) uses Obsidian to view/edit Markdown files and prefers to keep Obsidian-specific syntax like collapsible callout markers (e.g., `[!NOTE]-` for collapsible callouts) even if they're not GitHub-compatible.
📚 Learning: 2025-09-13T03:13:54.145Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-13T03:13:54.145Z
Learning: Use Meson/Ninja for build and tests; run lint and gauntlet locally; keep diffs minimal and pass CI with zero new clang-tidy warnings

Applied to files:

  • meson.build
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/**/meson.build : Do not hardcode `c_std=c23`; detect compiler support or provide a compatible minimum standard with feature checks

Applied to files:

  • meson.build
🧬 Code graph analysis (2)
core/tests/unit/test_cache_tree_size.c (1)
core/src/cache/tree_size.c (1)
  • gm_cache_calculate_size (89-93)
core/tests/unit/test_cache_branch_limits.c (3)
core/src/types/ulid.c (1)
  • gm_ulid_generate (118-126)
core/src/journal/writer.c (1)
  • gm_journal_append (263-267)
core/src/cache/builder.c (1)
  • gm_cache_rebuild (494-500)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Compat Canaries (non-blocking) (clang-18)
  • GitHub Check: Compat Canaries (non-blocking) (gcc-12)
  • GitHub Check: Compat Canaries (non-blocking) (clang-19)
  • GitHub Check: Compat Canaries (non-blocking) (gcc-13)
  • GitHub Check: lint-and-sanitize
🔇 Additional comments (2)
core/tests/unit/test_cache_tree_size.c (1)

72-75: LGTM: good end-to-end check against ODB sizes.

The test accurately validates gm_cache_calculate_size by summing tree+blob object sizes.

Also applies to: 82-88

docs/features/Features_Ledger.md (1)

58-62: Obsidian callouts retained intentionally.

Good use of [!INFO]- collapsible callouts per maintainer preference.

Also applies to: 73-81, 92-97, 108-113

Comment on lines +9 to +10
#include <git2/sys/commit.h>

ghost Sep 18, 2025

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Avoid libgit2 internal APIs; replace git2/sys/commit.h and _from_ids with public API.

sys headers are unstable; use git_commit_create with a looked-up tree.

-#include <git2/sys/commit.h>
+/* use only public libgit2 API */

@@
-    rc = git_commit_create_from_ids(&commit_oid, repo, NULL, sig, sig, NULL,
-                                    "init", &tree_oid, 0, NULL);
+    git_tree *tree = NULL;
+    rc = git_tree_lookup(&tree, repo, &tree_oid);
+    assert(rc == 0 && tree);
+    rc = git_commit_create(&commit_oid, repo, NULL, sig, sig, NULL,
+                           "init", tree, 0, NULL);
+    git_tree_free(tree);

Also applies to: 48-51

🤖 Prompt for AI Agents
In core/tests/unit/test_cache_branch_limits.c around lines 9-10 (and also apply
same change at lines 48-51), the test is including the internal header
git2/sys/commit.h and calling internal _from_ids helpers; replace those usages
with public libgit2 API: remove the sys header include, use git_oid and public
lookup functions to obtain a git_tree (git_tree_lookup or
git_tree_lookup_prefix) and then create commits with git_commit_create (or
git_commit_create_v) passing the looked-up tree and parent OIDs; ensure error
handling and resource cleanup follow public API patterns.

Comment thread docs/features/Features_Ledger.md
Comment on lines +22 to +27
${formula where features are weighted based on their estimated complexity}$

And here's how we calculate the completion percentage of the overall project:

${overall progress formula}$

ghost Sep 18, 2025

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Replace placeholder formulas with concrete definitions (placeholders likely fail gates).

The ${…}$ placeholders will flag “placeholder” heuristics and are unclear. Provide real formulas or succinct prose.

Apply this diff:

-${formula where features are weighted based on their estimated complexity}$
+Milestone progress = Σ(weight_i × completion_i) / Σ(weight_i),
+where weight_i is each feature’s KLoC (or normalized complexity) within that milestone.
 
-${overall progress formula}$
+Overall progress = Σ(W_m × progress_m) / Σ(W_m),
+where W_m are milestone weights defined in the roadmap (e.g., MVP=1, Alpha=1, Beta=1, v1.0.0=2).
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
${formula where features are weighted based on their estimated complexity}$
And here's how we calculate the completion percentage of the overall project:
${overall progress formula}$
Milestone progress = Σ(weight_i × completion_i) / Σ(weight_i),
where weight_i is each feature’s KLoC (or normalized complexity) within that milestone.
And here's how we calculate the completion percentage of the overall project:
Overall progress = Σ(W_m × progress_m) / Σ(W_m),
where W_m are milestone weights defined in the roadmap (e.g., MVP=1, Alpha=1, Beta=1, v1.0.0=2).
🤖 Prompt for AI Agents
In docs/features/Features_Ledger.md around lines 22 to 27, replace the two ${…}
placeholders with concrete formulas: define how feature weights are computed
from estimated complexity (e.g., weight_i = complexity_i /
sum_of_all_complexities) and define how a feature contributes to project
completion (e.g., feature_contribution = weight_i * feature_completion_percent),
then provide the overall progress formula as the sum of all feature
contributions (overall_progress = sum(feature_contribution_i)); keep the prose
short and include example variable names so readers can implement the formulas
unambiguously.

Comment thread docs/features/Features_Ledger.md
Comment on lines +50 to +51
**What “MVP” means:** Core linking/journal flows usable end-to-end for maintainers and early adopters; docs and safety rails in place for guided experiments. See `docs/planning/Milestone_Synthesis.md#mvpmmdash-show-hn-ready`.

ghost Sep 18, 2025

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

🧩 Analysis chain

Fix likely-broken section anchors in links to Milestone_Synthesis.md.

The “-mdash-” tokens won’t match GitHub-style anchors. Use the canonical slugs.

Apply this diff:

-See `docs/planning/Milestone_Synthesis.md#mvpmmdash-show-hn-ready`.
+See `docs/planning/Milestone_Synthesis.md#mvp-show-hn-ready`.
-See `docs/planning/Milestone_Synthesis.md#alpha-mdash-team-productivity`.
+See `docs/planning/Milestone_Synthesis.md#alpha-team-productivity`.
-See `docs/planning/Milestone_Synthesis.md#beta-mdash-community-onboarding`.
+See `docs/planning/Milestone_Synthesis.md#beta-community-onboarding`.
-See `docs/planning/Milestone_Synthesis.md#v100-mdash-production-grade`.
+See `docs/planning/Milestone_Synthesis.md#v100-production-grade`.

Run this to verify anchors and links locally:

Also applies to: 65-66, 84-85, 100-101


🏁 Script executed:

#!/bin/bash
set -euo pipefail
make md-lint || true
python3 tools/docs/check_docs.py --mode link docs/features/Features_Ledger.md

Length of output: 42


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "PWD: $(pwd)"

echo
echo "Checking docs directories..."
for d in docs docs/planning docs/features; do
  if [ -d "$d" ]; then
    echo "DIR: $d (exists)"
    ls -la "$d" | sed -n '1,120p'
  else
    echo "DIR: $d (missing)"
  fi
done

echo
for f in docs/features/Features_Ledger.md docs/planning/Milestone_Synthesis.md; do
  if [ -f "$f" ]; then
    echo "FOUND: $f"
  else
    echo "MISSING: $f"
  fi
done

echo
echo "--- Lines in Features_Ledger.md containing 'Milestone_Synthesis.md' or 'mdash' ---"
if [ -f docs/features/Features_Ledger.md ]; then
  grep -n -E 'Milestone_Synthesis.md#|mdash' docs/features/Features_Ledger.md || true
else
  echo "Features_Ledger.md not found"
fi

echo
echo "--- Show first 220 lines of Features_Ledger.md ---"
if [ -f docs/features/Features_Ledger.md ]; then
  sed -n '1,220p' docs/features/Features_Ledger.md | nl -ba | sed -n '1,220p'
else
  echo "Features_Ledger.md not found"
fi

echo
echo "--- Headings in Milestone_Synthesis.md and computed GitHub-style slugs ---"
if [ -f docs/planning/Milestone_Synthesis.md ]; then
  python3 - <<'PY'
import re, unicodedata, sys
p='docs/planning/Milestone_Synthesis.md'
try:
    with open(p,'r',encoding='utf-8') as f:
        lines=f.readlines()
except Exception as e:
    print("ERROR reading",p, e)
    sys.exit(0)

def slugify(s):
    s = s.strip().lower()
    s = unicodedata.normalize('NFKD', s)
    s = re.sub(r'<.*?>', '', s)
    s = re.sub(r'[^a-z0-9\s-]', ' ', s)
    s = re.sub(r'\s+', '-', s)
    s = re.sub(r'-+', '-', s)
    s = s.strip('-')
    return s

for i,l in enumerate(lines, start=1):
    m=re.match(r'^(#{1,6})\s+(.*)', l)
    if m:
        level=len(m.group(1))
        title=m.group(2).strip()
        print(f"{i:4d} H{level} {title} -> #{slugify(title)}")
PY
else
  echo "Milestone_Synthesis.md not found"
fi

echo
echo "--- Search for exact anchors suggested in the diff ---"
if [ -f docs/planning/Milestone_Synthesis.md ]; then
  for a in "#mvp-show-hn-ready" "#alpha-team-productivity" "#beta-community-onboarding" "#v100-production-grade"; do
    echo "Searching for anchor: $a"
    grep -n "${a#\#}" docs/planning/Milestone_Synthesis.md || true
  done
fi

Length of output: 4195


🏁 Script executed:

#!/bin/bash
set -euo pipefail

MS="docs/planning/Milestone_Synthesis.md"
FL="docs/features/Features_Ledger.md"

if [ ! -f "$MS" ]; then
  echo "Milestone_Synthesis.md not found: $MS"
  exit 0
fi
if [ ! -f "$FL" ]; then
  echo "Features_Ledger.md not found: $FL"
  exit 0
fi

echo "=== Headings in $MS with computed GitHub-style slugs ==="
python3 - <<'PY'
import re, unicodedata
p='docs/planning/Milestone_Synthesis.md'
def slugify(s):
    s = s.strip().lower()
    s = unicodedata.normalize('NFKD', s)
    s = re.sub(r'<.*?>', '', s)
    s = re.sub(r'[^a-z0-9\s-]', ' ', s)
    s = re.sub(r'\s+', '-', s)
    s = re.sub(r'-+', '-', s)
    return s.strip('-')

with open(p, 'r', encoding='utf-8') as f:
    for i, line in enumerate(f, start=1):
        m = re.match(r'^(#{1,6})\s+(.*)', line)
        if m:
            title = m.group(2).strip()
            print(f"{i:4d} {title} -> #{slugify(title)}")
PY

echo
echo "=== Problematic anchor occurrences in $FL ==="
grep -n -E 'Milestone_Synthesis.md#.*mdash|Milestone_Synthesis.md#mvpmmdash|Milestone_Synthesis.md#alpha-mdash|Milestone_Synthesis.md#beta-mdash|Milestone_Synthesis.md#v100-mdash' "$FL" || true

echo
echo "=== Suggestion (apply these replacements) ==="
cat <<'EOF'
See `docs/planning/Milestone_Synthesis.md#mvpmmdash-show-hn-ready`.
=> See `docs/planning/Milestone_Synthesis.md#mvp-show-hn-ready`.

See `docs/planning/Milestone_Synthesis.md#alpha-mdash-team-productivity`.
=> See `docs/planning/Milestone_Synthesis.md#alpha-team-productivity`.

See `docs/planning/Milestone_Synthesis.md#beta-mdash-community-onboarding`.
=> See `docs/planning/Milestone_Synthesis.md#beta-community-onboarding`.

See `docs/planning/Milestone_Synthesis.md#v100-mdash-production-grade`.
=> See `docs/planning/Milestone_Synthesis.md#v100-production-grade`.
EOF

Length of output: 2165


Fix Milestone_Synthesis.md anchors in Features_Ledger.md.

Replace occurrences in docs/features/Features_Ledger.md:

  • Line 50: docs/planning/Milestone_Synthesis.md#mvpmmdash-show-hn-ready → docs/planning/Milestone_Synthesis.md#mvp-show-hn-ready
  • Line 65: docs/planning/Milestone_Synthesis.md#alpha-mdash-team-productivity → docs/planning/Milestone_Synthesis.md#alpha-team-productivity
  • Line 84: docs/planning/Milestone_Synthesis.md#beta-mdash-community-onboarding → docs/planning/Milestone_Synthesis.md#beta-community-onboarding
  • Line 100: docs/planning/Milestone_Synthesis.md#v100-mdash-production-grade → docs/planning/Milestone_Synthesis.md#v1-0-0-production-grade
🤖 Prompt for AI Agents
In docs/features/Features_Ledger.md around lines 50-100, several broken anchor
links to docs/planning/Milestone_Synthesis.md must be corrected: change the
anchor at line 50 from
docs/planning/Milestone_Synthesis.md#mvpmmdash-show-hn-ready to
docs/planning/Milestone_Synthesis.md#mvp-show-hn-ready; at line 65 change
docs/planning/Milestone_Synthesis.md#alpha-mdash-team-productivity to
docs/planning/Milestone_Synthesis.md#alpha-team-productivity; at line 84 change
docs/planning/Milestone_Synthesis.md#beta-mdash-community-onboarding to
docs/planning/Milestone_Synthesis.md#beta-community-onboarding; and at line 100
change docs/planning/Milestone_Synthesis.md#v100-mdash-production-grade to
docs/planning/Milestone_Synthesis.md#v1-0-0-production-grade so each link
matches the actual anchor names.

@flyingrobots
flyingrobots force-pushed the feat/changelog-and-sweep-4 branch 2 times, most recently from c032894 to 7b894b1 Compare September 18, 2025 03:18

ghost left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (4)
meson.build (4)

3-3: Don’t hardcode C standard; probe and select highest supported (C23/2x).

Keeps older toolchains working and aligns with prior guidance.

-project('git-mind', 'c',
-        version: '0.6.0',
-        default_options: ['c_std=c2x', 'warning_level=3', 'werror=true'])
+project('git-mind', 'c',
+        version: '0.6.0',
+        default_options: ['warning_level=3', 'werror=true'])
+
+# Select the highest supported C23/2x mode
+cc = meson.get_compiler('c')
+std_candidates = ['-std=c2x', '-std=gnu2x', '-std=c23', '-std=gnu23']
+std_supported = cc.get_supported_arguments(std_candidates)
+if std_supported.length() == 0
+  error('A C23-capable compiler is required (supports one of: c2x/gnu2x/c23/gnu23).')
+endif
+add_project_arguments(std_supported[0], language: 'c')

8-12: Avoid subshells for env reads; use meson.get_env().

Cheaper, clearer, and more portable.

-in_docker = run_command('sh', '-lc', '[ "$GITMIND_DOCKER" = "1" ] && echo 1 || echo 0', check: false).stdout().strip() == '1'
-in_ci = run_command('sh', '-lc', '[ -n "$GITHUB_ACTIONS" ] && echo 1 || echo 0', check: false).stdout().strip() == '1'
-env_override = run_command('sh', '-lc', '[ "$GITMIND_ALLOW_HOST_BUILD" = "1" ] && echo 1 || echo 0', check: false).stdout().strip() == '1'
+in_docker = meson.get_env('GITMIND_DOCKER') == '1'
+in_ci = meson.get_env('GITHUB_ACTIONS') != ''
+env_override = meson.get_env('GITMIND_ALLOW_HOST_BUILD') == '1'

343-348: Duplicate test registrations resolved.

Now registered once each; configure error avoided.


377-378: Make -include path robust for out-of-tree builds.

Avoid '../' assumptions; use source-root absolute path.

-    c_args : ['-include', '../' + hdr],
+    c_args : ['-include', join_paths(meson.source_root(), hdr)],
🧹 Nitpick comments (1)
meson.build (1)

166-166: DRY up repeated test dependencies.

Define once and reuse to reduce churn.

 # Dependencies
 libsodium_dep = dependency('libsodium', required : true)
 libgit2_dep = dependency('libgit2', required : true)
 thread_dep = dependency('threads')
+test_deps_common = [libsodium_dep, libgit2_dep, thread_dep]
…
-test_error = executable('test_error',
+test_error = executable('test_error',
   'core/tests/unit/test_error.c',
   include_directories : inc,
   link_with : libgitmind,
-  dependencies : [libsodium_dep, libgit2_dep, thread_dep])
+  dependencies : test_deps_common)
…
-  dependencies : [libsodium_dep, libgit2_dep, thread_dep])
+  dependencies : test_deps_common)

Apply the same replacement to the other test executables shown in the selected lines. Leave tests that intentionally differ (those using test_backend_lib with custom deps) as-is.

Also applies to: 172-172, 178-178, 184-184, 190-190, 210-210, 216-216, 223-223, 230-230, 236-236, 242-242, 248-248, 254-254, 260-260, 266-266, 272-272, 278-278, 284-284, 290-290, 296-296, 302-302, 308-308, 314-314, 319-319

📜 Review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 288db48 and c032894.

📒 Files selected for processing (4)
  • core/tests/unit/test_cache_branch_limits.c (1 hunks)
  • core/tests/unit/test_cache_tree_size.c (1 hunks)
  • docs/features/Features_Ledger.md (1 hunks)
  • meson.build (7 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • core/tests/unit/test_cache_branch_limits.c
  • core/tests/unit/test_cache_tree_size.c
  • docs/features/Features_Ledger.md
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: flyingrobots
PR: neuroglyph/git-mind#169
File: docs/templates/code-review-feedback.md:26-33
Timestamp: 2025-09-16T17:10:27.450Z
Learning: The user (flyingrobots) uses Obsidian to view/edit Markdown files and prefers to keep Obsidian-specific syntax like collapsible callout markers (e.g., `[!NOTE]-` for collapsible callouts) even if they're not GitHub-compatible.
📚 Learning: 2025-09-13T03:13:54.145Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-13T03:13:54.145Z
Learning: Use Meson/Ninja for build and tests; run lint and gauntlet locally; keep diffs minimal and pass CI with zero new clang-tidy warnings

Applied to files:

  • meson.build
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/**/meson.build : Do not hardcode `c_std=c23`; detect compiler support or provide a compatible minimum standard with feature checks

Applied to files:

  • meson.build
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Compat Canaries (non-blocking) (clang-19)
  • GitHub Check: Compat Canaries (non-blocking) (gcc-12)
  • GitHub Check: Compat Canaries (non-blocking) (gcc-13)
  • GitHub Check: Compat Canaries (non-blocking) (clang-18)
🔇 Additional comments (5)
meson.build (5)

5-5: Docs pointer LGTM.

Good move to meson_options.txt.


13-32: Host-build hard gate: sensible with override path.

Message is clear; guard matches PR policy.

Please confirm CI images export GITMIND_DOCKER=1 everywhere (including sanitized/clang-tidy jobs) to avoid accidental gate trips.


126-127: New util/ref wired into lib.

Matches tests/docs; good.


130-130: Include order change LGTM.

Public first helps avoid accidental shadowing.


286-291: New tests added and linked correctly.

Targets + deps look consistent; nice coverage expansion.

Also applies to: 298-303, 304-309, 310-320

@flyingrobots
flyingrobots force-pushed the feat/changelog-and-sweep-4 branch from 7b894b1 to 62c7e48 Compare September 18, 2025 03:20

ghost left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (3)
meson.build (3)

3-3: Don’t hardcode c_std; detect highest supported (per prior preference).

Replace the fixed c_std=c2x with compiler-probed flags and require a C23-capable mode.

-project('git-mind', 'c',
-        version: '0.6.0',
-        default_options: ['c_std=c2x', 'warning_level=3', 'werror=true'])
+project('git-mind', 'c',
+        version: '0.6.0',
+        default_options: ['warning_level=3', 'werror=true'])
+
+cc = meson.get_compiler('c')
+std_candidates = ['-std=c2x', '-std=gnu2x', '-std=c23', '-std=gnu23']
+std_supported = cc.get_supported_arguments(std_candidates)
+if std_supported.length() == 0
+  error('A C23-capable compiler is required (supports one of: c2x/gnu2x/c23/gnu23).')
+endif
+add_project_arguments(std_supported[0], language: 'c')

8-12: Stop spawning shells for env checks; use meson.get_env().

Cheaper, portable, and clearer.

-in_docker = run_command('sh', '-lc', '[ "$GITMIND_DOCKER" = "1" ] && echo 1 || echo 0', check: false).stdout().strip() == '1'
-in_ci = run_command('sh', '-lc', '[ -n "$GITHUB_ACTIONS" ] && echo 1 || echo 0', check: false).stdout().strip() == '1'
-env_override = run_command('sh', '-lc', '[ "$GITMIND_ALLOW_HOST_BUILD" = "1" ] && echo 1 || echo 0', check: false).stdout().strip() == '1'
+in_docker = meson.get_env('GITMIND_DOCKER') == '1'
+in_ci = meson.get_env('GITHUB_ACTIONS') != ''
+env_override = meson.get_env('GITMIND_ALLOW_HOST_BUILD') == '1'

377-377: Make -include path robust for out-of-tree builds.

Use source_root + join_paths instead of ../.

-    c_args : ['-include', '../' + hdr],
+    c_args : ['-include', join_paths(meson.source_root(), hdr)],
🧹 Nitpick comments (6)
meson.build (6)

37-37: Avoid global -ffreestanding; scope it to the library only.

Global freestanding can break tests and sanitizers; apply only to lib.

-  '-ffreestanding',          # library and want tight control

142-149: Apply -ffreestanding only to libgitmind.

Move the flag here (paired with the removal above).

 libgitmind = static_library(
   'gitmind',
   src,
   include_directories : inc,
-  dependencies : [libsodium_dep, libgit2_dep, thread_dep, roaring_dep],
-  c_args : roaring_inc_args
+  dependencies : [libsodium_dep, libgit2_dep, thread_dep, roaring_dep],
+  c_args : roaring_inc_args + ['-ffreestanding']
 )

38-39: Gate -fstrict-flex-arrays=3 by compiler support.

Older compilers may not accept =3; probe and fallback.

 add_project_arguments(
-  '-fstrict-flex-arrays=3',  # C23 default; makes UB obvious
+  # strict flex arrays: prefer =3, fallback to =2 if needed
+  # (inserted just above via detection)
   '-Wdouble-promotion',

Add the detection above the add_project_arguments block:

+# Detect strict flex-array support
+strict_flags = cc.get_supported_arguments(['-fstrict-flex-arrays=3', '-fstrict-flex-arrays=2'])
+if strict_flags.length() > 0
+  add_project_arguments(strict_flags[0], language: 'c')
+endif

133-141: Prefer treating CRoaring includes as system via dependency, not raw -isystem.

Using pkg-config’s includedir as -isystem is coarse; let Meson mark the dep as system.

-# Mark roaring headers as system includes to suppress third-party warnings
-roaring_inc_args = []
-if roaring_dep.found()
-  # Use modern API that works with any dependency type
-  roaring_inc_dir = roaring_dep.get_variable(pkgconfig: 'includedir', default_value: '')
-  if roaring_inc_dir != ''
-    roaring_inc_args = ['-isystem', roaring_inc_dir]
-  endif
-endif
+roaring_sys_dep = roaring_dep
+if roaring_dep.found() and roaring_dep.has_method('as_system')
+  roaring_sys_dep = roaring_dep.as_system('system')
+endif
-  dependencies : [libsodium_dep, libgit2_dep, thread_dep, roaring_dep],
-  c_args : roaring_inc_args
+  dependencies : [libsodium_dep, libgit2_dep, thread_dep, roaring_sys_dep],
+  c_args : ['-ffreestanding']

Also applies to: 142-149


352-369: Add newly public headers to standalone compile checks.

Include CBOR constants and ref utils headers to catch drift.

 public_headers = [
   'include/gitmind/output.h',
   'include/gitmind/constants.h',
+  'include/gitmind/cbor/constants_cbor.h',
   'include/gitmind/error.h',
   'include/gitmind/safety.h',
   'core/include/gitmind/result.h',
   'core/include/gitmind/types.h',
   'core/include/gitmind/context.h',
   'core/include/gitmind/attribution.h',
   'core/include/gitmind/edge.h',
   'core/include/gitmind/edge_attributed.h',
   'core/include/gitmind/journal.h',
   'core/include/gitmind/cache.h',
   'core/include/gitmind/io/io.h',
   'core/include/gitmind/time/time.h',
   'core/include/gitmind/util/memory.h',
+  'core/include/gitmind/util/ref.h',
   'core/include/gitmind/utf8/validate.h',
 ]

161-225: DRY repeated test dependencies.

Hoist [libsodium_dep, libgit2_dep, thread_dep] into a variable and reuse.

+# After deps:
+core_test_deps = [libsodium_dep, libgit2_dep, thread_dep]

Example usage:

 test_error = executable('test_error',
   'core/tests/unit/test_error.c',
   include_directories : inc,
   link_with : libgitmind,
-  dependencies : [libsodium_dep, libgit2_dep, thread_dep])
+  dependencies : core_test_deps)
📜 Review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c032894 and 62c7e48.

📒 Files selected for processing (4)
  • core/tests/unit/test_cache_branch_limits.c (1 hunks)
  • core/tests/unit/test_cache_tree_size.c (1 hunks)
  • docs/features/Features_Ledger.md (1 hunks)
  • meson.build (7 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • core/tests/unit/test_cache_tree_size.c
  • docs/features/Features_Ledger.md
  • core/tests/unit/test_cache_branch_limits.c
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: flyingrobots
PR: neuroglyph/git-mind#169
File: docs/templates/code-review-feedback.md:26-33
Timestamp: 2025-09-16T17:10:27.450Z
Learning: The user (flyingrobots) uses Obsidian to view/edit Markdown files and prefers to keep Obsidian-specific syntax like collapsible callout markers (e.g., `[!NOTE]-` for collapsible callouts) even if they're not GitHub-compatible.
📚 Learning: 2025-09-15T01:19:37.384Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: docs/code-review/CLAUDE.md:0-0
Timestamp: 2025-09-15T01:19:37.384Z
Learning: Applies to docs/code-review/**/meson.build : Do not hardcode `c_std=c23`; detect compiler support or provide a compatible minimum standard with feature checks

Applied to files:

  • meson.build
📚 Learning: 2025-09-13T03:13:54.145Z
Learnt from: CR
PR: neuroglyph/git-mind#0
File: AGENTS.md:0-0
Timestamp: 2025-09-13T03:13:54.145Z
Learning: Use Meson/Ninja for build and tests; run lint and gauntlet locally; keep diffs minimal and pass CI with zero new clang-tidy warnings

Applied to files:

  • meson.build
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Compat Canaries (non-blocking) (gcc-13)
🔇 Additional comments (6)
meson.build (6)

13-32: Host-build hard stop: LGTM.

Clear guidance and safe overrides; aligns with Docker/CI-first policy.


126-127: gm_build_ref source wired: LGTM.

Ref utils now part of the library; matches tests/docs.


130-131: Include dirs unified: LGTM.

Public + core headers via inc looks correct.


166-173: Linking unit tests against libgit2: LGTM.

Consistent deps across tests; avoids ODR/link gaps after ref utils.

Also applies to: 178-185, 190-191, 210-217, 224-224, 230-231, 236-237, 242-243, 248-249, 254-255, 260-261, 266-267


286-315: New tests added: LGTM.

Good coverage for branch limits, shard distribution, tree size, OID fallback, and ref utils.


343-348: Test registrations: LGTM (no duplicates).

Previous duplication fixed.

ghost left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (7)
docs/talk-shop/Sandbox_Transactions.md (7)

37-46: Call out ref-construction invariants (align with gm_build_ref).

Explicitly document that branch inputs must not start with "refs/" and are normalized/validated; this prevents double-prefixing and keeps the RFC consistent with gm_build_ref and the new GITMIND_EDGES_REF_PREFIX work.

   refs/gitmind/
     pending/<txn-id>        # sandbox transaction refs
     applied/<txn-id>        # (optional) archive for auditing

-- Transaction IDs are ULIDs; metadata stored under refs/gitmind/pending/<txn-id>/meta.
-- Payload edges live under refs/gitmind/pending/<txn-id>/edges/<branch> mirroring the canonical layout so reuse is easy.
+- Transaction IDs are ULIDs; metadata stored under refs/gitmind/pending/<txn-id>/meta.
+- Payload edges live under refs/gitmind/pending/<txn-id>/edges/<branch> mirroring the canonical layout so reuse is easy.
+
+> [!NOTE]-
+> Ref construction invariants:
+> - Branch inputs must be Git-style names and must NOT begin with refs/ (to avoid double-prefixing).
+> - All refs are constructed via gm_build_ref(out, sz, prefix, branch) with bounds checks and libgit2 normalization.


49-51: Clarify “default” behavior to avoid confusion with Phase 2/3 gating.

Reads/writes are only redirected when a transaction is active (env/flag). Wording “by default” here conflicts with Phases 2–3.

-2. Subsequent `git mind link/list/...` commands operate inside the transaction by default (reads merge pending + canonical, writes hit pending).
+2. When a transaction is active, subsequent `git mind link/list/...` commands operate inside it (reads merge pending + canonical, writes hit pending).

56-59: Specify atomic ref update (CAS) to prevent TOCTOU races.

State that updates to refs/gitmind/edges/<branch> must use compare-and-swap with the recorded base OID (libgit2 expected-old-id), failing fast on mismatch.

 - Confirm the canonical journal tip still equals the recorded base OID (fast-forward); else replay on top (append new commits).
-- Update `refs/gitmind/edges/<branch>` and move the transaction ref under `refs/gitmind/applied/<txn-id>` (or delete if retention not needed).
+- Update `refs/gitmind/edges/<branch>` using an atomic expected-old-OID write; on mismatch, abort and retry replay. Then move the transaction ref under `refs/gitmind/applied/<txn-id>` (or delete if retention not needed).

62-64: Abort policy: also guard against foreign/immutable txns.

Add a note that abort must refuse txns owned by others (if namespaced) and any txn already finalized on the remote, enforced by server-side hooks.

 - Drop the pending ref; the CLI should refuse to abort if the transaction was already applied to avoid footguns.
+ - Drop the pending ref; the CLI should refuse to abort if the transaction was already applied or is not owned by the caller (if namespaced), with server-side hook enforcement.

71-74: Provide refspec examples to keep pending refs out of pushes by default.

Offer concrete push/fetch refspecs so pending/applied never leak unless explicitly requested.

 - Hooks (pre-push) should whitelist pending refs or ignore them entirely.
+- Hooks (pre-push) should whitelist pending refs or ignore them entirely. Recommended refspecs:
+
+```ini
+# .git/config (local)
+[remote "origin"]
+    fetch = +refs/heads/*:refs/remotes/origin/*        # normal branches
+    fetch = +refs/gitmind/edges/*:refs/remotes/origin/gitmind/edges/*
+    # Intentionally omit pending/applied
+    push  = +refs/heads/*:refs/heads/*
+    push  = +refs/gitmind/edges/*:refs/gitmind/edges/*
+```

88-89: Typo: “gm mind” → “git mind”.

Align CLI naming with earlier sections.

-- **Merge tool** – do we want a `gm mind txn rebase` to restack the transaction on a new base before applying?
+- **Merge tool** – do we want a `git mind txn rebase` to restack the transaction on a new base before applying?

35-46: Consider user- or namespace-scoped pending refs to reduce collisions and enable ACLs.

Design tweak: refs/gitmind/pending/<user>/<txn-id> and applied/<user>/<txn-id> simplifies ownership checks and pruning.

-  pending/<txn-id>        # sandbox transaction refs
-  applied/<txn-id>        # (optional) archive for auditing
+  pending/<user>/<txn-id> # sandbox transaction refs (namespaced)
+  applied/<user>/<txn-id> # (optional) archive for auditing

Also applies to: 83-90

📜 Review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 62c7e48 and 20a17d1.

📒 Files selected for processing (1)
  • docs/talk-shop/Sandbox_Transactions.md (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.md

📄 CodeRabbit inference engine (AGENTS.md)

Comply with repository markdown lint rules (.markdownlint.jsonc); use make md-lint / make md-fix

Files:

  • docs/talk-shop/Sandbox_Transactions.md
docs/**/*.md

📄 CodeRabbit inference engine (AGENTS.md)

Docs must pass link and TOC checks (tools/docs/check_docs.py --mode link|toc)

Files:

  • docs/talk-shop/Sandbox_Transactions.md
🧠 Learnings (1)
📓 Common learnings
Learnt from: flyingrobots
PR: neuroglyph/git-mind#169
File: docs/templates/code-review-feedback.md:26-33
Timestamp: 2025-09-16T17:10:27.450Z
Learning: The user (flyingrobots) uses Obsidian to view/edit Markdown files and prefers to keep Obsidian-specific syntax like collapsible callout markers (e.g., `[!NOTE]-` for collapsible callouts) even if they're not GitHub-compatible.
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Compat Canaries (non-blocking) (gcc-13)
🔇 Additional comments (1)
docs/talk-shop/Sandbox_Transactions.md (1)

91-96: Docs link & TOC checks passed — no action required.

Link and TOC checks for docs/talk-shop/Sandbox_Transactions.md succeeded; referenced files (docs/talk-shop/Graph-Lvl-Up-Tank.md, docs/features/Features_Ledger.md, core/tests/unit/test_cache_branch_limits.c, core/tests/unit/test_cache_tree_size.c) are present.

ghost left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (6)
docs/features/Features_Ledger.md (6)

50-50: Fix broken anchor to Milestone_Synthesis.md (MVP).

-See `docs/planning/Milestone_Synthesis.md#mvpmmdash-show-hn-ready`.
+See `docs/planning/Milestone_Synthesis.md#mvp-show-hn-ready`.

65-65: Fix broken anchor to Milestone_Synthesis.md (Alpha).

-See `docs/planning/Milestone_Synthesis.md#alpha-mdash-team-productivity`.
+See `docs/planning/Milestone_Synthesis.md#alpha-team-productivity`.

84-84: Fix broken anchor to Milestone_Synthesis.md (Beta).

-See `docs/planning/Milestone_Synthesis.md#beta-mdash-community-onboarding`.
+See `docs/planning/Milestone_Synthesis.md#beta-community-onboarding`.

100-100: Fix broken anchor to Milestone_Synthesis.md (v1.0.0).

-See `docs/planning/Milestone_Synthesis.md#v100-mdash-production-grade`.
+See `docs/planning/Milestone_Synthesis.md#v1-0-0-production-grade`.

22-27: Replace placeholder formulas with concrete definitions.

Placeholders will fail docs gates and are unclear. Provide explicit formulas.

-${formula where features are weighted based on their estimated complexity}$
+Milestone progress = Σ(weight_i × completion_i) / Σ(weight_i),
+where weight_i is each feature’s normalized complexity (e.g., KLoC or story‑points) within that milestone.
 
-${overall progress formula}$
+Overall progress = Σ(W_m × progress_m) / Σ(W_m),
+where W_m are milestone weights defined in the roadmap (e.g., MVP=1, Alpha=1, Beta=1, v1.0.0=2).

30-39: Fix stray code fence and clean up milestone table text.

Unmatched fence breaks rendering; table has an invalid separator row and informal remarks.

-```
 | Milestone | % | Remarks |
 |-----------|---|------------|
-| MVP       | `██████████████████████████████░░░░░░░░░░ 74%` | Min. Viable Product |
-| Alpha     | `█████████████████████████████▓░░░░░░░░░░ 73%` | Comes before Beta |
-| Beta      | `██████████████████████░░░░░░░░░░░░░░░░░░ 55%` | Half way |
-| v1.0.0    | `█████████████████████████████████░░░░░░░ 82%` | Lol what? |
-| --- |
-| Total   | `█████████████████████████████░░░░░░░░░░░ 72%` | Math don't be mathin' |
+| MVP       | `██████████████████████████████░░░░░░░░░░ 74%` | Minimum Viable Product |
+| Alpha     | `█████████████████████████████▓░░░░░░░░░░ 73%` | Pre‑Beta stabilization phase |
+| Beta      | `██████████████████████░░░░░░░░░░░░░░░░░░ 55%` | Midway hardening |
+| v1.0.0    | `█████████████████████████████████░░░░░░░ 82%` | Scope nearly stable |
+| Total     | `█████████████████████████████░░░░░░░░░░░ 72%` | Totals use milestone weights (see formulas below) |
🧹 Nitpick comments (3)
docs/features/Features_Ledger.md (3)

156-156: Normalize status label “V1” → “v1.0.0”.

Keep milestone names consistent across the doc.

-| 🧰 | Safe String/Memory | Core | — | core/include/gitmind/util | v1.0.0 | 0.4 | V1 | 90% | █████████░ | Safe wrappers adopted in hot paths. | Sweep stragglers; docs. | Unit | Security uplift. |
+| 🧰 | Safe String/Memory | Core | — | core/include/gitmind/util | v1.0.0 | 0.4 | v1.0.0 | 90% | █████████░ | Safe wrappers adopted in hot paths. | Sweep stragglers; docs. | Unit | Security uplift. |

180-180: Normalize status label “V1” → “v1.0.0”.

-| 🧪 | Worksheet Gates | DX | docs/tools | tools/review | Alpha | 0.3 | V1 | 90% | █████████░ | Pre‑push checks for placeholders + decisions. | Heuristics later (optional). | Scripted | Keeps quality high. |
+| 🧪 | Worksheet Gates | DX | docs/tools | tools/review | Alpha | 0.3 | v1.0.0 | 90% | █████████░ | Pre‑push checks for placeholders + decisions. | Heuristics later (optional). | Scripted | Keeps quality high. |

8-8: Bump last_updated after edits.

Update the front‑matter timestamp when you land the fixes.
[raise_nitpick_refactor]

📜 Review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0cf63a9 and bf5c7d4.

📒 Files selected for processing (2)
  • docs/features/Features_Ledger.md (1 hunks)
  • docs/planning/Milestone_Synthesis.md (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • docs/planning/Milestone_Synthesis.md
🧰 Additional context used
📓 Path-based instructions (2)
**/*.md

📄 CodeRabbit inference engine (AGENTS.md)

Comply with repository markdown lint rules (.markdownlint.jsonc); use make md-lint / make md-fix

Files:

  • docs/features/Features_Ledger.md
docs/**/*.md

📄 CodeRabbit inference engine (AGENTS.md)

Docs must pass link and TOC checks (tools/docs/check_docs.py --mode link|toc)

Files:

  • docs/features/Features_Ledger.md
🧠 Learnings (1)
📓 Common learnings
Learnt from: flyingrobots
PR: neuroglyph/git-mind#169
File: docs/templates/code-review-feedback.md:26-33
Timestamp: 2025-09-16T17:10:27.450Z
Learning: The user (flyingrobots) uses Obsidian to view/edit Markdown files and prefers to keep Obsidian-specific syntax like collapsible callout markers (e.g., `[!NOTE]-` for collapsible callouts) even if they're not GitHub-compatible.
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Compat Canaries (non-blocking) (clang-19)
  • GitHub Check: Compat Canaries (non-blocking) (clang-18)
  • GitHub Check: Compat Canaries (non-blocking) (gcc-13)
  • GitHub Check: Compat Canaries (non-blocking) (gcc-12)
🔇 Additional comments (1)
docs/features/Features_Ledger.md (1)

58-61: Confirm markdownlint/link/TOC pass for Obsidian callouts ([!INFO])

Obsidian callouts ([!INFO]) are acceptable; ensure markdownlint and the docs link/TOC checks pass for docs/features/Features_Ledger.md — lines 58–61, 73–81, 92–97, 108–113, 200–249. Run locally and paste outputs: make md-lint || true, python3 tools/docs/check_docs.py --mode link docs/features/Features_Ledger.md, python3 tools/docs/check_docs.py --mode toc docs/features/Features_Ledger.md

@flyingrobots
flyingrobots force-pushed the feat/changelog-and-sweep-4 branch 2 times, most recently from b8dcb2b to f531dc1 Compare September 18, 2025 11:26
@flyingrobots
flyingrobots force-pushed the feat/changelog-and-sweep-4 branch from f531dc1 to 62577ae Compare September 18, 2025 11:29
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