@plainconceptsplatform/workflows 1.14.0 → 1.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/dist/workflow-catalog.d.ts +1 -1
  2. package/dist/workflow-catalog.js +0 -2
  3. package/loops/actions/add-issue-labels/action.yml +50 -50
  4. package/loops/actions/agent-output.cjs +17 -17
  5. package/loops/actions/apply-agent-bundle/action.yml +24 -24
  6. package/loops/actions/apply-agent-comments/action.yml +42 -42
  7. package/loops/actions/apply-agent-labels/action.yml +55 -55
  8. package/loops/actions/cleanup-artifacts/action.yml +91 -91
  9. package/loops/actions/close-agent-issues/action.yml +43 -43
  10. package/loops/actions/create-issue-comment/action.yml +29 -29
  11. package/loops/actions/download-agent-output/action.yml +53 -53
  12. package/loops/actions/link-pr-to-issue/action.yml +40 -40
  13. package/loops/actions/list-open-issues/action.yml +33 -33
  14. package/loops/actions/load-issue-context/action.yml +45 -45
  15. package/loops/actions/merge-agent-pr/action.yml +49 -49
  16. package/loops/actions/remove-issue-labels/action.yml +37 -37
  17. package/loops/actions/update-agent-issues/action.yml +58 -58
  18. package/loops/actions/validate-refine-output/validate-refine-output.sh +28 -4
  19. package/loops/actions/validate-review-output/action.yml +35 -35
  20. package/loops/actions/validate-review-output/validate-review-output.sh +4 -1
  21. package/loops/actions/validate-triage-output/action.yml +36 -36
  22. package/loops/actions/validate-triage-output/validate-triage-output.sh +5 -2
  23. package/loops/actions/verify-composite-actions/action.yml +9 -9
  24. package/loops/actions/verify-refine-output/action.yml +9 -9
  25. package/loops/actions/verify-refine-output/verify-refine-output.sh +14 -0
  26. package/loops/actions/verify-route-matrix/action.yml +9 -9
  27. package/loops/actions/verify-route-matrix/verify-route-matrix.sh +32 -46
  28. package/loops/templates/agentics/agentics-maintenance.yml +121 -121
  29. package/loops/templates/issues/bug_report.yml +109 -109
  30. package/loops/templates/issues/feature_request.yml +75 -75
  31. package/loops/workflows/agent-refine.md +43 -119
  32. package/loops/workflows/shared/platform-defaults.md +53 -53
  33. package/package.json +1 -1
  34. package/loops/actions/report-workflow-errors/action.yml +0 -538
  35. package/loops/actions/report-workflow-errors/report-policy.cjs +0 -194
  36. package/loops/templates/agentics/agentics-error-report.yml +0 -101
@@ -1,37 +1,37 @@
1
- # Managed by @plainconceptsplatform/workflows. Source: loops/actions/remove-issue-labels/action.yml. Update with workflows update --force; consumer edits may be overwritten.
2
- name: Remove issue labels
3
- description: Remove one or more labels from an issue or pull request.
4
- inputs:
5
- token:
6
- description: GitHub token used by github-script.
7
- required: true
8
- issue-number:
9
- description: Issue or pull request number.
10
- required: true
11
- labels:
12
- description: Labels to remove, one per line. A comma-separated list is accepted as well.
13
- required: true
14
- runs:
15
- using: composite
16
- steps:
17
- - name: Remove labels
18
- uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
19
- env:
20
- ISSUE_NUMBER: ${{ inputs.issue-number }}
21
- LABELS: ${{ inputs.labels }}
22
- with:
23
- github-token: ${{ inputs.token }}
24
- script: |
25
- // Callers wrote `labels: a,b` while this split on newlines, so one label named "a,b"
26
- // was removed: a 404, swallowed below, and neither label ever came off.
27
- for (const label of process.env.LABELS.split(/\r?\n|,/).map((label) => label.trim()).filter(Boolean)) {
28
- try {
29
- await github.rest.issues.removeLabel({
30
- ...context.repo,
31
- issue_number: Number(process.env.ISSUE_NUMBER),
32
- name: label,
33
- });
34
- } catch (error) {
35
- if (error.status !== 404) throw error;
36
- }
37
- }
1
+ # Managed by @plainconceptsplatform/workflows. Source: loops/actions/remove-issue-labels/action.yml. Update with workflows update --force; consumer edits may be overwritten.
2
+ name: Remove issue labels
3
+ description: Remove one or more labels from an issue or pull request.
4
+ inputs:
5
+ token:
6
+ description: GitHub token used by github-script.
7
+ required: true
8
+ issue-number:
9
+ description: Issue or pull request number.
10
+ required: true
11
+ labels:
12
+ description: Labels to remove, one per line. A comma-separated list is accepted as well.
13
+ required: true
14
+ runs:
15
+ using: composite
16
+ steps:
17
+ - name: Remove labels
18
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
19
+ env:
20
+ ISSUE_NUMBER: ${{ inputs.issue-number }}
21
+ LABELS: ${{ inputs.labels }}
22
+ with:
23
+ github-token: ${{ inputs.token }}
24
+ script: |
25
+ // Callers wrote `labels: a,b` while this split on newlines, so one label named "a,b"
26
+ // was removed: a 404, swallowed below, and neither label ever came off.
27
+ for (const label of process.env.LABELS.split(/\r?\n|,/).map((label) => label.trim()).filter(Boolean)) {
28
+ try {
29
+ await github.rest.issues.removeLabel({
30
+ ...context.repo,
31
+ issue_number: Number(process.env.ISSUE_NUMBER),
32
+ name: label,
33
+ });
34
+ } catch (error) {
35
+ if (error.status !== 404) throw error;
36
+ }
37
+ }
@@ -1,58 +1,58 @@
1
- # Managed by @plainconceptsplatform/workflows. Source: loops/actions/update-agent-issues/action.yml. Update with workflows update --force; consumer edits may be overwritten.
2
- name: Update agent issues
3
- description: Apply every update_issue item from agent_output.json.
4
- inputs:
5
- output-file:
6
- description: Path to agent_output.json.
7
- required: true
8
- token:
9
- description: GitHub token with issues:write.
10
- required: true
11
- fallback-issue-number:
12
- description: Issue an item targets when it names none.
13
- required: false
14
- default: ''
15
- runs:
16
- using: composite
17
- steps:
18
- - name: Update issues
19
- uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
20
- env:
21
- AGENT_OUTPUT_LIB: ${{ github.action_path }}/../agent-output.cjs
22
- OUTPUT_FILE: ${{ inputs.output-file }}
23
- FALLBACK_ISSUE_NUMBER: ${{ inputs.fallback-issue-number }}
24
- with:
25
- github-token: ${{ inputs.token }}
26
- script: |
27
- const { readAgentItems } = require(process.env.AGENT_OUTPUT_LIB);
28
- const items = readAgentItems(process.env.OUTPUT_FILE, 'update_issue');
29
-
30
- let updated = 0;
31
-
32
- for (const item of items) {
33
- const target = item.item_number ?? process.env.FALLBACK_ISSUE_NUMBER;
34
-
35
- if (!target) {
36
- core.warning(`update_issue item has no item_number and no fallback, skipping: ${JSON.stringify(item)}`);
37
- continue;
38
- }
39
-
40
- const changes = {};
41
- if (item.title) changes.title = item.title;
42
- if (item.body) changes.body = item.body;
43
-
44
- if (Object.keys(changes).length === 0) {
45
- core.warning(`update_issue item changes nothing, skipping: ${JSON.stringify(item)}`);
46
- continue;
47
- }
48
-
49
- await github.rest.issues.update({
50
- ...context.repo,
51
- issue_number: Number(target),
52
- ...changes,
53
- });
54
-
55
- updated += 1;
56
- }
57
-
58
- core.info(`Updated ${updated} issue(s).`);
1
+ # Managed by @plainconceptsplatform/workflows. Source: loops/actions/update-agent-issues/action.yml. Update with workflows update --force; consumer edits may be overwritten.
2
+ name: Update agent issues
3
+ description: Apply every update_issue item from agent_output.json.
4
+ inputs:
5
+ output-file:
6
+ description: Path to agent_output.json.
7
+ required: true
8
+ token:
9
+ description: GitHub token with issues:write.
10
+ required: true
11
+ fallback-issue-number:
12
+ description: Issue an item targets when it names none.
13
+ required: false
14
+ default: ''
15
+ runs:
16
+ using: composite
17
+ steps:
18
+ - name: Update issues
19
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
20
+ env:
21
+ AGENT_OUTPUT_LIB: ${{ github.action_path }}/../agent-output.cjs
22
+ OUTPUT_FILE: ${{ inputs.output-file }}
23
+ FALLBACK_ISSUE_NUMBER: ${{ inputs.fallback-issue-number }}
24
+ with:
25
+ github-token: ${{ inputs.token }}
26
+ script: |
27
+ const { readAgentItems } = require(process.env.AGENT_OUTPUT_LIB);
28
+ const items = readAgentItems(process.env.OUTPUT_FILE, 'update_issue');
29
+
30
+ let updated = 0;
31
+
32
+ for (const item of items) {
33
+ const target = item.item_number ?? process.env.FALLBACK_ISSUE_NUMBER;
34
+
35
+ if (!target) {
36
+ core.warning(`update_issue item has no item_number and no fallback, skipping: ${JSON.stringify(item)}`);
37
+ continue;
38
+ }
39
+
40
+ const changes = {};
41
+ if (item.title) changes.title = item.title;
42
+ if (item.body) changes.body = item.body;
43
+
44
+ if (Object.keys(changes).length === 0) {
45
+ core.warning(`update_issue item changes nothing, skipping: ${JSON.stringify(item)}`);
46
+ continue;
47
+ }
48
+
49
+ await github.rest.issues.update({
50
+ ...context.repo,
51
+ issue_number: Number(target),
52
+ ...changes,
53
+ });
54
+
55
+ updated += 1;
56
+ }
57
+
58
+ core.info(`Updated ${updated} issue(s).`);
@@ -29,19 +29,31 @@ jq -r --arg marker "$marker" --arg prefix "$comment_prefix" --arg issue "$issue_
29
29
  any(.items[]; .type == "update_issue");
30
30
 
31
31
  # A temporal draft is a replacement body the worker still expects to grow: the draft
32
- # marker distinguishes it from a finished body.
32
+ # marker distinguishes it from a finished body. The gh-aw process_safe_outputs strips
33
+ # HTML comments from the body, so the draft marker (<!-- agent-refine-draft -->) can
34
+ # be gone by the time the validator reads it (Bots #1336, run 42214146974). When the
35
+ # draft marker is absent but the pending mark (_pending see questions below_) is
36
+ # present, the body is still a draft: the pending mark only appears in drafts, and a
37
+ # finished body has none.
33
38
  def has_draft_body:
34
39
  any(.items[]; .type == "update_issue" and
35
40
  (.item_number == null or (.item_number | tostring) == $issue) and
36
41
  (.body | type == "string") and
37
- (.body | contains($draft_marker)));
42
+ ((.body | contains($draft_marker)) or (.body | contains($pending_mark))));
38
43
 
39
44
  # The batched questions, by the sentence that opens them. It decides the outcome on its own:
40
45
  # Bots #561, #871 and Numa #821 asked, left a draft without the draft marker, were read as
41
46
  # complete, and implement started two seconds later on a story nobody had answered.
47
+ # The prompt asks the model to open with the exact questions_line, but models paraphrase
48
+ # it: GLM-5-2 wrote "I have some questions that the code cannot settle on its own" and the
49
+ # exact-line match failed, dropping a valid questions outcome (Bots #1336). Match the exact
50
+ # line, or its opening "I have some questions" prefix, which is specific enough in a refine
51
+ # comment to never match the complete or split messages.
42
52
  def asks_questions:
43
53
  any(.items[]; .type == "add_comment" and (.item_number | tostring) == $issue and
44
- (.body | type == "string") and (.body | contains($questions_line)));
54
+ (.body | type == "string") and
55
+ ((.body | contains($questions_line)) or
56
+ (.body | test("I have some questions"; "i"))));
45
57
 
46
58
  def has_pending_marks:
47
59
  any(.items[]; .type == "update_issue" and
@@ -109,6 +121,18 @@ jq -r --arg marker "$marker" --arg prefix "$comment_prefix" --arg issue "$issue_
109
121
  (.body | split($marker) | join("") | split($prefix) | join("") |
110
122
  gsub("<[^>]*>"; "") | test("[[:alnum:]]")));
111
123
 
124
+ # A completion announcement. Branch 5 (has_clarification -> questions) treats any comment
125
+ # with content as a question the agent asked, but a "Refinement complete" comment is not a
126
+ # question: paired with a draft body (which is how branch 5 is reached, via has_draft_body)
127
+ # it is a self-contradiction -- the agent said complete over a body still pending -- and the
128
+ # right outcome is invalid, not questions. Seen as a regression after has_draft_body started
129
+ # matching the pending mark when the HTML draft marker was stripped (1.15.0): the test "a body
130
+ # still pending with no questions asked is not complete" flipped from invalid to questions.
131
+ def has_completion_comment:
132
+ any(.items[]; .type == "add_comment" and (.item_number | tostring) == $issue and
133
+ (.body | type == "string") and
134
+ (.body | test("Refinement complete"; "i")));
135
+
112
136
  # Order matters: a run that wrote children is a split even though it also replaced the
113
137
  # parent body, and a lone child with no parent update is an incomplete split, not a
114
138
  # complete refinement. A body carrying the draft marker is a temporal draft, not a
@@ -128,7 +152,7 @@ jq -r --arg marker "$marker" --arg prefix "$comment_prefix" --arg issue "$issue_
128
152
  and (reported_incomplete | not) then "questions"
129
153
  elif has_replacement_body and (has_draft_body | not) and (has_pending_marks | not) and has_only_source_items then "complete"
130
154
  elif has_clarification and ((has_update | not) or has_draft_body) and has_only_source_items
131
- and (reported_incomplete | not) then "questions"
155
+ and (reported_incomplete | not) and (has_completion_comment | not) then "questions"
132
156
  else "invalid"
133
157
  end
134
158
  ' "$output_file"
@@ -1,35 +1,35 @@
1
- # Managed by @plainconceptsplatform/workflows. Source: loops/actions/validate-review-output/action.yml. Update with workflows update --force; consumer edits may be overwritten.
2
- name: Validate review output
3
- description: Verify an apply-review outcome accounts for every unresolved review thread.
4
- inputs:
5
- output-file:
6
- description: Path to agent_output.json.
7
- required: true
8
- pr-number:
9
- description: Pull request receiving the review feedback.
10
- required: true
11
- review-threads-file:
12
- description: JSON file containing unresolved review threads.
13
- required: true
14
- outputs:
15
- valid:
16
- description: Whether the agent output is a valid review outcome.
17
- value: ${{ steps.validate.outputs.valid }}
18
- outcome:
19
- description: "Deterministic review outcome: implemented, already-satisfied, needs-human, or invalid."
20
- value: ${{ steps.validate.outputs.outcome }}
21
- runs:
22
- using: composite
23
- steps:
24
- - name: Validate review outcome
25
- id: validate
26
- shell: bash
27
- env:
28
- OUTPUT_FILE: ${{ inputs.output-file }}
29
- PR_NUMBER: ${{ inputs.pr-number }}
30
- REVIEW_THREADS_FILE: ${{ inputs.review-threads-file }}
31
- run: |
32
- set -euo pipefail
33
- outcome="$(bash "${{ github.action_path }}/validate-review-output.sh" "$OUTPUT_FILE" "$PR_NUMBER" "$REVIEW_THREADS_FILE")"
34
- echo "outcome=$outcome" >> "$GITHUB_OUTPUT"
35
- echo "valid=$([ "$outcome" != 'invalid' ] && echo true || echo false)" >> "$GITHUB_OUTPUT"
1
+ # Managed by @plainconceptsplatform/workflows. Source: loops/actions/validate-review-output/action.yml. Update with workflows update --force; consumer edits may be overwritten.
2
+ name: Validate review output
3
+ description: Verify an apply-review outcome accounts for every unresolved review thread.
4
+ inputs:
5
+ output-file:
6
+ description: Path to agent_output.json.
7
+ required: true
8
+ pr-number:
9
+ description: Pull request receiving the review feedback.
10
+ required: true
11
+ review-threads-file:
12
+ description: JSON file containing unresolved review threads.
13
+ required: true
14
+ outputs:
15
+ valid:
16
+ description: Whether the agent output is a valid review outcome.
17
+ value: ${{ steps.validate.outputs.valid }}
18
+ outcome:
19
+ description: "Deterministic review outcome: implemented, already-satisfied, needs-human, or invalid."
20
+ value: ${{ steps.validate.outputs.outcome }}
21
+ runs:
22
+ using: composite
23
+ steps:
24
+ - name: Validate review outcome
25
+ id: validate
26
+ shell: bash
27
+ env:
28
+ OUTPUT_FILE: ${{ inputs.output-file }}
29
+ PR_NUMBER: ${{ inputs.pr-number }}
30
+ REVIEW_THREADS_FILE: ${{ inputs.review-threads-file }}
31
+ run: |
32
+ set -euo pipefail
33
+ outcome="$(bash "${{ github.action_path }}/validate-review-output.sh" "$OUTPUT_FILE" "$PR_NUMBER" "$REVIEW_THREADS_FILE")"
34
+ echo "outcome=$outcome" >> "$GITHUB_OUTPUT"
35
+ echo "valid=$([ "$outcome" != 'invalid' ] && echo true || echo false)" >> "$GITHUB_OUTPUT"
@@ -24,7 +24,10 @@ jq -r --arg pr "$pr_number" --slurpfile threads "$threads_file" '
24
24
  .items as $items
25
25
  | ($threads[0] | map(select(.isResolved == false and .isOutdated == false) | .id) | sort) as $expected
26
26
  | ($items | [.[] | select(.type == "add_comment" and (.item_number | tostring) == $pr and (.body | type == "string"))]) as $comments
27
- | ($comments | map(.body | if test("\\*\\*Review outcome:\\*\\*\\s*(implemented|already-satisfied|needs-human)"; "i") then capture("\\*\\*Review outcome:\\*\\*\\s*(?<v>implemented|already-satisfied|needs-human)"; "i").v | ascii_downcase else empty end) | .[0] // "invalid") as $outcome
27
+ # The line is matched by shape, not exact markdown: a model that writes
28
+ # **Review outcome** : implemented or **Review outcome - implemented still means
29
+ # the same. See the triage validator for the same pattern.
30
+ | ($comments | map(.body | if test("Review outcome[^\\w\\n]{0,6}(?<v>implemented|already-satisfied|needs-human)\\b"; "i") then capture("Review outcome[^\\w\\n]{0,6}(?<v>implemented|already-satisfied|needs-human)\\b"; "i").v | ascii_downcase else empty end) | .[0] // "invalid") as $outcome
28
31
  # `add` on an empty array is null, not [], and `unique` then dies with "Cannot iterate over
29
32
  # null". That is not an edge case: it is every pull-request-level review. Requesting changes
30
33
  # from the Files tab, or a plain review body with no inline comment, creates a review and no
@@ -1,36 +1,36 @@
1
- # Managed by @plainconceptsplatform/workflows. Source: loops/actions/validate-triage-output/action.yml. Update with workflows update --force; consumer edits may be overwritten.
2
- name: Validate triage output
3
- description: Verify agent_output.json contains a usable triage verdict before any GitHub writes.
4
- inputs:
5
- output-file:
6
- description: Path to agent_output.json.
7
- required: true
8
- issue-number:
9
- description: Issue number that every triage outcome must target.
10
- required: true
11
- outputs:
12
- valid:
13
- description: Whether the output contains a usable triage comment with a verdict.
14
- value: ${{ steps.validate.outputs.valid }}
15
- outcome:
16
- description: "Deterministic triage outcome: pass, needs-info, needs-maintainer, block, or invalid."
17
- value: ${{ steps.validate.outputs.outcome }}
18
- runs:
19
- using: composite
20
- steps:
21
- - name: Validate triage outcome
22
- id: validate
23
- shell: bash
24
- env:
25
- ISSUE_NUMBER: ${{ inputs.issue-number }}
26
- OUTPUT_FILE: ${{ inputs.output-file }}
27
- run: |
28
- set -euo pipefail
29
-
30
- outcome="$(bash "${{ github.action_path }}/validate-triage-output.sh" "$OUTPUT_FILE" "$ISSUE_NUMBER")"
31
- echo "outcome=$outcome" >> "$GITHUB_OUTPUT"
32
- echo "valid=$([ "$outcome" != 'invalid' ] && echo true || echo false)" >> "$GITHUB_OUTPUT"
33
-
34
- if [ "$outcome" = 'invalid' ]; then
35
- echo "::warning::Agent output has no usable triage outcome. It will not be applied."
36
- fi
1
+ # Managed by @plainconceptsplatform/workflows. Source: loops/actions/validate-triage-output/action.yml. Update with workflows update --force; consumer edits may be overwritten.
2
+ name: Validate triage output
3
+ description: Verify agent_output.json contains a usable triage verdict before any GitHub writes.
4
+ inputs:
5
+ output-file:
6
+ description: Path to agent_output.json.
7
+ required: true
8
+ issue-number:
9
+ description: Issue number that every triage outcome must target.
10
+ required: true
11
+ outputs:
12
+ valid:
13
+ description: Whether the output contains a usable triage comment with a verdict.
14
+ value: ${{ steps.validate.outputs.valid }}
15
+ outcome:
16
+ description: "Deterministic triage outcome: pass, needs-info, needs-maintainer, block, or invalid."
17
+ value: ${{ steps.validate.outputs.outcome }}
18
+ runs:
19
+ using: composite
20
+ steps:
21
+ - name: Validate triage outcome
22
+ id: validate
23
+ shell: bash
24
+ env:
25
+ ISSUE_NUMBER: ${{ inputs.issue-number }}
26
+ OUTPUT_FILE: ${{ inputs.output-file }}
27
+ run: |
28
+ set -euo pipefail
29
+
30
+ outcome="$(bash "${{ github.action_path }}/validate-triage-output.sh" "$OUTPUT_FILE" "$ISSUE_NUMBER")"
31
+ echo "outcome=$outcome" >> "$GITHUB_OUTPUT"
32
+ echo "valid=$([ "$outcome" != 'invalid' ] && echo true || echo false)" >> "$GITHUB_OUTPUT"
33
+
34
+ if [ "$outcome" = 'invalid' ]; then
35
+ echo "::warning::Agent output has no usable triage outcome. It will not be applied."
36
+ fi
@@ -20,12 +20,15 @@ fi
20
20
  # must contain a verdict line matching **Verdict:** pass|needs-info|needs-maintainer|block.
21
21
  # capture() returns an object use a named group (?<v>...) to extract the value.
22
22
  # test() before capture() avoids jq errors on non-matching bodies.
23
+ # The line is matched by shape, not exact markdown: a model that writes
24
+ # **Verdict** : pass or **Verdict - pass still means the same (Bots #1336 showed
25
+ # GLM-5-2 paraphrasing the expected sentence; the same happens with verdict lines).
23
26
  jq -r --arg issue "$issue_number" '
24
27
  def extract_verdict:
25
28
  [.items[] | select(.type == "add_comment" and (.item_number | tostring) == $issue and (.body | type == "string"))]
26
29
  | map(.body |
27
- if test("\\*\\*Verdict:\\*\\*\\s*(pass|needs-info|needs-maintainer|block)"; "i") then
28
- capture("\\*\\*Verdict:\\*\\*\\s*(?<v>pass|needs-info|needs-maintainer|block)"; "i").v | ascii_downcase
30
+ if test("Verdict[^\\w\\n]{0,6}(?<v>pass|needs-info|needs-maintainer|block)\\b"; "i") then
31
+ capture("Verdict[^\\w\\n]{0,6}(?<v>pass|needs-info|needs-maintainer|block)\\b"; "i").v | ascii_downcase
29
32
  else empty end
30
33
  )
31
34
  | .[0] // "none";
@@ -1,9 +1,9 @@
1
- # Managed by @plainconceptsplatform/workflows. Source: loops/actions/verify-composite-actions/action.yml. Update with workflows update --force; consumer edits may be overwritten.
2
- name: Verify composite actions
3
- description: Check every local composite action manifest parses and uses only contexts a composite action actually has.
4
- runs:
5
- using: composite
6
- steps:
7
- - name: Validate composite action manifests
8
- shell: bash
9
- run: bash "${GITHUB_ACTION_PATH}/verify-composite-actions.sh"
1
+ # Managed by @plainconceptsplatform/workflows. Source: loops/actions/verify-composite-actions/action.yml. Update with workflows update --force; consumer edits may be overwritten.
2
+ name: Verify composite actions
3
+ description: Check every local composite action manifest parses and uses only contexts a composite action actually has.
4
+ runs:
5
+ using: composite
6
+ steps:
7
+ - name: Validate composite action manifests
8
+ shell: bash
9
+ run: bash "${GITHUB_ACTION_PATH}/verify-composite-actions.sh"
@@ -1,9 +1,9 @@
1
- # Managed by @plainconceptsplatform/workflows. Source: loops/actions/verify-refine-output/action.yml. Update with workflows update --force; consumer edits may be overwritten.
2
- name: Verify refine output validation
3
- description: Exercise deterministic Refine output validation regressions.
4
- runs:
5
- using: composite
6
- steps:
7
- - name: Verify refinement outcomes
8
- shell: bash
9
- run: bash "${{ github.action_path }}/verify-refine-output.sh"
1
+ # Managed by @plainconceptsplatform/workflows. Source: loops/actions/verify-refine-output/action.yml. Update with workflows update --force; consumer edits may be overwritten.
2
+ name: Verify refine output validation
3
+ description: Exercise deterministic Refine output validation regressions.
4
+ runs:
5
+ using: composite
6
+ steps:
7
+ - name: Verify refinement outcomes
8
+ shell: bash
9
+ run: bash "${{ github.action_path }}/verify-refine-output.sh"
@@ -75,6 +75,20 @@ assert_output 'complete output cannot update another issue' invalid \
75
75
  '{"items":[{"type":"update_issue","item_number":42,"body":"# User story"},{"type":"update_issue","item_number":7,"body":"# Other story"}]}'
76
76
  assert_output 'draft update with questions comment is questions' questions \
77
77
  '{"items":[{"type":"update_issue","item_number":42,"body":"<!-- agent-refine-draft -->\n### Proposal\n_pending see questions below_"},{"type":"add_comment","item_number":42,"body":"<!-- agent-refine -->\nRefinement update\nI have some questions about this issue. Please reply in one comment and I''ll process your answers.\nWhich area owns this behavior?"}]}'
78
+
79
+ # From Bots #1336, run 42214146974. gh-aw process_safe_outputs strips HTML comments
80
+ # from the body, so the draft marker (<!-- agent-refine-draft -->) is gone. The
81
+ # model also paraphrased the questions line as "I have some questions that the code
82
+ # cannot settle on its own" instead of the exact sentence. The pending mark
83
+ # (_pending see questions below_) survives in the body and the comment is still on
84
+ # the source issue, so the outcome is questions, not invalid.
85
+ # The JSON fixture below carries literal markdown backticks from the real Bots #1336 output.
86
+ # The checker reads them as command substitution inside single quotes (SC2016), a false
87
+ # positive because the whole argument is data, not shell.
88
+ # shellcheck disable=SC2016
89
+ assert_output 'stripped draft marker with paraphrased questions is questions' questions \
90
+ '{"items":[{"type":"update_issue","item_number":42,"body":"**Complexity:** standard path\n\n> Refinement draft. Three open questions are in a separate comment. The parts they leave open are marked `_pending see questions below_`."},{"type":"add_comment","item_number":42,"body":"## Refinement update\n\nI have some questions that the code cannot settle on its own. Reply in one comment to change any of them.\n1. Does the conductor bot stay local only too?"}]}'
91
+
78
92
  assert_output 'draft update alone is invalid' invalid \
79
93
  '{"items":[{"type":"update_issue","item_number":42,"body":"<!-- agent-refine-draft -->\n### Proposal\n_pending see questions below_"}]}'
80
94
 
@@ -1,9 +1,9 @@
1
- # Managed by @plainconceptsplatform/workflows. Source: loops/actions/verify-route-matrix/action.yml. Update with workflows update --force; consumer edits may be overwritten.
2
- name: Verify route matrix
3
- description: Exercise the router's classifier against every supported event, and check that each route and dispatch operation has a job in work-router.yml.
4
- runs:
5
- using: composite
6
- steps:
7
- - name: Run route matrix verification
8
- shell: bash
9
- run: bash "${GITHUB_ACTION_PATH}/verify-route-matrix.sh"
1
+ # Managed by @plainconceptsplatform/workflows. Source: loops/actions/verify-route-matrix/action.yml. Update with workflows update --force; consumer edits may be overwritten.
2
+ name: Verify route matrix
3
+ description: Exercise the router's classifier against every supported event, and check that each route and dispatch operation has a job in work-router.yml.
4
+ runs:
5
+ using: composite
6
+ steps:
7
+ - name: Run route matrix verification
8
+ shell: bash
9
+ run: bash "${GITHUB_ACTION_PATH}/verify-route-matrix.sh"