@plainconceptsplatform/workflows 0.1.1 → 0.1.5

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 (67) hide show
  1. package/README.md +37 -7
  2. package/dist/catalog-installation.d.ts +4 -3
  3. package/dist/catalog-installation.js +28 -9
  4. package/dist/catalog-installation.test.js +111 -10
  5. package/dist/catalog-listing.d.ts +13 -0
  6. package/dist/catalog-listing.js +68 -0
  7. package/dist/catalog-listing.test.d.ts +1 -0
  8. package/dist/catalog-listing.test.js +137 -0
  9. package/dist/index.js +62 -11
  10. package/dist/index.test.d.ts +1 -0
  11. package/dist/index.test.js +112 -0
  12. package/dist/repository-inspection.test.d.ts +1 -0
  13. package/dist/repository-inspection.test.js +77 -0
  14. package/dist/workflow-catalog.d.ts +9 -7
  15. package/dist/workflow-catalog.js +21 -16
  16. package/dist/workflow-catalog.test.js +18 -3
  17. package/loops/actions/add-issue-labels/action.yml +30 -29
  18. package/loops/actions/agent-output.cjs +1 -0
  19. package/loops/actions/apply-agent-bundle/action.yml +24 -23
  20. package/loops/actions/apply-agent-bundle/apply-bundle.sh +1 -0
  21. package/loops/actions/apply-agent-comments/action.yml +42 -41
  22. package/loops/actions/apply-agent-labels/action.yml +55 -54
  23. package/loops/actions/apply-agent-output/action.yml +108 -107
  24. package/loops/actions/audit-close/action.yml +104 -103
  25. package/loops/actions/classify-route/action.yml +91 -90
  26. package/loops/actions/classify-route/classify-route.sh +1 -0
  27. package/loops/actions/cleanup-artifacts/action.yml +65 -64
  28. package/loops/actions/close-agent-issues/action.yml +43 -42
  29. package/loops/actions/create-agent-issues/action.yml +52 -51
  30. package/loops/actions/create-issue-comment/action.yml +29 -28
  31. package/loops/actions/download-agent-output/action.yml +53 -52
  32. package/loops/actions/identify-gate-subject/action.yml +97 -96
  33. package/loops/actions/link-pr-to-issue/action.yml +40 -39
  34. package/loops/actions/list-open-issues/action.yml +33 -32
  35. package/loops/actions/load-issue-context/action.yml +43 -42
  36. package/loops/actions/merge-agent-pr/action.yml +36 -35
  37. package/loops/actions/push-agent-branch/action.yml +45 -44
  38. package/loops/actions/remove-issue-labels/action.yml +35 -34
  39. package/loops/actions/stale-recovery/action.yml +288 -287
  40. package/loops/actions/update-agent-issues/action.yml +58 -57
  41. package/loops/actions/validate-refine-output/action.yml +44 -43
  42. package/loops/actions/validate-refine-output/validate-refine-output.sh +1 -0
  43. package/loops/actions/verify-composite-actions/action.yml +9 -8
  44. package/loops/actions/verify-composite-actions/verify-composite-actions.sh +1 -0
  45. package/loops/actions/verify-refine-output/action.yml +9 -8
  46. package/loops/actions/verify-refine-output/verify-refine-output.sh +1 -0
  47. package/loops/actions/verify-route-matrix/action.yml +9 -8
  48. package/loops/actions/verify-route-matrix/verify-route-matrix.sh +1 -0
  49. package/loops/scripts/compile-agent-workflows.mjs +18 -2
  50. package/loops/templates/agentics/agentics-checks.yml +86 -0
  51. package/loops/templates/agentics/agentics-maintenance.yml +121 -0
  52. package/loops/templates/ci/app-ci-dotnet-next.yml +167 -0
  53. package/loops/templates/ci/app-ci-node-monorepo.yml +178 -0
  54. package/loops/templates/opencode/opencode.ci.json +46 -0
  55. package/loops/templates/opencode/opencode.ci.json.md +41 -0
  56. package/loops/workflows/agent-apply-review.md +9 -10
  57. package/loops/workflows/agent-audit.md +6 -7
  58. package/loops/workflows/agent-direct.md +7 -8
  59. package/loops/workflows/agent-implement.md +7 -8
  60. package/loops/workflows/agent-merge-gate.md +9 -10
  61. package/loops/workflows/agent-propose.md +7 -8
  62. package/loops/workflows/agent-refine.md +5 -7
  63. package/loops/workflows/shared/opencode-ci.md +1 -0
  64. package/loops/workflows/shared/platform-defaults.md +1 -0
  65. package/loops/workflows/work-router.yml +1 -0
  66. package/package.json +42 -42
  67. package/loops/aw/repo-config.md +0 -12
@@ -1,54 +1,55 @@
1
- name: Apply agent labels
2
- description: Apply every add_labels and remove_labels item from agent_output.json.
3
- inputs:
4
- output-file:
5
- description: Path to agent_output.json.
6
- required: true
7
- token:
8
- description: GitHub token with issues:write.
9
- required: true
10
- runs:
11
- using: composite
12
- steps:
13
- - name: Apply label changes
14
- uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
15
- env:
16
- AGENT_OUTPUT_LIB: ${{ github.action_path }}/../agent-output.cjs
17
- OUTPUT_FILE: ${{ inputs.output-file }}
18
- with:
19
- github-token: ${{ inputs.token }}
20
- script: |
21
- const { readAgentItems } = require(process.env.AGENT_OUTPUT_LIB);
22
- const items = readAgentItems(process.env.OUTPUT_FILE)
23
- .filter((item) => item.type === 'add_labels' || item.type === 'remove_labels');
24
-
25
- let added = 0;
26
- let removed = 0;
27
-
28
- for (const item of items) {
29
- const labels = (item.labels ?? []).map((label) => label.name).filter(Boolean);
30
-
31
- if (!item.item_number || labels.length === 0) {
32
- core.warning(`${item.type} item is not actionable, skipping: ${JSON.stringify(item)}`);
33
- continue;
34
- }
35
-
36
- const issue_number = Number(item.item_number);
37
-
38
- if (item.type === 'add_labels') {
39
- await github.rest.issues.addLabels({ ...context.repo, issue_number, labels });
40
- added += labels.length;
41
- continue;
42
- }
43
-
44
- for (const name of labels) {
45
- try {
46
- await github.rest.issues.removeLabel({ ...context.repo, issue_number, name });
47
- removed += 1;
48
- } catch (error) {
49
- if (error.status !== 404) throw error;
50
- }
51
- }
52
- }
53
-
54
- core.info(`Added ${added} label(s), removed ${removed}.`);
1
+ # Managed by @plainconceptsplatform/workflows. Source: loops/actions/apply-agent-labels/action.yml. Update with workflows update --force; consumer edits may be overwritten.
2
+ name: Apply agent labels
3
+ description: Apply every add_labels and remove_labels 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
+ runs:
12
+ using: composite
13
+ steps:
14
+ - name: Apply label changes
15
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
16
+ env:
17
+ AGENT_OUTPUT_LIB: ${{ github.action_path }}/../agent-output.cjs
18
+ OUTPUT_FILE: ${{ inputs.output-file }}
19
+ with:
20
+ github-token: ${{ inputs.token }}
21
+ script: |
22
+ const { readAgentItems } = require(process.env.AGENT_OUTPUT_LIB);
23
+ const items = readAgentItems(process.env.OUTPUT_FILE)
24
+ .filter((item) => item.type === 'add_labels' || item.type === 'remove_labels');
25
+
26
+ let added = 0;
27
+ let removed = 0;
28
+
29
+ for (const item of items) {
30
+ const labels = (item.labels ?? []).map((label) => label.name).filter(Boolean);
31
+
32
+ if (!item.item_number || labels.length === 0) {
33
+ core.warning(`${item.type} item is not actionable, skipping: ${JSON.stringify(item)}`);
34
+ continue;
35
+ }
36
+
37
+ const issue_number = Number(item.item_number);
38
+
39
+ if (item.type === 'add_labels') {
40
+ await github.rest.issues.addLabels({ ...context.repo, issue_number, labels });
41
+ added += labels.length;
42
+ continue;
43
+ }
44
+
45
+ for (const name of labels) {
46
+ try {
47
+ await github.rest.issues.removeLabel({ ...context.repo, issue_number, name });
48
+ removed += 1;
49
+ } catch (error) {
50
+ if (error.status !== 404) throw error;
51
+ }
52
+ }
53
+ }
54
+
55
+ core.info(`Added ${added} label(s), removed ${removed}.`);
@@ -1,107 +1,108 @@
1
- name: Apply agent output
2
- description: Download the agent artifact and apply its safe outputs in one fixed order, so every worker concludes the same way.
3
- inputs:
4
- token:
5
- description: GitHub token the writes are made with.
6
- required: true
7
- artifact-name:
8
- description: >-
9
- Name of the agent artifact. Callers pass the activation job's artifact_prefix output
10
- followed by "agent"; gh-aw derives that prefix from the workflow's inputs, so it is
11
- non-empty for every workflow_call worker and the bare name never resolves.
12
- required: true
13
- merge-pull-request:
14
- description: Apply merge_pull_request items.
15
- required: false
16
- default: 'false'
17
- push-to-branch:
18
- description: Apply push_to_pull_request_branch items.
19
- required: false
20
- default: 'false'
21
- close-issues:
22
- description: Apply close_issue items.
23
- required: false
24
- default: 'false'
25
- create-issues:
26
- description: Apply create_issue items.
27
- required: false
28
- default: 'false'
29
- update-issues:
30
- description: Apply update_issue items.
31
- required: false
32
- default: 'false'
33
- apply-labels:
34
- description: Apply add_labels and remove_labels items.
35
- required: false
36
- default: 'true'
37
- fallback-issue-number:
38
- description: Issue an update_issue item targets when it names none.
39
- required: false
40
- default: ''
41
- outputs:
42
- item-count:
43
- description: Number of items the agent produced.
44
- value: ${{ steps.output.outputs.item-count }}
45
- first-issue-number:
46
- description: Issue number of the first issue created, or empty.
47
- value: ${{ steps.create-issues.outputs.first-issue-number }}
48
- runs:
49
- using: composite
50
- steps:
51
- - name: Download agent output
52
- id: output
53
- uses: ./.github/actions/download-agent-output
54
- with:
55
- artifact-name: ${{ inputs.artifact-name }}
56
-
57
- - name: Merge pull request
58
- if: inputs.merge-pull-request == 'true' && steps.output.outputs.item-count != '0'
59
- uses: ./.github/actions/merge-agent-pr
60
- with:
61
- output-file: ${{ steps.output.outputs.output-file }}
62
- token: ${{ inputs.token }}
63
-
64
- - name: Push to pull request branch
65
- if: inputs.push-to-branch == 'true' && steps.output.outputs.item-count != '0'
66
- uses: ./.github/actions/push-agent-branch
67
- with:
68
- output-file: ${{ steps.output.outputs.output-file }}
69
- bundle-file: ${{ steps.output.outputs.bundle-file }}
70
- token: ${{ inputs.token }}
71
-
72
- - name: Close issues
73
- if: inputs.close-issues == 'true' && steps.output.outputs.item-count != '0'
74
- uses: ./.github/actions/close-agent-issues
75
- with:
76
- output-file: ${{ steps.output.outputs.output-file }}
77
- token: ${{ inputs.token }}
78
-
79
- - name: Update issues
80
- if: inputs.update-issues == 'true' && steps.output.outputs.item-count != '0'
81
- uses: ./.github/actions/update-agent-issues
82
- with:
83
- output-file: ${{ steps.output.outputs.output-file }}
84
- token: ${{ inputs.token }}
85
- fallback-issue-number: ${{ inputs.fallback-issue-number }}
86
-
87
- - name: Create issues
88
- id: create-issues
89
- if: inputs.create-issues == 'true' && steps.output.outputs.item-count != '0'
90
- uses: ./.github/actions/create-agent-issues
91
- with:
92
- output-file: ${{ steps.output.outputs.output-file }}
93
- token: ${{ inputs.token }}
94
-
95
- - name: Post agent comments
96
- if: steps.output.outputs.item-count != '0'
97
- uses: ./.github/actions/apply-agent-comments
98
- with:
99
- output-file: ${{ steps.output.outputs.output-file }}
100
- token: ${{ inputs.token }}
101
-
102
- - name: Apply agent label changes
103
- if: inputs.apply-labels == 'true' && steps.output.outputs.item-count != '0'
104
- uses: ./.github/actions/apply-agent-labels
105
- with:
106
- output-file: ${{ steps.output.outputs.output-file }}
107
- token: ${{ inputs.token }}
1
+ # Managed by @plainconceptsplatform/workflows. Source: loops/actions/apply-agent-output/action.yml. Update with workflows update --force; consumer edits may be overwritten.
2
+ name: Apply agent output
3
+ description: Download the agent artifact and apply its safe outputs in one fixed order, so every worker concludes the same way.
4
+ inputs:
5
+ token:
6
+ description: GitHub token the writes are made with.
7
+ required: true
8
+ artifact-name:
9
+ description: >-
10
+ Name of the agent artifact. Callers pass the activation job's artifact_prefix output
11
+ followed by "agent"; gh-aw derives that prefix from the workflow's inputs, so it is
12
+ non-empty for every workflow_call worker and the bare name never resolves.
13
+ required: true
14
+ merge-pull-request:
15
+ description: Apply merge_pull_request items.
16
+ required: false
17
+ default: 'false'
18
+ push-to-branch:
19
+ description: Apply push_to_pull_request_branch items.
20
+ required: false
21
+ default: 'false'
22
+ close-issues:
23
+ description: Apply close_issue items.
24
+ required: false
25
+ default: 'false'
26
+ create-issues:
27
+ description: Apply create_issue items.
28
+ required: false
29
+ default: 'false'
30
+ update-issues:
31
+ description: Apply update_issue items.
32
+ required: false
33
+ default: 'false'
34
+ apply-labels:
35
+ description: Apply add_labels and remove_labels items.
36
+ required: false
37
+ default: 'true'
38
+ fallback-issue-number:
39
+ description: Issue an update_issue item targets when it names none.
40
+ required: false
41
+ default: ''
42
+ outputs:
43
+ item-count:
44
+ description: Number of items the agent produced.
45
+ value: ${{ steps.output.outputs.item-count }}
46
+ first-issue-number:
47
+ description: Issue number of the first issue created, or empty.
48
+ value: ${{ steps.create-issues.outputs.first-issue-number }}
49
+ runs:
50
+ using: composite
51
+ steps:
52
+ - name: Download agent output
53
+ id: output
54
+ uses: ./.github/actions/download-agent-output
55
+ with:
56
+ artifact-name: ${{ inputs.artifact-name }}
57
+
58
+ - name: Merge pull request
59
+ if: inputs.merge-pull-request == 'true' && steps.output.outputs.item-count != '0'
60
+ uses: ./.github/actions/merge-agent-pr
61
+ with:
62
+ output-file: ${{ steps.output.outputs.output-file }}
63
+ token: ${{ inputs.token }}
64
+
65
+ - name: Push to pull request branch
66
+ if: inputs.push-to-branch == 'true' && steps.output.outputs.item-count != '0'
67
+ uses: ./.github/actions/push-agent-branch
68
+ with:
69
+ output-file: ${{ steps.output.outputs.output-file }}
70
+ bundle-file: ${{ steps.output.outputs.bundle-file }}
71
+ token: ${{ inputs.token }}
72
+
73
+ - name: Close issues
74
+ if: inputs.close-issues == 'true' && steps.output.outputs.item-count != '0'
75
+ uses: ./.github/actions/close-agent-issues
76
+ with:
77
+ output-file: ${{ steps.output.outputs.output-file }}
78
+ token: ${{ inputs.token }}
79
+
80
+ - name: Update issues
81
+ if: inputs.update-issues == 'true' && steps.output.outputs.item-count != '0'
82
+ uses: ./.github/actions/update-agent-issues
83
+ with:
84
+ output-file: ${{ steps.output.outputs.output-file }}
85
+ token: ${{ inputs.token }}
86
+ fallback-issue-number: ${{ inputs.fallback-issue-number }}
87
+
88
+ - name: Create issues
89
+ id: create-issues
90
+ if: inputs.create-issues == 'true' && steps.output.outputs.item-count != '0'
91
+ uses: ./.github/actions/create-agent-issues
92
+ with:
93
+ output-file: ${{ steps.output.outputs.output-file }}
94
+ token: ${{ inputs.token }}
95
+
96
+ - name: Post agent comments
97
+ if: steps.output.outputs.item-count != '0'
98
+ uses: ./.github/actions/apply-agent-comments
99
+ with:
100
+ output-file: ${{ steps.output.outputs.output-file }}
101
+ token: ${{ inputs.token }}
102
+
103
+ - name: Apply agent label changes
104
+ if: inputs.apply-labels == 'true' && steps.output.outputs.item-count != '0'
105
+ uses: ./.github/actions/apply-agent-labels
106
+ with:
107
+ output-file: ${{ steps.output.outputs.output-file }}
108
+ token: ${{ inputs.token }}
@@ -1,103 +1,104 @@
1
- name: Close audit reports
2
- description: Close open audit reports once every issue they reference is closed.
3
- inputs:
4
- token:
5
- description: GitHub token with issues write access.
6
- required: true
7
- runs:
8
- using: composite
9
- steps:
10
- - name: Close every report whose referenced issues are all closed
11
- uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
12
- with:
13
- github-token: ${{ inputs.token }}
14
- script: |
15
- const reports = await github.paginate(github.rest.issues.listForRepo, {
16
- ...context.repo,
17
- state: 'open',
18
- labels: 'audit',
19
- per_page: 100,
20
- });
21
-
22
- if (reports.length === 0) {
23
- core.info('No open audit reports.');
24
- return;
25
- }
26
-
27
- // Skip `owner/repo#12` and `abc#12`: only a bare `#12` references this repository.
28
- const referencedIssues = (body) => {
29
- const matches = (body ?? '').matchAll(/(?:^|[^A-Za-z0-9_/])#(\d+)/g);
30
- return [...new Set([...matches].map((match) => Number(match[1])))];
31
- };
32
-
33
- let closed = 0;
34
- let keptOpen = 0;
35
-
36
- for (const report of reports.sort((a, b) => a.number - b.number)) {
37
- const refs = referencedIssues(report.body).filter((n) => n !== report.number);
38
-
39
- const stillOpen = [];
40
- const unknown = [];
41
- let closedRefs = 0;
42
- let resolved = 0;
43
-
44
- for (const ref of refs) {
45
- let state;
46
-
47
- try {
48
- ({ data: { state } } = await github.rest.issues.get({
49
- ...context.repo,
50
- issue_number: ref,
51
- }));
52
- } catch (error) {
53
- if (error.status === 404) {
54
- core.info(`#${report.number}: ignoring #${ref}, not an issue in this repository`);
55
- continue;
56
- }
57
- unknown.push(ref);
58
- resolved += 1;
59
- continue;
60
- }
61
-
62
- resolved += 1;
63
- if (state === 'closed') closedRefs += 1;
64
- else stillOpen.push(ref);
65
- }
66
-
67
- if (stillOpen.length > 0) {
68
- core.info(`#${report.number}: kept open, still-open references: ${stillOpen.join(', ')}`);
69
- keptOpen += 1;
70
- continue;
71
- }
72
-
73
- if (unknown.length > 0) {
74
- core.info(`#${report.number}: kept open, undetermined references: ${unknown.join(', ')}`);
75
- keptOpen += 1;
76
- continue;
77
- }
78
-
79
- const reason = resolved === 0
80
- ? 'This report references no issues.'
81
- : `All ${closedRefs} referenced issue(s) are closed.`;
82
-
83
- await github.rest.issues.createComment({
84
- ...context.repo,
85
- issue_number: report.number,
86
- body: `Closed automatically by \`Work Router: audit-close\`. ${reason}`,
87
- });
88
-
89
- await github.rest.issues.update({
90
- ...context.repo,
91
- issue_number: report.number,
92
- state: 'closed',
93
- state_reason: 'completed',
94
- });
95
-
96
- core.info(`#${report.number}: closed. ${reason}`);
97
- closed += 1;
98
- }
99
-
100
- await core.summary
101
- .addHeading('Audit close', 2)
102
- .addList([`Reports closed: ${closed}`, `Reports left open: ${keptOpen}`])
103
- .write();
1
+ # Managed by @plainconceptsplatform/workflows. Source: loops/actions/audit-close/action.yml. Update with workflows update --force; consumer edits may be overwritten.
2
+ name: Close audit reports
3
+ description: Close open audit reports once every issue they reference is closed.
4
+ inputs:
5
+ token:
6
+ description: GitHub token with issues write access.
7
+ required: true
8
+ runs:
9
+ using: composite
10
+ steps:
11
+ - name: Close every report whose referenced issues are all closed
12
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
13
+ with:
14
+ github-token: ${{ inputs.token }}
15
+ script: |
16
+ const reports = await github.paginate(github.rest.issues.listForRepo, {
17
+ ...context.repo,
18
+ state: 'open',
19
+ labels: 'audit',
20
+ per_page: 100,
21
+ });
22
+
23
+ if (reports.length === 0) {
24
+ core.info('No open audit reports.');
25
+ return;
26
+ }
27
+
28
+ // Skip `owner/repo#12` and `abc#12`: only a bare `#12` references this repository.
29
+ const referencedIssues = (body) => {
30
+ const matches = (body ?? '').matchAll(/(?:^|[^A-Za-z0-9_/])#(\d+)/g);
31
+ return [...new Set([...matches].map((match) => Number(match[1])))];
32
+ };
33
+
34
+ let closed = 0;
35
+ let keptOpen = 0;
36
+
37
+ for (const report of reports.sort((a, b) => a.number - b.number)) {
38
+ const refs = referencedIssues(report.body).filter((n) => n !== report.number);
39
+
40
+ const stillOpen = [];
41
+ const unknown = [];
42
+ let closedRefs = 0;
43
+ let resolved = 0;
44
+
45
+ for (const ref of refs) {
46
+ let state;
47
+
48
+ try {
49
+ ({ data: { state } } = await github.rest.issues.get({
50
+ ...context.repo,
51
+ issue_number: ref,
52
+ }));
53
+ } catch (error) {
54
+ if (error.status === 404) {
55
+ core.info(`#${report.number}: ignoring #${ref}, not an issue in this repository`);
56
+ continue;
57
+ }
58
+ unknown.push(ref);
59
+ resolved += 1;
60
+ continue;
61
+ }
62
+
63
+ resolved += 1;
64
+ if (state === 'closed') closedRefs += 1;
65
+ else stillOpen.push(ref);
66
+ }
67
+
68
+ if (stillOpen.length > 0) {
69
+ core.info(`#${report.number}: kept open, still-open references: ${stillOpen.join(', ')}`);
70
+ keptOpen += 1;
71
+ continue;
72
+ }
73
+
74
+ if (unknown.length > 0) {
75
+ core.info(`#${report.number}: kept open, undetermined references: ${unknown.join(', ')}`);
76
+ keptOpen += 1;
77
+ continue;
78
+ }
79
+
80
+ const reason = resolved === 0
81
+ ? 'This report references no issues.'
82
+ : `All ${closedRefs} referenced issue(s) are closed.`;
83
+
84
+ await github.rest.issues.createComment({
85
+ ...context.repo,
86
+ issue_number: report.number,
87
+ body: `Closed automatically by \`Work Router: audit-close\`. ${reason}`,
88
+ });
89
+
90
+ await github.rest.issues.update({
91
+ ...context.repo,
92
+ issue_number: report.number,
93
+ state: 'closed',
94
+ state_reason: 'completed',
95
+ });
96
+
97
+ core.info(`#${report.number}: closed. ${reason}`);
98
+ closed += 1;
99
+ }
100
+
101
+ await core.summary
102
+ .addHeading('Audit close', 2)
103
+ .addList([`Reports closed: ${closed}`, `Reports left open: ${keptOpen}`])
104
+ .write();