Skip to content

feat(retro): post evidence comments on related issues#82

Closed
rh-hemartin wants to merge 1 commit into
mainfrom
feat/60-evidence-comments
Closed

feat(retro): post evidence comments on related issues#82
rh-hemartin wants to merge 1 commit into
mainfrom
feat/60-evidence-comments

Conversation

@rh-hemartin

Copy link
Copy Markdown
Member

Summary

  • When the retro agent finds evidence corroborating an existing open issue, the post-script now posts that evidence as a comment directly on the referenced issue
  • Adds optional evidence_comments array to the retro result schema (issue_url + body)
  • Updates the retro analysis skill to instruct the agent to populate evidence_comments instead of burying evidence in the summary field
  • Same 401/403 graceful degradation pattern as summary comment posting

Closes #60

Test plan

  • All 17 post-retro tests pass (6 new evidence-specific tests)
  • Full make test suite passes (all repo script tests)
  • Schema validates as correct JSON
  • After next 10 retro runs with evidence, referenced issues should have comments

🤖 Generated with Claude Code

@rh-hemartin rh-hemartin requested a review from a team as a code owner July 9, 2026 08:42
@rh-hemartin rh-hemartin self-assigned this Jul 9, 2026
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Retro: post corroborating evidence as comments on existing issues

✨ Enhancement 🧪 Tests 🕐 40+ Minutes

Grey Divider

AI Description

• Extend retro output schema with optional evidence_comments for existing-issue corroboration.
• Post each evidence comment to the referenced GitHub issue with 401/403 non-fatal handling.
• Update retro analysis instructions and add fixtures/tests covering success and failure modes.
Diagram

graph TD
  A["Retro analysis skill"] --> B[["agent-result.json"]] --> C["post-retro.sh"] --> D{{"GitHub API"}}
  C --> E["Comment: referenced issues"] --> D
  C --> F["Comment: originating PR"] --> D
  B --> G[["retro-result.schema.json"]]
  subgraph Legend
    direction LR
    _proc["Process/Script"] ~~~ _file[["JSON/Schema"]] ~~~ _ext{{"External"}}
  end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Keep evidence only in originating PR summary comment
  • ➕ No additional API calls or cross-repo permissions concerns
  • ➕ Simpler output schema (no new field)
  • ➖ Issue owners miss corroborating data unless they read originating PR
  • ➖ Evidence becomes fragmented and harder to track per issue over time
2. Aggregate all evidence into a single comment per target repo/issue
  • ➕ Reduces API calls when many evidence items exist
  • ➕ Easier to read as a single narrative update
  • ➖ Harder to attribute evidence to specific issue URLs if multiple issues referenced
  • ➖ More complex batching/formatting logic and test surface
3. Open a dedicated “Evidence” issue or discussion thread per area
  • ➕ Centralizes data points and reduces noise on individual issues
  • ➕ Can apply consistent templates/labels for evidence
  • ➖ Adds process overhead and another artifact to maintain
  • ➖ Less actionable for owners of the specific impacted issue

Recommendation: The chosen approach (direct comments on the referenced issues) is the most actionable and keeps evidence attached to the work item it corroborates. The added 401/403 graceful degradation matches existing behavior and is appropriate given cross-repo permission variability; consider future batching only if evidence volume becomes large.

Files changed (4) +162 / -5

Enhancement (1) +41 / -0
post-retro.shPost evidence comments to referenced issues with permission-aware handling +41/-0

Post evidence comments to referenced issues with permission-aware handling

• Adds a new step that reads '.evidence_comments' from the agent result and posts each comment to the referenced 'owner/repo#issue' via 'gh api'. Implements non-fatal warnings for HTTP 401/403 and fails the run on other errors, mirroring the existing graceful-degradation pattern.

scripts/post-retro.sh

Tests (1) +84 / -2
post-retro-test.shAdd fixtures and tests for evidence comment posting and failure modes +84/-2

Add fixtures and tests for evidence comment posting and failure modes

• Enhances the gh API mock to differentiate summary comment failures vs evidence comment failures via 'GH_MOCK_EVIDENCE_FAIL'. Adds fixtures including evidence comments and proposals+evidence, plus new tests covering happy path, absence of field, 401/403 non-fatal behavior, and 500 fatal behavior.

scripts/post-retro-test.sh

Documentation (1) +13 / -3
SKILL.mdInstruct agent to populate 'evidence_comments' for corroborating evidence +13/-3

Instruct agent to populate 'evidence_comments' for corroborating evidence

• Updates guidance to stop burying corroborating evidence solely in 'summary' and instead populate 'evidence_comments' entries with 'issue_url' and a markdown 'body' including an originating PR link. Updates the documented strict schema and example JSON accordingly.

skills/retro-analysis/SKILL.md

Other (1) +24 / -0
retro-result.schema.jsonAdd 'evidence_comments' to retro result schema +24/-0

Add 'evidence_comments' to retro result schema

• Extends the retro result schema with an optional 'evidence_comments' array (max 5). Introduces a strict 'evidence_comment' object definition requiring 'issue_url' (GitHub issue URL pattern) and 'body' (bounded markdown content).

schemas/retro-result.schema.json

@fullsend-ai-review

fullsend-ai-review Bot commented Jul 9, 2026

Copy link
Copy Markdown

🤖 Review · ⚠️ Cancelled · Started 8:43 AM UTC · Ended 8:46 AM UTC
Commit: e8381e3 · View workflow run →

@rh-hemartin rh-hemartin force-pushed the feat/60-evidence-comments branch from 431a8a4 to 7ef19ed Compare July 9, 2026 08:45
@fullsend-ai-review

fullsend-ai-review Bot commented Jul 9, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 8:47 AM UTC · Completed 8:56 AM UTC
Commit: 7ef19ed · View workflow run →

@qodo-code-review

qodo-code-review Bot commented Jul 9, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (0) 📎 Requirement gaps (0) 📜 Skill insights (1)

Context used
✅ Compliance rules (platform): 55 rules
✅ Skills: 4 invoked
  code-review
  code-implementation
  pr-review
  docs-review

Grey Divider


Action required

1. Unsanitized vars in ::warning:: ✓ Resolved 📜 Skill insight ⛨ Security
Description
The new evidence-comment failure path emits a GitHub Actions workflow command (::warning::...)
while interpolating EVIDENCE_REPO/EVIDENCE_NUMBER without sanitization, and SAFE_OUTPUT is
only partially sanitized. This can allow workflow-command injection or log manipulation if any
interpolated value contains ::, encoded newlines, ANSI escapes, or control characters.
Code

scripts/post-retro.sh[R147-153]

+        SAFE_OUTPUT="${EVIDENCE_OUTPUT//::/}"
+        SAFE_OUTPUT="${SAFE_OUTPUT//%0A/}"
+        SAFE_OUTPUT="${SAFE_OUTPUT//%0a/}"
+        SAFE_OUTPUT="${SAFE_OUTPUT//%0D/}"
+        SAFE_OUTPUT="${SAFE_OUTPUT//%0d/}"
+        echo "::warning::Could not post evidence comment on ${EVIDENCE_REPO}#${EVIDENCE_NUMBER}: insufficient permissions (${SAFE_OUTPUT}). Skipping."
+      else
Relevance

⭐⭐ Medium

Security tightening sometimes rejected (PR #78), but no precedent about sanitizing interpolated
::warning:: values.

PR-#78

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The checklist requires every interpolated value in a GHA workflow command to be sanitized
individually for ::, %0A/%0D, ANSI escapes, and control characters. The new `::warning::Could
not post evidence comment on ${EVIDENCE_REPO}#${EVIDENCE_NUMBER}...(${SAFE_OUTPUT})` line
interpolates repo/number without sanitization, and SAFE_OUTPUT is only stripped of :: and
%0A/%0D.

scripts/post-retro.sh[145-159]
Skill: pr-review

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A GitHub Actions workflow command (`::warning::...`) is emitted with interpolated variables that are not all individually sanitized (and sanitization is incomplete for ANSI/control chars).

## Issue Context
`scripts/post-retro.sh` posts evidence comments and, on 401/403, logs a `::warning::...` message that includes `EVIDENCE_REPO`, `EVIDENCE_NUMBER`, and `EVIDENCE_OUTPUT`-derived content.

## Fix Focus Areas
- scripts/post-retro.sh[145-160]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Retro output contract mismatch ✓ Resolved 📜 Skill insight ≡ Correctness
Description
The PR introduces evidence_comments as a new producer→consumer contract (schema + post-script) but
the retro agent definition still states the top-level output must have exactly two properties
(summary and proposals). This mismatch can prevent evidence_comments from being emitted at
runtime, so evidence comments may never be posted.
Code

schemas/retro-result.schema.json[R22-27]

+    "evidence_comments": {
+      "type": "array",
+      "maxItems": 5,
+      "items": { "$ref": "#/$defs/evidence_comment" },
+      "description": "Comments to post on existing open issues when this retro found corroborating evidence."
    }
Relevance

⭐⭐ Medium

No close precedent; team enforces strict structured outputs (PR #24) but this specific mismatch
lacks history.

PR-#24

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The consumer (post-retro.sh) now reads .evidence_comments, and the schema/skill describe it, but
the producer-facing agent definition still mandates exactly two top-level fields, creating an
inter-component contract inconsistency that can stop the mechanism from triggering in production.

schemas/retro-result.schema.json[6-28]
scripts/post-retro.sh[125-132]
skills/retro-analysis/SKILL.md[156-183]
agents/retro.md[74-90]
Skill: pr-review

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The retro output contract is inconsistent: the schema/skill/post-script support `evidence_comments`, but the retro agent definition still mandates only `summary` and `proposals` at the top level.

## Issue Context
`post-retro.sh` consumes `.evidence_comments`, and `retro-result.schema.json` defines it, but `agents/retro.md` still documents an older two-field-only output.

## Fix Focus Areas
- agents/retro.md[74-90]
- schemas/retro-result.schema.json[6-28]
- scripts/post-retro.sh[125-132]
- skills/retro-analysis/SKILL.md[156-183]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Bad issue_url repo parsing ✓ Resolved 🐞 Bug ≡ Correctness
Description
scripts/post-retro.sh derives EVIDENCE_REPO by stripping everything after the first “/issues/”
segment, which mis-parses valid URLs when the repository name is literally "issues" (e.g.,
https://github.com/acme/issues/issues/42). This builds an invalid gh api endpoint
(repos/acme/issues/42/comments) and will fail posting evidence comments for such repos.
Code

scripts/post-retro.sh[R133-135]

+    # Parse repo and number from issue URL.
+    EVIDENCE_REPO=$(echo "${ISSUE_URL}" | sed -E 's#https://github.com/##; s#/issues/.*##')
+    EVIDENCE_NUMBER=$(basename "${ISSUE_URL}")
Relevance

⭐⭐ Medium

No historical evidence about edge-case parsing of GitHub issue URLs in bash scripts.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The script’s sed truncation removes from the first /issues/ occurrence, which will be the repo
segment when the repo name is issues. The schema explicitly permits such a repo name, so this is a
valid input that will break endpoint construction.

scripts/post-retro.sh[125-143]
schemas/retro-result.schema.json[35-39]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`scripts/post-retro.sh` parses `issue_url` using `sed ... s#/issues/.*##`, which removes the first `/issues/` segment it encounters. If the repo name itself is `issues`, the resulting `EVIDENCE_REPO` becomes just the owner (missing repo), causing an incorrect `gh api` endpoint.

## Issue Context
- The schema allows repo names matching `[a-zA-Z0-9._-]+`, which includes the literal repo name `issues`.
- `issue_url` is meant to be exactly `https://github.com/<owner>/<repo>/issues/<number>`.

## Fix Focus Areas
- scripts/post-retro.sh[125-160]

### Suggested implementation direction
- Replace the `sed` + `basename` parsing with a single bash regex match, e.g.:
 - `[[ "$ISSUE_URL" =~ ^https://github\.com/([^/]+/[^/]+)/issues/([0-9]+)$ ]]`
 - `EVIDENCE_REPO="${BASH_REMATCH[1]}"`
 - `EVIDENCE_NUMBER="${BASH_REMATCH[2]}"`
- If the match fails, emit a clear error (or warning+skip) rather than constructing a malformed endpoint.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

4. No-evidence test doesn't assert 🐞 Bug ⚙ Maintainability
Description
The new "no-evidence-field" test claims to ensure no extra API calls occur when evidence_comments is
absent, but it only checks stdout for "Post-retro complete." and never inspects the gh call log.
This test can pass even if evidence-comment gh api calls are accidentally made.
Code

scripts/post-retro-test.sh[R325-328]

+# Evidence comments: no evidence_comments field — no extra API calls.
+run_test_stdout "no-evidence-field" \
+  "${FIXTURE_NO_PROPOSALS}" \
+  "Post-retro complete."
Relevance

⭐⭐ Medium

No historical evidence on asserting GH_LOG/no-extra-gh-calls; past script changes don’t show this
test rigor pattern.

PR-#12

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The test uses run_test_stdout for the no-evidence scenario, and run_test_stdout never inspects
${GH_LOG}, so it cannot validate “no extra API calls.”

scripts/post-retro-test.sh[325-329]
scripts/post-retro-test.sh[200-251]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The `no-evidence-field` test is intended to validate that no evidence-comment API calls are made, but it uses `run_test_stdout`, which does not check `${GH_LOG}` at all.

## Issue Context
- `run_test()` verifies `${GH_LOG}` patterns.
- `run_test_stdout()` only greps stdout, so it cannot validate side effects like extra `gh api .../comments` calls.

## Fix Focus Areas
- scripts/post-retro-test.sh[200-251]
- scripts/post-retro-test.sh[325-329]

### Suggested implementation direction
- Either:
 - Add a new helper that asserts `${GH_LOG}` does *not* contain a substring (e.g., `target-repo/issues/42/comments`), or
 - Extend `run_test_stdout` to accept an optional `forbidden_pattern` (or expected call count) and assert against `${GH_LOG}`.
- Update `no-evidence-field` to assert the gh log contains only the originating summary comment call and no other `/comments` endpoints.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. Protected paths modified 📜 Skill insight § Compliance
Description
This PR modifies protected governance/infrastructure paths (scripts/ and skills/), which require
explicit human review and must not be auto-approved. Even with an issue link, this should be
surfaced as a protected-path change needing manual approval.
Code

scripts/post-retro.sh[R125-165]

+# Post evidence comments on referenced issues.
+EVIDENCE_COUNT=$(jq '.evidence_comments // [] | length' "${RESULT_FILE}")
+if [[ "${EVIDENCE_COUNT}" -gt 0 ]]; then
+  echo "Posting ${EVIDENCE_COUNT} evidence comment(s)"
+  for i in $(seq 0 $((EVIDENCE_COUNT - 1))); do
+    ISSUE_URL=$(jq -r ".evidence_comments[$i].issue_url" "${RESULT_FILE}")
+    EVIDENCE_BODY=$(jq -r ".evidence_comments[$i].body" "${RESULT_FILE}")
+
+    # Parse repo and number from issue URL.
+    EVIDENCE_REPO=$(echo "${ISSUE_URL}" | sed -E 's#https://github.com/##; s#/issues/.*##')
+    EVIDENCE_NUMBER=$(basename "${ISSUE_URL}")
+
+    SAFE_URL="${ISSUE_URL//::/}"
+    echo "  Commenting on ${EVIDENCE_REPO}#${EVIDENCE_NUMBER}"
+    EVIDENCE_OUTPUT=""
+    EVIDENCE_EXIT=0
+    EVIDENCE_OUTPUT=$(jq -nc --arg body "${EVIDENCE_BODY}" '{body: $body}' | gh api \
+      "repos/${EVIDENCE_REPO}/issues/${EVIDENCE_NUMBER}/comments" \
+      --input - 2>&1) || EVIDENCE_EXIT=$?
+
+    if [[ ${EVIDENCE_EXIT} -ne 0 ]]; then
+      if echo "${EVIDENCE_OUTPUT}" | grep -qE "HTTP (401|403)"; then
+        SAFE_OUTPUT="${EVIDENCE_OUTPUT//::/}"
+        SAFE_OUTPUT="${SAFE_OUTPUT//%0A/}"
+        SAFE_OUTPUT="${SAFE_OUTPUT//%0a/}"
+        SAFE_OUTPUT="${SAFE_OUTPUT//%0D/}"
+        SAFE_OUTPUT="${SAFE_OUTPUT//%0d/}"
+        echo "::warning::Could not post evidence comment on ${EVIDENCE_REPO}#${EVIDENCE_NUMBER}: insufficient permissions (${SAFE_OUTPUT}). Skipping."
+      else
+        SAFE_OUTPUT="${EVIDENCE_OUTPUT//::/}"
+        SAFE_OUTPUT="${SAFE_OUTPUT//%0A/}"
+        SAFE_OUTPUT="${SAFE_OUTPUT//%0a/}"
+        SAFE_OUTPUT="${SAFE_OUTPUT//%0D/}"
+        SAFE_OUTPUT="${SAFE_OUTPUT//%0d/}"
+        echo "ERROR: failed to post evidence comment on ${EVIDENCE_REPO}#${EVIDENCE_NUMBER}: ${SAFE_OUTPUT}"
+        exit 1
+      fi
+    fi
+  done
+fi
+
Relevance

⭐⭐ Medium

Protected-path concern raised before on skills/ edits (PR #59) but acceptance status was
undetermined.

PR-#59

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The checklist requires raising a finding whenever protected paths are modified; this PR changes both
scripts/post-retro.sh and skills/retro-analysis/SKILL.md, which are listed protected
directories.

scripts/post-retro.sh[125-165]
skills/retro-analysis/SKILL.md[121-183]
Skill: pr-review

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Protected governance/infrastructure paths were modified and must be explicitly flagged for human review.

## Issue Context
This PR changes automation scripts and agent skill instructions.

## Fix Focus Areas
- scripts/post-retro.sh[125-165]
- skills/retro-analysis/SKILL.md[121-183]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Informational

6. Unused SAFE_URL variable ✓ Resolved 🐞 Bug ⚙ Maintainability
Description
SAFE_URL is assigned in the evidence comment posting loop but never referenced, leaving dead code.
This can mislead readers into thinking URL sanitization is applied in logs.
Code

scripts/post-retro.sh[R137-138]

+    SAFE_URL="${ISSUE_URL//::/}"
+    echo "  Commenting on ${EVIDENCE_REPO}#${EVIDENCE_NUMBER}"
Relevance

⭐⭐ Medium

No historical evidence of enforcing removal of unused bash variables in this repo.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
SAFE_URL is assigned but not referenced anywhere later in the evidence-comment block.

scripts/post-retro.sh[133-139]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`SAFE_URL` is computed during evidence comment posting but never used.

## Issue Context
This appears to be leftover from the summary-comment sanitization pattern.

## Fix Focus Areas
- scripts/post-retro.sh[133-139]

### Suggested implementation direction
- Remove the `SAFE_URL=...` line, or use it in a log line if intended (and ensure sanitization is complete/consistent).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

Comment thread scripts/post-retro.sh
Comment thread schemas/retro-result.schema.json
Comment thread scripts/post-retro.sh
Comment on lines +125 to +165
# Post evidence comments on referenced issues.
EVIDENCE_COUNT=$(jq '.evidence_comments // [] | length' "${RESULT_FILE}")
if [[ "${EVIDENCE_COUNT}" -gt 0 ]]; then
echo "Posting ${EVIDENCE_COUNT} evidence comment(s)"
for i in $(seq 0 $((EVIDENCE_COUNT - 1))); do
ISSUE_URL=$(jq -r ".evidence_comments[$i].issue_url" "${RESULT_FILE}")
EVIDENCE_BODY=$(jq -r ".evidence_comments[$i].body" "${RESULT_FILE}")

# Parse repo and number from issue URL.
EVIDENCE_REPO=$(echo "${ISSUE_URL}" | sed -E 's#https://github.com/##; s#/issues/.*##')
EVIDENCE_NUMBER=$(basename "${ISSUE_URL}")

SAFE_URL="${ISSUE_URL//::/}"
echo " Commenting on ${EVIDENCE_REPO}#${EVIDENCE_NUMBER}"
EVIDENCE_OUTPUT=""
EVIDENCE_EXIT=0
EVIDENCE_OUTPUT=$(jq -nc --arg body "${EVIDENCE_BODY}" '{body: $body}' | gh api \
"repos/${EVIDENCE_REPO}/issues/${EVIDENCE_NUMBER}/comments" \
--input - 2>&1) || EVIDENCE_EXIT=$?

if [[ ${EVIDENCE_EXIT} -ne 0 ]]; then
if echo "${EVIDENCE_OUTPUT}" | grep -qE "HTTP (401|403)"; then
SAFE_OUTPUT="${EVIDENCE_OUTPUT//::/}"
SAFE_OUTPUT="${SAFE_OUTPUT//%0A/}"
SAFE_OUTPUT="${SAFE_OUTPUT//%0a/}"
SAFE_OUTPUT="${SAFE_OUTPUT//%0D/}"
SAFE_OUTPUT="${SAFE_OUTPUT//%0d/}"
echo "::warning::Could not post evidence comment on ${EVIDENCE_REPO}#${EVIDENCE_NUMBER}: insufficient permissions (${SAFE_OUTPUT}). Skipping."
else
SAFE_OUTPUT="${EVIDENCE_OUTPUT//::/}"
SAFE_OUTPUT="${SAFE_OUTPUT//%0A/}"
SAFE_OUTPUT="${SAFE_OUTPUT//%0a/}"
SAFE_OUTPUT="${SAFE_OUTPUT//%0D/}"
SAFE_OUTPUT="${SAFE_OUTPUT//%0d/}"
echo "ERROR: failed to post evidence comment on ${EVIDENCE_REPO}#${EVIDENCE_NUMBER}: ${SAFE_OUTPUT}"
exit 1
fi
fi
done
fi

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

3. Protected paths modified 📜 Skill insight § Compliance

This PR modifies protected governance/infrastructure paths (scripts/ and skills/), which require
explicit human review and must not be auto-approved. Even with an issue link, this should be
surfaced as a protected-path change needing manual approval.
Agent Prompt
## Issue description
Protected governance/infrastructure paths were modified and must be explicitly flagged for human review.

## Issue Context
This PR changes automation scripts and agent skill instructions.

## Fix Focus Areas
- scripts/post-retro.sh[125-165]
- skills/retro-analysis/SKILL.md[121-183]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment thread scripts/post-retro.sh Outdated
Comment on lines +325 to +328
# Evidence comments: no evidence_comments field — no extra API calls.
run_test_stdout "no-evidence-field" \
"${FIXTURE_NO_PROPOSALS}" \
"Post-retro complete."

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

5. No-evidence test doesn't assert 🐞 Bug ⚙ Maintainability

The new "no-evidence-field" test claims to ensure no extra API calls occur when evidence_comments is
absent, but it only checks stdout for "Post-retro complete." and never inspects the gh call log.
This test can pass even if evidence-comment gh api calls are accidentally made.
Agent Prompt
## Issue description
The `no-evidence-field` test is intended to validate that no evidence-comment API calls are made, but it uses `run_test_stdout`, which does not check `${GH_LOG}` at all.

## Issue Context
- `run_test()` verifies `${GH_LOG}` patterns.
- `run_test_stdout()` only greps stdout, so it cannot validate side effects like extra `gh api .../comments` calls.

## Fix Focus Areas
- scripts/post-retro-test.sh[200-251]
- scripts/post-retro-test.sh[325-329]

### Suggested implementation direction
- Either:
  - Add a new helper that asserts `${GH_LOG}` does *not* contain a substring (e.g., `target-repo/issues/42/comments`), or
  - Extend `run_test_stdout` to accept an optional `forbidden_pattern` (or expected call count) and assert against `${GH_LOG}`.
- Update `no-evidence-field` to assert the gh log contains only the originating summary comment call and no other `/comments` endpoints.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment thread scripts/post-retro.sh Outdated
@fullsend-ai-review

fullsend-ai-review Bot commented Jul 9, 2026

Copy link
Copy Markdown

Review

Verdict: Approve

All five findings from the prior review have been addressed:

  • agents/retro.md updated to document evidence_comments as an optional third property
  • ✅ Pre-validation loop added for issue_url runtime validation (defense-in-depth)
  • ✅ Test mock now captures request bodies via ${GH_LOG}.body
  • ✅ Multi-evidence fixture with 2 entries and corresponding tests added
  • ✅ Pre-validation pass validates all evidence entries before posting any

What looks good

  • Schema designevidence_comments is optional, backward-compatible, and properly typed with additionalProperties: false
  • Defense in depth — Pre-validation loop mirrors the proposal validation pattern, catching malformed URLs before any API calls
  • Error handling — 401/403 graceful degradation follows the established pattern from summary comment posting
  • Sanitization — All variables interpolated into GHA workflow commands are properly sanitized for :: sequences and URL-encoded newlines; regex-validated EVIDENCE_REPO and EVIDENCE_NUMBER cannot contain injection characters
  • Test coverage — 8 new test cases cover the key paths: happy path, body verification, no-evidence, with-proposals, 401/403 non-fatal, 500 fatal, multiple entries
  • Documentation consistency — Both agents/retro.md and skills/retro-analysis/SKILL.md are updated consistently with the schema changes

Minor observations

1. Evidence ordering relative to summary comment (low)

Evidence comments are posted before the summary comment (between proposal filing and summary posting). A non-permission fatal error (e.g., HTTP 404 if a referenced issue was deleted between analysis and posting) would prevent the summary from being posted. This follows the same pattern as proposal filing (which also can block the summary), but evidence targets external repos the script doesn't own, making unexpected responses slightly more likely. Consider moving evidence posting after the summary comment, or making all evidence errors non-fatal since evidence comments are supplementary data points.

2. No test for pre-validation rejection (low)

The pre-validation loop correctly rejects malformed issue_url values (e.g., /pull/ URLs, non-GitHub URLs) with a clear error message, but no test exercises this rejection path. A fixture with a bad URL asserting exit 1 would verify the guard works and protect against regressions.


Protected paths detected — this PR modifies files under one or more
protected paths. The review agent cannot approve PRs that touch these paths.
A human reviewer must approve this PR.

Protected files in this PR:

  • agents/retro.md
  • scripts/post-retro-test.sh
  • scripts/post-retro.sh
  • skills/retro-analysis/SKILL.md
Previous run

Review

Verdict: Request changes

Clean implementation that follows established patterns well — the error handling, test structure, and schema design are all consistent with the existing codebase. Two issues need attention before merge.

Findings

1. agents/retro.md not updated — feature is dead infrastructure (high)

agents/retro.md line 78 explicitly instructs the retro agent:

The top-level object must have exactly two properties — no others

Line 87 reinforces: "The schema enforces additionalProperties: false. Any extra top-level key ... will fail validation."

While the retro-analysis SKILL.md is updated in this PR to mention evidence_comments, the agent definition — which is the retro agent's primary instruction file — still forbids any top-level key beyond summary and proposals. The agent will follow the more restrictive instruction and never produce evidence_comments. This makes the schema change, post-script logic, and all 6 new tests dead infrastructure.

File: agents/retro.md, line 78
Remediation: Update lines 78–89 to list evidence_comments as an optional third property. Change "exactly two properties" to reflect that the schema now allows three (with evidence_comments being optional). Update the example JSON and the sentence about additionalProperties to list all three allowed keys.

2. Missing runtime validation of issue_url — defense-in-depth gap (medium)

The existing code validates ORIGINATING_URL at line 43 with a bash regex before parsing it with sed/basename and interpolating derived values into ::warning:: GHA workflow commands. The new evidence loop does not apply equivalent runtime validation to issue_url before parsing it into EVIDENCE_REPO and EVIDENCE_NUMBER.

Both EVIDENCE_REPO and EVIDENCE_NUMBER are interpolated unsanitized into:

  • echo "::warning::Could not post evidence comment on ${EVIDENCE_REPO}#${EVIDENCE_NUMBER}..." (GHA workflow command)
  • echo " Commenting on ${EVIDENCE_REPO}#${EVIDENCE_NUMBER}" (stdout, which GHA also interprets for :: commands)
  • gh api "repos/${EVIDENCE_REPO}/issues/${EVIDENCE_NUMBER}/comments" (API path)

The schema regex provides upstream validation, but the post-script defensively validates ORIGINATING_URL despite the same upstream constraints. The evidence loop should follow the same defense-in-depth pattern.

File: scripts/post-retro.sh (new evidence loop)
Remediation: Add a runtime validation check inside the loop, mirroring line 43:

if [[ ! "${ISSUE_URL}" =~ ^https://github\.com/[a-zA-Z0-9._-]+/[a-zA-Z0-9._-]+/issues/[0-9]+$ ]]; then
  echo "ERROR: evidence_comments[$i].issue_url does not match expected pattern" >&2
  exit 1
fi

3. Tests don't verify posted comment body (low)

The evidence-comment-posted test verifies the correct API endpoint appears in the gh call log, but the mock does not capture stdin. A bug in the jq expression constructing the payload (e.g., wrong field path) would produce a null/empty body and the test would still pass.

File: scripts/post-retro-test.sh
Remediation: Extend the mock to capture the request body (e.g., tee stdin to a file) and assert the posted body matches the fixture.

4. No test for multiple evidence comments (low)

All evidence fixtures contain exactly one evidence_comment entry, but the schema allows up to 5. There's no test verifying correct iteration over multiple entries or mixed success/failure across comments.

File: scripts/post-retro-test.sh
Remediation: Add a fixture with 2+ evidence comments and verify all are posted.

5. No pre-validation loop for evidence comments (low)

Proposals are validated in a dedicated loop (lines 57–72) before any are filed, preventing partial state from a malformed entry. The evidence loop has no equivalent — a failure mid-loop leaves earlier comments already posted with no summary comment.

File: scripts/post-retro.sh
Remediation: Add a pre-validation pass for evidence entries before posting any, or make all evidence errors non-fatal (like the 401/403 pattern) since evidence comments are supplementary.

What looks good

  • Schema design: evidence_comments is optional (not in required), backward compatible, and properly typed with additionalProperties: false
  • Error handling mirrors the established 401/403 graceful degradation pattern from the summary comment posting
  • Output sanitization correctly strips ::, %0A, %0D from SAFE_OUTPUT before GHA command interpolation
  • The jq '.evidence_comments // []' pattern safely handles missing field
  • Test coverage for the core scenarios (happy path, 401/403 non-fatal, 500 fatal, proposals+evidence together) is solid
  • SKILL.md updates are clear and well-structured

fullsend-ai-review[bot]

This comment was marked as outdated.

When the retro agent finds evidence corroborating an existing open issue,
the post-script now posts that evidence as a comment directly on the
referenced issue instead of burying it in the originating PR's summary.

Closes #60

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Hector Martinez <hemartin@redhat.com>
@rh-hemartin rh-hemartin force-pushed the feat/60-evidence-comments branch from 7ef19ed to 7a03769 Compare July 9, 2026 11:54
@fullsend-ai-review

fullsend-ai-review Bot commented Jul 9, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 11:57 AM UTC · Completed 12:28 PM UTC
Commit: 7a03769 · View workflow run →

@fullsend-ai-review fullsend-ai-review Bot dismissed their stale review July 9, 2026 12:28

Superseded by updated review

@fullsend-ai-review fullsend-ai-review Bot added the requires-manual-review Review requires human judgment label Jul 9, 2026

@ralphbean ralphbean left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Previous review findings all addressed in the latest push.

@rh-hemartin

Copy link
Copy Markdown
Member Author

Closing as discussed in our meeting. We will prevent retro from filing evidence directly in the post-retro.sh code

@rh-hemartin rh-hemartin closed this Jul 9, 2026
@rh-hemartin rh-hemartin deleted the feat/60-evidence-comments branch July 9, 2026 13:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

requires-manual-review Review requires human judgment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(retro): post evidence comments on related issues

2 participants