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
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ python3 install.py # --cli-only, --dev, --prefix, --verify, --uninstal
# Pipe a single command (non-interactive; cli.py detects a non-tty stdin)
echo '/search "q2 plan"' | python3 -m glean_code

# Run the full test suite (1,148 tests, stdlib unittest — works with or without pytest)
# Run the full test suite (1,151 tests, stdlib unittest — works with or without pytest)
python3 -m pytest tests/
python3 -m unittest discover tests/

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ The full Glean Code REPL — slash commands, status bar, mock/live switching, se
| 🔐 **[SSO / OAuth](docs/SSO_OAUTH.md)** · **[Secure tokens](docs/SECURE_TOKENS.md)** | Browser sign-in, secure refs, the masking matrix |
| 🔌 **[MCP server](docs/MCP.md)** | Glean as native tools in Claude Code, Claude Desktop, Cursor |
| 🏛️ **[Architecture](docs/ARCHITECTURE.md)** · **[REST paths](docs/REST_PATHS.md)** | Module map, request flow, endpoints, how to add a command |
| ✅ **[Testing](docs/TESTING.md)** | Running the 1,148-test suite and what it covers |
| ✅ **[Testing](docs/TESTING.md)** | Running the 1,151-test suite and what it covers |
| 🛟 **[Support](SUPPORT.md)** · **[Changelog](CHANGELOG.md)** | How to report a bug · release history |

> [!NOTE]
Expand Down
Binary file added assets/graph_example.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
23 changes: 22 additions & 1 deletion docs/COMMANDS.md
Original file line number Diff line number Diff line change
Expand Up @@ -589,7 +589,28 @@ Four kinds of node, four kinds of edge, and every edge carries the evidence that
/graph "access review" --datasource confluence --min-shared 3
```

**Output** — A terminal summary: node and edge counts by kind, the hubs by degree, connected clusters with the node anchoring each, and the strongest content links with their shared terms. With `--html`, also an interactive page: pan, zoom, drag, and click a node to see every edge and why it exists.
**Output** — A terminal summary: node and edge counts by kind, the hubs by degree, connected clusters with the node anchoring each, and the strongest content links with their shared terms.

```text
27 nodes 10 doc · 4 person · 5 source · 8 container
43 edges 10 authored_by · 10 in_source · 10 in_container · 13 shares_term

hubs
▪ doc Quarterly Access Review Procedure 9 edges
▪ doc SEC-241 — Enforce MFA on internal service dashboards 7 edges
◆ person Nina Kowalski 6 edges

strongest content links
Quarterly Access Review Procedure
↓ shares account, long-lived, access, service (5.1)
SEC-233 — Rotate service account keys before audit window
```

With `--html`, also an interactive page — pan, zoom, drag, and click a node to see every edge and why it exists:

![The /graph HTML view with one document selected and its edges listed](../assets/graph_example.png)

Full detail on the model and the scoring: [Knowledge Graph](GRAPH.md).

**Mock mode** — Fully supported. The mock corpus carries an author, datasource and container on all seventy documents, so the graph is complete offline.

Expand Down
10 changes: 9 additions & 1 deletion docs/GRAPH.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,15 @@ edges in score order.
## The HTML view

`--html <path>` writes a self-contained page: one file, no CDN, no framework, no network —
the same constraint `/flow timeline` works under. Inside it:
the same constraint `/flow timeline` works under.

![The /graph HTML view: a force-directed graph of the access review result set, with one document selected and its edges listed](../assets/graph_example.png)

*`/graph "access review" --html access.html` against the mock corpus, with the hub document
selected. Its neighbours stay lit while everything else dims, and the panel lists all nine of
its edges — each with the words that earned it and the score they carry.*

Inside it:

- A force-directed layout, seeded from deterministic ring positions so the same graph opens
the same way, then relaxed in the browser.
Expand Down
4 changes: 2 additions & 2 deletions docs/TESTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ files, and they outrank the `Glean Code.app` launcher in `Cmd+Space`:
export PYTHONPYCACHEPREFIX="$HOME/.cache/python"
```

1,148 tests covering the client and every mock response, commands and dispatch, config, UI, auth, completion, help docs, the mock corpus, indexing-walk, scaffold, the installer, the MCP server, the flow mapper, the Pages site builder, the knowledge graph, and Glean Personal (text extraction, the index, the content graph, ranking explanations, local mode, and the local MCP tools).
1,151 tests covering the client and every mock response, commands and dispatch, config, UI, auth, completion, help docs, the mock corpus, indexing-walk, scaffold, the installer, the MCP server, the flow mapper, the Pages site builder, the knowledge graph, and Glean Personal (text extraction, the index, the content graph, ranking explanations, local mode, and the local MCP tools).

## Development notes

Notes on the test suite added during development of glean-code-cli.

All 1,148 tests pass. Here's what was added across the development passes:
All 1,151 tests pass. Here's what was added across the development passes:

`tests/test_commands_extended.py` (155 new tests) — covers all previously untested commands:

Expand Down
25 changes: 25 additions & 0 deletions tests/test_graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -305,5 +305,30 @@ def test_registered_with_help_docs(self):
self.assertIn("--html", DOCS["graph"]["usage"])


class TestDocs(unittest.TestCase):
"""The screenshot in the docs is an asset like any other: it can go missing."""

REPO = Path(__file__).resolve().parents[1]

def test_screenshot_exists_and_is_a_png(self):
shot = self.REPO / "assets" / "graph_example.png"
self.assertTrue(shot.is_file(), "assets/graph_example.png is missing")
self.assertEqual(shot.read_bytes()[:8], b"\x89PNG\r\n\x1a\n")

def test_docs_reference_the_screenshot_with_a_working_path(self):
for name in ("GRAPH.md", "COMMANDS.md"):
doc = self.REPO / "docs" / name
body = doc.read_text(encoding="utf-8")
self.assertIn("../assets/graph_example.png", body, name)
# the path is relative to the document, so resolve it from there
self.assertTrue((doc.parent / "../assets/graph_example.png").resolve().is_file())

def test_screenshot_has_alt_text(self):
body = (self.REPO / "docs" / "GRAPH.md").read_text(encoding="utf-8")
line = next(l for l in body.split("\n") if "graph_example.png" in l)
alt = line[line.index("![") + 2:line.index("]")]
self.assertGreater(len(alt), 20, "alt text should describe the image")


if __name__ == "__main__":
unittest.main()
Loading