Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 45 additions & 33 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,68 +30,80 @@ pip install graqle

## Why GraQle exists

Your AI coding tool is good at generating code. It is bad at remembering.
Your organisation already knows the answer. It just can't hand it to an AI.

Every session it reconstructs your system from whatever files fit in the context window. It has never read the architecture decision you made last March, the incident that made you move validation into the service layer, or the policy that says refunds above a threshold need manager approval. That knowledge exists — in your repo, your docs, your decision records, your team's heads — but it isn't connected to anything, so it can't be reasoned over.
The refund threshold lives in a policy document. The reason you retain records for seven years is in an ADR nobody re-reads. The incident that moved validation into the service layer is in someone's head. The dependency that makes payments fragile is in the code. Every one of those is real knowledge — and none of it is connected to any of the others, so no model can reason across it.

GraQle builds that connection once and keeps it.
Each AI session starts from zero and rebuilds a partial picture from whatever files fit in the context window. Then the window closes and the picture is gone.

- **Architecture, not files.** AI assistants see files. GraQle sees relationships, dependencies and blast radius.
- **Memory that compounds.** Lessons, decisions and documents become durable graph nodes instead of disappearing with a chat session.
GraQle builds that connection once, keeps it, and grows it.

- **Relationships, not files.** Assistants see documents and files. GraQle sees how a policy, a decision and the code that implements it relate — and what breaks when one of them changes.
- **Memory that compounds.** Policies, decisions, lessons and architecture become durable graph nodes instead of disappearing with a chat session. Teach it once; every future session starts from there.
- **Model independence.** Swap models, providers or IDEs without rebuilding the intelligence layer.

---

## 90-second proof
## 90-second proof — no code required

Point GraQle at policies, ADRs, runbooks or specs. **Nothing else needed — this works on a folder with no code in it at all.**

```bash
pip install graqle

# 1. Scan a codebase into a typed knowledge graph
graq scan repo .
# → functions, classes, modules, imports, calls — architecture mapped in seconds
# 1. Turn a folder of organisational documents into a typed graph
graq scan docs ./policies
# → 3 files → 12 nodes: 3 Document + 9 Section, linked by SECTION_OF

# 2. Ask an architectural question, not a file question
graq run "what breaks if I change the payment module?"
# → activates the relevant subgraph, traces cross-file call + import chains
# → returns: answer + confidence + evidence trail + active nodes
# 2. Teach it a rule that lives in nobody's file
graq learn knowledge "vendor DPA must be signed before any data access" --domain policy
# → extracts the entity "DPA", then SEMANTICALLY_RELATED-links the rule to
# the vendor-onboarding document AND to its "Due diligence" section

# 3. Ask across the whole body of knowledge
graq run "what approval is needed for a large refund?"
# → answer + confidence + evidence trail + the exact sections consulted

# 3. Teach it something it cannot read from code
graq learn knowledge "payment module must never call user service directly"
# → persists as a graph node. Future reasoning activates this rule.
# 4. Audit what the organisation has taught it
graq learned
```

That third command is the one that compounds. It is also the one no amount of prompt engineering replacesit requires a persistent typed graph as the substrate.
Step 2 is the one that compounds, and the one no amount of prompt engineering replaces: it needs a persistent typed graph as the substrate. GraQle found where that rule belonged on its own — you never told it which document to attach it to.

### Bring in the knowledge that isn't code
Markdown, text, reStructuredText and AsciiDoc parse with the base install. PDF, DOCX, PPTX and XLSX need `pip install "graqle[docs]"` — without it those files are skipped and reported, never silently dropped.

### The same graph, for code

Where a codebase is part of the picture, it enters the same graph and connects to the documents that govern it:

```bash
pip install "graqle[docs]" # PDF / DOCX / PPTX / XLSX parsers
graq scan repo .
# → functions, classes, modules, imports, calls — architecture mapped in seconds

graq run "what breaks if I change the payment module?"
# → traces cross-file call + import chains, activates the relevant subgraph

# Ingest architecture docs, policies, ADRs, runbooks, specs
graq scan docs ./docs
graq learn doc ./policies/ ./decisions/architecture-review.docx
# → Document + Section nodes, auto-linked to the code they describe
graq impact payments.py # blast radius before you touch anything
```

Markdown, text, reStructuredText and AsciiDoc parse with the base install. PDF, DOCX, PPTX and XLSX need the `[docs]` extra — without it those files are skipped and reported, never silently dropped.
Software architecture is the deepest-mapped domain today — typed down to the function — and for engineering teams it is usually the fastest way to see the value. It is a wedge, not the boundary.

---

## The compounding advantage

The first time you run GraQle, it knows your codebase. After a month, it knows your patterns. After a year, it holds the architectural lessons, decisions and document context your team accumulated — and activates them on the change that is about to repeat an old mistake.
The first time you run GraQle, it knows what you gave it. After a month, it knows your patterns. After a year, it holds the policies, decisions, architectural lessons and document context your organisation accumulated — and activates the relevant ones on the work that is about to repeat an old mistake.

This is the part that survives model churn. When you switch from one provider to another, or from one IDE to another, the graph is unchanged. You are not re-teaching a new model what your system is; you are pointing a different model at intelligence you already own.
This is the part that survives model churn. When you switch provider or IDE, the graph is unchanged. You are not re-teaching a new model what your organisation knows; you are pointing a different model at intelligence you already own.

> **Own the intelligence your models and agents create.** Enterprises can own their data and still lose the reasoning state accumulated inside external AI tools. The graph is a local file you control.
> **Own the intelligence your models and agents create.** Enterprises can own their data and still lose the reasoning state accumulated inside external AI tools — the decisions, the corrections, the hard-won context. The graph is a local file you control.

---

## How it works

1. **Scan** → AST + dependency analysis builds a typed graph (functions, classes, modules, imports, calls). Documents and policies enter the same graph as Document and Section nodes, auto-linked to the code they describe.
2. **Connect** → Relationships become first-class: `IMPORTS`, `CALLS`, `DEFINES`, `SECTION_OF`. This is what makes cross-file reasoning possible.
1. **Scan** → Documents, policies, ADRs and specs become Document and Section nodes. Codebases enter the same graph through AST + dependency analysis (functions, classes, modules, imports, calls). One substrate, whatever the source.
2. **Connect** → Relationships become first-class: `SECTION_OF`, `SEMANTICALLY_RELATED`, `IMPORTS`, `CALLS`, `DEFINES`. Taught knowledge is auto-linked to the documents and code it concerns. This is what makes reasoning *across* sources possible.
3. **Activate** → A pre-reasoning layer scores each node for relevance, confidence and risk **before** the LLM runs, so the model receives the relevant subgraph instead of the whole repository.
4. **Reason** → Multiple agents debate. Outputs carry `confidence`, `graph_health`, `active_nodes` and evidence pointers.
5. **Validate** → Answers below the confidence floor are refused rather than guessed.
Expand Down Expand Up @@ -143,13 +155,13 @@ Runs **fully offline** with Ollama or llama.cpp. Route different task types to d

| Use case | Command |
|:---|:---|
| **Policies, ADRs and specs into the graph** | `graq scan docs ./policies` · `graq learn doc ./decisions/` |
| **Institutional memory that outlives the session** | `graq learn knowledge "..."` · `graq learned` |
| **Ask across documents, decisions and code at once** | `graq run "what approval is needed above the refund limit?"` |
| Onboarding without a walkthrough | `graq run "how does checkout work end to end?"` |
| Blast radius before a change | `graq impact payments.py` |
| Cross-file security audit | `graq run "find every auth bypass risk"` |
| Architecture Q&A for onboarding | `graq run "how does checkout work end to end?"` |
| Institutional memory | `graq learn knowledge "..."` · `graq learned` |
| Policy + document context | `graq scan docs ./docs` · `graq learn doc ./policies/` |
| Pre-change safety check | `graq preflight "refactor the auth layer"` |
| Combined risk read | `graq safety-check` |
| CI/CD governance gate | `graq predict "..." --fail-below-threshold` |

---
Expand Down
50 changes: 33 additions & 17 deletions README_PYPI.md
Original file line number Diff line number Diff line change
@@ -1,42 +1,58 @@
# GraQle — give your AI a memory of how your system actually works
# GraQle — give your AI a memory of how your organisation actually works

**Turn codebases, documents, policies and decisions into a persistent knowledge graph, so your AI agents reason over architecture and prior lessons instead of re-reading files every session.**
**Turn policies, decisions, documents and codebases into a persistent knowledge graph, so your AI agents reason over what your organisation already knows instead of rebuilding a partial picture every session.**

```bash
pip install graqle
```

Models change. Tools change. Your architecture and institutional knowledge should not.
Models change. Tools change. Your institutional knowledge should not.

---

## 60-second proof
## 60-second proof — no code required

Works on a folder with no code in it at all.

```bash
# 1. Scan a codebase into a typed knowledge graph
graq scan repo .
# 1. Turn organisational documents into a typed graph
graq scan docs ./policies
# → 3 files → 12 nodes: 3 Document + 9 Section, linked by SECTION_OF

# 2. Ask an architectural question, not a file question
graq run "what breaks if I change the payment module?"
# → answer + confidence + evidence trail + active nodes
# 2. Teach it a rule that lives in nobody's file
graq learn knowledge "vendor DPA must be signed before any data access" --domain policy
# → auto-links the rule to the vendor-onboarding doc AND its "Due diligence" section

# 3. Ask across the whole body of knowledge
graq run "what approval is needed for a large refund?"
# → answer + confidence + evidence trail + the sections consulted

# 4. Audit what the organisation has taught it
graq learned
```

# 3. Teach it what code cannot tell it
graq learn knowledge "payment module must never call user service directly"
# → persists in the graph. Future reasoning activates this rule.
Step 2 is the one that compounds — and the one prompt engineering cannot replace, because it needs a persistent typed graph as the substrate. GraQle worked out where that rule belonged on its own.

### The same graph, for code

```bash
graq scan repo . # functions, classes, imports, calls
graq run "what breaks if I change the payment module?"
graq impact payments.py # blast radius
```

Step 3 is the one that compoundsand the one prompt engineering cannot replace, because it needs a persistent typed graph as the substrate.
Software architecture is the deepest-mapped domain todaya wedge, not the boundary.

---

## Why this matters now

Agents are getting far more capable, and still reconstruct your system from scratch every session. Models are becoming cheaper and interchangeable, which makes the intelligence layer above them — not the model itself — the thing worth owning.
Agents are getting far more capable and still start from zero every session. Models are becoming cheaper and interchangeable, which makes the intelligence layer above them — not the model itself — the thing worth owning.

GraQle sits above the model:

- **Architecture, not files.** AI assistants see files. GraQle sees relationships, dependencies and blast radius.
- **Memory that compounds.** Lessons and decisions become durable graph nodes, not chat history.
- **Relationships, not files.** Assistants see documents and files. GraQle sees how a policy, a decision and the code implementing it relate.
- **Memory that compounds.** Policies, decisions and lessons become durable graph nodes, not chat history.
- **Model independence.** Switch providers or IDEs without rebuilding the intelligence layer.

---
Expand Down Expand Up @@ -65,7 +81,7 @@ graq scan docs ./docs # architecture docs, runbooks, specs
graq learn doc ./policies/ # policies, ADRs, decision records
```

Documents become Document and Section nodes, auto-linked to the code they describe. Markdown, text, RST and AsciiDoc work with the base install; the richer formats need the `[docs]` extra and are reported — never silently skipped — when it's missing.
Documents become Document and Section nodes, linked by `SECTION_OF` — and to any code that implements them. Markdown, text, RST and AsciiDoc work with the base install; the richer formats need the `[docs]` extra and are reported — never silently skipped — when it's missing.

---

Expand Down
54 changes: 46 additions & 8 deletions graqle/cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -523,7 +523,17 @@ def run(
# Display results
console.print("\n[bold green]Answer:[/bold green]")
console.print(result.answer)
console.print(f"\n[dim]Confidence: {result.confidence:.0%} | "
# A placeholder answer must never carry a confidence figure. The fallback
# backend labels its text "NO LLM CONFIGURED", but printing a percentage
# underneath made an unconfigured install read like a governed answer.
# backend_status is NOT usable here: it is only ever set to "failed" on an
# exception (core/graph.py), so the fallback path leaves it at "ok".
_conf_display = (
"not reported (no LLM configured)"
if getattr(backend, "is_fallback", False)
else f"{result.confidence:.0%}"
)
console.print(f"\n[dim]Confidence: {_conf_display} | "
f"Rounds: {result.rounds_completed} | "
f"Nodes: {result.node_count} | "
f"Cost: ${result.cost_usd:.4f} | "
Expand Down Expand Up @@ -2381,7 +2391,14 @@ def safety_check_command(
if not json_output:
from rich.markup import escape as rich_escape
console.print(f" {rich_escape(result.answer[:300])}")
console.print(f" [dim]Confidence: {result.confidence:.0%} | Cost: ${result.cost_usd:.4f}[/dim]")
# Same rule as `graq run`: no confidence figure on placeholder
# output from the silent no-backend-configured fallback.
_sc_conf = (
"not reported (no LLM configured)"
if getattr(backend, "is_fallback", False)
else f"{result.confidence:.0%}"
)
console.print(f" [dim]Confidence: {_sc_conf} | Cost: ${result.cost_usd:.4f}[/dim]")
except Exception as exc:
combined["reasoning"] = {"error": str(exc)[:200]}
if not json_output:
Expand Down Expand Up @@ -2742,10 +2759,18 @@ def reason(
console.print(f"Q: [green]{rich_escape(q)}[/green]")
console.print(f"A: {rich_escape(r.answer[:500])}")
mode_color = "green" if r.reasoning_mode == "full" else "yellow"
console.print(f"[dim]Confidence: {r.confidence:.0%} | Cost: ${r.cost_usd:.4f} | "
# Same rule as the single-query path: no confidence figure
# on placeholder output from the fallback backend.
_conf = ("not reported (no LLM configured)"
if getattr(backend, "is_fallback", False)
else f"{r.confidence:.0%}")
console.print(f"[dim]Confidence: {_conf} | Cost: ${r.cost_usd:.4f} | "
f"Mode: [{mode_color}]{r.reasoning_mode}[/{mode_color}][/dim]")
_avg = ("not reported (no LLM configured)"
if getattr(backend, "is_fallback", False)
else f"{avg_confidence:.0%}")
console.print(f"\n[bold]Batch Summary:[/bold] {len(queries)} queries | "
f"Avg confidence: {avg_confidence:.0%} | "
f"Avg confidence: {_avg} | "
f"Total cost: ${total_cost:.4f} | "
f"Total latency: {total_latency:.0f}ms")
return
Expand Down Expand Up @@ -2799,10 +2824,23 @@ def reason(
from rich.markup import escape as rich_escape
console.print(f"\n[bold green]Answer:[/bold green] {rich_escape(result.answer)}")
mode_color = "green" if result.reasoning_mode == "full" else "yellow"
console.print(f"[dim]Confidence: {result.confidence:.0%} | Rounds: {result.rounds_completed} | "
f"Nodes: {result.node_count} | Cost: ${result.cost_usd:.4f} | "
f"Latency: {result.latency_ms:.0f}ms | "
f"Mode: [{mode_color}]{result.reasoning_mode}[/{mode_color}][/dim]")
# A placeholder answer must never carry a confidence figure. The
# fallback backend already labels its text as "NO LLM CONFIGURED",
# but printing "Confidence: 62%" underneath made an unconfigured
# install read like a governed answer at a glance. backend_status
# is NOT usable here — it is only ever set to "failed" on an
# exception, so the fallback path leaves it "ok".
if getattr(backend, "is_fallback", False):
console.print(f"[dim]Confidence: not reported (no LLM configured) | "
f"Rounds: {result.rounds_completed} | "
f"Nodes: {result.node_count} | Cost: ${result.cost_usd:.4f} | "
f"Latency: {result.latency_ms:.0f}ms | "
f"Mode: [{mode_color}]{result.reasoning_mode}[/{mode_color}][/dim]")
else:
console.print(f"[dim]Confidence: {result.confidence:.0%} | Rounds: {result.rounds_completed} | "
f"Nodes: {result.node_count} | Cost: ${result.cost_usd:.4f} | "
f"Latency: {result.latency_ms:.0f}ms | "
f"Mode: [{mode_color}]{result.reasoning_mode}[/{mode_color}][/dim]")


@app.command()
Expand Down
Loading
Loading