@patronage/factory-ci 1.0.0-alpha.16 → 1.0.0-alpha.18
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/README.md +100 -1
- package/dist/index.d.ts +287 -2
- package/dist/index.js +808 -127
- package/package.json +1 -1
- package/src/candidate-impact-workflow.ts +2 -0
- package/src/execute-alchemy-entry.ts +84 -6
- package/src/index.ts +40 -0
- package/src/lifecycle-contract-lane.ts +113 -0
- package/src/preview-cleanup-topology.ts +115 -0
- package/src/preview-proof-inventory.ts +987 -0
- package/src/preview-proof-lifecycle.ts +316 -0
package/README.md
CHANGED
|
@@ -197,6 +197,65 @@ Trust boundary: candidate routing is a cost control inside the pull request's ow
|
|
|
197
197
|
|
|
198
198
|
The step calls `psf candidate:impact` with the pull request's exact `base` and `head` commits (`github.event.pull_request.base.sha` / `head.sha` by default) and classifies the merge-base-to-head delta. It is `continue-on-error`, and every generated target condition keeps work demanded unless the command succeeded, reported a usable decision, and explicitly withdrew that target — unreadable identity, malformed or unsupported graph data, and classifier refusal all route to full demand. The decision checkout must check out the exact head commit with full history (`fetchDepth: 0`, `ref` = the head SHA); the default merge-ref checkout refuses withdrawal because the head is not `HEAD`. Surface job names, runners, commands, and credentials stay with the consumer, and `factoryProductionImpactWorkflow` keeps its merge-push contract unchanged.
|
|
199
199
|
|
|
200
|
+
The non-credentialed lifecycle-contract lane follows the same ownership line through `factoryLifecycleContractLane` (#765). Presence is a profile declaration (`lifecycleContract` in `software-factory.profile.json`); this package never loads the profile. Pass the parsed object, or omit it, and include or skip the returned job:
|
|
201
|
+
|
|
202
|
+
```ts
|
|
203
|
+
const lane = factoryLifecycleContractLane(profile.lifecycleContract);
|
|
204
|
+
|
|
205
|
+
const jobs = [
|
|
206
|
+
core,
|
|
207
|
+
...(lane
|
|
208
|
+
? [
|
|
209
|
+
job(lane.jobId, {
|
|
210
|
+
name: lane.jobName,
|
|
211
|
+
permissions: { contents: "read" },
|
|
212
|
+
steps: [...setupSteps, ...lane.steps],
|
|
213
|
+
}),
|
|
214
|
+
]
|
|
215
|
+
: []),
|
|
216
|
+
];
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
When declared, the helper returns job id `factory-contracts`, display name `Factory / Alchemy Contracts` (overridable), a `run:` step that is exactly the declared package-script command, and an `always()` evidence summary that states what the lane proves and that it does not prove live deploy, D1, smoke, convergence, or cleanup. When omitted, the helper returns `undefined` and the caller emits no such job.
|
|
220
|
+
|
|
221
|
+
**Command contract.** Consumers expose a root package script and declare its invocation in the profile. The conventional name is `test:factory`:
|
|
222
|
+
|
|
223
|
+
```json
|
|
224
|
+
{
|
|
225
|
+
"lifecycleContract": {
|
|
226
|
+
"command": "pnpm test:factory"
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
Hosted CI runs that package script only. The allowed grammar is `pnpm run <script>` (and the npm/yarn/bun `run` equivalents) or a shorthand whose script name contains `:` (`pnpm test:factory`). Optional pnpm `--filter <pkg>` may precede either form. A bare manager verb (`pnpm create`, `npm init`) is not a script invocation. Shell operators, GitHub expressions, `secrets.`, Cloudflare/Alchemy credential env, extra flags, and direct Vitest are refused. The generated job and steps carry no `secrets.`, no Cloudflare or Alchemy password env, and no GitHub `environment:` that would inject deploy credentials. The lane must stay green in fork and no-secret contexts. Setup, runners, job `if:` conditions, and topology stay with the caller. The contract suites themselves stay consumer-owned.
|
|
232
|
+
|
|
233
|
+
The preview-cleanup residue audit follows the same ownership line through `factoryPreviewCleanupTopology` (#764). Callers pass the stack names and the whole-stage audit command; this package never loads a profile and never decides what counts as residue. Destroy _steps_ stay consumer-owned. The helper returns one destroy job id per stack and exactly one audit job whose `needs` lists every destroy:
|
|
234
|
+
|
|
235
|
+
```ts
|
|
236
|
+
const topology = factoryPreviewCleanupTopology({
|
|
237
|
+
stacks: ["website", "loop"],
|
|
238
|
+
audit: { command: "assert-stage-absent" },
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
const jobs = [
|
|
242
|
+
...topology.destroyJobs.map((destroy) =>
|
|
243
|
+
job(destroy.jobId, {
|
|
244
|
+
name: `Destroy ${destroy.stack}`,
|
|
245
|
+
steps: [...setupSteps, consumerDestroy(destroy.stack)],
|
|
246
|
+
})
|
|
247
|
+
),
|
|
248
|
+
job(topology.auditJob.jobId, {
|
|
249
|
+
name: topology.auditJob.jobName,
|
|
250
|
+
if: topology.auditJob.if,
|
|
251
|
+
needs: topology.auditJob.needs,
|
|
252
|
+
steps: [...setupSteps, ...topology.auditJob.steps],
|
|
253
|
+
}),
|
|
254
|
+
];
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
The audit job is `always()` so a failed destroy still runs the stage-wide check. It does not receive a stack name or path filter — per-stack audit filters are rejected because they trade away the whole-stage guarantee (paitronage#1143). `previewCleanupDestroyJobId(stack)` is the same id mapping callers can use when they assemble destroy jobs by hand.
|
|
258
|
+
|
|
200
259
|
### Generated shell
|
|
201
260
|
|
|
202
261
|
```ts
|
|
@@ -282,7 +341,7 @@ import { bundleAlchemyEntry, executeAlchemyEntry } from "@patronage/factory-ci";
|
|
|
282
341
|
|
|
283
342
|
`alias` is a specifier-to-target map handed to esbuild. Substitution runs before the `packages` and `external` decisions, so an aliased bare specifier is inlined even under `packages: "external"` — that is how a repo points a workspace-only or duplicated package at one file. Give absolute paths or package names; which aliases a repo needs is consumer policy and this package ships no defaults. `executeAlchemyEntry` passes its whole `bundle` option through, so the map is available there too. Because substitution runs first, an alias on `alchemy`, `effect`, or any of their subpaths would silently defeat the externals and bundle a second copy, so those keys are rejected outright. Targets are not string-matched — no rule over how a path is spelled can survive `..` segments or symlinks — so instead the build's metafile is checked afterwards and the bundle is rejected if it carries any input from a reserved package, however that file was reached. A consumer shim that re-exports `effect` by bare specifier stays external naturally and is allowed.
|
|
284
343
|
|
|
285
|
-
`executeAlchemyEntry({ from, bundle, args, ... })` owns the repeated choreography: resolve the consumer's Alchemy CLI from `from`, bundle the entry, run that CLI under the current Node binary with the absolute bundled entry appended, and throw on spawn errors, signals, missing statuses, or non-zero exits. It returns only after status 0.
|
|
344
|
+
`executeAlchemyEntry({ from, bundle, args, ... })` owns the repeated choreography: resolve the consumer's Alchemy CLI from `from`, bundle the entry, run that CLI under the current Node binary with the absolute bundled entry appended, and throw on spawn errors, signals, missing statuses, or non-zero exits. It returns only after status 0. Pass `bundledEntry` (absolute or cwd-relative) to skip the bundle step and reuse a path from a prior `bundleAlchemyEntry` call; `bundle` is then optional. Captured output (`stdio: "pipe"`) honors `maxBuffer` only when the caller supplies it (Node's `spawnSync` default is 1 MiB; pass `EXECUTE_ALCHEMY_ENTRY_MAX_BUFFER` for 64 MiB) and, when supplied, a `redact: (text: string) => string` hook applied to stdout and stderr before they are returned. Default `stdio: "inherit"` still streams the child unredacted. This package does not own a secret-name policy.
|
|
286
345
|
|
|
287
346
|
The caller still owns deploy/destroy/plan arguments, stage admission, credentials, environment shaping, destructive-plan guards, and convergence. Failure messages never repeat arguments or environment values.
|
|
288
347
|
|
|
@@ -298,6 +357,46 @@ import {
|
|
|
298
357
|
|
|
299
358
|
`local-pr-<pr>-<short sha>` construction and interpretation live behind one private grammar. `localPreviewStage({ pr, headSha, shaLength? })` accepts a positive PR, a full 40-character SHA, and a 7–40-character slice length (default 12). `parseLocalPreviewStage(stage, expected?)` returns the PR and SHA prefix, optionally proving ownership against a PR and full head SHA. `isLocalPreviewStage(stage, pr?)` is the boolean type guard. The raw regex is not public.
|
|
300
359
|
|
|
360
|
+
### Preview-proof lifecycle
|
|
361
|
+
|
|
362
|
+
```ts
|
|
363
|
+
import { previewProofLifecycle } from "@patronage/factory-ci";
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
`previewProofLifecycle` owns the commodity preview-proof state machine that two consumers had each written: admit a disposable stage, register envelope-bound proof at the candidate head, and record cleanup. `transition(state, event)` is the only mutation. `recover(state, cleanupEvent)` re-enters that same cleanup event from a failed outcome; it is not a second machine and not a CLI command. `resolve(state, query?)` is the consumer-readable registration read model: stack, stage, head SHA, proof identity, and cleanup status.
|
|
367
|
+
|
|
368
|
+
Events:
|
|
369
|
+
|
|
370
|
+
- `begin` — the pre-deploy gate. Refuses a draft, a closed PR, a dirty or mismatched worktree, and any stage the disposable grammar does not own for this PR head. Does not create a registration.
|
|
371
|
+
- `register` — the same identity gate, plus passed smoke, passed convergence, and a passing three-way-bound evidence envelope at this head. Writes a registration with `cleanupStatus: "pending"`. Machine evidence is that envelope; this module never posts a PR comment.
|
|
372
|
+
- `cleanup` — records an explicit passed or failed outcome onto an existing registration. Cleanup is never inferred from whether the stage still exists. `recover` is the failed-to-resolved re-entry of this event.
|
|
373
|
+
|
|
374
|
+
Proof runs entirely on one side of GitHub's draft/ready boundary: both `begin` and `register` refuse `isDraft: true`. Undraft first, then prove. Callers still own deploy, destroy, credentials, smoke probes, envelope emission, and stack names.
|
|
375
|
+
|
|
376
|
+
### Preview-proof inventory
|
|
377
|
+
|
|
378
|
+
```ts
|
|
379
|
+
import { previewProofInventory } from "@patronage/factory-ci";
|
|
380
|
+
|
|
381
|
+
const store = previewProofInventory.githubStore({
|
|
382
|
+
fetch,
|
|
383
|
+
token: process.env.GITHUB_TOKEN,
|
|
384
|
+
});
|
|
385
|
+
const rows = await previewProofInventory.list({ owner, repo, pr }, { store });
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
`previewProofInventory` is the hosted read and write API on that registration read model. A consumer workflow enumerates registered preview deployments for a PR (stack, stage, head SHA, proof identity, cleanup status) and records a cleanup outcome against a registration so the proof record reflects closure.
|
|
389
|
+
|
|
390
|
+
Registration is a consumer-readable read model. Cleanup outcomes are recorded by this API; they are never inferred from whether a Cloudflare or Alchemy stage still exists. Physical stage listing is a different artifact.
|
|
391
|
+
|
|
392
|
+
Persistence is an injectable GitHub transport in the same style as `mintInstallationToken`: the caller passes `fetch` and a token. This package does not read operator config or hold secrets. Records bind to the Patronage Factory GitHub App (`FACTORY_PROOF_GATE_APP_ID`) and the disposable-stage grammar. Check-runs named `patronage-factory/preview-proof` (`PREVIEW_PROOF_INVENTORY_CHECK_NAME`) carry the registration JSON. This API does not POST or PATCH issue comments.
|
|
393
|
+
|
|
394
|
+
`list({ owner, repo, pr }, { token })` works with a workflow `GITHUB_TOKEN` (read). `persist` and `recordCleanup` write App-owned check-runs, which GitHub only allows the producing App to update. Pass an installation token the caller minted (`mintInstallationToken`); a job `GITHUB_TOKEN` cannot write those records. There is no `psf` command for this surface.
|
|
395
|
+
|
|
396
|
+
`recordCleanup` loads the PR's registrations, applies `previewProofLifecycle.transition(..., { type: "cleanup" })`, then persists. Failed then passed uses that same event; in-memory re-entry from a failed outcome is `previewProofLifecycle.recover`, which calls that transition. Unknown stack or stage, and an identity mismatch on the disposable stage or head SHA, fail closed. Check-runs from another App, including `github-actions`, are ignored.
|
|
397
|
+
|
|
398
|
+
Pass `{ store }` to substitute the GitHub adapter. `previewProofInventory.memoryStore()` is an in-memory `list`/`put` port for tests. `githubStore({ token, fetch, timeoutMs? })` is the GitHub-backed implementation. Stack names stay caller strings.
|
|
399
|
+
|
|
301
400
|
### GitHub App installation tokens
|
|
302
401
|
|
|
303
402
|
```ts
|
package/dist/index.d.ts
CHANGED
|
@@ -161,6 +161,195 @@ interface LocalPreviewStageOptions {
|
|
|
161
161
|
*/
|
|
162
162
|
declare const localPreviewStage: (options: LocalPreviewStageOptions) => LocalPreviewStage;
|
|
163
163
|
//#endregion
|
|
164
|
+
//#region src/preview-proof-lifecycle.d.ts
|
|
165
|
+
/**
|
|
166
|
+
* Preview-proof lifecycle: admit a disposable preview, register envelope-bound
|
|
167
|
+
* proof at head, and record cleanup. One `transition` path owns those state
|
|
168
|
+
* changes. Recovery (#766) re-enters cleanup through the same event. Hosted
|
|
169
|
+
* inventory listing and cleanup-outcome persistence live in
|
|
170
|
+
* `previewProofInventory`, which sits on the registration read model `resolve`
|
|
171
|
+
* already returns.
|
|
172
|
+
*
|
|
173
|
+
* Proof sits entirely on one side of GitHub's draft/ready boundary
|
|
174
|
+
* (paitronage#1089): a draft candidate cannot begin or register. Machine
|
|
175
|
+
* evidence is the envelope at head (#355), never a PR comment.
|
|
176
|
+
*/
|
|
177
|
+
type PreviewProofCleanupStatus = "failed" | "passed" | "pending";
|
|
178
|
+
interface PreviewProofCandidate {
|
|
179
|
+
readonly branch: string;
|
|
180
|
+
readonly dirty: boolean;
|
|
181
|
+
readonly headSha: string;
|
|
182
|
+
readonly isDraft: boolean;
|
|
183
|
+
readonly pr: number;
|
|
184
|
+
readonly prHeadRef: string;
|
|
185
|
+
readonly prHeadSha: string;
|
|
186
|
+
readonly prRepository: string;
|
|
187
|
+
readonly prState: "CLOSED" | "MERGED" | "OPEN";
|
|
188
|
+
readonly repository: string;
|
|
189
|
+
}
|
|
190
|
+
interface PreviewProofEnvelopeEvidence {
|
|
191
|
+
readonly check: string;
|
|
192
|
+
readonly headSha: string;
|
|
193
|
+
readonly mergeBaseSha: string;
|
|
194
|
+
readonly outcome: "fail" | "pass";
|
|
195
|
+
readonly patchId: string;
|
|
196
|
+
}
|
|
197
|
+
interface PreviewProofCleanupOutcome {
|
|
198
|
+
readonly evidence: readonly string[];
|
|
199
|
+
readonly outcome: Exclude<PreviewProofCleanupStatus, "pending">;
|
|
200
|
+
readonly runUrl?: string;
|
|
201
|
+
}
|
|
202
|
+
interface PreviewProofRegistration {
|
|
203
|
+
readonly cleanup: {
|
|
204
|
+
readonly evidence: readonly string[];
|
|
205
|
+
readonly outcome: PreviewProofCleanupStatus;
|
|
206
|
+
readonly runUrl?: string;
|
|
207
|
+
};
|
|
208
|
+
readonly cleanupStatus: PreviewProofCleanupStatus;
|
|
209
|
+
readonly convergence: {
|
|
210
|
+
readonly detail: string;
|
|
211
|
+
readonly status: "passed";
|
|
212
|
+
};
|
|
213
|
+
readonly convergenceStatus: "passed";
|
|
214
|
+
readonly headSha: string;
|
|
215
|
+
readonly pr: number;
|
|
216
|
+
readonly proof: {
|
|
217
|
+
readonly check: string;
|
|
218
|
+
readonly headSha: string;
|
|
219
|
+
readonly mergeBaseSha: string;
|
|
220
|
+
readonly patchId: string;
|
|
221
|
+
};
|
|
222
|
+
readonly smoke: {
|
|
223
|
+
readonly detail: string;
|
|
224
|
+
readonly outcome: "passed";
|
|
225
|
+
};
|
|
226
|
+
readonly smokeStatus: "passed";
|
|
227
|
+
readonly source: "local-self-certified";
|
|
228
|
+
readonly stack: string;
|
|
229
|
+
readonly stage: LocalPreviewStage;
|
|
230
|
+
readonly url: string;
|
|
231
|
+
}
|
|
232
|
+
interface PreviewProofLifecycleState {
|
|
233
|
+
readonly registrations: readonly PreviewProofRegistration[];
|
|
234
|
+
}
|
|
235
|
+
type PreviewProofLifecycleEvent = {
|
|
236
|
+
readonly candidate: PreviewProofCandidate;
|
|
237
|
+
readonly stage: string;
|
|
238
|
+
readonly type: "begin";
|
|
239
|
+
} | {
|
|
240
|
+
readonly candidate: PreviewProofCandidate;
|
|
241
|
+
readonly convergence: {
|
|
242
|
+
readonly detail: string;
|
|
243
|
+
readonly status: "failed" | "passed";
|
|
244
|
+
};
|
|
245
|
+
readonly evidence: PreviewProofEnvelopeEvidence;
|
|
246
|
+
readonly smoke: {
|
|
247
|
+
readonly detail: string;
|
|
248
|
+
readonly outcome: "failed" | "passed";
|
|
249
|
+
};
|
|
250
|
+
readonly stack: string;
|
|
251
|
+
readonly stage: string;
|
|
252
|
+
readonly type: "register";
|
|
253
|
+
readonly url: string;
|
|
254
|
+
} | {
|
|
255
|
+
readonly evidence: readonly string[];
|
|
256
|
+
readonly outcome: Exclude<PreviewProofCleanupStatus, "pending">;
|
|
257
|
+
readonly pr: number;
|
|
258
|
+
readonly runUrl?: string;
|
|
259
|
+
readonly stack: string;
|
|
260
|
+
readonly stage: string;
|
|
261
|
+
readonly type: "cleanup";
|
|
262
|
+
};
|
|
263
|
+
interface PreviewProofResolveQuery {
|
|
264
|
+
readonly pr?: number;
|
|
265
|
+
readonly stack?: string;
|
|
266
|
+
readonly stage?: string;
|
|
267
|
+
}
|
|
268
|
+
declare const previewProofLifecycle: {
|
|
269
|
+
readonly empty: () => PreviewProofLifecycleState;
|
|
270
|
+
readonly recover: (state: PreviewProofLifecycleState, event: Extract<PreviewProofLifecycleEvent, {
|
|
271
|
+
type: "cleanup";
|
|
272
|
+
}>) => PreviewProofLifecycleState;
|
|
273
|
+
readonly resolve: (state: PreviewProofLifecycleState, query?: PreviewProofResolveQuery) => readonly PreviewProofRegistration[];
|
|
274
|
+
readonly transition: (state: PreviewProofLifecycleState, event: PreviewProofLifecycleEvent) => PreviewProofLifecycleState;
|
|
275
|
+
};
|
|
276
|
+
//#endregion
|
|
277
|
+
//#region src/preview-proof-inventory.d.ts
|
|
278
|
+
/**
|
|
279
|
+
* Hosted preview-proof inventory (#639): persist and list Factory-App
|
|
280
|
+
* registrations, and record cleanup outcomes, without PR comments.
|
|
281
|
+
*
|
|
282
|
+
* `list` is a read over App-owned commit check-runs and works with a workflow
|
|
283
|
+
* `GITHUB_TOKEN`. `persist` and `recordCleanup` write those check-runs, which
|
|
284
|
+
* GitHub only allows the producing App to update. Pass an installation token
|
|
285
|
+
* the caller minted; this package does not read operator config or hold
|
|
286
|
+
* secrets. Cleanup writes go through `previewProofLifecycle.transition` with
|
|
287
|
+
* `{ type: "cleanup" }`. Outcomes are never inferred from whether a stage
|
|
288
|
+
* still exists.
|
|
289
|
+
*/
|
|
290
|
+
/** Check-run name that carries one registration JSON payload. Not a gate. */
|
|
291
|
+
declare const PREVIEW_PROOF_INVENTORY_CHECK_NAME = "patronage-factory/preview-proof";
|
|
292
|
+
interface PreviewProofInventoryStore {
|
|
293
|
+
list: (input: {
|
|
294
|
+
owner: string;
|
|
295
|
+
pr: number;
|
|
296
|
+
repo: string;
|
|
297
|
+
}) => Promise<readonly PreviewProofRegistration[]>;
|
|
298
|
+
put: (input: {
|
|
299
|
+
owner: string;
|
|
300
|
+
registration: PreviewProofRegistration;
|
|
301
|
+
repo: string;
|
|
302
|
+
}) => Promise<void>;
|
|
303
|
+
}
|
|
304
|
+
interface PreviewProofInventoryTransport {
|
|
305
|
+
/** Injectable `fetch` (tests, or a caller with its own instrumented one). */
|
|
306
|
+
fetch?: typeof fetch;
|
|
307
|
+
/** Per-request timeout; defaults to five seconds. */
|
|
308
|
+
timeoutMs?: number;
|
|
309
|
+
/**
|
|
310
|
+
* Bearer token. `list` accepts a workflow `GITHUB_TOKEN` (read). `persist`
|
|
311
|
+
* and `recordCleanup` must use a Factory App installation token: GitHub
|
|
312
|
+
* refuses GITHUB_TOKEN writes to App-owned check-runs.
|
|
313
|
+
*/
|
|
314
|
+
token: string;
|
|
315
|
+
}
|
|
316
|
+
interface PreviewProofInventoryAccess {
|
|
317
|
+
fetch?: typeof fetch;
|
|
318
|
+
store?: PreviewProofInventoryStore;
|
|
319
|
+
timeoutMs?: number;
|
|
320
|
+
token?: string;
|
|
321
|
+
}
|
|
322
|
+
interface PreviewProofInventoryListInput {
|
|
323
|
+
owner: string;
|
|
324
|
+
pr: number;
|
|
325
|
+
repo: string;
|
|
326
|
+
stack?: string;
|
|
327
|
+
stage?: string;
|
|
328
|
+
}
|
|
329
|
+
interface PreviewProofInventoryPersistInput {
|
|
330
|
+
owner: string;
|
|
331
|
+
registration: PreviewProofRegistration;
|
|
332
|
+
repo: string;
|
|
333
|
+
}
|
|
334
|
+
interface PreviewProofInventoryCleanupInput {
|
|
335
|
+
evidence: readonly string[];
|
|
336
|
+
headSha?: string;
|
|
337
|
+
outcome: Exclude<PreviewProofCleanupStatus, "pending">;
|
|
338
|
+
owner: string;
|
|
339
|
+
pr: number;
|
|
340
|
+
repo: string;
|
|
341
|
+
runUrl?: string;
|
|
342
|
+
stack: string;
|
|
343
|
+
stage: string;
|
|
344
|
+
}
|
|
345
|
+
declare const previewProofInventory: {
|
|
346
|
+
readonly githubStore: (transport: PreviewProofInventoryTransport) => PreviewProofInventoryStore;
|
|
347
|
+
readonly list: (input: PreviewProofInventoryListInput, access: PreviewProofInventoryAccess) => Promise<readonly PreviewProofRegistration[]>;
|
|
348
|
+
readonly memoryStore: () => PreviewProofInventoryStore;
|
|
349
|
+
readonly persist: (input: PreviewProofInventoryPersistInput, access: PreviewProofInventoryAccess) => Promise<void>;
|
|
350
|
+
readonly recordCleanup: (input: PreviewProofInventoryCleanupInput, access: PreviewProofInventoryAccess) => Promise<PreviewProofRegistration>;
|
|
351
|
+
};
|
|
352
|
+
//#endregion
|
|
164
353
|
//#region src/factory-workflow.d.ts
|
|
165
354
|
interface WorkflowStep {
|
|
166
355
|
readonly continueOnError?: boolean;
|
|
@@ -282,19 +471,43 @@ declare const mintInstallationToken: (input: {
|
|
|
282
471
|
}, options?: GithubAppTokenOptions) => Promise<string>;
|
|
283
472
|
//#endregion
|
|
284
473
|
//#region src/execute-alchemy-entry.d.ts
|
|
474
|
+
/** Node's spawnSync default is 1 MiB; Alchemy plans routinely exceed that. */
|
|
475
|
+
declare const EXECUTE_ALCHEMY_ENTRY_MAX_BUFFER: number;
|
|
285
476
|
interface ExecuteAlchemyEntryOptions {
|
|
286
477
|
/**
|
|
287
478
|
* CLI arguments before the bundled entry. The absolute entry path is always
|
|
288
479
|
* appended as the final argument.
|
|
289
480
|
*/
|
|
290
481
|
readonly args: readonly string[];
|
|
291
|
-
|
|
482
|
+
/**
|
|
483
|
+
* Bundle the consumer entry before execution. Required unless `bundledEntry`
|
|
484
|
+
* is set. Ignored when `bundledEntry` is set.
|
|
485
|
+
*/
|
|
486
|
+
readonly bundle?: BundleAlchemyEntryOptions;
|
|
487
|
+
/**
|
|
488
|
+
* Already-bundled entry path. When set, skips the internal bundle step and
|
|
489
|
+
* appends this path as the CLI's final argument.
|
|
490
|
+
*/
|
|
491
|
+
readonly bundledEntry?: string;
|
|
292
492
|
/** Child working directory. Defaults to the bundle root, then process.cwd. */
|
|
293
493
|
readonly cwd?: string;
|
|
294
494
|
/** Child environment. Defaults to process.env. */
|
|
295
495
|
readonly env?: NodeJS.ProcessEnv;
|
|
296
496
|
/** Consumer module context; normally the caller's import.meta.url. */
|
|
297
497
|
readonly from: string | URL;
|
|
498
|
+
/**
|
|
499
|
+
* Largest captured stdout or stderr, in bytes. Omitted unless the caller
|
|
500
|
+
* sets it, so Node's spawnSync default (1 MiB) stays in force. Has no
|
|
501
|
+
* effect when stdio is `"inherit"`. Callers that need a larger capture
|
|
502
|
+
* pass `EXECUTE_ALCHEMY_ENTRY_MAX_BUFFER` or another explicit value.
|
|
503
|
+
*/
|
|
504
|
+
readonly maxBuffer?: number;
|
|
505
|
+
/**
|
|
506
|
+
* Applied to captured stdout and stderr before they are returned. Unused
|
|
507
|
+
* when stdio is `"inherit"`. This package does not supply a secret-name
|
|
508
|
+
* policy; the caller owns redaction.
|
|
509
|
+
*/
|
|
510
|
+
readonly redact?: (text: string) => string;
|
|
298
511
|
/** Child stdio. Default "inherit". */
|
|
299
512
|
readonly stdio?: "inherit" | "pipe";
|
|
300
513
|
}
|
|
@@ -307,6 +520,11 @@ interface ExecuteAlchemyEntryResult {
|
|
|
307
520
|
* Bundle a consumer-owned Alchemy entry, resolve that consumer's Alchemy CLI,
|
|
308
521
|
* run it under the current Node binary, and return only on a successful exit.
|
|
309
522
|
*
|
|
523
|
+
* Pass `bundledEntry` to skip the bundle step and reuse an already-bundled
|
|
524
|
+
* path. Captured stdout and stderr (`stdio: "pipe"`) can be redacted through
|
|
525
|
+
* `redact` before they are returned; `stdio: "inherit"` still streams the
|
|
526
|
+
* child unredacted.
|
|
527
|
+
*
|
|
310
528
|
* Deploy/destroy/plan selection, stage admission, credentials, and every
|
|
311
529
|
* convergence or destructive-change policy remain the caller's responsibility.
|
|
312
530
|
*/
|
|
@@ -623,6 +841,7 @@ declare const factoryProofReuseSummaryStep: (options: FactoryProofReusePresentat
|
|
|
623
841
|
declare const FACTORY_CANDIDATE_IMPACT_STEP_ID = "candidate_impact";
|
|
624
842
|
declare const FACTORY_CANDIDATE_IMPACT_DECISION_OUTPUT = "decision";
|
|
625
843
|
declare const FACTORY_CANDIDATE_IMPACT_BASIS_OUTPUT = "basis";
|
|
844
|
+
declare const FACTORY_CANDIDATE_IMPACT_INERT_OUTPUT = "inert_paths";
|
|
626
845
|
declare const FACTORY_CANDIDATE_IMPACT_UNSUBSCRIBED_OUTPUT = "unsubscribed_paths";
|
|
627
846
|
interface FactoryCandidateImpactWorkflowOptions {
|
|
628
847
|
readonly base?: string;
|
|
@@ -655,6 +874,72 @@ interface FactoryCandidateImpactWorkflow {
|
|
|
655
874
|
*/
|
|
656
875
|
declare const factoryCandidateImpactWorkflow: (options: FactoryCandidateImpactWorkflowOptions) => FactoryCandidateImpactWorkflow;
|
|
657
876
|
//#endregion
|
|
877
|
+
//#region src/lifecycle-contract-lane.d.ts
|
|
878
|
+
declare const FACTORY_LIFECYCLE_CONTRACT_JOB_ID = "factory-contracts";
|
|
879
|
+
declare const FACTORY_LIFECYCLE_CONTRACT_JOB_NAME = "Factory / Alchemy Contracts";
|
|
880
|
+
interface FactoryLifecycleContractLaneOptions {
|
|
881
|
+
readonly command: string;
|
|
882
|
+
readonly jobId?: string;
|
|
883
|
+
readonly jobName?: string;
|
|
884
|
+
}
|
|
885
|
+
interface FactoryLifecycleContractLane {
|
|
886
|
+
readonly jobId: string;
|
|
887
|
+
readonly jobName: string;
|
|
888
|
+
readonly steps: readonly WorkflowStep[];
|
|
889
|
+
}
|
|
890
|
+
/**
|
|
891
|
+
* Generate the factory-owned non-credentialed lifecycle-contract lane
|
|
892
|
+
* (#765). Consumers declare the package-script command in
|
|
893
|
+
* `software-factory.profile.json`; this helper never loads that profile.
|
|
894
|
+
* Callers pass the parsed declaration (or omit it) and include or skip the
|
|
895
|
+
* returned job. Setup, runners, topology, and credentials stay with the
|
|
896
|
+
* caller — and this lane must never receive credentials.
|
|
897
|
+
*
|
|
898
|
+
* The generated steps run only the declared package script and write an
|
|
899
|
+
* always() evidence summary of what the lane proves and does not prove.
|
|
900
|
+
* The command must be a package-script invocation: `run <script>`, or a
|
|
901
|
+
* shorthand whose script name contains `:` (`pnpm test:factory`). Optional
|
|
902
|
+
* pnpm `--filter <pkg>` may precede either form. Shell operators, credential
|
|
903
|
+
* env, extra flags, and direct Vitest are refused.
|
|
904
|
+
*/
|
|
905
|
+
declare const factoryLifecycleContractLane: (declaration?: FactoryLifecycleContractLaneOptions) => FactoryLifecycleContractLane | undefined;
|
|
906
|
+
//#endregion
|
|
907
|
+
//#region src/preview-cleanup-topology.d.ts
|
|
908
|
+
declare const FACTORY_PREVIEW_CLEANUP_AUDIT_JOB_ID = "stage-residue-audit";
|
|
909
|
+
declare const FACTORY_PREVIEW_CLEANUP_AUDIT_JOB_NAME = "Stage residue audit";
|
|
910
|
+
interface FactoryPreviewCleanupTopologyOptions {
|
|
911
|
+
readonly audit: {
|
|
912
|
+
readonly command: string;
|
|
913
|
+
readonly jobId?: string;
|
|
914
|
+
readonly jobName?: string;
|
|
915
|
+
};
|
|
916
|
+
readonly stacks: readonly string[];
|
|
917
|
+
}
|
|
918
|
+
interface FactoryPreviewCleanupDestroyJob {
|
|
919
|
+
readonly jobId: string;
|
|
920
|
+
readonly stack: string;
|
|
921
|
+
}
|
|
922
|
+
interface FactoryPreviewCleanupAuditJob {
|
|
923
|
+
readonly if: "always()";
|
|
924
|
+
readonly jobId: string;
|
|
925
|
+
readonly jobName: string;
|
|
926
|
+
readonly needs: readonly string[];
|
|
927
|
+
readonly steps: readonly WorkflowStep[];
|
|
928
|
+
}
|
|
929
|
+
interface FactoryPreviewCleanupTopology {
|
|
930
|
+
readonly auditJob: FactoryPreviewCleanupAuditJob;
|
|
931
|
+
readonly destroyJobs: readonly FactoryPreviewCleanupDestroyJob[];
|
|
932
|
+
}
|
|
933
|
+
declare const previewCleanupDestroyJobId: (stack: string) => string;
|
|
934
|
+
/**
|
|
935
|
+
* Generate the factory-owned preview-cleanup topology (#764): one destroy
|
|
936
|
+
* job identity per stack, then exactly one stage-wide residue-audit job
|
|
937
|
+
* that `needs` every destroy. The audit is whole-stage — this helper never
|
|
938
|
+
* threads a stack name or path filter into it. Callers own destroy steps,
|
|
939
|
+
* what counts as residue, credentials, and runners.
|
|
940
|
+
*/
|
|
941
|
+
declare const factoryPreviewCleanupTopology: (options: FactoryPreviewCleanupTopologyOptions) => FactoryPreviewCleanupTopology;
|
|
942
|
+
//#endregion
|
|
658
943
|
//#region src/production-impact-workflow.d.ts
|
|
659
944
|
declare const FACTORY_PRODUCTION_IMPACT_STEP_ID = "production_impact";
|
|
660
945
|
declare const FACTORY_PRODUCTION_IMPACT_DECISION_OUTPUT = "decision";
|
|
@@ -1016,4 +1301,4 @@ declare const assertWorkflowShellParses: (yaml: string, options: {
|
|
|
1016
1301
|
readonly source: string;
|
|
1017
1302
|
}) => void;
|
|
1018
1303
|
//#endregion
|
|
1019
|
-
export { type BundleAlchemyEntryOptions, type CheckoutStepOptions, type ExecuteAlchemyEntryOptions, type ExecuteAlchemyEntryResult, FACTORY_CANDIDATE_IMPACT_BASIS_OUTPUT, FACTORY_CANDIDATE_IMPACT_DECISION_OUTPUT, FACTORY_CANDIDATE_IMPACT_STEP_ID, FACTORY_CANDIDATE_IMPACT_UNSUBSCRIBED_OUTPUT, FACTORY_CANDIDATE_PULL_REQUEST_TYPES, FACTORY_PRODUCTION_IMPACT_BASIS_OUTPUT, FACTORY_PRODUCTION_IMPACT_DECISION_OUTPUT, FACTORY_PRODUCTION_IMPACT_STEP_ID, FACTORY_PRODUCTION_IMPACT_UNSUBSCRIBED_OUTPUT, FACTORY_PROOF_GATE_APP_ID, FACTORY_PROOF_GATE_CHECK_NAME, FACTORY_PROOF_GATE_GUARD, FACTORY_PROOF_GATE_IF, FACTORY_PROOF_GATE_MODE_OUTPUT, FACTORY_PROOF_GATE_OUTPUT, FACTORY_PROOF_GATE_REASONS, FACTORY_PROOF_GATE_REASON_OUTPUT, FACTORY_PROOF_GATE_SHELL, FACTORY_PROOF_GATE_SOURCE_URL_OUTPUT, FACTORY_PROOF_GATE_STEP_ID, FACTORY_PROOF_GATE_STEP_NAME, FACTORY_PUSH_IDENTITY_SCHEMA_VERSION, type FactoryCandidateImpactWorkflow, type FactoryCandidateImpactWorkflowOptions, type FactoryProductionImpactWorkflow, type FactoryProductionImpactWorkflowOptions, type FactoryProofGateOptions, type FactoryProofGateReason, type FactoryProofGateStep, type FactoryProofReusePresentationOptions, type FactoryProofReuseSummaryStep, type FactoryProofTimingStartStep, type FactoryPushIdentityConsumer, type FactoryPushIdentityConsumerOptions, type FactoryPushIdentityDisposition, type FactoryPushIdentityEnvelope, type FactoryPushIdentityProducer, type FactoryPushIdentityProducerOptions, type FactoryWorkflowArtifact, type FactoryWorkflowOptions, type FactoryWorkflowSetupOptions, GitHubApiError, type GithubAppCredentials, type GithubAppTokenOptions, type InstallStepOptions, type LocalPreviewStage, type LocalPreviewStageOptions, NODE_PNPM_ACTION_FAMILY_NODE24, type NodePnpmActionFamily, type ParseLocalPreviewStageExpected, type ParsedLocalPreviewStage, type PinnedAction, type ProofReuseCommand, type ProofReuseCoverageInput, type ProofReuseCoverageReport, type SetupNodeStepOptions, VITEST_PROFILE_SCHEMA_VERSION, VITEST_PROFILE_TOOL, type VitestJsonReport, type VitestProfile, type VitestProfileDependencies, type VitestProfileDurationSummary, type VitestProfileEnvironment, VitestProfileError, type VitestProfileOptions, type VitestProfileReadResult, type VitestProfileSample, type VitestProfileSampleExecution, type VitestTestStatus, type WorkflowShellParseFailure, type WorkflowStep, assertProofReuseCoverage, assertWorkflowShellParses, bundleAlchemyEntry, captureVitestProfileEnvironment, executeAlchemyEntry, factoryCandidateImpactWorkflow, factoryCandidateOrPushCondition, factoryProductionImpactWorkflow, factoryProofGateScript, factoryProofGateStep, factoryProofReuseSummaryStep, factoryProofTimingStartStep, factoryPushIdentityConsumer, factoryPushIdentityProducer, factoryWorkflow, githubAppJwt, isLocalPreviewStage, localPreviewStage, mintInstallationToken, normalizeVitestProfileSample, parseLocalPreviewStage, productionImpactTargetOutput, proofReuseCoverage, proofReuseRequiredCommands, readVitestProfileDocument, resolveProofReuseCommands, runVitestProfile, workflowRunBlocks, workflowShellParseFailures, writeVitestProfile };
|
|
1304
|
+
export { type BundleAlchemyEntryOptions, type CheckoutStepOptions, EXECUTE_ALCHEMY_ENTRY_MAX_BUFFER, type ExecuteAlchemyEntryOptions, type ExecuteAlchemyEntryResult, FACTORY_CANDIDATE_IMPACT_BASIS_OUTPUT, FACTORY_CANDIDATE_IMPACT_DECISION_OUTPUT, FACTORY_CANDIDATE_IMPACT_INERT_OUTPUT, FACTORY_CANDIDATE_IMPACT_STEP_ID, FACTORY_CANDIDATE_IMPACT_UNSUBSCRIBED_OUTPUT, FACTORY_CANDIDATE_PULL_REQUEST_TYPES, FACTORY_LIFECYCLE_CONTRACT_JOB_ID, FACTORY_LIFECYCLE_CONTRACT_JOB_NAME, FACTORY_PREVIEW_CLEANUP_AUDIT_JOB_ID, FACTORY_PREVIEW_CLEANUP_AUDIT_JOB_NAME, FACTORY_PRODUCTION_IMPACT_BASIS_OUTPUT, FACTORY_PRODUCTION_IMPACT_DECISION_OUTPUT, FACTORY_PRODUCTION_IMPACT_STEP_ID, FACTORY_PRODUCTION_IMPACT_UNSUBSCRIBED_OUTPUT, FACTORY_PROOF_GATE_APP_ID, FACTORY_PROOF_GATE_CHECK_NAME, FACTORY_PROOF_GATE_GUARD, FACTORY_PROOF_GATE_IF, FACTORY_PROOF_GATE_MODE_OUTPUT, FACTORY_PROOF_GATE_OUTPUT, FACTORY_PROOF_GATE_REASONS, FACTORY_PROOF_GATE_REASON_OUTPUT, FACTORY_PROOF_GATE_SHELL, FACTORY_PROOF_GATE_SOURCE_URL_OUTPUT, FACTORY_PROOF_GATE_STEP_ID, FACTORY_PROOF_GATE_STEP_NAME, FACTORY_PUSH_IDENTITY_SCHEMA_VERSION, type FactoryCandidateImpactWorkflow, type FactoryCandidateImpactWorkflowOptions, type FactoryLifecycleContractLane, type FactoryLifecycleContractLaneOptions, type FactoryPreviewCleanupAuditJob, type FactoryPreviewCleanupDestroyJob, type FactoryPreviewCleanupTopology, type FactoryPreviewCleanupTopologyOptions, type FactoryProductionImpactWorkflow, type FactoryProductionImpactWorkflowOptions, type FactoryProofGateOptions, type FactoryProofGateReason, type FactoryProofGateStep, type FactoryProofReusePresentationOptions, type FactoryProofReuseSummaryStep, type FactoryProofTimingStartStep, type FactoryPushIdentityConsumer, type FactoryPushIdentityConsumerOptions, type FactoryPushIdentityDisposition, type FactoryPushIdentityEnvelope, type FactoryPushIdentityProducer, type FactoryPushIdentityProducerOptions, type FactoryWorkflowArtifact, type FactoryWorkflowOptions, type FactoryWorkflowSetupOptions, GitHubApiError, type GithubAppCredentials, type GithubAppTokenOptions, type InstallStepOptions, type LocalPreviewStage, type LocalPreviewStageOptions, NODE_PNPM_ACTION_FAMILY_NODE24, type NodePnpmActionFamily, PREVIEW_PROOF_INVENTORY_CHECK_NAME, type ParseLocalPreviewStageExpected, type ParsedLocalPreviewStage, type PinnedAction, type PreviewProofCandidate, type PreviewProofCleanupOutcome, type PreviewProofCleanupStatus, type PreviewProofEnvelopeEvidence, type PreviewProofInventoryAccess, type PreviewProofInventoryCleanupInput, type PreviewProofInventoryListInput, type PreviewProofInventoryPersistInput, type PreviewProofInventoryStore, type PreviewProofInventoryTransport, type PreviewProofLifecycleEvent, type PreviewProofLifecycleState, type PreviewProofRegistration, type PreviewProofResolveQuery, type ProofReuseCommand, type ProofReuseCoverageInput, type ProofReuseCoverageReport, type SetupNodeStepOptions, VITEST_PROFILE_SCHEMA_VERSION, VITEST_PROFILE_TOOL, type VitestJsonReport, type VitestProfile, type VitestProfileDependencies, type VitestProfileDurationSummary, type VitestProfileEnvironment, VitestProfileError, type VitestProfileOptions, type VitestProfileReadResult, type VitestProfileSample, type VitestProfileSampleExecution, type VitestTestStatus, type WorkflowShellParseFailure, type WorkflowStep, assertProofReuseCoverage, assertWorkflowShellParses, bundleAlchemyEntry, captureVitestProfileEnvironment, executeAlchemyEntry, factoryCandidateImpactWorkflow, factoryCandidateOrPushCondition, factoryLifecycleContractLane, factoryPreviewCleanupTopology, factoryProductionImpactWorkflow, factoryProofGateScript, factoryProofGateStep, factoryProofReuseSummaryStep, factoryProofTimingStartStep, factoryPushIdentityConsumer, factoryPushIdentityProducer, factoryWorkflow, githubAppJwt, isLocalPreviewStage, localPreviewStage, mintInstallationToken, normalizeVitestProfileSample, parseLocalPreviewStage, previewCleanupDestroyJobId, previewProofInventory, previewProofLifecycle, productionImpactTargetOutput, proofReuseCoverage, proofReuseRequiredCommands, readVitestProfileDocument, resolveProofReuseCommands, runVitestProfile, workflowRunBlocks, workflowShellParseFailures, writeVitestProfile };
|