@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,306 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SoftwareFactoryModels = void 0;
|
|
4
|
+
const crypto_1 = require("crypto");
|
|
5
|
+
const projen_1 = require("projen");
|
|
6
|
+
/**
|
|
7
|
+
* Seed swamp model instances wiring the `@swamp/software-factory` state
|
|
8
|
+
* machine to this repo's GitHub issues/PRs and shell steps. These are
|
|
9
|
+
* `SampleFile`s (written once, then owned by the team) since the factory's
|
|
10
|
+
* stages/gates are the kind of thing a team tunes for its own workflow.
|
|
11
|
+
*/
|
|
12
|
+
class SoftwareFactoryModels {
|
|
13
|
+
constructor(project, options) {
|
|
14
|
+
const { repoName, githubOwner, baseBranch } = options;
|
|
15
|
+
const repo = `${githubOwner}/${repoName}`;
|
|
16
|
+
const issuesModel = `${repoName}-issues`;
|
|
17
|
+
const prModel = `${repoName}-pr`;
|
|
18
|
+
const shellModel = `${repoName}-shell`;
|
|
19
|
+
const shellArchitectureModel = `${repoName}-shell-architecture`;
|
|
20
|
+
const shellManifestModel = `${repoName}-shell-manifest`;
|
|
21
|
+
const secretsVault = `${repoName}-secrets`;
|
|
22
|
+
const factoryModel = `${repoName}-factory`;
|
|
23
|
+
new projen_1.SampleFile(project, `models/@goodcraft/github/${prModel}.yaml`, {
|
|
24
|
+
contents: `type: '@goodcraft/github'
|
|
25
|
+
typeVersion: 2026.06.14.1
|
|
26
|
+
id: ${(0, crypto_1.randomUUID)()}
|
|
27
|
+
name: ${prModel}
|
|
28
|
+
version: 1
|
|
29
|
+
tags: {}
|
|
30
|
+
globalArguments:
|
|
31
|
+
token: '\${{ vault.get(${secretsVault}, GITHUB_TOKEN) }}'
|
|
32
|
+
owner: ${githubOwner}
|
|
33
|
+
methods: {}
|
|
34
|
+
`,
|
|
35
|
+
});
|
|
36
|
+
new projen_1.SampleFile(project, `models/@webframp/github/${issuesModel}.yaml`, {
|
|
37
|
+
contents: `type: '@webframp/github'
|
|
38
|
+
typeVersion: 2026.08.28.1
|
|
39
|
+
id: ${(0, crypto_1.randomUUID)()}
|
|
40
|
+
name: ${issuesModel}
|
|
41
|
+
version: 1
|
|
42
|
+
tags: {}
|
|
43
|
+
globalArguments: {}
|
|
44
|
+
methods: {}
|
|
45
|
+
`,
|
|
46
|
+
});
|
|
47
|
+
for (const name of [shellModel, shellArchitectureModel, shellManifestModel]) {
|
|
48
|
+
new projen_1.SampleFile(project, `models/command/shell/${name}.yaml`, {
|
|
49
|
+
contents: `type: command/shell
|
|
50
|
+
typeVersion: 2026.02.09.1
|
|
51
|
+
id: ${(0, crypto_1.randomUUID)()}
|
|
52
|
+
name: ${name}
|
|
53
|
+
version: 1
|
|
54
|
+
tags: {}
|
|
55
|
+
globalArguments: {}
|
|
56
|
+
methods: {}
|
|
57
|
+
`,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
new projen_1.SampleFile(project, `models/@swamp/software-factory/${factoryModel}.yaml`, {
|
|
61
|
+
contents: `type: '@swamp/software-factory'
|
|
62
|
+
typeVersion: 2026.06.24.1
|
|
63
|
+
id: ${(0, crypto_1.randomUUID)()}
|
|
64
|
+
name: ${factoryModel}
|
|
65
|
+
version: 1
|
|
66
|
+
tags: {}
|
|
67
|
+
reports:
|
|
68
|
+
require:
|
|
69
|
+
- name: "@swamp/software-factory/work-item-summary"
|
|
70
|
+
methods: [summary]
|
|
71
|
+
globalArguments:
|
|
72
|
+
stages:
|
|
73
|
+
- id: intake
|
|
74
|
+
initial: true
|
|
75
|
+
description: >-
|
|
76
|
+
Fetch the GitHub issue for this work item (workItem is the bare
|
|
77
|
+
issue number) and record its context.
|
|
78
|
+
work:
|
|
79
|
+
mode: interactive
|
|
80
|
+
systemPrompt: >-
|
|
81
|
+
Fetch the GitHub issue numbered \${{ self.workItem }} for
|
|
82
|
+
${repo} using the ${issuesModel} model
|
|
83
|
+
(list_issues, then swamp data query filtered by number — see the
|
|
84
|
+
${issuesModel} data), and record the issue-context artifact.
|
|
85
|
+
artifacts:
|
|
86
|
+
- name: issue-context
|
|
87
|
+
schema:
|
|
88
|
+
type: object
|
|
89
|
+
required: [number, title, url]
|
|
90
|
+
properties:
|
|
91
|
+
number: { type: integer }
|
|
92
|
+
title: { type: string, minLength: 1 }
|
|
93
|
+
body: { type: string }
|
|
94
|
+
url: { type: string, minLength: 1 }
|
|
95
|
+
labels: { type: array, items: { type: string } }
|
|
96
|
+
transitions:
|
|
97
|
+
- name: submit
|
|
98
|
+
to: planning
|
|
99
|
+
gates:
|
|
100
|
+
- type: artifact-exists
|
|
101
|
+
config: { artifact: issue-context }
|
|
102
|
+
|
|
103
|
+
- id: planning
|
|
104
|
+
description: >-
|
|
105
|
+
Turn the issue into a real OpenSpec change (proposal, design,
|
|
106
|
+
specs, tasks) — OpenSpec's task list is the plan, not a
|
|
107
|
+
freeform artifact.
|
|
108
|
+
work:
|
|
109
|
+
mode: interactive
|
|
110
|
+
systemPrompt: >-
|
|
111
|
+
Using the recorded issue-context artifact, use the
|
|
112
|
+
openspec-propose skill to create a complete OpenSpec change
|
|
113
|
+
(proposal.md, design.md, specs with deltas, tasks.md) for this
|
|
114
|
+
work item under openspec/changes/<changeSlug>/ — do not write a
|
|
115
|
+
freeform plan instead of this. Then record the plan artifact
|
|
116
|
+
with the change's slug and a one-line summary.
|
|
117
|
+
artifacts:
|
|
118
|
+
- name: plan
|
|
119
|
+
schema:
|
|
120
|
+
type: object
|
|
121
|
+
required: [changeSlug, summary]
|
|
122
|
+
properties:
|
|
123
|
+
changeSlug: { type: string, minLength: 1 }
|
|
124
|
+
summary: { type: string, minLength: 1 }
|
|
125
|
+
transitions:
|
|
126
|
+
- name: submit
|
|
127
|
+
to: openspec-plan-verify
|
|
128
|
+
gates:
|
|
129
|
+
- type: artifact-exists
|
|
130
|
+
config: { artifact: plan }
|
|
131
|
+
|
|
132
|
+
- id: openspec-plan-verify
|
|
133
|
+
description: >-
|
|
134
|
+
Verify the OpenSpec change is real and well-formed (not just an
|
|
135
|
+
artifact claiming one exists) before implementation starts.
|
|
136
|
+
work:
|
|
137
|
+
mode: workflow
|
|
138
|
+
workflow:
|
|
139
|
+
name: openspec-plan-verify
|
|
140
|
+
inputs:
|
|
141
|
+
changeSlug: '\${{ data.latest(self.name, "artifact-plan").payload.changeSlug }}'
|
|
142
|
+
resultEvidence: plan-verify-run
|
|
143
|
+
transitions:
|
|
144
|
+
- name: pass
|
|
145
|
+
to: implementing
|
|
146
|
+
gates:
|
|
147
|
+
- type: workflow-succeeded
|
|
148
|
+
config: { workflow: openspec-plan-verify }
|
|
149
|
+
- name: fail
|
|
150
|
+
to: planning
|
|
151
|
+
gates:
|
|
152
|
+
- type: evidence-recorded
|
|
153
|
+
config: { name: plan-verify-run, requireField: { status: failed } }
|
|
154
|
+
|
|
155
|
+
- id: implementing
|
|
156
|
+
description: Implement the OpenSpec change's tasks on a branch.
|
|
157
|
+
work:
|
|
158
|
+
mode: interactive
|
|
159
|
+
systemPrompt: >-
|
|
160
|
+
Use the openspec-apply-change skill against the change recorded
|
|
161
|
+
in the plan artifact's changeSlug — work through its tasks.md
|
|
162
|
+
one task at a time, checking each off (\`- [ ]\` -> \`- [x]\`) as
|
|
163
|
+
you complete it, until every task is done. Commit the work on a
|
|
164
|
+
feature branch. Record the change-summary artifact and the
|
|
165
|
+
change-request evidence (branch name and head commit sha — no
|
|
166
|
+
PR yet, that happens after pre-PR verification passes).
|
|
167
|
+
artifacts:
|
|
168
|
+
- name: change-summary
|
|
169
|
+
schema:
|
|
170
|
+
type: object
|
|
171
|
+
required: [summary, headSha]
|
|
172
|
+
properties:
|
|
173
|
+
summary: { type: string, minLength: 1 }
|
|
174
|
+
headSha: { type: string, minLength: 7 }
|
|
175
|
+
evidence:
|
|
176
|
+
- name: change-request
|
|
177
|
+
schema:
|
|
178
|
+
type: object
|
|
179
|
+
required: [branch, headSha]
|
|
180
|
+
properties:
|
|
181
|
+
branch: { type: string, minLength: 1 }
|
|
182
|
+
headSha: { type: string, minLength: 7 }
|
|
183
|
+
url: { type: string }
|
|
184
|
+
transitions:
|
|
185
|
+
- name: submit
|
|
186
|
+
to: openspec-tasks-verify
|
|
187
|
+
gates:
|
|
188
|
+
- type: artifact-exists
|
|
189
|
+
config: { artifact: change-summary }
|
|
190
|
+
- type: evidence-recorded
|
|
191
|
+
config: { name: change-request }
|
|
192
|
+
|
|
193
|
+
- id: openspec-tasks-verify
|
|
194
|
+
description: >-
|
|
195
|
+
Verify every task in the OpenSpec change is actually checked off
|
|
196
|
+
before pre-PR verification runs.
|
|
197
|
+
work:
|
|
198
|
+
mode: workflow
|
|
199
|
+
workflow:
|
|
200
|
+
name: openspec-tasks-verify
|
|
201
|
+
inputs:
|
|
202
|
+
changeSlug: '\${{ data.latest(self.name, "artifact-plan").payload.changeSlug }}'
|
|
203
|
+
resultEvidence: tasks-verify-run
|
|
204
|
+
transitions:
|
|
205
|
+
- name: pass
|
|
206
|
+
to: pre-pr-verify
|
|
207
|
+
gates:
|
|
208
|
+
- type: workflow-succeeded
|
|
209
|
+
config: { workflow: openspec-tasks-verify }
|
|
210
|
+
- name: fail
|
|
211
|
+
to: implementing
|
|
212
|
+
gates:
|
|
213
|
+
- type: evidence-recorded
|
|
214
|
+
config: { name: tasks-verify-run, requireField: { status: failed } }
|
|
215
|
+
|
|
216
|
+
- id: pre-pr-verify
|
|
217
|
+
description: >-
|
|
218
|
+
Pre-PR verification: build/synth/test/lint plus the architecture
|
|
219
|
+
rule registry, run before the PR is opened rather than relying on
|
|
220
|
+
CI after the fact.
|
|
221
|
+
work:
|
|
222
|
+
mode: workflow
|
|
223
|
+
workflow:
|
|
224
|
+
name: pre-pr-verify
|
|
225
|
+
inputs:
|
|
226
|
+
commit: '\${{ data.latest(self.name, "evidence-change-request").payload.headSha }}'
|
|
227
|
+
branch: '\${{ data.latest(self.name, "evidence-change-request").payload.branch }}'
|
|
228
|
+
resultEvidence: verify-run
|
|
229
|
+
transitions:
|
|
230
|
+
- name: pass
|
|
231
|
+
to: open-pr
|
|
232
|
+
gates:
|
|
233
|
+
- type: workflow-succeeded
|
|
234
|
+
config: { workflow: pre-pr-verify }
|
|
235
|
+
- name: fail
|
|
236
|
+
to: implementing
|
|
237
|
+
gates:
|
|
238
|
+
- type: evidence-recorded
|
|
239
|
+
config: { name: verify-run, requireField: { status: failed } }
|
|
240
|
+
|
|
241
|
+
- id: open-pr
|
|
242
|
+
description: Open the pull request now that pre-PR verification has passed.
|
|
243
|
+
work:
|
|
244
|
+
mode: interactive
|
|
245
|
+
systemPrompt: >-
|
|
246
|
+
Before opening the PR, fetch the real pre-pr-verify attestation
|
|
247
|
+
with \`swamp data get --workflow pre-pr-verify
|
|
248
|
+
report-swamp-verification-attestation --json\` and include its
|
|
249
|
+
\`content\` verbatim (as a markdown block, e.g. under a "Pre-PR
|
|
250
|
+
verification" heading) in the PR body — never just assert in
|
|
251
|
+
prose that checks passed. Also fetch this same run's manifest step
|
|
252
|
+
output (\`swamp data query 'modelName == "${shellManifestModel}" &&
|
|
253
|
+
name == "result"' --select attributes.stdout --json\`, take the
|
|
254
|
+
latest) and append it to the PR body as
|
|
255
|
+
\`<!-- attestation-manifest {"commit": "<headSha>", "status":
|
|
256
|
+
"succeeded", ...the manifest step's JSON, spread in...} -->\` — an
|
|
257
|
+
HTML comment so it's invisible when rendered but still present in
|
|
258
|
+
the raw body text verify-attestation.yml reads via the GitHub API.
|
|
259
|
+
Also fetch the plan artifact's changeSlug and include an explicit
|
|
260
|
+
"OpenSpec change" line in the PR body naming it and its path
|
|
261
|
+
(\`openspec/changes/<changeSlug>/\`) — every PR the factory opens
|
|
262
|
+
must call out which OpenSpec change(s) drove the session, not
|
|
263
|
+
just imply it. If planning cycled through more than one change
|
|
264
|
+
(a rework loop produced a new changeSlug), list every distinct
|
|
265
|
+
changeSlug recorded across the run's plan artifact versions, not
|
|
266
|
+
only the latest. Then call ${prModel}'s openPr method
|
|
267
|
+
(repo=${repo}, head=<the branch recorded in
|
|
268
|
+
change-request evidence>, base=${baseBranch}, dryRun=false), with
|
|
269
|
+
title/body referencing the intake stage's issue number, the
|
|
270
|
+
OpenSpec change(s), the attestation block, and the manifest
|
|
271
|
+
comment, then record the pr-opened evidence with the returned PR
|
|
272
|
+
url and number.
|
|
273
|
+
evidence:
|
|
274
|
+
- name: pr-opened
|
|
275
|
+
schema:
|
|
276
|
+
type: object
|
|
277
|
+
required: [url, number]
|
|
278
|
+
properties:
|
|
279
|
+
url: { type: string, minLength: 1 }
|
|
280
|
+
number: { type: integer }
|
|
281
|
+
transitions:
|
|
282
|
+
- name: submit
|
|
283
|
+
to: done
|
|
284
|
+
gates:
|
|
285
|
+
- type: evidence-recorded
|
|
286
|
+
config: { name: pr-opened }
|
|
287
|
+
|
|
288
|
+
- id: done
|
|
289
|
+
terminal: true
|
|
290
|
+
|
|
291
|
+
- id: aborted
|
|
292
|
+
terminal: true
|
|
293
|
+
|
|
294
|
+
globalTransitions:
|
|
295
|
+
- name: abort
|
|
296
|
+
to: aborted
|
|
297
|
+
gates:
|
|
298
|
+
- type: human-approval
|
|
299
|
+
config: { id: abort-confirmation }
|
|
300
|
+
methods: {}
|
|
301
|
+
`,
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
exports.SoftwareFactoryModels = SoftwareFactoryModels;
|
|
306
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU29mdHdhcmVGYWN0b3J5TW9kZWxzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL1NvZnR3YXJlRmFjdG9yeU1vZGVscy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSxtQ0FBb0M7QUFDcEMsbUNBQW9DO0FBcUJwQzs7Ozs7R0FLRztBQUNILE1BQWEscUJBQXFCO0lBQ2hDLFlBQVksT0FBb0IsRUFBRSxPQUFxQztRQUNyRSxNQUFNLEVBQUUsUUFBUSxFQUFFLFdBQVcsRUFBRSxVQUFVLEVBQUUsR0FBRyxPQUFPLENBQUM7UUFDdEQsTUFBTSxJQUFJLEdBQUcsR0FBRyxXQUFXLElBQUksUUFBUSxFQUFFLENBQUM7UUFDMUMsTUFBTSxXQUFXLEdBQUcsR0FBRyxRQUFRLFNBQVMsQ0FBQztRQUN6QyxNQUFNLE9BQU8sR0FBRyxHQUFHLFFBQVEsS0FBSyxDQUFDO1FBQ2pDLE1BQU0sVUFBVSxHQUFHLEdBQUcsUUFBUSxRQUFRLENBQUM7UUFDdkMsTUFBTSxzQkFBc0IsR0FBRyxHQUFHLFFBQVEscUJBQXFCLENBQUM7UUFDaEUsTUFBTSxrQkFBa0IsR0FBRyxHQUFHLFFBQVEsaUJBQWlCLENBQUM7UUFDeEQsTUFBTSxZQUFZLEdBQUcsR0FBRyxRQUFRLFVBQVUsQ0FBQztRQUMzQyxNQUFNLFlBQVksR0FBRyxHQUFHLFFBQVEsVUFBVSxDQUFDO1FBRTNDLElBQUksbUJBQVUsQ0FBQyxPQUFPLEVBQUUsNEJBQTRCLE9BQU8sT0FBTyxFQUFFO1lBQ2xFLFFBQVEsRUFBRTs7TUFFVixJQUFBLG1CQUFVLEdBQUU7UUFDVixPQUFPOzs7OzJCQUlZLFlBQVk7V0FDNUIsV0FBVzs7Q0FFckI7U0FDSSxDQUFDLENBQUM7UUFFSCxJQUFJLG1CQUFVLENBQUMsT0FBTyxFQUFFLDJCQUEyQixXQUFXLE9BQU8sRUFBRTtZQUNyRSxRQUFRLEVBQUU7O01BRVYsSUFBQSxtQkFBVSxHQUFFO1FBQ1YsV0FBVzs7Ozs7Q0FLbEI7U0FDSSxDQUFDLENBQUM7UUFFSCxLQUFLLE1BQU0sSUFBSSxJQUFJLENBQUMsVUFBVSxFQUFFLHNCQUFzQixFQUFFLGtCQUFrQixDQUFDLEVBQUUsQ0FBQztZQUM1RSxJQUFJLG1CQUFVLENBQUMsT0FBTyxFQUFFLHdCQUF3QixJQUFJLE9BQU8sRUFBRTtnQkFDM0QsUUFBUSxFQUFFOztNQUVaLElBQUEsbUJBQVUsR0FBRTtRQUNWLElBQUk7Ozs7O0NBS1g7YUFDTSxDQUFDLENBQUM7UUFDTCxDQUFDO1FBRUQsSUFBSSxtQkFBVSxDQUFDLE9BQU8sRUFBRSxrQ0FBa0MsWUFBWSxPQUFPLEVBQUU7WUFDN0UsUUFBUSxFQUFFOztNQUVWLElBQUEsbUJBQVUsR0FBRTtRQUNWLFlBQVk7Ozs7Ozs7Ozs7Ozs7Ozs7OztZQWtCUixJQUFJLGNBQWMsV0FBVzs7WUFFN0IsV0FBVzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O3NEQXdLK0Isa0JBQWtCOzs7Ozs7Ozs7Ozs7Ozt1Q0FjakMsT0FBTztrQkFDNUIsSUFBSTsyQ0FDcUIsVUFBVTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0NBaUNwRDtTQUNJLENBQUMsQ0FBQztJQUNMLENBQUM7Q0FDRjtBQXhTRCxzREF3U0MiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyByYW5kb21VVUlEIH0gZnJvbSAnY3J5cHRvJztcbmltcG9ydCB7IFNhbXBsZUZpbGUgfSBmcm9tICdwcm9qZW4nO1xuaW1wb3J0IHsgTm9kZVByb2plY3QgfSBmcm9tICdwcm9qZW4vbGliL2phdmFzY3JpcHQnO1xuXG5leHBvcnQgaW50ZXJmYWNlIFNvZnR3YXJlRmFjdG9yeU1vZGVsc09wdGlvbnMge1xuICAvKipcbiAgICogVGhlIGJhcmUgcmVwbyBuYW1lIChlLmcuIGBleHBlbnNlLXRyYWNrZXJgKSwgdXNlZCB0byBkZXJpdmUgbW9kZWwgbmFtZXNcbiAgICogbGlrZSBgPHJlcG9OYW1lPi1mYWN0b3J5YCwgYDxyZXBvTmFtZT4tc2hlbGxgLCBgPHJlcG9OYW1lPi1zZWNyZXRzYC5cbiAgICovXG4gIHJlYWRvbmx5IHJlcG9OYW1lOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBHaXRIdWIgb3JnIHRoZSByZXBvIGxpdmVzIGluLlxuICAgKi9cbiAgcmVhZG9ubHkgZ2l0aHViT3duZXI6IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIGJyYW5jaCB0aGUgZmFjdG9yeSBvcGVucyBwdWxsIHJlcXVlc3RzIGFnYWluc3QuXG4gICAqL1xuICByZWFkb25seSBiYXNlQnJhbmNoOiBzdHJpbmc7XG59XG5cbi8qKlxuICogU2VlZCBzd2FtcCBtb2RlbCBpbnN0YW5jZXMgd2lyaW5nIHRoZSBgQHN3YW1wL3NvZnR3YXJlLWZhY3RvcnlgIHN0YXRlXG4gKiBtYWNoaW5lIHRvIHRoaXMgcmVwbydzIEdpdEh1YiBpc3N1ZXMvUFJzIGFuZCBzaGVsbCBzdGVwcy4gVGhlc2UgYXJlXG4gKiBgU2FtcGxlRmlsZWBzICh3cml0dGVuIG9uY2UsIHRoZW4gb3duZWQgYnkgdGhlIHRlYW0pIHNpbmNlIHRoZSBmYWN0b3J5J3NcbiAqIHN0YWdlcy9nYXRlcyBhcmUgdGhlIGtpbmQgb2YgdGhpbmcgYSB0ZWFtIHR1bmVzIGZvciBpdHMgb3duIHdvcmtmbG93LlxuICovXG5leHBvcnQgY2xhc3MgU29mdHdhcmVGYWN0b3J5TW9kZWxzIHtcbiAgY29uc3RydWN0b3IocHJvamVjdDogTm9kZVByb2plY3QsIG9wdGlvbnM6IFNvZnR3YXJlRmFjdG9yeU1vZGVsc09wdGlvbnMpIHtcbiAgICBjb25zdCB7IHJlcG9OYW1lLCBnaXRodWJPd25lciwgYmFzZUJyYW5jaCB9ID0gb3B0aW9ucztcbiAgICBjb25zdCByZXBvID0gYCR7Z2l0aHViT3duZXJ9LyR7cmVwb05hbWV9YDtcbiAgICBjb25zdCBpc3N1ZXNNb2RlbCA9IGAke3JlcG9OYW1lfS1pc3N1ZXNgO1xuICAgIGNvbnN0IHByTW9kZWwgPSBgJHtyZXBvTmFtZX0tcHJgO1xuICAgIGNvbnN0IHNoZWxsTW9kZWwgPSBgJHtyZXBvTmFtZX0tc2hlbGxgO1xuICAgIGNvbnN0IHNoZWxsQXJjaGl0ZWN0dXJlTW9kZWwgPSBgJHtyZXBvTmFtZX0tc2hlbGwtYXJjaGl0ZWN0dXJlYDtcbiAgICBjb25zdCBzaGVsbE1hbmlmZXN0TW9kZWwgPSBgJHtyZXBvTmFtZX0tc2hlbGwtbWFuaWZlc3RgO1xuICAgIGNvbnN0IHNlY3JldHNWYXVsdCA9IGAke3JlcG9OYW1lfS1zZWNyZXRzYDtcbiAgICBjb25zdCBmYWN0b3J5TW9kZWwgPSBgJHtyZXBvTmFtZX0tZmFjdG9yeWA7XG5cbiAgICBuZXcgU2FtcGxlRmlsZShwcm9qZWN0LCBgbW9kZWxzL0Bnb29kY3JhZnQvZ2l0aHViLyR7cHJNb2RlbH0ueWFtbGAsIHtcbiAgICAgIGNvbnRlbnRzOiBgdHlwZTogJ0Bnb29kY3JhZnQvZ2l0aHViJ1xudHlwZVZlcnNpb246IDIwMjYuMDYuMTQuMVxuaWQ6ICR7cmFuZG9tVVVJRCgpfVxubmFtZTogJHtwck1vZGVsfVxudmVyc2lvbjogMVxudGFnczoge31cbmdsb2JhbEFyZ3VtZW50czpcbiAgdG9rZW46ICdcXCR7eyB2YXVsdC5nZXQoJHtzZWNyZXRzVmF1bHR9LCBHSVRIVUJfVE9LRU4pIH19J1xuICBvd25lcjogJHtnaXRodWJPd25lcn1cbm1ldGhvZHM6IHt9XG5gLFxuICAgIH0pO1xuXG4gICAgbmV3IFNhbXBsZUZpbGUocHJvamVjdCwgYG1vZGVscy9Ad2ViZnJhbXAvZ2l0aHViLyR7aXNzdWVzTW9kZWx9LnlhbWxgLCB7XG4gICAgICBjb250ZW50czogYHR5cGU6ICdAd2ViZnJhbXAvZ2l0aHViJ1xudHlwZVZlcnNpb246IDIwMjYuMDguMjguMVxuaWQ6ICR7cmFuZG9tVVVJRCgpfVxubmFtZTogJHtpc3N1ZXNNb2RlbH1cbnZlcnNpb246IDFcbnRhZ3M6IHt9XG5nbG9iYWxBcmd1bWVudHM6IHt9XG5tZXRob2RzOiB7fVxuYCxcbiAgICB9KTtcblxuICAgIGZvciAoY29uc3QgbmFtZSBvZiBbc2hlbGxNb2RlbCwgc2hlbGxBcmNoaXRlY3R1cmVNb2RlbCwgc2hlbGxNYW5pZmVzdE1vZGVsXSkge1xuICAgICAgbmV3IFNhbXBsZUZpbGUocHJvamVjdCwgYG1vZGVscy9jb21tYW5kL3NoZWxsLyR7bmFtZX0ueWFtbGAsIHtcbiAgICAgICAgY29udGVudHM6IGB0eXBlOiBjb21tYW5kL3NoZWxsXG50eXBlVmVyc2lvbjogMjAyNi4wMi4wOS4xXG5pZDogJHtyYW5kb21VVUlEKCl9XG5uYW1lOiAke25hbWV9XG52ZXJzaW9uOiAxXG50YWdzOiB7fVxuZ2xvYmFsQXJndW1lbnRzOiB7fVxubWV0aG9kczoge31cbmAsXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBuZXcgU2FtcGxlRmlsZShwcm9qZWN0LCBgbW9kZWxzL0Bzd2FtcC9zb2Z0d2FyZS1mYWN0b3J5LyR7ZmFjdG9yeU1vZGVsfS55YW1sYCwge1xuICAgICAgY29udGVudHM6IGB0eXBlOiAnQHN3YW1wL3NvZnR3YXJlLWZhY3RvcnknXG50eXBlVmVyc2lvbjogMjAyNi4wNi4yNC4xXG5pZDogJHtyYW5kb21VVUlEKCl9XG5uYW1lOiAke2ZhY3RvcnlNb2RlbH1cbnZlcnNpb246IDFcbnRhZ3M6IHt9XG5yZXBvcnRzOlxuICByZXF1aXJlOlxuICAgIC0gbmFtZTogXCJAc3dhbXAvc29mdHdhcmUtZmFjdG9yeS93b3JrLWl0ZW0tc3VtbWFyeVwiXG4gICAgICBtZXRob2RzOiBbc3VtbWFyeV1cbmdsb2JhbEFyZ3VtZW50czpcbiAgc3RhZ2VzOlxuICAgIC0gaWQ6IGludGFrZVxuICAgICAgaW5pdGlhbDogdHJ1ZVxuICAgICAgZGVzY3JpcHRpb246ID4tXG4gICAgICAgIEZldGNoIHRoZSBHaXRIdWIgaXNzdWUgZm9yIHRoaXMgd29yayBpdGVtICh3b3JrSXRlbSBpcyB0aGUgYmFyZVxuICAgICAgICBpc3N1ZSBudW1iZXIpIGFuZCByZWNvcmQgaXRzIGNvbnRleHQuXG4gICAgICB3b3JrOlxuICAgICAgICBtb2RlOiBpbnRlcmFjdGl2ZVxuICAgICAgICBzeXN0ZW1Qcm9tcHQ6ID4tXG4gICAgICAgICAgRmV0Y2ggdGhlIEdpdEh1YiBpc3N1ZSBudW1iZXJlZCBcXCR7eyBzZWxmLndvcmtJdGVtIH19IGZvclxuICAgICAgICAgICR7cmVwb30gdXNpbmcgdGhlICR7aXNzdWVzTW9kZWx9IG1vZGVsXG4gICAgICAgICAgKGxpc3RfaXNzdWVzLCB0aGVuIHN3YW1wIGRhdGEgcXVlcnkgZmlsdGVyZWQgYnkgbnVtYmVyIOKAlCBzZWUgdGhlXG4gICAgICAgICAgJHtpc3N1ZXNNb2RlbH0gZGF0YSksIGFuZCByZWNvcmQgdGhlIGlzc3VlLWNvbnRleHQgYXJ0aWZhY3QuXG4gICAgICBhcnRpZmFjdHM6XG4gICAgICAgIC0gbmFtZTogaXNzdWUtY29udGV4dFxuICAgICAgICAgIHNjaGVtYTpcbiAgICAgICAgICAgIHR5cGU6IG9iamVjdFxuICAgICAgICAgICAgcmVxdWlyZWQ6IFtudW1iZXIsIHRpdGxlLCB1cmxdXG4gICAgICAgICAgICBwcm9wZXJ0aWVzOlxuICAgICAgICAgICAgICBudW1iZXI6IHsgdHlwZTogaW50ZWdlciB9XG4gICAgICAgICAgICAgIHRpdGxlOiB7IHR5cGU6IHN0cmluZywgbWluTGVuZ3RoOiAxIH1cbiAgICAgICAgICAgICAgYm9keTogeyB0eXBlOiBzdHJpbmcgfVxuICAgICAgICAgICAgICB1cmw6IHsgdHlwZTogc3RyaW5nLCBtaW5MZW5ndGg6IDEgfVxuICAgICAgICAgICAgICBsYWJlbHM6IHsgdHlwZTogYXJyYXksIGl0ZW1zOiB7IHR5cGU6IHN0cmluZyB9IH1cbiAgICAgIHRyYW5zaXRpb25zOlxuICAgICAgICAtIG5hbWU6IHN1Ym1pdFxuICAgICAgICAgIHRvOiBwbGFubmluZ1xuICAgICAgICAgIGdhdGVzOlxuICAgICAgICAgICAgLSB0eXBlOiBhcnRpZmFjdC1leGlzdHNcbiAgICAgICAgICAgICAgY29uZmlnOiB7IGFydGlmYWN0OiBpc3N1ZS1jb250ZXh0IH1cblxuICAgIC0gaWQ6IHBsYW5uaW5nXG4gICAgICBkZXNjcmlwdGlvbjogPi1cbiAgICAgICAgVHVybiB0aGUgaXNzdWUgaW50byBhIHJlYWwgT3BlblNwZWMgY2hhbmdlIChwcm9wb3NhbCwgZGVzaWduLFxuICAgICAgICBzcGVjcywgdGFza3MpIOKAlCBPcGVuU3BlYydzIHRhc2sgbGlzdCBpcyB0aGUgcGxhbiwgbm90IGFcbiAgICAgICAgZnJlZWZvcm0gYXJ0aWZhY3QuXG4gICAgICB3b3JrOlxuICAgICAgICBtb2RlOiBpbnRlcmFjdGl2ZVxuICAgICAgICBzeXN0ZW1Qcm9tcHQ6ID4tXG4gICAgICAgICAgVXNpbmcgdGhlIHJlY29yZGVkIGlzc3VlLWNvbnRleHQgYXJ0aWZhY3QsIHVzZSB0aGVcbiAgICAgICAgICBvcGVuc3BlYy1wcm9wb3NlIHNraWxsIHRvIGNyZWF0ZSBhIGNvbXBsZXRlIE9wZW5TcGVjIGNoYW5nZVxuICAgICAgICAgIChwcm9wb3NhbC5tZCwgZGVzaWduLm1kLCBzcGVjcyB3aXRoIGRlbHRhcywgdGFza3MubWQpIGZvciB0aGlzXG4gICAgICAgICAgd29yayBpdGVtIHVuZGVyIG9wZW5zcGVjL2NoYW5nZXMvPGNoYW5nZVNsdWc+LyDigJQgZG8gbm90IHdyaXRlIGFcbiAgICAgICAgICBmcmVlZm9ybSBwbGFuIGluc3RlYWQgb2YgdGhpcy4gVGhlbiByZWNvcmQgdGhlIHBsYW4gYXJ0aWZhY3RcbiAgICAgICAgICB3aXRoIHRoZSBjaGFuZ2UncyBzbHVnIGFuZCBhIG9uZS1saW5lIHN1bW1hcnkuXG4gICAgICBhcnRpZmFjdHM6XG4gICAgICAgIC0gbmFtZTogcGxhblxuICAgICAgICAgIHNjaGVtYTpcbiAgICAgICAgICAgIHR5cGU6IG9iamVjdFxuICAgICAgICAgICAgcmVxdWlyZWQ6IFtjaGFuZ2VTbHVnLCBzdW1tYXJ5XVxuICAgICAgICAgICAgcHJvcGVydGllczpcbiAgICAgICAgICAgICAgY2hhbmdlU2x1ZzogeyB0eXBlOiBzdHJpbmcsIG1pbkxlbmd0aDogMSB9XG4gICAgICAgICAgICAgIHN1bW1hcnk6IHsgdHlwZTogc3RyaW5nLCBtaW5MZW5ndGg6IDEgfVxuICAgICAgdHJhbnNpdGlvbnM6XG4gICAgICAgIC0gbmFtZTogc3VibWl0XG4gICAgICAgICAgdG86IG9wZW5zcGVjLXBsYW4tdmVyaWZ5XG4gICAgICAgICAgZ2F0ZXM6XG4gICAgICAgICAgICAtIHR5cGU6IGFydGlmYWN0LWV4aXN0c1xuICAgICAgICAgICAgICBjb25maWc6IHsgYXJ0aWZhY3Q6IHBsYW4gfVxuXG4gICAgLSBpZDogb3BlbnNwZWMtcGxhbi12ZXJpZnlcbiAgICAgIGRlc2NyaXB0aW9uOiA+LVxuICAgICAgICBWZXJpZnkgdGhlIE9wZW5TcGVjIGNoYW5nZSBpcyByZWFsIGFuZCB3ZWxsLWZvcm1lZCAobm90IGp1c3QgYW5cbiAgICAgICAgYXJ0aWZhY3QgY2xhaW1pbmcgb25lIGV4aXN0cykgYmVmb3JlIGltcGxlbWVudGF0aW9uIHN0YXJ0cy5cbiAgICAgIHdvcms6XG4gICAgICAgIG1vZGU6IHdvcmtmbG93XG4gICAgICAgIHdvcmtmbG93OlxuICAgICAgICAgIG5hbWU6IG9wZW5zcGVjLXBsYW4tdmVyaWZ5XG4gICAgICAgICAgaW5wdXRzOlxuICAgICAgICAgICAgY2hhbmdlU2x1ZzogJ1xcJHt7IGRhdGEubGF0ZXN0KHNlbGYubmFtZSwgXCJhcnRpZmFjdC1wbGFuXCIpLnBheWxvYWQuY2hhbmdlU2x1ZyB9fSdcbiAgICAgICAgcmVzdWx0RXZpZGVuY2U6IHBsYW4tdmVyaWZ5LXJ1blxuICAgICAgdHJhbnNpdGlvbnM6XG4gICAgICAgIC0gbmFtZTogcGFzc1xuICAgICAgICAgIHRvOiBpbXBsZW1lbnRpbmdcbiAgICAgICAgICBnYXRlczpcbiAgICAgICAgICAgIC0gdHlwZTogd29ya2Zsb3ctc3VjY2VlZGVkXG4gICAgICAgICAgICAgIGNvbmZpZzogeyB3b3JrZmxvdzogb3BlbnNwZWMtcGxhbi12ZXJpZnkgfVxuICAgICAgICAtIG5hbWU6IGZhaWxcbiAgICAgICAgICB0bzogcGxhbm5pbmdcbiAgICAgICAgICBnYXRlczpcbiAgICAgICAgICAgIC0gdHlwZTogZXZpZGVuY2UtcmVjb3JkZWRcbiAgICAgICAgICAgICAgY29uZmlnOiB7IG5hbWU6IHBsYW4tdmVyaWZ5LXJ1biwgcmVxdWlyZUZpZWxkOiB7IHN0YXR1czogZmFpbGVkIH0gfVxuXG4gICAgLSBpZDogaW1wbGVtZW50aW5nXG4gICAgICBkZXNjcmlwdGlvbjogSW1wbGVtZW50IHRoZSBPcGVuU3BlYyBjaGFuZ2UncyB0YXNrcyBvbiBhIGJyYW5jaC5cbiAgICAgIHdvcms6XG4gICAgICAgIG1vZGU6IGludGVyYWN0aXZlXG4gICAgICAgIHN5c3RlbVByb21wdDogPi1cbiAgICAgICAgICBVc2UgdGhlIG9wZW5zcGVjLWFwcGx5LWNoYW5nZSBza2lsbCBhZ2FpbnN0IHRoZSBjaGFuZ2UgcmVjb3JkZWRcbiAgICAgICAgICBpbiB0aGUgcGxhbiBhcnRpZmFjdCdzIGNoYW5nZVNsdWcg4oCUIHdvcmsgdGhyb3VnaCBpdHMgdGFza3MubWRcbiAgICAgICAgICBvbmUgdGFzayBhdCBhIHRpbWUsIGNoZWNraW5nIGVhY2ggb2ZmIChcXGAtIFsgXVxcYCAtPiBcXGAtIFt4XVxcYCkgYXNcbiAgICAgICAgICB5b3UgY29tcGxldGUgaXQsIHVudGlsIGV2ZXJ5IHRhc2sgaXMgZG9uZS4gQ29tbWl0IHRoZSB3b3JrIG9uIGFcbiAgICAgICAgICBmZWF0dXJlIGJyYW5jaC4gUmVjb3JkIHRoZSBjaGFuZ2Utc3VtbWFyeSBhcnRpZmFjdCBhbmQgdGhlXG4gICAgICAgICAgY2hhbmdlLXJlcXVlc3QgZXZpZGVuY2UgKGJyYW5jaCBuYW1lIGFuZCBoZWFkIGNvbW1pdCBzaGEg4oCUIG5vXG4gICAgICAgICAgUFIgeWV0LCB0aGF0IGhhcHBlbnMgYWZ0ZXIgcHJlLVBSIHZlcmlmaWNhdGlvbiBwYXNzZXMpLlxuICAgICAgYXJ0aWZhY3RzOlxuICAgICAgICAtIG5hbWU6IGNoYW5nZS1zdW1tYXJ5XG4gICAgICAgICAgc2NoZW1hOlxuICAgICAgICAgICAgdHlwZTogb2JqZWN0XG4gICAgICAgICAgICByZXF1aXJlZDogW3N1bW1hcnksIGhlYWRTaGFdXG4gICAgICAgICAgICBwcm9wZXJ0aWVzOlxuICAgICAgICAgICAgICBzdW1tYXJ5OiB7IHR5cGU6IHN0cmluZywgbWluTGVuZ3RoOiAxIH1cbiAgICAgICAgICAgICAgaGVhZFNoYTogeyB0eXBlOiBzdHJpbmcsIG1pbkxlbmd0aDogNyB9XG4gICAgICBldmlkZW5jZTpcbiAgICAgICAgLSBuYW1lOiBjaGFuZ2UtcmVxdWVzdFxuICAgICAgICAgIHNjaGVtYTpcbiAgICAgICAgICAgIHR5cGU6IG9iamVjdFxuICAgICAgICAgICAgcmVxdWlyZWQ6IFticmFuY2gsIGhlYWRTaGFdXG4gICAgICAgICAgICBwcm9wZXJ0aWVzOlxuICAgICAgICAgICAgICBicmFuY2g6IHsgdHlwZTogc3RyaW5nLCBtaW5MZW5ndGg6IDEgfVxuICAgICAgICAgICAgICBoZWFkU2hhOiB7IHR5cGU6IHN0cmluZywgbWluTGVuZ3RoOiA3IH1cbiAgICAgICAgICAgICAgdXJsOiB7IHR5cGU6IHN0cmluZyB9XG4gICAgICB0cmFuc2l0aW9uczpcbiAgICAgICAgLSBuYW1lOiBzdWJtaXRcbiAgICAgICAgICB0bzogb3BlbnNwZWMtdGFza3MtdmVyaWZ5XG4gICAgICAgICAgZ2F0ZXM6XG4gICAgICAgICAgICAtIHR5cGU6IGFydGlmYWN0LWV4aXN0c1xuICAgICAgICAgICAgICBjb25maWc6IHsgYXJ0aWZhY3Q6IGNoYW5nZS1zdW1tYXJ5IH1cbiAgICAgICAgICAgIC0gdHlwZTogZXZpZGVuY2UtcmVjb3JkZWRcbiAgICAgICAgICAgICAgY29uZmlnOiB7IG5hbWU6IGNoYW5nZS1yZXF1ZXN0IH1cblxuICAgIC0gaWQ6IG9wZW5zcGVjLXRhc2tzLXZlcmlmeVxuICAgICAgZGVzY3JpcHRpb246ID4tXG4gICAgICAgIFZlcmlmeSBldmVyeSB0YXNrIGluIHRoZSBPcGVuU3BlYyBjaGFuZ2UgaXMgYWN0dWFsbHkgY2hlY2tlZCBvZmZcbiAgICAgICAgYmVmb3JlIHByZS1QUiB2ZXJpZmljYXRpb24gcnVucy5cbiAgICAgIHdvcms6XG4gICAgICAgIG1vZGU6IHdvcmtmbG93XG4gICAgICAgIHdvcmtmbG93OlxuICAgICAgICAgIG5hbWU6IG9wZW5zcGVjLXRhc2tzLXZlcmlmeVxuICAgICAgICAgIGlucHV0czpcbiAgICAgICAgICAgIGNoYW5nZVNsdWc6ICdcXCR7eyBkYXRhLmxhdGVzdChzZWxmLm5hbWUsIFwiYXJ0aWZhY3QtcGxhblwiKS5wYXlsb2FkLmNoYW5nZVNsdWcgfX0nXG4gICAgICAgIHJlc3VsdEV2aWRlbmNlOiB0YXNrcy12ZXJpZnktcnVuXG4gICAgICB0cmFuc2l0aW9uczpcbiAgICAgICAgLSBuYW1lOiBwYXNzXG4gICAgICAgICAgdG86IHByZS1wci12ZXJpZnlcbiAgICAgICAgICBnYXRlczpcbiAgICAgICAgICAgIC0gdHlwZTogd29ya2Zsb3ctc3VjY2VlZGVkXG4gICAgICAgICAgICAgIGNvbmZpZzogeyB3b3JrZmxvdzogb3BlbnNwZWMtdGFza3MtdmVyaWZ5IH1cbiAgICAgICAgLSBuYW1lOiBmYWlsXG4gICAgICAgICAgdG86IGltcGxlbWVudGluZ1xuICAgICAgICAgIGdhdGVzOlxuICAgICAgICAgICAgLSB0eXBlOiBldmlkZW5jZS1yZWNvcmRlZFxuICAgICAgICAgICAgICBjb25maWc6IHsgbmFtZTogdGFza3MtdmVyaWZ5LXJ1biwgcmVxdWlyZUZpZWxkOiB7IHN0YXR1czogZmFpbGVkIH0gfVxuXG4gICAgLSBpZDogcHJlLXByLXZlcmlmeVxuICAgICAgZGVzY3JpcHRpb246ID4tXG4gICAgICAgIFByZS1QUiB2ZXJpZmljYXRpb246IGJ1aWxkL3N5bnRoL3Rlc3QvbGludCBwbHVzIHRoZSBhcmNoaXRlY3R1cmVcbiAgICAgICAgcnVsZSByZWdpc3RyeSwgcnVuIGJlZm9yZSB0aGUgUFIgaXMgb3BlbmVkIHJhdGhlciB0aGFuIHJlbHlpbmcgb25cbiAgICAgICAgQ0kgYWZ0ZXIgdGhlIGZhY3QuXG4gICAgICB3b3JrOlxuICAgICAgICBtb2RlOiB3b3JrZmxvd1xuICAgICAgICB3b3JrZmxvdzpcbiAgICAgICAgICBuYW1lOiBwcmUtcHItdmVyaWZ5XG4gICAgICAgICAgaW5wdXRzOlxuICAgICAgICAgICAgY29tbWl0OiAnXFwke3sgZGF0YS5sYXRlc3Qoc2VsZi5uYW1lLCBcImV2aWRlbmNlLWNoYW5nZS1yZXF1ZXN0XCIpLnBheWxvYWQuaGVhZFNoYSB9fSdcbiAgICAgICAgICAgIGJyYW5jaDogJ1xcJHt7IGRhdGEubGF0ZXN0KHNlbGYubmFtZSwgXCJldmlkZW5jZS1jaGFuZ2UtcmVxdWVzdFwiKS5wYXlsb2FkLmJyYW5jaCB9fSdcbiAgICAgICAgcmVzdWx0RXZpZGVuY2U6IHZlcmlmeS1ydW5cbiAgICAgIHRyYW5zaXRpb25zOlxuICAgICAgICAtIG5hbWU6IHBhc3NcbiAgICAgICAgICB0bzogb3Blbi1wclxuICAgICAgICAgIGdhdGVzOlxuICAgICAgICAgICAgLSB0eXBlOiB3b3JrZmxvdy1zdWNjZWVkZWRcbiAgICAgICAgICAgICAgY29uZmlnOiB7IHdvcmtmbG93OiBwcmUtcHItdmVyaWZ5IH1cbiAgICAgICAgLSBuYW1lOiBmYWlsXG4gICAgICAgICAgdG86IGltcGxlbWVudGluZ1xuICAgICAgICAgIGdhdGVzOlxuICAgICAgICAgICAgLSB0eXBlOiBldmlkZW5jZS1yZWNvcmRlZFxuICAgICAgICAgICAgICBjb25maWc6IHsgbmFtZTogdmVyaWZ5LXJ1biwgcmVxdWlyZUZpZWxkOiB7IHN0YXR1czogZmFpbGVkIH0gfVxuXG4gICAgLSBpZDogb3Blbi1wclxuICAgICAgZGVzY3JpcHRpb246IE9wZW4gdGhlIHB1bGwgcmVxdWVzdCBub3cgdGhhdCBwcmUtUFIgdmVyaWZpY2F0aW9uIGhhcyBwYXNzZWQuXG4gICAgICB3b3JrOlxuICAgICAgICBtb2RlOiBpbnRlcmFjdGl2ZVxuICAgICAgICBzeXN0ZW1Qcm9tcHQ6ID4tXG4gICAgICAgICAgQmVmb3JlIG9wZW5pbmcgdGhlIFBSLCBmZXRjaCB0aGUgcmVhbCBwcmUtcHItdmVyaWZ5IGF0dGVzdGF0aW9uXG4gICAgICAgICAgd2l0aCBcXGBzd2FtcCBkYXRhIGdldCAtLXdvcmtmbG93IHByZS1wci12ZXJpZnlcbiAgICAgICAgICByZXBvcnQtc3dhbXAtdmVyaWZpY2F0aW9uLWF0dGVzdGF0aW9uIC0tanNvblxcYCBhbmQgaW5jbHVkZSBpdHNcbiAgICAgICAgICBcXGBjb250ZW50XFxgIHZlcmJhdGltIChhcyBhIG1hcmtkb3duIGJsb2NrLCBlLmcuIHVuZGVyIGEgXCJQcmUtUFJcbiAgICAgICAgICB2ZXJpZmljYXRpb25cIiBoZWFkaW5nKSBpbiB0aGUgUFIgYm9keSDigJQgbmV2ZXIganVzdCBhc3NlcnQgaW5cbiAgICAgICAgICBwcm9zZSB0aGF0IGNoZWNrcyBwYXNzZWQuIEFsc28gZmV0Y2ggdGhpcyBzYW1lIHJ1bidzIG1hbmlmZXN0IHN0ZXBcbiAgICAgICAgICBvdXRwdXQgKFxcYHN3YW1wIGRhdGEgcXVlcnkgJ21vZGVsTmFtZSA9PSBcIiR7c2hlbGxNYW5pZmVzdE1vZGVsfVwiICYmXG4gICAgICAgICAgbmFtZSA9PSBcInJlc3VsdFwiJyAtLXNlbGVjdCBhdHRyaWJ1dGVzLnN0ZG91dCAtLWpzb25cXGAsIHRha2UgdGhlXG4gICAgICAgICAgbGF0ZXN0KSBhbmQgYXBwZW5kIGl0IHRvIHRoZSBQUiBib2R5IGFzXG4gICAgICAgICAgXFxgPCEtLSBhdHRlc3RhdGlvbi1tYW5pZmVzdCB7XCJjb21taXRcIjogXCI8aGVhZFNoYT5cIiwgXCJzdGF0dXNcIjpcbiAgICAgICAgICBcInN1Y2NlZWRlZFwiLCAuLi50aGUgbWFuaWZlc3Qgc3RlcCdzIEpTT04sIHNwcmVhZCBpbi4uLn0gLS0+XFxgIOKAlCBhblxuICAgICAgICAgIEhUTUwgY29tbWVudCBzbyBpdCdzIGludmlzaWJsZSB3aGVuIHJlbmRlcmVkIGJ1dCBzdGlsbCBwcmVzZW50IGluXG4gICAgICAgICAgdGhlIHJhdyBib2R5IHRleHQgdmVyaWZ5LWF0dGVzdGF0aW9uLnltbCByZWFkcyB2aWEgdGhlIEdpdEh1YiBBUEkuXG4gICAgICAgICAgQWxzbyBmZXRjaCB0aGUgcGxhbiBhcnRpZmFjdCdzIGNoYW5nZVNsdWcgYW5kIGluY2x1ZGUgYW4gZXhwbGljaXRcbiAgICAgICAgICBcIk9wZW5TcGVjIGNoYW5nZVwiIGxpbmUgaW4gdGhlIFBSIGJvZHkgbmFtaW5nIGl0IGFuZCBpdHMgcGF0aFxuICAgICAgICAgIChcXGBvcGVuc3BlYy9jaGFuZ2VzLzxjaGFuZ2VTbHVnPi9cXGApIOKAlCBldmVyeSBQUiB0aGUgZmFjdG9yeSBvcGVuc1xuICAgICAgICAgIG11c3QgY2FsbCBvdXQgd2hpY2ggT3BlblNwZWMgY2hhbmdlKHMpIGRyb3ZlIHRoZSBzZXNzaW9uLCBub3RcbiAgICAgICAgICBqdXN0IGltcGx5IGl0LiBJZiBwbGFubmluZyBjeWNsZWQgdGhyb3VnaCBtb3JlIHRoYW4gb25lIGNoYW5nZVxuICAgICAgICAgIChhIHJld29yayBsb29wIHByb2R1Y2VkIGEgbmV3IGNoYW5nZVNsdWcpLCBsaXN0IGV2ZXJ5IGRpc3RpbmN0XG4gICAgICAgICAgY2hhbmdlU2x1ZyByZWNvcmRlZCBhY3Jvc3MgdGhlIHJ1bidzIHBsYW4gYXJ0aWZhY3QgdmVyc2lvbnMsIG5vdFxuICAgICAgICAgIG9ubHkgdGhlIGxhdGVzdC4gVGhlbiBjYWxsICR7cHJNb2RlbH0ncyBvcGVuUHIgbWV0aG9kXG4gICAgICAgICAgKHJlcG89JHtyZXBvfSwgaGVhZD08dGhlIGJyYW5jaCByZWNvcmRlZCBpblxuICAgICAgICAgIGNoYW5nZS1yZXF1ZXN0IGV2aWRlbmNlPiwgYmFzZT0ke2Jhc2VCcmFuY2h9LCBkcnlSdW49ZmFsc2UpLCB3aXRoXG4gICAgICAgICAgdGl0bGUvYm9keSByZWZlcmVuY2luZyB0aGUgaW50YWtlIHN0YWdlJ3MgaXNzdWUgbnVtYmVyLCB0aGVcbiAgICAgICAgICBPcGVuU3BlYyBjaGFuZ2UocyksIHRoZSBhdHRlc3RhdGlvbiBibG9jaywgYW5kIHRoZSBtYW5pZmVzdFxuICAgICAgICAgIGNvbW1lbnQsIHRoZW4gcmVjb3JkIHRoZSBwci1vcGVuZWQgZXZpZGVuY2Ugd2l0aCB0aGUgcmV0dXJuZWQgUFJcbiAgICAgICAgICB1cmwgYW5kIG51bWJlci5cbiAgICAgIGV2aWRlbmNlOlxuICAgICAgICAtIG5hbWU6IHByLW9wZW5lZFxuICAgICAgICAgIHNjaGVtYTpcbiAgICAgICAgICAgIHR5cGU6IG9iamVjdFxuICAgICAgICAgICAgcmVxdWlyZWQ6IFt1cmwsIG51bWJlcl1cbiAgICAgICAgICAgIHByb3BlcnRpZXM6XG4gICAgICAgICAgICAgIHVybDogeyB0eXBlOiBzdHJpbmcsIG1pbkxlbmd0aDogMSB9XG4gICAgICAgICAgICAgIG51bWJlcjogeyB0eXBlOiBpbnRlZ2VyIH1cbiAgICAgIHRyYW5zaXRpb25zOlxuICAgICAgICAtIG5hbWU6IHN1Ym1pdFxuICAgICAgICAgIHRvOiBkb25lXG4gICAgICAgICAgZ2F0ZXM6XG4gICAgICAgICAgICAtIHR5cGU6IGV2aWRlbmNlLXJlY29yZGVkXG4gICAgICAgICAgICAgIGNvbmZpZzogeyBuYW1lOiBwci1vcGVuZWQgfVxuXG4gICAgLSBpZDogZG9uZVxuICAgICAgdGVybWluYWw6IHRydWVcblxuICAgIC0gaWQ6IGFib3J0ZWRcbiAgICAgIHRlcm1pbmFsOiB0cnVlXG5cbiAgZ2xvYmFsVHJhbnNpdGlvbnM6XG4gICAgLSBuYW1lOiBhYm9ydFxuICAgICAgdG86IGFib3J0ZWRcbiAgICAgIGdhdGVzOlxuICAgICAgICAtIHR5cGU6IGh1bWFuLWFwcHJvdmFsXG4gICAgICAgICAgY29uZmlnOiB7IGlkOiBhYm9ydC1jb25maXJtYXRpb24gfVxubWV0aG9kczoge31cbmAsXG4gICAgfSk7XG4gIH1cbn1cbiJdfQ==
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { NodeProject } from 'projen/lib/javascript';
|
|
2
|
+
/**
|
|
3
|
+
* Deterministic gate: fails unless every task in the named OpenSpec change's
|
|
4
|
+
* tasks.md is checked off. Fully generic — no per-repo parameterization.
|
|
5
|
+
*/
|
|
6
|
+
export declare class SoftwareFactoryOpenSpecGates {
|
|
7
|
+
constructor(project: NodeProject);
|
|
8
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SoftwareFactoryOpenSpecGates = void 0;
|
|
4
|
+
const projen_1 = require("projen");
|
|
5
|
+
/**
|
|
6
|
+
* Deterministic gate: fails unless every task in the named OpenSpec change's
|
|
7
|
+
* tasks.md is checked off. Fully generic — no per-repo parameterization.
|
|
8
|
+
*/
|
|
9
|
+
class SoftwareFactoryOpenSpecGates {
|
|
10
|
+
constructor(project) {
|
|
11
|
+
new projen_1.TextFile(project, 'openspec-gates/check-tasks-complete.ts', {
|
|
12
|
+
marker: true,
|
|
13
|
+
lines: [
|
|
14
|
+
'/**',
|
|
15
|
+
' * Gate: fails unless every task in the named OpenSpec change\'s tasks.md is',
|
|
16
|
+
' * checked off. `openspec validate`/`openspec status` don\'t check this (an',
|
|
17
|
+
' * in-progress change is a normal, valid state) — this is the deterministic',
|
|
18
|
+
' * check the pre-pr pipeline needs before letting implementation proceed.',
|
|
19
|
+
' */',
|
|
20
|
+
"import { execFileSync } from 'node:child_process';",
|
|
21
|
+
'',
|
|
22
|
+
'interface OpenSpecChangeSummary {',
|
|
23
|
+
' name: string;',
|
|
24
|
+
' completedTasks: number;',
|
|
25
|
+
' totalTasks: number;',
|
|
26
|
+
' status: string;',
|
|
27
|
+
'}',
|
|
28
|
+
'',
|
|
29
|
+
'function main(): number {',
|
|
30
|
+
' // pnpm\'s `-- <args>` forwarding (and projen\'s receiveArgs) can pass a',
|
|
31
|
+
' // literal "--" through as an argv token ahead of the real argument.',
|
|
32
|
+
" const slug = process.argv.slice(2).find((arg) => arg !== '--');",
|
|
33
|
+
' if (!slug) {',
|
|
34
|
+
" console.error('Usage: check-tasks-complete <change-slug>');",
|
|
35
|
+
' return 1;',
|
|
36
|
+
' }',
|
|
37
|
+
'',
|
|
38
|
+
" const raw = execFileSync('openspec', ['list', '--json'], { encoding: 'utf8' });",
|
|
39
|
+
' const { changes } = JSON.parse(raw) as { changes: OpenSpecChangeSummary[] };',
|
|
40
|
+
' const change = changes.find((c) => c.name === slug);',
|
|
41
|
+
'',
|
|
42
|
+
' if (!change) {',
|
|
43
|
+
' console.error(`OpenSpec change "${slug}" not found (openspec list --json)`);',
|
|
44
|
+
' return 1;',
|
|
45
|
+
' }',
|
|
46
|
+
" if (change.status !== 'complete') {",
|
|
47
|
+
' console.error(',
|
|
48
|
+
' `OpenSpec change "${slug}" has incomplete tasks: ${change.completedTasks}/${change.totalTasks}`,',
|
|
49
|
+
' );',
|
|
50
|
+
' return 1;',
|
|
51
|
+
' }',
|
|
52
|
+
'',
|
|
53
|
+
' console.log(`OpenSpec change "${slug}": all ${change.totalTasks} tasks complete`);',
|
|
54
|
+
' return 0;',
|
|
55
|
+
'}',
|
|
56
|
+
'',
|
|
57
|
+
'process.exit(main());',
|
|
58
|
+
],
|
|
59
|
+
});
|
|
60
|
+
new projen_1.JsonFile(project, 'openspec-gates/tsconfig.json', {
|
|
61
|
+
marker: false,
|
|
62
|
+
obj: {
|
|
63
|
+
extends: '../tsconfig.json',
|
|
64
|
+
compilerOptions: {
|
|
65
|
+
noEmit: true,
|
|
66
|
+
rootDir: '.',
|
|
67
|
+
},
|
|
68
|
+
include: ['*.ts'],
|
|
69
|
+
exclude: ['node_modules'],
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
exports.SoftwareFactoryOpenSpecGates = SoftwareFactoryOpenSpecGates;
|
|
75
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU29mdHdhcmVGYWN0b3J5T3BlblNwZWNHYXRlcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9Tb2Z0d2FyZUZhY3RvcnlPcGVuU3BlY0dhdGVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLG1DQUE0QztBQUc1Qzs7O0dBR0c7QUFDSCxNQUFhLDRCQUE0QjtJQUN2QyxZQUFZLE9BQW9CO1FBQzlCLElBQUksaUJBQVEsQ0FBQyxPQUFPLEVBQUUsd0NBQXdDLEVBQUU7WUFDOUQsTUFBTSxFQUFFLElBQUk7WUFDWixLQUFLLEVBQUU7Z0JBQ0wsS0FBSztnQkFDTCw4RUFBOEU7Z0JBQzlFLDZFQUE2RTtnQkFDN0UsNkVBQTZFO2dCQUM3RSwyRUFBMkU7Z0JBQzNFLEtBQUs7Z0JBQ0wsb0RBQW9EO2dCQUNwRCxFQUFFO2dCQUNGLG1DQUFtQztnQkFDbkMsaUJBQWlCO2dCQUNqQiwyQkFBMkI7Z0JBQzNCLHVCQUF1QjtnQkFDdkIsbUJBQW1CO2dCQUNuQixHQUFHO2dCQUNILEVBQUU7Z0JBQ0YsMkJBQTJCO2dCQUMzQiw0RUFBNEU7Z0JBQzVFLHdFQUF3RTtnQkFDeEUsbUVBQW1FO2dCQUNuRSxnQkFBZ0I7Z0JBQ2hCLGlFQUFpRTtnQkFDakUsZUFBZTtnQkFDZixLQUFLO2dCQUNMLEVBQUU7Z0JBQ0YsbUZBQW1GO2dCQUNuRixnRkFBZ0Y7Z0JBQ2hGLHdEQUF3RDtnQkFDeEQsRUFBRTtnQkFDRixrQkFBa0I7Z0JBQ2xCLGtGQUFrRjtnQkFDbEYsZUFBZTtnQkFDZixLQUFLO2dCQUNMLHVDQUF1QztnQkFDdkMsb0JBQW9CO2dCQUNwQix3R0FBd0c7Z0JBQ3hHLFFBQVE7Z0JBQ1IsZUFBZTtnQkFDZixLQUFLO2dCQUNMLEVBQUU7Z0JBQ0Ysc0ZBQXNGO2dCQUN0RixhQUFhO2dCQUNiLEdBQUc7Z0JBQ0gsRUFBRTtnQkFDRix1QkFBdUI7YUFDeEI7U0FDRixDQUFDLENBQUM7UUFFSCxJQUFJLGlCQUFRLENBQUMsT0FBTyxFQUFFLDhCQUE4QixFQUFFO1lBQ3BELE1BQU0sRUFBRSxLQUFLO1lBQ2IsR0FBRyxFQUFFO2dCQUNILE9BQU8sRUFBRSxrQkFBa0I7Z0JBQzNCLGVBQWUsRUFBRTtvQkFDZixNQUFNLEVBQUUsSUFBSTtvQkFDWixPQUFPLEVBQUUsR0FBRztpQkFDYjtnQkFDRCxPQUFPLEVBQUUsQ0FBQyxNQUFNLENBQUM7Z0JBQ2pCLE9BQU8sRUFBRSxDQUFDLGNBQWMsQ0FBQzthQUMxQjtTQUNGLENBQUMsQ0FBQztJQUNMLENBQUM7Q0FDRjtBQWpFRCxvRUFpRUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBKc29uRmlsZSwgVGV4dEZpbGUgfSBmcm9tICdwcm9qZW4nO1xuaW1wb3J0IHsgTm9kZVByb2plY3QgfSBmcm9tICdwcm9qZW4vbGliL2phdmFzY3JpcHQnO1xuXG4vKipcbiAqIERldGVybWluaXN0aWMgZ2F0ZTogZmFpbHMgdW5sZXNzIGV2ZXJ5IHRhc2sgaW4gdGhlIG5hbWVkIE9wZW5TcGVjIGNoYW5nZSdzXG4gKiB0YXNrcy5tZCBpcyBjaGVja2VkIG9mZi4gRnVsbHkgZ2VuZXJpYyDigJQgbm8gcGVyLXJlcG8gcGFyYW1ldGVyaXphdGlvbi5cbiAqL1xuZXhwb3J0IGNsYXNzIFNvZnR3YXJlRmFjdG9yeU9wZW5TcGVjR2F0ZXMge1xuICBjb25zdHJ1Y3Rvcihwcm9qZWN0OiBOb2RlUHJvamVjdCkge1xuICAgIG5ldyBUZXh0RmlsZShwcm9qZWN0LCAnb3BlbnNwZWMtZ2F0ZXMvY2hlY2stdGFza3MtY29tcGxldGUudHMnLCB7XG4gICAgICBtYXJrZXI6IHRydWUsXG4gICAgICBsaW5lczogW1xuICAgICAgICAnLyoqJyxcbiAgICAgICAgJyAqIEdhdGU6IGZhaWxzIHVubGVzcyBldmVyeSB0YXNrIGluIHRoZSBuYW1lZCBPcGVuU3BlYyBjaGFuZ2VcXCdzIHRhc2tzLm1kIGlzJyxcbiAgICAgICAgJyAqIGNoZWNrZWQgb2ZmLiBgb3BlbnNwZWMgdmFsaWRhdGVgL2BvcGVuc3BlYyBzdGF0dXNgIGRvblxcJ3QgY2hlY2sgdGhpcyAoYW4nLFxuICAgICAgICAnICogaW4tcHJvZ3Jlc3MgY2hhbmdlIGlzIGEgbm9ybWFsLCB2YWxpZCBzdGF0ZSkg4oCUIHRoaXMgaXMgdGhlIGRldGVybWluaXN0aWMnLFxuICAgICAgICAnICogY2hlY2sgdGhlIHByZS1wciBwaXBlbGluZSBuZWVkcyBiZWZvcmUgbGV0dGluZyBpbXBsZW1lbnRhdGlvbiBwcm9jZWVkLicsXG4gICAgICAgICcgKi8nLFxuICAgICAgICBcImltcG9ydCB7IGV4ZWNGaWxlU3luYyB9IGZyb20gJ25vZGU6Y2hpbGRfcHJvY2Vzcyc7XCIsXG4gICAgICAgICcnLFxuICAgICAgICAnaW50ZXJmYWNlIE9wZW5TcGVjQ2hhbmdlU3VtbWFyeSB7JyxcbiAgICAgICAgJyAgbmFtZTogc3RyaW5nOycsXG4gICAgICAgICcgIGNvbXBsZXRlZFRhc2tzOiBudW1iZXI7JyxcbiAgICAgICAgJyAgdG90YWxUYXNrczogbnVtYmVyOycsXG4gICAgICAgICcgIHN0YXR1czogc3RyaW5nOycsXG4gICAgICAgICd9JyxcbiAgICAgICAgJycsXG4gICAgICAgICdmdW5jdGlvbiBtYWluKCk6IG51bWJlciB7JyxcbiAgICAgICAgJyAgLy8gcG5wbVxcJ3MgYC0tIDxhcmdzPmAgZm9yd2FyZGluZyAoYW5kIHByb2plblxcJ3MgcmVjZWl2ZUFyZ3MpIGNhbiBwYXNzIGEnLFxuICAgICAgICAnICAvLyBsaXRlcmFsIFwiLS1cIiB0aHJvdWdoIGFzIGFuIGFyZ3YgdG9rZW4gYWhlYWQgb2YgdGhlIHJlYWwgYXJndW1lbnQuJyxcbiAgICAgICAgXCIgIGNvbnN0IHNsdWcgPSBwcm9jZXNzLmFyZ3Yuc2xpY2UoMikuZmluZCgoYXJnKSA9PiBhcmcgIT09ICctLScpO1wiLFxuICAgICAgICAnICBpZiAoIXNsdWcpIHsnLFxuICAgICAgICBcIiAgICBjb25zb2xlLmVycm9yKCdVc2FnZTogY2hlY2stdGFza3MtY29tcGxldGUgPGNoYW5nZS1zbHVnPicpO1wiLFxuICAgICAgICAnICAgIHJldHVybiAxOycsXG4gICAgICAgICcgIH0nLFxuICAgICAgICAnJyxcbiAgICAgICAgXCIgIGNvbnN0IHJhdyA9IGV4ZWNGaWxlU3luYygnb3BlbnNwZWMnLCBbJ2xpc3QnLCAnLS1qc29uJ10sIHsgZW5jb2Rpbmc6ICd1dGY4JyB9KTtcIixcbiAgICAgICAgJyAgY29uc3QgeyBjaGFuZ2VzIH0gPSBKU09OLnBhcnNlKHJhdykgYXMgeyBjaGFuZ2VzOiBPcGVuU3BlY0NoYW5nZVN1bW1hcnlbXSB9OycsXG4gICAgICAgICcgIGNvbnN0IGNoYW5nZSA9IGNoYW5nZXMuZmluZCgoYykgPT4gYy5uYW1lID09PSBzbHVnKTsnLFxuICAgICAgICAnJyxcbiAgICAgICAgJyAgaWYgKCFjaGFuZ2UpIHsnLFxuICAgICAgICAnICAgIGNvbnNvbGUuZXJyb3IoYE9wZW5TcGVjIGNoYW5nZSBcIiR7c2x1Z31cIiBub3QgZm91bmQgKG9wZW5zcGVjIGxpc3QgLS1qc29uKWApOycsXG4gICAgICAgICcgICAgcmV0dXJuIDE7JyxcbiAgICAgICAgJyAgfScsXG4gICAgICAgIFwiICBpZiAoY2hhbmdlLnN0YXR1cyAhPT0gJ2NvbXBsZXRlJykge1wiLFxuICAgICAgICAnICAgIGNvbnNvbGUuZXJyb3IoJyxcbiAgICAgICAgJyAgICAgIGBPcGVuU3BlYyBjaGFuZ2UgXCIke3NsdWd9XCIgaGFzIGluY29tcGxldGUgdGFza3M6ICR7Y2hhbmdlLmNvbXBsZXRlZFRhc2tzfS8ke2NoYW5nZS50b3RhbFRhc2tzfWAsJyxcbiAgICAgICAgJyAgICApOycsXG4gICAgICAgICcgICAgcmV0dXJuIDE7JyxcbiAgICAgICAgJyAgfScsXG4gICAgICAgICcnLFxuICAgICAgICAnICBjb25zb2xlLmxvZyhgT3BlblNwZWMgY2hhbmdlIFwiJHtzbHVnfVwiOiBhbGwgJHtjaGFuZ2UudG90YWxUYXNrc30gdGFza3MgY29tcGxldGVgKTsnLFxuICAgICAgICAnICByZXR1cm4gMDsnLFxuICAgICAgICAnfScsXG4gICAgICAgICcnLFxuICAgICAgICAncHJvY2Vzcy5leGl0KG1haW4oKSk7JyxcbiAgICAgIF0sXG4gICAgfSk7XG5cbiAgICBuZXcgSnNvbkZpbGUocHJvamVjdCwgJ29wZW5zcGVjLWdhdGVzL3RzY29uZmlnLmpzb24nLCB7XG4gICAgICBtYXJrZXI6IGZhbHNlLFxuICAgICAgb2JqOiB7XG4gICAgICAgIGV4dGVuZHM6ICcuLi90c2NvbmZpZy5qc29uJyxcbiAgICAgICAgY29tcGlsZXJPcHRpb25zOiB7XG4gICAgICAgICAgbm9FbWl0OiB0cnVlLFxuICAgICAgICAgIHJvb3REaXI6ICcuJyxcbiAgICAgICAgfSxcbiAgICAgICAgaW5jbHVkZTogWycqLnRzJ10sXG4gICAgICAgIGV4Y2x1ZGU6IFsnbm9kZV9tb2R1bGVzJ10sXG4gICAgICB9LFxuICAgIH0pO1xuICB9XG59XG4iXX0=
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { NodeProject } from 'projen/lib/javascript';
|
|
2
|
+
import { WorkflowActionVersions } from './WorkflowActionVersions';
|
|
3
|
+
export interface SoftwareFactoryWorkflowsOptions {
|
|
4
|
+
/**
|
|
5
|
+
* The bare repo name, used to derive the `<repoName>-shell[-architecture|-manifest]`
|
|
6
|
+
* model names these workflows dispatch shell commands through.
|
|
7
|
+
*/
|
|
8
|
+
readonly repoName: string;
|
|
9
|
+
/**
|
|
10
|
+
* Overrides for the pinned action versions used by `verify-attestation.yml`.
|
|
11
|
+
*/
|
|
12
|
+
readonly actionVersions?: WorkflowActionVersions;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* The 3 swamp workflows the factory's gate stages run (openspec-plan-verify,
|
|
16
|
+
* openspec-tasks-verify, pre-pr-verify), plus the GitHub Action that
|
|
17
|
+
* re-verifies a PR's embedded attestation at merge time.
|
|
18
|
+
*
|
|
19
|
+
* The swamp workflow YAMLs carry a swamp-assigned `id` that must stay stable
|
|
20
|
+
* across synths (swamp uses it as the workflow's identity), so — like the
|
|
21
|
+
* model instances in `SoftwareFactoryModels` — they're `SampleFile`s, written
|
|
22
|
+
* once and then owned by the team. `verify-attestation.yml` has no such
|
|
23
|
+
* identity constraint and is a plain GitHub Actions workflow, so it's built
|
|
24
|
+
* the same managed way `PrDeployWorkflow` is.
|
|
25
|
+
*/
|
|
26
|
+
export declare class SoftwareFactoryWorkflows {
|
|
27
|
+
constructor(project: NodeProject, options: SoftwareFactoryWorkflowsOptions);
|
|
28
|
+
}
|