zz-meridian 0.35.0 → 0.37.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/README.md +29 -7
- package/dist/adopt.js +68 -40
- package/dist/cli.js +32 -33
- package/dist/command-flags.js +32 -0
- package/dist/context.js +2 -2
- package/dist/create.js +12 -6
- package/dist/files.js +36 -10
- package/dist/migrations.js +314 -53
- package/dist/ownership.js +8 -7
- package/dist/rebrand.js +6 -6
- package/dist/reconcile.js +35 -7
- package/dist/session.js +18 -52
- package/dist/update-session.js +11 -4
- package/dist/update.js +4 -5
- package/package.json +1 -1
- package/payload/.env.example +3 -2
- package/payload/CHANGELOG.md +317 -97
- package/payload/CONTRIBUTING.md +3 -3
- package/payload/LICENSE +21 -0
- package/payload/README.md +1 -1
- package/payload/app/(dashboard)/(home)/README.md +3 -1
- package/payload/app/(dashboard)/(home)/loading.tsx +6 -34
- package/payload/app/(dashboard)/(home)/page.tsx +1 -1
- package/payload/app/(dashboard)/business/README.md +1 -1
- package/payload/app/(dashboard)/business/loading.tsx +6 -32
- package/payload/app/(dashboard)/business/page.tsx +1 -1
- package/payload/app/(dashboard)/customers/README.md +1 -1
- package/payload/app/(dashboard)/customers/[id]/README.md +3 -3
- package/payload/app/(dashboard)/engineering/README.md +2 -2
- package/payload/app/(dashboard)/engineering/loading.tsx +6 -23
- package/payload/app/(dashboard)/engineering/page.tsx +1 -1
- package/payload/app/(dashboard)/error.tsx +7 -4
- package/payload/app/(dashboard)/keys/README.md +1 -1
- package/payload/app/(dashboard)/keys/actions.ts +33 -18
- package/payload/app/(dashboard)/layout.tsx +4 -4
- package/payload/app/(dashboard)/members/README.md +2 -2
- package/payload/app/(dashboard)/members/actions.ts +7 -7
- package/payload/app/(dashboard)/members/page.tsx +7 -5
- package/payload/app/(dashboard)/operations-tickets/README.md +1 -0
- package/payload/app/(dashboard)/operations-tickets/actions.ts +4 -4
- package/payload/app/(dashboard)/operations-tickets/page.tsx +12 -9
- package/payload/app/(dashboard)/requests/README.md +2 -2
- package/payload/app/(dashboard)/requests/[id]/README.md +12 -4
- package/payload/app/(dashboard)/requests/[id]/actions.ts +11 -4
- package/payload/app/(dashboard)/requests/[id]/page.tsx +4 -3
- package/payload/app/(dashboard)/services/README.md +2 -2
- package/payload/app/(dashboard)/services/loading.tsx +2 -9
- package/payload/app/(dashboard)/settings/README.md +4 -2
- package/payload/app/(dashboard)/settings/actions.ts +4 -4
- package/payload/app/(dashboard)/usage/README.md +2 -2
- package/payload/app/(dashboard)/usage/loading.tsx +2 -9
- package/payload/app/(dashboard)/usage/page.tsx +1 -1
- package/payload/app/api/assistant/route.ts +34 -13
- package/payload/app/api/export/requests/route.ts +9 -4
- package/payload/app/embed/error.tsx +2 -2
- package/payload/app/embed/now/README.md +1 -0
- package/payload/app/embed/now/view.tsx +3 -2
- package/payload/app/embed/proposal/README.md +1 -1
- package/payload/app/embed/proposal/view.tsx +3 -1
- package/payload/app/embed/requests/README.md +2 -2
- package/payload/app/embed/requests/view.tsx +4 -3
- package/payload/app/layout.tsx +5 -1
- package/payload/app/sign-in/README.md +7 -2
- package/payload/app/sign-in/actions.ts +13 -8
- package/payload/app/sign-in/panel.tsx +21 -5
- package/payload/app/system/(atlas)/[section]/[id]/page.tsx +8 -2
- package/payload/app/system/(atlas)/_article.tsx +28 -3
- package/payload/app/system/(atlas)/page.tsx +6 -6
- package/payload/app/system/preview/[section]/[card]/page.tsx +2 -1
- package/payload/app/system/preview/[section]/[card]/stage.tsx +3 -2
- package/payload/app/system/states/error/page.tsx +4 -6
- package/payload/app/system/states/error/view.tsx +9 -0
- package/payload/docs/agents.md +14 -8
- package/payload/docs/assistant.md +31 -7
- package/payload/docs/atlas-scenario-coverage.md +12 -12
- package/payload/docs/benchmark.md +1 -1
- package/payload/docs/data-layers.md +35 -16
- package/payload/docs/distribution.md +24 -10
- package/payload/docs/product-workspaces.md +3 -3
- package/payload/docs/skill-evals.md +1 -1
- package/payload/docs/start-a-dashboard.md +5 -2
- package/payload/docs/surfaces.md +8 -3
- package/payload/docs/testing.md +37 -2
- package/payload/docs/voice.md +1 -1
- package/payload/journeys/workspaces.ts +41 -30
- package/payload/next.config.ts +3 -11
- package/payload/package.json +1 -1
- package/payload/proxy.ts +12 -5
- package/payload/scripts/ask.ts +16 -5
- package/payload/scripts/assistant.ts +2 -0
- package/payload/scripts/audit.ts +30 -40
- package/payload/scripts/brand.ts +28 -18
- package/payload/scripts/check.ts +19 -24
- package/payload/scripts/contrast.ts +1 -1
- package/payload/scripts/fake-llm.ts +9 -12
- package/payload/scripts/interactions.ts +21 -15
- package/payload/scripts/keyboard.ts +21 -35
- package/payload/scripts/lib/answered.ts +1 -3
- package/payload/scripts/lib/args.ts +17 -0
- package/payload/scripts/lib/bin.ts +29 -0
- package/payload/scripts/lib/chrome.ts +27 -14
- package/payload/scripts/lib/context-check.ts +6 -2
- package/payload/scripts/lib/coverage.ts +20 -2
- package/payload/scripts/lib/data-url.ts +67 -43
- package/payload/scripts/lib/deep.ts +46 -4
- package/payload/scripts/lib/effective-manifest.ts +19 -0
- package/payload/scripts/lib/journey.ts +47 -18
- package/payload/scripts/lib/layer-rules.ts +24 -11
- package/payload/scripts/lib/nav-under.ts +25 -8
- package/payload/scripts/lib/routes.ts +16 -9
- package/payload/scripts/lib/sample.ts +9 -4
- package/payload/scripts/lib/sizes.ts +3 -2
- package/payload/scripts/lib/team-config.ts +25 -0
- package/payload/scripts/lib/update-session.ts +9 -4
- package/payload/scripts/live.ts +39 -36
- package/payload/scripts/navigate.ts +6 -23
- package/payload/scripts/perf.ts +5 -4
- package/payload/scripts/rail.ts +10 -12
- package/payload/scripts/registry.ts +12 -12
- package/payload/scripts/shot.ts +5 -8
- package/payload/scripts/sizes.ts +3 -3
- package/payload/scripts/tokens.ts +23 -8
- package/payload/scripts/verify.baseline.json +29 -29
- package/payload/scripts/verify.config.ts +14 -5
- package/payload/scripts/verify.ts +17 -20
- package/payload/scripts/vitals.ts +4 -1
- package/payload/skills/zz-meridian/SKILL.md +2 -2
- package/payload/skills/zz-meridian/references/agents.md +14 -8
- package/payload/skills/zz-meridian/references/cache.md +34 -22
- package/payload/skills/zz-meridian/references/customize.md +51 -26
- package/payload/skills/zz-meridian/references/data-layers.md +35 -16
- package/payload/skills/zz-meridian/references/existing-project.md +5 -3
- package/payload/skills/zz-meridian/references/live.md +18 -27
- package/payload/skills/zz-meridian/references/ownership.md +4 -3
- package/payload/skills/zz-meridian/references/update.md +14 -4
- package/payload/skills/zz-meridian/references/validation.md +14 -2
- package/payload/skills/zz-meridian/references/voice.md +1 -1
- package/payload/src/components/base/motion/README.md +1 -1
- package/payload/src/components/base/motion/preview.tsx +2 -2
- package/payload/src/components/base/providers.tsx +24 -7
- package/payload/src/components/base/shell/README.md +5 -1
- package/payload/src/components/base/shell/index.tsx +10 -5
- package/payload/src/components/base/shell/leave-question.tsx +1 -1
- package/payload/src/components/base/shell/preview.tsx +5 -3
- package/payload/src/components/base/surface/index.tsx +14 -5
- package/payload/src/components/base/text-roles/README.md +1 -1
- package/payload/src/components/base/text-roles/preview.tsx +2 -2
- package/payload/src/components/charts/bar-list/index.tsx +6 -4
- package/payload/src/components/charts/bar-list/preview.tsx +1 -1
- package/payload/src/components/charts/column-chart/README.md +1 -1
- package/payload/src/components/charts/column-chart/grouped.tsx +25 -17
- package/payload/src/components/charts/column-chart/index.tsx +30 -18
- package/payload/src/components/charts/column-chart/shared.tsx +0 -1
- package/payload/src/components/charts/composition-bar/README.md +1 -1
- package/payload/src/components/charts/composition-bar/index.tsx +13 -10
- package/payload/src/components/charts/diverging-bars/index.tsx +2 -1
- package/payload/src/components/charts/heatmap/README.md +1 -1
- package/payload/src/components/charts/heatmap/index.tsx +17 -10
- package/payload/src/components/charts/meridian/README.md +3 -2
- package/payload/src/components/charts/meridian/index.tsx +15 -3
- package/payload/src/components/charts/sparkline/README.md +1 -1
- package/payload/src/components/charts/sparkline/index.tsx +12 -2
- package/payload/src/components/charts/sparkline/preview.tsx +7 -18
- package/payload/src/components/charts/trend-chart/README.md +2 -2
- package/payload/src/components/charts/trend-chart/index.tsx +17 -7
- package/payload/src/components/charts/uptime-bars/README.md +5 -2
- package/payload/src/components/charts/uptime-bars/index.tsx +22 -10
- package/payload/src/components/charts/uptime-bars/preview.tsx +22 -3
- package/payload/src/components/patterns/activity-feed/README.md +3 -3
- package/payload/src/components/patterns/activity-feed/index.tsx +2 -1
- package/payload/src/components/patterns/activity-feed/preview.tsx +11 -1
- package/payload/src/components/patterns/appearance-menu/README.md +6 -6
- package/payload/src/components/patterns/appearance-menu/index.tsx +7 -17
- package/payload/src/components/patterns/appearance-menu/preview.tsx +12 -11
- package/payload/src/components/patterns/ask-about/index.tsx +5 -4
- package/payload/src/components/patterns/assistant/README.md +4 -4
- package/payload/src/components/patterns/assistant/index.tsx +49 -23
- package/payload/src/components/patterns/assistant/preview.tsx +9 -4
- package/payload/src/components/patterns/command-palette/README.md +12 -5
- package/payload/src/components/patterns/command-palette/index.tsx +9 -10
- package/payload/src/components/patterns/command-palette/open.ts +36 -0
- package/payload/src/components/patterns/data-table/README.md +4 -3
- package/payload/src/components/patterns/data-table/index.tsx +20 -13
- package/payload/src/components/patterns/data-table/preview.tsx +8 -2
- package/payload/src/components/patterns/detail-head/README.md +1 -1
- package/payload/src/components/patterns/detail-head/index.tsx +1 -1
- package/payload/src/components/patterns/embed-frame/README.md +1 -1
- package/payload/src/components/patterns/embed-frame/index.tsx +12 -18
- package/payload/src/components/patterns/embed-frame/preview.tsx +8 -2
- package/payload/src/components/patterns/export-button/README.md +7 -5
- package/payload/src/components/patterns/export-button/index.tsx +10 -5
- package/payload/src/components/patterns/export-button/preview.tsx +4 -3
- package/payload/src/components/patterns/filter-bar/README.md +4 -4
- package/payload/src/components/patterns/filter-bar/index.tsx +6 -3
- package/payload/src/components/patterns/form-section/README.md +4 -4
- package/payload/src/components/patterns/form-section/index.tsx +9 -10
- package/payload/src/components/patterns/form-section/preview.tsx +5 -0
- package/payload/src/components/patterns/metric-tile/index.tsx +2 -2
- package/payload/src/components/patterns/metric-tile/preview.tsx +7 -19
- package/payload/src/components/patterns/page-loading/README.md +1 -1
- package/payload/src/components/patterns/page-loading/index.tsx +40 -0
- package/payload/src/components/patterns/page-loading/preview.tsx +7 -2
- package/payload/src/components/patterns/proposal/README.md +8 -7
- package/payload/src/components/patterns/proposal/index.tsx +10 -8
- package/payload/src/components/patterns/proposal/preview.tsx +4 -1
- package/payload/src/components/patterns/prose/preview.tsx +2 -2
- package/payload/src/components/patterns/rail/README.md +7 -5
- package/payload/src/components/patterns/rail/index.tsx +6 -8
- package/payload/src/components/patterns/rail/trail.ts +18 -4
- package/payload/src/components/patterns/shell-tools/README.md +3 -3
- package/payload/src/components/patterns/shell-tools/index.tsx +20 -5
- package/payload/src/components/patterns/status-list/README.md +1 -1
- package/payload/src/components/patterns/status-list/index.tsx +2 -3
- package/payload/src/components/patterns/status-list/preview.tsx +1 -1
- package/payload/src/components/ui/avatar/README.md +6 -4
- package/payload/src/components/ui/avatar/index.tsx +14 -3
- package/payload/src/components/ui/avatar/preview.tsx +3 -0
- package/payload/src/components/ui/badge/index.tsx +3 -2
- package/payload/src/components/ui/banner/README.md +3 -3
- package/payload/src/components/ui/banner/index.tsx +4 -3
- package/payload/src/components/ui/banner/preview.tsx +5 -3
- package/payload/src/components/ui/breadcrumb/README.md +3 -3
- package/payload/src/components/ui/breadcrumb/index.tsx +9 -3
- package/payload/src/components/ui/breadcrumb/preview.tsx +5 -0
- package/payload/src/components/ui/button/README.md +3 -0
- package/payload/src/components/ui/button/index.tsx +31 -15
- package/payload/src/components/ui/button/preview.tsx +12 -0
- package/payload/src/components/ui/card/README.md +4 -4
- package/payload/src/components/ui/card/preview.tsx +5 -5
- package/payload/src/components/ui/checkbox/README.md +2 -2
- package/payload/src/components/ui/checkbox/index.tsx +4 -2
- package/payload/src/components/ui/copy-field/README.md +5 -2
- package/payload/src/components/ui/copy-field/index.tsx +50 -21
- package/payload/src/components/ui/copy-field/preview.tsx +2 -0
- package/payload/src/components/ui/delta/README.md +2 -2
- package/payload/src/components/ui/delta/index.tsx +5 -2
- package/payload/src/components/ui/dialog/README.md +1 -1
- package/payload/src/components/ui/dialog/index.tsx +14 -4
- package/payload/src/components/ui/dialog/preview.tsx +4 -4
- package/payload/src/components/ui/disclosure/README.md +1 -1
- package/payload/src/components/ui/empty-state/README.md +1 -1
- package/payload/src/components/ui/empty-state/index.tsx +2 -2
- package/payload/src/components/ui/field/README.md +2 -2
- package/payload/src/components/ui/icon-button/preview.tsx +2 -1
- package/payload/src/components/ui/input/index.tsx +4 -2
- package/payload/src/components/ui/input/preview.tsx +1 -1
- package/payload/src/components/ui/key-value/README.md +4 -4
- package/payload/src/components/ui/key-value/index.tsx +23 -19
- package/payload/src/components/ui/key-value/preview.tsx +1 -1
- package/payload/src/components/ui/menu/README.md +1 -0
- package/payload/src/components/ui/menu/index.tsx +1 -1
- package/payload/src/components/ui/pagination/README.md +3 -3
- package/payload/src/components/ui/pagination/index.tsx +3 -2
- package/payload/src/components/ui/pagination/preview.tsx +10 -4
- package/payload/src/components/ui/popover/README.md +3 -3
- package/payload/src/components/ui/popover/index.tsx +4 -1
- package/payload/src/components/ui/popover/preview.tsx +17 -11
- package/payload/src/components/ui/progress/README.md +4 -1
- package/payload/src/components/ui/progress/index.tsx +18 -13
- package/payload/src/components/ui/progress/preview.tsx +6 -2
- package/payload/src/components/ui/radio-group/README.md +7 -1
- package/payload/src/components/ui/radio-group/index.tsx +6 -4
- package/payload/src/components/ui/radio-group/preview.tsx +11 -1
- package/payload/src/components/ui/search-input/README.md +2 -0
- package/payload/src/components/ui/search-input/index.tsx +3 -2
- package/payload/src/components/ui/search-input/preview.tsx +8 -2
- package/payload/src/components/ui/segmented/README.md +1 -1
- package/payload/src/components/ui/segmented/index.tsx +1 -1
- package/payload/src/components/ui/segmented/preview.tsx +18 -2
- package/payload/src/components/ui/select/index.tsx +1 -1
- package/payload/src/components/ui/select/preview.tsx +1 -2
- package/payload/src/components/ui/sheet/README.md +1 -1
- package/payload/src/components/ui/sheet/index.tsx +1 -1
- package/payload/src/components/ui/sheet/preview.tsx +2 -2
- package/payload/src/components/ui/status-dot/README.md +5 -5
- package/payload/src/components/ui/status-dot/index.tsx +2 -1
- package/payload/src/components/ui/status-dot/preview.tsx +4 -1
- package/payload/src/components/ui/switch/README.md +1 -1
- package/payload/src/components/ui/switch/index.tsx +4 -2
- package/payload/src/components/ui/table/README.md +3 -3
- package/payload/src/components/ui/table/preview.tsx +4 -2
- package/payload/src/components/ui/tabs/README.md +3 -3
- package/payload/src/components/ui/tabs/index.tsx +2 -0
- package/payload/src/components/ui/textarea/README.md +1 -1
- package/payload/src/components/ui/textarea/index.tsx +2 -2
- package/payload/src/components/ui/toast/README.md +3 -2
- package/payload/src/components/ui/toast/index.tsx +58 -7
- package/payload/src/data/README.md +5 -3
- package/payload/src/data/access.ts +14 -9
- package/payload/src/data/collections.ts +20 -17
- package/payload/src/data/derived.ts +15 -13
- package/payload/src/data/live-stream.ts +9 -20
- package/payload/src/data/member-mutations.ts +36 -30
- package/payload/src/data/metrics.ts +7 -18
- package/payload/src/data/read.ts +10 -7
- package/payload/src/data/requests.ts +6 -9
- package/payload/src/data/sample.ts +3 -3
- package/payload/src/data/ticket-mutations.ts +3 -3
- package/payload/src/data/uptime.ts +2 -2
- package/payload/src/data/view-as.ts +4 -4
- package/payload/src/lib/assistant/prompt.ts +10 -7
- package/payload/src/lib/assistant/scoped.ts +2 -2
- package/payload/src/lib/assistant/tools.ts +35 -19
- package/payload/src/lib/collection.ts +17 -2
- package/payload/src/lib/csv.ts +8 -2
- package/payload/src/lib/demo-gate.ts +5 -0
- package/payload/src/lib/explore.ts +15 -12
- package/payload/src/lib/facts.ts +12 -7
- package/payload/src/lib/format-date.ts +23 -16
- package/payload/src/lib/format.ts +17 -0
- package/payload/src/lib/live.ts +2 -1
- package/payload/src/lib/sort.ts +11 -0
- package/payload/src/lib/totals.ts +24 -0
- package/payload/src/logic/alerts.ts +6 -3
- package/payload/src/logic/customer-context.ts +6 -5
- package/payload/src/logic/customers-context.ts +16 -7
- package/payload/src/logic/derivations.ts +2 -2
- package/payload/src/logic/fact-insight.ts +9 -3
- package/payload/src/logic/home-context.ts +15 -13
- package/payload/src/logic/home-parts.ts +26 -25
- package/payload/src/logic/keys-context.ts +1 -1
- package/payload/src/logic/members-context.ts +4 -2
- package/payload/src/logic/now-context.ts +1 -3
- package/payload/src/logic/now-parts.ts +9 -9
- package/payload/src/logic/releases-context.ts +2 -1
- package/payload/src/logic/request-context.ts +18 -10
- package/payload/src/logic/requests-context.ts +2 -1
- package/payload/src/logic/requests-explore.ts +2 -3
- package/payload/src/logic/revenue-context.ts +13 -9
- package/payload/src/logic/revenue-parts.ts +16 -16
- package/payload/src/logic/services-context.ts +2 -2
- package/payload/src/logic/tests-context.ts +2 -2
- package/payload/src/logic/tools.ts +2 -2
- package/payload/src/logic/usage-context.ts +6 -5
- package/payload/src/logic/usage-parts.ts +4 -5
- package/payload/src/styles/base.css +21 -5
- package/payload/src/styles/fonts/Geist-Variable.woff2 +0 -0
- package/payload/src/styles/fonts/GeistMono-Variable.woff2 +0 -0
- package/payload/src/styles/tokens.css +35 -5
- package/payload/src/system/atlas-shell.tsx +4 -3
- package/payload/src/system/card-stage.tsx +12 -3
- package/payload/src/system/content.ts +8 -2
- package/payload/src/system/fixtures/company.ts +9 -12
- package/payload/src/system/fixtures/sample-records.ts +11 -7
- package/payload/src/system/fixtures/sample.ts +0 -1
- package/payload/src/system/hero.tsx +9 -6
- package/payload/src/system/page-stage.tsx +2 -2
- package/payload/src/system/preview-loading.tsx +7 -0
- package/payload/src/system/sample-cells.tsx +14 -5
- package/payload/src/system/token-view.tsx +9 -9
- package/payload/src/views/console-chrome.tsx +6 -1
- package/payload/src/views/console-live.tsx +4 -3
- package/payload/src/views/customer.tsx +12 -8
- package/payload/src/views/customers.tsx +1 -3
- package/payload/src/views/home.tsx +9 -11
- package/payload/src/views/keys.tsx +16 -8
- package/payload/src/views/members.tsx +42 -34
- package/payload/src/views/no-access.tsx +5 -4
- package/payload/src/views/not-found-address.tsx +1 -1
- package/payload/src/views/not-found.tsx +2 -4
- package/payload/src/views/now.tsx +7 -9
- package/payload/src/views/period-actions.tsx +4 -4
- package/payload/src/views/refusal.tsx +1 -1
- package/payload/src/views/releases.tsx +3 -3
- package/payload/src/views/request.tsx +38 -22
- package/payload/src/views/requests.tsx +2 -3
- package/payload/src/views/revenue.tsx +11 -14
- package/payload/src/views/roles-matrix.tsx +5 -3
- package/payload/src/views/sample-footer.tsx +12 -8
- package/payload/src/views/settings.tsx +18 -10
- package/payload/src/views/tests.tsx +8 -9
- package/payload/src/views/tickets.tsx +32 -17
- package/payload/src/views/unread.tsx +2 -1
- package/payload/src/views/usage.tsx +3 -6
- package/payload/src/views/workspaces.ts +4 -11
- package/payload/tests/action-needs.test.tsx +1 -1
- package/payload/tests/activity-feed-link.test.tsx +1 -2
- package/payload/tests/agent-page-spec.test.ts +2 -3
- package/payload/tests/agents.test.tsx +0 -11
- package/payload/tests/alerts-read.test.tsx +33 -0
- package/payload/tests/appearance-menu-keyboard.test.tsx +29 -0
- package/payload/tests/assistant-access.test.ts +8 -22
- package/payload/tests/assistant-column-draft.test.tsx +57 -0
- package/payload/tests/assistant-explore-tool.test.ts +3 -19
- package/payload/tests/assistant-guard.test.ts +114 -3
- package/payload/tests/assistant-ime.test.tsx +18 -0
- package/payload/tests/assistant-page-text.test.tsx +6 -4
- package/payload/tests/assistant-panel.test.tsx +4 -5
- package/payload/tests/assistant-prompt-truth.test.ts +5 -12
- package/payload/tests/assistant-prompt-writes.test.ts +1 -4
- package/payload/tests/assistant-proposal.test.tsx +40 -5
- package/payload/tests/assistant-questions.test.tsx +0 -4
- package/payload/tests/assistant-route.test.ts +10 -0
- package/payload/tests/assistant-safety.test.ts +80 -2
- package/payload/tests/assistant-settings.test.tsx +9 -7
- package/payload/tests/assistant-stale-scope.test.tsx +0 -4
- package/payload/tests/assistant-thread-scope.test.tsx +1 -5
- package/payload/tests/assistant-thread.test.tsx +0 -1
- package/payload/tests/assistant-tools.test.ts +2 -4
- package/payload/tests/assistant-withheld.test.ts +4 -13
- package/payload/tests/atlas-layers.test.ts +18 -39
- package/payload/tests/atlas-product-slice.test.tsx +1 -29
- package/payload/tests/atlas-shell-early-press.test.tsx +24 -0
- package/payload/tests/atlas-template-contracts.test.tsx +2 -69
- package/payload/tests/avatar-initials.test.tsx +34 -0
- package/payload/tests/banner-preview.test.tsx +18 -0
- package/payload/tests/bar-list-forms.test.tsx +30 -13
- package/payload/tests/bar-list-links.test.tsx +1 -1
- package/payload/tests/brand-config.test.tsx +1 -4
- package/payload/tests/breadcrumb-fold.test.tsx +20 -0
- package/payload/tests/button-busy.test.tsx +45 -0
- package/payload/tests/card-header-title.test.tsx +0 -14
- package/payload/tests/card-stage-hydration.test.tsx +2 -12
- package/payload/tests/card-stage-loading.test.tsx +40 -0
- package/payload/tests/chart-count-default.test.tsx +20 -0
- package/payload/tests/chart-scale-held.test.ts +1 -1
- package/payload/tests/chart-semantics.test.tsx +3 -3
- package/payload/tests/chart-table-memo.test.tsx +51 -0
- package/payload/tests/check-nav-under.test.ts +27 -7
- package/payload/tests/choice-description.test.tsx +33 -0
- package/payload/tests/chrome-navigation.test.tsx +7 -8
- package/payload/tests/client-imports.test.ts +0 -8
- package/payload/tests/collection-aggregate.test.ts +8 -9
- package/payload/tests/column-chart-crowded.test.tsx +0 -7
- package/payload/tests/column-chart-grouped.test.tsx +5 -21
- package/payload/tests/column-chart-labels.test.tsx +4 -42
- package/payload/tests/column-chart-no-data.test.tsx +0 -4
- package/payload/tests/column-chart-readout.test.tsx +0 -3
- package/payload/tests/column-chart-running.test.tsx +0 -21
- package/payload/tests/column-chart-signed.test.tsx +1 -4
- package/payload/tests/column-chart.test.tsx +2 -8
- package/payload/tests/composition-bar.test.tsx +22 -9
- package/payload/tests/console-chrome.test.tsx +12 -12
- package/payload/tests/console-live.test.tsx +4 -0
- package/payload/tests/context-check.test.ts +3 -0
- package/payload/tests/contexts-timezone.test.ts +45 -0
- package/payload/tests/copy-field.test.tsx +197 -1
- package/payload/tests/counts-and-lists.test.tsx +3 -15
- package/payload/tests/csv-bom.test.ts +27 -0
- package/payload/tests/customer-empty-period.test.ts +25 -0
- package/payload/tests/customer-figures.test.ts +28 -12
- package/payload/tests/customers-masthead.test.tsx +0 -1
- package/payload/tests/customers-payload.test.tsx +3 -6
- package/payload/tests/data-model.test.ts +0 -1
- package/payload/tests/data-read.test.ts +3 -4
- package/payload/tests/data-table-manual-size.test.tsx +21 -0
- package/payload/tests/data-table.test.tsx +26 -10
- package/payload/tests/day-in-progress.test.ts +0 -2
- package/payload/tests/delta-flat.test.tsx +26 -0
- package/payload/tests/demo-gate.test.ts +14 -1
- package/payload/tests/demo-policy.test.ts +0 -1
- package/payload/tests/derivations.test.ts +5 -24
- package/payload/tests/derived-answer.test.ts +178 -19
- package/payload/tests/dialog-focus.test.tsx +33 -0
- package/payload/tests/disclosure.test.tsx +4 -5
- package/payload/tests/diverging-bars.test.tsx +2 -7
- package/payload/tests/effective-manifest.test.ts +56 -0
- package/payload/tests/embed-context-lifetime.test.tsx +79 -0
- package/payload/tests/embed-page-failure.test.tsx +1 -8
- package/payload/tests/embed-proposal.test.tsx +43 -0
- package/payload/tests/embed-requests-provenance.test.tsx +46 -1
- package/payload/tests/embed-theme.test.tsx +62 -0
- package/payload/tests/engineering-records.test.ts +1 -19
- package/payload/tests/engineering-workflows.test.ts +4 -57
- package/payload/tests/explore-answer-length.test.ts +4 -26
- package/payload/tests/explore-contract.test.ts +2 -5
- package/payload/tests/explore-group-change.test.ts +5 -12
- package/payload/tests/explore-io.ts +16 -0
- package/payload/tests/explore-money.test.ts +6 -12
- package/payload/tests/explore-narrowed-measure.test.ts +6 -11
- package/payload/tests/explore-none.test.ts +4 -8
- package/payload/tests/explore-percent.test.ts +5 -12
- package/payload/tests/explore-refers.test.ts +7 -6
- package/payload/tests/explore-runner.test.ts +3 -5
- package/payload/tests/export-button.test.tsx +45 -0
- package/payload/tests/facts-config.test.ts +0 -6
- package/payload/tests/facts-engineering.test.ts +1 -12
- package/payload/tests/facts.test.ts +1 -18
- package/payload/tests/failed-request.test.ts +20 -0
- package/payload/tests/fake-llm.test.ts +1 -1
- package/payload/tests/feature-access.test.ts +2 -9
- package/payload/tests/feature-definitions.test.ts +1 -21
- package/payload/tests/featured-metric.test.tsx +1 -24
- package/payload/tests/feel-column-chart.test.tsx +1 -1
- package/payload/tests/feel-sparkline.test.tsx +13 -1
- package/payload/tests/filter-bar-search.test.tsx +10 -15
- package/payload/tests/form-section-actions.test.tsx +0 -3
- package/payload/tests/form-section-readonly.test.tsx +14 -0
- package/payload/tests/format-currency.test.ts +1 -1
- package/payload/tests/format-date-calendar.test.ts +23 -0
- package/payload/tests/format-semantics.test.ts +1 -3
- package/payload/tests/format.test.ts +31 -23
- package/payload/tests/heatmap-states.test.tsx +1 -37
- package/payload/tests/honest-controls.test.tsx +8 -28
- package/payload/tests/incident-card-hyphens.test.tsx +3 -18
- package/payload/tests/incident-card.test.tsx +1 -1
- package/payload/tests/input-states.test.tsx +12 -0
- package/payload/tests/key-value.test.tsx +11 -32
- package/payload/tests/keys-actions.test.ts +8 -7
- package/payload/tests/keys-gate.test.tsx +8 -31
- package/payload/tests/keys-scopes-view.test.tsx +1 -2
- package/payload/tests/keys-secret-view.test.tsx +2 -3
- package/payload/tests/linked-records.test.ts +12 -38
- package/payload/tests/live-client.test.tsx +66 -1
- package/payload/tests/live-resume.test.ts +0 -2
- package/payload/tests/live-route.test.ts +3 -3
- package/payload/tests/loading-routes.test.tsx +1 -10
- package/payload/tests/logo.test.ts +13 -0
- package/payload/tests/member-duplicate.test.ts +12 -1
- package/payload/tests/member-mutations.test.ts +30 -28
- package/payload/tests/member-roles.test.ts +0 -11
- package/payload/tests/member-roster-boundary.test.ts +3 -9
- package/payload/tests/members-optimistic.test.tsx +61 -60
- package/payload/tests/meridian.test.tsx +25 -2
- package/payload/tests/metric-tile-compact.test.tsx +0 -38
- package/payload/tests/metric-tile-delta-format.test.tsx +1 -2
- package/payload/tests/metric-tile-note.test.tsx +1 -15
- package/payload/tests/metric-tile-pointed-empty.test.tsx +1 -1
- package/payload/tests/metric-tile-title.test.tsx +0 -1
- package/payload/tests/metric-tile.test.tsx +2 -17
- package/payload/tests/next-start.test.ts +21 -0
- package/payload/tests/no-access.test.tsx +18 -10
- package/payload/tests/not-found.test.ts +7 -4
- package/payload/tests/page-frame-title.test.tsx +7 -99
- package/payload/tests/page-gates.test.tsx +2 -2
- package/payload/tests/page-loading.test.tsx +66 -45
- package/payload/tests/page-server-module.test.ts +32 -0
- package/payload/tests/pages-read-every-row.test.tsx +17 -31
- package/payload/tests/pagination-sizes.test.tsx +16 -0
- package/payload/tests/palette-hint.test.tsx +2 -6
- package/payload/tests/palette-ime.test.tsx +46 -0
- package/payload/tests/palette-open.test.ts +24 -0
- package/payload/tests/period-whole-previous.test.ts +25 -0
- package/payload/tests/plural.test.ts +11 -1
- package/payload/tests/popover-name.test.tsx +15 -0
- package/payload/tests/popover-preview.test.tsx +14 -0
- package/payload/tests/preview-live-controls.test.tsx +37 -0
- package/payload/tests/progress-values.test.tsx +40 -0
- package/payload/tests/proposal-approval.test.tsx +31 -0
- package/payload/tests/prose-cell-labels.test.tsx +0 -8
- package/payload/tests/providers-stored.test.tsx +28 -0
- package/payload/tests/rail-branch-feel.test.tsx +3 -71
- package/payload/tests/rail-branch.test.tsx +17 -23
- package/payload/tests/rail-name-title.test.tsx +0 -4
- package/payload/tests/rail-trail.test.ts +16 -1
- package/payload/tests/read-all-query.test.ts +56 -8
- package/payload/tests/read-every-row.test.ts +6 -16
- package/payload/tests/records-consumers.test.tsx +9 -76
- package/payload/tests/refusal-descriptor.test.ts +1 -12
- package/payload/tests/release-phone-cell.test.ts +0 -3
- package/payload/tests/release-wording.test.ts +2 -7
- package/payload/tests/request-curl.test.ts +108 -0
- package/payload/tests/request-keys-link.test.tsx +24 -0
- package/payload/tests/request-replay.test.ts +19 -1
- package/payload/tests/request-usage.test.tsx +40 -0
- package/payload/tests/request-view-replay.test.tsx +36 -28
- package/payload/tests/requests-export.test.ts +15 -1
- package/payload/tests/requests-p95-one-rule.test.ts +24 -0
- package/payload/tests/requests-query.test.ts +6 -3
- package/payload/tests/requests-summary-newest.test.ts +0 -1
- package/payload/tests/review-held-scales.test.tsx +1 -31
- package/payload/tests/roles-context.test.ts +0 -1
- package/payload/tests/roles-matrix-redraw.test.tsx +22 -0
- package/payload/tests/roles-matrix.test.tsx +0 -2
- package/payload/tests/routes-discover-shapes.test.ts +45 -0
- package/payload/tests/script-args.test.ts +86 -0
- package/payload/tests/search-input.test.tsx +54 -0
- package/payload/tests/segmented-measure.test.tsx +23 -0
- package/payload/tests/served.tsx +34 -0
- package/payload/tests/settings-access.test.tsx +11 -11
- package/payload/tests/settings-agents.test.tsx +0 -25
- package/payload/tests/settings-save.test.tsx +15 -11
- package/payload/tests/setup.ts +4 -0
- package/payload/tests/shared-context.test.tsx +132 -105
- package/payload/tests/shell-alerts.test.ts +11 -13
- package/payload/tests/shell-drawer-open.test.tsx +3 -2
- package/payload/tests/shell-first-arrival.test.tsx +0 -6
- package/payload/tests/shell-promise.test.tsx +2 -12
- package/payload/tests/shell-search-name.test.tsx +14 -10
- package/payload/tests/sign-in-answer.test.tsx +37 -0
- package/payload/tests/sign-in-honest.test.tsx +20 -12
- package/payload/tests/sign-in-persona.test.ts +28 -6
- package/payload/tests/sparkline-forms.test.tsx +5 -5
- package/payload/tests/specimen-still.test.tsx +1 -1
- package/payload/tests/status-list.test.tsx +8 -0
- package/payload/tests/table-cut-cell.test.tsx +14 -42
- package/payload/tests/table-grid.test.tsx +3 -59
- package/payload/tests/template-consumers.test.tsx +0 -4
- package/payload/tests/ticket-mutations.test.ts +0 -1
- package/payload/tests/ticket-owner.test.ts +0 -10
- package/payload/tests/tickets-view.test.tsx +61 -9
- package/payload/tests/tile-row.test.tsx +29 -0
- package/payload/tests/toast-timing.test.tsx +53 -0
- package/payload/tests/trend-chart-band.test.tsx +1 -3
- package/payload/tests/trend-chart-curve.test.tsx +6 -6
- package/payload/tests/trend-chart-forms.test.tsx +6 -7
- package/payload/tests/trend-chart-whole.test.tsx +2 -0
- package/payload/tests/trend-chart.test.tsx +28 -0
- package/payload/tests/truncation-keeps-text.test.tsx +4 -5
- package/payload/tests/update-session.test.ts +19 -13
- package/payload/tests/uptime-bars-end.test.tsx +2 -4
- package/payload/tests/uptime-edges.test.tsx +38 -0
- package/payload/tests/uptime-no-data.test.tsx +1 -3
- package/payload/tests/uptime-svg.test.tsx +1 -3
- package/payload/tests/uptime-tap.test.tsx +15 -0
- package/payload/tests/usage-figures.test.ts +0 -12
- package/payload/tests/usage-summary.test.tsx +0 -1
- package/payload/tests/use-size-late.test.tsx +1 -1
- package/payload/tests/verify-coverage.test.ts +10 -0
- package/payload/tests/verify-data-url.test.ts +88 -15
- package/payload/tests/verify-explore-surfaces.test.ts +10 -7
- package/payload/tests/verify-loopback.test.ts +10 -10
- package/payload/tests/verify-personas.test.ts +3 -22
- package/payload/tests/verify-sample-surfaces.test.ts +34 -11
- package/payload/tests/verify-sizes.test.ts +1 -5
- package/payload/tests/verify-suite-outcome.test.ts +14 -3
- package/payload/tests/verify-timing.test.ts +1 -2
- package/payload/tests/view-as.test.ts +1 -7
- package/payload/tests/view-tool-modules.test.ts +1 -2
- package/payload/tests/view-tool-needs.test.ts +0 -12
- package/payload/tests/workspace-access.test.ts +20 -4
- package/payload/tests/workspace-chrome.test.tsx +1 -13
- package/payload/tests/workspace-data-paths.test.ts +0 -13
- package/payload/tests/workspace-figures.test.ts +0 -1
- package/payload/tests/workspace-home.test.tsx +0 -10
- package/payload/tests/workspaces.test.ts +1 -27
- package/payload/tests/bar-list-axis-words.test.tsx +0 -42
- package/payload/tests/bypasses.test.ts +0 -72
- package/payload/tests/dialog-xl.test.tsx +0 -25
- package/payload/tests/feel-bar-list.test.tsx +0 -22
- package/payload/tests/forced-colors-states.test.ts +0 -62
- package/payload/tests/hatch.test.ts +0 -45
- package/payload/tests/heatmap-names-column.test.tsx +0 -30
- package/payload/tests/logic-alerts.test.ts +0 -50
- package/payload/tests/logic-layer.test.ts +0 -58
- package/payload/tests/moved-paths-documented.test.ts +0 -51
- package/payload/tests/sample-company.test.ts +0 -227
- package/payload/tests/sample.test.ts +0 -158
- package/payload/tests/segmented-fit.test.tsx +0 -22
- package/payload/tests/table-cut-align.test.tsx +0 -30
- package/payload/tests/table-hide-below-pad.test.tsx +0 -18
package/README.md
CHANGED
|
@@ -34,20 +34,29 @@ npx zz-meridian@<version> brand [brand flags] # rebrand this project, with t
|
|
|
34
34
|
npx zz-meridian@latest skill [--global] # install only the agent skill
|
|
35
35
|
```
|
|
36
36
|
|
|
37
|
-
Brand flags: `--name "Acme Ops"`, `--hex '#2E6BE4'` (or `--accent indigo|cobalt|jade|graphite`), `--theme dark|light`,
|
|
37
|
+
Brand flags: `--name "Acme Ops"`, `--hex '#2E6BE4'` (or `--hue 250 --chroma 0.14`, or `--accent indigo|cobalt|jade|graphite`), `--theme dark|light`,
|
|
38
38
|
`--workspace`, `--timezone`, `--currency`, `--user`, `--role`. `--workspace` sets `app.workspace`, the environment named
|
|
39
39
|
in a page's kicker ("Production"); it does not touch the navigation workspaces.
|
|
40
|
+
`--timezone` must be accepted by `Intl.DateTimeFormat`, for example `UTC` or `Europe/London`; an unsupported zone is refused rather than saved.
|
|
41
|
+
Quoted brand strings remain literal values across repeated rebranding; changing a role does not rewrite the person's existing name.
|
|
42
|
+
Every valued flag needs its own value, including with the standalone `pnpm brand`: missing values and a following flag used as a value are refused before any configuration changes.
|
|
43
|
+
Commands reject extra positional arguments before changing files: only `create` takes a folder argument.
|
|
40
44
|
|
|
41
45
|
**adopt** copies Meridian's tokens, styles, components, gates and scripts into `src/`, `tokens/` and `scripts/`;
|
|
42
46
|
merges the dependencies and scripts it needs into your `package.json`; adds the `@meridian/*` alias to your
|
|
43
47
|
`tsconfig.json` (yours is kept as `tsconfig.before.json` when it carries comments or trailing commas, which JSON
|
|
44
48
|
cannot hold); replaces your global stylesheet (yours is kept
|
|
45
|
-
beside it as `*.before.css`);
|
|
49
|
+
beside it as `*.before.css`); preserves string keys and values in your TypeScript configuration, including punctuation;
|
|
50
|
+
brands it; adds Meridian's managed block to your `AGENTS.md` between two markers, keeping your own text there byte
|
|
46
51
|
for byte; writes an empty `docs/brief.md` (your product, users, data, decisions and glossary) if you have none; installs the skill into
|
|
47
52
|
`.agents/skills/` (Codex) and `.claude/skills/` (Claude Code); records every Meridian file it copied in `.meridian/manifest.json`;
|
|
48
|
-
installs and
|
|
49
|
-
|
|
50
|
-
|
|
53
|
+
installs and reports route-generation and TypeScript diagnostics. An installation failure exits nonzero; diagnostic
|
|
54
|
+
failures are reported as `types: fails` but adoption still exits zero, because your existing routes may need repairs.
|
|
55
|
+
This is not a clean-typecheck guarantee: fix those diagnostics before running the gate. Your routes, your data layer
|
|
56
|
+
and your own components are not touched. Meridian's files import each other by relative path, so a
|
|
57
|
+
`components/ui/button` of your own is never confused with Meridian's; your code imports Meridian as `@meridian/…`.
|
|
58
|
+
Supported dependency specifications below Meridian's required floor are raised, including within the same major;
|
|
59
|
+
newer versions are kept. Custom specifications are kept with a note to confirm compatibility.
|
|
51
60
|
|
|
52
61
|
It refuses, and writes nothing, when the git tree has uncommitted changes (so its change is one reviewable diff), when
|
|
53
62
|
the project is not Next.js with the App Router, or when a file it would copy already exists with other content.
|
|
@@ -68,10 +77,12 @@ writes nothing; run it first.
|
|
|
68
77
|
- It reports a migration for each interface the release changed where one of your own files still has the old shape,
|
|
69
78
|
such as `cache-components-config` or `nav-needs`. `cli/src/migrations.ts` holds every one; resolve them as the skill's
|
|
70
79
|
`references/update.md` says.
|
|
80
|
+
- Team-owned sample files are checked again on every forward upgrade, even after their migration's introduction, so newer managed tests do not silently outrun the sample they exercise. They remain team-owned: the migration asks for review and never overwrites them.
|
|
71
81
|
- Everything it did and everything left to do is in `.meridian/update/<version>/MERGE.md`. Resolve the items, then run
|
|
72
82
|
the pinned `npx zz-meridian@<version> update --finalize`; `--resume` continues an interrupted run and `--abort` restores
|
|
73
83
|
what it changed. Only finalize records the new version. `--finalize --verify` validates with the project's default
|
|
74
84
|
`verify` instead of the gate and the build, and reports its coverage line.
|
|
85
|
+
- Failure and coverage metadata is recorded literally in the report, including `$` sequences; it is not interpreted as report-template syntax.
|
|
75
86
|
- It refuses, writing nothing, on a dirty git tree (unless `--allow-dirty`) or while another update is open. `--verbose`
|
|
76
87
|
lists every file.
|
|
77
88
|
|
|
@@ -80,8 +91,11 @@ styles) and `src/app.config.ts` for the new flags and records them in the manife
|
|
|
80
91
|
refuses when one of those outputs was edited, while an update is open, or on a dirty tree (unless `--allow-dirty`). Run
|
|
81
92
|
it with the version the manifest records. The project's own `pnpm brand` still works, but its changes count as your edits.
|
|
82
93
|
|
|
94
|
+
**skill** checks both `.agents/skills/zz-meridian` and `.claude/skills/zz-meridian` before writing either. Identical files are retained; different content or symlinks are refused. Move a customized copy aside, install the shipped skill, then reconcile the customization manually rather than losing it to an overwrite.
|
|
95
|
+
An incomplete package without its `SKILL.md` is refused before either destination is written.
|
|
96
|
+
|
|
83
97
|
The standard a project on Meridian is built to is
|
|
84
|
-
[data-layers.md](https://github.com/zhixuan312/zz-meridian/blob/
|
|
98
|
+
[data-layers.md](https://github.com/zhixuan312/zz-meridian/blob/master/docs/data-layers.md): the four layers between a
|
|
85
99
|
database and the screen, the contract a backend answers, and the six rules a project switches on in its own
|
|
86
100
|
`scripts/check.local.ts`.
|
|
87
101
|
|
|
@@ -102,6 +116,14 @@ telemetry. It talks to npm only, when `npx` fetches it and when `update` reads r
|
|
|
102
116
|
public, so leave out anything that identifies you, your organisation or your product, and describe the problem with
|
|
103
117
|
Meridian's own template or sample data.
|
|
104
118
|
|
|
119
|
+
## Maintaining this package
|
|
120
|
+
|
|
121
|
+
From the repository root, run `node cli/scripts/build-payload.ts` before `pnpm exec tsc -p cli/tsconfig.json` and packing. The producer reads committed `HEAD` by default; use `--worktree` to try uncommitted tracked changes. It also generates `cli/src/update-session.ts` from the canonical standalone `scripts/lib/update-session.ts`, using the same source provenance as the payload. Edit only the canonical module, never its generated CLI companion.
|
|
122
|
+
The payload excludes `.env` and its variants at every directory depth, even when tracked; deliberate `.env.example`
|
|
123
|
+
files remain available as public configuration templates. Never put credentials in an example file.
|
|
124
|
+
|
|
125
|
+
The template's copied-command regression runs real cURL on loopback and needs a POSIX shell and `curl`, with no external endpoint or credentials.
|
|
126
|
+
|
|
105
127
|
## License
|
|
106
128
|
|
|
107
|
-
MIT
|
|
129
|
+
MIT: the text is `payload/LICENSE` in the package and `LICENSE` in a project `create` makes.
|
package/dist/adopt.js
CHANGED
|
@@ -3,20 +3,50 @@
|
|
|
3
3
|
* its data layer. Everything here is the settled part of the skill's Route A; rebuilding each page on Meridian's
|
|
4
4
|
* components is the agent's work, and the printed next step hands it over.
|
|
5
5
|
*
|
|
6
|
-
* Nothing is written until every check has passed: a
|
|
7
|
-
* or a file of the same name with other content stops
|
|
6
|
+
* Nothing is written until every check has passed: a project already on Meridian (its manifest: update is the command),
|
|
7
|
+
* a dirty tree, a project that is not Next.js with the App Router, or a file of the same name with other content stops
|
|
8
|
+
* it before the first write.
|
|
8
9
|
*/
|
|
9
10
|
import fs from 'node:fs';
|
|
10
11
|
import path from 'node:path';
|
|
11
12
|
import { VERSION, brandArgs, effectiveBrand, inside, installArgs, installSkill, jsoncExtras, packageManager, payloadBytes, payloadFiles, readJsonc, readPayload, relativeImports, skillPaths, run, runTool, sha256, writeIn, writeManifest, } from './files.js';
|
|
12
13
|
import { BRIEF_TEMPLATE, managedBlock, upsertManagedBlock } from './context.js';
|
|
13
|
-
import { FIXED, adoptSetOf, managedPaths } from './ownership.js';
|
|
14
|
-
|
|
15
|
-
const DEPS = ['next', 'react', 'react-dom', 'radix-ui', 'lucide-react', 'clsx', 'tailwind-merge', 'react-markdown', 'remark-gfm', 'ai', '@ai-sdk/react', 'zod'];
|
|
16
|
-
const DEV_DEPS = ['typescript', '@types/node', '@types/react', '@types/react-dom', 'tailwindcss', '@tailwindcss/postcss', 'eslint', 'eslint-config-next', 'vitest', '@vitejs/plugin-react', 'jsdom', '@testing-library/react', '@testing-library/dom', '@testing-library/jest-dom'];
|
|
17
|
-
const SCRIPTS = ['typecheck', 'test', 'tokens', 'check', 'contrast', 'gate', 'audit', 'verify', 'brand', 'shot', 'interactions', 'keyboard', 'vitals'];
|
|
18
|
-
const major = (spec) => Number(/(\d+)/.exec(spec)?.[1] ?? NaN);
|
|
14
|
+
import { FIXED, adoptSetOf, managedPaths, parseManifest } from './ownership.js';
|
|
15
|
+
import { MERIDIAN_SCRIPTS, TOOLCHAIN, compareMinimum, needOf } from './reconcile.js';
|
|
19
16
|
const TS = /\.(ts|tsx)$/;
|
|
17
|
+
/** Raise known dependency floors in place; custom specifications stay the team's decision. */
|
|
18
|
+
export function adoptDependencies(pkg, tpl, field, names) {
|
|
19
|
+
const notes = [];
|
|
20
|
+
pkg[field] ??= {};
|
|
21
|
+
for (const n of names) {
|
|
22
|
+
const want = tpl.dependencies?.[n] ?? tpl.devDependencies?.[n];
|
|
23
|
+
if (!want)
|
|
24
|
+
continue;
|
|
25
|
+
const have = pkg.dependencies?.[n] ?? pkg.devDependencies?.[n];
|
|
26
|
+
if (!have) {
|
|
27
|
+
pkg[field][n] = want;
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
const order = compareMinimum(have, want);
|
|
31
|
+
if (order === null) {
|
|
32
|
+
notes.push(`kept ${n} ${have}, which Meridian cannot compare: confirm it meets ${want} before running the gate`);
|
|
33
|
+
}
|
|
34
|
+
else if (order < 0) {
|
|
35
|
+
const at = pkg.dependencies?.[n] ? 'dependencies' : 'devDependencies';
|
|
36
|
+
pkg[at][n] = want;
|
|
37
|
+
notes.push(`raised ${n} from ${have} to ${want} (Meridian needs this floor; read its upgrade guide)`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return notes;
|
|
41
|
+
}
|
|
42
|
+
/** Adoption is installed even when a team's existing routes need type repairs; report both diagnostic stages. */
|
|
43
|
+
function adoptionTypes(root) {
|
|
44
|
+
const route = runTool(root, 'next/dist/bin/next', ['typegen']);
|
|
45
|
+
const tsc = runTool(root, 'typescript/bin/tsc', ['--noEmit']);
|
|
46
|
+
const failures = [['next typegen', route], ['tsc', tsc]];
|
|
47
|
+
const failed = failures.filter(([, result]) => result.status !== 0);
|
|
48
|
+
return failed.length ? `fails:\n${failed.map(([name, result]) => `${name}:\n${(result.stdout + result.stderr).trim().split('\n').slice(0, 30).join('\n')}`).join('\n')}` : 'passes';
|
|
49
|
+
}
|
|
20
50
|
/** A specifier inside a copied file, pinned to the exact module so a team file of a similar name can never win. */
|
|
21
51
|
function exactImports(rel, source, known) {
|
|
22
52
|
const pin = (spec) => {
|
|
@@ -93,13 +123,14 @@ export function projectConfig(template, pages) {
|
|
|
93
123
|
.replace(/export const nav: NavGroup\[\] = \[[\s\S]*?\n\];/, `/** Written by zz-meridian adopt from the project's pages: give each its own icon and group them. */\nexport const nav: NavGroup[] = [\n {\n items: [\n${items}\n ],\n },\n];`);
|
|
94
124
|
}
|
|
95
125
|
/**
|
|
96
|
-
* `scripts/verify.config.ts` as a project gets it. The sample's persona rows are what used `EVERY_ROUTE
|
|
97
|
-
* config object leaves
|
|
98
|
-
* wrote, 0.7 s after the other steps passed
|
|
126
|
+
* `scripts/verify.config.ts` as a project gets it. The sample's persona rows are what used `EVERY_ROUTE` and `ROLE_ROUTES`,
|
|
127
|
+
* so replacing the config object leaves them declared and never read — which the gate's own lint fails, in the project
|
|
128
|
+
* adopt just wrote, 0.7 s after the other steps passed — and names the sample's routes in the team's file. Each goes
|
|
129
|
+
* with its doc line. Exported so a test can hold the rewrite to that.
|
|
99
130
|
*/
|
|
100
131
|
export function verifyConfig() {
|
|
101
132
|
return readPayload('scripts/verify.config.ts')
|
|
102
|
-
.replace(
|
|
133
|
+
.replace(/^\/\*\*[^\n]*\*\/\nconst (?:EVERY_ROUTE|ROLE_ROUTES) = \[[^\n]*\n\n?/gm, '')
|
|
103
134
|
.replace(/const config: VerifyConfig = \{[\s\S]*?\n\};/, `const config: VerifyConfig = {
|
|
104
135
|
// One detail page per state worth seeing (a normal record, a failed one, a missing one), with ids from your data.
|
|
105
136
|
detailRoutes: [],
|
|
@@ -182,6 +213,17 @@ export function adopt(o) {
|
|
|
182
213
|
// ── Checks: nothing is written until all of them pass ─────────────────────────────────────────────────
|
|
183
214
|
if (!fs.existsSync(pkgPath))
|
|
184
215
|
return fail(`no package.json in ${root}: run adopt in the project's folder`);
|
|
216
|
+
// A project adopt or create already set up holds Meridian's files as its manifest records them, and whatever the team
|
|
217
|
+
// changed since; adopted again, every edited one would be listed as a conflict. Moving it to this release is update's.
|
|
218
|
+
const manifestPath = path.join(root, '.meridian/manifest.json');
|
|
219
|
+
if (fs.existsSync(manifestPath)) {
|
|
220
|
+
let at = '';
|
|
221
|
+
try {
|
|
222
|
+
at = ` ${parseManifest(fs.readFileSync(manifestPath, 'utf8')).version}`;
|
|
223
|
+
}
|
|
224
|
+
catch { /* the version is only named */ }
|
|
225
|
+
return fail(`this project is already on Meridian${at} (.meridian/manifest.json): run npx zz-meridian@latest update to move it to this release`);
|
|
226
|
+
}
|
|
185
227
|
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
|
186
228
|
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
187
229
|
const dir = appDir(root);
|
|
@@ -257,28 +299,13 @@ Rename or move them, then run adopt again.`);
|
|
|
257
299
|
}
|
|
258
300
|
// ── Merged files: the project's own, changed only where Meridian needs it ────────────────────────────
|
|
259
301
|
const tpl = JSON.parse(readPayload('package.json'));
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
continue;
|
|
266
|
-
const have = pkg.dependencies?.[n] ?? pkg.devDependencies?.[n];
|
|
267
|
-
if (!have) {
|
|
268
|
-
pkg[field][n] = want;
|
|
269
|
-
continue;
|
|
270
|
-
}
|
|
271
|
-
if (major(have) < major(want)) {
|
|
272
|
-
const at = pkg.dependencies?.[n] ? 'dependencies' : 'devDependencies';
|
|
273
|
-
pkg[at][n] = want;
|
|
274
|
-
notes.push(`raised ${n} from ${have} to ${want} (Meridian needs the newer major; read its upgrade guide)`);
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
};
|
|
278
|
-
merge('dependencies', DEPS);
|
|
279
|
-
merge('devDependencies', DEV_DEPS);
|
|
302
|
+
// The packages the adopted modules import, and the framework: the rule `update` applies to a created project.
|
|
303
|
+
const sources = new Map(set.filter((rel) => TS.test(rel)).map((rel) => [rel, payloadBytes(rel).toString('utf8')]));
|
|
304
|
+
sources.set('src/app.config.ts', config);
|
|
305
|
+
notes.push(...adoptDependencies(pkg, tpl, 'dependencies', needOf(tpl, sources).runtime));
|
|
306
|
+
notes.push(...adoptDependencies(pkg, tpl, 'devDependencies', TOOLCHAIN));
|
|
280
307
|
pkg.scripts ??= {};
|
|
281
|
-
for (const s of
|
|
308
|
+
for (const s of MERIDIAN_SCRIPTS) {
|
|
282
309
|
const want = tpl.scripts[s];
|
|
283
310
|
if (!pkg.scripts[s])
|
|
284
311
|
pkg.scripts[s] = want;
|
|
@@ -364,8 +391,11 @@ Rename or move them, then run adopt again.`);
|
|
|
364
391
|
const brandDirs = () => ['tokens', 'src/styles'].flatMap((d) => listFiles(root, d));
|
|
365
392
|
const existed = new Set(brandDirs());
|
|
366
393
|
const b = run(process.execPath, ['scripts/brand.ts', ...brandArgs(brand), '--existing'], root);
|
|
367
|
-
if (b.status !== 0)
|
|
368
|
-
|
|
394
|
+
if (b.status !== 0) {
|
|
395
|
+
// From a clean tree, git takes back exactly what adopt wrote; with --allow-dirty it would take the team's changes too.
|
|
396
|
+
const back = o.allowDirty ? 'remove what adopt wrote (git status shows it beside your own changes)' : 'put the tree back (git restore . && git clean -fd removes only what adopt wrote, since it started clean)';
|
|
397
|
+
return fail(`scripts/brand.ts failed (above) after the files were copied, and the manifest and agent files are not written. Fix the cause, ${back}, and run zz-meridian adopt again with the same flags`);
|
|
398
|
+
}
|
|
369
399
|
// The project's own AGENTS.md keeps every byte and gains the managed block; the brief is the team's, written only when absent.
|
|
370
400
|
// Neither is a Meridian file, so neither is recorded in the manifest.
|
|
371
401
|
const pm = packageManager(root);
|
|
@@ -390,16 +420,14 @@ Rename or move them, then run adopt again.`);
|
|
|
390
420
|
files[rel] = sha256(fs.readFileSync(inside(root, rel)));
|
|
391
421
|
installSkill(root, files);
|
|
392
422
|
writeManifest(root, { version: VERSION, route: 'adopt', brand, files });
|
|
393
|
-
// ── Install and
|
|
423
|
+
// ── Install and report type diagnostics (existing team code may still need repairs) ──────────────────
|
|
394
424
|
let typed = 'not run (--no-install)';
|
|
395
425
|
if (o.install) {
|
|
396
426
|
say(`\nInstalling with ${pm}…`);
|
|
397
427
|
if (run(pm, installArgs(pm), root).status !== 0)
|
|
398
428
|
return fail(`${pm} install failed (above). Fix it, then run ${pm} install and ${pm} run typecheck.`);
|
|
399
|
-
// Route types first (LayoutProps, PageProps), as the gate does.
|
|
400
|
-
|
|
401
|
-
const tsc = runTool(root, 'typescript/bin/tsc', ['--noEmit']);
|
|
402
|
-
typed = tsc.status === 0 ? 'passes' : `fails:\n${(tsc.stdout + tsc.stderr).trim().split('\n').slice(0, 30).join('\n')}`;
|
|
429
|
+
// Route types first (LayoutProps, PageProps), as the gate does; neither failure may be reported as passing.
|
|
430
|
+
typed = adoptionTypes(root);
|
|
403
431
|
}
|
|
404
432
|
say(`
|
|
405
433
|
Meridian ${VERSION} is in ${root}.
|
package/dist/cli.js
CHANGED
|
@@ -5,9 +5,8 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import os from 'node:os';
|
|
7
7
|
import path from 'node:path';
|
|
8
|
-
import { parseArgs } from 'node:util';
|
|
9
8
|
import { adopt } from './adopt.js';
|
|
10
|
-
import { misapplied } from './command-flags.js';
|
|
9
|
+
import { misapplied, readFlags } from './command-flags.js';
|
|
11
10
|
import { create } from './create.js';
|
|
12
11
|
import { BRAND_FLAGS, VERSION, installSkill } from './files.js';
|
|
13
12
|
import { brandCommand } from './rebrand.js';
|
|
@@ -38,31 +37,20 @@ const HELP = `zz-meridian ${VERSION}
|
|
|
38
37
|
|
|
39
38
|
Brand flags: --name "Acme Ops" --workspace Production --timezone Europe/London --currency EUR
|
|
40
39
|
--user "Ada Park" --role Admin --accent indigo|cobalt|jade|graphite | --hex '#2E6BE4' | --hue 250 --chroma 0.14
|
|
40
|
+
--theme dark|light
|
|
41
41
|
|
|
42
42
|
Then give your coding agent the skill: .agents/skills/zz-meridian/SKILL.md.`;
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
'dry-run': { type: 'boolean' },
|
|
50
|
-
resume: { type: 'boolean' },
|
|
51
|
-
finalize: { type: 'boolean' },
|
|
52
|
-
abort: { type: 'boolean' },
|
|
53
|
-
verify: { type: 'boolean' },
|
|
54
|
-
verbose: { type: 'boolean' },
|
|
55
|
-
global: { type: 'boolean' },
|
|
56
|
-
help: { type: 'boolean', short: 'h' },
|
|
57
|
-
version: { type: 'boolean', short: 'v' },
|
|
58
|
-
},
|
|
59
|
-
});
|
|
60
|
-
const flags = values;
|
|
43
|
+
const read = readFlags(process.argv.slice(2));
|
|
44
|
+
if ('error' in read) {
|
|
45
|
+
console.error(`zz-meridian: ${read.error}. zz-meridian --help lists the commands and their flags.`);
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
const { values: flags, positionals } = read;
|
|
61
49
|
const brand = Object.fromEntries(BRAND_FLAGS.flatMap((f) => (typeof flags[f] === 'string' ? [[f, flags[f]]] : [])));
|
|
62
|
-
const install = !
|
|
50
|
+
const install = !flags['no-install'];
|
|
63
51
|
const [command, arg] = positionals;
|
|
64
52
|
function main() {
|
|
65
|
-
if (
|
|
53
|
+
if (flags.version) {
|
|
66
54
|
console.log(VERSION);
|
|
67
55
|
return 0;
|
|
68
56
|
}
|
|
@@ -72,9 +60,9 @@ function main() {
|
|
|
72
60
|
console.error(`zz-meridian: --${unsafe[0]} may not contain a backslash or a line break`);
|
|
73
61
|
return 1;
|
|
74
62
|
}
|
|
75
|
-
if (
|
|
63
|
+
if (flags.help || !command) {
|
|
76
64
|
console.log(HELP);
|
|
77
|
-
return command ||
|
|
65
|
+
return command || flags.help ? 0 : 1;
|
|
78
66
|
}
|
|
79
67
|
// A flag a command does not read is refused, never ignored: `adopt --dry-run` wrote the project rather than previewing it.
|
|
80
68
|
const wrong = misapplied(command, flags);
|
|
@@ -82,8 +70,13 @@ function main() {
|
|
|
82
70
|
console.error(`zz-meridian ${command}: --${wrong.flag} belongs to ${wrong.belongsTo}`);
|
|
83
71
|
return 1;
|
|
84
72
|
}
|
|
73
|
+
const extra = positionals[command === 'create' ? 2 : 1];
|
|
74
|
+
if (extra !== undefined) {
|
|
75
|
+
console.error(`zz-meridian ${command}: unexpected argument ${JSON.stringify(extra)}`);
|
|
76
|
+
return 1;
|
|
77
|
+
}
|
|
85
78
|
if (command === 'adopt')
|
|
86
|
-
return adopt({ root: process.cwd(), brand, allowDirty: Boolean(
|
|
79
|
+
return adopt({ root: process.cwd(), brand, allowDirty: Boolean(flags['allow-dirty']), install });
|
|
87
80
|
if (command === 'create') {
|
|
88
81
|
if (!arg) {
|
|
89
82
|
console.error('zz-meridian create: name the folder for the new dashboard');
|
|
@@ -92,26 +85,32 @@ function main() {
|
|
|
92
85
|
return create({ dir: arg, brand, install });
|
|
93
86
|
}
|
|
94
87
|
if (command === 'update') {
|
|
95
|
-
const modes = ['dry-run', 'resume', 'finalize', 'abort'].filter((m) =>
|
|
88
|
+
const modes = ['dry-run', 'resume', 'finalize', 'abort'].filter((m) => flags[m]);
|
|
96
89
|
if (modes.length > 1) {
|
|
97
90
|
console.error(`zz-meridian update: ${modes.map((m) => `--${m}`).join(' and ')} cannot be combined`);
|
|
98
91
|
return 1;
|
|
99
92
|
}
|
|
100
|
-
if (
|
|
93
|
+
if (flags.verify && !flags.finalize) {
|
|
101
94
|
console.error('zz-meridian update: --verify belongs to --finalize');
|
|
102
95
|
return 1;
|
|
103
96
|
}
|
|
104
97
|
const mode = modes[0] ?? 'update';
|
|
105
|
-
return update({ root: process.cwd(), mode, flags: { verbose: Boolean(
|
|
98
|
+
return update({ root: process.cwd(), mode, flags: { verbose: Boolean(flags.verbose), allowDirty: Boolean(flags['allow-dirty']), install, verify: Boolean(flags.verify) } });
|
|
106
99
|
}
|
|
107
100
|
if (command === 'brand')
|
|
108
|
-
return brandCommand({ root: process.cwd(), flags: brand, allowDirty: Boolean(
|
|
101
|
+
return brandCommand({ root: process.cwd(), flags: brand, allowDirty: Boolean(flags['allow-dirty']) });
|
|
109
102
|
if (command === 'skill') {
|
|
110
|
-
const roots =
|
|
111
|
-
|
|
112
|
-
|
|
103
|
+
const roots = flags.global ? [os.homedir()] : [process.cwd()];
|
|
104
|
+
try {
|
|
105
|
+
for (const r of roots)
|
|
106
|
+
installSkill(r);
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
console.error(`zz-meridian skill: ${error instanceof Error ? error.message : String(error)}`);
|
|
110
|
+
return 1;
|
|
111
|
+
}
|
|
113
112
|
const skill = path.join(roots[0], '.claude/skills/zz-meridian/SKILL.md');
|
|
114
|
-
console.log(`The zz-meridian skill is in ${
|
|
113
|
+
console.log(`The zz-meridian skill is in ${flags.global ? path.join(os.homedir(), '.agents/skills') + ' and ' + path.join(os.homedir(), '.claude/skills') : '.agents/skills and .claude/skills'}. Codex may need a restart to list it.`);
|
|
115
114
|
console.log(`To follow it now, read ${skill} and the references beside it: it says how to build what was asked and when it is done.`);
|
|
116
115
|
return 0;
|
|
117
116
|
}
|
package/dist/command-flags.js
CHANGED
|
@@ -3,7 +3,39 @@
|
|
|
3
3
|
* else it is refused by name rather than accepted and ignored, so `adopt --dry-run` never modifies a project while the
|
|
4
4
|
* person waits for a preview.
|
|
5
5
|
*/
|
|
6
|
+
import { parseArgs } from 'node:util';
|
|
6
7
|
import { BRAND_FLAGS } from './files.js';
|
|
8
|
+
/**
|
|
9
|
+
* The command line, read: its flags and positionals, or the reason it cannot be read (an unknown flag, a value-less one),
|
|
10
|
+
* as one line for the person rather than a stack trace.
|
|
11
|
+
*/
|
|
12
|
+
export function readFlags(args) {
|
|
13
|
+
try {
|
|
14
|
+
const { values, positionals } = parseArgs({
|
|
15
|
+
args,
|
|
16
|
+
allowPositionals: true,
|
|
17
|
+
options: {
|
|
18
|
+
...Object.fromEntries(BRAND_FLAGS.map((f) => [f, { type: 'string' }])),
|
|
19
|
+
'allow-dirty': { type: 'boolean' },
|
|
20
|
+
'no-install': { type: 'boolean' },
|
|
21
|
+
'dry-run': { type: 'boolean' },
|
|
22
|
+
resume: { type: 'boolean' },
|
|
23
|
+
finalize: { type: 'boolean' },
|
|
24
|
+
abort: { type: 'boolean' },
|
|
25
|
+
verify: { type: 'boolean' },
|
|
26
|
+
verbose: { type: 'boolean' },
|
|
27
|
+
global: { type: 'boolean' },
|
|
28
|
+
help: { type: 'boolean', short: 'h' },
|
|
29
|
+
version: { type: 'boolean', short: 'v' },
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
return { values: { ...values }, positionals };
|
|
33
|
+
}
|
|
34
|
+
catch (e) {
|
|
35
|
+
// Node's first sentence names the flag; the rest is about positionals that start with a dash.
|
|
36
|
+
return { error: e.message.split('. ')[0] };
|
|
37
|
+
}
|
|
38
|
+
}
|
|
7
39
|
/** Every command reads these. */
|
|
8
40
|
const EVERYWHERE = ['help', 'version'];
|
|
9
41
|
/** The brand flags, read by the commands that write a brand. */
|
package/dist/context.js
CHANGED
|
@@ -41,8 +41,8 @@ Brand, layout and behaviour choices already made, one line each with its reason,
|
|
|
41
41
|
## Glossary
|
|
42
42
|
The team's own words for things, one per line: term and what it means here.
|
|
43
43
|
`;
|
|
44
|
-
/**
|
|
45
|
-
function command(pm, script, flags) {
|
|
44
|
+
/** A package script with flags, as the package manager runs it: npm passes flags on only after `--`. */
|
|
45
|
+
export function command(pm, script, flags) {
|
|
46
46
|
if (pm === 'pnpm')
|
|
47
47
|
return `pnpm ${script}${flags}`;
|
|
48
48
|
if (pm === 'npm')
|
package/dist/create.js
CHANGED
|
@@ -6,10 +6,12 @@
|
|
|
6
6
|
import fs from 'node:fs';
|
|
7
7
|
import path from 'node:path';
|
|
8
8
|
import { managedPaths } from './ownership.js';
|
|
9
|
-
import { BRIEF_TEMPLATE, managedBlock, upsertManagedBlock } from './context.js';
|
|
9
|
+
import { BRIEF_TEMPLATE, command, managedBlock, upsertManagedBlock } from './context.js';
|
|
10
10
|
import { VERSION, brandArgs, effectiveBrand, hasCommand, inside, installSkill, payloadBytes, payloadFiles, run, sha256, writeIn, writeManifest } from './files.js';
|
|
11
11
|
export function create(o) {
|
|
12
12
|
const root = path.resolve(o.dir);
|
|
13
|
+
if (fs.existsSync(root) && !fs.statSync(root).isDirectory())
|
|
14
|
+
return fail(`${root} is a file: name a new folder`);
|
|
13
15
|
if (fs.existsSync(root) && fs.readdirSync(root).length)
|
|
14
16
|
return fail(`${root} exists and is not empty: name a new folder`);
|
|
15
17
|
let brand;
|
|
@@ -27,7 +29,7 @@ export function create(o) {
|
|
|
27
29
|
const name = brand.name ?? path.basename(root).replace(/[-_]+/g, ' ').replace(/\b\w/g, (c) => c.toUpperCase());
|
|
28
30
|
brand = effectiveBrand({ ...brand, name });
|
|
29
31
|
if (run(process.execPath, ['scripts/brand.ts', ...brandArgs(brand), '--product'], root).status !== 0) {
|
|
30
|
-
return fail(
|
|
32
|
+
return fail(`scripts/brand.ts failed (above). ${root} holds the unbranded template and nothing else: fix the cause, delete the folder and run zz-meridian create again with the same flags`);
|
|
31
33
|
}
|
|
32
34
|
// pnpm installs from the template's lockfile, with install scripts off (pnpm-workspace.yaml). Without pnpm, corepack
|
|
33
35
|
// (bundled with Node 22) runs it; only without both does npm install, from the version ranges, with scripts off too.
|
|
@@ -71,16 +73,20 @@ export function create(o) {
|
|
|
71
73
|
if (hasCommand('git'))
|
|
72
74
|
run('git', ['init', '-q'], root);
|
|
73
75
|
if (o.install && run(install[0], install[1], root).status !== 0)
|
|
74
|
-
return fail(`${install.join(' ')} failed (above); run it again in ${root}`);
|
|
76
|
+
return fail(`${install[0]} ${install[1].join(' ')} failed (above); run it again in ${root}`);
|
|
75
77
|
console.log(`
|
|
76
78
|
${name} is a new Meridian ${VERSION} dashboard in ${root}.
|
|
77
79
|
skill: .agents/skills/zz-meridian (Codex) and .claude/skills/zz-meridian (Claude Code)
|
|
78
80
|
|
|
79
|
-
|
|
80
|
-
step 4's colour check, then data and the pages, then the loop in references/standard.md until ${pm} run verify --full --timed ends with "the project meets the
|
|
81
|
-
Meridian standard" and no view on the scoreboard is Weak.`);
|
|
81
|
+
${nextStep(pm)}`);
|
|
82
82
|
return 0;
|
|
83
83
|
}
|
|
84
|
+
/** What the person does next, with the full verify written so their package manager passes its flags on. */
|
|
85
|
+
export function nextStep(pm) {
|
|
86
|
+
return `Next: follow .agents/skills/zz-meridian/SKILL.md from step 3's brief (the template is fetched and branded): the brief,
|
|
87
|
+
step 4's colour check, then data and the pages, then the loop in references/standard.md until ${command(pm, 'verify', ' --full --timed')} ends with "the project meets the
|
|
88
|
+
Meridian standard" and no view on the scoreboard is Weak.`;
|
|
89
|
+
}
|
|
84
90
|
function fail(msg) {
|
|
85
91
|
console.error(`zz-meridian create: ${msg}`);
|
|
86
92
|
return 1;
|
package/dist/files.js
CHANGED
|
@@ -7,7 +7,7 @@ import { spawnSync } from 'node:child_process';
|
|
|
7
7
|
import fs from 'node:fs';
|
|
8
8
|
import path from 'node:path';
|
|
9
9
|
import { fileURLToPath } from 'node:url';
|
|
10
|
-
/** The template snapshot this package carries,
|
|
10
|
+
/** The template snapshot this package carries, extracted from the release commit by `git archive` (cli/scripts/build-payload.ts). */
|
|
11
11
|
export const PAYLOAD = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', 'payload');
|
|
12
12
|
export const VERSION = JSON.parse(fs.readFileSync(path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', 'package.json'), 'utf8')).version;
|
|
13
13
|
/**
|
|
@@ -73,6 +73,8 @@ export function writeIn(root, rel, content) {
|
|
|
73
73
|
fs.writeFileSync(abs, content);
|
|
74
74
|
}
|
|
75
75
|
export const sha256 = (content) => `sha256-${createHash('sha256').update(content).digest('hex')}`;
|
|
76
|
+
/** What a quiet command may print and still be read whole: past Node's 1 MiB default the child is killed, and a long gate reads as exit 1. */
|
|
77
|
+
const OUTPUT = 256 * 1024 * 1024;
|
|
76
78
|
/**
|
|
77
79
|
* A command with its arguments, without a shell, so nothing in a name or a path is ever interpreted. The one exception
|
|
78
80
|
* is a Windows .cmd shim (npm, pnpm, tsc), which Node runs only through a shell: those calls pass fixed arguments
|
|
@@ -80,7 +82,7 @@ export const sha256 = (content) => `sha256-${createHash('sha256').update(content
|
|
|
80
82
|
*/
|
|
81
83
|
export function run(cmd, args, cwd, quiet = false) {
|
|
82
84
|
const shim = process.platform === 'win32' && cmd !== process.execPath;
|
|
83
|
-
return spawnSync(shim && cmd.includes(' ') ? `"${cmd}"` : cmd, args, { cwd, encoding: 'utf8', stdio: quiet ? 'pipe' : 'inherit', shell: shim });
|
|
85
|
+
return spawnSync(shim && cmd.includes(' ') ? `"${cmd}"` : cmd, args, { cwd, encoding: 'utf8', stdio: quiet ? 'pipe' : 'inherit', shell: shim, maxBuffer: OUTPUT });
|
|
84
86
|
}
|
|
85
87
|
/** The package manager a project already uses, from its lockfile; npm when it has none. */
|
|
86
88
|
export function packageManager(root) {
|
|
@@ -99,7 +101,7 @@ export function packageManager(root) {
|
|
|
99
101
|
export const installArgs = (pm) => (pm === 'pnpm' ? ['install', '--no-frozen-lockfile'] : ['install']);
|
|
100
102
|
/** A tool in the project's node_modules, run as `node <its script>`: no shell and no .cmd shim on any platform. */
|
|
101
103
|
export function runTool(root, entry, args, quiet = true) {
|
|
102
|
-
return spawnSync(process.execPath, [path.join(root, 'node_modules', entry), ...args], { cwd: root, encoding: 'utf8', stdio: quiet ? 'pipe' : 'inherit' });
|
|
104
|
+
return spawnSync(process.execPath, [path.join(root, 'node_modules', entry), ...args], { cwd: root, encoding: 'utf8', stdio: quiet ? 'pipe' : 'inherit', maxBuffer: OUTPUT });
|
|
103
105
|
}
|
|
104
106
|
export const hasCommand = (cmd) => spawnSync(cmd, ['--version'], { stdio: 'ignore', shell: process.platform === 'win32' }).status === 0;
|
|
105
107
|
/** A JSONC document's text with the comments dropped, and whether anything had to be dropped to read it. */
|
|
@@ -138,7 +140,8 @@ function strippedJsonc(text) {
|
|
|
138
140
|
}
|
|
139
141
|
out += c;
|
|
140
142
|
}
|
|
141
|
-
|
|
143
|
+
// Consume strings whole before removing trailing commas: their keys and values may themselves contain ",]" or ",}".
|
|
144
|
+
const json = out.replace(/"(?:\\.|[^"\\])*"|,(\s*[}\]])/g, (match, end) => end ?? match);
|
|
142
145
|
return { json, dropped: dropped || json.length !== out.length };
|
|
143
146
|
}
|
|
144
147
|
/** JSON with the comments and trailing commas a tsconfig may carry. */
|
|
@@ -164,9 +167,16 @@ export function relativeImports(rel, source) {
|
|
|
164
167
|
return `${lead}${q}${to}${q}`;
|
|
165
168
|
});
|
|
166
169
|
}
|
|
170
|
+
/**
|
|
171
|
+
* The manifest file as every writer writes it: paths sorted by code unit (never the machine's collation), two-space
|
|
172
|
+
* indent, a final newline. Finalize tells an interrupted rename by comparing the file with this, byte for byte.
|
|
173
|
+
*/
|
|
174
|
+
export function manifestText(m) {
|
|
175
|
+
const files = Object.fromEntries(Object.entries(m.files).sort(([a], [b]) => (a < b ? -1 : 1)));
|
|
176
|
+
return `${JSON.stringify({ ...m, files }, null, 2)}\n`;
|
|
177
|
+
}
|
|
167
178
|
export function writeManifest(root, m) {
|
|
168
|
-
|
|
169
|
-
writeIn(root, '.meridian/manifest.json', JSON.stringify({ ...m, files: sorted }, null, 2) + '\n');
|
|
179
|
+
writeIn(root, '.meridian/manifest.json', manifestText(m));
|
|
170
180
|
}
|
|
171
181
|
/**
|
|
172
182
|
* Where the skill goes: the folders each agent reads in a repository, Codex (`.agents`) and Claude Code (`.claude`), and
|
|
@@ -175,13 +185,29 @@ export function writeManifest(root, m) {
|
|
|
175
185
|
*/
|
|
176
186
|
export function skillPaths() {
|
|
177
187
|
const files = payloadFiles('skills/zz-meridian');
|
|
188
|
+
if (!files.includes('skills/zz-meridian/SKILL.md'))
|
|
189
|
+
throw new Error('skills/zz-meridian/SKILL.md is not in cli/payload/: rebuild the payload or reinstall a complete package before installing the skill.');
|
|
178
190
|
return ['.agents/skills/zz-meridian', '.claude/skills/zz-meridian'].flatMap((base) => files.map((f) => ({ rel: `${base}/${f.slice('skills/zz-meridian/'.length)}`, payload: f })));
|
|
179
191
|
}
|
|
180
|
-
/**
|
|
192
|
+
/** Refuse a different existing skill before writing either agent's copy. Identical copies need no write. */
|
|
181
193
|
export function installSkill(root, record) {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
194
|
+
const contents = new Map();
|
|
195
|
+
const plan = skillPaths().map(({ rel, payload }) => {
|
|
196
|
+
const abs = inside(root, rel);
|
|
197
|
+
let content = contents.get(payload);
|
|
198
|
+
if (!content) {
|
|
199
|
+
content = payloadBytes(payload);
|
|
200
|
+
contents.set(payload, content);
|
|
201
|
+
}
|
|
202
|
+
const existing = fs.lstatSync(abs, { throwIfNoEntry: false });
|
|
203
|
+
if (existing && (!existing.isFile() || !fs.readFileSync(abs).equals(content))) {
|
|
204
|
+
throw new Error(`refusing to overwrite ${rel}: it differs from the packaged skill. Move your copy aside before installing again; no skill files were written.`);
|
|
205
|
+
}
|
|
206
|
+
return { rel, content, exists: Boolean(existing) };
|
|
207
|
+
});
|
|
208
|
+
for (const { rel, content, exists } of plan) {
|
|
209
|
+
if (!exists)
|
|
210
|
+
writeIn(root, rel, content);
|
|
185
211
|
if (record)
|
|
186
212
|
record[rel] = sha256(content);
|
|
187
213
|
}
|