Skip to content

Artifact-aware documentation generation (build, CI, container, manifest, config files) - #106

Merged
anhnh2002 merged 2 commits into
mainfrom
feat/artifact-aware-generation
Sep 10, 2026
Merged

Artifact-aware documentation generation (build, CI, container, manifest, config files)#106
anhnh2002 merged 2 commits into
mainfrom
feat/artifact-aware-generation

Conversation

@anhnh2002

Copy link
Copy Markdown
Collaborator

Problem

CodeWiki documents only what is in the dependency graph, and the graph is built from files whose extension is in CODE_EXTENSIONS. Dockerfiles, CI workflows, Makefiles, package manifests, configuration, schema and script files are dropped before a single Node exists. As a result no generated wiki describes how a system is built, packaged, shipped, configured or tested. Across seven benchmark wikis there was not one mention of GitHub Actions.

What this PR does

A second analysis pass (dependency_analyzer/analyzers/artifact.py) runs after the language analyzers over the same file tree and emits artifact nodes that flow through the existing clustering and agent machinery:

  • Nodes. One node per artifact file (<path>::<file>, source = capped 16 KB head) plus unit nodes for CI jobs, Dockerfile stages, Makefile targets, package.json scripts and pyproject/setup.cfg entry points. Classes: manifest, build, container, ci, packaging, test_infra, schema, config, script (and opt-in prose).
  • Edges. Artifact -> code references from COPY/ENTRYPOINT/RUN, CI run: lines, python -m, make <target>, npm run <script>, module:function entry points and compose build contexts. Only fully resolved ids are emitted (the parser falls back to name matching otherwise).
  • Caps. Per-file head, 40 files per class, total token budget (default 200k) filled in class priority order. Lock files and binaries are never read. README and docs/ stay out unless --with-prose.
  • File walk. ARTIFACT_WHITELIST lets .github/workflows, *.ini, bin/*.sh, *.gradle survive DEFAULT_IGNORE_PATTERNS; user --exclude and .gitignore still win. Artifact names added to DEFAULT_INCLUDE_PATTERNS.
  • Leaf selection. artifact is always a valid leaf type; artifact -> code edges no longer prune code leaves at the 400-leaf reduction.
  • Clustering. Artifact files are tagged (artifact: <class>) in the cluster prompt with an instruction that they are essential. ensure_artifact_module inserts a top-level Build, Deployment and Configuration module when clustering placed fewer than 80% of artifact nodes (both run() and the CLI adapter path).
  • Prompts. Fence language now falls back to text instead of raising KeyError for Dockerfile, Makefile, .yml, .toml, .cfg, .ini. Artifact groups inline their capped source instead of re-reading the whole file. A compact <REPOSITORY_ARTIFACTS> index is appended to module prompts and to the repository overview prompt; USER_PROMPT itself is unchanged so the MCP prompt server keeps working.
  • Tools. str_replace_editor view on a directory no longer hides .github and quotes the path.
  • Config. Node.artifact_class; temp/artifact_index.json; flags --artifacts/--no-artifacts (default on), --artifact-token-budget, --with-prose, --artifact-exclude (also agent_instructions.artifact_exclude).

Test plan

  • pytest -o addopts="" tests/ -q: 99 passed (60 existing + 39 new in tests/test_artifact_analyzer.py: classifier table, whitelist, nodes and units, edge resolution, caps, leaf selection and pruning, user prompt, fallback module).
  • End-to-end on pypiserver (~10k LOC): 41 artifact nodes, 79 edges; clustering placed 41/41 artifacts and produced a build_deployment_and_configuration module with CI/container/tooling/manifest sub-docs; the overview gained a "How it is built and run" section. Baseline with --no-artifacts behaves as before (same graph, 0 artifact nodes). No errors in either run.

Notes for reviewers

  • --no-artifacts restores the previous behaviour exactly, so the change is one flag away for ablation.
  • Edge heuristics are per-format and shallow; they connect artifacts to code for clustering and cross-links but are not a call graph.
  • Existing outputs resumed from a cached first_module_tree.json will not gain the fallback module; use a fresh output directory.

CodeWiki only documented what reached the dependency graph, and the graph was
built from files whose extension is in CODE_EXTENSIONS. Dockerfiles, CI
workflows, Makefiles, package manifests, config, schema and script files were
dropped before a single Node existed, so no wiki ever described how a system
is built, packaged, shipped, configured or tested.

This adds a second analysis pass over the same file tree
(dependency_analyzer/analyzers/artifact.py) that emits `artifact` nodes:

- one node per artifact file (id `<path>::<file>`, source = capped 16 KB head)
  plus unit nodes for CI jobs, Dockerfile stages, Makefile targets,
  package.json scripts and pyproject/setup.cfg entry points;
- edges from artifacts to the code they reference (COPY/ENTRYPOINT paths,
  `run:` lines, `python -m`, `make <target>`, `npm run`, `module:function`
  entry points, compose build contexts), emitted only for fully resolved ids;
- caps: per-file head, 40 files per class, total token budget filled in class
  priority order; lock files and binaries are never read; README/docs stay
  out unless --with-prose.

Pipeline changes so the new nodes flow through unchanged machinery:

- repo_analyzer: an ARTIFACT_WHITELIST lets `.github/workflows`, `*.ini`,
  `bin/*.sh`, `*.gradle` survive the default ignore list (user excludes and
  .gitignore still win); artifact names added to DEFAULT_INCLUDE_PATTERNS.
- leaf_selection: `artifact` is always a valid leaf type; topo_sort no longer
  lets artifact->code edges prune code leaves.
- cluster prompts mark artifact files `(artifact: <class>)` and tell the LLM
  they are essential; `ensure_artifact_module` inserts a top-level
  "Build, Deployment and Configuration" module when clustering placed fewer
  than 80% of the artifact nodes (both the CLI adapter and run() paths).
- prompt_template: fence language falls back to `text` instead of raising
  KeyError for Dockerfile/Makefile/.yml/.toml; artifact groups inline their
  capped source instead of re-reading the whole file; a
  <REPOSITORY_ARTIFACTS> index is appended to module prompts and to the
  repository overview prompt (USER_PROMPT itself is unchanged for the MCP
  prompt server).
- str_replace_editor `view` on a directory no longer hides `.github` and
  quotes the path.
- Node gains `artifact_class`; the graph builder writes temp/artifact_index.json.

Flags: --artifacts/--no-artifacts (default on), --artifact-token-budget
(200000), --with-prose (off), --artifact-exclude, and an
agent_instructions.artifact_exclude key.

Tests: tests/test_artifact_analyzer.py (classifier, whitelist, nodes and
units, edge resolution, caps, leaf selection, prompt, fallback module).
CI lints every changed Python file in full, so pre-existing findings in the
files this branch touches also fail the check. Apply ruff's safe fixes and
formatting (pep585/pep604 annotations, import ordering, regex flag aliases)
and resolve the rest by hand without behaviour changes:

- blind `except Exception` sites get `# noqa: BLE001` with the reason, as the
  codebase already does elsewhere; bare `except:` becomes `except Exception`
- subprocess.run calls pass `check=False` and use `capture_output=True`
- dead assignments removed (`repo_name`, `filtered_folders_path`,
  `generation_time`, `start_time`, `generation_options`, `current_branch`)
  along with the imports they kept alive
- mutable default arguments in `cluster_modules()` become `None` and are
  normalised at the top of the function
- nested ifs merged, `endswith` tuple, needless-bool return, loop-variable
  closure in the package.json exports walker takes explicit parameters
- shebang removed from the non-executable str_replace_editor module
@anhnh2002
anhnh2002 merged commit 2531801 into main Sep 10, 2026
2 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