Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
bfaec2e
chore(core/migration): remove legacy src/ duplicates; convert include…
flyingrobots Sep 13, 2025
2c614d3
fix(tidy/include-cleaner): include exact libgit2 headers; drop unused…
flyingrobots Sep 13, 2025
2bc9c75
Update include/gitmind.h
flyingrobots Sep 13, 2025
187afcf
Update core/include/gitmind/hooks/augment.h
flyingrobots Sep 13, 2025
140412a
Update core/include/gitmind/hooks/augment.h
flyingrobots Sep 13, 2025
5fccc48
fix(core/journal): include minimal libgit2 headers; replace strncpy/s…
flyingrobots Sep 14, 2025
58be14d
fix(core/journal): base64-encode CBOR in commit messages (libsodium);…
flyingrobots Sep 14, 2025
bd178ec
feat(core): introduce gm_oid_t (SHA-agnostic); extend gm_edge with gi…
flyingrobots Sep 14, 2025
7331481
feat(core/edge): populate git_oid alongside legacy SHA; prefer OID co…
flyingrobots Sep 14, 2025
7fef97d
build(test): add standalone header compilation checks for public headers
flyingrobots Sep 14, 2025
f18ebf3
feat(core/hooks): migrate augment hooks to OID-first API (gm_hook_*);…
flyingrobots Sep 14, 2025
f4ee7ff
feat(core/cache): migrate builder/query to OID-first (gm_oid_t); upda…
flyingrobots Sep 14, 2025
ef52094
feat(core/edge_attrib): add gm_oid_t fields; populate OIDs on create;…
flyingrobots Sep 14, 2025
38a489f
feat(core): OID-first CBOR for edges + attributed; journal commit saf…
flyingrobots Sep 14, 2025
1b71390
fix(core/edge): require OID equality when present; fallback only if O…
flyingrobots Sep 14, 2025
4fe31a5
refactor(cbor): centralize CBOR key constants; use across edge/journa…
flyingrobots Sep 14, 2025
a03f926
feat(edge/attributed): add public CBOR encode/decode (+ex) and tests\…
flyingrobots Sep 14, 2025
098bfd0
refactor(journal): use public attributed CBOR encode/decode; remove l…
flyingrobots Sep 14, 2025
48a7d4a
chore(tests): add edge equality semantics tests; minor include cleanu…
flyingrobots Sep 15, 2025
2ab2f39
docs: document Meson feature toggles; add cache OID-only migration no…
flyingrobots Sep 15, 2025
6a94e02
test(cache): add cache meta legacy-ref fallback test
flyingrobots Sep 15, 2025
1c69b5c
chore(hooks): normalize error codes to GM_ERR_*; update review doc note
flyingrobots Sep 15, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,16 @@
- Enable hooks: `pre-commit install` (clang-format + detect-secrets + docs link/TOC checks)
- Docs linter (all docs): `python3 tools/docs/check_docs.py --mode link` and `--mode toc`
- Pre-commit (changed files): `pre-commit run --all-files docs-link-check` and `docs-toc-check`
- 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`
Comment on lines +21 to +23

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)

Add blank lines around sub-list to satisfy markdownlint (MD032).

Run make md-fix or insert blank lines before/after the marked bullets.

- - 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`
+
📝 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
- 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`
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

21-21: Lists should be surrounded by blank lines

(MD032, blanks-around-lists)

🤖 Prompt for AI Agents
In AGENTS.md around lines 21 to 23, the nested sub-list lacks blank lines which
triggers markdownlint MD032; add a blank line before the first sub-list item and
a blank line after the last sub-list item (i.e., ensure there is an empty line
separating the preceding paragraph/bullet and the sub-list, and another empty
line after the sub-list) so the sub-list is visually separated and passes
md-lint.


## Coding Style & Naming Conventions
- Language: C23 with warnings-as-errors; no VLAs or shadowing; explicit prototypes.
- Formatting: `.clang-format` (LLVM-based, 4 spaces, 80 cols, pointer alignment right). Pre-commit runs `clang-format`.
- Naming: functions/vars `lower_snake_case` (prefix `gm_`), macros `UPPER_SNAKE`, types end in `_t`, header guards `GITMIND_*`.
- Includes: prefer specific headers; order/regroup per `.clang-format`.
- Public headers must be umbrella-safe: compile standalone, correct include order, stable header guards, and `extern "C"` when included from C++.

## Testing Guidelines
- Unit tests live in `core/tests/unit/` as `test_<module>.c`. Keep deterministic and isolated.
Expand All @@ -33,14 +37,17 @@
## Commit & Pull Request Guidelines
- Conventional commits: `type(scope): description` (e.g., `fix(core/cbor): handle null keys`). Reference issues (`Fixes #123`).
- PRs must describe changes, link issues, include a short test plan, pass CI, and introduce no new clang-tidy warnings (`./tools/docker-clang-tidy.sh`). Update docs when applicable.
- Code review (CodeRabbit): Keep `.coderabbit.yml` updated. Prefer summary reviews, limit per-line comments on docs. If rejecting a suggestion, add a note under `docs/code-reviews/rejected-suggestions/{commit}_{branch}_{PR#}_{suggestion}.md` with a link to the original comment and rationale.

## Security & Configuration
- Do not commit secrets. Pre-commit runs `detect-secrets` with `.secrets.baseline`.
- Use `.env.example` as a template; never check in real credentials.
- E2E safety: some CI E2E steps require `GITMIND_SAFETY=off` in the container environment.

## Agent-Specific Notes
- Make minimal, focused diffs; avoid drive-by refactors. Match existing patterns in `core/` and headers under `include/`.
- Run build, tests, and lint locally before proposing changes. Keep changes zero-warnings and formatted.
- Prefer OID-first APIs for SHA-agnostic correctness. Use `git_oid` (typedef `gm_oid_t`) in new core interfaces, and compare via `git_oid_cmp`.

## Working Knowledge (for agents)
- Journal-first graph: Edges are CBOR commits under `refs/gitmind/edges/<branch>`; cache lives in `refs/gitmind/cache/<branch>` and is rebuildable (never merged).
Expand All @@ -50,6 +57,25 @@
- Link vs code authors: Edge attribution `author` is the link creator (from `git config` unless provided); code authorship at the chosen commit is recorded separately (per-file last commit author/time) when captured by external tooling.
- Docker hygiene: Images are namespaced/labeled (`gitmind/ci:clang-20`, `gitmind/gauntlet:<compiler>`; label `com.gitmind.project=git-mind`). Use `make docker-clean` to reclaim space safely.
- CI/Tidy nuance: Local builds and tests pass. Clang-tidy in Docker depends on CRoaring headers in the CI image; add a source build step for deterministic results on aarch64 if CI flags it.
- CI path filters: Core build/test workflows are restricted to code paths; doc-only changes do not trigger core builds. Markdown lint runs separately with reduced noise via `.markdownlint.jsonc`.

## Agent Activity Log

2025-09-14
- CI/CD: Added Markdown linting with repo-aligned rules (`.markdownlint.jsonc`), `make md-lint`/`md-fix` targets, and path filters limiting core workflows to code paths. Enabled docker pull retry and set `GITMIND_SAFETY=off` for E2E in the core workflow.
- Header hygiene: Standardized header guards to `GITMIND_*`, added umbrella viability check (public headers compile standalone), and a header guard linter (`tools/quality/check_header_guards.py`) wired via Meson run target.
- OID-first migration: Introduced `typedef git_oid gm_oid_t` and `GM_OID_RAWSZ`. Migrated edges, cache queries, and hooks APIs to OID-first and switched equality to `git_oid_cmp`. Maintained compatibility where needed; CBOR decode backfills OIDs from legacy fields temporarily.
- Journal safety: Base64-encoded CBOR commit messages on write and decoded on read; added strict `gm_snprintf` overflow checks and security-conscious includes.
- CLI fixes: Adjusted `apps/cli` commands for include hygiene, error handling, and consistent porcelain output; freed libgit2 arrays correctly.
- Reviews/PRs: Pushed branches, resolved merge conflicts, and responded to CodeRabbit with summary feedback. Opened a PR for CodeRabbit + markdownlint config changes and updated PRs addressing invalid path errors and core cleanup.

## Next Steps (handoff checklist)
- Complete on-disk cache migration to OID-only storage and naming; ensure rebuild and fallback readers handle both formats or gate with a one-time migration.
- Extend journal CBOR schema to store OIDs explicitly (not only derivable from legacy fields); update reader/writer and consumers.
- Sweep any remaining headers for guard/extern "C" issues and fix items flagged by `lint_header_guards`.
- Expand attributed edge CBOR to include OIDs alongside legacy fields; update cache/journal consumers accordingly.
- Stabilize and merge open PRs (#164, #165, #166, #167) after CI green; incorporate CodeRabbit actionable feedback and document any rejections under `docs/code-reviews/rejected-suggestions/`.
- Add focused tests: journal base64 encode/decode roundtrip, `gm_snprintf` truncation behavior, and OID-based equality/lookup paths in cache and hooks.


## Vision Snapshot
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
16 changes: 8 additions & 8 deletions core/include/gitmind/cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
#include <stdint.h>

#include <git2/types.h>
#include <git2/oid.h>

Comment on lines 11 to 13

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

Do not expose libgit2 from public headers; include project types.

gm_oid_t comes from gitmind/types.h; avoid leaking <git2/oid.h> in public API.

Apply this diff:

-#include <git2/types.h>
-#include <git2/oid.h>
+#include <git2/types.h>
+#include "gitmind/types.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/types.h>
#include <git2/oid.h>
#include <git2/types.h>
#include "gitmind/types.h"
🤖 Prompt for AI Agents
In core/include/gitmind/cache.h around lines 11 to 13, the header is exposing
libgit2 by including <git2/oid.h>; replace that include with the project type
header that defines gm_oid_t (e.g., include "gitmind/types.h" or the appropriate
project header) so the public API uses gm_oid_t instead of leaking libgit2
types; remove the <git2/oid.h> include and add the project header import, then
rebuild to ensure no undefined type errors.

#include "gitmind/context.h"
#include "gitmind/result.h"

#ifdef __cplusplus
extern "C" {
Expand All @@ -30,7 +30,7 @@ extern "C" {
#define GM_CACHE_SHARD_BITS 8 /* 2 hex chars = 256 shards */
#define GM_CACHE_REF_PREFIX "refs/gitmind/cache/"
#define GM_CACHE_BRANCH_NAME_SIZE 64 /* Maximum branch name length */
#define GM_CACHE_OID_STRING_SIZE 41 /* Git OID as string + null terminator */
#define GM_CACHE_OID_STRING_SIZE (GIT_OID_HEXSZ + 1) /* OID hex + NUL */

/* Cache result containing edge IDs matching a query */
typedef struct {
Expand Down Expand Up @@ -65,24 +65,24 @@ int gm_cache_init(void);
int gm_cache_rebuild(gm_context_t *ctx, const char *branch, bool force_full);

/**
* Query edges by source SHA (forward traversal)
* Query edges by source OID (forward traversal)
* @param ctx Git-mind context containing repository
* @param src_sha Source SHA bytes (20 bytes)
* @param src_oid Source object ID
* @param result Output result structure
* @return GM_OK on success, error code on failure
*/
int gm_cache_query_fanout(gm_context_t *ctx, const char *branch, const uint8_t *src_sha,
int gm_cache_query_fanout(gm_context_t *ctx, const char *branch, const gm_oid_t *src_oid,
gm_cache_result_t *result);

/**
* Query edges by target SHA (reverse traversal)
* Query edges by target OID (reverse traversal)
* @param ctx Git-mind context containing repository
* @param branch Branch name to query
* @param tgt_sha Target SHA bytes (20 bytes)
* @param tgt_oid Target object ID
* @param result Output result structure
* @return GM_OK on success, error code on failure
*/
int gm_cache_query_fanin(gm_context_t *ctx, const char *branch, const uint8_t *tgt_sha,
int gm_cache_query_fanin(gm_context_t *ctx, const char *branch, const gm_oid_t *tgt_oid,
gm_cache_result_t *result);

/**
Expand Down
6 changes: 3 additions & 3 deletions core/include/gitmind/cache/cache.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/* SPDX-License-Identifier: LicenseRef-MIND-UCAL-1.0 */
/* © 2025 J. Kirby Ross / Neuroglyph Collective */

#ifndef GM_CACHE_H
#define GM_CACHE_H
#ifndef GITMIND_CACHE_CACHE_H
#define GITMIND_CACHE_CACHE_H

#include <git2/types.h>

Expand Down Expand Up @@ -75,4 +75,4 @@ void gm_cache_result_free(gm_cache_result_t *result);
int gm_cache_stats(git_repository *repo, const char *branch,
uint64_t *edge_count, uint64_t *cache_size_bytes);

#endif /* GM_CACHE_H */
#endif /* GITMIND_CACHE_CACHE_H */
35 changes: 35 additions & 0 deletions core/include/gitmind/cbor/keys.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/* SPDX-License-Identifier: LicenseRef-MIND-UCAL-1.0 */
/* © 2025 J. Kirby Ross / Neuroglyph Collective */

#ifndef GITMIND_CBOR_KEYS_H
#define GITMIND_CBOR_KEYS_H

/* Common CBOR keys for edge encodings */

/* Legacy/basic edge fields */
#define GM_CBOR_KEY_SRC_SHA 0
#define GM_CBOR_KEY_TGT_SHA 1
#define GM_CBOR_KEY_REL_TYPE 2
#define GM_CBOR_KEY_CONFIDENCE 3
#define GM_CBOR_KEY_TIMESTAMP 4
#define GM_CBOR_KEY_SRC_PATH 5
#define GM_CBOR_KEY_TGT_PATH 6
#define GM_CBOR_KEY_ULID 7

/* OID-first additions (raw bytes of length GM_OID_RAWSZ) */
#define GM_CBOR_KEY_SRC_OID 8
#define GM_CBOR_KEY_TGT_OID 9

/* Attributed extras */
#define GM_CBOR_KEY_SOURCE_TYPE 10
#define GM_CBOR_KEY_AUTHOR 11
#define GM_CBOR_KEY_SESSION 12
#define GM_CBOR_KEY_FLAGS 13
#define GM_CBOR_KEY_LANE 14

/* Field counts for writers */
#define GM_CBOR_EDGE_FIELDS_TOTAL 10 /* legacy 8 + 2 OID fields */
#define GM_CBOR_ATTR_EDGE_FIELDS_TOTAL 15 /* edge total + 5 attribution fields */

Comment on lines +30 to +33

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

Derive field-count macros from highest key to prevent drift.

Avoid hand-maintaining totals; make them follow the last key automatically.

-#define GM_CBOR_EDGE_FIELDS_TOTAL       10  /* legacy 8 + 2 OID fields */
-#define GM_CBOR_ATTR_EDGE_FIELDS_TOTAL  15  /* edge total + 5 attribution fields */
+#define GM_CBOR_EDGE_FIELDS_TOTAL       (GM_CBOR_KEY_TGT_OID + 1)
+#define GM_CBOR_ATTR_EDGE_FIELDS_TOTAL  (GM_CBOR_KEY_LANE + 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
/* Field counts for writers */
#define GM_CBOR_EDGE_FIELDS_TOTAL 10 /* legacy 8 + 2 OID fields */
#define GM_CBOR_ATTR_EDGE_FIELDS_TOTAL 15 /* edge total + 5 attribution fields */
/* Field counts for writers */
#define GM_CBOR_EDGE_FIELDS_TOTAL (GM_CBOR_KEY_TGT_OID + 1)
#define GM_CBOR_ATTR_EDGE_FIELDS_TOTAL (GM_CBOR_KEY_LANE + 1)
🤖 Prompt for AI Agents
In core/include/gitmind/cbor/keys.h around lines 30 to 33, the fixed numeric
macros GM_CBOR_EDGE_FIELDS_TOTAL and GM_CBOR_ATTR_EDGE_FIELDS_TOTAL are
hand-maintained and can drift; change them to be derived from the highest key
macro instead (e.g. use the last edge key macro + 1 for total, and then add the
5 attribution fields for the attr total). Update the macros to compute totals
from the highest key symbol (replace literal 10 and 15 with expressions like
(GM_CBOR_EDGE_FIELD_LAST + 1) and ((GM_CBOR_EDGE_FIELD_LAST + 1) + 5)), and
adjust the comment to explain they are derived, not hand-maintained.

#endif /* GITMIND_CBOR_KEYS_H */

2 changes: 1 addition & 1 deletion core/include/gitmind/constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
/* Cache system constants */
#define BITS_PER_HEX_CHAR 4
#define HEX_CHARS_PER_BYTE 2
#define SHA_HEX_SIZE (GM_SHA1_SIZE * HEX_CHARS_PER_BYTE + 1)
#define SHA_HEX_SIZE (GM_OID_RAWSZ * HEX_CHARS_PER_BYTE + 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

Rename to OID-centric macro; keep backward-compat alias.

The size now depends on OID raw size. Rename for clarity and define a compat alias to avoid confusion during migration.

-#define SHA_HEX_SIZE (GM_OID_RAWSZ * HEX_CHARS_PER_BYTE + 1)
+#define OID_HEX_SIZE (GM_OID_RAWSZ * HEX_CHARS_PER_BYTE + 1)
+/* Back-compat: remove after all callsites migrate */
+#define SHA_HEX_SIZE OID_HEX_SIZE
📝 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
#define SHA_HEX_SIZE (GM_OID_RAWSZ * HEX_CHARS_PER_BYTE + 1)
#define OID_HEX_SIZE (GM_OID_RAWSZ * HEX_CHARS_PER_BYTE + 1)
/* Back-compat: remove after all callsites migrate */
#define SHA_HEX_SIZE OID_HEX_SIZE
🤖 Prompt for AI Agents
In core/include/gitmind/constants.h around line 35, rename the macro
SHA_HEX_SIZE to an OID-centric name (e.g., OID_HEX_SIZE or GM_OID_HEX_SIZE) and
define it using the existing expression (GM_OID_RAWSZ * HEX_CHARS_PER_BYTE + 1);
then add a backward-compatibility alias that defines SHA_HEX_SIZE to the new
OID-centric macro so old code still compiles. Ensure the new macro is placed
where other related size macros live and that the alias follows immediately
after the new definition.

#define ZERO_SHA_STRING "0000000000000000000000000000000000000000"
Comment on lines +35 to 36

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

❓ Verification inconclusive

ZERO_SHA_STRING is SHA‑1 length; breaks with SHA‑256 OIDs.

Using a fixed 40-‘0’ string is inconsistent with OID‑agnostic sizing and risks truncation/semantics drift. Prefer generating zero OID strings at use sites based on GIT_OID_HEXSZ (see suggested fix in builder.c).


Replace hard-coded ZERO_SHA_STRING with OID-size-aware generation

ZERO_SHA_STRING is a hard-coded 40-'0' SHA‑1 value and contradicts the OID-agnostic SHA_HEX_SIZE macro; this will break for larger OIDs (e.g., SHA‑256). File: core/include/gitmind/constants.h, lines 35–36.

#define SHA_HEX_SIZE (GM_OID_RAWSZ * HEX_CHARS_PER_BYTE + 1)
#define ZERO_SHA_STRING "0000000000000000000000000000000000000000"

Action: remove the fixed ZERO_SHA_STRING and instead generate zero OID strings from SHA_HEX_SIZE (or compute from GM_OID_RAWSZ * HEX_CHARS_PER_BYTE) at use sites, or provide a small helper that returns a null-terminated zero OID string of the correct length.

🤖 Prompt for AI Agents
In core/include/gitmind/constants.h around lines 35 to 36, replace the
hard-coded 40-character ZERO_SHA_STRING with an OID-size-aware approach: remove
the fixed macro and either provide a small inline helper function or a macro
that builds a null-terminated string of GM_OID_RAWSZ * HEX_CHARS_PER_BYTE '0'
characters using SHA_HEX_SIZE, and update call sites to use that helper (or
compute GM_OID_RAWSZ * HEX_CHARS_PER_BYTE at use) so the zero-oid string length
matches the configured OID size.

#define EDGE_MAP_BUCKETS 1024
#define DIR_PERMS_NORMAL 0755
Expand Down
6 changes: 4 additions & 2 deletions core/include/gitmind/edge.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@ typedef struct gm_context gm_context_t;
* Edge structure representing a directed relationship between two git objects
*/
typedef struct gm_edge {
uint8_t src_sha[GM_SHA1_SIZE]; /**< Source object SHA-1 */
uint8_t tgt_sha[GM_SHA1_SIZE]; /**< Target object SHA-1 */
uint8_t src_sha[GM_SHA1_SIZE]; /**< Source object SHA-1 (legacy) */
uint8_t tgt_sha[GM_SHA1_SIZE]; /**< Target object SHA-1 (legacy) */
gm_oid_t src_oid; /**< Source object OID (preferred) */
gm_oid_t tgt_oid; /**< Target object OID (preferred) */
Comment on lines +33 to +36

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

Public struct growth: confirm ABI policy or gate behind version bump

Adding fields to a public struct changes its size/layout and breaks ABI for consumers. If ABI stability is required, either bump the SONAME/major version and document the break or make gm_edge_t opaque with accessors. At minimum, publish a migration note.

Run to find potential size-sensitive usage:


🏁 Script executed:

#!/bin/bash
rg -nP '\bsizeof\s*\(\s*gm_edge_t\s*\)|gm_edge_encode_cbor|gm_edge_decode_cbor|memcpy\s*\([^,]+,\s*&\s*\w*edge' -C2

Length of output: 14211


Public-ABI break: gm_edge_t enlarged — bump SONAME or make opaque

Adding fields changes sizeof(gm_edge_t) and will break callers and code that assume a fixed-size POD (memcpy/memset/alloc). Evidence in tree: core/src/edge/edge.c:45 (memset(..., sizeof(gm_edge_t))), docs/architecture/attribution-integration-guide.md:119-121 (memcpy(&edge,&legacy_edge,sizeof(gm_edge_t))), core/src/journal/writer.c:298 (journal_append_generic(..., sizeof(gm_edge_t), ...)), core/src/hooks/augment.c:119 (malloc(... * sizeof(gm_edge_t))), core/src/cache/query.c:206-209,281-283 (memcpy/malloc), and the public header core/include/gitmind/edge.h.

Action required: either bump the SONAME/major version and publish a migration note, or make gm_edge_t opaque and add accessors—then update all memcpy/memset/sizeof/alloc sites, tests, and docs to use the new API.

🤖 Prompt for AI Agents
core/include/gitmind/edge.h lines 33-36: the added fields enlarge gm_edge_t and
break the public ABI; you must either (A) bump SONAME/major and publish a
migration note or (B) make gm_edge_t opaque and provide accessors—do not leave
the public struct changed. To fix via the opaque-struct route, move the
gm_edge_t definition from the public header into core/src/edge/edge.c, expose a
forward declaration in core/include/gitmind/edge.h, add constructor/destructor
(e.g., gm_edge_new/free), explicit getters/setters for every field (src/tgt
OID/SHA and any other members), and add helper APIs for
copying/serializing/deserializing and for retrieving a stable size if needed;
then update every site that uses sizeof/gm_edge_t, memcpy, memset, malloc
(listed in the review) to use the new APIs (use gm_edge_new + setters,
gm_edge_copy, gm_edge_serialize/journal_append helpers, or an accessor for a
packed legacy representation), and update tests/docs accordingly. If you choose
the SONAME bump instead, increment the library major/SONAME, update packaging
and release notes with a migration guide showing how to map old memcpy/sizeof
usage to the new struct layout, and run tests to ensure consumers rebuild
against the new ABI.

uint16_t rel_type; /**< Relationship type */
uint16_t confidence; /**< Confidence (IEEE-754 half float) */
uint64_t timestamp; /**< Creation time (Unix millis) */

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

Timestamp units mismatch (docs vs. impl)

Comment says “Unix millis”, but augment.c initializes via time(NULL) (seconds). Align units or fix the impl to millis; otherwise sorting and TTLs will be wrong.

🤖 Prompt for AI Agents
In core/include/gitmind/edge.h around line 39, the comment says "Creation time
(Unix millis)" but the implementation initializes timestamp with time(NULL)
(seconds); to fix, make units consistent either by changing the comment to "Unix
seconds" if seconds are intended, or (preferred) change the initialization in
augment.c to set timestamp in milliseconds (e.g., obtain current time with
clock_gettime/gettimeofday and convert to uint64_t milliseconds) and update any
related code/tests that assume seconds; ensure the header comment,
initialization code, and any consumers all use the same millisecond unit.

Expand Down
40 changes: 38 additions & 2 deletions core/include/gitmind/edge_attributed.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,10 @@ typedef enum {
*/
typedef struct gm_edge_attributed {
/* Base edge fields */
uint8_t src_sha[GM_SHA1_SIZE]; /**< Source object SHA-1 */
uint8_t tgt_sha[GM_SHA1_SIZE]; /**< Target object SHA-1 */
uint8_t src_sha[GM_SHA1_SIZE]; /**< Source object SHA-1 (legacy) */
uint8_t tgt_sha[GM_SHA1_SIZE]; /**< Target object SHA-1 (legacy) */
gm_oid_t src_oid; /**< Source object OID (preferred) */
gm_oid_t tgt_oid; /**< Target object OID (preferred) */
uint16_t rel_type; /**< Relationship type */
Comment on lines +41 to 45

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)

Add lane aliases used by tests to avoid enum drift.

Tests reference GM_LANE_DEFAULT and GM_LANE_ANALYSIS; add synonyms to keep API stable.

Apply:

 typedef enum {
     GM_LANE_PRIMARY = 0,    /**< Primary knowledge lane */
     GM_LANE_EXPLORATION = 1,/**< Exploratory connections */
     GM_LANE_REVIEW = 2,     /**< Under review */
-    GM_LANE_ARCHIVED = 3    /**< Archived/deprecated */
+    GM_LANE_ARCHIVED = 3,   /**< Archived/deprecated */
+    /* Aliases for compatibility */
+    GM_LANE_DEFAULT = GM_LANE_PRIMARY,
+    GM_LANE_ANALYSIS = GM_LANE_EXPLORATION
 } gm_lane_type_t;

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

🤖 Prompt for AI Agents
In core/include/gitmind/edge_attributed.h around lines 41 to 45, tests expect
GM_LANE_DEFAULT and GM_LANE_ANALYSIS symbols but the enum values have drifted;
add stable aliases by defining GM_LANE_DEFAULT and GM_LANE_ANALYSIS as synonyms
of the current lane enum values (using the same style as the header: either
#define GM_LANE_DEFAULT <existing_enum_value> and #define GM_LANE_ANALYSIS
<existing_enum_value> or static const enum entries if enums are extended); place
the aliases next to the lane enum declaration with brief comments so tests keep
working without changing existing enum order.

uint16_t confidence; /**< Confidence (IEEE-754 half float) */
uint64_t timestamp; /**< Creation time (Unix millis) */
Comment on lines 45 to 47

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

Docs: confidence field isn’t IEEE‑754 f16.

Update comments to reflect fixed‑point scaling (1.0→0x3C00) or switch implementation to true half‑float. Recommend doc update for now.

Apply:

-    uint16_t confidence;                /**< Confidence (IEEE-754 half float) */
+    uint16_t confidence;                /**< Confidence (fixed-point; 1.0 -> 0x3C00) */
📝 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
uint16_t rel_type; /**< Relationship type */
uint16_t confidence; /**< Confidence (IEEE-754 half float) */
uint64_t timestamp; /**< Creation time (Unix millis) */
uint16_t rel_type; /**< Relationship type */
uint16_t confidence; /**< Confidence (fixed-point; 1.0 -> 0x3C00) */
uint64_t timestamp; /**< Creation time (Unix millis) */
🤖 Prompt for AI Agents
In core/include/gitmind/edge_attributed.h around lines 45 to 47, the confidence
comment incorrectly states the field is an IEEE‑754 half float; update the
comment to state it is a fixed‑point scaled representation (1.0 maps to 0x3C00)
and document the scaling/interpretation (e.g., stored as a 16‑bit fixed
representation where 0x3C00 == 1.0) so callers know how to convert to/from
floating point; alternatively note that switching to a true IEEE‑754 f16
implementation is an option, but for now change the comment to reflect
fixed‑point scaling and include a short conversion note.

Expand Down Expand Up @@ -119,6 +121,40 @@ gm_result_void_t gm_edge_attributed_format(const gm_edge_attributed_t *edge,
gm_result_void_t gm_edge_attributed_format_with_attribution(
const gm_edge_attributed_t *edge, char *buffer, size_t len);

/**
* Encode attributed edge to CBOR (OID-first; includes legacy fields for compat).
*
* @param edge Edge to encode
* @param buffer Output buffer
* @param len In: buffer size, Out: bytes written
* @return Result indicating success or error
*/
gm_result_void_t gm_edge_attributed_encode_cbor(const gm_edge_attributed_t *edge,
uint8_t *buffer, size_t *len);

/**
* Decode attributed edge from CBOR.
*
* @param buffer CBOR data
* @param len Buffer length
* @return Result with decoded edge on success
*/
gm_result_edge_attributed_t gm_edge_attributed_decode_cbor(const uint8_t *buffer,
size_t len);

/**
* Decode attributed edge from CBOR and return bytes consumed.
*
* @param buffer CBOR data
* @param len Buffer length
* @param edge_out Output edge
* @param consumed Bytes consumed
* @return GM_OK on success or error code
*/
int gm_edge_attributed_decode_cbor_ex(const uint8_t *buffer, size_t len,
gm_edge_attributed_t *edge_out,
size_t *consumed);

#ifdef __cplusplus
}
#endif
Expand Down
68 changes: 49 additions & 19 deletions core/include/gitmind/hooks/augment.h
Original file line number Diff line number Diff line change
@@ -1,21 +1,33 @@
/* SPDX-License-Identifier: LicenseRef-MIND-UCAL-1.0 */
/* © 2025 J. Kirby Ross / Neuroglyph Collective */

#ifndef GM_AUGMENT_H
#define GM_AUGMENT_H
#ifndef GITMIND_AUGMENT_H
#define GITMIND_AUGMENT_H

#include "gitmind.h"
#include "gitmind/context.h"
#include "gitmind/edge.h"

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <git2/types.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.

🛠️ Refactor suggestion

⚠️ Potential issue

Public API: use git_oid (hash‑agnostic) and gm_ prefix; add required libgit2 headers.

Avoid hard‑coding 20‑byte SHA‑1 and follow project naming. Switch to git_oid, add the missing libgit2 headers, and prefix functions with gm_.

Apply:

 #include <stdint.h>
 #include <git2/types.h>
+#include <git2/oid.h>
+#include <git2/repository.h>
@@
-/* Get blob SHA for a file at a specific commit
+/* Get blob OID for a file at a specific commit
@@
- * @param sha_out   Output buffer for 20-byte SHA-1
+ * @param oid_out   Output object id (git_oid)
@@
-int get_blob_sha(git_repository *repo, const char *commit_ref,
-                 const char *file_path, uint8_t *sha_out);
+int gm_get_blob_oid(git_repository *repo, const char *commit_ref,
+                    const char *file_path, git_oid *oid_out);
@@
-/* Find recent edges with given source blob
+/* Find recent edges with given source blob
@@
- * @param src_sha   Source blob SHA to search for
+ * @param src_oid   Source blob OID to search for
@@
-int find_edges_by_source(gm_context_t *ctx, const uint8_t *src_sha,
-                         gm_edge_t **edges_out, size_t *count_out);
+int gm_find_edges_by_source(gm_context_t *ctx, const git_oid *src_oid,
+                            gm_edge_t **edges_out, size_t *count_out);
@@
-/* Create AUGMENTS edge between two blob versions
+/* Create AUGMENTS edge between two blob versions
@@
- * @param old_sha   Old blob SHA (source)
- * @param new_sha   New blob SHA (target)
+ * @param old_oid   Old blob OID (source)
+ * @param new_oid   New blob OID (target)
@@
-int create_augments_edge(gm_context_t *ctx, const uint8_t *old_sha,
-                         const uint8_t *new_sha, const char *file_path);
+int gm_create_augments_edge(gm_context_t *ctx, const git_oid *old_oid,
+                            const git_oid *new_oid, const char *file_path);
@@
-int process_changed_file(gm_context_t *ctx, git_repository *repo,
-                         const char *file_path);
+int gm_process_changed_file(gm_context_t *ctx, git_repository *repo,
+                            const char *file_path);
@@
-int is_merge_commit(git_repository *repo, bool *is_merge);
+int gm_is_merge_commit(git_repository *repo, bool *is_merge);

Optionally keep backward compatibility with deprecated aliases (outside this hunk):

/* Deprecated: remove after one release */
#define get_blob_sha(repo, ref, path, sha_out) \
    gm_get_blob_oid((repo), (ref), (path), (sha_out))
#define find_edges_by_source(ctx, sha, edges_out, count_out) \
    gm_find_edges_by_source((ctx), (sha), (edges_out), (count_out))
#define create_augments_edge(ctx, old_sha, new_sha, path) \
    gm_create_augments_edge((ctx), (old_sha), (new_sha), (path))
#define process_changed_file gm_process_changed_file
#define is_merge_commit gm_is_merge_commit

Also applies to: 28-38, 41-49, 50-59, 61-70, 71-77

Comment on lines +7 to 13

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 transitive includes; add required headers.

Include gm types (for gm_oid_t size) and string.h (needed by the deprecated adapters); prefer explicit libgit2 header for repository.

Apply:

 #include "gitmind/context.h"
 #include "gitmind/edge.h"
+#include "gitmind/types.h"
@@
 #include <stdint.h>
 #include <git2/types.h>
+#include <git2/repository.h>
+#include <string.h>
🤖 Prompt for AI Agents
In core/include/gitmind/hooks/augment.h around lines 7 to 13, avoid relying on
transitive includes: add the explicit header that defines gm types (so gm_oid_t
size is available), include <string.h> because deprecated adapters in this
header use string.h functions, and replace or add the specific libgit2
repository header (e.g. <git2/repository.h>) rather than relying on the
transitive <git2/types.h>; update include list accordingly so all required types
are declared directly.

#ifdef __cplusplus
extern "C" {
// keep C linkage open until end
#endif

/* Constants */
#define MAX_CHANGED_FILES 50 /* Skip if more files changed */
#define LOOKBACK_LIMIT 200 /* Max edges to scan */
#define HOOK_TIMEOUT_MS 500 /* Abort if taking too long */
#define MAX_PATH_LENGTH 4096 /* Maximum file path length */
/* Constants (public, prefixed) */

#define GM_AUGMENT_MAX_CHANGED_FILES 50 /* Skip if more files changed */
#define GM_AUGMENT_LOOKBACK_LIMIT 200 /* Max edges to scan */
#define GM_AUGMENT_HOOK_TIMEOUT_MS 500 /* Abort if taking too long */
#define GM_AUGMENT_MAX_PATH_LENGTH 4096 /* Maximum file path length */

Comment on lines +21 to +25

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)

Unify path-length constant with global limit.

Prevent drift from GM_PATH_MAX used in core/src.

Apply:

-#define GM_AUGMENT_MAX_PATH_LENGTH 4096 /* Maximum file path length */
+#define GM_AUGMENT_MAX_PATH_LENGTH GM_PATH_MAX /* Keep in sync with global path limit */
📝 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
#define GM_AUGMENT_MAX_CHANGED_FILES 50 /* Skip if more files changed */
#define GM_AUGMENT_LOOKBACK_LIMIT 200 /* Max edges to scan */
#define GM_AUGMENT_HOOK_TIMEOUT_MS 500 /* Abort if taking too long */
#define GM_AUGMENT_MAX_PATH_LENGTH 4096 /* Maximum file path length */
#define GM_AUGMENT_MAX_CHANGED_FILES 50 /* Skip if more files changed */
#define GM_AUGMENT_LOOKBACK_LIMIT 200 /* Max edges to scan */
#define GM_AUGMENT_HOOK_TIMEOUT_MS 500 /* Abort if taking too long */
#define GM_AUGMENT_MAX_PATH_LENGTH GM_PATH_MAX /* Keep in sync with global path limit */
🤖 Prompt for AI Agents
In core/include/gitmind/hooks/augment.h around lines 21-25, the local
GM_AUGMENT_MAX_PATH_LENGTH macro should be unified with the global GM_PATH_MAX
to avoid drift; remove the GM_AUGMENT_MAX_PATH_LENGTH definition and instead
include or reference the header that defines GM_PATH_MAX (e.g., the core/src
header where GM_PATH_MAX is declared) so the hook uses GM_PATH_MAX directly;
ensure the include guard and include path are correct and update any uses of
GM_AUGMENT_MAX_PATH_LENGTH in this header or its consumers to use GM_PATH_MAX.

/* Backward-compat (deprecated): old macro names */
#define MAX_CHANGED_FILES GM_AUGMENT_MAX_CHANGED_FILES
#define LOOKBACK_LIMIT GM_AUGMENT_LOOKBACK_LIMIT
#define HOOK_TIMEOUT_MS GM_AUGMENT_HOOK_TIMEOUT_MS
#define MAX_PATH_LENGTH GM_AUGMENT_MAX_PATH_LENGTH
Comment on lines +26 to +30

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)

Guard legacy macro aliases to avoid redefinition.

Apply:

 /* Backward-compat (deprecated): old macro names */
-#define MAX_CHANGED_FILES GM_AUGMENT_MAX_CHANGED_FILES
-#define LOOKBACK_LIMIT GM_AUGMENT_LOOKBACK_LIMIT
-#define HOOK_TIMEOUT_MS GM_AUGMENT_HOOK_TIMEOUT_MS
-#define MAX_PATH_LENGTH GM_AUGMENT_MAX_PATH_LENGTH
+#ifndef MAX_CHANGED_FILES
+#define MAX_CHANGED_FILES GM_AUGMENT_MAX_CHANGED_FILES
+#endif
+#ifndef LOOKBACK_LIMIT
+#define LOOKBACK_LIMIT GM_AUGMENT_LOOKBACK_LIMIT
+#endif
+#ifndef HOOK_TIMEOUT_MS
+#define HOOK_TIMEOUT_MS GM_AUGMENT_HOOK_TIMEOUT_MS
+#endif
+#ifndef MAX_PATH_LENGTH
+#define MAX_PATH_LENGTH GM_AUGMENT_MAX_PATH_LENGTH
+#endif
📝 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
/* Backward-compat (deprecated): old macro names */
#define MAX_CHANGED_FILES GM_AUGMENT_MAX_CHANGED_FILES
#define LOOKBACK_LIMIT GM_AUGMENT_LOOKBACK_LIMIT
#define HOOK_TIMEOUT_MS GM_AUGMENT_HOOK_TIMEOUT_MS
#define MAX_PATH_LENGTH GM_AUGMENT_MAX_PATH_LENGTH
/* Backward-compat (deprecated): old macro names */
#ifndef MAX_CHANGED_FILES
#define MAX_CHANGED_FILES GM_AUGMENT_MAX_CHANGED_FILES
#endif
#ifndef LOOKBACK_LIMIT
#define LOOKBACK_LIMIT GM_AUGMENT_LOOKBACK_LIMIT
#endif
#ifndef HOOK_TIMEOUT_MS
#define HOOK_TIMEOUT_MS GM_AUGMENT_HOOK_TIMEOUT_MS
#endif
#ifndef MAX_PATH_LENGTH
#define MAX_PATH_LENGTH GM_AUGMENT_MAX_PATH_LENGTH
#endif
🤖 Prompt for AI Agents
In core/include/gitmind/hooks/augment.h around lines 26 to 30, the legacy macro
aliases (MAX_CHANGED_FILES, LOOKBACK_LIMIT, HOOK_TIMEOUT_MS, MAX_PATH_LENGTH)
are unguarded and may cause redefinition warnings or errors; wrap each alias in
an appropriate #ifndef/#define/#endif guard (e.g., #ifndef MAX_CHANGED_FILES
then #define MAX_CHANGED_FILES GM_AUGMENT_MAX_CHANGED_FILES ... #endif) so the
legacy names are only defined if not already present.


/* Get blob SHA for a file at a specific commit
*
Expand All @@ -25,19 +37,19 @@
* @param sha_out Output buffer for 20-byte SHA-1
* @return 0 on success, error code otherwise
*/
int get_blob_sha(git_repository *repo, const char *commit_ref,
const char *file_path, uint8_t *sha_out);
int gm_hook_get_blob_sha(git_repository *repo, const char *commit_ref,
const char *file_path, gm_oid_t *sha_out);

/* Find recent edges with given source blob
*
* @param ctx git-mind context
* @param src_sha Source blob SHA to search for
* @param edges_out Output array of matching edges (caller must free)
* @param edges_out Output array of matching edges (caller must free with free())
* @param count_out Number of edges found
* @return 0 on success, error code otherwise
*/
int find_edges_by_source(gm_context_t *ctx, const uint8_t *src_sha,
gm_edge_t **edges_out, size_t *count_out);
int gm_hook_find_edges_by_source(gm_context_t *ctx, const gm_oid_t *src_oid,
gm_edge_t **edges_out, size_t *count_out);

/* Create AUGMENTS edge between two blob versions
*
Expand All @@ -47,8 +59,8 @@ int find_edges_by_source(gm_context_t *ctx, const uint8_t *src_sha,
* @param file_path Path to file (for human readability)
* @return 0 on success, error code otherwise
*/
int create_augments_edge(gm_context_t *ctx, const uint8_t *old_sha,
const uint8_t *new_sha, const char *file_path);
int gm_hook_create_augments_edge(gm_context_t *ctx, const gm_oid_t *old_oid,
const gm_oid_t *new_oid, const char *file_path);

/* Process a single changed file
*
Expand All @@ -57,15 +69,33 @@ int create_augments_edge(gm_context_t *ctx, const uint8_t *old_sha,
* @param file_path Path to changed file
* @return 0 on success, error code otherwise
*/
int process_changed_file(gm_context_t *ctx, git_repository *repo,
const char *file_path);
int gm_hook_process_changed_file(gm_context_t *ctx, git_repository *repo,
const char *file_path);

/* Check if this is a merge commit
*
* @param repo Git repository
* @param is_merge Output: true if merge commit
* @return 0 on success, error code otherwise
*/
int is_merge_commit(git_repository *repo, bool *is_merge);
int gm_hook_is_merge_commit(git_repository *repo, bool *is_merge);

/* Backward-compatibility macros (deprecated) */
#define get_blob_sha gm_hook_get_blob_sha
#define find_edges_by_source gm_hook_find_edges_by_source
#define create_augments_edge gm_hook_create_augments_edge
#define process_changed_file gm_hook_process_changed_file
#define is_merge_commit gm_hook_is_merge_commit

Comment on lines +83 to +89

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

Deprecated macro remaps are unsafe: signatures changed

These macros map old names to new functions but the parameter types differ (uint8_t* vs gm_oid_t*), breaking source compatibility. Replace with inline adapters and drop the macros.

-/* Backward-compatibility macros (deprecated) */
-#define get_blob_sha gm_hook_get_blob_sha
-#define find_edges_by_source gm_hook_find_edges_by_source
-#define create_augments_edge gm_hook_create_augments_edge
-#define process_changed_file gm_hook_process_changed_file
-#define is_merge_commit gm_hook_is_merge_commit
+/* Backward-compatibility adapters (deprecated: remove next release) */
+#include <string.h>
+#include <git2/oid.h>
+static inline int get_blob_sha(git_repository *repo, const char *commit_ref,
+                               const char *file_path, uint8_t *sha_out) {
+    gm_oid_t oid;
+    int rc = gm_hook_get_blob_sha(repo, commit_ref, file_path, &oid);
+    if (rc != 0) return rc;
+    /* git_oid is raw bytes; copy out */
+    memcpy(sha_out, &oid, GM_OID_RAWSZ);
+    return 0;
+}
+static inline int find_edges_by_source(gm_context_t *ctx, const uint8_t *src_sha,
+                                       gm_edge_t **edges_out, size_t *count_out) {
+    gm_oid_t oid;
+    memcpy(&oid, src_sha, GM_OID_RAWSZ);
+    return gm_hook_find_edges_by_source(ctx, &oid, edges_out, count_out);
+}
+static inline int create_augments_edge(gm_context_t *ctx, const uint8_t *old_sha,
+                                       const uint8_t *new_sha, const char *file_path) {
+    gm_oid_t old_oid, new_oid;
+    memcpy(&old_oid, old_sha, GM_OID_RAWSZ);
+    memcpy(&new_oid, new_sha, GM_OID_RAWSZ);
+    return gm_hook_create_augments_edge(ctx, &old_oid, &new_oid, file_path);
+}
+/* Names without signature changes can stay as aliases */
+#define process_changed_file gm_hook_process_changed_file
+#define is_merge_commit gm_hook_is_merge_commit

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

🤖 Prompt for AI Agents
In core/include/gitmind/hooks/augment.h around lines 77 to 83, the deprecated
macros that remap old names to new functions are unsafe because the parameter
types changed (uint8_t* vs gm_oid_t*); replace the macros with static inline
adapter functions that preserve the old API by accepting the original uint8_t*
parameters, convert or cast them to gm_oid_t* as needed, and call the new
gm_hook_* functions (then remove the macro definitions); ensure adapters have
the same return types and const-correctness as the originals and are guarded
with appropriate deprecation attributes/comments.

/* Preferred names (aliases) */
#define gm_augment_get_blob_sha gm_hook_get_blob_sha
#define gm_augment_find_edges_by_source gm_hook_find_edges_by_source
#define gm_augment_create_augments_edge gm_hook_create_augments_edge
#define gm_augment_process_changed_file gm_hook_process_changed_file
#define gm_augment_is_merge_commit gm_hook_is_merge_commit

#ifdef __cplusplus
}
#endif

#endif /* GM_AUGMENT_H */
#endif /* GITMIND_AUGMENT_H */
9 changes: 9 additions & 0 deletions core/include/gitmind/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include <stddef.h>
#include <stdint.h>
#include <git2/oid.h>

#ifdef __cplusplus
extern "C" {
Expand All @@ -19,6 +20,10 @@ extern "C" {
/* Size constants */
#define GM_SHA1_SIZE 20
#define GM_SHA256_SIZE 32
#ifndef GIT_OID_RAWSZ
#define GIT_OID_RAWSZ 20
#endif
#define GM_OID_RAWSZ GIT_OID_RAWSZ
#define GM_PATH_MAX 256
Comment on lines +23 to 27

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

Guarded fallback for GIT_OID_RAWSZ is fine; add a compile‑time size check

Add a static assert to ensure gm_oid_t matches the configured raw OID size to catch toolchain/header mismatches early.

 #define GM_SHA256_SIZE 32
 #ifndef GIT_OID_RAWSZ
 #define GIT_OID_RAWSZ 20
 #endif
 #define GM_OID_RAWSZ GIT_OID_RAWSZ
+/* Ensure alias size matches configured raw OID size */
+_Static_assert(sizeof(gm_oid_t) == GM_OID_RAWSZ, "gm_oid_t size mismatch");

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

🤖 Prompt for AI Agents
In core/include/gitmind/types.h around lines 23-27, add a compile-time assertion
that the gm_oid_t size equals GM_OID_RAWSZ to detect toolchain/header mismatches
early; implement this using a C11 _Static_assert (or static_assert for C++)
placed after the GM_OID_RAWSZ/Gm_PATH_MAX defines (or immediately after gm_oid_t
is defined) comparing sizeof(gm_oid_t) to GM_OID_RAWSZ, and ensure the code uses
the appropriate language feature/header so the check fails the build if sizes
differ.

#define GM_ULID_SIZE 26
#define GM_FORMAT_BUFFER_SIZE 512
Expand All @@ -37,6 +42,10 @@ typedef enum {
} gm_rel_type_t;

/* Include sub-types */
/**
* OID type (SHA-agnostic). Use instead of raw byte arrays in new code.
*/
typedef git_oid gm_oid_t;

#ifdef __cplusplus
}
Expand Down
Loading