[build-system] requires = ["hatchling"] build-backend = "hatchling.build" [project] name = "graqle" # V-ADR240-DELTA: native version bump (G4 config, CG-14 native-edit precedent). # 0.84.0 = CR-README-01 public repositioning (README + PyPI long-description now # lead with persistent organisational intelligence; readme pointer moved to # README_PYPI.md so PyPI finally renders the conversion page) + CR-010.R3 # compliance packs as data (x-sox SOX/COSO first) + CR-DIST-06 distribution # manifest autosync. 0.83.0 = CR-010 R6 scheduler contract (--headless/--json/--report-json, # exit codes 0/1/2/3) + ADR-245 W3 reasoning-quota wall (free monthly cap on # graph reasoning). 0.79.0 = ADR-242-A1 CR-SEED-02: graqle.workflow.seed — seed a project graph # from goal + build profile + source chunks before any code exists, and the # flat-scanner-shape serializer for raw-dict graph consumers; additive, # backward-compatible, no IP concern. 0.78.0 = ADR-240 D1+D2: BackendRaceChain # (first-to-finish/best-of-N) + CostAwareRouter (auto cost/latency selection) — # dual-provider autonomy. 0.77.0 = ADR-239 Stage 2 # (CheckpointProtocol + run_tests). 0.76.0 = ADR-225 G1 multi-tenant memory. version = "0.84.0" description = "Persistent organisational intelligence for AI agents. Turn codebases, documents, policies and decisions into a knowledge graph so Claude Code, Cursor and Copilot reason over architecture, dependencies and prior lessons — with confidence scores and evidence. 13 LLM backends + custom, fully offline capable." readme = "README_PYPI.md" license = {text = "Apache-2.0"} requires-python = ">=3.10" authors = [ { name = "Harish Kumar", email = "harish.kumar@quantamixsolutions.com" }, ] keywords = [ "knowledge-graph", "code-analysis", "dependency-analysis", "architecture", "impact-analysis", "code-intelligence", "mcp", "mcp-server", "claude-code", "cursor", "vscode", "copilot", "ai-coding", "codebase-reasoning", "graqle", "graph-reasoning", "dev-intelligence", "development-tools", "static-analysis", "code-quality", "cli", "refactoring", "multi-agent", "reasoning", "governance", "ai-assistant", "code-understanding", "institutional-memory", # Category keywords — ADR-README-001 repositioning toward persistent # organisational intelligence. The code keywords above stay: code # architecture remains the developer wedge and the discovery path. "organizational-intelligence", "organisational-intelligence", "persistent-memory", "agent-memory", "context-engineering", "document-intelligence", "ai-governance", "governed-autonomy", "model-agnostic", "rag-alternative", ] classifiers = [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "Intended Audience :: Science/Research", "Intended Audience :: System Administrators", "License :: OSI Approved :: Apache Software License", "Environment :: Console", "Operating System :: OS Independent", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Topic :: Scientific/Engineering :: Artificial Intelligence", "Topic :: Software Development :: Libraries :: Python Modules", "Topic :: Software Development :: Quality Assurance", "Topic :: Software Development :: Testing", ] dependencies = [ "cryptography>=42.0", "jsonschema>=4.0", "networkx>=3.0", "numpy>=1.24", "pydantic>=2.0", "pydantic-settings>=2.0", "pyyaml>=6.0", "rfc8785==0.1.4", "typer[all]>=0.9", "rich>=13.0", "fastapi>=0.100", "uvicorn[standard]>=0.20", "jinja2>=3.1", ] [project.optional-dependencies] embeddings = [ "sentence-transformers>=2.2,<3.0", ] gpu = [ "torch>=2.0,<2.5", "transformers>=4.35,<4.50", "peft>=0.7,<0.14", "vllm>=0.3", "sentence-transformers>=2.2,<3.0", ] cpu = [ "llama-cpp-python>=0.2", "sentence-transformers>=2.2,<3.0", ] lite = [] neo4j = [ "neo4j>=5.0", ] watch = [ # v0.63.0: enables MCP background filesystem watcher (auto-grow on file # change). SPEC-v063-mcp-background-grow.md + ADR-213. Optional — the # watcher gracefully degrades to "disabled" if watchdog is missing. "watchdog>=3.0,<5.0", ] api = [ "anthropic>=0.18", "openai>=1.0", "boto3>=1.28", "httpx>=0.25", "pyshacl>=0.25.0", "rdflib>=7.0.0", "neo4j>=5.0", # V-A1B-NATIVE-003: native Edit — graq_edit G4 gate demands a CG-14 baseline # accept that inline approved_by does not satisfy (CG-G4-CONFIG gap). # A1b: Cognito ID-token signature verification (cross-tenant trust root). "pyjwt[crypto]>=2.8", ] server = [ "fastapi>=0.100", "uvicorn[standard]>=0.20", ] studio = [ "fastapi>=0.100", "uvicorn[standard]>=0.20", "jinja2>=3.1", ] docs = [ "pdfplumber>=0.9", "python-docx>=0.8", "python-pptx>=0.6", "openpyxl>=3.1", ] scorch = [ "playwright>=1.40", "Pillow>=10.0", "boto3>=1.28", ] phantom = [ "playwright>=1.40", "Pillow>=10.0", "boto3>=1.28", ] all = [ "graqle[embeddings,neo4j,api,server,studio,docs,scorch,phantom]", ] all-gpu = [ "graqle[all,gpu]", ] security = [ # V-CR-BIZQ-001-NATIVE-S2-010/012: pin sigstore to 3.x — the Rekor transport # (anchors/sigstore_rekor.py) uses RekorClient.production() + the rekor_types # Hashedrekord proposal. 2.x's bundled TUF trust root has aged out of the live # Sigstore infra ("no active Rekor key"); 4.x restructured the Rekor v2 client. "sigstore>=3.0,<4.0", "cyclonedx-bom>=4.0", "pip-audit>=2.6", ] dev = [ "pytest>=7.0", "pytest-asyncio>=0.21", "pytest-xdist>=3.0", "pytest-mock>=3.10", "pytest-env>=1.0", "pytest-cov>=4.0", "mypy>=1.0", "ruff>=0.1", "coverage>=7.0", "httpx>=0.25", "boto3>=1.28", "requests>=2.28", "rdflib>=7.0.0", "pyshacl>=0.25.0", # V-A1B-NATIVE-005: A1b — PyJWT is needed to TEST the Cognito-JWT trust root # (tests/test_studio/test_auth.py). The CI `test` job installs only `.[dev]`, # so without this the test module fails collection (ModuleNotFoundError: jwt). "pyjwt[crypto]>=2.8", ] [project.scripts] graq = "graqle.cli.main:app" [project.urls] Homepage = "https://graqle.com" Documentation = "https://github.com/quantamixsol/graqle#readme" Repository = "https://github.com/quantamixsol/graqle" Changelog = "https://github.com/quantamixsol/graqle/releases" "Bug Tracker" = "https://github.com/quantamixsol/graqle/issues" "Patent Notice" = "https://quantamixsolutions.com/patents" [tool.hatch.build.targets.sdist] exclude = ["graqle/benchmarks/data/*", "paper/*", "patent/*"] [tool.hatch.build] artifacts = [ "graqle/integrations/bridges/*.md", "graqle/docs/*.md", # T09 (v0.51.6): ship MCP tool inventory in wheel # P1 (ADR-222): ship the governance constitution single-source-of-truth so # `graq init` renders the full rulebook into CLAUDE.md/AGENTS.md/etc. Without # this the .md fragments are stripped from the wheel and init silently falls # back to the abridged inline copy. Owner-approved (harish, 2026-06-07). # V-CR-GOV-INSTALL-P1-NATIVE-001: graq_edit G4 + graq_config_audit could not # resolve the worktree path (S-010 class); native edit with recorded approval. "graqle/data/constitution/*.md", # ed25519 cutover (ADR-215 §5): the Community trust source — PUBLIC licence # signing keys so offline installs can verify v2 licences. Public-key-only # (the private signer is server-side; keygen.py is excluded below). "graqle/licensing/trusted_keys.json", # CR-010.R1: the frozen proof spec + its conformance corpus. These MUST ship # in the wheel — the whole point is that a third party can implement a # conformant verifier from the published schemas + golden vectors alone. # Loaded via importlib.resources (never __file__), so they resolve from a # zip-imported wheel. Spec version is decoupled from the SDK version. "graqle/pct/schema/proof-spec/**/*.json", "graqle/pct/schema/proof-spec/**/*.md", "graqle/pct/schema/conformance/*.json", "graqle/pct/schema/conformance/fixtures/*", # CR-010.R3: compliance packs are DATA — a framework is a pack.yaml plus a # schema.json, so adding NIST AI RMF / ISO 42001 needs no Python. These MUST # ship in the wheel or the packs silently vanish from an installed SDK and # only first-party imports keep working. Loaded via importlib.resources # (never Path(__file__).parents[N], which resolves elsewhere once installed). "graqle/compliance/packs/**/*.yaml", "graqle/compliance/packs/**/*.json", ] [tool.hatch.build.targets.wheel] packages = ["graqle"] exclude = [ "graqle/benchmarks/data/*", # B3/S2: shapes.ttl excluded from wheel — structural SHACL logic is # readable even with opaque URNs; keep it server-side only until ADR-206 # documents accepted disclosure posture before public PyPI. "graqle/governance/shacl/shapes.ttl", # WS-C C1 (ADR-BIZ-001): the Community (Apache-2.0) wheel ships WITHOUT the # proprietary commercial backends. These live in the source tree but are # carved out of the public wheel; the proprietary graqle-studio / # graqle-enterprise distributions re-include them. The thin cli/commands/* # wrappers ship and degrade gracefully (graqle/cli/_edition_guard.py) when a # backend is absent. An import-direction CI gate enforces that no Community # module eagerly imports these (lazy-only invariant). scorch + phantom are # NON-CORE plugins and intentionally REMAIN in Community (Harish, 2026-06-01). "graqle/cloud/*", "graqle/leads/*", "graqle/studio/*", "graqle/server/*", # WS-D D-pkg (ADR-BIZ-001): the admin licence SIGNER must not ship in the # public Community wheel. keygen.py embeds the legacy HMAC signing secret # (its own docstring: "never distribute to end users"); generate_key signs # licences. With ed25519 (WS-D) the wheel verifies with a PUBLIC key only and # cannot forge, but excluding the signer is belt-and-suspenders — the public # artifact carries verification, never issuance. "graqle/licensing/keygen.py", # WS-F (ADR-BIZ-001): trade-secret calibration internals — TS-1..TS-4 # implementation details (weights, AGREEMENT_THRESHOLD, J̄ formula, θ_fold # derivation, STG production rules). The Community wheel ships the public # interface (output scores, status enums) but never the computation internals. # The trade-secret wheel gate (scripts/ci/trade_secret_wheel_gate.py) enforces # this mechanically on every PR and release build. "graqle/governance/calibration.py", "graqle/governance/calibration_store.py", ] [tool.hatch.build.targets.wheel.force-include] # NOTE: graqle/data/claude_gate is covered by packages=["graqle"] above. # Adding a force-include for a path already under the packages tree # creates duplicate local-header entries in the wheel ZIP and causes # PyPI to reject the upload with HTTP 400 "Duplicate filename in # local headers". Only force-include paths OUTSIDE the packages tree. "examples" = "graqle/examples" [tool.ruff] target-version = "py310" line-length = 100 [tool.ruff.lint] select = ["E", "F", "I", "N", "W", "UP"] [tool.mypy] python_version = "3.10" strict = true warn_return_any = true [tool.pytest.ini_options] testpaths = ["tests"] asyncio_mode = "auto" # Parallel execution: safe tests run with -n auto; serial-marked tests excluded # Usage: # Fast (parallel, no CLI/subprocess): pytest -n auto -m "not serial" # Full suite serial: pytest tests/ # Full suite parallel (experimental): pytest -n auto markers = [ "serial: mark test to run serially (not safe for parallel execution)", "slow_subprocess: mark test as spawning subprocesses (inherently slow)", "integration: mark test as requiring external infra (Neo4j, etc.); excluded from fast unit CI", ] # xdist: keep each file's tests on a single worker to prevent chdir() conflicts # Use: pytest -n auto -m "not serial" for fast parallel run addopts = "--dist=loadfile"