yadflow 2.6.0 → 2.7.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/CHANGELOG.md +4 -7
- package/README.md +23 -2
- package/bin/yad.mjs +22 -1
- package/cli/docs.mjs +298 -0
- package/cli/manifest.mjs +6 -1
- package/docs/index.html +4 -4
- package/package.json +2 -2
- package/skills/sdlc/config.yaml +19 -0
- package/skills/sdlc/install.sh +1 -1
- package/skills/sdlc/module-help.csv +4 -0
- package/skills/yad-connect-docs/SKILL.md +132 -0
- package/skills/yad-connect-docs/references/docs-registry.md +74 -0
- package/skills/yad-docs/SKILL.md +159 -0
- package/skills/yad-docs/references/data-mapping.md +75 -0
- package/skills/yad-docs/references/theme-map.md +69 -0
- package/skills/yad-docs/templates/app/README.md +31 -0
- package/skills/yad-docs/templates/app/eslint.config.js +23 -0
- package/skills/yad-docs/templates/app/index.html +17 -0
- package/skills/yad-docs/templates/app/package-lock.json +4030 -0
- package/skills/yad-docs/templates/app/package.json +35 -0
- package/skills/yad-docs/templates/app/public/favicon.svg +28 -0
- package/skills/yad-docs/templates/app/public/logo.svg +39 -0
- package/skills/yad-docs/templates/app/public/vite.svg +1 -0
- package/skills/yad-docs/templates/app/src/App.tsx +98 -0
- package/skills/yad-docs/templates/app/src/components/Auth/LoginPage.tsx +101 -0
- package/skills/yad-docs/templates/app/src/components/Canvas/AnimatedMessage.tsx +101 -0
- package/skills/yad-docs/templates/app/src/components/Canvas/ConnectionLine.tsx +90 -0
- package/skills/yad-docs/templates/app/src/components/Canvas/FlowCanvas.tsx +216 -0
- package/skills/yad-docs/templates/app/src/components/Canvas/SystemComponent.tsx +153 -0
- package/skills/yad-docs/templates/app/src/components/Controls/PlaybackBar.tsx +284 -0
- package/skills/yad-docs/templates/app/src/components/Controls/StepDetail.tsx +167 -0
- package/skills/yad-docs/templates/app/src/components/DetailPanel/HandlerLogicSnippet.tsx +41 -0
- package/skills/yad-docs/templates/app/src/components/DetailPanel/RequestPayloadPreview.tsx +46 -0
- package/skills/yad-docs/templates/app/src/components/DetailPanel/RightPanel.tsx +88 -0
- package/skills/yad-docs/templates/app/src/components/DetailPanel/StatusCard.tsx +76 -0
- package/skills/yad-docs/templates/app/src/components/DetailPanel/TriggerEventCard.tsx +45 -0
- package/skills/yad-docs/templates/app/src/components/DocLayout/DocPageShell.tsx +80 -0
- package/skills/yad-docs/templates/app/src/components/DocLayout/DocSectionCard.tsx +55 -0
- package/skills/yad-docs/templates/app/src/components/DocLayout/DocTableOfContents.tsx +79 -0
- package/skills/yad-docs/templates/app/src/components/DocLayout/RoleCard.tsx +67 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/ApiReferenceSection.tsx +108 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/CancelabilitySection.tsx +73 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/CriticalRunbookSection.tsx +177 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/DataMigrationSection.tsx +102 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/DbSchemaSection.tsx +98 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/DeploymentGuideSection.tsx +104 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/DriverIntegrationSection.tsx +127 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/ExecutiveSummarySection.tsx +69 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/FlowOverviewSection.tsx +73 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/FlowPathsChecklistSection.tsx +96 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/MiddlewareChainSection.tsx +107 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/MonitoringAlertingSection.tsx +106 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/NotificationLocalizationSection.tsx +102 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/PMRoadmapSection.tsx +133 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/PerformanceTestingSection.tsx +91 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/RiderIntegrationSection.tsx +99 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/SecuritySection.tsx +74 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/StatusMachineSection.tsx +90 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/TestPlanSection.tsx +163 -0
- package/skills/yad-docs/templates/app/src/components/Logs/SystemLogsTerminal.tsx +126 -0
- package/skills/yad-docs/templates/app/src/components/Navigation/TopNavBar.tsx +90 -0
- package/skills/yad-docs/templates/app/src/components/Reference/BullMQJobsList.tsx +60 -0
- package/skills/yad-docs/templates/app/src/components/Reference/DecisionTreeView.tsx +49 -0
- package/skills/yad-docs/templates/app/src/components/Reference/DeeplinkActionsChips.tsx +69 -0
- package/skills/yad-docs/templates/app/src/components/Reference/DriverUIStatesTable.tsx +61 -0
- package/skills/yad-docs/templates/app/src/components/Reference/FeatureFlagMatrix.tsx +73 -0
- package/skills/yad-docs/templates/app/src/components/Reference/RiderUIStatesTable.tsx +61 -0
- package/skills/yad-docs/templates/app/src/components/Reference/RulesLegendPanel.tsx +217 -0
- package/skills/yad-docs/templates/app/src/components/Reference/StakeholderToggle.tsx +41 -0
- package/skills/yad-docs/templates/app/src/components/Reference/TroubleshootingSection.tsx +93 -0
- package/skills/yad-docs/templates/app/src/components/Sidebar/PathSelector.tsx +148 -0
- package/skills/yad-docs/templates/app/src/components/Sidebar/SidebarFooter.tsx +40 -0
- package/skills/yad-docs/templates/app/src/components/Sidebar/StepList.tsx +234 -0
- package/skills/yad-docs/templates/app/src/components/shared/Badge.tsx +28 -0
- package/skills/yad-docs/templates/app/src/components/shared/CommandPalette.tsx +213 -0
- package/skills/yad-docs/templates/app/src/components/shared/Icon.tsx +21 -0
- package/skills/yad-docs/templates/app/src/components/shared/Tooltip.tsx +42 -0
- package/skills/yad-docs/templates/app/src/data/components.ts +74 -0
- package/skills/yad-docs/templates/app/src/data/docSections.ts +231 -0
- package/skills/yad-docs/templates/app/src/data/paths.ts +2319 -0
- package/skills/yad-docs/templates/app/src/data/referenceData.ts +392 -0
- package/skills/yad-docs/templates/app/src/data/roles.ts +145 -0
- package/skills/yad-docs/templates/app/src/data/types.ts +79 -0
- package/skills/yad-docs/templates/app/src/hooks/useAnimationQueue.ts +41 -0
- package/skills/yad-docs/templates/app/src/hooks/usePlayback.ts +100 -0
- package/skills/yad-docs/templates/app/src/hooks/useStakeholderFilter.ts +10 -0
- package/skills/yad-docs/templates/app/src/index.css +121 -0
- package/skills/yad-docs/templates/app/src/main.tsx +13 -0
- package/skills/yad-docs/templates/app/src/pages/RoleSelectPage.tsx +34 -0
- package/skills/yad-docs/templates/app/src/pages/StakeholderDocPage.tsx +98 -0
- package/skills/yad-docs/templates/app/src/pages/SubPathDetailPage.tsx +282 -0
- package/skills/yad-docs/templates/app/src/store/useAuthStore.ts +42 -0
- package/skills/yad-docs/templates/app/src/store/useFlowStore.ts +197 -0
- package/skills/yad-docs/templates/app/src/utils/iconMap.ts +46 -0
- package/skills/yad-docs/templates/app/tsconfig.app.json +28 -0
- package/skills/yad-docs/templates/app/tsconfig.json +7 -0
- package/skills/yad-docs/templates/app/tsconfig.node.json +26 -0
- package/skills/yad-docs/templates/app/vite.config.ts +10 -0
- package/skills/yad-docs-overview/SKILL.md +129 -0
- package/skills/yad-docs-overview/references/pipeline-model.md +102 -0
- package/skills/yad-docs-sync/SKILL.md +99 -0
- package/skills/yad-docs-sync/references/staleness.md +81 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: yad-docs-sync
|
|
3
|
+
description: 'The maintenance/CI reconciler for the generated docs sites — mirroring the `yad check` / `yad gate ci` drift pattern. Recomputes each site''s freshness hashes (per-epic: the artifact hash + repo HEADs; overview: config.yaml + module-help.csv + the overview diagram + skill count) and compares them to each docs-build.json baseline: a site is stale when any hash differs or its shell template is out of date. `--check` (default, read-only) reports which sites are stale and WHY; `--refresh` regenerates + redeploys each stale site; `--wire` commits the CI workflow that runs the check on push and rebuilds on staleness. Refresh is always a human/CI decision, never silent; docs are never a gate. Use when the user says "sync the docs", "check docs staleness", "refresh stale docs sites", or "wire the docs CI".'
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# SDLC — Sync the Docs Sites (the staleness reconciler)
|
|
7
|
+
|
|
8
|
+
**Goal:** Keep the generated docs sites in step with the artifacts they render — the per-epic sites
|
|
9
|
+
(`epics/EP-<slug>/docs-site/`) and the project overview (`docs/sdlc-site/`). It mirrors the `yad check`
|
|
10
|
+
/ `yad gate ci` reconcile pattern: it does **not** re-author content; it **detects drift** between each
|
|
11
|
+
site's `docs-build.json` baseline and the current inputs, and reports / refreshes / wires CI accordingly.
|
|
12
|
+
|
|
13
|
+
Docs are an output enrichment, so this skill is **never a gate** — it never touches `state.json`,
|
|
14
|
+
approvals, or the contract lock. Refreshing a stale site is always a **human or CI decision**, never
|
|
15
|
+
silent (the same discipline as `yad repo refresh`).
|
|
16
|
+
|
|
17
|
+
## Conventions
|
|
18
|
+
|
|
19
|
+
- `{project-root}` resolves from the project working directory (the **product hub**).
|
|
20
|
+
- Per-epic baseline: `epics/EP-<slug>/.sdlc/docs-build.json` (written by `yad-docs`). Overview baseline:
|
|
21
|
+
`docs/sdlc-site/.docs-build.json` (written by `yad-docs-overview`).
|
|
22
|
+
- The hashing + build + deploy is the **`yad docs sync` CLI**'s job; the regeneration of a stale site is
|
|
23
|
+
delegated back to `yad-docs` / `yad-docs-overview` (the AI generation step). This skill orchestrates
|
|
24
|
+
the reconcile.
|
|
25
|
+
- The docs target is `.sdlc/docs.json` (`yad-connect-docs`).
|
|
26
|
+
- Speak in the configured `communication_language`; write documents in `document_output_language`.
|
|
27
|
+
|
|
28
|
+
## Inputs
|
|
29
|
+
|
|
30
|
+
- `action` — `check` (default, read-only) | `refresh` | `wire`.
|
|
31
|
+
- `epic` — optional. Default: **sweep all epics** under `epics/` **plus the overview**. Given an
|
|
32
|
+
`EP-<slug>`, scope to that one site.
|
|
33
|
+
|
|
34
|
+
## On Activation
|
|
35
|
+
|
|
36
|
+
### Step 1 — Compute the current freshness hashes per target
|
|
37
|
+
For each target in scope, recompute its hash inputs (exact inputs in `references/staleness.md`):
|
|
38
|
+
|
|
39
|
+
- **Per-epic** (`epics/EP-<slug>/`): the `artifactHash` (sha256 of `epic.md` + `architecture.md` +
|
|
40
|
+
`contract.md` CONTRACT-SURFACE + `ui-design.md` + each story) **and** `repoHeads` (current
|
|
41
|
+
`git -C <path> rev-parse HEAD` for each repo in `epic.repos`).
|
|
42
|
+
- **Overview** (`docs/sdlc-site/`): sha256 of `skills/sdlc/config.yaml` + `skills/sdlc/module-help.csv`
|
|
43
|
+
+ `docs/diagrams/sdlc-overview.mmd` + the current `skillCount` (number of `yad-*` skills).
|
|
44
|
+
|
|
45
|
+
This is the same drift computation `yad check` runs for repos; reuse the repos.json HEAD-sha rule.
|
|
46
|
+
|
|
47
|
+
### Step 2 — Compare to each build manifest
|
|
48
|
+
Read each `docs-build.json` and compare. A site is **stale** when **any** of:
|
|
49
|
+
- its `artifactHash` differs (a rendered artifact moved), or
|
|
50
|
+
- any `repoHeads[<repo>]` differs from the repo's current HEAD (the code the components cite advanced —
|
|
51
|
+
the same head-sha staleness as `repos.json`), or
|
|
52
|
+
- for the overview, `config.yaml` / `module-help.csv` / the `.mmd` / `skillCount` moved, or
|
|
53
|
+
- its `templateVersion` < the current shell template version (the shell was upgraded).
|
|
54
|
+
|
|
55
|
+
A missing `docs-build.json` (a site never generated) counts as **stale → needs generate**.
|
|
56
|
+
|
|
57
|
+
### Step 3 — Act on `action`
|
|
58
|
+
- **`check`** (default, **read-only**) — print which sites are stale and **WHY**, in `yad check` drift
|
|
59
|
+
style: *which artifact moved* (name it), *which repo HEAD advanced* (`<repo>: <old>→<new>`), *config /
|
|
60
|
+
manifest / diagram / skill-count changed*, or *shell upgraded* (`templateVersion`). Writes nothing.
|
|
61
|
+
- **`refresh`** — for each stale site, re-run the generator (`yad-docs` for an epic site, `yad-docs-overview`
|
|
62
|
+
for the overview) to regenerate `src/data/*.ts` + theme + manifest, then redeploy via `yad docs deploy`
|
|
63
|
+
(degrading to build-only when no platform CLI). Report every site refreshed. **Never silent** — refresh
|
|
64
|
+
is a deliberate human/CI act, surfaced exactly like `yad repo refresh`.
|
|
65
|
+
- **`wire`** — commit the CI workflow (Step 4) that automates the check + rebuild.
|
|
66
|
+
|
|
67
|
+
### Step 4 — `wire`: the CI auto-rebuild workflow
|
|
68
|
+
Commit the platform-matched workflow (GitHub `.github/workflows/yad-docs.yml`, or a GitLab `pages` job at
|
|
69
|
+
`.gitlab/ci/yad-docs.yml` that must be `include:`d from the root `.gitlab-ci.yml` —
|
|
70
|
+
`include: { local: .gitlab/ci/yad-docs.yml }`, the same fragment+include shape as the `yad-checks` gates):
|
|
71
|
+
- on push, run **`yad docs sync --check`**; on detected staleness, **rebuild + deploy** the affected
|
|
72
|
+
site(s);
|
|
73
|
+
- carry **`[skip ci]`** on any commit the workflow itself makes (the regenerated source / manifest) and
|
|
74
|
+
a **concurrency group** (one docs deploy at a time) — both to **prevent deploy loops** (a rebuild must
|
|
75
|
+
not retrigger the workflow). See `references/staleness.md`.
|
|
76
|
+
|
|
77
|
+
### Step 5 — Report
|
|
78
|
+
Report per target: **fresh** or **stale (why)**; for `refresh`, what was regenerated + the deploy URL or
|
|
79
|
+
"build-only"; for `wire`, the workflow path committed. Never advance any epic; docs are not a gate.
|
|
80
|
+
|
|
81
|
+
## Hard rules
|
|
82
|
+
|
|
83
|
+
- **Refresh is never silent.** A stale site is *reported*; regenerating + redeploying is a human or CI
|
|
84
|
+
decision (the `yad repo refresh` discipline). `check` is strictly read-only.
|
|
85
|
+
- **Docs are never a gate.** This skill never touches `state.json`, `approvals.json`, or
|
|
86
|
+
`contract-lock.json`. Staleness blocks nothing in the SDLC; it only flags out-of-date docs.
|
|
87
|
+
- **HEAD-sha staleness, reused.** Repo drift uses the exact `repos.json` `syncedHead`-vs-current-HEAD
|
|
88
|
+
rule. The overview uses config + manifest + diagram + skill-count.
|
|
89
|
+
- **Loop-prevention is mandatory in CI.** The wired workflow must carry `[skip ci]` on its own commits
|
|
90
|
+
and a concurrency group so a deploy never retriggers a deploy.
|
|
91
|
+
- **Reconcile, don't re-author.** This skill detects drift and delegates regeneration to `yad-docs` /
|
|
92
|
+
`yad-docs-overview`; it does not generate `src/data/*.ts` itself.
|
|
93
|
+
|
|
94
|
+
## Reference
|
|
95
|
+
- The manifest schema (per-epic + overview), the exact hash inputs, the head-sha staleness rule, and the
|
|
96
|
+
CI loop-prevention note: `references/staleness.md`.
|
|
97
|
+
- The generators this delegates to: `../yad-docs/SKILL.md`, `../yad-docs-overview/SKILL.md`.
|
|
98
|
+
- The docs target it deploys to: `../yad-connect-docs/SKILL.md`.
|
|
99
|
+
- The drift / refresh discipline this mirrors: `../yad-connect-repos/SKILL.md` (HEAD-sha staleness).
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# Docs staleness — manifests, hash inputs, and the CI loop note
|
|
2
|
+
|
|
3
|
+
`yad-docs-sync` reconciles each generated site against a **build manifest** (`docs-build.json`) written
|
|
4
|
+
when the site was last generated. A site is **stale** when the manifest's recorded hashes no longer match
|
|
5
|
+
the current inputs, or its shell template is out of date. This mirrors the `repos.json`
|
|
6
|
+
`syncedHead`-vs-current-HEAD drift rule used across the SDLC.
|
|
7
|
+
|
|
8
|
+
## Build manifest schema
|
|
9
|
+
|
|
10
|
+
### Per-epic — `epics/EP-<slug>/.sdlc/docs-build.json` (written by `yad-docs`)
|
|
11
|
+
|
|
12
|
+
```json
|
|
13
|
+
{
|
|
14
|
+
"builtAt": "<YYYY-MM-DD>",
|
|
15
|
+
"theme": "design.json | DESIGN.md | default",
|
|
16
|
+
"artifactHash": "<sha256 of epic.md + architecture.md + contract.md CONTRACT-SURFACE + ui-design.md + each story>",
|
|
17
|
+
"repoHeads": { "<repo>": "<HEAD sha>" },
|
|
18
|
+
"deployUrl": "<url or null>",
|
|
19
|
+
"templateVersion": "<shell template version>"
|
|
20
|
+
}
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Overview — `docs/sdlc-site/.docs-build.json` (written by `yad-docs-overview`)
|
|
24
|
+
|
|
25
|
+
```json
|
|
26
|
+
{
|
|
27
|
+
"builtAt": "<YYYY-MM-DD>",
|
|
28
|
+
"theme": "yadflow-brand",
|
|
29
|
+
"artifactHash": "<sha256 of config.yaml + module-help.csv + docs/diagrams/sdlc-overview.mmd>",
|
|
30
|
+
"skillCount": <number of yad-* skills>,
|
|
31
|
+
"deployUrl": "<url or null>",
|
|
32
|
+
"templateVersion": "<shell template version>"
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Exact hash inputs
|
|
37
|
+
|
|
38
|
+
| Target | `artifactHash` inputs | head inputs |
|
|
39
|
+
|--------|-----------------------|-------------|
|
|
40
|
+
| **per-epic** | `epic.md` + `architecture.md` + `contract.md` **CONTRACT-SURFACE only** + `ui-design.md` + **each** `stories/*.md` (concatenated in stable story-id order, hashed sha256) | `repoHeads`: `git -C <path> rev-parse HEAD` for each repo in `epic.repos` |
|
|
41
|
+
| **overview** | `skills/sdlc/config.yaml` + `skills/sdlc/module-help.csv` + `docs/diagrams/sdlc-overview.mmd`, concatenated in that order, hashed sha256 (`skillCount` is an informational manifest field, not a hash input — `module-help.csv` already moves when the skill set does) | — (no repos) |
|
|
42
|
+
|
|
43
|
+
Because `yad-docs` generates `src/data/*.ts` **deterministically** (stable-ID sort, fixed key order, no
|
|
44
|
+
embedded timestamps), an unchanged input set re-hashes identically — so a hash move means a *real*
|
|
45
|
+
content move, not a regeneration artifact. The contract uses the **CONTRACT-SURFACE block only** so
|
|
46
|
+
non-surface edits to `contract.md` don't churn the docs.
|
|
47
|
+
|
|
48
|
+
## Staleness rule
|
|
49
|
+
|
|
50
|
+
A site is **stale** when ANY holds:
|
|
51
|
+
|
|
52
|
+
1. recomputed `artifactHash` ≠ manifest `artifactHash` — a rendered artifact moved (name it in the report);
|
|
53
|
+
2. for any repo, current HEAD ≠ manifest `repoHeads[<repo>]` — the cited code advanced (`<repo>:
|
|
54
|
+
<old>→<new>`). **Identical to the `repos.json` `syncedHead` staleness rule** — and, as there, a stale
|
|
55
|
+
repo is *flagged*, never auto-refreshed: the `code-context` itself is refreshed by a human via
|
|
56
|
+
`yad repo refresh`, and the docs are regenerated only on an explicit `refresh`/CI decision;
|
|
57
|
+
3. (overview) `config.yaml` / `module-help.csv` / the `.mmd` moved — the pipeline changed (this is what
|
|
58
|
+
enforces "the overview regenerates whenever the workflow definition or skill set changes"); or the
|
|
59
|
+
`templateVersion` (the yad CLI version) advanced — the doc shell upgraded;
|
|
60
|
+
4. manifest `templateVersion` < the current shell template version — the `templates/app/` shell was
|
|
61
|
+
upgraded, so every site should re-copy it;
|
|
62
|
+
5. the `docs-build.json` is **missing** — the site was never generated (treat as stale → generate).
|
|
63
|
+
|
|
64
|
+
`check` reports which of these tripped and why; `refresh` regenerates + redeploys; neither blocks any
|
|
65
|
+
SDLC step (docs are never a gate).
|
|
66
|
+
|
|
67
|
+
## CI loop-prevention note
|
|
68
|
+
|
|
69
|
+
The `wire` workflow (`.github/workflows/yad-docs.yml`, or the GitLab `pages` job at
|
|
70
|
+
`.gitlab/ci/yad-docs.yml` included from the root `.gitlab-ci.yml`) runs
|
|
71
|
+
`yad docs sync --check` on push and rebuilds + deploys on staleness. Because the rebuild **commits** the
|
|
72
|
+
regenerated `src/data/*.ts` + refreshed `docs-build.json`, that commit would re-trigger the same workflow
|
|
73
|
+
— a deploy loop. Two guards, both mandatory:
|
|
74
|
+
|
|
75
|
+
- **`[skip ci]`** in the message of any commit the workflow itself makes (the regenerated source +
|
|
76
|
+
manifest), so the workflow does not re-fire on its own output;
|
|
77
|
+
- a **concurrency group** (e.g. `concurrency: { group: yad-docs-deploy, cancel-in-progress: true }`) so
|
|
78
|
+
at most one docs build/deploy runs at a time, and a queued one is superseded rather than stacking.
|
|
79
|
+
|
|
80
|
+
Together these make the CI rebuild idempotent: a push that moves an artifact deploys exactly one fresh
|
|
81
|
+
site, and the resulting bot commit does not start another round.
|