yigraf 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. yigraf-0.1.0/.claude/.gitignore +4 -0
  2. yigraf-0.1.0/.claude/settings.local.json +28 -0
  3. yigraf-0.1.0/.claude/skills/yigraf/SKILL.md +49 -0
  4. yigraf-0.1.0/.github/workflows/release.yml +26 -0
  5. yigraf-0.1.0/.gitignore +29 -0
  6. yigraf-0.1.0/AGENTS.md +7 -0
  7. yigraf-0.1.0/CLAUDE.md +90 -0
  8. yigraf-0.1.0/LICENSE +21 -0
  9. yigraf-0.1.0/PKG-INFO +222 -0
  10. yigraf-0.1.0/README.md +176 -0
  11. yigraf-0.1.0/docs/language-support.md +50 -0
  12. yigraf-0.1.0/pyproject.toml +80 -0
  13. yigraf-0.1.0/scripts/eval/README.md +113 -0
  14. yigraf-0.1.0/scripts/eval/cases.yaml +56 -0
  15. yigraf-0.1.0/scripts/eval/judge.py +180 -0
  16. yigraf-0.1.0/scripts/eval/parse_run.py +140 -0
  17. yigraf-0.1.0/scripts/eval/render_ab.py +119 -0
  18. yigraf-0.1.0/scripts/eval/run_ab.py +299 -0
  19. yigraf-0.1.0/src/yigraf/__init__.py +3 -0
  20. yigraf-0.1.0/src/yigraf/__main__.py +6 -0
  21. yigraf-0.1.0/src/yigraf/artifacts.py +312 -0
  22. yigraf-0.1.0/src/yigraf/astnorm.py +151 -0
  23. yigraf-0.1.0/src/yigraf/cache.py +102 -0
  24. yigraf-0.1.0/src/yigraf/cli.py +626 -0
  25. yigraf-0.1.0/src/yigraf/config.py +143 -0
  26. yigraf-0.1.0/src/yigraf/counters.py +288 -0
  27. yigraf-0.1.0/src/yigraf/drift.py +113 -0
  28. yigraf-0.1.0/src/yigraf/embeddings.py +297 -0
  29. yigraf-0.1.0/src/yigraf/extract.py +166 -0
  30. yigraf-0.1.0/src/yigraf/graph.py +57 -0
  31. yigraf-0.1.0/src/yigraf/hooks.py +268 -0
  32. yigraf-0.1.0/src/yigraf/languages/__init__.py +73 -0
  33. yigraf-0.1.0/src/yigraf/languages/base.py +252 -0
  34. yigraf-0.1.0/src/yigraf/languages/go.py +277 -0
  35. yigraf-0.1.0/src/yigraf/languages/jsts.py +324 -0
  36. yigraf-0.1.0/src/yigraf/languages/python.py +379 -0
  37. yigraf-0.1.0/src/yigraf/languages/resolve.py +42 -0
  38. yigraf-0.1.0/src/yigraf/languages/tags.py +813 -0
  39. yigraf-0.1.0/src/yigraf/memory.py +325 -0
  40. yigraf-0.1.0/src/yigraf/retrieval.py +604 -0
  41. yigraf-0.1.0/src/yigraf/scaffold.py +102 -0
  42. yigraf-0.1.0/tests/conftest.py +24 -0
  43. yigraf-0.1.0/tests/test_artifacts.py +77 -0
  44. yigraf-0.1.0/tests/test_astnorm.py +86 -0
  45. yigraf-0.1.0/tests/test_build.py +199 -0
  46. yigraf-0.1.0/tests/test_cchooks.py +160 -0
  47. yigraf-0.1.0/tests/test_cli.py +32 -0
  48. yigraf-0.1.0/tests/test_config.py +30 -0
  49. yigraf-0.1.0/tests/test_context.py +181 -0
  50. yigraf-0.1.0/tests/test_counters.py +295 -0
  51. yigraf-0.1.0/tests/test_drift.py +96 -0
  52. yigraf-0.1.0/tests/test_embeddings.py +130 -0
  53. yigraf-0.1.0/tests/test_eval_judge.py +76 -0
  54. yigraf-0.1.0/tests/test_eval_parse.py +67 -0
  55. yigraf-0.1.0/tests/test_eval_runab.py +44 -0
  56. yigraf-0.1.0/tests/test_extract.py +123 -0
  57. yigraf-0.1.0/tests/test_graph.py +26 -0
  58. yigraf-0.1.0/tests/test_hooks.py +83 -0
  59. yigraf-0.1.0/tests/test_init.py +47 -0
  60. yigraf-0.1.0/tests/test_language_drift.py +128 -0
  61. yigraf-0.1.0/tests/test_languages.py +435 -0
  62. yigraf-0.1.0/tests/test_memory.py +218 -0
  63. yigraf-0.1.0/tests/test_status.py +91 -0
  64. yigraf-0.1.0/tests/test_tags.py +299 -0
  65. yigraf-0.1.0/tests/test_verbs.py +131 -0
  66. yigraf-0.1.0/uv.lock +1640 -0
  67. yigraf-0.1.0/yigraf/.gitattributes +4 -0
  68. yigraf-0.1.0/yigraf/.gitignore +7 -0
  69. yigraf-0.1.0/yigraf/.local/telemetry.json +78 -0
  70. yigraf-0.1.0/yigraf/cache/structure.json +23783 -0
  71. yigraf-0.1.0/yigraf/config.yaml +38 -0
  72. yigraf-0.1.0/yigraf/graph.json +23425 -0
  73. yigraf-0.1.0/yigraf/index/meta.json +98 -0
  74. yigraf-0.1.0/yigraf/index/vectors.npy +0 -0
  75. yigraf-0.1.0/yigraf/intents/drift-detection.md +12 -0
  76. yigraf-0.1.0/yigraf/intents/enforceable-link.md +11 -0
  77. yigraf-0.1.0/yigraf/intents/hook-surfacing.md +12 -0
  78. yigraf-0.1.0/yigraf/intents/memory-family.md +15 -0
  79. yigraf-0.1.0/yigraf/intents/memory-maturity.md +15 -0
  80. yigraf-0.1.0/yigraf/intents/semantic-recall.md +15 -0
  81. yigraf-0.1.0/yigraf/intents/status-surface.md +15 -0
  82. yigraf-0.1.0/yigraf/intents/structure-index.md +16 -0
  83. yigraf-0.1.0/yigraf/intents/token-cheap-context.md +11 -0
  84. yigraf-0.1.0/yigraf/memory/001-concerns-reuses-the-implements-drift-machinery.md +24 -0
  85. yigraf-0.1.0/yigraf/memory/002-the-first-memory-milestone-captures-agent.md +19 -0
  86. yigraf-0.1.0/yigraf/memory/003-supersession-counters-are-stamped-only-on.md +21 -0
  87. yigraf-0.1.0/yigraf/memory/004-embed-only-memory-and-intent-with.md +24 -0
  88. yigraf-0.1.0/yigraf/memory/005-the-embedding-backend-is-an-optional.md +21 -0
  89. yigraf-0.1.0/yigraf/memory/006-v0-counters-are-local-recomputable-model.md +21 -0
  90. yigraf-0.1.0/yigraf/memory/007-maturity-is-git-derived-survival-commits.md +21 -0
  91. yigraf-0.1.0/yigraf/memory/008-gc-archives-superseded-churn-moves-it.md +21 -0
  92. yigraf-0.1.0/yigraf/memory/009-maturity-survival-is-derived-in-a.md +21 -0
  93. yigraf-0.1.0/yigraf/memory/010-claude-hooks-write-the-abs-interpreter.md +21 -0
  94. yigraf-0.1.0/yigraf/memory/011-capture-gap-legibility-surface-done-tasks.md +21 -0
  95. yigraf-0.1.0/yigraf/memory/012-human-facing-graph-stats-ride-a.md +21 -0
  96. yigraf-0.1.0/yigraf/memory/013-context-window-occupancy-is-an-injected.md +21 -0
  97. yigraf-0.1.0/yigraf/memory/014-freshness-is-derived-by-comparing-the.md +21 -0
  98. yigraf-0.1.0/yigraf/plans/active/language-drift-coverage.md +29 -0
  99. yigraf-0.1.0/yigraf/plans/active/memory-milestone.md +47 -0
  100. yigraf-0.1.0/yigraf/plans/active/phase-3-structure-depth.md +47 -0
  101. yigraf-0.1.0/yigraf/plans/active/status-surface.md +21 -0
  102. yigraf-0.1.0/yigraf/plans/active/yigraf-v0.md +55 -0
@@ -0,0 +1,4 @@
1
+ # Machine-local Claude Code settings written by `yigraf install-claude-hooks`. The hook commands bake
2
+ # in this clone's absolute interpreter path, so they're per-machine — kept out of git. A teammate
3
+ # inherits the committed SKILL.md + AGENTS.md block and just re-runs `yigraf install-claude-hooks`.
4
+ settings.local.json
@@ -0,0 +1,28 @@
1
+ {
2
+ "hooks": {
3
+ "PostToolUse": [
4
+ {
5
+ "matcher": "Edit|Write",
6
+ "hooks": [
7
+ {
8
+ "type": "command",
9
+ "command": "\"/Users/r1m9n/Documents/yigraf/.venv/bin/python3\" -m yigraf hook post-tool-use",
10
+ "timeout": 15
11
+ }
12
+ ]
13
+ }
14
+ ],
15
+ "SessionStart": [
16
+ {
17
+ "matcher": "startup|resume|clear|compact",
18
+ "hooks": [
19
+ {
20
+ "type": "command",
21
+ "command": "\"/Users/r1m9n/Documents/yigraf/.venv/bin/python3\" -m yigraf hook session-start",
22
+ "timeout": 15
23
+ }
24
+ ]
25
+ }
26
+ ]
27
+ }
28
+ }
@@ -0,0 +1,49 @@
1
+ ---
2
+ name: yigraf
3
+ description: Use when implementing or changing code in this repo to keep intent, code, and the reasoning behind it in sync. Before starting work, run `yigraf context "<topic>"` to surface governing intents, plans, prior decisions, and drift. After finishing a task, run `yigraf link <task> <symbol>` to name the symbols that implement it, and `yigraf remember` the non-obvious choices you made.
4
+ ---
5
+
6
+ # yigraf — the intent↔code spine
7
+
8
+ This repo is indexed by **yigraf**: one graph over code structure, intents (specs), plans, and the
9
+ **memory** of why the code is the way it is — with enforceable links (`implements`, `concerns`)
10
+ whose drift is surfaced when code and the thing that governs it diverge. A few rituals keep it
11
+ useful — the hooks are a safety net, not a substitute.
12
+
13
+ ## 0. Orient before you touch code (always)
14
+ Run `yigraf context "<what you're about to work on>"`. **This is the one command you need to read the
15
+ graph** — the governing requirement(s), the implementing symbols (signature by default, full source
16
+ when configured), the open tasks, the prior **decisions and their *why***, and any **drift** all come
17
+ back through it, as a token-cheap map. Don't reach for a separate query or drift tool. If a spec
18
+ already covers your change, refine it; don't duplicate. If a decision already settled the question,
19
+ follow it (or `supersede` it on purpose).
20
+
21
+ ## 1. Link when a task is done (the seam)
22
+ When you finish a task, name the symbols that implement it:
23
+ `yigraf link task:<plan>/<n> sym:<path>#<name>` — this anchors the link to the symbol's current
24
+ content. Linking once per completed task (not per edit) is enough.
25
+
26
+ ## 2. Capture the *why* (decisions & constraints)
27
+ When you make a non-obvious choice — picked an approach over a named alternative, set a constraint,
28
+ worked around something — persist the reasoning that `/clear` would otherwise lose. One line of why
29
+ plus the rejected option is enough; capture at the *conclusion*, not mid-thinking.
30
+ - `yigraf remember "<the decision, one line>" --type decision --why "<reasoning>" --serves int:<slug> --concerns sym:<path>#<name> [--rejected "<the alternative + why not>"]`
31
+ - A correction or rule → `yigraf note-constraint "<rule>" --concerns sym:<path>#<name>` (flagged as a
32
+ candidate to promote into an enforced check).
33
+ - Changed your mind? Never edit a decision in place — `yigraf supersede mem:<id> "<new decision>" --why "<what changed>"`. The old one stays as a rejected alternative.
34
+
35
+ A `--concerns` link is **anchored** like `implements`: edit that code later and yigraf surfaces a
36
+ "re-verify this decision still holds" reconcile. That's the payoff — the next agent to touch the code
37
+ sees the decision and its rationale without reading the history.
38
+
39
+ ## 3. Author specs as you plan
40
+ - `yigraf intent <slug> -s "The system SHALL …" --scenario "Given …, When …, Then …" [--design "…"]`
41
+ - `yigraf plan <slug> -t "<title>" --task "<description>"` then `yigraf link task:<plan>/1 int:<slug>`
42
+ to track the intent.
43
+
44
+ ## 4. Drift means re-verify
45
+ You don't poll for drift — `yigraf context` and the edit hook surface it for you: soft drift (a linked
46
+ symbol's body changed) or hard drift (it's gone), for both `implements` (task→code) and `concerns`
47
+ (decision→code) links. A pure rename auto-re-anchors. When drift surfaces, re-verify the code still
48
+ satisfies the spec/decision, then `yigraf link` (or re-`remember` / `supersede` the decision) to
49
+ re-anchor. (`yigraf drift` exits non-zero on drift — that's the commit/CI gate, not something you poll.)
@@ -0,0 +1,26 @@
1
+ name: Release
2
+
3
+ # Build + publish to PyPI on a published GitHub Release, via PyPI Trusted Publishing (OIDC) —
4
+ # no API token stored anywhere. One-time setup on PyPI: project → Publishing → add a trusted
5
+ # publisher (owner: mansilla, repo: yigraf, workflow: release.yml, environment: pypi).
6
+
7
+ on:
8
+ release:
9
+ types: [published]
10
+
11
+ permissions:
12
+ contents: read
13
+
14
+ jobs:
15
+ publish:
16
+ runs-on: ubuntu-latest
17
+ environment: pypi
18
+ permissions:
19
+ id-token: write # OIDC token for trusted publishing
20
+ steps:
21
+ - uses: actions/checkout@v4
22
+ - uses: astral-sh/setup-uv@v5
23
+ - name: Build sdist + wheel
24
+ run: uv build
25
+ - name: Publish to PyPI
26
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,29 @@
1
+ # --- Python ---
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ .eggs/
6
+ build/
7
+ dist/
8
+ .pytest_cache/
9
+ .ruff_cache/
10
+ .mypy_cache/
11
+
12
+ # --- Environments ---
13
+ .venv/
14
+ venv/
15
+
16
+ # --- OS ---
17
+ .DS_Store
18
+
19
+ # --- Reference clones (studied alongside yigraf; each carries its own .git history) ---
20
+ # Not vendored or submoduled — kept out of yigraf's own repo. See origins/ on disk.
21
+ origins/
22
+
23
+ # --- Eval harness output (captured transcripts + per-arm settings; rebuildable) ---
24
+ scripts/eval/runs/
25
+
26
+ # --- Claude Code per-machine hook wiring ---
27
+ # `yigraf install-claude-hooks` writes the absolute interpreter path into .claude/settings.local.json
28
+ # (per-machine), which .claude/.gitignore keeps out of git. The shareable SKILL.md + AGENTS.md block
29
+ # (and a future shared .claude/settings.json) ARE committed. See docs/caveats.md M5.
yigraf-0.1.0/AGENTS.md ADDED
@@ -0,0 +1,7 @@
1
+ <!-- yigraf:start -->
2
+ ## yigraf
3
+ This repo uses **yigraf** (a graph over code, intent, plan, and the *why*). Before changing code, run
4
+ `yigraf context "<topic>"` — the one read command: it surfaces governing intents, prior decisions, and
5
+ any drift to re-verify. After finishing a task, run `yigraf link task:<plan>/<n> sym:<path>#<name>`, and
6
+ `yigraf remember` the non-obvious choices (with `--why` and `--concerns <sym>`).
7
+ <!-- yigraf:end -->
yigraf-0.1.0/CLAUDE.md ADDED
@@ -0,0 +1,90 @@
1
+ # yigraf — read this first
2
+
3
+ **yigraf is a tool for AI coding agents, not for human beings.** Every surface it exposes — the CLI
4
+ output, the hook injections, the error messages, the docs, this file — is designed to be *consumed by
5
+ an agent*, optimized for an agent's constraints (a finite context window, a working memory wiped by
6
+ `/clear`, no scrollback), and judged by whether it makes an agent's next action better. It is **not** a
7
+ tool for a human to "understand the codebase," read the plan, or browse the design. A human is the
8
+ *principal* whose intent yigraf carries; the **agent is the operator and the audience**.
9
+
10
+ ## The name
11
+
12
+ **yigraf = "Why I Graph?"** It exists to answer, *for the agent*, the **why's** and **what-for's** of
13
+ its current state — the questions an agent cannot answer from source alone and loses on every reset:
14
+
15
+ - **What is this?** → `structure` (code symbols, files, calls — from tree-sitter)
16
+ - **What is it *for*?** → `intent` (the SHALL/MUST contracts and goals it serves)
17
+ - **What am I doing / what's left?** → `plan` (tasks in a DAG, with state)
18
+ - **Why is it this way?** → `memory` (the decisions, constraints, and rejected alternatives)
19
+
20
+ These four node families and the **cross-family edges** between them (`implements`, `tracks`,
21
+ `serves`, `concerns`, `supersedes`) *are* the answer. Retrieval is "ask once, get the answer as a
22
+ token-cheap slice." This is the whole product.
23
+
24
+ ## The design law (apply it to every change)
25
+
26
+ When you add or change anything in yigraf, the test is **"is this better for the agent consuming
27
+ it?"** — never "is this nicer for a human to read." Concretely, this is why the code looks the way it
28
+ does, and the shape you must preserve:
29
+
30
+ 1. **Errors teach abandonment — so recoverable conditions exit 0 with guidance, not a stack trace.**
31
+ An unresolved locator, a near-duplicate, an existing name → `_guidance()` prints how to fix it and
32
+ exits `0`, so the agent reads it and retries instead of learning "this tool fails, stop calling it."
33
+ Only genuine stop-conditions (no workspace, the CI drift gate) exit non-zero. (`cli.py:_guidance`)
34
+ 2. **Output is for a context window, not a screen.** `context` returns locators + signatures (not
35
+ source by default), under a token budget, ranked — because the agent pays for every token and
36
+ re-reading what's already encoded is the waste yigraf exists to remove. (`retrieval.py`)
37
+ 3. **yigraf speaks *into* the agent's context, at the moment of action.** The value is delivered by
38
+ Claude Code hooks: `PostToolUse(Edit|Write)` injects the governing intent + drift for the file just
39
+ touched; `SessionStart(clear|compact)` re-injects the active plan + intents — *this is the
40
+ mechanism by which memory survives `/clear`*. (`cli.py:_post_tool_use`, `_session_start`)
41
+ 4. **Silence is a feature.** The edit hook returns `None` (injects nothing) unless the locus is
42
+ actually governed or has drift. Respect the agent's attention budget; never nag on a routine edit.
43
+ (`retrieval.py:context_for_locus`)
44
+ 5. **Fail-open, always.** A hook or a query must never block or break the agent's work — every hook
45
+ handler swallows exceptions and exits 0. (`cli.py:_run_hook`)
46
+ 6. **Files are truth; `graph.json` is a derived, recomputable projection.** Never write volatile state
47
+ (usage/last_seen) into the committed graph — it lives in the gitignored `.local/` sidecar.
48
+ (DESIGN.md R1)
49
+
50
+ If a proposed change optimizes for human ergonomics at the cost of any of these, it is probably wrong
51
+ for yigraf. State the agent-cost/benefit in the change, not the human-readability.
52
+
53
+ ## The working loop (what the agent does with yigraf)
54
+
55
+ This is the loop the `yigraf` skill and `AGENTS.md` instruct an agent to follow on **any** repo:
56
+
57
+ ```
58
+ yigraf context "<topic>" # before touching code: governing intent, plan, prior why, drift
59
+ … do the work …
60
+ yigraf link task:<plan>/<n> sym:<path>#<name> # name the symbols a task implements (anchors them)
61
+ yigraf remember "<decision>" --why "…" --concerns sym:<path>#<name> [--rejected "…"] # persist the why
62
+ ```
63
+
64
+ `context` is the **one read command** — intent, plan, implementing signatures, prior decisions, and
65
+ drift all come back through it. Don't reach for separate query/drift tools.
66
+
67
+ ## Developing yigraf itself
68
+
69
+ yigraf is **self-hosted**: it indexes its own repo, so the loop above applies here too. Before
70
+ changing code, run `uv run yigraf context "<topic>"` to surface the governing intent and prior
71
+ decisions; after a task, `link` the symbols and `remember` the non-obvious choices.
72
+
73
+ - **Run / test:** `uv sync`, then `uv run pytest` (fast, no network). `uv run yigraf --help`.
74
+ - **Optional semantic recall:** `uv pip install -e '.[embeddings]'` (local `bge-small`). Absent ⇒
75
+ retrieval degrades to the lexical seeder; never a hard dependency.
76
+ - **Docs:** the public references are [`README.md`](README.md) (overview, install, how-it-works) and
77
+ [`docs/language-support.md`](docs/language-support.md) (the tested capability matrix). The internal
78
+ design corpus (decision log, milestone notes, research) was removed from the repo; that history lives
79
+ in git, and the authoritative *current* state is the code, the tests, and this file.
80
+ - **Layout:** package under `src/yigraf/` (src-layout is deliberate — `yigraf init` creates a data dir
81
+ named `yigraf/` at a repo root, and the two must not collide).
82
+ - **Status:** v0 spine (M0–M6) + memory milestone (M7–M9) complete and self-hosted. Counters are
83
+ local + recomputable (v0); the shared/committed counter model is v1/Enterprise (cloud) work.
84
+
85
+ ## Conventions
86
+
87
+ - Commit messages and PRs follow the harness footer rules (see the agent's commit guidance). Only
88
+ commit/push when asked.
89
+ - Match the surrounding code: terse module docstrings that cite the governing decision (e.g. `R1`,
90
+ `M8`), dataclasses for results, no speculative abstraction.
yigraf-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Ricardo Mansilla
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
yigraf-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,222 @@
1
+ Metadata-Version: 2.4
2
+ Name: yigraf
3
+ Version: 0.1.0
4
+ Summary: A harness primitive for AI coding agents: one connected graph over code, intent, plan, and memory — legible (token-cheap retrieval) and enforceable (intent↔code drift checks).
5
+ Project-URL: Homepage, https://github.com/mansilla/yigraf
6
+ Project-URL: Repository, https://github.com/mansilla/yigraf
7
+ Project-URL: Issues, https://github.com/mansilla/yigraf/issues
8
+ Author-email: Ricardo Mansilla <rick.mansilla@gmail.com>
9
+ License: MIT
10
+ License-File: LICENSE
11
+ Keywords: agents,ai,claude,code-intelligence,knowledge-graph,llm,tree-sitter
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Topic :: Software Development :: Libraries
20
+ Classifier: Topic :: Software Development :: Quality Assurance
21
+ Requires-Python: >=3.11
22
+ Requires-Dist: networkx>=3.4
23
+ Requires-Dist: pyyaml>=6.0
24
+ Requires-Dist: tree-sitter-bash<0.25,>=0.23
25
+ Requires-Dist: tree-sitter-c-sharp<0.25,>=0.23
26
+ Requires-Dist: tree-sitter-c<0.25,>=0.23
27
+ Requires-Dist: tree-sitter-cpp<0.25,>=0.23
28
+ Requires-Dist: tree-sitter-go<0.26,>=0.23
29
+ Requires-Dist: tree-sitter-java<0.25,>=0.23
30
+ Requires-Dist: tree-sitter-javascript<0.26,>=0.23
31
+ Requires-Dist: tree-sitter-kotlin<2.0,>=1.0
32
+ Requires-Dist: tree-sitter-php<0.25,>=0.23
33
+ Requires-Dist: tree-sitter-python<0.26,>=0.23
34
+ Requires-Dist: tree-sitter-ruby<0.25,>=0.23
35
+ Requires-Dist: tree-sitter-rust<0.25,>=0.23
36
+ Requires-Dist: tree-sitter-scala<0.27,>=0.23
37
+ Requires-Dist: tree-sitter-sql<0.4,>=0.3
38
+ Requires-Dist: tree-sitter-swift<0.9,>=0.7
39
+ Requires-Dist: tree-sitter-typescript<0.25,>=0.23
40
+ Requires-Dist: tree-sitter<0.26,>=0.25
41
+ Requires-Dist: typer>=0.12
42
+ Provides-Extra: embeddings
43
+ Requires-Dist: numpy>=1.24; extra == 'embeddings'
44
+ Requires-Dist: sentence-transformers>=2.2; extra == 'embeddings'
45
+ Description-Content-Type: text/markdown
46
+
47
+ # yigraf
48
+
49
+ > **yigraf — "Why I Graph?"** A tool **for AI coding agents, not for humans.** It answers, *for the
50
+ > agent*, the **why's** and **what-for's** of its current state — the questions an agent can't recover
51
+ > from source alone and loses on every `/clear`. A human is the *principal* whose intent it carries; the
52
+ > agent is the operator and the audience.
53
+
54
+ ## What is yigraf?
55
+
56
+ yigraf is a **harness primitive** for AI coding agents: it projects your repo into one connected graph
57
+ over four kinds of knowledge —
58
+
59
+ - **structure** — the code itself (*what is this?*)
60
+ - **intent** — specs/requirements (*what is it for?*)
61
+ - **plan** — goals and tasks (*what's left?*)
62
+ - **memory** — decisions and their reasoning (*why is it this way?*)
63
+
64
+ — and keeps them linked, so the right slice of an agent's work is both **legible** (scoped, token-cheap
65
+ retrieval instead of re-reading files) and **enforceable** (an intent↔code *drift check* that fires when
66
+ code and the thing governing it diverge). It retrofits onto an existing repo — `yigraf init` and go.
67
+
68
+ The problem it solves: an agent's working memory is wiped on every `/clear`, and source code doesn't
69
+ record *why* it's the way it is or *what* it's supposed to do. yigraf persists that context as a
70
+ queryable graph and re-surfaces the relevant piece exactly when the agent needs it.
71
+
72
+ ### Capabilities
73
+
74
+ - **Structure index** — tree-sitter parsing into file/module/symbol nodes with a reformatting-stable
75
+ content hash, across **16 languages** (see [`docs/language-support.md`](docs/language-support.md)).
76
+ - **Intent & plan** — author specs and task plans as Markdown; link a task to the symbols that implement
77
+ it, **anchored** to their current content.
78
+ - **Drift detection** — when anchored code changes, yigraf surfaces *"re-verify this still holds, then
79
+ re-link or supersede."* A pure rename re-anchors automatically; a body change is honest drift. (This is
80
+ the part that makes yigraf governance, not just an index.)
81
+ - **Memory** — capture decisions + the reasoning behind them; recall by **meaning** (optional embeddings)
82
+ or lexically; a decision earns `settled` after surviving K commits un-superseded; `gc` archives churn.
83
+ - **Token-cheap retrieval** — `yigraf context "<topic>"` returns a scoped, budgeted slice (locators +
84
+ signatures, not file dumps) — measured ≈2.5× cheaper than reading the file.
85
+ - **Agent integration** — Claude Code hooks inject governing intent + drift on edit and re-inject the
86
+ plan after `/clear`; a skill teaches the rituals. The `yigraf` CLI works with any agent.
87
+
88
+ ### Requirements (and what each is for)
89
+
90
+ | Requirement | Why |
91
+ |---|---|
92
+ | **Python ≥ 3.11** | yigraf runs as a Python CLI |
93
+ | **A git repo** | drift anchoring and git-derived maturity read git history (degrades gracefully without git) |
94
+ | **Tree-sitter grammars** | structure extraction — **bundled**, no setup |
95
+ | **An agent harness** | Claude Code gets hooks + a skill out of the box; any other agent can drive the CLI |
96
+ | **An embeddings backend** *(optional, `[embeddings]` extra)* | semantic recall of memory/intent by meaning; **falls back to lexical** retrieval if absent — never required |
97
+
98
+ ## Quickstart
99
+
100
+ ```bash
101
+ # 1. install (see Installation for per-platform setup)
102
+ uv tool install git+https://github.com/mansilla/yigraf.git
103
+
104
+ # 2. in your repo: create the workspace and index the code
105
+ cd your-repo
106
+ yigraf init
107
+ yigraf build
108
+
109
+ # 3. wire it into Claude Code (hooks + skill)
110
+ yigraf install-claude-hooks
111
+
112
+ # 4. use it
113
+ yigraf context "session expiry" # a scoped, token-cheap slice for a topic
114
+ yigraf intent session-expiry -s "The system SHALL expire a session after 30m idle."
115
+ yigraf link task:auth/1 sym:src/auth/session.py#refresh # anchor a task to its code
116
+ yigraf remember "chose monotonic clock" --why "wall-clock skews under NTP"
117
+ yigraf drift # report any intent↔code drift
118
+ ```
119
+
120
+ ## Installation
121
+
122
+ yigraf installs from source (not yet on PyPI). It needs **Python ≥ 3.11**; the tree-sitter grammars are
123
+ bundled, so there's nothing else to set up. Installing as an isolated tool (uv or pipx) is recommended.
124
+
125
+ **Any platform — pick one:**
126
+
127
+ ```bash
128
+ uv tool install git+https://github.com/mansilla/yigraf.git # uv
129
+ pipx install "git+https://github.com/mansilla/yigraf.git" # pipx
130
+
131
+ # with semantic recall (numpy + sentence-transformers):
132
+ uv tool install "yigraf[embeddings] @ git+https://github.com/mansilla/yigraf.git"
133
+ ```
134
+
135
+ ### macOS
136
+
137
+ ```bash
138
+ brew install uv # or: brew install pipx ; and Python 3.11+ via `brew install python@3.12`
139
+ uv tool install git+https://github.com/mansilla/yigraf.git
140
+ ```
141
+
142
+ ### Linux
143
+
144
+ ```bash
145
+ # Debian/Ubuntu — ensure Python 3.11+ and git
146
+ sudo apt-get update && sudo apt-get install -y python3 python3-venv git
147
+ curl -LsSf https://astral.sh/uv/install.sh | sh # install uv (or: pipx via your package manager)
148
+ uv tool install git+https://github.com/mansilla/yigraf.git
149
+ ```
150
+
151
+ ### Windows
152
+
153
+ ```powershell
154
+ winget install astral-sh.uv # install uv
155
+ winget install Git.Git # drift anchoring uses git; install Git for Windows
156
+ # (Python 3.11+ via `winget install Python.Python.3.12` if you don't have it)
157
+ uv tool install git+https://github.com/mansilla/yigraf.git
158
+ ```
159
+
160
+ ### From source (development)
161
+
162
+ ```bash
163
+ git clone https://github.com/mansilla/yigraf.git
164
+ cd yigraf
165
+ uv sync # create the venv + install deps (incl. dev tools)
166
+ uv run yigraf --help
167
+ uv run pytest
168
+ ```
169
+
170
+ ## How yigraf works
171
+
172
+ yigraf projects your repo into one graph and keeps it in sync with the *why*:
173
+
174
+ 1. **Index** — `yigraf build` parses your code into file/module/symbol nodes, each with an
175
+ AST-normalized content hash (so reformatting and comments don't count as change).
176
+ 2. **Author** — write **intents** (specs) and **plans** (tasks) as Markdown; capture **memory**
177
+ (a decision + its reasoning) with `yigraf remember`.
178
+ 3. **Link** — `yigraf link <task> <symbol>` records which code implements a task and **anchors** the
179
+ link to that symbol's current content hash.
180
+ 4. **Retrieve** — `yigraf context "<topic>"` returns a scoped, token-budgeted slice: the governing
181
+ intents, the implementing symbols (as locators + signatures), prior decisions, open tasks, and any
182
+ drift — a small map, not a pile of file dumps.
183
+ 5. **Enforce** — when a symbol's anchored content changes, yigraf reports **drift** so the change gets
184
+ re-verified against what governs it (or the link re-anchored / the decision superseded).
185
+
186
+ With Claude Code wired up (`yigraf install-claude-hooks`), steps 4–5 happen automatically: a
187
+ **PostToolUse** hook injects governing intent + drift the moment the agent edits a governed file, and a
188
+ **SessionStart** hook re-injects the active plan after a `/clear` — so a flow interrupted by a context
189
+ reset resumes instead of restarting. The hook stays silent on ungoverned, undrifted edits (no nagging).
190
+
191
+ ## Files yigraf creates
192
+
193
+ `yigraf init` lays down a `yigraf/` workspace at your repo root:
194
+
195
+ ```
196
+ yigraf/
197
+ ├── config.yaml # committed — enabled languages, ignore globs, retrieval tunables
198
+ ├── intents/<slug>.md # committed — requirement / goal / capability specs
199
+ ├── plans/{active,completed}/ # committed — plans + tasks (the filesystem is the state)
200
+ ├── memory/<id>-<slug>.md # committed — decisions / constraints + the "why"
201
+ ├── graph.json # committed — the graph projection (recomputable state only)
202
+ ├── index/ # gitignored — embedding index (rebuildable)
203
+ ├── cache/ # gitignored — extraction cache
204
+ └── .local/ # gitignored — volatile telemetry (usage / last_seen)
205
+ ```
206
+
207
+ The **committed** artifacts (`intents/`, `plans/`, `memory/`, `graph.json`, `config.yaml`) are the
208
+ shareable record — they travel with the repo, so the next agent or teammate inherits the *why*. Derived
209
+ and volatile state stays gitignored and rebuilds from source. yigraf also writes a self-contained
210
+ `yigraf/.gitignore`, so nothing extra needs to be added to your repo's ignore rules.
211
+
212
+ Two opt-in installers wire yigraf into your tooling:
213
+
214
+ - **`yigraf install-claude-hooks`** — writes `.claude/settings.local.json` (machine-local hooks, *not*
215
+ committed) and `.claude/skills/yigraf/SKILL.md`.
216
+ - **`yigraf install-hooks`** — adds a git **post-commit** hook that keeps `graph.json` synced to `HEAD`.
217
+
218
+ ## Language support
219
+
220
+ 16 languages, indexed at two depths (bespoke extractors for Python/Go/JS-TS, a generic tags-query tier
221
+ for the rest). The full **tested** capability matrix — symbols / calls / imports / inheritance / drift,
222
+ per language — is in **[`docs/language-support.md`](docs/language-support.md)**.
yigraf-0.1.0/README.md ADDED
@@ -0,0 +1,176 @@
1
+ # yigraf
2
+
3
+ > **yigraf — "Why I Graph?"** A tool **for AI coding agents, not for humans.** It answers, *for the
4
+ > agent*, the **why's** and **what-for's** of its current state — the questions an agent can't recover
5
+ > from source alone and loses on every `/clear`. A human is the *principal* whose intent it carries; the
6
+ > agent is the operator and the audience.
7
+
8
+ ## What is yigraf?
9
+
10
+ yigraf is a **harness primitive** for AI coding agents: it projects your repo into one connected graph
11
+ over four kinds of knowledge —
12
+
13
+ - **structure** — the code itself (*what is this?*)
14
+ - **intent** — specs/requirements (*what is it for?*)
15
+ - **plan** — goals and tasks (*what's left?*)
16
+ - **memory** — decisions and their reasoning (*why is it this way?*)
17
+
18
+ — and keeps them linked, so the right slice of an agent's work is both **legible** (scoped, token-cheap
19
+ retrieval instead of re-reading files) and **enforceable** (an intent↔code *drift check* that fires when
20
+ code and the thing governing it diverge). It retrofits onto an existing repo — `yigraf init` and go.
21
+
22
+ The problem it solves: an agent's working memory is wiped on every `/clear`, and source code doesn't
23
+ record *why* it's the way it is or *what* it's supposed to do. yigraf persists that context as a
24
+ queryable graph and re-surfaces the relevant piece exactly when the agent needs it.
25
+
26
+ ### Capabilities
27
+
28
+ - **Structure index** — tree-sitter parsing into file/module/symbol nodes with a reformatting-stable
29
+ content hash, across **16 languages** (see [`docs/language-support.md`](docs/language-support.md)).
30
+ - **Intent & plan** — author specs and task plans as Markdown; link a task to the symbols that implement
31
+ it, **anchored** to their current content.
32
+ - **Drift detection** — when anchored code changes, yigraf surfaces *"re-verify this still holds, then
33
+ re-link or supersede."* A pure rename re-anchors automatically; a body change is honest drift. (This is
34
+ the part that makes yigraf governance, not just an index.)
35
+ - **Memory** — capture decisions + the reasoning behind them; recall by **meaning** (optional embeddings)
36
+ or lexically; a decision earns `settled` after surviving K commits un-superseded; `gc` archives churn.
37
+ - **Token-cheap retrieval** — `yigraf context "<topic>"` returns a scoped, budgeted slice (locators +
38
+ signatures, not file dumps) — measured ≈2.5× cheaper than reading the file.
39
+ - **Agent integration** — Claude Code hooks inject governing intent + drift on edit and re-inject the
40
+ plan after `/clear`; a skill teaches the rituals. The `yigraf` CLI works with any agent.
41
+
42
+ ### Requirements (and what each is for)
43
+
44
+ | Requirement | Why |
45
+ |---|---|
46
+ | **Python ≥ 3.11** | yigraf runs as a Python CLI |
47
+ | **A git repo** | drift anchoring and git-derived maturity read git history (degrades gracefully without git) |
48
+ | **Tree-sitter grammars** | structure extraction — **bundled**, no setup |
49
+ | **An agent harness** | Claude Code gets hooks + a skill out of the box; any other agent can drive the CLI |
50
+ | **An embeddings backend** *(optional, `[embeddings]` extra)* | semantic recall of memory/intent by meaning; **falls back to lexical** retrieval if absent — never required |
51
+
52
+ ## Quickstart
53
+
54
+ ```bash
55
+ # 1. install (see Installation for per-platform setup)
56
+ uv tool install git+https://github.com/mansilla/yigraf.git
57
+
58
+ # 2. in your repo: create the workspace and index the code
59
+ cd your-repo
60
+ yigraf init
61
+ yigraf build
62
+
63
+ # 3. wire it into Claude Code (hooks + skill)
64
+ yigraf install-claude-hooks
65
+
66
+ # 4. use it
67
+ yigraf context "session expiry" # a scoped, token-cheap slice for a topic
68
+ yigraf intent session-expiry -s "The system SHALL expire a session after 30m idle."
69
+ yigraf link task:auth/1 sym:src/auth/session.py#refresh # anchor a task to its code
70
+ yigraf remember "chose monotonic clock" --why "wall-clock skews under NTP"
71
+ yigraf drift # report any intent↔code drift
72
+ ```
73
+
74
+ ## Installation
75
+
76
+ yigraf installs from source (not yet on PyPI). It needs **Python ≥ 3.11**; the tree-sitter grammars are
77
+ bundled, so there's nothing else to set up. Installing as an isolated tool (uv or pipx) is recommended.
78
+
79
+ **Any platform — pick one:**
80
+
81
+ ```bash
82
+ uv tool install git+https://github.com/mansilla/yigraf.git # uv
83
+ pipx install "git+https://github.com/mansilla/yigraf.git" # pipx
84
+
85
+ # with semantic recall (numpy + sentence-transformers):
86
+ uv tool install "yigraf[embeddings] @ git+https://github.com/mansilla/yigraf.git"
87
+ ```
88
+
89
+ ### macOS
90
+
91
+ ```bash
92
+ brew install uv # or: brew install pipx ; and Python 3.11+ via `brew install python@3.12`
93
+ uv tool install git+https://github.com/mansilla/yigraf.git
94
+ ```
95
+
96
+ ### Linux
97
+
98
+ ```bash
99
+ # Debian/Ubuntu — ensure Python 3.11+ and git
100
+ sudo apt-get update && sudo apt-get install -y python3 python3-venv git
101
+ curl -LsSf https://astral.sh/uv/install.sh | sh # install uv (or: pipx via your package manager)
102
+ uv tool install git+https://github.com/mansilla/yigraf.git
103
+ ```
104
+
105
+ ### Windows
106
+
107
+ ```powershell
108
+ winget install astral-sh.uv # install uv
109
+ winget install Git.Git # drift anchoring uses git; install Git for Windows
110
+ # (Python 3.11+ via `winget install Python.Python.3.12` if you don't have it)
111
+ uv tool install git+https://github.com/mansilla/yigraf.git
112
+ ```
113
+
114
+ ### From source (development)
115
+
116
+ ```bash
117
+ git clone https://github.com/mansilla/yigraf.git
118
+ cd yigraf
119
+ uv sync # create the venv + install deps (incl. dev tools)
120
+ uv run yigraf --help
121
+ uv run pytest
122
+ ```
123
+
124
+ ## How yigraf works
125
+
126
+ yigraf projects your repo into one graph and keeps it in sync with the *why*:
127
+
128
+ 1. **Index** — `yigraf build` parses your code into file/module/symbol nodes, each with an
129
+ AST-normalized content hash (so reformatting and comments don't count as change).
130
+ 2. **Author** — write **intents** (specs) and **plans** (tasks) as Markdown; capture **memory**
131
+ (a decision + its reasoning) with `yigraf remember`.
132
+ 3. **Link** — `yigraf link <task> <symbol>` records which code implements a task and **anchors** the
133
+ link to that symbol's current content hash.
134
+ 4. **Retrieve** — `yigraf context "<topic>"` returns a scoped, token-budgeted slice: the governing
135
+ intents, the implementing symbols (as locators + signatures), prior decisions, open tasks, and any
136
+ drift — a small map, not a pile of file dumps.
137
+ 5. **Enforce** — when a symbol's anchored content changes, yigraf reports **drift** so the change gets
138
+ re-verified against what governs it (or the link re-anchored / the decision superseded).
139
+
140
+ With Claude Code wired up (`yigraf install-claude-hooks`), steps 4–5 happen automatically: a
141
+ **PostToolUse** hook injects governing intent + drift the moment the agent edits a governed file, and a
142
+ **SessionStart** hook re-injects the active plan after a `/clear` — so a flow interrupted by a context
143
+ reset resumes instead of restarting. The hook stays silent on ungoverned, undrifted edits (no nagging).
144
+
145
+ ## Files yigraf creates
146
+
147
+ `yigraf init` lays down a `yigraf/` workspace at your repo root:
148
+
149
+ ```
150
+ yigraf/
151
+ ├── config.yaml # committed — enabled languages, ignore globs, retrieval tunables
152
+ ├── intents/<slug>.md # committed — requirement / goal / capability specs
153
+ ├── plans/{active,completed}/ # committed — plans + tasks (the filesystem is the state)
154
+ ├── memory/<id>-<slug>.md # committed — decisions / constraints + the "why"
155
+ ├── graph.json # committed — the graph projection (recomputable state only)
156
+ ├── index/ # gitignored — embedding index (rebuildable)
157
+ ├── cache/ # gitignored — extraction cache
158
+ └── .local/ # gitignored — volatile telemetry (usage / last_seen)
159
+ ```
160
+
161
+ The **committed** artifacts (`intents/`, `plans/`, `memory/`, `graph.json`, `config.yaml`) are the
162
+ shareable record — they travel with the repo, so the next agent or teammate inherits the *why*. Derived
163
+ and volatile state stays gitignored and rebuilds from source. yigraf also writes a self-contained
164
+ `yigraf/.gitignore`, so nothing extra needs to be added to your repo's ignore rules.
165
+
166
+ Two opt-in installers wire yigraf into your tooling:
167
+
168
+ - **`yigraf install-claude-hooks`** — writes `.claude/settings.local.json` (machine-local hooks, *not*
169
+ committed) and `.claude/skills/yigraf/SKILL.md`.
170
+ - **`yigraf install-hooks`** — adds a git **post-commit** hook that keeps `graph.json` synced to `HEAD`.
171
+
172
+ ## Language support
173
+
174
+ 16 languages, indexed at two depths (bespoke extractors for Python/Go/JS-TS, a generic tags-query tier
175
+ for the rest). The full **tested** capability matrix — symbols / calls / imports / inheritance / drift,
176
+ per language — is in **[`docs/language-support.md`](docs/language-support.md)**.