Skip to content

Commit 8cc65ea

Browse files
authored
Merge pull request #1882 from Hack23/copilot/fix-agentic-workflow-errors
Fix safeoutputs MCP session expiry causing silent PR failures across all news workflows
2 parents ab84c6b + b4a4397 commit 8cc65ea

12 files changed

Lines changed: 88 additions & 29 deletions

.github/aw/SHARED_PROMPT_PATTERNS.md

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,15 @@ TOTAL_READ_BYTES=0
7171
TOTAL_ONDISK_BYTES=0
7272
while read -r f; do
7373
if [ -f "$f" ]; then
74-
FSIZE=$(wc -c < "$f" | tr -d ' ')
74+
# AWF-safe: no $(...) command substitution — use tempfile + read redirection, then clean up.
75+
wc -c < "$f" | tr -d ' ' > /tmp/fsize-$$.txt
76+
read FSIZE < /tmp/fsize-$$.txt
77+
rm -f /tmp/fsize-$$.txt
7578
TOTAL_ONDISK_BYTES=$((TOTAL_ONDISK_BYTES + FSIZE))
76-
echo "--- BEGIN ANALYSIS FILE: $f (size: ${FSIZE} bytes) ---"
79+
echo "--- BEGIN ANALYSIS FILE: $f (size: $FSIZE bytes) ---"
7780
if [ "$FSIZE" -gt "$MAX_FILE_BYTES" ]; then
7881
# Extremely rare — emit the full file but warn.
79-
echo "⚠️ File exceeds ${MAX_FILE_BYTES}-byte soft cap; emitting in full regardless (§P0-5)."
82+
echo "⚠️ File exceeds $MAX_FILE_BYTES-byte soft cap; emitting in full regardless (§P0-5)."
8083
fi
8184
cat "$f"
8285
TOTAL_READ_BYTES=$((TOTAL_READ_BYTES + FSIZE))
@@ -497,7 +500,7 @@ if [ "$IS_TIER_C" = "1" ]; then
497500
monthly-review*) MULT_NUM=15; MULT_DEN=10 ;; # 1.5×
498501
*) MULT_NUM=10; MULT_DEN=10 ;; # fallback baseline
499502
esac
500-
echo "📐 Period-scope multiplier for '$ANALYSIS_SUBFOLDER': ${MULT_NUM}/${MULT_DEN}"
503+
echo "📐 Period-scope multiplier for '$ANALYSIS_SUBFOLDER': $MULT_NUM/$MULT_DEN"
501504

502505
declare -A TIER_C_BASE_SIZES=(
503506
["README.md"]=3000
@@ -513,9 +516,12 @@ if [ "$IS_TIER_C" = "1" ]; then
513516
echo "🔴 MISSING Tier-C: $REQUIRED_FILE — Tier-C workflow MUST CREATE"
514517
TIER_C_MISSING=$((TIER_C_MISSING + 1))
515518
else
516-
FSIZE=$(wc -c < "$ANALYSIS_DIR/$REQUIRED_FILE")
519+
# AWF-safe: no $(...) command substitution — use tempfile + read redirection, then clean up.
520+
wc -c < "$ANALYSIS_DIR/$REQUIRED_FILE" | tr -d ' ' > /tmp/fsize-$$.txt
521+
read FSIZE < /tmp/fsize-$$.txt
522+
rm -f /tmp/fsize-$$.txt
517523
if [ "$FSIZE" -lt "$MIN_SIZE" ]; then
518-
echo "🔴 UNDERSIZED Tier-C: $REQUIRED_FILE ($FSIZE bytes < $MIN_SIZE scaled minimum — base $BASE_SIZE × ${MULT_NUM}/${MULT_DEN}) — MUST ENRICH"
524+
echo "🔴 UNDERSIZED Tier-C: $REQUIRED_FILE ($FSIZE bytes < $MIN_SIZE scaled minimum — base $BASE_SIZE × $MULT_NUM/$MULT_DEN) — MUST ENRICH"
519525
TIER_C_MISSING=$((TIER_C_MISSING + 1))
520526
else
521527
echo "✅ OK Tier-C: $REQUIRED_FILE ($FSIZE bytes ≥ $MIN_SIZE scaled minimum)"
@@ -2663,9 +2669,10 @@ Then call the health gate:
26632669
> 🚨 **UNIVERSAL SAFE OUTPUT RULES — ALL WORKFLOWS MUST FOLLOW:**
26642670
>
26652671
> 1. **Call `safeoutputs___create_pull_request` as EARLY as possible** — the moment you have committed files. The safeoutputs MCP session has a finite lifetime. Successful runs call it by minute ~25. Failed runs that delayed past minute 40 got "session not found" and lost all work.
2666-
> 2. **NEVER call `safeoutputs___noop` when artifacts exist.** Noop means "I did nothing." If you created files, you DID something and MUST create a PR. Partial work in a PR is infinitely better than lost work via noop.
2667-
> 3. **At HARD DEADLINE**: If ANY files were created → `safeoutputs___create_pull_request`. ONLY noop if truly ZERO files were created.
2668-
> 4. **Architecture reminder**: `safeoutputs___create_pull_request` records your intent. A separate `safe_outputs` job executes the PR creation AFTER the agent job ends. If the MCP session expires before you record the intent, the `safe_outputs` job is SKIPPED and all work is lost.
2672+
> 2. **Heartbeat PR to keep the safeoutputs session alive (`max: 2+`)** — the Streamable-HTTP safeoutputs MCP session has a ~30–35 min idle lifetime (observed in PR #1835 and run #24672037751). Every `safeoutputs___create_pull_request` call **resets the session idle timer**. If the workflow sets `create-pull-request.max: 2` or higher, call the tool once at minute ~22–25 as a **heartbeat PR** capturing work-in-progress (partial analysis + first article draft), then call it again at minute 40–45 with the polished final output. Each call creates a separate PR on a separate branch; the final PR supersedes the heartbeat. This pattern was proven in `news-translate` (`max: 5`, zero session expiries across 55-minute runs) and `news-realtime-monitor` (`max: 3`). **Single-PR workflows (`max: 1`) that delay their only call past minute 35 WILL lose all work to session expiry.**
2673+
> 3. **NEVER call `safeoutputs___noop` when artifacts exist.** Noop means "I did nothing." If you created files, you DID something and MUST create a PR. Partial work in a PR is infinitely better than lost work via noop.
2674+
> 4. **At HARD DEADLINE**: If ANY files were created → `safeoutputs___create_pull_request`. ONLY noop if truly ZERO files were created.
2675+
> 5. **Architecture reminder**: `safeoutputs___create_pull_request` records your intent. A separate `safe_outputs` job executes the PR creation AFTER the agent job ends. If the MCP session expires before you record the intent, the `safe_outputs` job is SKIPPED and all work is lost.
26692676
26702677
### Layer 3: MCP Gateway Diagnostics (run when tools fail)
26712678
@@ -2932,9 +2939,9 @@ echo "=== 🔍 Analysis Enrichment Verification Gate ==="
29322939
for f in "$ANALYSIS_DIR"/*.md; do
29332940
[ ! -f "$f" ] && continue
29342941
# Skip the factual data-download-manifest.md — its script marker is expected and not a stub
2935-
FBASE=$(basename "$f")
2936-
case "$FBASE" in
2937-
data-download-manifest.md) echo "⏭️ SKIP (factual manifest): $f"; continue ;;
2942+
# AWF-safe: use `$f` path-pattern tests instead of $(basename "$f")
2943+
case "$f" in
2944+
*/data-download-manifest.md) echo "⏭️ SKIP (factual manifest): $f"; continue ;;
29382945
esac
29392946
# Match the legacy `pre-article-analysis script` marker present in historical stub files.
29402947
# The current download script writes only the factual `data-download-manifest.md` (skipped above),

.github/workflows/news-article-generator.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ safe-outputs:
128128
labels: [agentic-news, analysis-data]
129129
draft: false
130130
expires: 14d
131+
max: 2
131132
add-comment: {}
132133
dispatch-workflow:
133134
workflows: [news-translate]
@@ -379,7 +380,9 @@ read START_TIME < /tmp/start_time.txt
379380
| Setup | 0–3 | Date check, `get_sync_status()` warm-up, check recent generation |
380381
| Download | 3–6 | Run data download scripts (MCP data fetch) |
381382
| **AI Analysis Pass 1** | **6–21** | **🚨 MANDATORY 15 min minimum**: Read ALL methodology guides, create per-file analysis for EVERY document with Mermaid diagrams, evidence tables, SWOT entries. |
382-
| **AI Analysis Pass 2** | **21–28** | **🚨 MANDATORY 7 min minimum**: Read ALL analysis back completely, improve every section, replace ALL script stubs with AI analysis. |
383+
| **AI Analysis Pass 2 (Part A)** | **21–22** | Begin reading ALL analysis artifacts back and identify improvement targets. |
384+
| **Heartbeat PR** | **22–25** | 🫀 `git add && git commit` analysis + any drafts so far, then `safeoutputs___create_pull_request` (title `🫀 Heartbeat - Article Generator - {date}`). This refreshes the safeoutputs MCP session (which expires after ~30–35 min idle) AND guarantees no work is lost if later phases fail. After the call succeeds, run `git checkout main` so subsequent commits don't stack onto the frozen patch. |
385+
| **AI Analysis Pass 2 (Part B)** | **25–28** | **Complete improvements (6 min improvement work total across Parts A+B)**: improve every section, replace ALL script stubs with AI analysis. |
383386
| Gates | 28–30 | Run ENFORCED Minimum Time Gate + Enrichment Verification Gate (SHARED_PROMPT_PATTERNS.md). Both MUST pass. |
384387
| Generate | 30–36 | Run `generate-news-enhanced.ts` in batches |
385388
| **Article Improvement** | **36–40** | 🚨 Read ALL articles back, replace AI_MUST_REPLACE markers, improve content. Run article quality component gate. |
@@ -389,6 +392,7 @@ read START_TIME < /tmp/start_time.txt
389392
> ⚠️ **Analysis phase is 22 minutes minimum (Pass 1: 15 min + Pass 2: 7 min)** — every analysis file must contain color-coded Mermaid diagrams, structured evidence tables with dok_id citations, and follow template structure exactly. ALL script-generated stubs MUST be replaced with AI-enriched analysis. Run the ENFORCED gates from SHARED_PROMPT_PATTERNS.md before article generation.
390393
391394
**Hard cutoffs** — check elapsed time before each phase:
395+
- `>= 25 min` and no safeoutputs call yet → 🚨 call `safeoutputs___create_pull_request` as a heartbeat with whatever files exist. Do NOT delay — the safeoutputs session expires at ~30–35 min idle.
392396
- `>= 35 min` → Stop generating, commit what you have, create PR immediately
393397
- `>= 43 min` → STOP ALL WORK, call safe output immediately
394398

.github/workflows/news-committee-reports.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ safe-outputs:
119119
labels: [agentic-news, analysis-data]
120120
draft: false
121121
expires: 14d
122+
max: 2
122123
add-comment: {}
123124
dispatch-workflow:
124125
workflows: [news-translate]
@@ -286,7 +287,9 @@ read START_TIME < /tmp/start_time.txt
286287
- **Minutes 0–3**: Date check, MCP warm-up with `get_sync_status()`
287288
- **Minutes 3–6**: Run download-parliamentary-data pipeline (download data)
288289
- **Minutes 6–21**: 🚨 **AI Analysis Pass 1 (15 min minimum)**: Read ALL methodology guides, create per-file analysis for EVERY document with Mermaid diagrams, evidence tables, SWOT entries.
289-
- **Minutes 21–28**: 🚨 **AI Analysis Pass 2 (7 min minimum)**: Read ALL analysis back completely, improve every section, replace ALL script stubs with AI analysis. Run enrichment verification gate.
290+
- **Minutes 21–22**: 🚨 **AI Analysis Pass 2 (Part A, start)**: Begin reading ALL analysis artifacts back and identify improvement targets.
291+
- **Minutes 22–25**: 🫀 **Heartbeat PR**`git add && git commit` analysis artifacts so far, then `safeoutputs___create_pull_request` (title `🫀 Heartbeat - Committee Reports - {date}`). Refreshes the safeoutputs MCP session (idle timeout ~30–35 min) AND preserves work if later phases fail. Run `git checkout main` after the call so subsequent commits don't stack onto the frozen patch.
292+
- **Minutes 25–28**: 🚨 **AI Analysis Pass 2 (Part B, complete — 6 min improvement work total across Parts A+B)**: Improve every section, replace ALL script stubs with AI analysis. Run enrichment verification gate.
290293
- **Minutes 28–30**: Run ENFORCED Minimum Time Gate + Enrichment Verification Gate (SHARED_PROMPT_PATTERNS.md). Both MUST pass.
291294
- **Minutes 30–36**: Generate articles for core languages (EN, SV) using `npx tsx scripts/generate-news-enhanced.ts`
292295
- **Minutes 36–40**: 🚨 **Article Improvement Pass**: Read ALL articles back, replace AI_MUST_REPLACE markers, improve content. Run article quality component gate.

.github/workflows/news-evening-analysis.md

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ safe-outputs:
127127
labels: [agentic-news, analysis-data]
128128
draft: false
129129
expires: 14d
130+
max: 2
130131
add-comment: {}
131132
dispatch-workflow:
132133
workflows: [news-translate]
@@ -317,7 +318,9 @@ read START_TIME < /tmp/start_time.txt
317318
| Setup | 0–3 | Date check, `get_sync_status()`, determine day type | MCP responds |
318319
| Download | 3–6 | Run `populate-analysis-data.ts` + `download-parliamentary-data.ts` (script-driven data download) | Data files exist |
319320
| **AI Analysis Pass 1** | **6–21** | **🚨 MANDATORY 15 min minimum**: Read ALL methodology guides, create per-file analysis for EVERY document with Mermaid diagrams, evidence tables, SWOT entries. **Create ALL 9 required artifacts.** | 9 artifact files exist |
320-
| **AI Analysis Pass 2** | **21–28** | **🚨 MANDATORY 7 min minimum**: Read ALL 9 analysis artifacts back completely, improve every section, add missing Mermaid diagrams and evidence tables, replace ALL script stubs with AI analysis. | All 9 files ≥500 bytes |
321+
| **AI Analysis Pass 2 (Part A)** | **21–22** | Begin reading ALL 9 analysis artifacts back and identify improvement targets. | Files opened for review |
322+
| **Heartbeat PR** | **22–25** | 🫀 `git add && git commit` analysis + any drafts so far, then `safeoutputs___create_pull_request` (title `🫀 Heartbeat - Evening Analysis - {date}`). This refreshes the safeoutputs MCP session (which expires after ~30–35 min idle) AND guarantees no work is lost if later phases fail. After the call succeeds, run `git checkout main` so subsequent commits don't stack onto the frozen patch. | Heartbeat PR created |
323+
| **AI Analysis Pass 2 (Part B)** | **25–28** | **Complete improvements (6 min improvement work total across Parts A+B)**: improve every section, add missing Mermaid diagrams and evidence tables, replace ALL script stubs with AI analysis. | All 9 files ≥500 bytes |
321324
| Gates | 28–30 | Run ENFORCED Minimum Time Gate + Enrichment Verification Gate + **9-artifact completeness check** (SHARED_PROMPT_PATTERNS.md). ALL MUST pass. | 0 failures |
322325
| Generate | 30–36 | Run generation script OR manual synthesis (see Step 3) | HTML files created |
323326
| **Article Improvement** | **36–40** | 🚨 **Article Improvement Pass**: Read ALL articles back, replace AI_MUST_REPLACE markers, improve content. Run article quality component gate. | 0 AI_MUST_REPLACE markers |
@@ -328,7 +331,7 @@ read START_TIME < /tmp/start_time.txt
328331
>
329332
> 🔴 **ANTI-PATTERN (REJECTED)**: Creating only synthesis-summary.md + significance-scoring.md + stakeholder-perspectives.md and skipping the other 6 artifacts. This produces shallow articles missing SWOT tables, risk matrices, threat analysis, and classification data.
330333
331-
**Hard cutoffs**: `>= 35 min` → commit & PR now; `>= 43 min` → STOP ALL WORK, call safe output immediately.
334+
**Hard cutoffs**: `>= 25 min` and no safeoutputs call yet → 🚨 call `safeoutputs___create_pull_request` as a heartbeat with whatever files exist (do NOT delay — the safeoutputs session expires at ~30–35 min idle); `>= 35 min` → commit & PR now; `>= 43 min` → STOP ALL WORK, call safe output immediately.
332335

333336
## Required Skills
334337

@@ -611,9 +614,12 @@ for REQUIRED_FILE in README.md executive-brief.md scenario-analysis.md comparati
611614
echo "🔴 MISSING Tier-C: $REQUIRED_FILE — aggregation workflow MUST CREATE"
612615
MISSING=$((MISSING + 1))
613616
else
614-
FSIZE=$(wc -c < "$ANALYSIS_DIR/$REQUIRED_FILE")
617+
# AWF-safe: no $(...) command substitution — use tempfile + read redirection, then clean up.
618+
wc -c < "$ANALYSIS_DIR/$REQUIRED_FILE" | tr -d ' ' > /tmp/fsize-$$.txt
619+
read FSIZE < /tmp/fsize-$$.txt
620+
rm -f /tmp/fsize-$$.txt
615621
if [ "$FSIZE" -lt "$MIN" ]; then
616-
echo "🔴 UNDERSIZED Tier-C: $REQUIRED_FILE ($FSIZE < $MIN — base $BASE_MIN × ${PERIOD_SCOPE_MULT_NUM}/${PERIOD_SCOPE_MULT_DEN}) — MUST ENRICH"
622+
echo "🔴 UNDERSIZED Tier-C: $REQUIRED_FILE ($FSIZE < $MIN — base $BASE_MIN × $PERIOD_SCOPE_MULT_NUM/$PERIOD_SCOPE_MULT_DEN) — MUST ENRICH"
617623
MISSING=$((MISSING + 1))
618624
else
619625
echo "✅ OK Tier-C: $REQUIRED_FILE ($FSIZE bytes)"

.github/workflows/news-interpellations.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ safe-outputs:
119119
labels: [agentic-news, analysis-data]
120120
draft: false
121121
expires: 14d
122+
max: 2
122123
add-comment: {}
123124
dispatch-workflow:
124125
workflows: [news-translate]
@@ -295,7 +296,9 @@ read START_TIME < /tmp/start_time.txt
295296
- **Minutes 0–3**: Date check, MCP warm-up with `get_sync_status()`
296297
- **Minutes 3–6**: Run download-parliamentary-data pipeline (download data)
297298
- **Minutes 6–21**: 🚨 **AI Analysis Pass 1 (15 min minimum)**: Read ALL methodology guides, create per-file analysis for EVERY document with Mermaid diagrams, evidence tables, SWOT entries.
298-
- **Minutes 21–28**: 🚨 **AI Analysis Pass 2 (7 min minimum)**: Read ALL analysis back completely, improve every section, replace ALL script stubs with AI analysis. Run enrichment verification gate.
299+
- **Minutes 21–22**: 🚨 **AI Analysis Pass 2 (Part A, start)**: Begin reading ALL analysis artifacts back and identify improvement targets.
300+
- **Minutes 22–25**: 🫀 **Heartbeat PR**`git add && git commit` analysis artifacts so far, then `safeoutputs___create_pull_request` (title `🫀 Heartbeat - Interpellations - {date}`). Refreshes the safeoutputs MCP session (idle timeout ~30–35 min) AND preserves work if later phases fail. Run `git checkout main` after the call so subsequent commits don't stack onto the frozen patch.
301+
- **Minutes 25–28**: 🚨 **AI Analysis Pass 2 (Part B, complete — 6 min improvement work total across Parts A+B)**: Improve every section, replace ALL script stubs with AI analysis. Run enrichment verification gate.
299302
- **Minutes 28–30**: Run ENFORCED Minimum Time Gate + Enrichment Verification Gate (SHARED_PROMPT_PATTERNS.md). Both MUST pass.
300303
- **Minutes 30–36**: Generate articles for core languages (EN, SV) using `npx tsx scripts/generate-news-enhanced.ts`
301304
- **Minutes 36–40**: 🚨 **Article Improvement Pass**: Read ALL articles back, replace AI_MUST_REPLACE markers, improve content. Run article quality component gate.

.github/workflows/news-month-ahead.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ safe-outputs:
120120
labels: [agentic-news, analysis-data]
121121
draft: false
122122
expires: 14d
123+
max: 2
123124
add-comment: {}
124125
dispatch-workflow:
125126
workflows: [news-translate]
@@ -274,7 +275,9 @@ read START_TIME < /tmp/start_time.txt
274275
- **Minutes 0–3**: Date check, MCP warm-up with `get_sync_status()`
275276
- **Minutes 3–5**: Run download-parliamentary-data pipeline (download data)
276277
- **Minutes 5–15**: 🚨 **AI Analysis Pass 1 (10 min minimum)**: Read ALL methodology guides, create analysis for EVERY document with Mermaid diagrams, evidence tables, SWOT entries.
277-
- **Minutes 15–22**: 🚨 **AI Analysis Pass 2 + Enrichment Verification (7 min minimum)**: Read ALL analysis back, improve every section, replace ALL script stubs with AI analysis, and complete enrichment verification before the shared minimum-time gate.
278+
- **Minutes 15–19**: 🚨 **AI Analysis Pass 2 (Part A)**: Read ALL analysis back, improve major sections, replace script stubs.
279+
- **Minutes 19–21**: 🫀 **Heartbeat PR**`git add && git commit` analysis artifacts so far, then `safeoutputs___create_pull_request` (title `🫀 Heartbeat - Month Ahead - {date}`). Refreshes the safeoutputs MCP session AND preserves work if later phases fail. Run `git checkout main` after the call so subsequent commits don't stack onto the frozen patch.
280+
- **Minutes 21–22**: 🚨 **AI Analysis Pass 2 (Part B) + Enrichment Verification**: Complete remaining improvements and run enrichment verification before the shared minimum-time gate.
278281
- **Minutes 22–23**: Run ENFORCED Minimum Time Gate (set `MINIMUM_ANALYSIS_MINUTES=14` for 30-min workflows) + final Enrichment Verification Gate (SHARED_PROMPT_PATTERNS.md). Both MUST pass.
279282
- **Minutes 23–28**: Generate articles for all 14 languages. Read articles back, replace AI_MUST_REPLACE markers. Run article quality gate.
280283
- **Minutes 28–29**: Validate and commit analysis + articles

0 commit comments

Comments
 (0)