161 lines
9.7 KiB
Markdown
161 lines
9.7 KiB
Markdown
# Post-Deploy Live Verification
|
|
|
|
```
|
|
name: Post-Deploy Live Verification
|
|
slug: post-deploy-live-verification
|
|
tier: forward-deployed (operations)
|
|
role: fde
|
|
status: template
|
|
score: 53 (demand 5, pain 5, differentiation 4, usability 5, connectors 5)
|
|
intent: merged-is-not-live as a procedure: prove that what production serves
|
|
is what was approved, on every route that matters, before the change
|
|
is called done
|
|
when to use: after every merge that changes anything a user or crawler sees; as
|
|
the standing final step of any pipeline that ships
|
|
when not to use: pre-merge checking (that is CI Prove-Gate Wiring's territory);
|
|
content-claim truth (Corpus Integrity and Correction); a live
|
|
regression from an already-promoted lane (Incident Response and
|
|
Lane Demotion, which this workflow's failures feed)
|
|
gap note: this workflow's core is the tier's largest DECLARED CATALOG GAP;
|
|
most phases are inline procedure with qa-testing and seo-technical
|
|
as the nearest anchors. It is written to be runnable anyway.
|
|
```
|
|
|
|
## Connectors
|
|
|
|
```
|
|
connectors:
|
|
- capability: crawl.read
|
|
access: read
|
|
- capability: repo.change
|
|
access: write-held # only for fixes the verification surfaces
|
|
```
|
|
|
|
Verification is read-only. Fixes it surfaces land held; deploy-platform actions (promoting, purging, redeploying) are human actions on the platform, outside these connectors by design.
|
|
|
|
## Prerequisites
|
|
|
|
- Claude with the catalog installed: `/plugin marketplace add rampstackco/claude-skills`
|
|
- The production domain, and the list of routes the change touched plus the routes that share templates or data with them.
|
|
- A way to read which build produced a served page (a deployment id, build hash, or asset fingerprint in the rendered HTML; every modern host embeds one).
|
|
- The approved state: the merged content, metadata, and values the pages are supposed to show.
|
|
|
|
## Phases
|
|
|
|
### Phase 1: Capture the expected state · lane: convergent (Tholo)
|
|
|
|
Skills: qa-testing (nearest anchor; procedure inline)
|
|
Capability class: deploy.expected-state (declared catalog gap)
|
|
Input: the merged change; the route list
|
|
Run:
|
|
|
|
From the merged change, record what production should now show, per
|
|
route: the content values that changed, titles and meta descriptions,
|
|
canonical URLs, structured data, and at least one DISCRIMINATOR VALUE
|
|
per route: something this deploy changed that the previous build could
|
|
not be showing (new copy, a new derived count, a version string). Add
|
|
the blast-radius routes: pages sharing the template, layout, nav, or
|
|
data source with the changed ones, because deploys regress neighbors.
|
|
Record the newest deployment or build identifier the platform reports.
|
|
|
|
Output artifact: the expected-state sheet (route, expected values, discriminator value, expected build id)
|
|
Done when: every touched and blast-radius route has expected values and a discriminator
|
|
Fails look like: verifying only the changed route. The route you edited is the one you will look at anyway; the regression ships on the sibling route nobody listed
|
|
|
|
### Phase 2: Production fetch and identity check · lane: gate (Basano)
|
|
|
|
Skills: qa-testing, seo-technical (anchors; procedure inline)
|
|
Capability class: deploy.live-verify (declared catalog gap)
|
|
Input: the expected-state sheet
|
|
Run:
|
|
|
|
Fetch each route's PRODUCTION URL: not a preview, not a staging domain,
|
|
not localhost, and not a browser with a warm cache. For each route,
|
|
record: the discriminator value present or absent; the build identifier
|
|
the served page embeds; title, meta description, canonical, social-share
|
|
metadata, and structured data against expected; and status codes on the
|
|
route and its internal links. Fetch twice with a short gap; a CDN can
|
|
serve different edges different builds, and one fetch is a sample, not
|
|
a verdict. Report per route: VERIFIED (discriminator present, build id
|
|
current, values match), STALE (old build id or missing discriminator),
|
|
or WRONG (current build, unexpected values).
|
|
|
|
Output artifact: the live report (verdict, evidence, build id per route, both fetches)
|
|
Done when: every route on the sheet has a verdict from production fetches
|
|
Fails look like: trusting the deploy dashboard. The platform saying the deployment succeeded is a claim about the build, not about what a given route serves; tool-reported success is not verified state, and only the rendered production URL is ground truth
|
|
|
|
### Phase 3: Discriminate the failure class · lane: convergent (Tholo)
|
|
|
|
Skills: none; this is the decision table (procedure inline; the discriminator pattern generalizes production incidents on an unnamed property)
|
|
Capability class: deploy.failure-discriminate (declared catalog gap)
|
|
Input: the live report, when any route is STALE or WRONG
|
|
Run:
|
|
|
|
Apply the decision table. ALL routes stale on the same old build id:
|
|
the deploy never promoted; the fix is platform-side promotion, not code.
|
|
SOME routes current and SOME stale: route-level cache or incremental
|
|
render staleness; the stale HTML was generated under the old build and
|
|
is being served past the new deploy; the fix is a targeted purge or
|
|
revalidation of those routes, and if a purged route goes stale again,
|
|
its background regeneration is failing and the platform's function logs
|
|
for that route are the next read. Routes CURRENT but WRONG: the defect
|
|
merged; the fix is code, as a held change. State which class the
|
|
evidence supports and what evidence would distinguish it further if
|
|
ambiguous.
|
|
|
|
Output artifact: the failure-class finding with its evidence
|
|
Done when: every non-verified route has a named failure class or a named ambiguity with the next check specified
|
|
Fails look like: purge-and-hope. Purging a cache without knowing whether the deploy promoted treats two different diseases with one drug; when it happens to work, nothing was learned, and when it does not, the next hour is spent purging harder
|
|
|
|
### Phase 4: Route the fix · lane: divergent (human)
|
|
|
|
Skills: none; the actions here are deliberately human
|
|
Input: the failure-class finding
|
|
Run: promotion, purge, revalidation, and redeploy are performed by a person
|
|
on the platform (these are production state changes, and they stay
|
|
human). Code defects land as held changes (repo.change) for normal
|
|
review. The human records what action was taken and against which
|
|
failure class.
|
|
Output artifact: the action taken, recorded against the finding
|
|
Done when: the action for every non-verified route is taken or explicitly deferred
|
|
Operated-layer note: in an operated deployment the finding and the action land as an agreement-log row; a promoted lane whose deploys repeatedly land STALE is exactly the post_merge_outcome signal Incident Response and Lane Demotion consumes
|
|
Fails look like: the verification performing the platform action itself. The read side of this workflow can be trusted precisely because it cannot touch what it measures
|
|
|
|
### Phase 5: Re-verify and close · lane: gate (Basano)
|
|
|
|
Skills: qa-testing (anchor; procedure inline)
|
|
Capability class: deploy.live-verify (declared catalog gap)
|
|
Input: the expected-state sheet; the actions taken
|
|
Run:
|
|
|
|
Re-run Phase 2 on every route that was not VERIFIED, same discipline:
|
|
production URL, discriminator, build id, two fetches. The change closes
|
|
only when every route on the sheet reads VERIFIED. Record the closure
|
|
with the final build id per route. If this workflow runs as a pipeline's
|
|
standing final step (it should), the closure record is the pipeline's
|
|
definition of done.
|
|
|
|
Output artifact: the closure record (all routes VERIFIED, final build ids, timestamps)
|
|
Done when: all routes VERIFIED on production, and the closure record exists
|
|
Fails look like: closing at merge, or closing on the first good fetch after a purge. Done is a property of what production serves, held across both fetches, on every route on the sheet
|
|
|
|
## Failure modes
|
|
|
|
- Preview verification: any fetch that is not the production URL proves nothing about production.
|
|
- Single-fetch verdicts: CDN edges disagree; two fetches minimum, and disagreement between them is itself a finding.
|
|
- Dashboard trust: deploy success and served state are different facts (Phase 2's inline failure).
|
|
- Sibling blindness: verifying only the edited route (Phase 1's inline failure).
|
|
- Purge-and-hope (Phase 3's inline failure).
|
|
- Missing discriminator: without a value only the new build can show, a stale page that happens to look right passes; the discriminator is what makes VERIFIED falsifiable.
|
|
- Merge-time closure: the change is done when production says so, not when the repo does.
|
|
|
|
## Worked example
|
|
|
|
Pending. Populates when this workflow is executed as written on a showcase-designated property. The verification core generalizes real post-merge passes on rampstack.co (rendered-state checks, cross-link verification, build-identity reads across two merges in one day); the failure-class decision table additionally generalizes production incidents on an unnamed property, including a route serving a twelve-day-old render while its sibling served current data. Status flips to validated when a run record links here.
|
|
|
|
## Boundaries
|
|
|
|
- CI Prove-Gate Wiring owns pre-merge gates; this workflow begins where CI ends, because CI runs against the build and this runs against the world.
|
|
- Incident Response and Lane Demotion consumes this workflow's repeated failures on promoted lanes; a STALE that recurs is an incident, not a verification note.
|
|
- Content Pipeline Phase 5 and Corpus Integrity Phase 5 are this workflow's content-shaped instances; they share the declared gap and the doctrine.
|