Conversation
Automated sync from stranske/Workflows Template hash: a4274c4ed410 Changes synced from sync-manifest.yml
🤖 Keepalive Loop StatusPR #144 | Agent: Codex | Iteration 0/5 Current State
🔍 Failure Classification| Error type | infrastructure | |
There was a problem hiding this comment.
Pull request overview
Syncs workflow templates/scripts from stranske/Workflows, expanding the automation stack to support agent registry–driven routing and adding LangSmith trace metadata capture for LangChain-based steps.
Changes:
- Added agent registry (
.github/agents/registry.yml) and JS helper (.github/scripts/agent_registry.js), and updated multiple workflows to resolveagent_key/ branch prefixes from it. - Added LangSmith metadata + trace URL extraction utilities and propagated trace IDs/URLs into verifier + follow-up issue generator outputs.
- Updated workflow LLM dependency pins and refreshed several workflows’ triggering/labeling behavior (e.g., autofix
workflow_jobtrigger, verify-to-* label routing).
Reviewed changes
Copilot reviewed 20 out of 20 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| tools/requirements-llm.txt | Bumps pinned LangChain-related runtime deps for workflow LLM steps. |
| tools/llm_provider.py | Adds shared LangSmith config/metadata builders and trace extraction helpers. |
| scripts/sync_dev_dependencies.py | Simplifies output/flow for --check vs --apply. |
| scripts/langchain/pr_verifier.py | Captures LangSmith trace id/url from invocations and surfaces them in reports. |
| scripts/langchain/issue_optimizer.py | Minor formatting/whitespace sync. |
| scripts/langchain/followup_issue_generator.py | Captures LangSmith traces per operation and appends trace links as comments. |
| CLAUDE.md | Removes the CI test policy section from assistant guidance. |
| .github/workflows/autofix.yml | Adds workflow_job trigger and refactors PR context resolution/helpers. |
| .github/workflows/agents-verify-to-new-pr.yml | Includes registry helper in sparse checkout; routes follow-up issue labels based on resolved agent. |
| .github/workflows/agents-verify-to-issue.yml | Updates user-facing guidance to reference agent:* labels generically. |
| .github/workflows/agents-verify-to-issue-v2.yml | Includes registry helper in sparse checkout; routes follow-up issue labels based on resolved agent. |
| .github/workflows/agents-autofix-loop.yml | Adds agent type detection via registry and gates loop to Codex-only support. |
| .github/workflows/agents-auto-pilot.yml | Loads default agent + branch prefix from registry and dispatches belt with agent_key. |
| .github/workflows/agents-73-codex-belt-conveyor.yml | Adds agent_key input and uses registry-derived branch prefix + concurrency naming. |
| .github/workflows/agents-72-codex-belt-worker.yml | Adds agent_key input and updates labeling/branch-step conventions to be agent-aware. |
| .github/workflows/agents-72-codex-belt-worker-dispatch.yml | Adds agent_key input passthrough for manual dispatch wrapper. |
| .github/workflows/agents-71-codex-belt-dispatcher.yml | Adds agent_key input/output and uses registry-derived queue labels + branch prefix. |
| .github/scripts/keepalive_loop.js | Resolves agent routing via registry helper (safer handling of conflicting agent labels). |
| .github/scripts/agent_registry.js | New registry loader + minimal YAML parser + routing/config helpers. |
| .github/agents/registry.yml | New source-of-truth registry for agents (default agent, secrets, branch prefix, capabilities). |
Comments suppressed due to low confidence (1)
.github/workflows/agents-72-codex-belt-worker.yml:236
- This step interpolates
${{ inputs.agent_key }}directly into a single-quoted JavaScript string. If the input contains quotes/newlines, it can break the script and potentially allow JS injection. Use${{ toJson(inputs.agent_key) }}(or an env var) to safely pass the input into the github-script step.
script: |
const agentKey = String('${{ inputs.agent_key }}' || 'codex').trim().toLowerCase() || 'codex';
const issueInput = '${{ inputs.issue }}'.trim();
const branchInput = '${{ inputs.branch }}'.trim();
const baseInput = '${{ inputs.base }}'.trim();
const sourceInput = '${{ inputs.source }}'.trim();
| # Fallback: Some LangChain providers may use id attribute directly | ||
| # WARNING: This may not always correspond to the LangSmith trace ID | ||
| if hasattr(response, "id"): | ||
| trace_id = str(response.id) | ||
| logger.debug( | ||
| "Using response.id as trace ID (fallback). " | ||
| "Verify this corresponds to LangSmith trace for your provider." | ||
| ) | ||
| return trace_id | ||
|
|
||
| # Additional fallback for compatibility | ||
| if hasattr(response, "__dict__"): | ||
| response_dict = response.__dict__ | ||
| if "id" in response_dict: | ||
| trace_id = str(response_dict["id"]) | ||
| logger.debug( | ||
| "Using response.__dict__['id'] as trace ID (fallback). " | ||
| "Verify this corresponds to LangSmith trace for your provider." | ||
| ) | ||
| return trace_id |
There was a problem hiding this comment.
extract_trace_id() falls back to using response.id / __dict__['id'] as the LangSmith trace ID without validating the format. In many LangChain providers this id is a provider message/completion id (e.g., chatcmpl-...) rather than a LangSmith run UUID, which will produce misleading trace URLs/logging. Consider only accepting the fallback when the value matches the expected LangSmith run id format (e.g., UUID), otherwise return None.
| const forced = '${{ inputs.force_issue }}'; | ||
| const agentKey = String('${{ inputs.agent_key }}' || 'codex').trim().toLowerCase() || 'codex'; |
There was a problem hiding this comment.
This step interpolates ${{ inputs.agent_key }} directly into a single-quoted JavaScript string. If the input contains quotes/newlines (even accidentally), it can break the script (and in the worst case enable script injection). Prefer injecting workflow inputs via ${{ toJson(inputs.agent_key) }} (or pass via env) so the value is safely escaped before it reaches JS.
| const forced = '${{ inputs.force_issue }}'; | |
| const agentKey = String('${{ inputs.agent_key }}' || 'codex').trim().toLowerCase() || 'codex'; | |
| const forced = ${{ toJson(inputs.force_issue) }}; | |
| const agentKeyInput = ${{ toJson(inputs.agent_key) }}; | |
| const agentKey = String(agentKeyInput || 'codex').trim().toLowerCase() || 'codex'; |
| const issueValue = Number(issueRaw); | ||
| const issueNumber = Number.isFinite(issueValue) && issueValue > 0 ? issueValue : null; | ||
| const branch = '${{ inputs.branch }}'.trim(); | ||
| const agentKey = String('${{ inputs.agent_key }}' || 'codex').trim().toLowerCase() || 'codex'; | ||
| const prNumber = Number('${{ inputs.pr_number }}'); | ||
| const targetPr = Number.isFinite(prNumber) ? `#${prNumber}` : 'Unknown'; | ||
| const modeDisplay = dryRun ? 'Preview (dry run)' : 'Live (merge ready)'; | ||
| const runId = context.runId; | ||
| const concurrencyKey = branch || issueNumber || runId; | ||
| const concurrencyGroup = concurrencyKey ? `codex-belt-conveyor-${concurrencyKey}` : ''; | ||
| const concurrencyGroup = concurrencyKey | ||
| ? (agentKey === 'codex' | ||
| ? `codex-belt-conveyor-${concurrencyKey}` |
There was a problem hiding this comment.
inputs.agent_key is injected into JS via a single-quoted string literal (several occurrences in this workflow). If the value contains quotes/newlines, it can break the script and may enable JS injection. Prefer ${{ toJson(inputs.agent_key) }} (or env) so the value is JSON-escaped before use.
| const agentKey = String('${{ inputs.agent_key }}' || 'codex').trim().toLowerCase() || 'codex'; | ||
| let branchPrefix = 'codex/issue-'; | ||
| try { | ||
| const { getAgentConfig } = require('./.github/scripts/agent_registry.js'); | ||
| const cfg = getAgentConfig(agentKey); | ||
| branchPrefix = String(cfg.branch_prefix || branchPrefix); |
There was a problem hiding this comment.
Another instance of directly interpolating ${{ inputs.agent_key }} into a single-quoted JS string literal. To avoid broken scripts / injection risk, pass the value via ${{ toJson(inputs.agent_key) }} (or env) before calling getAgentConfig() / building regex patterns.
| const { withRetry } = retryHelpers; | ||
| const { owner, repo } = context.repo; | ||
| const agentKey = String('${{ inputs.agent_key }}' || 'codex').trim().toLowerCase() || 'codex'; | ||
| try { | ||
| await withRetry(() => github.rest.actions.createWorkflowDispatch({ | ||
| owner, | ||
| repo, | ||
| workflow_id: 'agents-71-codex-belt-dispatcher.yml', | ||
| ref: 'refs/heads/' + (process.env.GITHUB_REF_NAME || context.ref.replace('refs/heads/', '')) | ||
| ref: 'refs/heads/' + (process.env.GITHUB_REF_NAME || context.ref.replace('refs/heads/', '')), | ||
| inputs: { | ||
| agent_key: agentKey, | ||
| }, |
There was a problem hiding this comment.
This workflow dispatch step also injects ${{ inputs.agent_key }} into JS via a single-quoted literal before using it in API inputs. Use ${{ toJson(inputs.agent_key) }} (or env) so the string is safely escaped and cannot break the github-script step.
|
Autofix updated these files:
|
|
Superseded by newer sync PR #145 |
Sync Summary
Files Updated
Files Skipped
Review Checklist
Source: stranske/Workflows
Manifest:
.github/sync-manifest.yml