Skip to content

Commit a532887

Browse files
Publish multi-page documentation site
Nine pages generated from README.md, ROADMAP.md, CONTRIBUTING.md and docs/cookbook/01-06: overview, getting started, models, agents & tools, verification & memory, governance, serving & operations, roadmap, contributing. Static HTML + one stylesheet, no build step. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
0 parents  commit a532887

11 files changed

Lines changed: 3105 additions & 0 deletions

.nojekyll

Whitespace-only changes.

agents-and-tools.html

Lines changed: 380 additions & 0 deletions
Large diffs are not rendered by default.

contributing.html

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1">
6+
<title>Contributing — GraphARC</title>
7+
<meta name="description" content="Tests, the live-marker rule, PR conventions, and the honesty rule for docs.">
8+
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>📚</text></svg>">
9+
<link rel="stylesheet" href="style.css">
10+
</head>
11+
<body>
12+
<div class="layout">
13+
<nav class="side" aria-label="Documentation contents">
14+
<a class="brand" href="index.html"><b>GraphARC<span class="amp"> docs</span></b><span>a governed agent runtime on LangGraph</span></a>
15+
<ul>
16+
<li class="nav-chapter"><a href="index.html">Overview</a>
17+
</li>
18+
<li class="nav-chapter"><a href="getting-started.html">Getting started</a>
19+
</li>
20+
<li class="nav-chapter"><a href="models.html">Models</a>
21+
</li>
22+
<li class="nav-chapter"><a href="agents-and-tools.html">Agents & tools</a>
23+
</li>
24+
<li class="nav-chapter"><a href="verification-and-memory.html">Verification & memory</a>
25+
</li>
26+
<li class="nav-chapter"><a href="governance.html">Governance</a>
27+
</li>
28+
<li class="nav-chapter"><a href="serving-and-ops.html">Serving & operations</a>
29+
</li>
30+
<li class="nav-chapter"><a href="roadmap.html">Roadmap</a>
31+
</li>
32+
<li class="nav-chapter"><a class="active" href="contributing.html">Contributing</a>
33+
<ul><li><a href="#intro">Intro</a></li><li><a href="#setup">Setup</a></li><li><a href="#running-the-tests">Running the tests</a></li><li><a href="#the-live-marker-rule">The live-marker rule</a></li><li><a href="#writing-a-change-pr-conventions">Writing a change (PR conventions</a></li><li><a href="#the-honesty-rule-for-documentation">The honesty rule for documentation</a></li><li><a href="#packaging-changes">Packaging changes</a></li><li><a href="#releasing">Releasing</a></li></ul>
34+
</li>
35+
</ul>
36+
</nav>
37+
<main>
38+
<header class="page-head">
39+
<h1>Contributing</h1>
40+
<p class="sub">Tests, the live-marker rule, PR conventions, and the honesty rule for docs.</p>
41+
</header>
42+
<h2 id="intro"><a class="anchor" href="#intro">Intro</a></h2>
43+
<p>The file covers the three things easiest to get wrong in this repo: how to run the tests, the rule that keeps live tests from spending your money, and the standard the project holds documentation to.</p>
44+
<h2 id="setup"><a class="anchor" href="#setup">Setup</a></h2>
45+
<p>The toolchain is uv. <code>uv.lock</code> is committed, so everyone resolves to the same versions. <code>--all-extras</code> matters, because several tests skip themselves when an optional dependency is missing — syncing only the dev group silently shrinks the suite instead of failing.</p>
46+
<figure class="term"><figcaption class="term-bar"><span class="dot"></span><span class="dot"></span><span class="dot"></span><span class="term-cmd">bash</span></figcaption><pre class="term-body">git clone https://github.com/CodeGraphContext/GraphARC
47+
cd GraphARC
48+
uv sync --all-extras --group dev</pre></figure>
49+
<h2 id="running-the-tests"><a class="anchor" href="#running-the-tests">Running the tests</a></h2>
50+
<p>Standard pytest invocations for the whole suite, a single file, a pattern, or first-failure. Lint and autofix with ruff. Both are what CI runs (<code>.github/workflows/ci.yml</code>), across Python 3.12, 3.13 and 3.14.</p>
51+
<figure class="term"><figcaption class="term-bar"><span class="dot"></span><span class="dot"></span><span class="dot"></span><span class="term-cmd">bash</span></figcaption><pre class="term-body">uv run pytest # the whole suite
52+
uv run pytest tests/test_server.py # one file
53+
uv run pytest -k retrieval # one pattern
54+
uv run pytest -x -q # stop at the first failure</pre></figure>
55+
<figure class="term"><figcaption class="term-bar"><span class="dot"></span><span class="dot"></span><span class="dot"></span><span class="term-cmd">bash</span></figcaption><pre class="term-body">uv run ruff check . --fix</pre></figure>
56+
<h2 id="the-live-marker-rule"><a class="anchor" href="#the-live-marker-rule">The live-marker rule</a></h2>
57+
<p><strong>A test marked <code>live</code> calls a real model backend and spends real money.</strong> Never run <code>pytest -m live</code> casually, never in CI, and never because a failing test looked like it might pass against a real model. The mechanics, so you can tell when they are broken: <code>addopts</code> in <code>pyproject.toml</code> carries <code>-m &#x27;not live&#x27;</code> and must stay there; <code>addopts</code> also carries <code>--strict-markers</code>, which is part of the same guarantee rather than a style preference, since without it a misspelled <code>@pytest.mark.lvie</code> is only a warning and the test calls the API on a plain <code>pytest</code>; every marker must be registered in the <code>markers</code> table before use, and <code>tests/test_packaging.py</code> fails if the tree uses one that is not; <code>required_plugins</code> names <code>pytest-asyncio</code> and <code>pytest-timeout</code>, because registering their markers locally would make a missing plugin silent with no timeout enforced; and CI has a <code>live-marker-guard</code> job comparing the default selection against the <code>-m live</code> selection, failing if anything is in both.</p>
58+
<figure class="term"><figcaption class="term-bar"><span class="dot"></span><span class="dot"></span><span class="dot"></span><span class="term-cmd">bash</span></figcaption><pre class="term-body">pytest # &#x27;not live&#x27; — every paid test is deselected
59+
pytest -m live # opt in, deliberately, with your own key</pre></figure>
60+
<div class="codeblock"><div class="code-lang">python</div><pre class="code-body">@pytest.mark.live
61+
<span class="tok-k">def</span> test_something_against_a_real_backend():
62+
...</pre></div>
63+
<aside class="edge"><span class="edge-tag">sharp edge</span> Mark a live test, keep it out of any fixture the default suite touches, and say in the test what it costs to run.</aside>
64+
<h2 id="writing-a-change-pr-conventions"><a class="anchor" href="#writing-a-change-pr-conventions">Writing a change (PR conventions</a></h2>
65+
<p><strong>One concern per PR</strong> — a fix and the refactor around it are two PRs. <strong>A bug fix comes with a test that fails without it</strong>: prove it by reverting the fix, watching the new test go red, and putting the fix back; a test that passes either way is documentation, not a regression guard. <strong>Never weaken an existing test to make a change pass</strong> — if an assertion is genuinely wrong, say so in the PR and explain why in the same breath as changing it. <strong>Keep <code>ruff check .</code> clean</strong>; line length is 100. <strong>Note behaviour changes in the commit message</strong> when you change behaviour, the public API, or what ships.</p>
66+
<h2 id="the-honesty-rule-for-documentation"><a class="anchor" href="#the-honesty-rule-for-documentation">The honesty rule for documentation</a></h2>
67+
<p>Enforced hardest, because this repo has broken it before and the ROADMAP still carries a <code>!</code> legend entry for claims that shipped while being false. <strong>A docstring, a README line, or a comment must not claim a guarantee the code does not provide</strong> — not &quot;aspirationally&quot;, not &quot;once the TODO lands&quot;, not because the happy path happens to hold. Concretely: if a function is confined, sandboxed, budgeted, atomic, ordered or durable <strong>only under conditions</strong>, name the conditions in the docstring (<code>render_context</code> documents the single case where it overshoots <code>max_tokens</code>; <code>LocalExecutor</code> is named for what it does not do). If something is defense in depth rather than a boundary, say which (<code>SandboxedExecutor</code> is an audit-hook sandbox, not a kernel boundary, and its docstring says so). If a name oversells the thing — the way an exact-string match was once labelled &quot;GraphRAG&quot; — rename it or write down precisely what it does (<code>HashingEmbedder</code>&#x27;s docstring states it is lexical, not semantic). If an extra, config key or parameter exists but nothing implements it yet, say that where a reader will hit it — the optional-dependency table in <code>pyproject.toml</code> states, per extra, whether anything under <code>grapharc/</code> imports it today. When you fix something, fix the prose in the same commit: a stale docstring that used to be true is exactly as harmful as one that was never true.</p>
68+
<aside class="edge"><span class="edge-tag">sharp edge</span> The failure mode to avoid is confident prose over a guarantee the code does not provide. A missing feature is fine; a feature documented as working that is not will cost somebody a debugging session, or will be trusted with something it cannot hold.</aside>
69+
<aside class="edge"><span class="edge-tag">sharp edge</span> If you cannot close a gap, write the gap down — <code>ROADMAP.md</code> has a <em>Known gaps</em> section for exactly that.</aside>
70+
<h2 id="packaging-changes"><a class="anchor" href="#packaging-changes">Packaging changes</a></h2>
71+
<p><code>pyproject.toml</code> is the authority for what ships. <code>[tool.hatch.build.targets.sdist].include</code> is an allowlist, so a new top-level file that should ship has to be added there; <code>MANIFEST.in</code> mirrors that list for readers and tools, hatchling never reads it, and <code>tests/test_packaging.py</code> fails if the two drift. <code>[tool.hatch.build].ignore-vcs</code> is on deliberately, because with hatchling&#x27;s default a <code>.gitignore</code> entry doubles as a build exclusion — verified to drop the whole <code>grapharc/tools</code> subpackage out of the wheel with no error and a successful build; junk you want kept out belongs in <code>[tool.hatch.build].exclude</code>. After a packaging change, build and install into a throwaway environment rather than trusting the build&#x27;s exit code. CI does the same on every PR, for both the wheel and the sdist.</p>
72+
<figure class="term"><figcaption class="term-bar"><span class="dot"></span><span class="dot"></span><span class="dot"></span><span class="term-cmd">bash</span></figcaption><pre class="term-body">uv build
73+
uv venv /tmp/check &amp;&amp; uv pip install --python /tmp/check/bin/python &quot;$(echo dist/*.whl)[all]&quot;
74+
cd /tmp &amp;&amp; /tmp/check/bin/python -c &quot;import grapharc, pkgutil, importlib
75+
[importlib.import_module(m.name) for m in pkgutil.walk_packages(grapharc.__path__, &#x27;grapharc.&#x27;)]&quot;
76+
/tmp/check/bin/grapharc --version</pre></figure>
77+
<h2 id="releasing"><a class="anchor" href="#releasing">Releasing</a></h2>
78+
<p>Tag-driven. <code>.github/workflows/release.yml</code> refuses a tag that disagrees with the version in <code>pyproject.toml</code>, builds, verifies the artifacts in clean environments, and publishes through PyPI Trusted Publishing. There is no API token in this repository or in its secrets. Steps: bump <code>version</code> in <code>pyproject.toml</code> <strong>and</strong> <code>__version__</code> in <code>grapharc/__init__.py</code> (CI fails if the two disagree); tag the release, with the commit log as the record of what changed; tag <code>vX.Y.Z</code> and push it.</p>
79+
<aside class="edge"><span class="edge-tag">sharp edge</span> The three numbered steps are partly redundant — step 2 and step 3 both describe tagging.</aside>
80+
<p>Source files read in full: <code>/home/shashank/Desktop/GraphARC/README.md</code>, <code>/home/shashank/Desktop/GraphARC/ROADMAP.md</code>, <code>/home/shashank/Desktop/GraphARC/CONTRIBUTING.md</code>. Referenced but not read: <code>/home/shashank/Desktop/GraphARC/docs/diagrams/</code> (architecture.png, 03-agent-node.png, grapharc-architecture.drawio, architecture.py), <code>/home/shashank/Desktop/GraphARC/docs/cookbook/</code>, <code>/home/shashank/Desktop/GraphARC/grapharc/examples/plan_incident.py</code>, <code>/home/shashank/Desktop/GraphARC/grapharc/policy/example.toml</code>, <code>/home/shashank/Desktop/GraphARC/grapharc/stdlib.py</code>.</p>
81+
<footer class="pager-row">
82+
<a class="pager prev" href="roadmap.html">&larr; Roadmap</a><span class="pager-spacer"></span>
83+
</footer>
84+
<footer class="colophon">
85+
Generated from the repository's README and cookbook (docs/cookbook/01–06) ·
86+
<a href="https://github.com/CodeGraphContext/GraphARC">CodeGraphContext/GraphARC</a> · MIT license
87+
</footer>
88+
</main>
89+
</div>
90+
91+
<script>
92+
(function () {
93+
var links = document.querySelectorAll('.nav-chapter ul a');
94+
var byId = {};
95+
links.forEach(function (a) { byId[a.getAttribute('href').slice(1)] = a; });
96+
var current = null;
97+
var obs = new IntersectionObserver(function (entries) {
98+
entries.forEach(function (e) {
99+
if (e.isIntersecting) {
100+
var a = byId[e.target.id];
101+
if (a) {
102+
if (current) current.classList.remove('active');
103+
a.classList.add('active');
104+
current = a;
105+
}
106+
}
107+
});
108+
}, { rootMargin: '0px 0px -70% 0px' });
109+
document.querySelectorAll('main h2[id]').forEach(function (h) { obs.observe(h); });
110+
})();
111+
</script>
112+
</body>
113+
</html>

0 commit comments

Comments
 (0)