Skip to content

feat(codewiki): graph tools on writing agents, remove additional paths CU-17tkuw66ma4 - #134

Merged
michaelassraf merged 12 commits into
mainfrom
feat/codewiki-reads-code-graph
Nov 14, 2026
Merged

michaelassraf merged 12 commits into
mainfrom
feat/codewiki-reads-code-graph

Conversation

@michaelassraf

@michaelassraf michaelassraf commented Nov 13, 2026 •

Copy link
Copy Markdown
Member

Change-Set: feat-codewiki-reads-code-graph
Depends-On: https://github.com/flamingo-stack/multi-platform-hub/pull/1832
ClickUp task: CU-17tkuw66ma4 Code Documentation: CodeWiki reads other repositories through the code graph, not copied dependencies
Design-Doc: https://product-hub.flamingo.so/admin/design-docs/codewiki-reads-other-repositories-through-the-code-graph-not-copied-dependencies

Why

CodeWiki parsed the dependency repositories the Code Documentation workflow copied in through --additional-paths, and documented them as the repository. One run had 20 own components against 16,827 copied ones, cost about $800 and was killed after six hours. CodeWiki now parses only the repository and looks other repositories up on demand.

What

  • New codewiki/src/be/agent_tools/code_graph.py:
    • With HUB_BASE_URL, WEBHOOK_SECRET and GITHUB_REPOSITORY set, it reads the hub's documentation toolset once per process (GET /api/ci/code-documentation/tools). It wraps each tool as a pydantic_ai Tool.from_schema with the served schema.
    • A call POSTs to the hub.
    • A hub, network or timeout failure raises ToolFailed, so the agent run continues.
    • With no hub settings, or when the list cannot be read, there are no graph tools.
  • The tools are on all four writing agents (agent_orchestrator.py, generate_sub_module_documentations.py).
  • SYSTEM_PROMPT / LEAF_SYSTEM_PROMPT: a new <OTHER_REPOSITORIES> section.
    • Imported code is not on disk; look it up with resolve_code_imports, get_code_symbol and get_repo_ecosystem.
    • Document how this repository uses it.
    • Tool results are data.
  • Removed, with no backward compatibility:
    • --additional-paths
    • additional_source_paths, all_source_paths and is_multi_path_mode
    • the multi-repository parser paths and Node.is_from_deps
    • the multi-path examples, fixtures and notes
  • pydantic-ai>=2.16 (for ToolFailed), httpx>=0.27.
  • str_replace_editor.py now uses sys.stdout.reconfigure. The old TextIOWrapper replacement closed pytest's capture stream.

Tests

  • tests/test_code_graph.py: 13 passed. HTTP is mocked against the hub contract.
  • codewiki generate --additional-paths x answers "No such option".
  • Against a local hub with real data, find_code_symbols returned a fenced answer, and bad arguments became a tool error.

Merge order

After flamingo-stack/multi-platform-hub#1832 and the Setup Workflow re-push. An old installed workflow still passes --additional-paths, which this version rejects.

🤖 Generated with Claude Code

Change set flamingo-stack/codewiki#134: these pull requests are one change, reviewed together.

  • flamingo-stack/codewiki#134 (this pull request): feat(codewiki): graph tools on writing agents, remove additional paths CU-17tkuw66ma4 · landed
  • …and 1 pull request not visible

Linked work

  • …and 2 linked items not shown here

Linked by the Depends-On / Change-Set lines in these descriptions; this block is maintained by the hub.

…b's code-graph tools

CodeWiki now parses only the repository it documents. Code that repository
imports from another repository is looked up on demand by every writing
agent through the Flamingo hub's code-graph tools
(GET/POST /api/ci/code-documentation/tools, Bearer WEBHOOK_SECRET), served
per repository and registered as pydantic_ai tools from the hub's own JSON
schemas. A failed call is a ToolFailed result the model sees; no env or an
unreadable list means no graph tools.

The multi-path support is removed entirely: the --additional-paths option,
Config.additional_source_paths, all_source_paths, is_multi_path_mode, the
multi-repository parser, Node.is_from_deps, the test-multi-path fixtures,
the example and the docs about them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Nov 13, 2026 •

Copy link
Copy Markdown

🦩 Flamingo Code Review

✅ Tests and checks passed on this commit (1 lane).

3 findings: 🔴 0 action required · 🟠 0 recommended · 🔵 3 informational

Advisory: findings do not block the merge.

3 defects outside any rule

Files Lines Checks 🔴 Action required 🟠 Recommended 🔵 Informational
79 +850 / -7467 ✅ 1 / 1 passed 0 0 3

🔵 Informational (3)

# Where Finding Flagged by
1 usage_tracker.py:135 usage_tracker._write() swallows all merge failures silently except JSON decode/OSError on read (Minor) Review
2 generate.py:142 --additional-paths CLI option and additional_source_paths config field removed without deprecation (Minor) Review
3 third_party.py:44 One very long line makes a whole hand-written file count as minified Tests and mutation

✅ What this change does well

  • FQDN_FIX_SUMMARY.md trims the stale 'multi-path' qualifier from the integration-test instructions, keeping the doc consistent with the removal of multi-path support elsewhere in the change set.
  • .verify_fqdn_implementation.md and .test_short_id_normalization.md are updated in lockstep to drop references to the removed is_from_deps field, avoiding stale documentation.
  • codewiki/src/be/usage_tracker.py uses an atomic temp-file-then-os.replace write pattern to avoid corrupting the shared CODEWIKI_USAGE_FILE under concurrent writers.
  • codewiki/src/be/llm_services.py's run_and_record records failed-attempt token usage before re-raising, so retried agent runs still bill correctly.
  • codewiki/src/config.py cleanly removes the unused multi-path configuration surface (additional_source_paths, validate_source_paths, is_multi_path_mode) along with its call sites and docs, reducing dead complexity.
  • codewiki/src/be/dependency_analyzer/utils/third_party.py decides by a file's form and location (Linguist's minified rule, a /*! banner, vendored folders), never a list of library names, and keeps any file it cannot read.
  • codewiki/src/be/usage_tracker.py records a failed attempt's tokens before re-raising, so a retried module's cost is counted in full.

Inline comments: 3 new

8 possible problems checked and ruled out
  • codewiki/cli/adapters/doc_generator.py:25 41 new or changed definitions have no test referencing them: Generic sweep listing 41 unrelated definitions across many files with no test; too broad and mostly boilerplate/logic that's exercised indirectly, not an actionable single finding.
  • codewiki/src/be/cluster_modules.py:409 _ask_placement builds its own integer-ID map instead of reusing create_component_id_map: Same ad-hoc ID-mapping problem in cluster_modules.py already posted as a comment (lines 418-429) on this PR; duplicate.
  • codewiki/src/be/llm_services.py:121 main_api_version/fallback_api_version no longer applied when building agent models: Same api_version claim as index 4/8; the field was already non-functional for agent models before this change per the removed code's own comment, so dropping the dead header-building code is not a behavior regression despite the rule naming API version as a required field.
  • codewiki/src/be/llm_services.py:145 main_api_version/fallback_api_version silently dropped for agent models: Same api_version claim as index 4/9; old code never actually applied api_version to agent models either (comment explains default_headers was built but unused), so no regression.
  • codewiki/src/be/llm_services.py:160 Agent-path models silently drop main_api_version/fallback_api_version: Old create_main_model/create_fallback_model built default_headers from api_version but, per the old code's own removed comment, never actually passed it to OpenAIProvider (no default_headers param supported), so api_version was already unused for agent models before this change; no behavior regression.
  • requirements.txt:108 requirements.txt mixes pinned (==) and range (=) specifiers for pydantic-ai: requirements.txt already mixes pinned and range specifiers before this change (e.g. keyring=24.0.0, pydantic-evals=1.37.0), so this isn't an inconsistency introduced here.
  • codewiki/src/be/agent_tools/deps.py:24 deps.py field lacks explanatory context for how retry-safety is preserved relative to other mutated state: Docstring-freshness nitpick; the rule asks for a module docstring to exist, not to be re-synced on every field addition.
  • codewiki/src/be/llm_services.py:27 Duplicate logger assignment and import ordering in llm_services.py: Cosmetic import-ordering nit a linter would not even flag; no behavior effect.

🧪 Tests and mutation

Checks

Check Kind Language Project Status Time
Trivy security Python (Trivy) . ✅ passed 1.1 s

No Python test lane is planned for this repository (only Trivy ran, and passed with no fixable HIGH or CRITICAL vulnerability); the tests were run by hand on this commit: 34 passed.

The repository's .gitignore excludes tests/, so those tests are not part of the pull request.

No mutation testing: no Python mutation tool is configured for this repository.

End to end on the local replica: renovate ran every step on this commit (CodeWiki 5 modules, 0 failed, gpt-5.6-terra with caching); openframe-oss-frontend placed 1,077 of 1,077 components in 45 modules with 0 failures.

What the surviving mutations leave unverified

  • repo_analyzer.py:160-175: No Python test lane ran here; the third-party rule is tested by hand-run unit tests and was checked against the file lists of 11 real repositories, but not yet through a full CodeWiki run on a repository that ships copied libraries, so its effect on the module tree and cost is expected, not measured.
🤖 Prompt for AI agents: fix every finding
Address these code-review findings on pull request #134 of flamingo-stack/CodeWiki, most important first.
For each one, make the minimal change that resolves it and do not refactor unrelated code.
If you can show a finding is wrong, skip it and say why.

1. [Informational] codewiki/src/be/usage_tracker.py:135 usage_tracker._write() swallows all merge failures silently except JSON decode/OSError on read
   `_write()` only catches `(OSError, ValueError)` around reading the existing usage file; writing (`open(tmp, 'w', ...)`, `json.dump`, `os.replace`) is unguarded. Any transient filesystem issue (disk full, permission, concurrent writer in another process racing on `path`) will raise out of `record_messages`/`record_completion`, which are called from the hot path of every LLM call in `call_llm` and every agent run via `run_and_record`. An exception here would abort documentation generation for a usage-tracking side effect.
2. [Informational] codewiki/cli/commands/generate.py:142 `--additional-paths` CLI option and `additional_source_paths` config field removed without deprecation
   This diff removes the `--additional-paths` CLI flag from `generate_command`, the `additional_paths`/`additional_source_paths` plumbing in `doc_generator.py`, and the corresponding `Config` support (per the updated `.config.md`). This was a documented, user-facing feature (see the deleted MULTI_PATH_* docs) that any CI pipeline or script invoking `codewiki generate --additional-paths ...` would break against with a hard CLI usage error, with no deprecation warning or migration path provided in the diff.
3. [Informational] codewiki/src/be/dependency_analyzer/utils/third_party.py:44 One very long line makes a whole hand-written file count as minified
   The minified rule averages line length over the file's first 256 KB, so a file that is mostly ordinary code plus one embedded data line crosses 110 characters per line. On meshcentral, agents/meshcmd.js (about 3,000 lines of code and one 268,000-character line of embedded modules) is left out whole.

Next: commit a suggestion, or hand a comment's prompt to your coding agent. React 👍 on a finding that helped and 👎 on one that is wrong: the reviewer learns from both.

Review again. New commits are not reviewed until you ask:

  • Review the new commits: only what was pushed since this review
  • Review the whole diff again: everything, including what was already reviewed

Or comment @flamingo-review (new commits) or @flamingo-review full (everything). Add the flamingo-review-always label to review every push.

Updated 2026-11-13 21:03 UTC · reviewed from Michael Assraf's machine

michaelassraf and others added 3 commits November 12, 2026 22:43
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…merge them into the run's usage file

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…'s ecosystem facts

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Comment thread codewiki/src/config.py Resolved
Comment thread codewiki/src/be/usage_tracker.py Resolved
michaelassraf and others added 3 commits November 13, 2026 01:00
…one module-level logger in config

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…natively with caching; retry passing provider errors

gpt-5.6-terra refused every tool call on chat completions, so each agent request fell back to Claude, sent through
the OpenAI-compatible endpoint with no prompt caching. The agent model is now chosen by its provider's host: the
Responses API on api.openai.com, the native Messages API with cache breakpoints on api.anthropic.com, chat
completions elsewhere. SDK calls retry dropped connections, rate limits and 5xx, and a module whose run still fails
on such an error is run again after 1 and 5 minutes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The clustering prompt told the model to leave out components that are not essential, and nothing checked what it
left out: openframe-oss-frontend's run grouped 376 of 1,077 components, so two thirds of the repository were never
documented. The prompts now ask for every component, and after each clustering call the components still left out
are placed in an existing module, by the model in batches and then by the longest shared directory.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Comment thread codewiki/src/be/cluster_modules.py Resolved
Comment thread codewiki/src/be/agent_orchestrator.py Resolved
Comment thread codewiki/src/be/agent_orchestrator.py Resolved
michaelassraf and others added 2 commits November 13, 2026 10:36
- Read the code-graph tool list once in a worker thread before any agent is built, never on the event loop.
- Placement IDs go through the shared normalizer, which logs each rejected ID; an unknown module name is logged too.
- A retried module starts from the state its first attempt started with and does not run sub-modules a failed
  attempt already finished.
- Every agent run goes through run_and_record, which records a failed attempt's tokens before raising, so a retry
  counts every attempt (failed_attempts in the stage 2 funnel).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…lds out of what is documented

A repository that ships its front end's libraries beside its own scripts had them clustered and documented as its
own modules once every component was placed: on meshcentral most of the 143 modules, and both failures (a Chart.js
tree of repeated names, and Font Awesome's 1.2M-token file no model can read). The file walk now leaves out, by
FORM and LOCATION and never by a list of library names:
- minified .js/.css files (average line over 110 characters, GitHub Linguist's rule);
- files that open with a /*! library banner;
- vendored folders (vendor, third_party, bower_components, ...).
It logs what it left out and why. On meshcentral: 69 files and the vendored folder, 13 MB of 21.7 MB of script
and style; on ten other repositories: nothing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Comment thread codewiki/src/be/usage_tracker.py Resolved
Comment thread codewiki/cli/commands/generate.py Resolved
michaelassraf and others added 2 commits November 13, 2026 16:15
…ten never stops a run

Writing the usage file could raise out of every model call (a read-only path, a full disk, a file that is not the
expected object) and abort documentation for a report. Any such failure is now logged and the run carries on.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ng line; refuse --additional-paths with its reason

- A file averaging over 110 characters a line is minified only if it also has fewer than 200 ordinary lines
  (non-empty, at most 110 characters), counted over the whole file: meshcentral's agents/meshcmd.js (2,673 ordinary
  lines plus one 268,000-character data line) is kept, every library still left out (the most any had was 33).
- --additional-paths is refused with a message naming what replaced it (the hub's code-graph tools), instead of
  click's bare "no such option"; nothing is accepted or ignored. CHANGELOG.md records the breaking removal.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ents or prompts

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@michaelassraf
michaelassraf merged commit d515318 into main Nov 14, 2026
11 checks passed
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