Pass dedup=False into graph construction so repeated labels do not collapse distinct non-AST identities. Preserve existing AST and document-file twin reconciliation. Fixes#4019.
Assisted-by: OpenAI Codex (GPT-6)
(cherry picked from commit 1f3805f16e)
The top-of-README language switcher already lists every language; keep
the bottom section as a short pointer to docs/translations/ and the
PR-to-contribute call, instead of duplicating the full table.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
List all 32 README languages in a dedicated Translations section (a
#translations anchor), like other large OSS READMEs, with a pointer to
docs/translations/ for improving or adding one.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add a one-click "Install in VS Code" button (uvx --from graphifyy[mcp]
graphify-mcp, no API key) and a Smithery install command for the MCP
server, plus a Smithery badge linking to the server page as the
ownership backlink Smithery verifies.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Register .vh with the existing Verilog detection and extraction paths,
including incremental and watch coverage.
Refs #3749
AI-Assisted-By: OpenAI Codex
(cherry picked from commit 3b74b8ad3d)
After `uv tool upgrade graphifyy` or `pip install -U graphifyy`, the
installed skills stay on the old version. `graphify install` only fixes
the platform it detects, so codex, opencode, gemini and the others keep
running outdated instructions until someone reinstalls each one by hand.
The CLI now checks the version stamp of every user-scope skill on its
first run after an upgrade, `graphify update` included, and re-copies
the ones that are older than the package. This is on by default and can
be turned off with GRAPHIFY_NO_AUTO_REFRESH=1.
It is deliberately conservative about what it touches:
- only skills graphify installed itself (stamp and SKILL.md both present)
- never a skill newer than the package, so nothing gets downgraded (#1568)
- never a directory that two installers write to, such as copilot and
`graphify vscode install`, or two platform dirs symlinked to the same
place, because the stamp can't say which variant lives there
- a locally edited SKILL.md is kept as SKILL.md.bak (#3144)
Install, uninstall and the refresh take the same lock per skill
directory, so two processes never write through each other's fixed
.tmp staging names, and an uninstall can't race a refresh that would
put the skill back. It is an OS file lock (flock on POSIX,
msvcrt.locking on Windows). The OS releases it however the holder
exits, so a crash never leaves a directory locked and there is no
staleness timeout to tune. The lock file lives under
~/.cache/graphify/skill-locks/ rather than in the skill directory, so a
project install leaves nothing behind in the repository. Install and
uninstall wait for the lock; the refresh skips a directory another
process holds and reads the stamp again once it has the lock. Where the
file system can't lock, install and uninstall run unlocked as they did
before, and the refresh leaves the skill to the version warning.
Output goes to stderr, one line per refreshed directory, so --json and
the MCP stdio server are unaffected. A failed refresh never breaks the
command the user actually ran: the stamp stays old and the existing
version warning still points to the manual fix.
While here, the version warning now also checks the gemini skill, which
it used to miss because gemini is not in _PLATFORM_CONFIG, and the vscode
skill path moved into _vscode_skill_destination() so install, uninstall
and the refresh share it. The README lists the new variable and mentions
the refresh in the version-mismatch troubleshooting entry.
(cherry picked from commit 50ebe642af)
Add a Contributors section rendering the contributor avatars via
contrib.rocks, linking to the contributors graph.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- The bare 'graphify' / 'graphify --help' screen now prints the logo
banner on top (TTY-gated, reusing _print_banner) and the
app.graphify.com hosted-platform line at the bottom, matching the
install banner.
- Update the hosted-platform offer copy to 'Try the graphify platform
free for 14 days' across the CLI help, the install banner, and the
README early-access banner (was 'open free before the public v1 launch').
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Add CI status, Apache-2.0 license, and Docs (docs.graphify.com) badges
to the top row (health signals were absent).
- Link docs.graphify.com from 'Learn more' and repoint the issue-template
Documentation contact to the docs site (was README, 0 prior mentions).
- Replace the inline Contributing <details> block (duplicated CONTRIBUTING.md
and prone to drift) with a short pointer to CONTRIBUTING.md/ARCHITECTURE.md;
the issue-template Contributing link already targets CONTRIBUTING.md.
README drops from ~64.8 KB to ~62 KB.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Follow-up edits on #3845 to match the settled maintainer decisions:
- CODE_OF_CONDUCT.md: set the enforcement/reporting contact to
safi@graphify.com (was an unspecified 'email the maintainer if known').
- README team-graph section: add the machine-local never-commit list
(.graphify_root, .graphify_python, .graphify_analysis.json, the AST
cache, needs_update) and the re-extract-to-update note. manifest.json
stays committable since #3781 made its keys portable.
- Add RELEASING.md (maintainer-facing): version bump + changelog +
uv.lock, test on 3.10/3.13, push v8, gh release create -> PyPI via
trusted publishing (no twine/token), verify with uvx --refresh.
- CONTRIBUTING Further Reading: drop the paid Gumroad link, point at
RELEASING.md instead.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Point the README and he-IL translation at the single current invite (the old 2DDrEgvZb4/598Ad9zQZ links are retired). All Discord references now resolve to one canonical invite.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add a Robot Framework extractor using the official robot.api parser (pure-Python, optional
[robot] extra), emitting suite/test/keyword nodes plus keyword-call, resource-import, and
library edges. Keyword resolution is case/space/underscore-insensitive (RF's real semantics)
and handles BDD prefixes and ${CURDIR}/${EXECDIR} path resolution; degrades to an actionable
error when robotframework is absent.
Two accuracy corrections to the Recommended workflow table: the post-checkout hook rebuilds
only on branch switches (not a file-only git checkout -- <path>), and the commit/switch
rebuilds run detached in the background so the graph can briefly lag the commit.
Add a Recommended workflow section documenting that commits and branch switches rebuild the
graph automatically via the installed hooks, while a git pull/merge needs a manual
graphify update . (no pull hook exists), with a pull-alias shortcut and a troubleshooting
entry for a stale graph.
Adds --no-dedup (default off, so dedup stays on) to skip the fuzzy near-duplicate merge
pass on build and incremental merge, for operators who would rather keep distinct symbols
that fuzzy-matched than pay the merge. Exact-id uniqueness is unaffected (it is a graph
structural invariant, not a dedup responsibility), and the flag arms the #479 shrink
guard so a surprising node drop is refused loudly. Mutually exclusive with --dedup-llm.
A response that parses but carries no symbols (a "hollow" reply) was routed into the
truncation-bisection path, which just re-split a chunk the model had already answered
emptily, wasting calls. Give hollow its own finish_reason and route it through a bounded
same-chunk retry with backoff instead; on persistent hollow, give up loudly and mark the
files partial. GRAPHIFY_MAX_RETRY_DEPTH=0 now disables the hollow retry too, so a chunk
costs exactly one call. The #2866 timeout and the truncation paths still bisect.
tree-sitter-commonlisp-backed extractor for packages, classes, functions,
methods, generics, macros, variable definers, and same-file calls. Handles the
grammar's dedicated defun node (defun/defmacro/defmethod/defgeneric via
defun_header) and the generic list_lit + leading-symbol forms (defvar/defclass/
defpackage), recurses into wrapper macros (eval-when/progn) and reader
conditionals, and maps CL operator chars (= < > ? ! + *) to readable id
suffixes. Wired into detect/extract dispatch, the extractor registry, a
[commonlisp] optional extra, and the README; ships a fixture and a 23-test suite
behind an importorskip guard.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
New graphify/extractors/ocaml.py handles both the implementation grammar
(language_ocaml, .ml) and the interface grammar (language_ocaml_interface,
.mli). Emits nodes for modules, top-level/module-level values and functions,
types and their variant constructors; edges for defines/contains, open ->
imports_from, and application -> calls. Qualified paths (Geo.area) resolve to
the final value name, not the module qualifier; local let ... in bindings do
not mint nodes or steal call attribution. Cross-file open/call targets are
sourceless stubs so the corpus rewire collapses them onto the unique real
definition (no #1402 sourced-stub leak).
Wired into detect.py (CODE_EXTENSIONS), extract.py (dispatch +
_EXTRA_FOR_EXTENSION), pyproject.toml ([ocaml] extra + all + dev dep), and
README. Adds tests/test_ocaml.py (behind importorskip).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The two bedrock-runtime clients (primary extraction in _call_bedrock and
the secondary dispatch path in _call_llm) were built with no botocore
config, so Converse used botocore's 60s default read timeout and ignored
GRAPHIFY_API_TIMEOUT / --api-timeout entirely. A long opus-class
generation then died with "Read timeout on endpoint URL" no matter how
high the timeout was set.
Both client constructions now pass a botocore.config.Config wiring
read_timeout to _resolve_api_timeout() (default 600s), a 10s
connect_timeout, and retries from _resolve_max_retries() in adaptive
mode. This mirrors the fixes that closed the same gap for the claude-cli
subprocess (#1112/#1111) and the secondary LLM dispatch path (#1442) --
bedrock was the last cloud backend still ignoring the knob.
Also updates the README env-var row, which listed the timeout as
applying to HTTP/claude-cli/Anthropic only, and the _fake_boto3 test
fixture to register botocore.config and capture the client config so the
new coverage can assert the timeout is wired.
`graphify codex install` registers `graphify hook-check` in .codex/hooks.json,
and #2165 reported that as a stale/unrecognized subcommand producing a silent
no-op. `hook-check` is in fact a real, deliberate no-op command: Codex Desktop
rejects hookSpecificOutput.additionalContext on PreToolUse, so the Codex hook
intentionally does nothing and AGENTS.md carries the always-on guidance
(cli.py dispatches `hook-check`; __main__.py lists it in _silent_cmds).
Repointing the installer at `hook-guard` would reintroduce the #522-class
breakage on Codex Desktop, so the behavior is left as is.
What actually misled the report was the documentation and the installer's own
output, which both describe the Codex hook as if it enforced graph usage:
- README: the Codex row claimed a PreToolUse hook that "fires before every Bash
tool call, same always-on mechanism as Claude Code". It now states that the
hook is a deliberate no-op, why (Codex Desktop rejects additionalContext), and
that AGENTS.md is the always-on mechanism on this platform.
- `_install_codex_hook` printed "PreToolUse hook registered (... hook-check)"
with no hint that the entry is inert. It now says so inline.
Also adds the regression guard the issue implicitly asks for: a test that reads
the command out of the generated .codex/hooks.json and asserts its subcommand is
one the CLI actually dispatches. A genuinely renamed/stale hook command now
fails the suite instead of shipping a permanently dead hook.
Note: contrary to the report, an unrecognized subcommand already exits non-zero
(`graphify totally-bogus-subcommand` -> "error: unknown command", exit 1), so no
change was needed there.
The inline api.star-history.com SVG rate-limits on a repo this large and
serves a 503 instead of a chart, so the image was permanently broken.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The top-level `graphify --help` has listed --code-only since #1734, but the
`graphify extract` usage string and the README never mentioned it. A user
evaluating graphify on a "can this run with no network call" constraint sees
the extract usage / README first and can conclude the flag doesn't exist.
Add --code-only to the extract usage line, name it in the Privacy section and
the command reference, and add a test asserting the usage advertises it.
`uv run --with graphifyy python -m graphify` runs the system interpreter, so an
older `graphifyy` in system site-packages loads before the uv-managed one — with
no error. Env overrides like OPENAI_BASE_URL are then ignored and requests 401
against the default endpoint. The existing `skill is from graphify X, package is
Y` warning is the real fingerprint, but users dismiss it as a stale skill.
Add a troubleshooting entry next to the uvx-resolution one: name the symptom,
show how to confirm which module actually loaded, and point at
`uvx --from graphifyy` / uninstalling the stale copy.
GitHub is the top organic source of waitlist signups, but the only path to the
site was the logo and a CTA at the very bottom of the README. Add a short,
plain-voice waitlist line right after the value proposition, and change the
Enterprise-section CTA from "Learn more" to an explicit "Join the waitlist".
Rename the "Penpax" section to "graphify Enterprise" (linking graphify.com) and
add a Website badge to the Community and links footer.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Stamp the 0.9.19 release date, add a README note for the strict PreToolUse hook
(graphify install --project --strict), and credit both the #1814 reporter
(@Greg-Moskalenko) and the fix author (@alphanury).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Stamp the 0.9.18 release date and add a README troubleshooting entry for the
new #1951 behavior: an incomplete extraction refuses to overwrite a larger
existing graph, with --allow-partial as the escape hatch.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
querylog wrote every query/path/explain question + corpus path (and full
responses under GRAPHIFY_QUERY_LOG_RESPONSES) to a default-on, unbounded,
fail-silent plaintext file at ~/.cache/graphify-queries.log — outside any repo's
.gitignore/retention, and undocumented. A default-on plaintext record of
proprietary queries contradicts graphify's on-device / no-telemetry posture.
Flip to opt-in: _log_path() returns None unless GRAPHIFY_QUERY_LOG_ENABLE=1
(default path) or GRAPHIFY_QUERY_LOG=<path> is set; GRAPHIFY_QUERY_LOG_DISABLE=1
still forces it off (back-compat, wins). Document all four env vars in the
README (the old entries implied default-on). Regression tests cover
default-off, both enable paths, disable-wins, and that log_query writes nothing
without opt-in.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Switch every website URL from graphifylabs.ai to graphify.com — the hero logo,
the Penpax section, and the waitlist link — across the main README and the
translated READMEs. The contact email stays on graphifylabs.ai (mail is hosted
there); no mailto links were changed. graphify.com is the official graphify
product site; graphifylabs.ai remains the company site (org profile + email).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The badge's href pointed at www.ycombinator.com/companies/graphify, which 404s
— the public S26 company page isn't published yet. Show the badge without a
link rather than ship a dead click; re-add the href once YC publishes the page.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>