Skip to content

Stop building generated code from unsanitized free text in skill instructions - #3442

Open
ayushcodes10 wants to merge 6 commits into
Graphify-Labs:v8from
ayushcodes10:fix-3439-skill-injection
Open

Stop building generated code from unsanitized free text in skill instructions#3442
ayushcodes10 wants to merge 6 commits into
Graphify-Labs:v8from
ayushcodes10:fix-3439-skill-injection

Conversation

@ayushcodes10

Copy link
Copy Markdown
Contributor

Fixes #3439.

Two of the generated skill reference docs instructed the host agent to substitute raw, unsanitized values directly into generated Python or shell source.

add-watch.md (the /graphify add flow)

The instructions had the agent embed a URL and optional author/contributor name inside a single-quoted Python string literal, passed to python -c "...":

out = ingest('URL', Path('./raw'), author='AUTHOR', contributor='CONTRIBUTOR')

An embedded apostrophe breaks the Python syntax; crafted input runs arbitrary Python.

query/default.md (all three save-result call sites: query, path, explain)

The instructions had the agent substitute the user's verbatim question and a full LLM-generated answer (unbounded length, arbitrary content) into a double-quoted shell argument:

graphify save-result --question "ORIGINAL_QUESTION" --answer "ANSWER" ...

Double quotes still allow command substitution/backticks, and embedded quotes break argument boundaries.

Fix

save-result already had --answer-file for exactly this reason (#1502). This PR:

  1. Adds the missing symmetric options: --question-file/--correction-file for save-result, and a --from-file (JSON payload: url/author/contributor/dir) for graphify add. All existing positional/flag forms are unchanged — purely additive.
  2. Rewrites both fragment files to have the agent write the value to a file with its own file-write tool first, then pass only that file's path — never the content — on the command line. This closes the injection surface entirely rather than just narrowing it: the content never enters shell or Python source at all.
  3. Regenerates all 14 platform skill variants and their tools/skillgen/expected/ fixtures from the updated shared fragments.

Test plan

  • pytest tests/test_ingest.py tests/test_reflect.py — new tests cover --question-file/--correction-file round-tripping adversarial content (backticks, $(), both quote styles) through save-result, and graphify add --from-file passing an adversarial JSON payload through to ingest() unexecuted (mocked, network-free) plus a check that the original positional-arg form still works unchanged
  • python -m tools.skillgen --check and all guard modes (--audit-coverage, --schema-singleton, --monolith-roundtrip, --always-on-roundtrip) pass
  • Full suite passes except pre-existing, unrelated failures (test_ollama_retry_cap.py, missing openai module in this environment; test_ts_normalizer_scales_linearly_on_large_files, a flaky wall-clock timing assertion, confirmed to pass in isolation)

🤖 Generated with Claude Code

https://claude.ai/code/session_017qfdzgbA5KedGEjD1AayNh

ayushcodes10 and others added 2 commits September 9, 2026 22:30
save result already had an answer file option for exactly this
reason; adding equivalents for the question and correction fields
makes every free text field on that command safe to pass through a
file instead of a command line argument. graphify add gets a
symmetric file input reading a JSON payload for url, author, and
contributor. Neither command's existing positional/flag form
changes.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017qfdzgbA5KedGEjD1AayNh
Two of the generated skill references instructed the host agent to
substitute raw, unsanitized values directly into generated Python or
shell source. The add reference embedded a URL and optional
author/contributor name inside a single quoted Python literal
passed to python's inline script flag, so an embedded quote broke
it and crafted input could run arbitrary Python. The query
reference substituted the user's verbatim question and a full LLM
generated answer, unbounded length, into a double quoted shell
argument, where an embedded backtick or command substitution still
executes.

Both now write the value to a file with the agent's own file write
tool first and pass only that file's path on the command line,
never the content itself, so there is no injection surface left at
all. Regenerated all fourteen platform skill variants and their
expected fixtures from the updated shared fragments; every
skillgen guard still passes.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017qfdzgbA5KedGEjD1AayNh

@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.

Worth a look — the grounded gate found no coupling regressions or blocking issues, but 3 advisory finding(s) below merit a look before merge.

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


Graphify review — findings

Adds a shell-injection-safe path for graphify add and save-result by accepting --from-file (JSON payload of url/author/contributor/dir), --question-file, --answer-file, and --correction-file, each reading its value from a file whose only shell argument is the agent-controlled path. Requires exactly one of --question/--question-file and --answer/--answer-file, erroring otherwise, while the legacy positional/flag forms still work. Rewrites the agent skill references (across all generator variants and expected fixtures) to instruct writing free-text question/answer/correction and add-payloads to files instead of substituting them into command or heredoc strings.

Worth a look

  • Missing --from-file operand is treated as the URLgraphify/cli.py:1974 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • add --from-file crashes with KeyError instead of clean error when 'url' missinggraphify/cli.py:1985 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • Fixed /tmp save-result filenames race across concurrent sessionsgraphify/skills/claw/references/query.md:176 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
Analysis details — impact, health, verification

Impact & health

Graphify review

Impact — 691 functions depend on the 482 functions this change touches.

Health — this change adds coupling hotspots:

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

Verification — 691 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: 637 function(s) in the blast radius were not formally verified this run

Test selection

Test selection

262 of 262 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 — 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_generic_callsites.py — full-run-safety
  • … and 212 more

non-code file(s) changed (graphify/skills/agents/references/add-watch.md, graphify/skills/agents/references/query.md, graphify/skills/amp/references/add-watch.md, graphify/skills/amp/references/query.md, graphify/skills/claude/references/add-watch.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/skills/agents/references/add-watch.md, graphify/skills/agents/references/query.md, graphify/skills/amp/references/add-watch.md, graphify/skills/amp/references/query.md, graphify/skills/claude/references/add-watch.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)

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

ayushcodes10 and others added 2 commits September 9, 2026 23:34
A missing operand for the from file flag fell through to the
positional url branch and treated the flag's own name as the url, a
confusing blocked scheme error instead of pointing at the actual
mistake. A payload missing the required url key raised a raw,
unhandled KeyError instead of the same clean error message every
other failure in this command already produces. Both now exit with
a clear, single line error, matching malformed JSON and a missing
file, which already went through the same path.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017qfdzgbA5KedGEjD1AayNh
The prior fix wrote question/answer/payload content to a fixed,
shared temp filename. Two concurrent graphify sessions, two agents
or two terminal tabs on the same machine, following the same
instructions at once would race on that one path: one session's
write could overwrite or be read as another session's value. Each
instruction now runs mktemp first to reserve a path unique to that
run before writing anything, closing the race the same file based
handoff was meant to avoid in the first place. Regenerated all
fourteen platform skill variants and their expected fixtures.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017qfdzgbA5KedGEjD1AayNh
@ayushcodes10

Copy link
Copy Markdown
Contributor Author

Investigated this round's bot findings.

Confirmed real, fixed (now at cea4992):

  1. "Missing --from-file operand is treated as the URL" -- graphify add --from-file with no path argument fell through to the positional-url branch and treated the literal string "--from-file" as the URL, producing a confusing "Blocked URL scheme" error instead of pointing at the actual mistake. Reproduced directly. Now detects the flag is present with no operand and exits with a clear error.

  2. "add --from-file crashes with KeyError instead of clean error when 'url' missing" -- a payload missing the required "url" key raised a raw, unhandled KeyError instead of the same clean error message every other failure in this command already produces. Reproduced directly. Also added the same clean-error handling for malformed JSON and a missing file, which hit the same code path but weren't specifically called out.

  3. "Fixed /tmp save-result filenames race across concurrent sessions" -- confirmed: the instructions used a fixed, shared filename (/tmp/graphify_answer.txt, etc.) for the question/answer/payload handoff files. Two concurrent graphify sessions (two agents, two terminal tabs) following the same instructions at once could race on that path, with one session's write overwriting or being read as another's value -- undermining the whole point of the file-based handoff this PR introduced. Every instruction now runs mktemp first to reserve a path unique to that run before writing anything.

Regression tests added for both CLI fixes; all 14 platform skill variants and expected fixtures regenerated for the mktemp fix; all skillgen guards and the full test suite pass (same pre-existing, unrelated failures as before: a missing optional dependency and one flaky timing test, both confirmed unrelated to this change).

@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.

Worth a look — the grounded gate found no coupling regressions or blocking issues, but 2 advisory finding(s) below merit a look before merge.

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


Graphify review — findings

Replaces shell-inlined free text in save-result and add with file-based inputs to close a shell-injection surface (#3439): dispatch_command now accepts --question-file, --correction-file, and --from-file (a JSON payload with url plus optional author/contributor/dir) alongside the existing --answer-file, erroring when neither a value nor its file is supplied. Rewrites the skill references so agents mktemp unique paths, write question/answer/payload via a file-write tool, and pass only those paths to the CLI. Updates the ingest and reflect test suites to cover the new file-driven paths.

Worth a look

  • --from-file crashes on non-object JSON payloadsgraphify/cli.py:1984 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • Explain save command still inlines an untrusted node namegraphify/skills/droid/references/query.md:340 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
Analysis details — impact, health, verification

Impact & health

Graphify review

Impact — 697 functions depend on the 488 functions this change touches.

Health — this change adds coupling hotspots:

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

Verification — 697 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: 643 function(s) in the blast radius were not formally verified this run

Test selection

Test selection

262 of 262 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 — 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_generic_callsites.py — full-run-safety
  • … and 212 more

non-code file(s) changed (graphify/skills/agents/references/add-watch.md, graphify/skills/agents/references/query.md, graphify/skills/amp/references/add-watch.md, graphify/skills/amp/references/query.md, graphify/skills/claude/references/add-watch.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/skills/agents/references/add-watch.md, graphify/skills/agents/references/query.md, graphify/skills/amp/references/add-watch.md, graphify/skills/amp/references/query.md, graphify/skills/claude/references/add-watch.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)

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

ayushcodes10 and others added 2 commits September 11, 2026 14:39
A payload that parsed as valid JSON but was not an object, a list,
a bare string, a number, raised a raw TypeError from subscripting
it with url, since json.JSONDecodeError alone only catches a syntax
error, not a value of the wrong shape. Checks the parsed value is a
dict before looking up url and names the actual type it got in the
error.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017qfdzgbA5KedGEjD1AayNh
The path and explain save commands still built their question
argument from a template with a node label spliced in inline. A
node label is not guaranteed free of shell characters either, since
it can come from extracted document content, not just a source
identifier. Both now write the question to a reserved unique file
the same way the answer already does, closing the gap between two
fields in the same command that were treated inconsistently.
Regenerated the affected platform skill variants and their expected
fixtures.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017qfdzgbA5KedGEjD1AayNh
@ayushcodes10

Copy link
Copy Markdown
Contributor Author

Investigated this round's bot findings.

Confirmed real, fixed (now at d66f2b2):

  1. "--from-file crashes on non-object JSON payloads" -- json.JSONDecodeError alone only catches a syntax error; valid JSON that isn't an object (a list, a bare string, a number) parsed fine and then raised a raw TypeError from subscripting it with "url". Reproduced directly for all three shapes. Now checks the parsed value is a dict before looking up "url" and names the actual type in the error.

  2. "Explain save command still inlines an untrusted node name" -- confirmed: the path and explain save-result templates still built --question from "Path from NODE_A to NODE_B" / "Explain NODE_NAME" with the node label spliced in inline, while the answer next to it was already file-based. A node label isn't guaranteed free of shell characters either, since it can come from extracted document content. Both now write the question to a reserved unique file the same way the answer already does.

Regression tests added for the non-object payload cases; affected platform skill variants and expected fixtures regenerated; all skillgen guards and the full test suite pass (same pre-existing, unrelated failures as before).

@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.

Worth a look — the grounded gate found no coupling regressions or blocking issues, but 4 advisory finding(s) below merit a look before merge.

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


Graphify review — findings

Replaces the shell-inlined graphify add and save-result invocations with file-backed inputs to eliminate command injection from untrusted free text: save-result now accepts --question-file/--correction-file alongside the existing --answer-file, requiring one of --question/--question-file, and add gains a --from-file mode that reads a JSON payload with a required url key plus optional author/contributor/dir. Rewrites the agent skill references to reserve unique mktemp paths, write values via a file-write tool, and pass only the paths to the CLI. Invalid or missing payloads (bad JSON, non-object, missing url, missing --from-file path) exit non-zero with an explanatory message.

Worth a look

  • Untrusted graph node labels are still substituted directly into shell commandsgraphify/skills/copilot/references/query.md:279 · Escalate · high
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • save-result now rejects a present but empty --question argumentgraphify/cli.py:1480 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • add --from-file can traceback on invalid dir typegraphify/cli.py:2000 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • Windows add-watch skill requires POSIX mktempgraphify/skills/windows/references/add-watch.md:15 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
Analysis details — impact, health, verification

Impact & health

Graphify review

Impact — 699 functions depend on the 490 functions this change touches.

Health — this change adds coupling hotspots:

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

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

Health delta baseline: last indexed commit 23f2ffa (diverged from this PR's base — delta is approximate).

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: 645 function(s) in the blast radius were not formally verified this run

Test selection

Test selection

262 of 262 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 — 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_generic_callsites.py — full-run-safety
  • … and 212 more

non-code file(s) changed (graphify/skills/agents/references/add-watch.md, graphify/skills/agents/references/query.md, graphify/skills/amp/references/add-watch.md, graphify/skills/amp/references/query.md, graphify/skills/claude/references/add-watch.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/skills/agents/references/add-watch.md, graphify/skills/agents/references/query.md, graphify/skills/amp/references/add-watch.md, graphify/skills/amp/references/query.md, graphify/skills/claude/references/add-watch.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)

· 6 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.

Skill instructions interpolate unsanitized user input into Python/shell source (query.md, add-watch.md)

1 participant