Adds a new `--to zip` (and `--to all`) tools-pack Windows build target that
produces a portable `.zip` from the cached `win-unpacked` tree using the
bundled 7z. The zip lays files at the archive root so users can extract it
anywhere and launch `Open Design.exe` without going through the NSIS
installer, addressing the no-install download request.
Release plumbing is updated to publish the portable zip and its sha256
beside the existing installer on R2 for beta, preview, and stable channels
(default on, gated by `WINDOWS_INCLUDE_ZIP`/`WIN_INCLUDE_ZIP`). The
electron-updater `latest.yml` feed continues to point only at the
installer; the zip is a manual-download convenience and is intentionally
excluded from the in-app updater.
Closes#1121
Generated-By: looper 0.0.0-dev (runner=worker, agent=claude-code)
Co-authored-by: libertecode <libertecode@proton.me>
* feat(landing-page): synthesize fallback preview cards for instruction skills
The skill catalog renders a diagonal-stripe placeholder for any skill
without a runnable example.html, which leaves ~70% of /skills/ as a
field of bare grey thumbs (instruction skills like copywriting,
creative-director, color-expert, brainstorming have no static demo
because their output depends on the agent's input).
Synthesize a typographic editorial card from each SKILL.md frontmatter
and screenshot it through the same Playwright pipeline that handles
real demos, so every catalog row carries a thumbnail. Cards include:
- OPEN DESIGN · SKILL top label + Nº NNN index (1..96 over the
instruction subset, sorted by od.featured then alphabetical)
- Big Playfair Display slug with a coral dot accent
- Italic serif description clamped to 3 lines
- mode/category chips + "Curated from <author>" attribution
- Warm-paper background with a subtle 135° stripe to thread the
landing's existing visual language
Bundle a few related improvements caught while building this:
- SkillRecord gains a `kind: 'instruction' | 'template'` field so
the detail page can render differently per kind (instruction
skills now render the SKILL.md body inline as "About this skill",
template skills keep the click-to-expand iframe demo).
- Catalog row thumbnails switch from the bespoke IntersectionObserver
pipeline to native `loading="lazy"` (with eager + fetchpriority=high
on the first 3). The observer's swap latency stranded mid-list
rows on the SVG placeholder during fast scrolls; native lazy uses
the browser's 1250-3000px lookahead so the placeholder flash is
gone.
- precise-lazyload rootMargin bumped to 1500px for any remaining
data-precise-src callers.
- CI cache key for generated previews now folds in
fallback-preview-card.ts so a template tweak invalidates the cache.
* feat(landing-page): rebuild plugins library to mirror in-app taxonomy
The marketing site's `/skills/`, `/templates/`, `/systems/`, `/craft/`
top-level entries were organized around author-supplied `od.mode` /
`od.scenario` taxonomies that visitors never see inside Open Design
itself. The in-app Plugins home (`apps/web/src/components/plugins-home/`)
groups every bundled plugin by the artifact it produces — Prototype,
Live Artifact, Slides, Image, Video, HyperFrames, Audio — and that's
the language users encounter the moment they open the product.
This PR rebuilds the public library around the same taxonomy and the
same data source so a visitor reading "Templates · 231" on the
marketing site sees the same 231 inside the app.
## What changes
- New top-level `/plugins/` hub: four tiles (Templates, Skills,
Systems, Craft) with live counts pulled straight from
`plugins/_official/<bucket>/<slug>/open-design.json` — the daemon's
bundled-plugin registry.
- `/plugins/templates/` lists every bundled plugin that lands in one
of the seven artifact kinds. Seven sub-routes
(`/plugins/templates/prototype/`, `/deck/`, `/image/`, `/video/`,
`/hyperframes/`, `/audio/`, `/live-artifact/`) carry the same chip
rail with an active state, so visitors can switch artifact kinds
with one click without losing the rail.
- Each artifact-kind sub-route shows a Scene chip rail when the kind
has scene buckets (Prototype / Slides / Image / Video each get
five-six). The Scene filter runs client-side via inline `style.display`
toggles; URLs stay one-per-kind so we don't multiply 25 × 18 locales
worth of static pages just for filter combinations.
- `/plugins/skills/` collects the instruction-only entries (mode
doesn't fit any of the seven kinds) — copywriting, color theory,
creative direction, brainstorming, etc.
- `/plugins/systems/` lists the 150 bundled design systems via the
legacy SystemCard renderer (palette swatches, tagline) so the
visual treatment matches the in-product library.
- `/plugins/craft/` keeps the existing craft principles list.
- `/plugins/<manifest-id>/` detail pages built from manifest metadata:
hero (poster image or playable Cloudflare Stream MP4 for video
templates), author / mode / scenario / tags, GitHub source link.
Author URLs pointing at the `nexu-io` org redirect to the
`nexu-io/open-design` repo so the attribution is actionable.
- Header dropdown labelled "Plugins" with the four sub-routes; footer
Library column updated to match.
- Old marketplace registry pages under `/plugins/` and
`/[locale]/plugins/` removed (they were a dormant placeholder UI;
the actual manifests it tried to load lived nowhere). The rest of
the legacy plugin-registry loader stays intact for any other
consumer.
## Preview generation
Bundled plugins ship `od.preview.poster` URLs on R2 for image and
video templates; those are used directly. The other 293 entries
(html-mode examples, design-systems, scenarios) had no poster, so
`generate-previews.ts` was extended to:
1. Screenshot a local `example.html` referenced by `od.preview.entry`
when present (134 examples).
2. Synthesize the same typographic editorial card the SKILL.md
fallback uses, sourced from manifest title / description / mode /
author (159 systems / scenarios / misc).
Output lands at `public/previews/plugins/<manifest-id>.png`. The
catalog loader checks for the local file when the manifest carries no
poster URL, so the row's `<img src>` always has something to point at.
Result: every catalog row and every detail page has a thumbnail;
visiting `/plugins/templates/video/` shows the same 48 entries the
in-app Plugins home shows, hyperframes the same 13, etc.
## Counts
- Templates: 231 (Prototype 59 + Slides 59 + Image 46 + Video 48 +
HyperFrames 13 + Audio 1 + Live Artifact 5)
- Skills: 15
- Systems: 150
- Craft: 11
Atoms (13 infrastructure plugins, `od.kind === 'atom'`) are filtered
to mirror the in-app behaviour.
* fix(landing-page): use Astro 6 render() helper for SKILL.md body
Astro 6 dropped `entry.render()` in favour of a top-level `render(entry)`
helper imported from `astro:content`. The instruction-kind skill detail
page was still using the legacy method, which compiled locally on Astro
6 only because tsx ignored the missing prototype method, but `astro
check` (run in CI) flagged it as ts(2551) and broke the workflow.
---------
Co-authored-by: Joey-nexu <joeylee12629@gmail.com>
PR #2461 sync prep — resolves 14 conflicts merging 84 main-side commits
on top of 58 release-side commits accumulated during the 0.8.0 cycle.
Resolution summary:
Take main (theirs) where main carried deliberate forward progress:
- apps/web/src/components/PluginCard.tsx — 7 hunks, i18n migration:
hardcoded English aria-labels/titles replaced with t() calls keyed
on pluginCard.* (all 8 keys verified present in en.ts).
- apps/web/src/components/TasksView.tsx — 1 hunk, source-ingestion
feature: sortedRoutines (newest-first), sourceIngestionTemplates,
patchSourceForm, submitSourceIngestion. activeCount/pausedCount
semantics preserved (now keyed on sortedRoutines, count unchanged).
- e2e/ui/app.test.ts — new node:fs/promises + tmpdir + path + @/timeouts
imports needed by main-side test helpers.
- e2e/ui/settings-local-cli-codex-fallback.test.ts — menu-dismissal
helper block added by main.
Keep both sides where each added a different field to the same object
literal:
- apps/web/src/components/ProjectView.tsx (locale + analyticsHints
spread).
- apps/web/src/components/DesignSystemFlow.tsx (locale + analyticsHints).
Take release (ours) where release carried deliberate work that ships
0.8.0:
- CHANGELOG.md — release-side 0.8.0 entry + PR link refs; main's
Unreleased section was the same body of work, now finalized.
- apps/landing-page/public/{apple-touch-icon,favicon}.png +
apps/web/public/app-icon.svg — release-side visual refresh assets
consistent with 0.8.0 stable ship.
- tools/pack/src/linux.ts — packageVersion const required by line 466;
taking main's empty line would build-error.
- e2e/ui/project-management-flows.test.ts +
e2e/ui/settings-api-protocol.test.ts +
e2e/ui/settings-memory-routines.test.ts — release-side release-smoke
hardening (shangxinyu1 + PerishFire) takes precedence on overlap.
Closes-issue / unblocks: PR #2461 sync release/v0.8.0 → main.
* fix(ci): fall back to manifest PR number for visual comments
* fix(ci): restore authoritative visual PR lookup
Generated-By: looper 0.8.1 (runner=fixer, agent=opencode)
* i18n: add translations for media provider coming soon section (#2415)
* i18n: add translations for media provider coming soon section
- Add 'settings.mediaProviderComingSoonHint' key to all 19 locales
- Replace hardcoded English strings in SettingsDialog.tsx with i18n keys
- Reuse existing 'tasks.comingSoon' and 'settings.agentInstall.docs' keys
- Resolves TODO(i18n) comment at line 5091
* fix: escape single quotes in translation strings
* fix: escape all single quotes in English translation string
* feat(release): upload browser sourcemaps to PostHog for packaged builds
Next.js was emitting minified JS with no browser sourcemaps, so PostHog
Error Tracking surfaces frames like fO / fz / s4 / tD instead of real
file:line locations. This wires up the full pipeline:
- apps/web/next.config.ts: enable productionBrowserSourceMaps so next build
emits .js.map alongside each chunk.
- tools/pack/src/web-sourcemaps.ts: new helper that runs after next build
and before any packaging step copies the web output into the Electron
resources. Uses @posthog/cli to inject chunk IDs and upload sourcemaps
to PostHog, then ALWAYS strips every .map under .next/static so source
never ships inside an installer (saves ~14 MB per packaged image too).
- tools/pack/src/{mac/workspace,win/app,linux}.ts: call processWebSourcemaps
immediately after the @open-design/web build step.
- tools/pack/src/config.ts: read POSTHOG_CLI_API_KEY + POSTHOG_CLI_PROJECT_ID
(with POSTHOG_PERSONAL_API_KEY / POSTHOG_PROJECT_ID aliases) and expose
them on ToolPackConfig with the same shape as the existing posthogKey /
posthogHost fields.
- .github/workflows/release-{beta,preview,stable}.yml: pass the new secrets
through so all three release channels symbolicate stacks.
When the API key is missing (PR builds, forks, local contributor builds),
the helper logs and skips the upload — but still strips .map files. The
strip step is unconditional because shipping a sourcemap is equivalent to
shipping the source.
Adds tools/pack/tests/web-sourcemaps.test.ts covering: missing chunks dir
silently noop, no-map noop, strip-only path when credentials are absent,
recursive walker for nested subdirectories. CLI happy path is left to the
release workflow itself.
Required follow-up (cannot push from code): add a repo secret named
POSTHOG_CLI_API_KEY (the phx_ personal API key) and a repo var named
POSTHOG_CLI_PROJECT_ID (the numeric project id, 420348 for our project)
in nexu-io/open-design settings before merging.
* fix(web-sourcemaps): use management host for CLI, not ingest host
POSTHOG_HOST is the ingest URL (us.i.posthog.com) used by the runtime SDK
to POST events to /capture/. The @posthog/cli sourcemap upload talks to
the **management** API (us.posthog.com) and gets a 404 on the ingest
host. The two are not interchangeable.
Adds a separate `posthogCliHost` field on ToolPackConfig sourced from
POSTHOG_CLI_HOST (with no fallback to POSTHOG_HOST). When the env is
unset the @posthog/cli defaults to the US Cloud app host on its own,
which is correct for our project — so this PR doesn't need a new repo
variable for it.
---------
Co-authored-by: Nicholas-Xiong <2482929840@qq.com>
Conflict resolved by taking origin/main:
- apps/web/src/components/EntryNavRail.tsx design-systems rail
button icon name palette-filled (release-side) -> blocks (main);
main's icon swap is part of the more recent design-systems rail
pass.
Conflicts resolved by taking origin/main on all six points:
- apps/web/src/components/HomeHero.tsx:479-487 brand div removed
(main dropped the .home-hero__brand wrapper; the release-side visual
refresh still had it).
- apps/web/src/components/HomeHero.tsx:894-898 attach Icon size
18 (main's update) replaces 20 from release.
- apps/web/src/components/HomeHero.tsx:913-927 submit button uses
<Icon name="arrow-up" size={22} /> (main's component refactor)
instead of the release-side inline SVG.
- apps/web/src/components/EntryShell.tsx:578-582 Discord Icon size
14 (main) instead of 16 (release).
- apps/web/src/styles/home/home-hero.css drop .home-hero__brand /
__brand-mark / __brand-name rules — main removed both the component
div and these CSS rules together; keeping the CSS would be dead code.
- apps/web/src/styles/home/entry-layout.css Discord badge icon color
#5865f2 (main, the brand color introduced by PR #2386) instead of
release's neutral var(--text-strong).
* test(e2e): harden extended coverage contracts
* docs(testing): add e2e hardening status
* fix(web): persist artifact chips after daemon runs
* ci: install playwright browsers for e2e vitest
* Fix daemon run recovery across reloads
Pin daemon-created runs to assistant messages immediately so hard reloads before the create response can reattach.
Replay terminal and active run events from the beginning on reload so restored turns keep assistant text, thinking events, produced files, and artifacts.
Fixes#2366Fixes#2368Fixes#2371
* test(e2e): preserve fake runtime selection across reload
* fix(web): scope daemon run recovery to daemon mode
* fix(e2e): remove duplicate delayed smoke flag
* fix(web): scope replay artifact recovery to current run
* fix(daemon): remove duplicate run-create pin
* feat(blog): daily 3-day Search Console traffic digest
Adds `blog-3day-report.yml` (cron 09:00 Asia/Shanghai) and a
companion `report-3day.ts` script that refreshes
`docs/blog-traffic-digest.md` once per day. The digest has two
sections:
- T-3 spotlight: posts published exactly three days ago, with their
3-day Search Analytics window plus current URL Inspection coverage
state.
- Rolling 30-day cohort: every post 1–30 days old with its latest
3-day Search Analytics window, sorted by impressions descending.
The workflow is read-only against Google APIs (no Indexing API,
no "request indexing" automation) and mirrors the secret / config
plumbing already used by `blog-indexing-monitor.yml`. Output lands
in a reviewable `automation/blog-traffic-digest` PR opened by the
open-design bot.
Also widens `querySearchAnalytics` to accept `windowDays: 3 | 7 | 28`
and updates `docs/blog-indexing-automation.md` with the new pipeline.
Co-authored-by: Cursor <cursoragent@cursor.com>
* feat(seo): post daily Search Console report to Feishu
Co-authored-by: Cursor <cursoragent@cursor.com>
* feat(blog): push traffic digest to Feishu
Emit a compact JSON summary from the daily 3-day traffic digest and add a Feishu custom bot sender for the summary card. Wire the workflow to send the card when `FEISHU_BLOG_DIGEST_WEBHOOK` is configured while keeping Markdown PR output as the source of truth.
Co-authored-by: Cursor <cursoragent@cursor.com>
* feat(landing-page): add Discord routing CTAs
Add a lightweight Discord pill to the landing hero and Discord links in the landing and blog footers so community routing is visible without displacing the primary GitHub and download CTAs.
Add a blog-ending conversion card that points guide and use-case readers to the internal workflows library, while keeping Discord as a secondary support path.
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: ashley li <ashleyli@ashleydeMacBook-Air-2.local>
Co-authored-by: Cursor <cursoragent@cursor.com>
Set an explicit base branch for generated indexing status PRs so create-pull-request works after SHA-based checkouts.
Co-authored-by: ashley li <ashleyli@ashleydeMacBook-Air-2.local>
Co-authored-by: Cursor <cursoragent@cursor.com>
* ci: add PR-author and stale-issue inactivity workflows
Adds two queue-management automations:
- pr-author-inactivity: reminds PR authors after 72h of inactivity
following human reviewer/maintainer feedback (issue comments,
non-approval reviews, or inline review comments) and closes after
120h. Author response is detected via issue comments, inline review
replies, or commit/force-push events. Bot-authored reviews are
intentionally excluded so authors are not pressured by automated
nits alone.
- stale-issues: marks issues stale after 30 days of inactivity and
closes after a further 7 days. Exempts good first issue, help
wanted, and security labels. A pre-step also auto-applies
'exempt-from-stale' to issues opened by org members/owners/
collaborators, since actions/stale only supports label-based
exemptions. PR processing is disabled (handled by the workflow
above).
* fix: limit PR inactivity feedback to trusted reviewers
Generated-By: looper 0.0.0-dev (runner=fixer, agent=opencode)
* fix: count author PR reviews as inactivity responses
Generated-By: looper 0.0.0-dev (runner=fixer, agent=opencode)
Use full workspace installs for blog indexing workflows so root postinstall can resolve workspace build dependencies, and enrich sitemap metadata for blog URLs from frontmatter dates.
Co-authored-by: ashley li <ashleyli@ashleydeMacBook-Air-2.local>
Co-authored-by: Cursor <cursoragent@cursor.com>
The other workflows under .github/workflows declare explicit
`permissions:` blocks that scope their GITHUB_TOKEN to the minimum
required (contents: read for build-only flows). `nix-check.yml` was
the lone outlier and inherited the repository's default token
permissions instead.
Add `permissions: { contents: read }` to align with the rest of the
workflow suite and follow GitHub's least-privilege workflow guidance.
No behavior change: the job only reads the repo, runs `nix flake
check`, and uploads a logs artifact on failure (which uses an action
that already declares its own permissions internally).
Co-authored-by: nicejames <nicejames@gmail.com>
* fix(ci): avoid duplicate nix-check runs on PR branches
* fix(ci): keep nix-check on main pushes
Restore the nix-check push trigger for main-only updates while still avoiding duplicate PR-branch runs.
Generated-By: looper 0.0.0-dev (runner=fixer, agent=opencode)
* docs: point 0.8.0 preview contributors at main, not preview/v0.8.0
0.8.0 has been merged into main (#1832). Anywhere we used to tell
contributors to checkout / PR against preview/v0.8.0 was actively
mis-routing new PRs. Update:
- docs/preview-v0.8.0-announcement.md + zh-CN: status line, Branch row,
source-build checkout, and 'open a PR against' guidance now point at
main
- .github/ISSUE_TEMPLATE/bug-report.yml + feature-request.yml: phrase
the 'use the preview template' nudge as 'about the 0.8.0 preview
features (now on main)' instead of 'about the preview/v0.8.0 branch'
- .github/ISSUE_TEMPLATE/config.yml: same rewording for the contact link
- .github/ISSUE_TEMPLATE/preview-v0.8.0-feedback.yml: refresh the
description and the intro body so it reads as 'preview features
pre-tag', not 'features pre-merge'
The preview-v0.8.0-feedback template and preview/v0.8.0 label are
intentionally kept: 0.8.0 isn't tagged yet, so we still want a
dedicated lane for preview-features feedback.
* chore: stop treating preview/v0.8.0 as a live branch
Earlier in this PR we kept the preview-v0.8.0 surface area intact —
that was the wrong call. 0.8.0 is now on main; pretending there's a
parallel 'preview' branch in the templates, labels, and copy was going
to keep mis-routing contributors.
Drop:
- .github/ISSUE_TEMPLATE/preview-v0.8.0-feedback.yml (the dedicated
template that auto-applied the preview/v0.8.0 label and prefix)
- .github/ISSUE_TEMPLATE/config.yml contact_links entry pointing at it
- bug-report.yml + feature-request.yml nudges that sent users there
- The Preview-v0.8.0-feedback link block from both announcement docs
(replaced with normal bug-report / feature-request links)
Rename:
- docs/preview-v0.8.0-announcement.{md,zh-CN.md}
-> docs/v0.8.0-announcement.{md,zh-CN.md}
so the on-disk doc title reads as a 0.8.0 announcement, not a
branch-specific one. No other repo file referenced the old paths.
The preview/v0.8.0 label and branch themselves are intentionally
untouched — those are separate ops the maintainer will decide on
later. This PR only removes mentions inside the repo.
* chore: keep 0.8.0 preview-feedback template as a chooser-level ad
The previous commit deleted preview-v0.8.0-feedback.yml entirely. Bring
it back, but reframe it: it's now the dedicated 0.8.0 lane in the
issue chooser — a high-visibility surface that tells visitors "0.8.0
is here as a preview, please share what you noticed."
- Renamed in the chooser to "Open Design 0.8.0 — preview feedback"
- Title prefix shortened from "[preview/v0.8.0] " to "[0.8.0] " so the
branch slug no longer leaks into issue titles
- label preview/v0.8.0 still auto-applied (the label entity is still in
use across 26 issues; maintainer will decide on its fate separately)
- Area dropdown widened from "Skills + Automations" to cover the
actual 0.8.0 surface (plugins, headless, agent flow, desktop shell)
- Intro body rewritten to read as a preview-release ad, not a
feature-branch tester request
Announcement docs (English + Chinese) also routed their "open an
issue" CTA back through this template instead of the generic bug-report
/ feature-request links — same advertising goal.
Currently the artifact only contains vitest.log + the tools-pack build
log. The packaged daemon's own stdout/stderr lands in
$RUNNER_TEMP/tools-pack/runtime/linux/namespaces/<ns>/logs/desktop/latest.log,
outside the artifact path, so when 'headless-root.json not written
within 35s' fires we have no signal on what the spawned child actually
did.
Copy the runtime logs/ and runtime/ subdirectories into the report dir
before upload so the artifact captures daemon/web sidecar startup
output, identity markers, and per-app state JSON.
The v0.8.0 launch doc explicitly lists Linux as "coming soon" — the
packaged Linux headless runtime is known-incomplete in this release.
Keep the smoke job running so we keep collecting signal, but don't block
PRs on it until the Linux client lands.
Re-enable (drop continue-on-error) once the Linux packaged client is
ready in a future release.
* feat(landing): add blog indexing automation
Automate supported blog discovery checks through sitemap submission, URL Inspection monitoring, IndexNow notifications, and guarded SEO CI checks.
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix(landing): support oauth for blog indexing
Use OAuth refresh-token auth as the preferred Search Console path while keeping service-account auth as a fallback, so the indexing workflows can run despite GSC service-account invite issues.
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix(landing): tighten blog indexing observability
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: ashley li <ashleyli@ashleydeMacBook-Air-2.local>
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs: plan linux client issue 709
* fix: complete linux headless lifecycle routing
* feat: add linux packaged inspect
* test: add linux headless packaged smoke
* ci: add linux headless packaged smoke
* ci: smoke linux AppImage release artifacts
* docs: document linux packaged client status
* chore: finalize linux client audit remediation
* docs: add linux client publication packet
* test: harden linux client smoke coverage
* ci: preserve linux smoke audit evidence
* refactor: consolidate linux e2e helpers
Move pathExists and the desktop/web/daemon app-key array out of
linux.spec.ts into linux-helpers.ts, where expectPathInside and
linuxUserHome already live. Keeps the spec file focused on tests and
the helpers file as the canonical home for shared Linux e2e utilities.
* fix: move linux e2e helpers to lib
* fix: address linux release review blockers
* fix: drop npm dependency from containerized linux build
writeAssembledApp() previously called runNpmInstall() which executed
`npm install` directly. Inside the containerized build path,
electronuserland/builder:base strips npm/npx/corepack, so the inner
tools-pack build would fail at the assembled-app install step.
Route the install through OD_TOOLS_PACK_PNPM_BIN: buildDockerArgs sets
the env to the standalone pnpm binary it bootstraps, and the new
resolveProductionInstallCommand helper consumes that env to run
`<bin> install --prod --no-lockfile --config.node-linker=hoisted`.
Host invocations with no env set keep the prior npm behavior.
--config.node-linker=hoisted preserves the flat node_modules layout
that electron-builder packs the same way as npm-installed trees.
New tests cover the resolver branches and assert the docker-arg-to-
resolver chain end-to-end so reviewers can see the container's inner
build receives the env that switches its install away from npm.
* fix: harden linux container bootstrap
* fix: validate desktop marker liveness in headless cleanup
cleanup --headless previously skipped on any parseable desktop-root.json, trapping recovery when the AppImage had crashed and left a stale marker. Validate the marker the same way stopPackedLinuxApp does: if the PID is not in the live snapshot list, proceed through cleanup instead of skipping.
Extract the validation into validateDesktopAppImageMarker so the stop and cleanup paths share one definition of live and owned. Tests cover both branches: a stale marker drives cleanup to remove the runtime/output roots, while a live marker drives cleanup to skip and preserve them.
Following the rename of the feature branch from preview/0.8.0 to preview/v0.8.0
(to match the release/v0.7.0 convention), update all issue-template
references so the label, filename, and deep-link URL stay consistent.
Changes:
- git mv preview-0.8.0-feedback.yml → preview-v0.8.0-feedback.yml
- update labels reference, title prefix, display name, body copy
- update version placeholder example to 0.8.0-preview.2 (current build)
- update cross-references in bug-report.yml and feature-request.yml
- update config.yml first contact_link URL + about text