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.
- yigraf-0.1.0/.claude/.gitignore +4 -0
- yigraf-0.1.0/.claude/settings.local.json +28 -0
- yigraf-0.1.0/.claude/skills/yigraf/SKILL.md +49 -0
- yigraf-0.1.0/.github/workflows/release.yml +26 -0
- yigraf-0.1.0/.gitignore +29 -0
- yigraf-0.1.0/AGENTS.md +7 -0
- yigraf-0.1.0/CLAUDE.md +90 -0
- yigraf-0.1.0/LICENSE +21 -0
- yigraf-0.1.0/PKG-INFO +222 -0
- yigraf-0.1.0/README.md +176 -0
- yigraf-0.1.0/docs/language-support.md +50 -0
- yigraf-0.1.0/pyproject.toml +80 -0
- yigraf-0.1.0/scripts/eval/README.md +113 -0
- yigraf-0.1.0/scripts/eval/cases.yaml +56 -0
- yigraf-0.1.0/scripts/eval/judge.py +180 -0
- yigraf-0.1.0/scripts/eval/parse_run.py +140 -0
- yigraf-0.1.0/scripts/eval/render_ab.py +119 -0
- yigraf-0.1.0/scripts/eval/run_ab.py +299 -0
- yigraf-0.1.0/src/yigraf/__init__.py +3 -0
- yigraf-0.1.0/src/yigraf/__main__.py +6 -0
- yigraf-0.1.0/src/yigraf/artifacts.py +312 -0
- yigraf-0.1.0/src/yigraf/astnorm.py +151 -0
- yigraf-0.1.0/src/yigraf/cache.py +102 -0
- yigraf-0.1.0/src/yigraf/cli.py +626 -0
- yigraf-0.1.0/src/yigraf/config.py +143 -0
- yigraf-0.1.0/src/yigraf/counters.py +288 -0
- yigraf-0.1.0/src/yigraf/drift.py +113 -0
- yigraf-0.1.0/src/yigraf/embeddings.py +297 -0
- yigraf-0.1.0/src/yigraf/extract.py +166 -0
- yigraf-0.1.0/src/yigraf/graph.py +57 -0
- yigraf-0.1.0/src/yigraf/hooks.py +268 -0
- yigraf-0.1.0/src/yigraf/languages/__init__.py +73 -0
- yigraf-0.1.0/src/yigraf/languages/base.py +252 -0
- yigraf-0.1.0/src/yigraf/languages/go.py +277 -0
- yigraf-0.1.0/src/yigraf/languages/jsts.py +324 -0
- yigraf-0.1.0/src/yigraf/languages/python.py +379 -0
- yigraf-0.1.0/src/yigraf/languages/resolve.py +42 -0
- yigraf-0.1.0/src/yigraf/languages/tags.py +813 -0
- yigraf-0.1.0/src/yigraf/memory.py +325 -0
- yigraf-0.1.0/src/yigraf/retrieval.py +604 -0
- yigraf-0.1.0/src/yigraf/scaffold.py +102 -0
- yigraf-0.1.0/tests/conftest.py +24 -0
- yigraf-0.1.0/tests/test_artifacts.py +77 -0
- yigraf-0.1.0/tests/test_astnorm.py +86 -0
- yigraf-0.1.0/tests/test_build.py +199 -0
- yigraf-0.1.0/tests/test_cchooks.py +160 -0
- yigraf-0.1.0/tests/test_cli.py +32 -0
- yigraf-0.1.0/tests/test_config.py +30 -0
- yigraf-0.1.0/tests/test_context.py +181 -0
- yigraf-0.1.0/tests/test_counters.py +295 -0
- yigraf-0.1.0/tests/test_drift.py +96 -0
- yigraf-0.1.0/tests/test_embeddings.py +130 -0
- yigraf-0.1.0/tests/test_eval_judge.py +76 -0
- yigraf-0.1.0/tests/test_eval_parse.py +67 -0
- yigraf-0.1.0/tests/test_eval_runab.py +44 -0
- yigraf-0.1.0/tests/test_extract.py +123 -0
- yigraf-0.1.0/tests/test_graph.py +26 -0
- yigraf-0.1.0/tests/test_hooks.py +83 -0
- yigraf-0.1.0/tests/test_init.py +47 -0
- yigraf-0.1.0/tests/test_language_drift.py +128 -0
- yigraf-0.1.0/tests/test_languages.py +435 -0
- yigraf-0.1.0/tests/test_memory.py +218 -0
- yigraf-0.1.0/tests/test_status.py +91 -0
- yigraf-0.1.0/tests/test_tags.py +299 -0
- yigraf-0.1.0/tests/test_verbs.py +131 -0
- yigraf-0.1.0/uv.lock +1640 -0
- yigraf-0.1.0/yigraf/.gitattributes +4 -0
- yigraf-0.1.0/yigraf/.gitignore +7 -0
- yigraf-0.1.0/yigraf/.local/telemetry.json +78 -0
- yigraf-0.1.0/yigraf/cache/structure.json +23783 -0
- yigraf-0.1.0/yigraf/config.yaml +38 -0
- yigraf-0.1.0/yigraf/graph.json +23425 -0
- yigraf-0.1.0/yigraf/index/meta.json +98 -0
- yigraf-0.1.0/yigraf/index/vectors.npy +0 -0
- yigraf-0.1.0/yigraf/intents/drift-detection.md +12 -0
- yigraf-0.1.0/yigraf/intents/enforceable-link.md +11 -0
- yigraf-0.1.0/yigraf/intents/hook-surfacing.md +12 -0
- yigraf-0.1.0/yigraf/intents/memory-family.md +15 -0
- yigraf-0.1.0/yigraf/intents/memory-maturity.md +15 -0
- yigraf-0.1.0/yigraf/intents/semantic-recall.md +15 -0
- yigraf-0.1.0/yigraf/intents/status-surface.md +15 -0
- yigraf-0.1.0/yigraf/intents/structure-index.md +16 -0
- yigraf-0.1.0/yigraf/intents/token-cheap-context.md +11 -0
- yigraf-0.1.0/yigraf/memory/001-concerns-reuses-the-implements-drift-machinery.md +24 -0
- yigraf-0.1.0/yigraf/memory/002-the-first-memory-milestone-captures-agent.md +19 -0
- yigraf-0.1.0/yigraf/memory/003-supersession-counters-are-stamped-only-on.md +21 -0
- yigraf-0.1.0/yigraf/memory/004-embed-only-memory-and-intent-with.md +24 -0
- yigraf-0.1.0/yigraf/memory/005-the-embedding-backend-is-an-optional.md +21 -0
- yigraf-0.1.0/yigraf/memory/006-v0-counters-are-local-recomputable-model.md +21 -0
- yigraf-0.1.0/yigraf/memory/007-maturity-is-git-derived-survival-commits.md +21 -0
- yigraf-0.1.0/yigraf/memory/008-gc-archives-superseded-churn-moves-it.md +21 -0
- yigraf-0.1.0/yigraf/memory/009-maturity-survival-is-derived-in-a.md +21 -0
- yigraf-0.1.0/yigraf/memory/010-claude-hooks-write-the-abs-interpreter.md +21 -0
- yigraf-0.1.0/yigraf/memory/011-capture-gap-legibility-surface-done-tasks.md +21 -0
- yigraf-0.1.0/yigraf/memory/012-human-facing-graph-stats-ride-a.md +21 -0
- yigraf-0.1.0/yigraf/memory/013-context-window-occupancy-is-an-injected.md +21 -0
- yigraf-0.1.0/yigraf/memory/014-freshness-is-derived-by-comparing-the.md +21 -0
- yigraf-0.1.0/yigraf/plans/active/language-drift-coverage.md +29 -0
- yigraf-0.1.0/yigraf/plans/active/memory-milestone.md +47 -0
- yigraf-0.1.0/yigraf/plans/active/phase-3-structure-depth.md +47 -0
- yigraf-0.1.0/yigraf/plans/active/status-surface.md +21 -0
- 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
|
yigraf-0.1.0/.gitignore
ADDED
|
@@ -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)**.
|