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:
@@ -43,4 +43,3 @@ automation_profile: trusted
|
||||
invariants:
|
||||
- "All existing tests must continue to pass"
|
||||
- "Public API signatures must not change without deprecation"
|
||||
|
||||
|
||||
@@ -56,4 +56,3 @@ inputs_schema:
|
||||
- parquet
|
||||
required:
|
||||
- stages
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -25,4 +25,3 @@ definition_of_done: |
|
||||
reusable: true
|
||||
read_only: true
|
||||
state: available
|
||||
|
||||
|
||||
@@ -16,4 +16,3 @@ definition_of_done: |
|
||||
|
||||
reusable: true
|
||||
read_only: true
|
||||
|
||||
|
||||
@@ -34,4 +34,4 @@ context:
|
||||
global:
|
||||
conversation_mode: true
|
||||
# Actor-specific context variables
|
||||
default_actor: openai/gpt-4
|
||||
default_actor: openai/gpt-4
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -28,4 +28,3 @@ mcp_servers:
|
||||
- create_pull_request
|
||||
- list_repos
|
||||
- get_file_contents
|
||||
|
||||
|
||||
@@ -34,4 +34,3 @@ inline_tools:
|
||||
type: string
|
||||
required: ["text"]
|
||||
writes: false
|
||||
|
||||
|
||||
@@ -20,4 +20,3 @@ mcp_servers:
|
||||
tool_filter:
|
||||
exclude:
|
||||
- delete_project
|
||||
|
||||
|
||||
@@ -8,4 +8,3 @@ tools:
|
||||
- name: builtin/read_file
|
||||
- name: builtin/list_directory
|
||||
- name: builtin/search_files
|
||||
|
||||
|
||||
@@ -2,4 +2,3 @@
|
||||
# Register: agents skill add --config validation-only.yaml
|
||||
|
||||
name: local/empty-skill
|
||||
|
||||
|
||||
Reference in New Issue
Block a user