@plainconceptsplatform/workflows 0.19.2 → 0.20.1

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 (53) hide show
  1. package/dist/catalog-installation.js +12 -1
  2. package/dist/index.js +0 -0
  3. package/dist/stack-defaults.js +16 -16
  4. package/dist/worker-env.js +14 -0
  5. package/loops/actions/add-issue-labels/action.yml +50 -50
  6. package/loops/actions/agent-output.cjs +17 -17
  7. package/loops/actions/apply-agent-bundle/action.yml +24 -24
  8. package/loops/actions/apply-agent-comments/action.yml +42 -42
  9. package/loops/actions/apply-agent-labels/action.yml +55 -55
  10. package/loops/actions/apply-agent-output/action.yml +108 -108
  11. package/loops/actions/assess-blast-radius/action.yml +148 -0
  12. package/loops/actions/assess-blast-radius/assess-blast-radius.sh +138 -0
  13. package/loops/actions/classify-route/action.yml +100 -100
  14. package/loops/actions/cleanup-artifacts/action.yml +91 -91
  15. package/loops/actions/close-agent-issues/action.yml +43 -43
  16. package/loops/actions/create-agent-issues/action.yml +52 -52
  17. package/loops/actions/create-issue-comment/action.yml +29 -29
  18. package/loops/actions/download-agent-output/action.yml +53 -53
  19. package/loops/actions/housekeeping/action.yml +55 -2
  20. package/loops/actions/link-pr-to-issue/action.yml +40 -40
  21. package/loops/actions/list-open-issues/action.yml +33 -33
  22. package/loops/actions/load-issue-context/action.yml +45 -45
  23. package/loops/actions/merge-agent-pr/action.yml +49 -49
  24. package/loops/actions/push-agent-branch/action.yml +45 -45
  25. package/loops/actions/remove-issue-labels/action.yml +37 -37
  26. package/loops/actions/update-agent-issues/action.yml +58 -58
  27. package/loops/actions/validate-merge-gate-output/action.yml +62 -40
  28. package/loops/actions/validate-merge-gate-output/validate-merge-gate-output.sh +147 -31
  29. package/loops/actions/validate-refine-output/action.yml +48 -44
  30. package/loops/actions/validate-refine-output/validate-refine-output.sh +15 -4
  31. package/loops/actions/validate-review-output/action.yml +35 -35
  32. package/loops/actions/validate-triage-output/action.yml +36 -36
  33. package/loops/actions/verify-composite-actions/action.yml +9 -9
  34. package/loops/actions/verify-refine-output/action.yml +9 -9
  35. package/loops/actions/verify-refine-output/verify-refine-output.sh +6 -1
  36. package/loops/actions/verify-route-matrix/action.yml +9 -9
  37. package/loops/actions/verify-route-matrix/verify-gate-metrics.mjs +51 -0
  38. package/loops/actions/verify-route-matrix/verify-route-matrix.sh +329 -29
  39. package/loops/scripts/compile-agent-workflows.mjs +331 -331
  40. package/loops/templates/agentics/agentics-maintenance.yml +121 -121
  41. package/loops/templates/ci/app-ci-dotnet-next.yml +330 -330
  42. package/loops/templates/ci/app-ci-node-monorepo.yml +260 -260
  43. package/loops/templates/issues/bug_report.yml +109 -109
  44. package/loops/templates/issues/feature_request.yml +75 -75
  45. package/loops/templates/opencode/opencode.ci.json +55 -49
  46. package/loops/templates/opencode/opencode.ci.json.md +59 -49
  47. package/loops/templates/release/github-release.yml +30 -30
  48. package/loops/workflows/agent-merge-gate.md +367 -148
  49. package/loops/workflows/agent-refine.md +60 -16
  50. package/loops/workflows/authorize-bot-work.yml +105 -105
  51. package/loops/workflows/shared/opencode-ci.md +206 -206
  52. package/loops/workflows/shared/platform-defaults.md +19 -19
  53. package/package.json +12 -11
@@ -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"
@@ -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
@@ -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"
@@ -7,6 +7,7 @@ set -euo pipefail
7
7
  HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
8
8
  VALIDATOR="${HERE}/../validate-refine-output/validate-refine-output.sh"
9
9
  MARKER='<!-- agent-refine -->'
10
+ DRAFT_MARK='<!-- agent-refine-draft -->'
10
11
  PREFIX='Refinement update'
11
12
  TEMP_DIR="$(mktemp -d)"
12
13
 
@@ -23,7 +24,7 @@ assert_output() {
23
24
  local actual
24
25
 
25
26
  printf '%s' "$payload" > "$output_file"
26
- actual="$(bash "$VALIDATOR" "$output_file" "$MARKER" "$PREFIX" 42)"
27
+ actual="$(bash "$VALIDATOR" "$output_file" "$MARKER" "$PREFIX" 42 "$DRAFT_MARK")"
27
28
 
28
29
  if [ "$actual" = "$expected" ]; then
29
30
  PASS=$((PASS + 1))
@@ -55,6 +56,10 @@ assert_output 'wrong issue output is invalid' invalid \
55
56
  '{"items":[{"type":"add_comment","item_number":7,"body":"Which users need this feature?"}]}'
56
57
  assert_output 'complete output cannot update another issue' invalid \
57
58
  '{"items":[{"type":"update_issue","item_number":42,"body":"# User story"},{"type":"update_issue","item_number":7,"body":"# Other story"}]}'
59
+ assert_output 'draft update with questions comment is questions' questions \
60
+ '{"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?"}]}'
61
+ assert_output 'draft update alone is invalid' invalid \
62
+ '{"items":[{"type":"update_issue","item_number":42,"body":"<!-- agent-refine-draft -->\n### Proposal\n_pending — see questions below_"}]}'
58
63
 
59
64
  # From a real run. The agent's first update_issue went out malformed, the bridge counted it
60
65
  # as spent, the retry carrying the body was refused, and the "Refinement complete" comment
@@ -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"
@@ -0,0 +1,51 @@
1
+ // Managed by @plainconceptsplatform/workflows. Source: loops/actions/verify-route-matrix/verify-gate-metrics.mjs. Update with `workflows update --force`; consumer edits may be overwritten.
2
+ // Runs the housekeeping digest's gate-metrics renderer against fixtures. The auto-merge rate
3
+ // is the number the merge gate asks to be judged on, and the one Phase 7 would widen trust
4
+ // from, so "it cannot merge anything wrong" is not a reason to leave its arithmetic untested.
5
+ import { readFileSync } from "node:fs";
6
+ const yml = readFileSync(process.argv[2], "utf8").replace(/\r\n/g, "\n");
7
+
8
+ // Pull the gate metrics renderer out of the inline github-script block and run it. The counting
9
+ // loops above it need a GitHub API to exercise, but the arithmetic does not, and the arithmetic
10
+ // is the part that reports a number somebody will act on.
11
+ const start = yml.indexOf("const gateSection = () => {");
12
+ if (start === -1) { console.error("FAIL: housekeeping has no gateSection renderer"); process.exit(1); }
13
+ let depth = 0, end = start;
14
+ for (let i = yml.indexOf("{", start); i < yml.length; i++) {
15
+ if (yml[i] === "{") depth++;
16
+ else if (yml[i] === "}") { depth--; if (depth === 0) { end = i + 1; break; } }
17
+ }
18
+ const src = yml.slice(start, end).replace(/^\s+/gm, " ");
19
+
20
+ const run = (dispositions, autoMerged, reverts) =>
21
+ new Function("dispositions", "autoMerged", "reverts", "metricsWindowMs",
22
+ `${src}; return gateSection();`)(dispositions, autoMerged, reverts, 14 * 24 * 3600000);
23
+
24
+ let failed = 0;
25
+ const check = (name, got, want) => {
26
+ const ok = typeof want === "function" ? want(got) : got === want;
27
+ if (!ok) { failed = 1; console.error(`FAIL: gate metrics ${name}: got ${JSON.stringify(got)}`); }
28
+ };
29
+
30
+ check("is empty when the gate has posted nothing",
31
+ run({}, [], []), "");
32
+ check("reports the auto-merge share",
33
+ run({ "auto-merge": 12, "human-review": 2, "owner-review": 1 }, [], []),
34
+ (s) => s.includes("**80% auto-merged** (12 of 15 dispositions)"));
35
+ check("rounds rather than truncates",
36
+ run({ "auto-merge": 2, "human-review": 1 }, [], []),
37
+ (s) => s.includes("**67% auto-merged**"));
38
+ check("counts a revert only against the pull request it names",
39
+ run({ "auto-merge": 2 }, [11, 12], [12, 99]),
40
+ (s) => s.includes("later reverted: 1"));
41
+ check("counts no reverts when none match",
42
+ run({ "auto-merge": 2 }, [11, 12], [77]),
43
+ (s) => s.includes("later reverted: 0"));
44
+ check("a repository with only parked pull requests reads as zero, not as an error",
45
+ run({ "human-review": 3 }, [], []),
46
+ (s) => s.includes("**0% auto-merged** (0 of 3 dispositions)"));
47
+ check("lists every disposition it saw",
48
+ run({ "auto-merge": 1, blocked: 2 }, [], []),
49
+ (s) => s.includes("`blocked` · 2") && s.includes("`auto-merge` · 1"));
50
+
51
+ process.exit(failed);