chore(ci): fix pre-commit hook failures

Fix JSON syntax errors in .devcontainer/devcontainer.json (removed
invalid JS-style // comments) and .devcontainer/opencode.json (removed
90+ trailing commas). Apply auto-fixes for end-of-file and trailing
whitespace issues across 100+ files. Fix SIM105 ruff violations in
benchmarks/core_circuit_breaker_bench.py (use contextlib.suppress).

Note: The security fix from issue #7478 (validate_path startswith bypass)
was already delivered to master in commit e18ac5f2. This PR as currently
structured is non-atomic (35 commits across 10+ issues) and needs
significant restructure before merge. This commit only addresses the
CI/pre-commit failures.

ISSUES CLOSED: #7478
This commit is contained in:
2026-05-17 14:58:50 +00:00
committed by drew
parent 90083e3ae5
commit f808abff86
101 changed files with 227 additions and 372 deletions
-1
View File
@@ -43,4 +43,3 @@ automation_profile: trusted
invariants:
- "All existing tests must continue to pass"
- "Public API signatures must not change without deprecation"
-1
View File
@@ -56,4 +56,3 @@ inputs_schema:
- parquet
required:
- stages
-1
View File
@@ -47,4 +47,3 @@ invariants:
- "All findings must include reproducible steps"
- "Secrets found during scanning must be redacted in reports"
- "Remediation fixes must not break existing tests"
-1
View File
@@ -25,4 +25,3 @@ definition_of_done: |
reusable: true
read_only: true
state: available
-1
View File
@@ -16,4 +16,3 @@ definition_of_done: |
reusable: true
read_only: true
+1 -1
View File
@@ -34,4 +34,4 @@ context:
global:
conversation_mode: true
# Actor-specific context variables
default_actor: openai/gpt-4
default_actor: openai/gpt-4
+74 -74
View File
@@ -82,7 +82,7 @@ actors:
if not routed:
# Pass the user input along with the stage routing
result = f"GOTO_{stage.upper()}:{clean_input}"
print(f"DEBUG: returning: {result}", file=sys.stderr)
@@ -96,7 +96,7 @@ actors:
# Debug: print what we received
import sys
print(f"DEBUG command_handler: input_data='{input_data}'", file=sys.stderr)
# Extract the actual command from the input_data
# It comes as "GOTO_COMMAND_HANDLER:!next" from workflow_controller
msg = ''
@@ -104,27 +104,27 @@ actors:
parts = input_data.split(':', 1)
if len(parts) > 1:
msg = parts[1].strip()
# Fallback to checking context
if not msg:
msg = context.get('initial_message', '').strip()
# Last fallback
if not msg and input_data:
msg = input_data.strip() if input_data != 'GOTO_COMMAND_HANDLER' else ''
print(f"DEBUG command_handler: using msg='{msg}'", file=sys.stderr)
if not msg:
result = "COMMAND_OUTPUT:Error: No command provided"
else:
parts = msg.split(maxsplit=1)
command = parts[0]
args = parts[1] if len(parts) > 1 else ''
if command == '!help':
result = 'COMMAND_OUTPUT:Available Commands:\n!help - Shows this help message.\n!next [stage_name] - Advances to the next stage, or the one specified.\n!start - Start/run the current stage.\n!write - (section_writing) Proceed from source selection to writing the section.\n!proofread - (section_writing) Proceed from writing to proofreading.\n!accept - Accepts current content and proceeds to next section/stage.\n!stage - Describes the current stage.\n!stages - Lists all stages and marks the current one.\n!context [hops|all] - Shows current context. \'hops\' shows recent history, \'all\' shows full history.\n!finish - Automatically completes remaining stages using first-pass suggestions and citations.'
elif command == '!next':
current_stage = context.get('writing_stage') or 'intro'
stage_order = context.get('stage_order')
@@ -149,26 +149,26 @@ actors:
context['writing_stage'] = target_stage
# Trigger the stage flow immediately by routing to it with empty input
result = f"GOTO_{target_stage.upper()}:"
elif command == '!start':
# Start/run the current stage (useful after transitioning to a new stage)
current_stage = context.get('writing_stage') or 'intro'
result = f"GOTO_{current_stage.upper()}:"
elif command == '!write':
# Proceed from source selection to section writing
if context.get('writing_stage') == 'section_writing':
result = "GOTO_SECTION_WRITER:"
else:
result = "COMMAND_OUTPUT:!write is only available during section_writing stage"
elif command == '!proofread':
# Proceed from section writing to proofreading
if context.get('writing_stage') == 'section_writing':
result = "GOTO_SECTION_PROOFREADER:"
else:
result = "COMMAND_OUTPUT:!proofread is only available during section_writing stage"
elif command == '!accept':
# Accept current section and move to next
if context.get('writing_stage') == 'section_writing':
@@ -177,7 +177,7 @@ actors:
section_paths = context.get('section_paths', [])
new_index = current_index + 1
context['current_section_index'] = new_index
# Check if we've completed all sections
if new_index >= len(section_paths):
# Keep stage as section_writing so !next advances to paper_review
@@ -203,7 +203,7 @@ actors:
result = "Final stage complete."
except (ValueError, IndexError):
result = "Error advancing stage."
elif command == '!stage':
stage_descriptions = {
'intro': 'Introduction to the writing system.',
@@ -218,7 +218,7 @@ actors:
current_stage = context.get('writing_stage', 'unknown')
description = stage_descriptions.get(current_stage, 'No description available.')
result = f"COMMAND_OUTPUT:Current Stage: {current_stage}\nPurpose: {description}"
elif command == '!stages':
stage_order = context.get('stage_order', [])
current_stage = context.get('writing_stage', 'unknown')
@@ -227,7 +227,7 @@ actors:
marker = '-->' if stage == current_stage else ' '
lines.append(f"{marker} {stage}")
result = 'COMMAND_OUTPUT:' + '\n'.join(lines)
elif command == '!context':
import json
context_copy = dict(context)
@@ -245,7 +245,7 @@ actors:
output_str += "\n\n-- History --\n"
output_str += json.dumps(history_to_show, indent=2, default=str)
result = 'COMMAND_OUTPUT:' + output_str
elif command == '!finish':
required_fields = ['topic', 'length', 'audience', 'publication', 'format']
paper_details = context.get('paper_details', {}) or {}
@@ -263,7 +263,7 @@ actors:
context['auto_finish_active'] = True
context['auto_finish_state'] = {'expect': None}
result = "GOTO_AUTO_FINISH:START"
else:
result = f"COMMAND_OUTPUT:Unknown command: {command}"
@@ -482,22 +482,22 @@ actors:
context['auto_finish_last_output'] = message
auto_active = context.get('auto_finish_active', False)
final_stage = context.get('auto_finish_final_stage', False)
# Check if this is the final output (latex source was just saved)
# We detect this by checking if latex_source exists and message contains latex-related content
latex_source = context.get('latex_source', '')
is_latex_completion = bool(latex_source) and ('document' in message.lower() or 'latex' in message.lower() or 'assembled' in message.lower() or 'compile' in message.lower())
# If auto-finish just completed (final stage done), return the full paper content
if final_stage and is_latex_completion:
# Mark as complete now
context['auto_finish_active'] = False
context['auto_finish_final_stage'] = False
context['auto_finish_state'] = {}
section_count = len(context.get('section_paths') or [])
topic = context.get('paper_details', {}).get('topic', 'Unknown')
# Build the complete paper output
output_parts = []
output_parts.append("=" * 80)
@@ -506,16 +506,16 @@ actors:
output_parts.append(f"\nPaper: {topic}")
output_parts.append(f"Sections: {section_count}")
output_parts.append("")
# Include the paper content from section_content
section_content = context.get('section_content', {})
section_paths = context.get('section_paths', [])
if section_content:
output_parts.append("\n" + "=" * 80)
output_parts.append("PAPER CONTENT")
output_parts.append("=" * 80 + "\n")
for path in section_paths:
content = section_content.get(path, '')
if content:
@@ -527,18 +527,18 @@ actors:
output_parts.append(f"\n{'#' * (depth + 1)} {path.split(' > ')[-1]}\n")
output_parts.append(content)
output_parts.append("")
# Include LaTeX if available
if latex_source:
output_parts.append("\n" + "=" * 80)
output_parts.append("LATEX SOURCE")
output_parts.append("=" * 80 + "\n")
output_parts.append(latex_source)
output_parts.append("\n" + "=" * 80)
output_parts.append("All stages completed: brainstorming, vetting, structure, section writing, paper review, and LaTeX generation.")
output_parts.append("=" * 80)
result = '\n'.join(output_parts)
elif not auto_active:
# Auto-finish was manually deactivated or never active - just pass through
@@ -665,7 +665,7 @@ actors:
result = f"ROUTE_ASK_OTHER:{msg}"
else:
result = "DISCOVERY_RESPONSE:Discovery complete! All parameters set. Type !next to proceed to brainstorming."
print(f"DEBUG discovery_controller: returning: {result}", file=sys.stderr)
ask_topic:
@@ -845,29 +845,29 @@ actors:
- name: save_vetting
code: |
import json
# Extract sources from the special markers
sources = []
message = input_data
if 'SOURCES_JSON_START' in message and 'SOURCES_JSON_END' in message:
start_marker = 'SOURCES_JSON_START'
end_marker = 'SOURCES_JSON_END'
start_pos = message.find(start_marker)
end_pos = message.find(end_marker)
if start_pos != -1 and end_pos != -1:
json_start = start_pos + len(start_marker)
json_content = message[json_start:end_pos].strip()
try:
sources = json.loads(json_content)
if not isinstance(sources, list):
sources = []
except json.JSONDecodeError:
sources = []
# Update context
if sources:
context['vetting_sources'] = sources
@@ -1046,13 +1046,13 @@ actors:
# Check if we need to parse the TOC first
section_paths = context.get('section_paths')
fallback_sections = ['Introduction', 'Methods', 'Results', 'Discussion']
# Re-parse if section_paths is empty, None, or still the generic fallback
needs_parse = (
not section_paths or
section_paths == fallback_sections
)
if needs_parse:
toc_text = context.get('table_of_contents', '')
if not toc_text:
@@ -1174,9 +1174,9 @@ actors:
You are helping select relevant sources for writing ONE SPECIFIC section of the paper.
CURRENT SECTION TO WRITE: "{{ context.current_section_path }}"
Section progress: {{ context.current_section_index + 1 }} of {{ context.section_paths|length if context.section_paths else 'unknown' }}
{% if ' > ' in context.current_section_path %}
NOTE: This is a SUBSECTION - you will be writing detailed content for this specific topic.
{% else %}
@@ -1193,20 +1193,20 @@ actors:
{% else %}
No vetted sources have been captured yet. Let the user know and suggest running !next after the vetting stage completes.
{% endif %}
YOUR TASK:
When you receive ANY message (including just a section name, "suggest something", or any other input):
1. First, announce which section we're working on: "Now working on section: [section name]"
2. List the available sources with their numbers and brief descriptions
3. Recommend which sources are most relevant for THIS specific section and explain why
4. Ask the user if they want to use these sources, find additional ones, or have questions
You MUST always show the actual source citations and your recommendations - never skip this step!
If the user asks for changes to source selection or has questions, help them.
IMPORTANT: When the user is satisfied with the source selection, tell them to type !write to proceed to writing.
Example ending: "These sources should work well for this section. When you're ready, type !write to proceed to writing."
@@ -1263,29 +1263,29 @@ actors:
- name: save_found_sources
code: |
import json
# Extract sources from the special markers
sources = []
message = input_data
if 'SOURCES_JSON_START' in message and 'SOURCES_JSON_END' in message:
start_marker = 'SOURCES_JSON_START'
end_marker = 'SOURCES_JSON_END'
start_pos = message.find(start_marker)
end_pos = message.find(end_marker)
if start_pos != -1 and end_pos != -1:
json_start = start_pos + len(start_marker)
json_content = message[json_start:end_pos].strip()
try:
sources = json.loads(json_content)
if not isinstance(sources, list):
sources = []
except json.JSONDecodeError:
sources = []
# Update context with new sources (replaces existing since source_finder includes all)
if sources:
context['vetting_sources'] = sources
@@ -1303,19 +1303,19 @@ actors:
max_history: 20
system_prompt: |
You are writing EXACTLY ONE section: "{{ context.current_section_path }}"
Paper topic: {{ context.paper_details.topic }}
Paper focus: {{ context.brainstorming_summary }}
Target length: {{ context.paper_details.length }} words total
Target audience: {{ context.paper_details.audience }}
Complete section structure (for reference only - write ONLY the current section):
{% if context.section_paths %}
{% for path in context.section_paths %}
{{ ">>> " if path == context.current_section_path else " " }}{{ path }}
{% endfor %}
{% endif %}
Available sources:
{% if context.vetting_sources %}
{% for source in context.vetting_sources %}
@@ -1325,7 +1325,7 @@ actors:
CRITICAL INSTRUCTIONS:
1. Write ONLY the content for "{{ context.current_section_path }}" - nothing else.
2. Section type guidance:
{% if ' > ' in context.current_section_path %}
- This is a SUBSECTION ({{ context.current_section_path }})
@@ -1337,12 +1337,12 @@ actors:
- Do NOT write the subsection content here - those will be written separately
- Just provide a roadmap/overview of what the subsections will address
{% endif %}
3. Do NOT include:
- Content from other sections
- Subsection headers or subsection content (those are separate sections)
- A full treatment of the topic if this is a parent section
4. Use academic tone and cite sources appropriately.
YOUR TASK:
@@ -1350,14 +1350,14 @@ actors:
- Include proper academic citations from the available sources (e.g., Author et al., Year)
- Work with the user to refine the content based on their feedback
- If the user asks for changes, make them and present the revised content
RESPONSE FORMAT (MANDATORY):
SECTION_CONTENT:
<final section text>
NEXT_ACTION:
Type !proofread when you are satisfied with this section.
Do NOT include any other commentary, explanations, or conversational text. The SECTION_CONTENT block must contain only the section prose that will be stored in the paper.
section_writer_saver:
@@ -1464,16 +1464,16 @@ actors:
5. Look for logical inconsistencies or unclear arguments
6. Ensure smooth transitions and flow
7. Verify the content matches what the section should cover (based on the TOC)
YOUR TASK:
- Present your detailed proofreading feedback on the section content shown above
- List any issues found or confirm the section is well-written
- If the user asks you to make changes, make them and present the corrected version
- When you provide a fully revised section, respond with **only** `UPDATED_SECTION_CONTENT:` followed by the final section text. This allows the system to store the new content verbatim.
- Work with the user until they are satisfied with the section
IMPORTANT: When the user is satisfied with the proofread section, tell them to type !accept to accept the section and move to the next one.
Example ending: "The section looks good overall. Type !accept when you're ready to move to the next section."
@@ -1513,14 +1513,14 @@ actors:
section_content = context.get('section_content', {})
section_paths = context.get('section_paths', [])
# Debug: show what sections we have
print(f"DEBUG section_content has {len(section_content)} sections", file=sys.stderr)
print(f"DEBUG section_paths has {len(section_paths)} paths", file=sys.stderr)
for p in section_paths[:5]:
has_content = p in section_content
print(f"DEBUG path={p[:50]} has_content={has_content}", file=sys.stderr)
if not section_content:
result = "ERROR: No sections found. Please complete section writing stage first."
else:
@@ -1900,7 +1900,7 @@ routes:
target: auto_finish_driver
extract_message: true
separator: ":"
# Command output (non-routing command results) go directly to end
- match_type: prefix
@@ -1975,14 +1975,14 @@ routes:
target: section_accept_handler
extract_message: true
separator: ":"
- match_type: prefix
pattern: "GOTO_PAPER_REVIEW"
target: paper_review
extract_message: true
separator: ":"
- match_type: prefix
pattern: "GOTO_LATEX_GENERATION"
@@ -2105,9 +2105,9 @@ routes:
target: auto_finish_driver
extract_message: true
separator: ":"
# Paper review routing
- match_type: prefix
pattern: "ROUTE_REVIEW_PAPER"
target: paper_review_agent
@@ -2185,7 +2185,7 @@ routes:
auto_finish_passthrough:
type: actor
actor: auto_finish_passthrough
intro:
type: actor
actor: intro_agent
@@ -2291,14 +2291,14 @@ routes:
paper_review:
type: actor
actor: paper_review_controller
paper_review_actor:
type: actor
actor: paper_review_agent
metadata:
max_history_messages: 10
max_history_chars: 6000
paper_review_saver:
type: actor
actor: paper_review_saver
@@ -2528,7 +2528,7 @@ routes:
type: context_value
key: next_node
value: paper_review
- source: router
target: paper_review_agent
condition:
+4 -4
View File
@@ -16,19 +16,19 @@ routes:
simple_chat:
type: graph
entry_point: start
nodes:
# Process user input
process_input:
type: agent
agent: assistant
edges:
- source: start
target: process_input
- source: process_input
target: end
# Input stream that triggers the graph
chat_input:
type: stream
@@ -50,4 +50,4 @@ context:
app_name: "Simple LangGraph Chat"
# Actor-specific configuration
default_actor: openai/gpt-3.5-turbo
enable_actor_fallback: true
enable_actor_fallback: true
-1
View File
@@ -28,4 +28,3 @@ mcp_servers:
- create_pull_request
- list_repos
- get_file_contents
-1
View File
@@ -34,4 +34,3 @@ inline_tools:
type: string
required: ["text"]
writes: false
-1
View File
@@ -20,4 +20,3 @@ mcp_servers:
tool_filter:
exclude:
- delete_project
-1
View File
@@ -8,4 +8,3 @@ tools:
- name: builtin/read_file
- name: builtin/list_directory
- name: builtin/search_files
-1
View File
@@ -2,4 +2,3 @@
# Register: agents skill add --config validation-only.yaml
name: local/empty-skill