Skip to content

Add --output flag to graphify export html; dated report/HTML names in the Claude skill - #3428

Open
staypo wants to merge 1 commit into
Graphify-Labs:v8from
staypo:feat/dated-output-filenames
Open

Add --output flag to graphify export html; dated report/HTML names in the Claude skill#3428
staypo wants to merge 1 commit into
Graphify-Labs:v8from
staypo:feat/dated-output-filenames

Conversation

@staypo

@staypo staypo commented Sep 8, 2026

Copy link
Copy Markdown

Summary

The main build path (Claude skill.md Steps 4-6) always writes graphify-out/GRAPH_REPORT.md and graph.html - generic names that say nothing about which corpus they cover or when they were generated. That gets confusing once a few runs pile up in the same graphify-out/ directory (which report is which?).

This PR:

  • Adds an additive, opt-in --output PATH flag to graphify export html (reusing the shared --output flag already parsed for callflow-html). Omit it and behavior is byte-for-byte unchanged.
  • Updates the Claude skill.md main build path (new Step 2.6) to compute a {corpus-slug}-{YYYY-MM-DD} basename once per run, and use it for the markdown report ({base}-report.md instead of GRAPH_REPORT.md) and the HTML export ({base}.html via the new --output flag).
  • Updates references/update.md so --update recomputes the basename before reusing Steps 4-8.

What's intentionally left unchanged

  • graph.json keeps its fixed name. It's read back in by --update, --cluster-only, query, path, explain, --neo4j-push, --mcp, and the benchmark step across sessions - renaming it per run would break "ask questions weeks later."
  • graphify cluster-only/label and --watch/the git commit hook still write the fixed GRAPH_REPORT.md/graph.html names. Both are implemented directly in cli.py with their own stale-marker and shrink-guard state keyed to those literal filenames (e.g. the "existing graph.html left unchanged" skip logic, #1392-adjacent guards). Renaming those safely is a bigger, separate change than this one - documented as a known scope gap in skill.md and the relevant reference docs rather than silently left inconsistent.
  • --svg/--graphml/--neo4j/--falkordb exports are untouched for the same reason (scope).

Testing

Added two tests to tests/test_cli_export.py:

  • test_export_html_output_flag_writes_to_custom_path - --output writes to the custom path and does not also create graph.html.
  • test_export_html_no_viz_removes_file_at_output_path - --no-viz --output PATH removes the file at the custom path.

Ran the full export/cli suite against an editable install of this branch: 505 passed, 23 skipped (1 unrelated failure in test_ollama_retry_cap.py from a missing optional openai dependency in my test venv, not from this change).

Context

I'm a graphify user - I ran into the generic-filename issue while using the Claude skill to build several knowledge-graph reports back to back in the same directory and couldn't tell them apart. Happy to adjust scope/naming convention if you'd prefer a different approach (e.g. a dedicated flag name instead of reusing --output, or a different slug/date format).

…mes in the Claude skill

The main build path (skill.md Steps 4-6) always wrote graphify-out/GRAPH_REPORT.md
and graph.html - generic names with no indication of what corpus they cover or
when they were generated, which gets confusing once a few reports pile up in the
same graphify-out/ directory.

- skill.md: new Step 2.6 computes a `{corpus-slug}-{YYYY-MM-DD}` basename once per
  run (slug from the processed folder's name). Steps 4/5 write the markdown report
  to `{base}-report.md` instead of GRAPH_REPORT.md; Step 6 passes the new --output
  flag to `graphify export html` so the HTML lands at `{base}.html`.
- cli.py: `graphify export html` gains an --output PATH flag (reusing the shared
  --output flag already parsed for callflow-html), letting callers choose the
  target path instead of always writing graph.html. Purely additive - omit the
  flag and behavior is unchanged.
- references/update.md: --update recomputes the basename (same slug, fresh date)
  before reusing Steps 4-8.
- graph.json intentionally keeps its fixed name - it's read back in by --update,
  --cluster-only, query, path, explain, --neo4j-push, --mcp, and the benchmark
  step across sessions, so renaming it would break "ask questions weeks later."

Scoped out of this change (documented as a follow-up, not silently left broken):
`graphify cluster-only`/`label` and `--watch`/the git commit hook write
GRAPH_REPORT.md/graph.html directly from cli.py with their own stale-marker and
shrink-guard state keyed to those literal filenames. Renaming those safely is a
separate, larger change than this one.

Added two tests for the new flag (custom --output path, and --no-viz + --output
removing the right file). Full export/cli test suite passes (505 passed, 1
pre-existing unrelated failure from a missing optional `openai` dep in my test
venv).

@graphify-labs graphify-labs Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Graphify reviewed this change.

Looks safe to merge — no coupling regressions and no blocking issues, checked against the code graph (not a self-assessment).

Formal verification. No changes could be formally verified in this run.


Graphify review — findings

No blocking issues surfaced.

Analysis details — impact, health, verification

Impact & health

Graphify review

Impact — 381 functions depend on the 172 functions this change touches.

Health — this change adds coupling hotspots:

  • new: dispatch_command() — 2 callers, 124 callees
  • new: _make_graph() — 35 callers, 6 callees
  • new: _stale_graph_sources() — 7 callers, 6 callees
  • new: _run_hook_guard() — 4 callers, 8 callees
  • new: test_poisoned_manifest_is_healed() — 0 callers, 6 callees

Verification — 381 functions in the blast radius were not formally verified this run (proofs are advisory here).

Gate & verification

graphify gate

PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.

Advisory (not blocking):

  • verification_scope: 327 function(s) in the blast radius were not formally verified this run

Test selection

Test selection

259 of 259 test file(s) selected (100%) via static blast radius.

Escalated to a full run for safety — the selection is not trustworthy on its own (see below). CI should run the whole suite.

  • tests/test_affected_cli.py — impact, full-run-safety
  • tests/test_affected_member_seed.py — full-run-safety
  • tests/test_agents_platform.py — impact, full-run-safety
  • tests/test_analyze.py — full-run-safety
  • tests/test_anthropic_custom_endpoint.py — full-run-safety
  • tests/test_antigravity_install.py — full-run-safety
  • tests/test_apm_fallback_version.py — full-run-safety
  • tests/test_architecture_doc.py — full-run-safety
  • tests/test_astro_extraction.py — full-run-safety
  • tests/test_astro_import_ids.py — full-run-safety
  • tests/test_atomic_canvas_export.py — full-run-safety
  • tests/test_atomic_version_stamp.py — full-run-safety
  • tests/test_atomic_writes.py — full-run-safety
  • tests/test_backend_extras.py — full-run-safety
  • tests/test_benchmark.py — full-run-safety
  • tests/test_benchmark_raw_graph.py — full-run-safety
  • tests/test_build.py — full-run-safety
  • tests/test_build_merge_hyperedges_and_prune.py — full-run-safety
  • tests/test_build_merge_shrink_guard.py — full-run-safety
  • tests/test_builtin_global_type_refs.py — full-run-safety
  • tests/test_cache.py — full-run-safety
  • tests/test_callflow_html.py — full-run-safety
  • tests/test_cargo_introspect.py — full-run-safety
  • tests/test_carried_hyperedge_remap.py — full-run-safety
  • tests/test_case_sensitive_resolution.py — full-run-safety
  • tests/test_charmap_encoding.py — full-run-safety
  • tests/test_chunking.py — full-run-safety
  • tests/test_cjs_module_extension.py — full-run-safety
  • tests/test_claude_cli_backend.py — full-run-safety
  • tests/test_claude_md.py — full-run-safety
  • tests/test_cli_broken_pipe.py — full-run-safety
  • tests/test_cli_export.py — impact, changed-test, full-run-safety
  • tests/test_cli_help.py — full-run-safety
  • tests/test_cluster.py — full-run-safety
  • tests/test_codebuddy.py — impact, full-run-safety
  • tests/test_community_hub_labels.py — full-run-safety
  • tests/test_community_labels_skill.py — full-run-safety
  • tests/test_confidence.py — full-run-safety
  • tests/test_corrupt_graph_json.py — full-run-safety
  • tests/test_cpp_nested_and_cli.py — full-run-safety
  • tests/test_cpp_objc_cross_file_calls.py — full-run-safety
  • tests/test_cpp_preprocess.py — full-run-safety
  • tests/test_cross_extension_reexport_self_cycle.py — full-run-safety
  • tests/test_cross_language_call_resolution.py — full-run-safety
  • tests/test_cross_repo_member_calls.py — full-run-safety
  • tests/test_cross_repo_shared_types.py — full-run-safety
  • tests/test_csharp_call_site_generic_args.py — full-run-safety
  • tests/test_csharp_enum_members.py — full-run-safety
  • tests/test_csharp_field_generic_args.py — full-run-safety
  • tests/test_csharp_interface_dispatch.py — full-run-safety
  • … and 209 more

non-code file(s) changed (graphify/skill.md, graphify/skills/claude/references/add-watch.md, graphify/skills/claude/references/hooks.md, graphify/skills/claude/references/update.md) → running the full suite for safety (a code graph can't see config/fixture/data deps)

changed code file(s) with no mapped test (graphify/skill.md, graphify/skills/claude/references/add-watch.md, graphify/skills/claude/references/hooks.md, graphify/skills/claude/references/update.md) — a coverage gap or a missing link — running the full suite rather than only the selected tests

Selection is safe under the controlled-regression assumption; always-run tests + a periodic full run are the backstops. Advisory — it never changes the check verdict.

Formal verification

Could not verify: Could not verify dispatch\_command.

The verifier did not have enough to check dispatch\_command, so it is saying so rather than guessing. No false assurance is the whole point.

Guarantee: No guarantee either way, this is an honest abstention, not a pass.

Note: Reason: not verifiable: all 23 sampled inputs raised on both versions — the function never executed, so 'no divergence' would be vacuous (mostly SystemExit — names the real obstacle, not a sampling gap)

· 5 more finding(s) on lines outside this diff (see the check run).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant