chore: sync workflow templates - #5232
Conversation
Automated sync from stranske/Workflows Template hash: e8404abaa4ec Changes synced from sync-manifest.yml
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 82323a2a31
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if (markerPattern && hasTitle && !cleanString(issue.body)) { | ||
| return true; |
There was a problem hiding this comment.
Require marker/label before matching empty-body trackers
This early return makes any non-PR issue with a matching title look like a tracker whenever markerPattern is configured and the issue body is empty, even if it has neither tracker labels nor marker content. In findTracker, that can select and mutate the wrong issue (labels/body updates) when a similarly titled empty issue exists, because issueMatchesTracker is used both before and after fetching the full issue.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Pull request overview
This PR syncs workflow-template utilities from stranske/Workflows into this repository, adding shared runner dispatch helpers plus a shared “issue/PR context” truncation utility so downstream agent workflows can cap prompt size consistently.
Changes:
- Added
scripts/runner_lib/utilities for assembling provider prompts, parsing runner output, and debouncing dispatches via GitHub-backed storage. - Introduced
scripts/langchain/issue_pr_context.pyand integrated token-budget capping into issue ingestion scripts (issue_formatter,issue_optimizer,context_extractor) plus improved workflow-sync acceptance-criteria detection. - Added new durable tracker / sync-state helpers under
.github/scripts/sync_tracker_state/and enhanced.github/scripts/issue_context_utils.jsto use the shared Python context capper.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| scripts/runner_lib/core.py | New shared runner prompt assembly, output parsing, and dispatch debounce utilities. |
| scripts/runner_lib/init.py | Exposes runner_lib public API via __all__. |
| scripts/runner_lib/main.py | Provides python -m scripts.runner_lib entrypoint. |
| scripts/langchain/issue_pr_context.py | New shared issue/PR context builder with token-budget truncation and marker reuse. |
| scripts/langchain/issue_optimizer.py | Caps issue body via shared context builder before LLM analysis/apply flows. |
| scripts/langchain/issue_formatter.py | Caps issue body via shared context builder before formatting. |
| scripts/langchain/context_extractor.py | Caps issue body via shared context builder before context extraction. |
| scripts/langchain/followup_issue_generator.py | Refines detection of workflow-sync vs repo-local acceptance criteria. |
| .github/scripts/sync_tracker_state/index.js | New durable tracker + stuck-window helpers for consumer sync workflows. |
| .github/scripts/issue_context_utils.js | Adds Python-backed capped issue payload extraction and returns truncation metadata. |
| .github/scripts/agents_pr_meta_update_body.js | Ensures downstream context extraction runs with a stable workflow identifier via env. |
|
|
||
| from scripts import reference_packs | ||
| from scripts.state_fingerprint import GitHubApi, _github_context | ||
|
|
| clone_dir = Path("/tmp") / f"ref-pack-{plan.name}" | ||
| shutil.rmtree(clone_dir, ignore_errors=True) | ||
| clone_url = f"https://github.com/{plan.repo}.git" | ||
| if token: | ||
| clone_url = f"https://x-access-token:{token}@github.com/{plan.repo}.git" | ||
|
|
||
| clone_cmd = ["git", "clone", "--depth=1", "--filter=blob:none", "--sparse"] | ||
| is_sha = bool(re.fullmatch(r"[0-9a-fA-F]{40}", plan.ref)) | ||
| if not is_sha: | ||
| clone_cmd.extend(["--branch", plan.ref]) | ||
| clone_cmd.extend([clone_url, str(clone_dir)]) | ||
| subprocess.check_call(clone_cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) |
| try { | ||
| const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'workflows-issue-context-')); | ||
| const inputPath = path.join(tmpDir, 'issue.md'); | ||
| fs.writeFileSync(inputPath, body, 'utf8'); | ||
| const args = [ | ||
| 'scripts/langchain/issue_pr_context.py', | ||
| '--kind', | ||
| 'issue', | ||
| '--input-file', | ||
| inputPath, | ||
| '--json', | ||
| '--token-budget', | ||
| String(options.tokenBudget || process.env.ISSUE_PR_CONTEXT_TOKEN_BUDGET || 4000), | ||
| '--downstream-workflow', | ||
| options.downstreamWorkflow || process.env.ISSUE_PR_CONTEXT_WORKFLOW || 'issue_context_utils', | ||
| ]; | ||
| const output = childProcess.execFileSync('python3', args, { encoding: 'utf8' }); | ||
| const payload = JSON.parse(output); | ||
| return { | ||
| formattedBody: String(payload.formatted_body || body), | ||
| truncated: Boolean(payload.truncated), | ||
| estimatedTokens: payload.estimated_tokens, | ||
| tokenBudget: payload.token_budget, | ||
| }; | ||
| } catch (_error) { | ||
| return { formattedBody: body, truncated: false }; | ||
| } |
| 'use strict'; | ||
|
|
||
| // API guard: callers pass createTokenAwareRetry / github-api-with-retry.js | ||
| // `withRetry` wrappers into these helpers; tests use lightweight mock clients. | ||
| const DURABLE_TRACKER_LABEL = 'tracker:durable'; | ||
| const AUTOMATED_LABEL = 'automated'; | ||
| const DEFAULT_STUCK_WINDOW_SCHEMA = 'sync-tracker-stuck-window/v1'; | ||
| const STUCK_WINDOW_MARKER_RE = /<!--\s*sync-tracker-stuck-window:v1\s+([\s\S]*?)\s*-->/; | ||
| const DURABLE_HEADER_RE = /^>\s*\*\*Durable tracker\*\*[\s\S]*?(?=\n(?!>)|\n*$)/im; | ||
|
|
| def parse_runner_output(provider: str, raw_output: str) -> RunnerResult: | ||
| """Parse raw Codex/Claude output into a common result shape.""" | ||
| provider = _validate_provider(provider) | ||
| raw = raw_output or "" | ||
| truncated = len(raw) > 64000 or bool(re.search(r"\btruncated\b", raw, re.IGNORECASE)) | ||
| clipped = raw[:64000] if len(raw) > 64000 else raw | ||
|
|
||
| messages, errors = _parse_jsonl_output(clipped) if provider == "codex" else ([], []) | ||
| final_message = messages[-1] if messages else clipped.strip() | ||
|
|
||
| if not errors and re.search(r"(^::error::|\bTraceback\b|\bError:|\bException\b)", clipped): | ||
| first = next((line.strip() for line in clipped.splitlines() if line.strip()), "") | ||
| errors.append(first or "runner output indicates an error") | ||
|
|
||
| if not final_message: | ||
| final_message = "No output captured" | ||
|
|
||
| summary = re.sub(r"\s+", " ", final_message).strip()[:500] or "No output captured" | ||
| return RunnerResult( | ||
| provider=provider, | ||
| success=not errors, | ||
| final_message=final_message, | ||
| summary=summary, | ||
| error=errors[0] if errors else None, | ||
| truncated=truncated, | ||
| ) |
|
Closing as superseded by newer sync workflow template PR #5235 for this repository. |
Sync Summary
Files Updated
Files Skipped
Review Checklist
Source: stranske/Workflows
Source SHA:
14712a74486e8cc0325e7a818896dd75b32865ecTemplate hash:
e8404abaa4ecSync branch:
sync/workflows-e8404abaa4ecConsumer repo:
stranske/Trend_Model_ProjectManifest:
.github/sync-manifest.yml