Skip to content

feat: implement git commit context tracing (ctx trace)#53

Merged
josealekhine merged 3 commits intomainfrom
feature/commit-context-tracing
Apr 1, 2026
Merged

feat: implement git commit context tracing (ctx trace)#53
josealekhine merged 3 commits intomainfrom
feature/commit-context-tracing

Conversation

@parlakisik
Copy link
Copy Markdown
Contributor

Link every git commit back to the decisions, tasks, learnings, and sessions that motivated it. git log shows what changed, git blame shows who — ctx trace shows why.

Embed context pointers in git commit trailers via a prepare-commit-msg hook. A new ctx trace command resolves those pointers back to the original reasoning.

New CLI commands:

  • ctx trace [commit] show context for a specific commit
  • ctx trace --last N show recent commits with context
  • ctx trace --json machine-readable JSON output
  • ctx trace file show context trail for a file
  • ctx trace tag manually tag a commit with --note
  • ctx trace hook enable install prepare-commit-msg hook
  • ctx trace hook disable remove the hook

Three-source context detection:

  1. Pending: refs accumulated from ctx add and ctx task complete
  2. Staged: new entries detected in staged .context/ file diffs
  3. Working state: in-progress tasks and CTX_SESSION_ID env var

Storage:
.context/state/pending-context.jsonl accumulated refs, cleared per commit
.context/trace/history.jsonl permanent commit-to-context map
.context/trace/overrides.jsonl manual tags from ctx trace tag

@parlakisik parlakisik requested a review from josealekhine as a code owner April 1, 2026 02:41
@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages bot commented Apr 1, 2026

Deploying ctx with  Cloudflare Pages  Cloudflare Pages

Latest commit: 8655f26
Status: ✅  Deploy successful!
Preview URL: https://29840438.ctx-bhl.pages.dev
Branch Preview URL: https://feature-commit-context-traci.ctx-bhl.pages.dev

View logs

@parlakisik parlakisik force-pushed the feature/commit-context-tracing branch from 4eaf023 to c9f07b1 Compare April 1, 2026 07:01
@parlakisik parlakisik requested a review from bilersan as a code owner April 1, 2026 07:01
@parlakisik parlakisik force-pushed the feature/commit-context-tracing branch from c9f07b1 to 1be7979 Compare April 1, 2026 07:19
@josealekhine
Copy link
Copy Markdown
Member

solid, well-structured feature. Murat clearly understands the codebase conventions. The PR is ready for merge with minor nits.

What looks good

  • Architecture: Clean separation — internal/trace/ is a pure library (types, JSONL, git helpers, resolve), internal/cli/trace/ is the CLI wiring. Follows the existing cmd/ + core/
    pattern used elsewhere.
  • Three-source collection model (pending, staged, working) is well thought out. Deduplication across sources is handled correctly.
  • JSONL storage with generic readJSONL[T]/appendJSONL[T] helpers — clean and reusable.
  • Git hook design: Two-hook approach (prepare-commit-msg injects trailer, post-commit records to history) avoids the pitfall of recording before the commit succeeds. Non-ctx hooks are
    detected and left alone.
  • Test coverage: Tests for pending, history, overrides, collect, resolve, staged, working, plus an integration test in trace_test.go. Good edge cases (empty, missing file, short hash
    matching, dedup).
  • Docs: docs/cli/trace.md and workflow docs updated. Commands.yaml entries present.
  • Lint cleanup: The fmt.Fprintf(&sb, ...) migration from sb.WriteString(fmt.Sprintf(...)) is a nice QF1012 fix — reduces allocations. The gosec G703 nolint annotations are properly
    justified.

Some Nits That I will Address Separately (not merge blockers)

  1. Complete() return value change — adding a third return value (int) to Complete() is a breaking change to the internal API. The MCP handler call sites were updated (good), but anyone
    calling Complete() externally will break. Worth a note in the commit message that this is an internal-only function.
  2. ctx add always records as deps: Bump actions/checkout from 4 to 6 #1 — In add/cmd/root/run.go:80, new decisions/learnings are assumed to be deps: Bump actions/checkout from 4 to 6 #1 because they're prepended. This is fragile if the prepend logic ever changes. A
    comment explaining why is there, but it's a coupling to watch.
  3. RecordCommit reads trailer then truncates pending — If the trailer is empty (e.g. user committed outside the hook), pending refs are silently discarded. This seems intentional but
    worth documenting that pending context is always consumed per-commit, even when no hook runs.
  4. ParsePathArg handles file.go:42-60 but not Windows paths with drive letters like C:\foo. Probably fine for a unix-first tool, just noting it.
  5. ShowLast iterates git log twice (once for the table, once internally per commit via CollectRefsForCommit which reads trailers). For --last 50 this could be slow since each commit
    spawns a git log -1 subprocess. The includeTrailers: true flag in ShowCommit vs false in TraceFile is a good optimization, but ShowLast uses true.
    about ensuring ctx is in PATH.

Verdict

Good to merge. The feature is self-contained, well-tested, follows project conventions, and the docs are complete. The nits above are all minor — none are blockers.

@parlakisik parlakisik force-pushed the feature/commit-context-tracing branch from 1be7979 to ca744b7 Compare April 1, 2026 15:13
@parlakisik
Copy link
Copy Markdown
Contributor Author

/test

Link every git commit back to the decisions, tasks, learnings, and
sessions that motivated it. git log shows what changed, git blame
shows who — ctx trace shows why.

Embed context pointers in git commit trailers via a prepare-commit-msg
hook. A new ctx trace command resolves those pointers back to the
original reasoning.

New CLI commands:
  - ctx trace [commit]          show context for a specific commit
  - ctx trace --last N          show recent commits with context
  - ctx trace --json            machine-readable JSON output
  - ctx trace file <path>       show context trail for a file
  - ctx trace tag <commit>      manually tag a commit with --note
  - ctx trace hook enable       install prepare-commit-msg hook
  - ctx trace hook disable      remove the hook

Three-source context detection:
  1. Pending: refs accumulated from ctx add and ctx task complete
  2. Staged: new entries detected in staged .context/ file diffs
  3. Working state: in-progress tasks and CTX_SESSION_ID env var

Storage:
  .context/state/pending-context.jsonl  accumulated refs, cleared per commit
  .context/trace/history.jsonl          permanent commit-to-context map
  .context/trace/overrides.jsonl        manual tags from ctx trace tag

Also fixes pre-existing lint issues surfaced by upgraded golangci-lint
(gosec G703 path traversal nolint, staticcheck QF1012 Fprintf) and
TestBinaryIntegration symlink resolution on macOS.

Signed-off-by: Murat Parlakisik <parlakisik@gmail.com>
@parlakisik parlakisik force-pushed the feature/commit-context-tracing branch from ca744b7 to 7c47af4 Compare April 1, 2026 16:27
Signed-off-by: Jose Alekhinne <jose@ctx.ist>
Structural fixes applied to the commit context tracing feature (PR #53)
and pre-existing code quality issues surfaced during review.

cmd/core separation:
- Extract Complete() from cmd/complete to core/complete
- Extract initScratchpad, hasEssentialFiles, ensureGitignoreEntries,
  writeGettingStarted from initialize/cmd/root to core/ packages
- Privatize RunAddSilent/RunCompleteSilent → addEntry/completeTask
- Split private functions into own files per convention

Safe I/O:
- Replace os.WriteFile nolint:gosec with io.SafeWriteFile (18 sites)
- Replace os.Open/os.ReadFile nolint:gosec with safe variants
- Replace os.Stat nolint:gosec with io.SafeStat
- Add io.SafeMkdirAll, io.SafeStat, io.SafeFprintf
- Fix readErr shadowing in hook/cmd/root/run.go

i18n pipeline alignment:
- All trace cmd strings through assets/descriptors
- All trace errors through err/trace package
- All trace output through write/trace package
- Hook scripts from Go const to embedded assets (hooks/trace/*.sh)
- flagbind adoption: BoolFlag, BoolFlagP, IntFlagP, StringFlagPDefault
- Magic numbers to config/trace constants
- fmt.Fprintf buffer writes through io.SafeFprintf with warn sink

Performance:
- ShowLast uses includeTrailers=false (avoids N git subprocesses)

Trace library cleanup:
- All exec.Command("git",...) through internal/exec/git.Run
- All magic strings to config constants
- Private functions split to own files per convention
- Proper doc.go blocks on all new packages

Context files:
- CLAUDE.md: deduplicate, align with golden template, fix heading
- AGENTS.md: restore 3-line redirect (was 125 lines of GitNexus)
- AGENT_PLAYBOOK.md: sync golden↔live, add supplementary files table,
  restore missing anti-patterns and validation checklist sections
- Delete dead .context/PROMPT.md and assets/hooks/copilot-instructions.md
- Restore .github/copilot-instructions.md

Pre-existing fixes (own the branch):
- gosec violations in parser/copilot, setup/agents, setup/copilot_cli
- Dead ExtractIndex function removed from load_gate
- Magic relay prefix strings in check_journal and check_ceremony

Signed-off-by: Jose Alekhinne <jose@ctx.ist>
Copy link
Copy Markdown
Member

@josealekhine josealekhine left a comment

Choose a reason for hiding this comment

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

🌮 .

@josealekhine josealekhine merged commit 01bb6e0 into main Apr 1, 2026
12 checks passed
@josealekhine josealekhine deleted the feature/commit-context-tracing branch April 1, 2026 20:49
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