@macedon-technologies/batman 1.17.2 → 1.18.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.
- package/.jsii +205 -26
- package/.swamp.yaml +6 -0
- package/API.md +164 -1
- package/CLAUDE.md +44 -0
- package/architecture-rules/README.md +42 -0
- package/architecture-rules/check.ts +162 -0
- package/architecture-rules/rules.json +3 -0
- package/architecture-rules/tsconfig.json +14 -0
- package/attestation/manifest.ts +40 -0
- package/attestation/tsconfig.json +13 -0
- package/attestation/verify.ts +142 -0
- package/build-tools/scan-generated-workflows.ts +18 -11
- package/lib/Application.js +6 -1
- package/lib/BatmanProject.js +8 -2
- package/lib/BootcampProject.js +8 -2
- package/lib/CodeOwnersFile.js +1 -1
- package/lib/ProductionDeployWorkflow.js +1 -1
- package/lib/ProjenWorkflowHardening.d.ts +18 -0
- package/lib/ProjenWorkflowHardening.js +59 -0
- package/lib/SoftwareFactoryArchitectureRules.d.ts +10 -0
- package/lib/SoftwareFactoryArchitectureRules.js +245 -0
- package/lib/SoftwareFactoryAttestation.d.ts +18 -0
- package/lib/SoftwareFactoryAttestation.js +221 -0
- package/lib/SoftwareFactoryFiles.d.ts +45 -0
- package/lib/SoftwareFactoryFiles.js +102 -0
- package/lib/SoftwareFactoryModels.d.ts +25 -0
- package/lib/SoftwareFactoryModels.js +306 -0
- package/lib/SoftwareFactoryOpenSpecGates.d.ts +8 -0
- package/lib/SoftwareFactoryOpenSpecGates.js +75 -0
- package/lib/SoftwareFactoryWorkflows.d.ts +28 -0
- package/lib/SoftwareFactoryWorkflows.js +326 -0
- package/lib/StagingDeployWorkflow.js +1 -1
- package/lib/WorkflowActionVersions.d.ts +31 -1
- package/lib/WorkflowActionVersions.js +5 -1
- package/lib/WorkflowAutoDiscover.js +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.js +2 -1
- package/lib/utils.js +29 -1
- package/models/@goodcraft/github/platform-common-pr.yaml +10 -0
- package/models/@swamp/software-factory/platform-common-factory.yaml +240 -0
- package/models/@webframp/github/platform-common-issues.yaml +8 -0
- package/models/command/shell/platform-common-shell-architecture.yaml +8 -0
- package/models/command/shell/platform-common-shell-manifest.yaml +8 -0
- package/models/command/shell/platform-common-shell.yaml +8 -0
- package/openspec-gates/check-tasks-complete.ts +44 -0
- package/openspec-gates/tsconfig.json +13 -0
- package/package.json +6 -1
- package/workflows/workflow-openspec-plan-verify.yaml +51 -0
- package/workflows/workflow-openspec-tasks-verify.yaml +51 -0
- package/workflows/workflow-pre-pr-verify.yaml +118 -0
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
type: '@swamp/software-factory'
|
|
2
|
+
typeVersion: 2026.06.24.1
|
|
3
|
+
id: 7e207e5d-7067-4286-9a84-ca8330a26f53
|
|
4
|
+
name: platform-common-factory
|
|
5
|
+
version: 1
|
|
6
|
+
tags: {}
|
|
7
|
+
reports:
|
|
8
|
+
require:
|
|
9
|
+
- name: "@swamp/software-factory/work-item-summary"
|
|
10
|
+
methods: [summary]
|
|
11
|
+
globalArguments:
|
|
12
|
+
stages:
|
|
13
|
+
- id: intake
|
|
14
|
+
initial: true
|
|
15
|
+
description: >-
|
|
16
|
+
Fetch the GitHub issue for this work item (workItem is the bare
|
|
17
|
+
issue number) and record its context.
|
|
18
|
+
work:
|
|
19
|
+
mode: interactive
|
|
20
|
+
systemPrompt: >-
|
|
21
|
+
Fetch the GitHub issue numbered ${{ self.workItem }} for
|
|
22
|
+
macedon-technologies/platform-common using the platform-common-issues model
|
|
23
|
+
(list_issues, then swamp data query filtered by number — see the
|
|
24
|
+
platform-common-issues data), and record the issue-context artifact.
|
|
25
|
+
artifacts:
|
|
26
|
+
- name: issue-context
|
|
27
|
+
schema:
|
|
28
|
+
type: object
|
|
29
|
+
required: [number, title, url]
|
|
30
|
+
properties:
|
|
31
|
+
number: { type: integer }
|
|
32
|
+
title: { type: string, minLength: 1 }
|
|
33
|
+
body: { type: string }
|
|
34
|
+
url: { type: string, minLength: 1 }
|
|
35
|
+
labels: { type: array, items: { type: string } }
|
|
36
|
+
transitions:
|
|
37
|
+
- name: submit
|
|
38
|
+
to: planning
|
|
39
|
+
gates:
|
|
40
|
+
- type: artifact-exists
|
|
41
|
+
config: { artifact: issue-context }
|
|
42
|
+
|
|
43
|
+
- id: planning
|
|
44
|
+
description: >-
|
|
45
|
+
Turn the issue into a real OpenSpec change (proposal, design,
|
|
46
|
+
specs, tasks) — OpenSpec's task list is the plan, not a
|
|
47
|
+
freeform artifact.
|
|
48
|
+
work:
|
|
49
|
+
mode: interactive
|
|
50
|
+
systemPrompt: >-
|
|
51
|
+
Using the recorded issue-context artifact, use the
|
|
52
|
+
openspec-propose skill to create a complete OpenSpec change
|
|
53
|
+
(proposal.md, design.md, specs with deltas, tasks.md) for this
|
|
54
|
+
work item under openspec/changes/<changeSlug>/ — do not write a
|
|
55
|
+
freeform plan instead of this. Then record the plan artifact
|
|
56
|
+
with the change's slug and a one-line summary.
|
|
57
|
+
artifacts:
|
|
58
|
+
- name: plan
|
|
59
|
+
schema:
|
|
60
|
+
type: object
|
|
61
|
+
required: [changeSlug, summary]
|
|
62
|
+
properties:
|
|
63
|
+
changeSlug: { type: string, minLength: 1 }
|
|
64
|
+
summary: { type: string, minLength: 1 }
|
|
65
|
+
transitions:
|
|
66
|
+
- name: submit
|
|
67
|
+
to: openspec-plan-verify
|
|
68
|
+
gates:
|
|
69
|
+
- type: artifact-exists
|
|
70
|
+
config: { artifact: plan }
|
|
71
|
+
|
|
72
|
+
- id: openspec-plan-verify
|
|
73
|
+
description: >-
|
|
74
|
+
Verify the OpenSpec change is real and well-formed (not just an
|
|
75
|
+
artifact claiming one exists) before implementation starts.
|
|
76
|
+
work:
|
|
77
|
+
mode: workflow
|
|
78
|
+
workflow:
|
|
79
|
+
name: openspec-plan-verify
|
|
80
|
+
inputs:
|
|
81
|
+
changeSlug: '${{ data.latest(self.name, "artifact-plan").payload.changeSlug }}'
|
|
82
|
+
resultEvidence: plan-verify-run
|
|
83
|
+
transitions:
|
|
84
|
+
- name: pass
|
|
85
|
+
to: implementing
|
|
86
|
+
gates:
|
|
87
|
+
- type: workflow-succeeded
|
|
88
|
+
config: { workflow: openspec-plan-verify }
|
|
89
|
+
- name: fail
|
|
90
|
+
to: planning
|
|
91
|
+
gates:
|
|
92
|
+
- type: evidence-recorded
|
|
93
|
+
config: { name: plan-verify-run, requireField: { status: failed } }
|
|
94
|
+
|
|
95
|
+
- id: implementing
|
|
96
|
+
description: Implement the OpenSpec change's tasks on a branch.
|
|
97
|
+
work:
|
|
98
|
+
mode: interactive
|
|
99
|
+
systemPrompt: >-
|
|
100
|
+
Use the openspec-apply-change skill against the change recorded
|
|
101
|
+
in the plan artifact's changeSlug — work through its tasks.md
|
|
102
|
+
one task at a time, checking each off (`- [ ]` -> `- [x]`) as
|
|
103
|
+
you complete it, until every task is done. Commit the work on a
|
|
104
|
+
feature branch. Record the change-summary artifact and the
|
|
105
|
+
change-request evidence (branch name and head commit sha — no
|
|
106
|
+
PR yet, that happens after pre-PR verification passes).
|
|
107
|
+
artifacts:
|
|
108
|
+
- name: change-summary
|
|
109
|
+
schema:
|
|
110
|
+
type: object
|
|
111
|
+
required: [summary, headSha]
|
|
112
|
+
properties:
|
|
113
|
+
summary: { type: string, minLength: 1 }
|
|
114
|
+
headSha: { type: string, minLength: 7 }
|
|
115
|
+
evidence:
|
|
116
|
+
- name: change-request
|
|
117
|
+
schema:
|
|
118
|
+
type: object
|
|
119
|
+
required: [branch, headSha]
|
|
120
|
+
properties:
|
|
121
|
+
branch: { type: string, minLength: 1 }
|
|
122
|
+
headSha: { type: string, minLength: 7 }
|
|
123
|
+
url: { type: string }
|
|
124
|
+
transitions:
|
|
125
|
+
- name: submit
|
|
126
|
+
to: openspec-tasks-verify
|
|
127
|
+
gates:
|
|
128
|
+
- type: artifact-exists
|
|
129
|
+
config: { artifact: change-summary }
|
|
130
|
+
- type: evidence-recorded
|
|
131
|
+
config: { name: change-request }
|
|
132
|
+
|
|
133
|
+
- id: openspec-tasks-verify
|
|
134
|
+
description: >-
|
|
135
|
+
Verify every task in the OpenSpec change is actually checked off
|
|
136
|
+
before pre-PR verification runs.
|
|
137
|
+
work:
|
|
138
|
+
mode: workflow
|
|
139
|
+
workflow:
|
|
140
|
+
name: openspec-tasks-verify
|
|
141
|
+
inputs:
|
|
142
|
+
changeSlug: '${{ data.latest(self.name, "artifact-plan").payload.changeSlug }}'
|
|
143
|
+
resultEvidence: tasks-verify-run
|
|
144
|
+
transitions:
|
|
145
|
+
- name: pass
|
|
146
|
+
to: pre-pr-verify
|
|
147
|
+
gates:
|
|
148
|
+
- type: workflow-succeeded
|
|
149
|
+
config: { workflow: openspec-tasks-verify }
|
|
150
|
+
- name: fail
|
|
151
|
+
to: implementing
|
|
152
|
+
gates:
|
|
153
|
+
- type: evidence-recorded
|
|
154
|
+
config: { name: tasks-verify-run, requireField: { status: failed } }
|
|
155
|
+
|
|
156
|
+
- id: pre-pr-verify
|
|
157
|
+
description: >-
|
|
158
|
+
Pre-PR verification: build/synth/test/lint plus the architecture
|
|
159
|
+
rule registry, run before the PR is opened rather than relying on
|
|
160
|
+
CI after the fact.
|
|
161
|
+
work:
|
|
162
|
+
mode: workflow
|
|
163
|
+
workflow:
|
|
164
|
+
name: pre-pr-verify
|
|
165
|
+
inputs:
|
|
166
|
+
commit: '${{ data.latest(self.name, "evidence-change-request").payload.headSha }}'
|
|
167
|
+
branch: '${{ data.latest(self.name, "evidence-change-request").payload.branch }}'
|
|
168
|
+
resultEvidence: verify-run
|
|
169
|
+
transitions:
|
|
170
|
+
- name: pass
|
|
171
|
+
to: open-pr
|
|
172
|
+
gates:
|
|
173
|
+
- type: workflow-succeeded
|
|
174
|
+
config: { workflow: pre-pr-verify }
|
|
175
|
+
- name: fail
|
|
176
|
+
to: implementing
|
|
177
|
+
gates:
|
|
178
|
+
- type: evidence-recorded
|
|
179
|
+
config: { name: verify-run, requireField: { status: failed } }
|
|
180
|
+
|
|
181
|
+
- id: open-pr
|
|
182
|
+
description: Open the pull request now that pre-PR verification has passed.
|
|
183
|
+
work:
|
|
184
|
+
mode: interactive
|
|
185
|
+
systemPrompt: >-
|
|
186
|
+
Before opening the PR, fetch the real pre-pr-verify attestation
|
|
187
|
+
with `swamp data get --workflow pre-pr-verify
|
|
188
|
+
report-swamp-verification-attestation --json` and include its
|
|
189
|
+
`content` verbatim (as a markdown block, e.g. under a "Pre-PR
|
|
190
|
+
verification" heading) in the PR body — never just assert in
|
|
191
|
+
prose that checks passed. Also fetch this same run's manifest step
|
|
192
|
+
output (`swamp data query 'modelName == "platform-common-shell-manifest" &&
|
|
193
|
+
name == "result"' --select attributes.stdout --json`, take the
|
|
194
|
+
latest) and append it to the PR body as
|
|
195
|
+
`<!-- attestation-manifest {"commit": "<headSha>", "status":
|
|
196
|
+
"succeeded", ...the manifest step's JSON, spread in...} -->` — an
|
|
197
|
+
HTML comment so it's invisible when rendered but still present in
|
|
198
|
+
the raw body text verify-attestation.yml reads via the GitHub API.
|
|
199
|
+
Also fetch the plan artifact's changeSlug and include an explicit
|
|
200
|
+
"OpenSpec change" line in the PR body naming it and its path
|
|
201
|
+
(`openspec/changes/<changeSlug>/`) — every PR the factory opens
|
|
202
|
+
must call out which OpenSpec change(s) drove the session, not
|
|
203
|
+
just imply it. If planning cycled through more than one change
|
|
204
|
+
(a rework loop produced a new changeSlug), list every distinct
|
|
205
|
+
changeSlug recorded across the run's plan artifact versions, not
|
|
206
|
+
only the latest. Then call platform-common-pr's openPr method
|
|
207
|
+
(repo=macedon-technologies/platform-common, head=<the branch recorded in
|
|
208
|
+
change-request evidence>, base=main, dryRun=false), with
|
|
209
|
+
title/body referencing the intake stage's issue number, the
|
|
210
|
+
OpenSpec change(s), the attestation block, and the manifest
|
|
211
|
+
comment, then record the pr-opened evidence with the returned PR
|
|
212
|
+
url and number.
|
|
213
|
+
evidence:
|
|
214
|
+
- name: pr-opened
|
|
215
|
+
schema:
|
|
216
|
+
type: object
|
|
217
|
+
required: [url, number]
|
|
218
|
+
properties:
|
|
219
|
+
url: { type: string, minLength: 1 }
|
|
220
|
+
number: { type: integer }
|
|
221
|
+
transitions:
|
|
222
|
+
- name: submit
|
|
223
|
+
to: done
|
|
224
|
+
gates:
|
|
225
|
+
- type: evidence-recorded
|
|
226
|
+
config: { name: pr-opened }
|
|
227
|
+
|
|
228
|
+
- id: done
|
|
229
|
+
terminal: true
|
|
230
|
+
|
|
231
|
+
- id: aborted
|
|
232
|
+
terminal: true
|
|
233
|
+
|
|
234
|
+
globalTransitions:
|
|
235
|
+
- name: abort
|
|
236
|
+
to: aborted
|
|
237
|
+
gates:
|
|
238
|
+
- type: human-approval
|
|
239
|
+
config: { id: abort-confirmation }
|
|
240
|
+
methods: {}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gate: fails unless every task in the named OpenSpec change's tasks.md is
|
|
3
|
+
* checked off. `openspec validate`/`openspec status` don't check this (an
|
|
4
|
+
* in-progress change is a normal, valid state) — this is the deterministic
|
|
5
|
+
* check the pre-pr pipeline needs before letting implementation proceed.
|
|
6
|
+
*/
|
|
7
|
+
import { execFileSync } from 'node:child_process';
|
|
8
|
+
|
|
9
|
+
interface OpenSpecChangeSummary {
|
|
10
|
+
name: string;
|
|
11
|
+
completedTasks: number;
|
|
12
|
+
totalTasks: number;
|
|
13
|
+
status: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function main(): number {
|
|
17
|
+
// pnpm's `-- <args>` forwarding (and projen's receiveArgs) can pass a
|
|
18
|
+
// literal "--" through as an argv token ahead of the real argument.
|
|
19
|
+
const slug = process.argv.slice(2).find((arg) => arg !== '--');
|
|
20
|
+
if (!slug) {
|
|
21
|
+
console.error('Usage: check-tasks-complete <change-slug>');
|
|
22
|
+
return 1;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const raw = execFileSync('openspec', ['list', '--json'], { encoding: 'utf8' });
|
|
26
|
+
const { changes } = JSON.parse(raw) as { changes: OpenSpecChangeSummary[] };
|
|
27
|
+
const change = changes.find((c) => c.name === slug);
|
|
28
|
+
|
|
29
|
+
if (!change) {
|
|
30
|
+
console.error(`OpenSpec change "${slug}" not found (openspec list --json)`);
|
|
31
|
+
return 1;
|
|
32
|
+
}
|
|
33
|
+
if (change.status !== 'complete') {
|
|
34
|
+
console.error(
|
|
35
|
+
`OpenSpec change "${slug}" has incomplete tasks: ${change.completedTasks}/${change.totalTasks}`,
|
|
36
|
+
);
|
|
37
|
+
return 1;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
console.log(`OpenSpec change "${slug}": all ${change.totalTasks} tasks complete`);
|
|
41
|
+
return 0;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
process.exit(main());
|
package/package.json
CHANGED
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"main": "lib/index.js",
|
|
50
50
|
"license": "Apache-2.0",
|
|
51
51
|
"stability": "stable",
|
|
52
|
-
"version": "1.
|
|
52
|
+
"version": "1.18.0",
|
|
53
53
|
"jest": {
|
|
54
54
|
"coverageProvider": "v8",
|
|
55
55
|
"testMatch": [
|
|
@@ -104,6 +104,8 @@
|
|
|
104
104
|
},
|
|
105
105
|
"//": "~~ Generated by projen. To modify, edit .projenrc.ts and run \"pnpm exec projen\".",
|
|
106
106
|
"scripts": {
|
|
107
|
+
"attestation:manifest": "projen attestation:manifest",
|
|
108
|
+
"attestation:verify": "projen attestation:verify",
|
|
107
109
|
"build": "projen build",
|
|
108
110
|
"bump": "projen bump",
|
|
109
111
|
"bump:releasable-commits": "projen bump:releasable-commits",
|
|
@@ -114,6 +116,7 @@
|
|
|
114
116
|
"docgen": "projen docgen",
|
|
115
117
|
"eject": "projen eject",
|
|
116
118
|
"eslint": "projen eslint",
|
|
119
|
+
"openspec:check-tasks-complete": "projen openspec:check-tasks-complete",
|
|
117
120
|
"package": "projen package",
|
|
118
121
|
"package-all": "projen package-all",
|
|
119
122
|
"package:js": "projen package:js",
|
|
@@ -121,10 +124,12 @@
|
|
|
121
124
|
"post-upgrade": "projen post-upgrade",
|
|
122
125
|
"pre-compile": "projen pre-compile",
|
|
123
126
|
"release": "projen release",
|
|
127
|
+
"swamp:bootstrap": "projen swamp:bootstrap",
|
|
124
128
|
"test": "projen test",
|
|
125
129
|
"test:watch": "projen test:watch",
|
|
126
130
|
"unbump": "projen unbump",
|
|
127
131
|
"upgrade": "projen upgrade",
|
|
132
|
+
"validate:architecture": "projen validate:architecture",
|
|
128
133
|
"watch": "projen watch",
|
|
129
134
|
"zizmor": "projen zizmor",
|
|
130
135
|
"projen": "projen"
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
id: 9876c89c-de05-4c3c-9595-cbc7622f5391
|
|
2
|
+
name: openspec-plan-verify
|
|
3
|
+
description: >-
|
|
4
|
+
Fails unless the named OpenSpec change is well-formed (proposal, design,
|
|
5
|
+
specs with deltas, tasks all present) via `openspec validate`. Gates the
|
|
6
|
+
factory's planning stage: a request can't proceed to implementation until
|
|
7
|
+
it's a real OpenSpec change, not just prose in a swamp artifact.
|
|
8
|
+
tags: {}
|
|
9
|
+
inputs:
|
|
10
|
+
type: object
|
|
11
|
+
required: [changeSlug]
|
|
12
|
+
properties:
|
|
13
|
+
changeSlug:
|
|
14
|
+
type: string
|
|
15
|
+
description: The openspec change name (openspec/changes/<changeSlug>/).
|
|
16
|
+
jobs:
|
|
17
|
+
- name: verify
|
|
18
|
+
description: Validate the OpenSpec change is complete and well-formed
|
|
19
|
+
steps:
|
|
20
|
+
- name: validate
|
|
21
|
+
description: openspec validate <changeSlug> --type change
|
|
22
|
+
task:
|
|
23
|
+
type: model_method
|
|
24
|
+
modelIdOrName: platform-common-shell
|
|
25
|
+
methodName: execute
|
|
26
|
+
inputs:
|
|
27
|
+
run: 'openspec validate ${{ inputs.changeSlug }} --type change'
|
|
28
|
+
dependsOn: []
|
|
29
|
+
weight: 0
|
|
30
|
+
allowFailure: false
|
|
31
|
+
- name: assert-valid
|
|
32
|
+
description: openspec validate must exit 0
|
|
33
|
+
task:
|
|
34
|
+
type: assert
|
|
35
|
+
expr: >-
|
|
36
|
+
data.query('modelName == "platform-common-shell" && name == "result" &&
|
|
37
|
+
workflowRunId == "' + run.id + '"')[0].attributes.exitCode == 0
|
|
38
|
+
message: >-
|
|
39
|
+
OpenSpec change is not valid/complete (missing proposal, design,
|
|
40
|
+
specs with deltas, or tasks) — see the platform-common-shell result data
|
|
41
|
+
for openspec's own remediation output
|
|
42
|
+
severity: high
|
|
43
|
+
dependsOn:
|
|
44
|
+
- step: validate
|
|
45
|
+
condition:
|
|
46
|
+
type: succeeded
|
|
47
|
+
weight: 0
|
|
48
|
+
allowFailure: false
|
|
49
|
+
dependsOn: []
|
|
50
|
+
weight: 0
|
|
51
|
+
version: 1
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
id: 57139fa5-bcae-4338-90c0-1f4d2fa05398
|
|
2
|
+
name: openspec-tasks-verify
|
|
3
|
+
description: >-
|
|
4
|
+
Fails unless every task in the named OpenSpec change's tasks.md is checked
|
|
5
|
+
off (openspec-gates/check-tasks-complete.ts, via `pnpm run
|
|
6
|
+
openspec:check-tasks-complete`). Gates the factory's implementing stage:
|
|
7
|
+
work isn't done until the change's own task list says it's done, not just
|
|
8
|
+
because an artifact was recorded.
|
|
9
|
+
tags: {}
|
|
10
|
+
inputs:
|
|
11
|
+
type: object
|
|
12
|
+
required: [changeSlug]
|
|
13
|
+
properties:
|
|
14
|
+
changeSlug:
|
|
15
|
+
type: string
|
|
16
|
+
description: The openspec change name (openspec/changes/<changeSlug>/).
|
|
17
|
+
jobs:
|
|
18
|
+
- name: verify
|
|
19
|
+
description: Check every task in the change's tasks.md is complete
|
|
20
|
+
steps:
|
|
21
|
+
- name: check-tasks
|
|
22
|
+
description: pnpm run openspec:check-tasks-complete -- <changeSlug>
|
|
23
|
+
task:
|
|
24
|
+
type: model_method
|
|
25
|
+
modelIdOrName: platform-common-shell
|
|
26
|
+
methodName: execute
|
|
27
|
+
inputs:
|
|
28
|
+
run: 'pnpm run openspec:check-tasks-complete -- ${{ inputs.changeSlug }}'
|
|
29
|
+
dependsOn: []
|
|
30
|
+
weight: 0
|
|
31
|
+
allowFailure: false
|
|
32
|
+
- name: assert-tasks-complete
|
|
33
|
+
description: openspec:check-tasks-complete must exit 0
|
|
34
|
+
task:
|
|
35
|
+
type: assert
|
|
36
|
+
expr: >-
|
|
37
|
+
data.query('modelName == "platform-common-shell" && name == "result" &&
|
|
38
|
+
workflowRunId == "' + run.id + '"')[0].attributes.exitCode == 0
|
|
39
|
+
message: >-
|
|
40
|
+
OpenSpec change has incomplete tasks — see the platform-common-shell
|
|
41
|
+
result data for the completedTasks/totalTasks breakdown
|
|
42
|
+
severity: high
|
|
43
|
+
dependsOn:
|
|
44
|
+
- step: check-tasks
|
|
45
|
+
condition:
|
|
46
|
+
type: succeeded
|
|
47
|
+
weight: 0
|
|
48
|
+
allowFailure: false
|
|
49
|
+
dependsOn: []
|
|
50
|
+
weight: 0
|
|
51
|
+
version: 1
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
id: a3b4b6f9-cb73-460a-8a5a-c464250c7d03
|
|
2
|
+
name: pre-pr-verify
|
|
3
|
+
description: >-
|
|
4
|
+
Pre-PR verification: run the same checks CI would run, before the factory
|
|
5
|
+
opens a PR rather than after — build/synth/test/lint (pnpm build) and the
|
|
6
|
+
architecture rule registry (pnpm validate:architecture). Both must pass.
|
|
7
|
+
tags: {}
|
|
8
|
+
inputs:
|
|
9
|
+
type: object
|
|
10
|
+
properties:
|
|
11
|
+
commit:
|
|
12
|
+
type: string
|
|
13
|
+
description: >-
|
|
14
|
+
The commit sha being verified. Read by the built-in
|
|
15
|
+
@swamp/verification-attestation report's subject.commit — pass the
|
|
16
|
+
real HEAD sha or the attestation renders "unknown".
|
|
17
|
+
branch:
|
|
18
|
+
type: string
|
|
19
|
+
description: Same as commit, but for @swamp/verification-attestation's subject.branch.
|
|
20
|
+
jobs:
|
|
21
|
+
- name: verify
|
|
22
|
+
description: Build/test/lint plus architecture-rule checks, gating PR creation
|
|
23
|
+
steps:
|
|
24
|
+
- name: build
|
|
25
|
+
description: compile -> cdk synth -> jest -> eslint (existing projen build task)
|
|
26
|
+
task:
|
|
27
|
+
type: model_method
|
|
28
|
+
modelIdOrName: platform-common-shell
|
|
29
|
+
methodName: execute
|
|
30
|
+
inputs:
|
|
31
|
+
run: pnpm build
|
|
32
|
+
dependsOn: []
|
|
33
|
+
weight: 0
|
|
34
|
+
allowFailure: false
|
|
35
|
+
- name: assert-build
|
|
36
|
+
description: pnpm build must exit 0
|
|
37
|
+
task:
|
|
38
|
+
type: assert
|
|
39
|
+
expr: >-
|
|
40
|
+
data.query('modelName == "platform-common-shell" && name == "result" &&
|
|
41
|
+
workflowRunId == "' + run.id + '"')[0].attributes.exitCode == 0
|
|
42
|
+
message: >-
|
|
43
|
+
pnpm build failed (compile/synth/test/lint) — see the platform-common-shell
|
|
44
|
+
result data for stdout/stderr
|
|
45
|
+
severity: high
|
|
46
|
+
dependsOn:
|
|
47
|
+
- step: build
|
|
48
|
+
condition:
|
|
49
|
+
type: succeeded
|
|
50
|
+
weight: 0
|
|
51
|
+
allowFailure: false
|
|
52
|
+
- name: architecture
|
|
53
|
+
description: run the architecture rule registry (architecture-rules/rules.json)
|
|
54
|
+
task:
|
|
55
|
+
type: model_method
|
|
56
|
+
modelIdOrName: platform-common-shell-architecture
|
|
57
|
+
methodName: execute
|
|
58
|
+
inputs:
|
|
59
|
+
run: pnpm run validate:architecture
|
|
60
|
+
dependsOn:
|
|
61
|
+
- step: assert-build
|
|
62
|
+
condition:
|
|
63
|
+
type: succeeded
|
|
64
|
+
weight: 0
|
|
65
|
+
allowFailure: false
|
|
66
|
+
- name: assert-architecture
|
|
67
|
+
description: architecture rule registry must exit 0 (no enabled-rule violations)
|
|
68
|
+
task:
|
|
69
|
+
type: assert
|
|
70
|
+
expr: >-
|
|
71
|
+
data.query('modelName == "platform-common-shell-architecture" && name == "result" &&
|
|
72
|
+
workflowRunId == "' + run.id + '"')[0].attributes.exitCode == 0
|
|
73
|
+
message: >-
|
|
74
|
+
architecture rule violation(s) found — see the platform-common-shell result
|
|
75
|
+
data for details
|
|
76
|
+
severity: high
|
|
77
|
+
dependsOn:
|
|
78
|
+
- step: architecture
|
|
79
|
+
condition:
|
|
80
|
+
type: succeeded
|
|
81
|
+
weight: 0
|
|
82
|
+
allowFailure: false
|
|
83
|
+
- name: manifest
|
|
84
|
+
description: >-
|
|
85
|
+
compute the attestation-manifest checksums (attestation/manifest.ts)
|
|
86
|
+
that verify-attestation.yml re-checks at merge time
|
|
87
|
+
task:
|
|
88
|
+
type: model_method
|
|
89
|
+
modelIdOrName: platform-common-shell-manifest
|
|
90
|
+
methodName: execute
|
|
91
|
+
inputs:
|
|
92
|
+
run: pnpm run attestation:manifest
|
|
93
|
+
dependsOn:
|
|
94
|
+
- step: assert-architecture
|
|
95
|
+
condition:
|
|
96
|
+
type: succeeded
|
|
97
|
+
weight: 0
|
|
98
|
+
allowFailure: false
|
|
99
|
+
- name: assert-manifest
|
|
100
|
+
description: attestation:manifest must exit 0
|
|
101
|
+
task:
|
|
102
|
+
type: assert
|
|
103
|
+
expr: >-
|
|
104
|
+
data.query('modelName == "platform-common-shell-manifest" && name == "result" &&
|
|
105
|
+
workflowRunId == "' + run.id + '"')[0].attributes.exitCode == 0
|
|
106
|
+
message: >-
|
|
107
|
+
failed to compute the attestation manifest — see the
|
|
108
|
+
platform-common-shell-manifest result data for stdout/stderr
|
|
109
|
+
severity: high
|
|
110
|
+
dependsOn:
|
|
111
|
+
- step: manifest
|
|
112
|
+
condition:
|
|
113
|
+
type: succeeded
|
|
114
|
+
weight: 0
|
|
115
|
+
allowFailure: false
|
|
116
|
+
dependsOn: []
|
|
117
|
+
weight: 0
|
|
118
|
+
version: 1
|