Feature/style config#19
Conversation
- Add .code-to-docs/style.md auto-detection for persistent style rules - Add style-config-path action input for custom style file location - Inject style guidelines into generation prompts with proper precedence (per-file > user instructions > style guidelines > base rules) - Add parser-based output validation (markdown, docutils, asciidoctor.js) - Add retry loop (max 2 retries) to fix LLM format errors before accepting - Skip files with persistent format errors (no invalid output in PRs) - Add strip_code_fences() to clean LLM output wrapped in code blocks - Add comprehensive tests for all new functionality Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The file selection and area-relevance prompts only looked for docs that would become factually incorrect, missing cases where new functionality extends an existing documented feature and makes docs incomplete. Updated both prompts to also select docs when: - New functionality falls within the scope of what the doc covers - Defaults or output referenced in docs change Simplified DO NOT rules to reduce false negatives. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
load_all_indexes() was converting hyphens to slashes when deriving folder names from index filenames (e.g. operator-manual.index.md became operator/manual). This caused get_files_in_areas() to look for a non-existent folder, so candidate files from subdirectories were never found — only root-level docs were returned. Fix: check the stem against actual doc folders first, only fall back to the slash conversion for genuinely nested paths. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
get_doc_folders() now returns sub-folder paths (e.g. operator-manual/server-commands) instead of just top-level folders (e.g. operator-manual). This produces more granular indexes, so area selection returns smaller, more relevant candidate sets instead of hundreds of files from a broad top-level directory. Also simplified load_all_indexes() to use a reverse lookup from actual folder paths, removing the ambiguous hyphen-to-slash conversion. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
get_files_in_areas() was using rglob (recursive) which pulled in all sub-folder files even though sub-folders now have their own indexes. Changed to glob (direct children only) so selecting an area only returns files at that level, not files from sub-folders that have their own separate indexes. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The previous prompt rewrites were too permissive, causing the area selection to return too many folders (proposals, architecture, upgrade guides). Reverted both prompts to the original strict wording and added only the minimal change needed: 'or extended' / 'or MEANINGFULLY INCOMPLETE' to cover new functionality without losing the conservative filtering that keeps candidate counts low. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The area prompt (strict) handles narrowing to relevant folders. The file selection prompt now uses the balanced version that also catches new functionality, since the candidate set is already small at this stage. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
get_docs_in_folder() was using rglob (recursive) so parent folder indexes included files from sub-folders that have their own separate indexes. Changed to glob (direct children only) so each index covers only its own level. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ally Root-level doc files were unconditionally added to every file selection query regardless of which areas the AI selected. Now they are indexed under a virtual '_root' folder and only included when the AI selects that area as relevant, like any other folder. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Instead of selecting areas then loading all files for a second round of LLM filtering, the index prompt now asks the LLM to pick specific files directly from the per-file descriptions in the index. This collapses area selection + file selection into a single step. Reduces API calls from ~10 (area selection + batch file selection) to ~4 (index file selection + content generation). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Added 'do NOT group files or use wildcards' to the index building prompt and the file selection prompt. Added validation to reject glob patterns in returned file paths as a safety net. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
In same-repo scenarios, the docs PR was branching from the code PR's HEAD, causing it to include the code commits alongside the doc changes. Now it branches from origin/<base_branch> and only applies the doc file changes, so the docs PR contains a single commit with only doc updates. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The previous approach used git checkout HEAD@{1} to recover doc files
after switching to the base branch, but the reflog reference was
unreliable. Now saves file contents in memory before the branch switch
and writes them back onto the clean base.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
In same-repo scenarios, instead of creating a separate docs PR, the doc changes are committed and pushed directly to the code PR's branch. This keeps everything in one PR — no separate docs PR to review. The separate-repo flow is unchanged (still creates its own PR). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
🤖 Finished Review · ✅ Success · Started 2:40 PM UTC · Completed 2:53 PM UTC |
ReviewFindingsMedium
Low
Previous runReviewFindingsHigh
Medium
Low
Info
Previous run (2)ReviewReason: stale-head The review agent reviewed commit Previous run (3)ReviewFindingsHigh
Medium
Low
Info
|
| @@ -964,53 +982,45 @@ def _process_area_batch(client, prompt, batch_num, total_batches, batch_folders) | |||
| messages=[{"role": "user", "content": prompt}], | |||
There was a problem hiding this comment.
[medium] logic-error
_process_file_selection_batch no longer filters LLM-returned file paths against the batch's known folders. LLM-hallucinated paths would pass through the post-hoc filter and fail silently downstream.
Suggested fix: Add validation that checks returned file paths against actual files known from the indexes.
| @@ -204,13 +311,25 @@ def ask_ai_for_updated_content(diff, file_path, current_content, user_instructio | |||
| - The complete updated file with ONLY the minimal necessary changes | |||
There was a problem hiding this comment.
[low] injection
Style guidelines from a repository .md file are interpolated into the LLM prompt with delimiter-based containment. While mitigated by instruction hierarchy and requiring repo write access, delimiter containment is not a reliable security boundary.
| return True, "" | ||
| except Exception as e: | ||
| return False, f"AsciiDoc validation failed: {e}" | ||
|
|
There was a problem hiding this comment.
[low] injection
_validate_asciidoc stderr output could echo attacker-controlled content back into a retry prompt. Multi-step attack chain makes this low risk.
- Same-repo push: warn when GH_TOKEN or PR_HEAD_SHA is missing instead of silently losing doc updates - Style budget: account for diff size to avoid crowding out diff content - File selection: validate returned paths exist on disk, skip hallucinated paths from the LLM - Retry loop: return NO_UPDATE_NEEDED on exception instead of falling through with invalid content Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Truncate validation errors from asciidoctor stderr and docutils to 1000 chars before feeding them into the retry prompt. Prevents attacker-controlled content in doc files from injecting large payloads through the validation error path. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
🤖 Finished Review · ✅ Success · Started 3:08 PM UTC · Completed 3:26 PM UTC |
- strip_code_fences: handle missing newline before closing fence - Retry test: mock validate_format to actually exercise the retry path - README: add style-config-path to workflow example Accepted risks (not changed): - Markdown validation is lenient by design (markdown lib doesn't error) - Style guidelines injection: same trust level as workflow files - config.py importing security_utils: no circular dependency risk Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
/fs-review |
|
🤖 Finished Review · ✅ Success · Started 3:28 PM UTC · Completed 3:41 PM UTC |
High: - Update README Performance section to reflect single-stage discovery Medium: - Fix _index.md exclusion: check only directory parts, not filenames - Add --safe-mode=secure to asciidoctor to prevent include:: file reads - Remove dead code: get_files_in_areas and its tests - Fix batch_indexes operator precedence (separator between all items) Low: - Re-apply trailing newline after retry fix response - Scope creep acknowledged in PR description Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
🤖 Finished Review · ✅ Success · Started 3:55 PM UTC · Completed 4:10 PM UTC |
- discovery.py module docstring: reflects single-stage index-based approach - generation.py: clarify return after retry loop with comment Remaining review items (accepted): - PR_HEAD_SHA naming: renaming is a breaking change, works correctly in practice - Style budget drops guidelines on large diffs: safe behavior, diff takes priority - Style injection: same trust level as workflow files, document CODEOWNERS - Scope creep: acknowledged and documented in PR description Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
🤖 Finished Review · ✅ Success · Started 4:14 PM UTC · Completed 4:30 PM UTC |
|
Review skipped — this PR is already merged. The Posted by fullsend post-review check |
Summary
This PR adds three capabilities to code-to-docs:
1. Persistent style guidelines
Users can define documentation style rules in
.code-to-docs/style.md(auto-detected) or via thestyle-config-pathaction input. Guidelines are injected into generation prompts with clear precedence: per-file instructions > user instructions > style guidelines > base rules.2. Output format validation with retry
LLM output is validated using real parsers (markdown, docutils, asciidoctor.js) before writing to files. If validation fails, the output is sent back to the LLM with the error details for correction (max 2 retries). Files with persistent format errors are skipped entirely — no invalid output makes it into a PR.
3. Discovery pipeline improvements
During testing, several issues with the file discovery pipeline were identified and fixed:
_rootfolder instead of being unconditionally included in every queryload_all_indexes()was converting hyphens to slashes, causing sub-folder files to be missedOther fixes
include::directives)Test plan
[review-docs]and[update-docs]commands[update-docs]commits directly to the PR branch