Files
lefarcen da7c4ae051 fix(web): rank Community "Newest" by shipped publishedAt, not local install timestamps (#5597)
* fix(web): rank Community "Newest" by shipped publishedAt, not local install timestamps

The Community gallery Newest toggle sorted by the installed-record
updatedAt/installedAt. Those are stamped when a machine seeds its own
database, so a fresh install (or an upgrade that re-stamps the catalog)
writes the whole bundled catalog milliseconds apart in folder-walk
order — Newest showed reverse walk order (roughly reverse-alphabetical),
unrelated to publication recency.

Root-cause fix: bundled templates now ship a real publication date.

- packages/contracts: add optional manifest field publishedAt (ISO 8601).
- apps/web sortByNewest: freshness = publishedAt when parseable, else
  updatedAt (right signal for user-installed plugins); tie-breaks and
  stability unchanged.
- plugins/_official: backfill publishedAt into all 460 bundled manifests
  from each folder's first-appearance commit date in upstream git
  history.
- e2e: repository-resource guard requiring every bundled manifest to
  declare a parseable publishedAt, so the signal cannot silently erode.
- docs: field reference entries in plugins-spec (en + zh-CN).

Issue: https://plane.powerformer.net/open-design/projects/49832a02-3158-4faf-bf2f-d0e39c40c7e6/issues/ca0778af-97f5-4fc0-bc63-739280904979

Generated-By: looper 0.0.0-dev (runner=worker, agent=claude-code)

* worker: 模板用最新筛选,筛选出来的不是最新的

Generated-By: looper 0.0.0-dev (runner=worker, agent=claude-code)

* fix(web): keep shipped appeal order inside same-publishedAt batches

Review follow-up (#5597, nettee): after the freshness tie on an equal
publishedAt, the comparator still consulted local updatedAt/installedAt,
which a fresh install stamps in folder-walk order — so every
same-publication batch (largest: 322 manifests on one catalog date)
re-sorted per machine instead of keeping the shipped visual-appeal
ranking. Same-publishedAt records now preserve their incoming position;
local timestamps break ties only when at least one side has no usable
publishedAt. Adds the requested regression spec pinning
same-publishedAt / different-updatedAt records.

Generated-By: looper 0.0.0-dev (runner=worker, agent=claude-code)

* fix(web): gate publishedAt freshness to bundled records; untrack oversized looper attachment

Review follow-up (#5597, nettee round 2): publishedAt was overriding
updatedAt for every visible plugin, so a user-installed github/local/
marketplace plugin carrying an old manifest publishedAt would be buried
behind bundled templates despite a newer local install. publishedAtMs
now returns null for non-bundled records — "Newest" means install
recency for user installs, catalog publication for bundled ones. Adds
the requested regression (non-bundled, old publishedAt, newer
updatedAt) and clarifies the field docs (en + zh-CN).

CI repair: commit 578f7a9 tracked .looper-attachments/bug13_1.png
(3.8MB bug screenshot), tripping the Static gate 1MiB blob guard and
the Validate workspace aggregate. Untrack it and gitignore
.looper-attachments/ so harness attachments stay out of the repo.

Generated-By: looper 0.0.0-dev (runner=worker, agent=claude-code)
2026-07-14 08:43:57 +00:00

114 lines
6.1 KiB
JSON
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"$schema": "https://open-design.ai/schemas/plugin.v1.json",
"specVersion": "1.0.0",
"name": "design-system-default",
"title": "Neutral Modern",
"title_i18n": {
"zh-CN": "中性现代",
"zh-TW": "中性現代",
"ja": "ニュートラルモダン",
"ko": "뉴트럴 모던",
"de": "Neutral Modern",
"fr": "Moderne Neutre",
"ru": "Нейтральный Современный",
"es": "Moderno Neutral",
"pt-BR": "Moderno Neutro",
"it": "Moderno Neutro",
"vi": "Hiện Đại Trung Tính",
"pl": "Neutralny Nowoczesny",
"id": "Modern Netral",
"nl": "Neutraal Modern",
"ar": "حديث محايد",
"tr": "Nötr Modern",
"uk": "Нейтральний Сучасний",
"en": "Neutral Modern"
},
"version": "0.1.0",
"publishedAt": "2026-05-12T07:18:16Z",
"description": "A clean, product-oriented default. Use when the brief doesn't call for a specific mood — good for B2B tools, dashboards, and utility pages.",
"description_i18n": {
"zh-CN": "简洁的产品导向默认风格。适用于没有特定情绪要求的场景——适合 B2B 工具、仪表板和实用页面。",
"zh-TW": "簡潔的產品導向預設風格。適用於沒有特定情緒要求的場景——適合 B2B 工具、儀表板和實用頁面。",
"ja": "すっきりとした製品志向のデフォルトスタイル。特定のムードが求められていない場合に使用 — B2Bツール、ダッシュボード、ユーティリティページに最適。",
"ko": "깔끔하고 제품 중심적인 기본 스타일. 특정 분위기가 필요하지 않을 때 사용 — B2B 도구, 대시보드, 유틸리티 페이지에 적합합니다.",
"de": "Ein klarer, produktzentrierter Standard. Verwenden Sie dies, wenn keine spezifische Stimmung gefordert ist — gut für B2B-Tools, Dashboards und Utility-Seiten.",
"fr": "Un style par défaut épuré et axé sur le produit. À utiliser lorsque le brief ne demande pas d'ambiance particulière — idéal pour les outils B2B, tableaux de bord et pages utilitaires.",
"ru": "Чистый, ориентированный на продукт стиль по умолчанию. Используйте, когда не требуется особое настроение — подходит для B2B-инструментов, дашбордов и служебных страниц.",
"es": "Un estilo predeterminado limpio y orientado al producto. Úsalo cuando no se requiera un ambiente específico — ideal para herramientas B2B, dashboards y páginas de utilidad.",
"pt-BR": "Um padrão limpo e orientado ao produto. Use quando o briefing não exigir um clima específico — bom para ferramentas B2B, dashboards e páginas utilitárias.",
"it": "Uno stile predefinito pulito e orientato al prodotto. Da usare quando il brief non richiede un mood specifico — ideale per strumenti B2B, dashboard e pagine utility.",
"vi": "Phong cách mặc định gọn gàng, hướng đến sản phẩm. Sử dụng khi không yêu cầu phong cách cụ thể — phù hợp cho công cụ B2B, dashboard và trang tiện ích.",
"pl": "Czysty, zorientowany na produkt styl domyślny. Użyj, gdy brief nie wymaga konkretnego nastroju — dobry dla narzędzi B2B, dashboardów i stron użytkowych.",
"id": "Gaya default yang bersih dan berorientasi produk. Gunakan saat tidak memerlukan nuansa khusus — cocok untuk alat B2B, dashboard, dan halaman utilitas.",
"nl": "Een schone, productgerichte standaard. Gebruik wanneer de briefing geen specifieke sfeer vraagt — geschikt voor B2B-tools, dashboards en utiliteitspagina's.",
"ar": "نمط افتراضي نظيف وموجه نحو المنتج. استخدمه عندما لا يتطلب الموجز مزاجاً محدداً — مناسب لأدوات B2B ولوحات المعلومات والصفحات الوظيفية.",
"tr": "Temiz, ürün odaklı bir varsayılan stil. Belirli bir ruh hali gerektirmeyen durumlar için kullanın — B2B araçları, kontrol panelleri ve yardımcı sayfalar için idealdir.",
"uk": "Чистий, орієнтований на продукт стиль за замовчуванням. Використовуйте, коли не потрібен специфічний настрій — підходить для B2B-інструментів, дашбордів та службових сторінок.",
"en": "A clean, product-oriented default. Use when the brief doesn't call for a specific mood — good for B2B tools, dashboards, and utility pages."
},
"license": "MIT",
"tags": [
"design-system",
"first-party",
"design",
"starter"
],
"od": {
"kind": "scenario",
"taskKind": "new-generation",
"mode": "design-system",
"scenario": "design",
"surface": "web",
"useCase": {
"query": {
"en": "Generate a {{artifactKind}} using the Neutral Modern design system. Stay faithful to its colour palette, typography, spacing, iconography, and component vocabulary as documented in DESIGN.md.",
"zh-CN": "使用这个插件完成以下任务:Generate a {{artifactKind}} using the Neutral Modern design system. Stay faithful to its colour palette, typography, spacing, iconography, and component vocabulary as documented in DESIGN.md."
}
},
"inputs": [
{
"name": "artifactKind",
"label": "Artifact kind",
"type": "select",
"options": [
"landing page",
"dashboard",
"marketing site",
"app screen"
],
"default": "landing page"
},
{
"name": "brief",
"label": "Brief",
"type": "text",
"placeholder": "What should the page communicate?"
}
],
"context": {
"designSystem": {
"ref": "default",
"primary": true
},
"assets": [
"./DESIGN.md"
]
},
"pipeline": {
"stages": [
{
"id": "generate",
"atoms": [
"file-write",
"live-artifact"
]
}
]
},
"capabilities": [
"prompt:inject",
"fs:write"
]
}
}